> For the complete documentation index, see [llms.txt](https://docs.infocus.company/ios-sdk/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.infocus.company/ios-sdk/premium-ios-sdk.md).

# Premium iOS SDK

* Version: **2.4.0**
* Minimum supported iOS version: **15.8.3** (this is what we test)
* Minimum compiling iOS version: **14** (this is where it compiles, but it does not actually work, and we block it by a warning message on the SDK initial screen)
* UI framework: SwiftUI
* Appearance: Light/Dark
* Supported orientations: Portrait
* SDK Size: up to 2 MB
* Supported languages: English/Russian/Kazakh

## iOS Compatibility

<table><thead><tr><th width="152.59375"></th><th></th></tr></thead><tbody><tr><td><strong>iOS Version</strong></td><td><strong>Expected behavior</strong></td></tr><tr><td>&#x3C; 14.0</td><td>App cannot be installed</td></tr><tr><td>14.0 – 15.8.2</td><td>Installs, displays upgrade notice</td></tr><tr><td>15.8.3+</td><td>Full functionality</td></tr></tbody></table>

## How to setup the SDK

To get the dependency, you first need to configure access to our repository.

* Install AWS CLI using this [guide](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-version.html).
* Configure AWS CLI using the credentials provided by us. To do this, run the following command in your terminal.

```shell
> aws configure

# After executing the command, you will be prompted to enter the following information
AWS Access Key ID [None]: <YOUR_ACCESS_KEY>
AWS Secret Access Key [None]: <YOUR_SECRET_KEY>
Default region name [None]: eu-central-1
Default output format [None]: json
```

* Initialise your app

```shell
swift package init --type executable
```

* Configure your swift client using this AWS CLI CodeArtifact command

```sh
aws codeartifact login --tool swift --repository premium-sdk --domain infocus --domain-owner 346627266603 --region eu-central-1
```

* Modify the Package.swift file within your application project directory to adjust the package dependencies utilized by your project. If the Package.swift file does not have a dependencies section, include one. Within the targets section, add the targets requiring the dependency. It should look similar to code snippet below:

```swift
import PackageDescription

let package = Package(
    name: "premium-sdk-test",
    dependencies: [
        .package(id: "ios-premium.premium-ios-sdk", from: "2.0.0")
    ],
    targets: [
        // Targets are the basic building blocks of a package, defining a module or a test suite.
        // Targets can depend on other targets in this package and products from dependencies.
        .executableTarget(
            name: "premium-sdk-test",
            dependencies: ["premium_sdk"]
        ),
    ]
)
```

Use the **resolve** command to download the package dependencies from CodeArtifact.

```sh
swift package resolve
```

Alternatively, you can add packages by navigating to App > package dependencies on Xcode. “Click” on the + icon, Enter **ios.premium-ios-sdk**. Once the package is found, choose the package and “Click” on **Add Package**. After a second or two, the package name appears on the list. On the top right side, you can verify the source repository (next to the **Registry** label).

* Import the framework

```swift
import premium_sdk
```

Add strings to Info.plist to avoid crashes&#x20;

<figure><img src="https://3357793733-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5t89kNfXUXFXgxM6GWtD%2Fuploads%2FcqsMKdxiscjR9vs7TvGN%2FScreenshot%202025-03-16%20at%2022.39.04.png?alt=media&amp;token=e7484140-734c-4832-8215-d086480dd9fa" alt=""><figcaption></figcaption></figure>

* There are 2 convenience initialisers for SDK: by client token and by customer ID (⚠️ **Deprecated. Not in use.**)\
  \
  To init the SDK by client token you will need to set a client token. **To obtain this token, your backend must have the appropriate API.** You need to implement the logic for retrieving this token from your backend and passing it to the SDK. Init ConciergeSDK with your client token

```swift
let sdk = PremiumSDK(
    clientToken: "<<YOUR CLIENT TOKEN>>"
)
```

* \[Optionally] Set language:

```swift
sdk.setLanguage(.en)
```

* \[Optionally] Set colors:

```swift
sdk.setColors(
    SharedColors(
        mainColor: Color(hex: "#C28BFC"),
        mainColorTinted: Color(hex: "#E3DEFC"),
        defaultShadowColor: Color.dynamicColor(
            light: Color(red: 0.525, green: 0.442, blue: 0.613, opacity: 0.13),
            dark: Color(red: 0.035, green: 0.031, blue: 0.157, opacity: 0.5)
        ),
        mainBlack: Color.dynamicColor(
            light: Color(hex: "#090828"),
            dark: Color(hex: "#E3DEFC")
        ),
        mainGray: Color.gray,
        mainWhite: Color(hex: "#FFFFFF"),
        background: ColorSettings(
            withSolidColor: Color.dynamicColor(
                light: Color(hex: "#F6F6FA"),
                dark: Color(hex: "#090828")
            )
        ),
        primaryButtonBackground: ColorSettings(withSolidColor: Color(hex: "#C28BFC")),
        primaryButtonBorderColor: Color(hex: "#C28BFC"),
        primaryButtonShadowColor: Color.dynamicColor(
            light: Color(red: 0.525, green: 0.442, blue: 0.613, opacity: 0.13),
            dark: Color(red: 0.035, green: 0.031, blue: 0.157, opacity: 0.5)
        ),
        textFieldBackgroundColor: Color(hex: "#FFFFFF"),
        textFieldTextColor: Color(hex: "#090828"),
        textInputBorderColor: Color(hex: "#090828").opacity(0.12),
        textInputUnderlineColor: Color(hex: "#090828"),
        hintBackgroundColor: Color(hex: "#090828").opacity(0.07),
        hintTextColor: Color(hex: "#090828").opacity(0.5),
        radioButtonDefaultStateColor: Color(hex: "#090828").opacity(0.35),
        radioButtonSelectedStateColor: Color(hex: "#C28BFC"),
        spinnerColor: Color(hex: "#C28BFC"),
        successIconTintColor: Color(hex: "#C28BFC"),
        accordionBorderColor: Color(hex: "#090828").opacity(0.12),
        intermediateBackgroundColor: Color.dynamicColor(
            light: Color(hex: "#FFFFFF"),
            dark: Color(hex: "#1E1240")
        ),
        errorColor: Color(hex: "#D92D20"),
        hyperlinkColor: Color.blue,
        iconTint: Color(hex: "#C28BFC"),
        benefitCardOverlayTextColor: Color.white,
        benefitCardOverlayGradientStartColor: Color.black.opacity(0.35),
        benefitCardOverlayGradientEndColor: Color.black.opacity(0.15),
        errorPopupIconBackgroundColor: Color(hex: "#D92D20").opacity(0.08),
        errorPopupIconBorderColor: Color(hex: "#D92D20").opacity(0.2),
        errorPopupIconForegroundColor: Color.white,
        progressBarFilledColor: Color(hex: "#C28BFC"),
        progressBarTrackStripeColor: Color(.systemGray4).opacity(0.6),
        progressBarTrackBackgroundColor: Color(.systemGray5).opacity(0.5)
    )
)
```

There is also an option to use pre-define color themes to avoid setting the long list of colors. A the moment SDK supports 2 color schemes: **light** and **dark.** If you want to resent previous theme then you need to specify **custom** theme

```swift
sdk.setColorTheme(.light)
```

<figure><img src="https://3357793733-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5t89kNfXUXFXgxM6GWtD%2Fuploads%2Fr1cESq3X7giUncXS0hWx%2FMain%20Page.png?alt=media&amp;token=b5e8c3f4-1ee7-4ac3-b1f1-a915faaca09f" alt=""><figcaption></figcaption></figure>

* \[Optionally] Buttons customization:\
  There are 2 types of customizations:\
  SDK-wide (like on snipped below):

```swift
sdk.setColors(
    SharedColors(
        primaryButtonBackground: ColorSettings(
            withGradientType: .vertical,
            startColor: Color(hex: "#1434CB"),
            endColor: Color(hex: "#0A1F8F")
        ),
        primaryButtonBorderColor: Color(hex: "#1434CB"),
        primaryButtonShadowColor: Color.black.opacity(0.2)
    )
)
sdk.setSharedUISettings(
    SharedUISettings(
        primaryButtonSettings: ButtonSettings(
            foregroundColor: .white,
            cornerRadius: 16,
            borderType: .solid,
            borderWidth: 1,
            shadowEnabled: true,
            shadowColor: .black.opacity(0.2),
            shadowRadius: 8,
            height: 56,
            fontSize: 18,
            fontWeight: .semibold,
            shadowOffset: CGSize(width: 0, height: 4)
        )
    )
)
```

...and Benefits-specific (like on snippet below)

```swift
sdk.setBenefitsColors(
    BenefitsColors(
        informationalButtonBackground: ColorSettings(withSolidColor: Color(hex: "#1434CB")),
        informationalButtonBorderColor: Color(hex: "#1434CB"),
        backHomeButtonBackground: ColorSettings(withSolidColor: Color(hex: "#FFFFFF")),
        backHomeButtonBorderColor: Color(hex: "#1434CB")
    )
)

sdk.setBenefitsUISettings(
    BenefitsUISettings(
        informationalButtonSettings: ButtonSettings(borderType: .none),
        backHomeButtonSettings: ButtonSettings(shadowEnabled: false)
    )
)
```

* \[Optionally] Set images\
  Now there is an ability to set different sets of images for different sub-systems of the SDK. At the moment of writing this documentation there are 2 main subsystems: Concierge and Shared (which are used in both Concierge and Benefits parts of SDK).\
  So in order to specify images you need to invoke code similar to what is shown below:

```swift
sdk.setSharedImages(
    SharedImages(
        visaLogo: Image(systemName: "creditcard.fill"),
        documentUploadIcon: Image(systemName: "paperclip"),
        documentUploadRemoveIcon: Image(systemName: "trash")
    )
)

sdk.setConciergeImages(
    ConciergeImages(
        conciergeAvatarImage: Image(systemName: "person.crop.circle.fill"),
        infoLogoImage: Image(systemName: "info.circle.fill"),
        tasksState1: Image(systemName: "1.circle.fill"),
        tasksState2: Image(systemName: "2.circle.fill"),
        tasksState3: Image(systemName: "3.circle.fill")
    )
)
```

* \[Optionally] Set fonts:\
  This customisation is common for Concierge and Benefits sub-systems and will be applied in both of them

```swift
sdk.setFonts(
    SharedFonts(customFontName: "Rubik-Medium")
)
```

* \[Optionally] Set benefits list view screen banner:\
  SDK allows to show additional element on benefits list view which displays HTML content. It is configured as JSON which looks like shown below

```swift
let bannerJSON = """
{
  "additionalInfo": {
    "title": "Banner Title"
  },
  "info": "{\\"title\\":\\"Some info here\\"}",
  "text": "<!DOCTYPE html><html><head><meta name='viewport' content='width=device-width, initial-scale=1.0'></head><body><h3>Card benefits</h3><p>Your custom HTML banner content.</p></body></html>"
}
"""

sdk.setBenefitsUISettings(
    BenefitsUISettings(
        benefitsListShowsCards: true,
        benefitsListBannerJSON: bannerJSON
    )
)
```

* \[Optionally] Set custom texts if needed:\
  This customisation is only for Concierge sub-system

```swift
sdk.setConciergeTexts( 
    ConciergeTexts(
        chatInfoAdditionalText: "For questions about Premium cards and transactions, please contact the XXXX toll-free line."
    )
)
```

* \[Optionally] Set other UI settings if needed:\
  The idea is the same as with setting custom images: there are 3 subsystems (Concierge, Benefits and Shared which is used in both Concierge and Benefits part of SDK)

<pre class="language-swift"><code class="lang-swift">sdk.setSharedUISettings(
    SharedUISettings(
        primaryButtonCornerRadius: 12,
        primaryButtonBorderType: .solid,
        primaryButtonBorderWidth: 1,
        primaryButtonShadowEnabled: true,
        primaryButtonShadowRadius: 10,
        dateTimeInputMode: .textInput,
        textInputBorderType: .solid,
        textInputBorderWidth: 1,
        showTextInputUnderline: true,
        textInputUnderlineWidth: 1,
        accordionBorderType: .solid,
        accordionBorderWidth: 1,
        documentUploadStyle: .compact
    )
)

sdk.setBenefitsUISettings(
    BenefitsUISettings(
        benefitsShowsCheckSpending: true
    )
)

sdk.setConciergeUISettings(
<strong>    ConciergeUISettings(
</strong>        chatStyle: .messenger,
        chatFilePickerEnabled: true,
        shouldShowVisaLogoInInfo: true
    )

)
</code></pre>

* Set delegate and implement delegate methods&#x20;

<pre class="language-swift"><code class="lang-swift"><strong>sdk.setDelegate(self)
</strong></code></pre>

* Call start() function

```swift
sdk.start()
```

* **ATTENTION**: If you are using ***SwiftUI*** for implementing you app please instantiate main SDK view like shown in example below (in not then see description below):\
  Depending on which sub-system of SDK you want to use (Concierge/Benefits) you should invoke corresponding function

```swift
sdk.createBenefitsView() // or 'sdk.createConciergeView()'
```

The code snippet above opens benefits list view which allows to navigate among benefits. If you are not interested in this step and want to navigate directly to benefit internal you may pass benefit ID as shown in code snippet below.

```swift
sdk.createBenefitsView(
    withSelectedBenefitId: "<SOME_ID_HERE>"
)
```

* **ATTENTION**: If you are using ***UIKit*** for implementing your app please instantiate main SDK view controller like shown in example below:

```swift
// Somewhere inside your view controller...

let viewController = sdk.createBenefitsViewController(
    withSelectedBenefitId: nil,
    // SDK needs your app's navigation controller to smoothly embed 
    // into your push navigation stack so back-button and swipe-back work properly
    navigationController: navigationController
)

// Push it into your app's navigation stack.
// 'navigationController' is a standalone property of UIViewController
navigationController.pushViewController(viewController, animated: true)
```

* \[Optionally] Clear user-specific data (for example during logout). This method clears keychain, files cache and user settings

```swift
sdk.flush()
```

* \[Optionally] Add URL filtering.\
  Now SDK notifies client code when it's about to open some URL via optional: \
  \
  @objc\
  optional func *premiumSDKWantsToOpenUrl(*

  &#x20;   *url: String,*

  &#x20;   *usingNavigationController navigationController: UINavigationController?*

  *) -> Bool* \
  \
  delegate method. Client code may react on this event and either allow it by returning 'true' or block by returning 'false' from delegate method. If method is not implemented then SDK will open all URLs. SDK also passes optional UINavigationController to delegate method which it uses for it's internal navigation stack so client code may also embed it's screen within SDK navigation stack. This navigationController is available only when SDK is used in UIKit-mode.

