Component Reference

iOS SDK: Component Reference

Complete reference for all UI components available in the Digital Card Engine SDK through the UILibrary protocol.

High-Level Components

CardListView

Full-featured card list with built-in ViewModel, loading states, and error handling.

func getCardListView(
    properties: CardListViewProperties? = nil,
    style: CardListViewStyle? = nil,
    onSelect: @escaping (CardEntity) -> Void,
    onAddCard: @escaping () -> Void,
    onError: ((DCEUIError) -> Void)? = nil
) throws -> AnyView

Parameters:

ParameterTypeRequiredDescription
propertiesCardListViewProperties?NoDisplay configuration (title, buttons, layout, etc.)
styleCardListViewStyle?NoVisual styling (padding, radius, etc.)
onSelect(CardEntity) -> VoidYesCallback when card is tapped
onAddCard() -> VoidYesCallback for "Add Card" button
onError((DCEUIError) -> Void)?NoCallback for error handling (default: nil)

Features:

  • Automatic card fetching via getCards()
  • Loading indicator during fetch
  • Error state with retry button
  • Empty state when no cards
  • "Add Card" action button (configurable)

Example:

struct CardsScreen: View {
    let sdk: DigitalCardEngine
    @State private var navigationPath = NavigationPath()
    
    var body: some View {
        NavigationStack(path: $navigationPath) {
            try? sdk.getCardListView(
                onSelect: { card in
                    navigationPath.append(card.receivedCard.giftCardId)
                },
                onAddCard: {
                    // Navigate to add card screen
                },
                onError: { error in
                    print("Error: \(error)")
                }
            )
        }
    }
}

CardDetailsView

Detailed card information view with optional secure fields and action buttons.

func getCardDetailsView(
    card: CardEntity,
    properties: CardDetailsViewProperties? = nil,
    style: CardDetailsViewStyle? = nil,
    onLockCard: @escaping (CardEntity) -> Void,
    onManageCard: @escaping (CardEntity) -> Void,
    onFocusedCardChange: ((CardEntity) -> Void)? = nil,
    onError: ((DCEUIError) -> Void)? = nil
) throws -> AnyView

Parameters:

ParameterTypeRequiredDescription
cardCardEntityYesCard to display
propertiesCardDetailsViewProperties?NoDisplay configuration (buttons, slider, info)
styleCardDetailsViewStyle?NoVisual styling (padding, radius, etc.)
onLockCard(CardEntity) -> VoidYes"Lock Card" callback
onManageCard(CardEntity) -> VoidYes"Manage Card" callback
onFocusedCardChange((CardEntity) -> Void)?NoCallback when focused card changes (slider mode)
onError((DCEUIError) -> Void)?NoCallback for error handling

CardDetailsViewProperties:

public struct CardDetailsViewProperties {
    public var actionButton: Bool = true
    public var slider: Bool = false
    public var cardInfoLayout: CardDetailsViewLayout = .detailLayout
}

public enum CardDetailsViewLayout {
    case briefLayout    // Compact info
    case detailLayout   // Full details (default)
}

Example:

struct CardDetailsScreen: View {
    let sdk: DigitalCardEngine
    let card: CardEntity
    
    var body: some View {
        try? sdk.getCardDetailsView(
            card: card,
            properties: CardDetailsViewProperties(
                actionButton: true,
                slider: false,
                cardInfoLayout: .detailLayout
            ),
            onLockCard: { card in
                // Lock card logic
            },
            onManageCard: { card in
                // Navigate to card management
            },
            onError: { error in
                print("Error: \(error)")
            }
        )
    }
}

TransactionHistoryView

Transactions list with built-in ViewModel, filtering, and data fetching.

func getTransactionHistoryView(
    card: CardEntity,
    fullscreen: Bool,
    properties: TransactionHistoryViewProperties? = nil,
    style: TransactionHistoryViewStyle? = nil,
    onTransactionClick: @escaping (Transaction) -> Void,
    onSeeMoreClick: @escaping () -> Void,
    onError: ((DCEUIError) -> Void)? = nil
) throws -> AnyView

Parameters:

ParameterTypeRequiredDescription
cardCardEntityYesCard to fetch transactions for
fullscreenBoolYesIf true, shows full list; if false, limited
propertiesTransactionHistoryViewProperties?NoDisplay configuration (filter, grouping, etc.)
styleTransactionHistoryViewStyle?NoVisual styling (padding, radius, etc.)
onTransactionClick(Transaction) -> VoidYesTransaction tap callback
onSeeMoreClick() -> VoidYes"See More" callback
onError((DCEUIError) -> Void)?NoCallback for error handling

TransactionHistoryViewProperties:

public struct TransactionHistoryViewProperties {
    public var leadingElement: TransactionHistoryLeadingElement = .icon
    public var groupByMonth: Bool = true
    public var timestampFormat: String = "dd/MM/yyyy HH:mm"
    public var filter: Bool = true
    public var numberOfTransactions: Int = 5
}

