# SwiftUI Components

VGS Collect iOS SDK provide support for integration with apps that are buid with SwiftUI toolkit by providing SwiftUI wrappers for all VGS textfields. VGS Collect SwiftUI wrappers are designed to make integration easier and more straight forward by taking care of all needed state and editing events.

## VGSTextFieldRepresentable

A component that displays an editable text interface.

### Declaration

```swift
struct VGSTextFieldRepresentable: UIViewRepresentable
```

### Creating VGSTextFieldRepresentable

```swift
/// Initialization
///
/// - Parameters:
///   - configuration: `VGSConfiguration` instance.
public init(configuration: VGSConfiguration)
```

### Instance Methods

`VGSTextFieldRepresentable` is a SwiftUI wrapper around `VGSTextField` and have similar attributes and functionality represented in SwiftUI way.

### VGSTextFieldRepresentable Text modifiers

```swift
/// Set `UIFont` value.
public func font(_ font: UIFont)
/// Set `placeholder` string.
public func placeholder(_ text: String)
/// Set `attributedPlaceholder` string.
public func attributedPlaceholder(_ text: NSAttributedString?)
/// Set `UITextAutocapitalizationType` type.
public func autocapitalizationType(_ type: UITextAutocapitalizationType)
/// Set `UITextSpellCheckingType` type.
public func spellCheckingType(_ type: UITextSpellCheckingType)
/// Set `NSTextAlignment` type.
public func textAlignment(_ alignment: NSTextAlignment)
/// Set `adjustsFontForContentSizeCategory` value.
public func adjustsFontForContentSizeCategory(_ adjusts: Bool)
/// Set `isSecureTextEntry` value.
public func setSecureTextEntry(_ secure: Bool)
/// Coordinates connection between scan data and text field.
public func cardScanCoordinator(_ coordinator: VGSCardScanCoordinator)
```

### VGSTextFieldRepresentable View and Layout modifiers

```swift
/// Set `UIEdgeInsets` insets.
public func textFieldPadding(_ insets: UIEdgeInsets)
/// Set `borderColor` and `lineWidth`.
public func border(color: UIColor, lineWidth: CGFloat)
/// Set `keyboardAccessoryView` view.
public func keyboardAccessoryView(_ view: UIView?)
```

### VGSTextFieldRepresentable Accessibility modifiers

```swift
/// Set `textFieldAccessibilityLabel` string.
public func textFieldAccessibilityLabel(_ label: String)
```

### VGSTextFieldRepresentable Event modifiers

```swift
/// Handle  VGSTextFieldRepresentable editing events.
public func onEditingEvent(_ action: ((VGSTextFieldEditingEvent<StateType>) -> Void)?)
/// Handle `VGSTextFieldState` changes.
public func onStateChange(_ action: ((VGSTextFieldState) -> Void)?)
```

### Code example

```swift
struct CardDataCollectionView: View {
  // Collector
  let vgsCollect = VGSCollect(id: "vaultId" environment: .sandbox)

  // State
  @State private var textFieldState: VGSTextFieldState? = nil
  
  // MARK: - Textfield UI attributes
  let paddings = UIEdgeInsets(top: 2,left: 8,bottom: 2,right: 8)
  let validColor = UIColor.lightGray
  let invalidColor = UIColor.red
      
  // Build View
  var body: some View {
    
    // extfield Configuration
    var configuration: VGSConfiguration {
      let config = VGSConfiguration(collector: vgsCollect, fieldName: "name")
      config.type = .cardHolderName
      return config
    }
    
    return VStack() {
      VGSTextFieldRepresentable(configuration: configuration)
        .placeholder("Holder Name")
        /// Track field editing events and State
        .onEditingEvent { event in
            switch event {
            case .didBegin(let state):
              print("Editing began with state: \(state.description)")
            case .didChange(let state):
                print("Editing changed with state: \(state.description)")
            case .didEnd(let state):
                print("Editing ended with state: \(state.description)")
            }
        }
        /// Track field State changes
        .onStateChange { newState in
          print(newState.isValid)
          textFieldState = newState
        }
        .textFieldPadding(paddings)
        .border(color: (textFieldState?.isValid ?? true) ? validColor : invalidColor, lineWidth: 1)
        .frame(height: 54)
    }
  }
}
```