Due to the tab bar and navigation bars, It should be presented as a full screen cover or as separate window\
\
Full example:

```swift
import SwiftUI
import premium_sdk

struct InputView: View {
    var body: some View {
        NavigationView {
            VStack(spacing: 24) {
                Spacer()

                Text("Authentication")
                    .font(.title2)
                    .fontWeight(.semibold)

                TextField("Access token", text: $viewModel.authToken)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .autocapitalization(.none)
                    .disableAutocorrection(true)

                Toggle("Auth by customer ID", isOn: $viewModel.isAuthByCustomerId)

                if case .authFailed(let message) = viewModel.state {
                    Text(message)
                        .foregroundColor(.red)
                        .padding(.horizontal)
                }

                if viewModel.state == .authenticating {
                    ProgressView("Authenticating...")
                }

                HStack(spacing: 16) {
                    Button("Benefits") {
                        viewModel.handleBenefitsButtonPressed()
                    }

                    Button("Concierge") {
                        viewModel.handleConciergeButtonPressed()
                    }
                }
                .buttonStyle(.bordered)

                NavigationLink(
                    tag: .benefits,
                    selection: $targetRoute,
                    destination: {
                        if let sdk = viewModel.sdk {
                            AnyView(
                                sdk.createBenefitsView(
                                    withSelectedBenefitId: nil,
                                    withConcierge: true,
                                    usingSwiftUINavigation: true
                                )
                            )
                        } else {
                            AnyView(EmptyView())
                        }
                    },
                    label: { EmptyView() }
                )

                NavigationLink(
                    tag: .concierge,
                    selection: $targetRoute,
                    destination: {
                        if let sdk = viewModel.sdk {
                            AnyView(
                                sdk.createConciergeView(
                                    usingSwiftUINavigation: true
                                )
                            )
                        } else {
                            AnyView(EmptyView())
                        }
                    },
                    label: { EmptyView() }
                )

                Spacer()
            }
            .padding()
        }
        .onAppear {
            viewModel.onAuthenticated = { target in
                switch target {
                case .benefits:
                    targetRoute = .benefits
                case .concierge:
                    targetRoute = .concierge
                case .none:
                    break
                }
            }
        }
    }

    @StateObject private var viewModel = InputViewModel()
    @State private var targetRoute: Route?

    private enum Route: Hashable {
        case benefits
        case concierge
    }
}

@MainActor
final class InputViewModel: ObservableObject {
    enum State: Equatable {
        case idle
        case authenticating
        case authFailed(String)
    }

    enum TargetScreen {
        case none
        case concierge
        case benefits
    }

    @Published var state: State = .idle
    @Published var authToken: String = ""
    @Published var isAuthByCustomerId: Bool = false

    private(set) var sdk: PremiumSDK?
    private(set) var targetScreen: TargetScreen = .none

    var onAuthenticated: ((TargetScreen) -> Void)?

    func handleBenefitsButtonPressed() {
        targetScreen = .benefits
        authenticate()
    }

    func handleConciergeButtonPressed() {
        targetScreen = .concierge
        authenticate()
    }

    private func authenticate() {
        guard !authToken.isEmpty else {
            state = .authFailed("Auth info is not provided")
            return
        }

        state = .authenticating

        sdk = isAuthByCustomerId
            ? PremiumSDK(withCustomerIdAccessToken: authToken)
            : PremiumSDK(clientToken: authToken)

        configureSDK()

        sdk?.setDelegate(self)
        sdk?.start()
    }

    private func configureSDK() {
        sdk?.setLanguage(.en)

        // Use either a predefined theme...
        sdk?.setColorTheme(.light)

        // ...or full manual color customization.
        // sdk?.setColors(SharedColors(...))

        sdk?.setFonts(
            SharedFonts(
                customFontName: nil
            )
        )

        sdk?.setSharedImages(
            SharedImages(
                visaLogo: Image(systemName: "creditcard.fill"),
                documentUploadIcon: Image(systemName: "paperclip"),
                documentUploadRemoveIcon: Image(systemName: "trash")
            )
        )

        sdk?.setConciergeImages(
            ConciergeImages(
                conciergeAvatarImage: Image(systemName: "person.crop.circle.fill"),
                infoLogoImage: Image(systemName: "info.circle.fill"),
                tasksState1: Image(systemName: "1.circle.fill"),
                tasksState2: Image(systemName: "2.circle.fill"),
                tasksState3: Image(systemName: "3.circle.fill")
            )
        )

        sdk?.setSharedUISettings(
            SharedUISettings(
                primaryButtonCornerRadius: 12,
                primaryButtonBorderType: .solid,
                primaryButtonBorderWidth: 1,
                primaryButtonShadowEnabled: true,
                primaryButtonShadowRadius: 10,
                dateTimeInputMode: .textInput,
                textInputBorderType: .solid,
                textInputBorderWidth: 1,
                showTextInputUnderline: true,
                textInputUnderlineWidth: 1,
                accordionBorderType: .solid,
                accordionBorderWidth: 1,
                documentUploadStyle: .compact
            )
        )

        sdk?.setBenefitsUISettings(
            BenefitsUISettings(
                benefitsShowsCheckSpending: true
            )
        )

        sdk?.setConciergeUISettings(
            ConciergeUISettings(
                chatStyle: .messenger,
                chatFilePickerEnabled: true,
                shouldShowVisaLogoInInfo: true
            )
        )

        sdk?.setConciergeTexts(
            ConciergeTexts(
                chatInfoAdditionalText: "For questions about Premium cards and transactions, please contact support."
            )
        )
    }
}

extension InputViewModel: PremiumSDK.Delegate {
    func conciergeSDKDidStart(isSubscribed: Bool) {
        state = .idle
        onAuthenticated?(targetScreen)
    }

    func conciergeSDKDidSubscribe() {
        state = .idle
        onAuthenticated?(targetScreen)
    }

    func conciergeSDKDidStartWithError(_ error: Error) {
        state = .authFailed(error.localizedDescription)
    }

    func conciergeSDKCantAuthorize() {
        state = .authFailed("Failed to authorize")
    }
}
```