public enum TransactionHistoryLeadingElement {
    case none
    case icon
    case brandLogo
}

Example:

struct TransactionHistoryScreen: View {
    let sdk: DigitalCardEngine
    let card: CardEntity
    
    var body: some View {
        try? sdk.getTransactionHistoryView(
            card: card,
            fullscreen: true,
            properties: TransactionHistoryViewProperties(
                leadingElement: .icon,
                groupByMonth: true,
                filter: true,
                numberOfTransactions: 20
            ),
            onTransactionClick: { transaction in
                // Navigate to transaction details
            },
            onSeeMoreClick: {
                // Show all transactions
            },
            onError: { error in
                print("Error: \(error)")
            }
        )
    }
}

TransactionDetailsView

Detailed view for a single transaction.

func getTransactionDetailsView(
    transaction: Transaction,
    style: TransactionHistoryViewStyle? = nil
) throws -> AnyView

Parameters:

ParameterTypeRequiredDescription
transactionTransactionYesTransaction to display
styleTransactionHistoryViewStyle?NoVisual styling (padding, radius, etc.)

Example:

struct TransactionDetailScreen: View {
    let sdk: DigitalCardEngine
    let transaction: Transaction
    
    var body: some View {
        try? sdk.getTransactionDetailsView(transaction: transaction)
    }
}

CardPageView

Combined card details and transactions view for a full card screen (pre-configured).

func getCardPageView() throws -> AnyView

Features:

  • Card details with secure fields (MCD)
  • Transaction history preview
  • Card events list
  • Loading and error states for all sections

Example:

struct CardScreen: View {
    let sdk: DigitalCardEngine
    
    var body: some View {
        try? sdk.getCardPageView()
    }
}

Component Comparison

When to use which component?

ComponentUse CaseData FetchingState Management
CardListViewQuick integration, standard card listBuilt-inBuilt-in
CardDetailsViewCustom card details layoutManualBuilt-in
TransactionHistoryViewTransaction displayBuilt-inBuilt-in
TransactionDetailsViewSingle transaction detailsManualManual
CardPageViewFull card screen (pre-configured)Built-inBuilt-in

Composition Patterns

Pattern 1: Fully Managed

Use high-level components with built-in data fetching.

struct EasyIntegration: View {
    let sdk: DigitalCardEngine
    
    var body: some View {
        NavigationStack {
            try? sdk.getCardListView(
                onSelect: { card in /* ... */ },
                onAddCard: { /* ... */ }
            )
        }
    }
}

Pros: Quick, minimal code
Cons: Less control over state/fetching

Pattern 2: Custom Navigation

Use components with SwiftUI NavigationStack.

struct CustomNavigationApp: View {
    let sdk: DigitalCardEngine
    @State private var selectedCard: CardEntity?
    
    var body: some View {
        NavigationStack {
            try? sdk.getCardListView(
                onSelect: { card in
                    selectedCard = card
                },
                onAddCard: {
                    // Show add card flow
                }
            )
            .navigationDestination(item: $selectedCard) { card in
                try? sdk.getCardDetailsView(
                    card: card,
                    onLockCard: { card in
                        // Lock logic
                    },
                    onManageCard: { card in
                        // Manage logic
                    }
                )
            }
        }
    }
}

Pros: Full navigation control
Cons: More setup code

Pattern 3: Custom Styling

Override global styles for specific components.

struct CustomStyledApp: View {
    let sdk: DigitalCardEngine
    
    var body: some View {
        try? sdk.getCardListView(
            properties: CardListViewProperties(
                title: false,
                actionButton: true,
                cardListLayout: .defaultLayout
            ),
            style: CardListViewStyle(
                internalHorizontalPadding: 20,
                internalVerticalPadding: 16,
                externalPadding: 24,
                radius: 16
            ),
            onSelect: { card in /* ... */ },
            onAddCard: { /* ... */ }
        )
    }
}

Styling All Components

Apply consistent styling globally:

class MyApp: App {
    let sdk: DigitalCardEngine
    
    init() {
        // Initialize SDK
        sdk = try! DigitalCardEngine(
            token: "your-token",
            dceConfiguration: DceConfiguration(/* ... */),
            totpCallback: { _ in /* ... */ }
        )
        
        // Apply global styling
        sdk.styleConfiguration.palette.secondary = Color(hex: 0x00A86B)
        sdk.styleConfiguration.spacing = 12
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(sdk.styleConfiguration)
        }
    }
}

Error Handling

All UI components support optional error callbacks:

struct ErrorHandlingExample: View {
    let sdk: DigitalCardEngine
    @State private var errorMessage: String?
    
    var body: some View {
        VStack {
            if let error = errorMessage {
                Text("Error: \(error)")
                    .foregroundColor(.red)
            }
            
            try? sdk.getCardListView(
                onSelect: { card in /* ... */ },
                onAddCard: { /* ... */ },
                onError: { error in
                    errorMessage = error.localizedDescription
                }
            )
        }
    }
}