## VGSCardTextFieldRepresentable

A component that displays an editable text interface, for use instead of a `VGSTextFieldRepresentable` when you need to detect credit card brand while user typing data and display card brand image in a text field. All card brand images are included in the SDK, however you still can set your custom images.

### Declaration

```swift
struct VGSCardTextFieldRepresentable: UIViewRepresentable
```

### Creating VGSCardTextFieldRepresentable

```swift
/// Initialization
///
/// - Parameters:
///   - configuration: `VGSConfiguration` instance.
public init(configuration: VGSConfiguration)
```

### Instance Methods

`VGSCardTextFieldRepresentable` is a SwiftUI wrapper around `VGSCardTextField` and have similar attributes and functionality represented in SwiftUI way. `VGSCardTextFieldRepresentable` has same functionality as `VGSTextFieldRepresentable` with additional modifiers.

### VGSCardTextFieldRepresentable Card Icon modifiers

```swift
/// Set `size` of card icon.
public func cardIconSize(_ size: CGSize)
/// Set Card brand icon positions `CardIconLocation`.
public func cardIconLocation(_ location: VGSCardTextField.CardIconLocation)
```

Also `VGSCardTextFieldRepresentable` provide extandable `VGSCardState` with attributes specific to Card Number validation

```swift
/// Handle `VGSCardState` changes.
public func onStateChange(_ action: ((VGSCardState) -> Void)?)
```

### Code example

```swift
// Setup  VGSConfiguration
var cardNumConfiguration: VGSConfiguration {
  let config = VGSConfiguration(collector: vgsCollect, fieldName: "card_number")
  config.type = .cardNumber
  return config
}
/// Set card brand icons globally
VGSPaymentCards.visa.brandIcon = UIImage(named: "my visa icon")
VGSPaymentCards.unknown.brandIcon = UIImage(named: "my unknown brand icon")
/// Return VGSCardTextFieldRepresentable Component
VGSCardTextFieldRepresentable(configuration: cardNumConfiguration)
          .placeholder("4111 1111 1111 1111")
          .onStateChange { newState in
            print(newState.bin)
            print(newState.cardBrand)
            cardTextFieldState = newState
          }
          .cardIconSize(CGSize(width: 40, height: 20))
          .cardIconLocation(.right)
          .textFieldPadding(paddings)
          .border(color: (cardTextFieldState?.isValid ?? true) ? validColor : invalidColor, lineWidth: 1)
          .frame(height: 54)
```

## VGSCVCTextFieldRepresentable

A component that displays an editable text interface, for use instead of a `VGSCVCTextFieldRepresentable` when you need to display CVC image. CVC image can change dynamically for specific card brand(e.g. CVC image for Amex contains 4 digits). CVC image files are included in the SDK, however you still can set your custom images.

### Declaration

```swift
struct VGSCVCTextFieldRepresentable: UIViewRepresentable
```

### Creating VGSCVCTextFieldRepresentable

```swift
/// Initialization
///
/// - Parameters:
///   - configuration: `VGSConfiguration` instance.
public init(configuration: VGSConfiguration)
```

### Instance Methods

`VGSCVCTextFieldRepresentable` is a SwiftUI wrapper around `VGSCVCTextField` and have similar attributes and functionality represented in SwiftUI way. `VGSCVCTextFieldRepresentable` has same functionality as `VGSTextFieldRepresentable` with additional modifiers.

### VGSCVCTextFieldRepresentable Card Icon modifiers