## **CHANGELOG**

### 2.4.0

Release tag: release/2.4.0

#### Breaking changes

* Replaced individual button appearance arguments in `SharedColors`, `SharedUISettings`, `BenefitsColors`, and `BenefitsUISettings` with the public `ButtonSettings` type.
* Configure primary buttons through `SharedUISettings(primaryButtonSettings:)` and informational / “Back home” buttons through `BenefitsUISettings(informationalButtonSettings:backHomeButtonSettings:)`.

#### Added

* Unified button customization for solid or gradient backgrounds, foreground colors, borders, corner radius, and shadows.
* Added disabled-state background and foreground colors, button height, font size and weight, and shadow offset settings.
* Informational and “Back home” buttons inherit each unspecified setting from the primary button. Remaining unspecified values use SDK defaults.

#### Changed

* Migrated the SwiftUI and UIKit customization samples, including benefits-only variants, to `ButtonSettings` while preserving their existing customization controls.
* Preserved the benefit-loading error screen’s “Back home” action when adopting the new button settings API.

### 2.3.3

Release tag: `release/2.3.3`

#### Added

* Added support for `PROMOCODE` benefit-flow elements, including loading from `promocodeUrl`, displaying the existing copyable promo-code card, and loading/error/retry states.

#### Changed

* “Back home” now always returns to the benefits list, including direct entry with a benefit ID and benefit-loading errors.
* Visible document-upload fields are always required before submitting or advancing to the next screen.

#### Fixed

* Missing or oversized uploads show validation feedback with the configured error-color border. Selecting or removing a file refreshes validation.

### 2.3.2

Release tag: `release/2.3.2`

#### Added

* Added Armenian language support and translations for benefits, concierge, and shared SDK text.
* Added a dismiss button to pickers using the existing customized button colors.
* Added an error screen when a benefit cannot be loaded, with a “Back home” action.

#### Changed

* QR-code validity displays “Valid for:” with the remaining time.
* Reworked the benefits toolbar and moved the order-history button to the right.
* Child pickers appear or disappear according to the selected parent value.

#### Fixed

* Restored compilation with an iOS 14 deployment target while retaining the unsupported-version screen below iOS 15.8.
* Order-history icons now use the existing customizable icon tint and a 32-point size.
* Empty, null, or failed dynamic-URL responses show an error instead of silently falling back to another action.
* Fixed active-order rendering, SwiftUI “Back home” navigation, and swipe-back behavior on benefit-loading errors.
* Informational buttons without a URL can navigate to their target screen after validation; buttons without a usable action show an error.
* Corrected API header casing and the SDK version header.

### 2.3.1

Release tag: `release/2.3.1`

#### Changed

* Expanded localization for benefit, concierge, document, image, and shared interface text.
* Pinned concierge task actions to the bottom of the screen, improved text wrapping, and show document download only when documents are available.