```swift
/// Set size of CVC  icon.
public func cvcIconSize(_ size: CGSize)
/// Set `VGSCVCTextField.CVCIconLocation` inside textfield.
public func cvcIconLocation(_ location: VGSCVCTextField.CVCIconLocation)
/// Set CVC icon image for specific `VGSPaymentCards.CardBrand`.
public func cvcIconSource(_ sourceImage: @escaping (VGSPaymentCards.CardBrand) -> UIImage?)
```

### Code example

```swift
// Setup  VGSConfiguration
var cvcConfiguration: VGSConfiguration {
  let config = VGSConfiguration(collector: vgsCollect, fieldName: "card_cvc")
  config.type = .cvc
  return config
}
/// Set card brand icons globally(you can also set icon via `cvcIconSource(:)` modifier)
VGSPaymentCards.amex.cvcIcon = UIImage(named: "my CVC icon for Amex")
VGSPaymentCards.unknown.cvcIcon = UIImage(named: "my CVC icon for unknown brand")
/// Return VGSCVCTextFieldRepresentable Component
VGSCVCTextFieldRepresentable(configuration: cvcConfiguration)
    .placeholder("CVC/CVV")
    .setSecureTextEntry(true)
    .cvcIconSize(CGSize(width: 30, height: 20))
    .textFieldPadding(paddings)
    .border(color: (cvcTextFieldState?.isValid ?? true) ? validColor : invalidColor, lineWidth: 1)
    .frame(height: 54)
```

## VGSExpDateTextFieldRepresentable

A component that displays an editable text interface. In addition, `VGSExpDateTextFieldRepresentable` provides an option to use date picker as input source instead of keyboard. Input source can be specified in `VGSExpDateConfiguration`.

### Declaration

```swift
struct VGSExpDateTextFieldRepresentable: UIViewRepresentable
```

### Creating VGSExpDateTextFieldRepresentable

```swift
/// Initialization
///
/// - Parameters:
///   - configuration: `VGSExpDateConfiguration` instance.
public init(configuration: VGSExpDateConfiguration)
```

### Instance Methods

`VGSExpDateTextFieldRepresentable` is a SwiftUI wrapper around `VGSExpDateTextField` and have similar attributes and functionality represented in SwiftUI way. `VGSExpDateTextFieldRepresentable` has same functionality as `VGSTextFieldRepresentable` with additional modifiers.

### VGSExpDateTextFieldRepresentable Input Source modifiers

```swift
/// Set `VGSExpDateTextField.MonthFormat`  UIPicker format.  Default is `.longSymbols`.
public func monthPickerFormat(_ format: VGSExpDateTextField.MonthFormat)
/// Set `VGSExpDateTextField.YearFormat`  UIPicker format.  Default is `.long`.
public func yearPickerFormat(_ format: VGSExpDateTextField.YearFormat) 
```

### Code example

```swift
// Setup  VGSExpDateConfiguration
let expDateConfiguration = VGSExpDateConfiguration(collector: vgsCollect, fieldName: "card_expirationDate")
expDateConfiguration.type = .expDate
/// Set input source if needed. Default is `VGSTextFieldInputSource.datePicker`
expDateConfiguration.inputSource = .datePicker
/// Return VGSExpDateTextFieldRepresentable Component
VGSExpDateTextFieldRepresentable(configuration: expDateConfiguration)
  .placeholder( "MM/YY")
  /// Set month picker date format as long symbols: e.g.:`January`
  .monthPickerFormat(.longSymbols)
  /// Set year picker date format as long year: e.g.:`2021`
  .yearPickerFormat(.long)
  .onStateChange { newState in
    print(newState.isValid)
  }
  .textFieldPadding(paddings)
  .frame(height: 54)
/// Output format will be same as field formatPattern:
/// "##/##" - "01/21"
/// OR
/// "##/####" - "01/2021"
```