#### Fixed

* Corrected share-button positioning.
* Restored the “Something went wrong” message for expired-token errors.
* Removed the invisible offline overlay when connectivity is available.
* Corrected document file-size labels to use MB.

### 2.3.0

Release tag: `release/2.3.0`

#### Added

* Added dynamic URL loading for benefit buttons.
* Added server error-message handling for benefit loading and submission.
* Added promo-code cards and order-history promo-code details, including copy support and customizable appearance.
* Added API request headers.

#### Changed

* Updated order-history icons and promo-code details.
* Preserved the benefits list scroll position when returning from a benefit.
* At this release, “Back home” exited the SDK when it was opened with a benefit ID; this behavior was changed in 2.3.3.

#### Fixed

* Removed the placeholder promo code from expired orders.
* Fixed horizontal carousel gestures interfering with vertical scrolling.
* Restored scrolling within the promotional banner and disabled pinch zoom.
* Improved navigation and error handling carried over from the demo implementation.

### 2.2.2

Release tag: `release/2.2.2`

#### Breaking changes

* Moved informational-button and “Back home” background/border colors from `SharedColors` to `BenefitsColors`.
* Moved their border type/width settings from shared UI configuration to `BenefitsUISettings`. Host apps using these initializer arguments must move them to the benefits-specific configuration.

### 2.2.1

Release tag: `release/2.2.1`

#### Added

* Added informational-button and “Back home” appearance customization.
* Added file and image sharing in Concierge.
* Added support for opening a URL from a submit button.

#### Fixed

* Corrected localization strings.

### 2.2.0

Release tag: `release/2.2.0`

#### Added

* Added host-controlled URL filtering.
* Added conditional visibility through benefit-flow `visibilityConditions`, including dependent picker handling.
* Added a “See all” action for active orders on the benefits home screen.
* Added UIKit-style navigation customization, a custom back button, and back-button tint configuration.

#### Fixed

* Corrected guest-name validation.
* Fixed text-input and concierge colors across device and SDK light/dark theme combinations.
* Fixed customizable icon tint and primary-button transparency.
* Removed duplicate navigation controls and extra header fading when opening a benefit directly by ID in UIKit integrations.
* Added the missing back button on the active-orders screen.
* Corrected Ukrainian and Azerbaijani localization.

### 2.1.1

Release tag: `release/2.1.1`

#### Breaking changes

* Replaced `BenefitsUISettings.benefitsShowsCheckSpending` with `benefitsListShowsCards`. The new option controls visibility of the benefits card carousel.

### 2.1.0

Release tag: `release/2.1.0`

#### Added

* Added UIKit integration through `createBenefitsViewController` and `createConciergeViewController`, alongside SwiftUI integration.
* Added guest entry to benefit forms.
* Added Azerbaijani localization and updated Ukrainian translations.
* Added header/footer fade overlay utilities.