> • The date format displayed in the picker doesn't have impact on date format displayed in the field. SDK will automatically convert selected date when setting it into the field, based on the field **formatPattern**.\
> • Date picker have limited valid expiration date range. Basicaly, it allows to set any date in future from current month plus 20 years.\
> • If you need to collect date with long year format(**MM/YYYY**) you should update field **.formatPattern** and change default **VGSValidationRuleCardExpirationDate** rule in filed validation rules.

## VGSDateTextFieldRepresentable

A component that displays an editable text interface. Component provides an option to validate that date is in a specific range. It also allows to use date picker as input source instead of keyboard. Input source and date range can be specified in `VGSDateConfiguration`.

### Declaration

```swift
struct VGSDateTextFieldRepresentable: UIViewRepresentable
```

### Creating VGSDateTextFieldRepresentable

```swift
/// Initialization
///
/// - Parameters:
///   - configuration: `VGSDateConfiguration` instance.
public init(configuration: VGSDateConfiguration)
```

### Instance Methods

`VGSDateTextFieldRepresentable` is a SwiftUI wrapper around `VGSDateTextField` and have similar attributes and functionality represented in SwiftUI way. `VGSDateTextFieldRepresentable` has same functionality as `VGSTextFieldRepresentable` with additional modifiers.

### VGSDateTextFieldRepresentable Input Source modifiers

```swift
/// Set `VGSDateTextField.MonthFormat`  UIPicker format. Default is `.shortSymbols`.
public func monthPickerFormat(_ format: VGSDateTextField.MonthFormat)
```

> • The date format displayed in the picker doesn't have impact on date format displayed in the field. SDK will automatically convert selected date when setting it into the field, based on the field `formatPattern`.\
> • Date picker will use the `datePickerStartDate` and `datePickerEndDate` dates as limited valid range. If they are not supplied, it will use the default range as:\
> \- `datePickerStartDate`: Today minus 100 years.\
> \- `datePickerEndDate`: Today plus 100 years.\\

### Code example

```swift
// Setup  VGSDateConfiguration
/// Set start and end dates, this is optional
let startDate = VGSDate(day: 1, month: 1, year: 2010)
let endDate = VGSDate(day: 1, month: 1, year: 2020)
/// Date format
let inputDateFormat = VGSDateFormat.mmddyyyy
/// Create configuration
let dateFieldConfiguration = VGSDateConfiguration(
  collector: vgsCollect,
  fieldName: "date_field",
  datePickerStartDate: startDate,
  datePickerEndDate: endDate
)
dateFieldConfiguration.inputDateFormat = inputDateFormat
dateFieldConfiguration.outputDateFormat = .yyyymmdd
dateFieldConfiguration.inputSource = .datePicker
dateFieldConfiguration.divider = "-"
dateFieldConfiguration.formatPattern = "##/##/####"
/// Setup validation rules, it is important to set the same start date,
/// end date and input date format used in the configuration
dateFieldConfiguration.validationRules = VGSValidationRuleSet(
  rules: [
    VGSValidationRuleDateRange(
      dateFormat: inputDateFormat,
      error: VGSValidationErrorType.date.rawValue,
      start: startDate,
      end: endDate
    )
  ]
)
/// Return VGSDateTextFieldRepresentable Component
VGSDateTextFieldRepresentable(configuration: dateFieldConfiguration)
  .placeholder("MM/DD/YYYY")
  .monthPickerFormat(.longSymbols)
  .onStateChange { newState in
    print(newState.isValid)
  }
  .textFieldPadding(paddings)
  .frame(height: 54)

/// Input format will use the formatPattern to display the date:
/// "01-02-2000" - "01/02/2010"
///
/// Output format will be same as field formatPattern using the divider:
/// "##/##/####" - "2010-02-01"
///
/// If no custom divider is set, output format will use the default divider "/":
/// "##/##/####" - "2010/02/01"
```

For more details about available attributes and functionality check our [Demo App](https://github.com/verygoodsecurity/vgs-collect-ios)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.verygoodsecurity.com/vault/developer-tools/vgs-collect/ios-sdk/swiftui-components.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