#### Changed

* Reworked navigation for UIKit and SwiftUI integrations and extracted reusable benefit-flow subviews.

#### Fixed

* Corrected UIKit navigation and localization issues.

### 2.0.1

#### ⚠ Breaking

* `BenefitsListScreenBannerInfo` removed → pass banner configuration as a JSON string through `BenefitsUISettings.benefitsListBannerJSON`.

#### ✦ Added

* Added configurable benefits list banner rendering from `BenefitsUISettings.benefitsListBannerJSON`.
* Added support for banner JSON with a top-level `text` field containing HTML content.
* Added auto-height WebView rendering for benefits list banner HTML.
* Added optional `redirectUrl` field for benefit cards; when present, tapping the benefit opens the URL.
* Added availability hint popup title extraction from benefit flow JSON.
* Added close and localized confirmation buttons for availability hint popups.

#### ✎ Changed

* Benefit card taps now open `redirectUrl` when provided and fall back to the existing benefit details flow otherwise.
* Availability hint popups now hide the top back and concierge buttons while presented.
* Chat message rows now reserve 25% horizontal spacing around message content and use left horizontal row alignment.
* Example customization screens now load benefits banner JSON from a bundled `banner.json` resource instead of hardcoded JSON.

#### 🐛 Fixed

* Fixed missing header text in availability hint popups.
* Fixed availability hint popup close control placement and sizing.
* Fixed customize banner toggle persistence between app launches in example customization targets.

#### ⌛ Deprecated

* none

### 2.0.0

#### Added

* Added extended SDK UI customization support for shared, concierge, and benefits UI surfaces.
* Added shared UI configuration for primary buttons, text inputs, accordions, document upload presentation, shadows, borders, corner radius, and date/time input mode.
* Added benefits UI configuration through `BenefitsUISettings`, including check-spending visibility and custom benefits list banner JSON.
* Added concierge UI configuration for chat presentation and related feature switches.

#### Changed

* Expanded the SDK setup flow so host apps can provide UI configuration objects before starting the SDK.
