# Card-on-file

Learn about how to configure the card-on-file component.

## Basic usage

### Minimal configuration

At minimum, the card-on-file component can be created with default settings to display all saved card tokens:


```typescript
import PxpCheckout from '@pxp-io/web-components-sdk';

const pxpCheckout = PxpCheckout.initialize({
  session: {
    sessionId: 'your-session-id',
    hmacKey: 'your-hmac-key',
    encryptionKey: 'your-encryption-key'
  },
  environment: 'production',
  transactionData: {
    amount: 1000,
    currency: 'USD',
    entryType: 'Ecom',
    intent: {
      card: 'Authorisation'
    },
    merchantTransactionId: 'unique-transaction-id',
    merchantTransactionDate: () => new Date().toISOString()
  },
  ownerType: 'MerchantGroup',
  ownerId: 'your-owner-id'
});

// Create card-on-file component
const cardOnFileComponent = pxpCheckout.create('card-on-file', {});

// Mount component
cardOnFileComponent.mount('card-on-file-container');
```

### Advanced configuration

For more complex implementations, you can configure filtering, sorting, and display options:


```typescript
// Create additional components for card-on-file
const cardCvc = pxpCheckout.create('card-cvc', {
  label: "Security code",
  required: true
});

const cardExpiry = pxpCheckout.create('card-expiry-date', {
  label: "Expiry date"
});

// Create card-on-file with advanced configuration
const cardOnFileComponent = pxpCheckout.create('card-on-file', {
  // Filtering options
  limitTokens: 5,
  filterBy: {
    excludeExpiredTokens: true,
    schemes: ["Visa", "Mastercard"],
    fundingSource: "Credit",
    issuerCountryCode: "USA",
    ownerType: "Consumer"
  },
  
  // Sorting options
  orderBy: {
    expiryDate: { 
      direction: "asc",
      priority: 1
    },
    scheme: { 
      valuesOrder: ["Visa", "Mastercard", "Amex"],
      priority: 2
    },
    fundingSource: { 
      valuesOrder: ["Credit", "Debit"],
      priority: 3
    },
    lastUsageDate: { 
      direction: "desc",
      orderByField: "lastSuccessfulPurchaseDate",
      priority: 4
    }
  },
  
  // UI configuration
  isExpiryDateEditable: true,
  isCvcRequired: true,
  allowDeleteToken: true,
  
  // Nested components
  cvcComponentConfig: {
    required: true,
    label: "Security code",
    applyMask: true,
    showMaskToggle: true
  },
  expiryDateComponentConfig: {
    label: "Expiry date",
    formatOptions: "MM/YY"
  }
});
```

| Property | Description |
|  --- | --- |
| `limitTokens`number | The maximum number of tokens to display in the component. For example, if set to `5` then only the first five card tokens are displayed. Defaults to `null`. |
| `filterBy`object | Details about the filtering options. Defaults to `null`. |
| `filterBy.excludeExpiredTokens`boolean | Whether to exclude tokens associated with expired cards. Defaults to `false`. |
| `filterBy.schemes`string[] | The list of card schemes to include. For example, `["Visa", "Mastercard"]`. Defaults to `null`. |
| `filterBy.fundingSource`string | The funding source type to include. For example `Credit` or `Debit`. Defaults to `null`. |
| `filterBy.issuerCountryCode`string | The issuer country code to include. Defaults to `null`. |
| `filterBy.ownerType`string | The owner type to include. Defaults to `null`. |
| `orderBy`object | Details about the ordering options. Defaults to `null`. |
| `orderBy.expiryDate`object | Details for ordering by expiry date. Defaults to `null`. |
| `orderBy.expiryDate.direction`string | The direction to order by.Possible values:`desc``asc` Defaults to `null`. |
| `orderBy.expiryDate.priority`number | The priority of the ordering option. Defaults to `null`. |
| `orderBy.scheme`object | Details for ordering by card scheme. Defaults to `null`. |
| `orderBy.scheme.valuesOrder`string | The card scheme. Defaults to `null`. |
| `orderBy.scheme.priority`number | The priority of the ordering option. Defaults to `null`. |
| `orderBy.fundingSource`object | Details for ordering by funding source. Defaults to `null`. |
| `orderBy.fundingSource.valuesOrder`string | The funding source.Possible values:`Credit``Debit` Defaults to `null`. |
| `orderBy.fundingSource.priority`number | The priority of the ordering option. Defaults to `null`. |
| `orderBy.ownerType`object | Details for ordering by owner type. Defaults to `null`. |
| `orderBy.ownerType.valuesOrder`string | The owner type.Possible values:`Consumer``Commercial` Defaults to `null`. |
| `orderBy.ownerType.priority`number | The priority of the ordering option. Defaults to `null`. |
| `orderBy.issuerCountryCode`object | Details for ordering by issuer country code. Defaults to `null`. |
| `orderBy.issuerCountryCode.direction`string | The direction to order by.Possible values:`desc``asc` Defaults to `null`. |
| `orderBy.issuerCountryCode.priority`number | The priority of the ordering option. Defaults to `null`. |
| `orderBy.lastUsageDate`object | Details for ordering by last usage date. Defaults to `null`. |
| `orderBy.lastUsageDate.direction`string | The direction to order by.Possible values:`desc``asc` Defaults to `null`. |
| `orderBy.lastUsageDate.orderByField`string | The field to order by.Possible values:`lastSuccessfulPurchaseDate``lastSuccessfulPayoutDate` Defaults to `null`. |
| `orderBy.lastUsageDate.priority`number | The priority of the ordering option. Defaults to `null`. |
| `transactionInitiatorType`TransactionInitiatorType | Transaction initiator type. Defaults to `null`. |
| `isExpiryDateEditable`boolean | Whether the expiry date field can be edited by the cardholder. Defaults to `false`. |
| `isCvcRequired`boolean | Whether CVC is required when selecting a token. This applies to all tokens. Defaults to `false`. |
| `allowDeleteToken`boolean | Whether to allow cardholders to delete a token (previously saved card). Defaults to `false`. |
| `cvcComponentConfig`CardCvcComponentConfig | Configuration for the standalone card CVC component. See [Card CVC](/guides/checkout/components/web/card/card-cvc). Defaults to `null`. |
| `expiryDateComponentConfig`CardExpiryDateComponentConfig | Configuration for the standalone card expiry date component. See [Card expiry date](/guides/checkout/components/web/card/card-expiry-date). Defaults to `null`. |


## Styling

### Default styling

The card-on-file component renders saved cards with these default styles:


```typescript
const defaultCardOnFileStyles = {
  container: {
    display: 'flex',
    flexDirection: 'column',
    gap: '12px',
    width: '100%'
  },
  
  tokenItem: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'space-between',
    padding: '16px',
    backgroundColor: '#ffffff',
    border: '1px solid #dee2e6',
    borderRadius: '8px',
    cursor: 'pointer'
  },
  
  cardBrandImage: {
    width: '40px',
    height: 'auto'
  },
  
  cardDetails: {
    display: 'flex',
    flexDirection: 'column',
    gap: '4px'
  },
  
  expiredText: {
    color: '#dc3545',
    fontSize: '12px',
    fontWeight: '500'
  },
  
  validThruText: {
    color: '#6c757d',
    fontSize: '12px'
  }
};
```

| Property | Description |
|  --- | --- |
| `id`string | Unique identifier for the component element. Defaults to `null`. |
| `class`string | CSS class name applied to the component. Defaults to `null`. |
| `tokenItemClass`string | Custom class for the token item. Defaults to `null`. |


### Custom styling

You can override the default appearance by providing custom styles, images, and text labels:


```typescript
const cardOnFileComponent = pxpCheckout.create('card-on-file', {
  // Custom text labels
  expiredText: "Card expired",
  validThruText: "Valid until",
  deleteErrorMessage: "Unable to delete card. Please try again.",
  deleteSuccessMessage: "Card has been removed successfully.",
  updateErrorMessage: "Unable to update card information. Please try again.",
  updateSuccessMessage: "Card information updated successfully.",
  
  // Custom styling
  styles: {
    backgroundColor: '#f8f9fa',
    border: '1px solid #dee2e6',
    borderRadius: '8px',
    padding: '20px'
  },
  
  inputStyles: {
    borderRadius: '5px',
    backgroundColor: '#ffffff'
  },
  
  tokenItemClass: "custom-token-item-class",
  
  // Custom icons
  iconDeleteSrc: "https://example.com/icons/delete.svg",
  iconSaveSrc: "https://example.com/icons/save.svg",
  iconCancelSrc: "https://example.com/icons/cancel.svg",
  iconEditSrc: "https://example.com/icons/edit.svg",
  
  // Custom card brand images
  cardBrandImages: {
    visaSrc: "https://example.com/brands/visa-logo.png",
    mastercardSrc: "https://example.com/brands/mastercard-logo.png",
    amexSrc: "https://example.com/brands/amex-logo.png",
    cupSrc: "https://example.com/brands/cup-logo.png",
    dinersSrc: "https://example.com/brands/diners-logo.png",
    discoverSrc: "https://example.com/brands/discover-logo.png",
    jcbSrc: "https://example.com/brands/jcb-logo.png"
  },
  
  useTransparentCardBrandImage: true,
  
  // Accessibility labels
  editCardInformationAriaLabel: "Edit card information button",
  saveCardInformationAriaLabel: "Save card information button",
  cancelEditCardInformationAriaLabel: "Cancel edit card information button",
  deleteCardButtonAriaLabel: "Delete card button",
  cardNumberAriaLabel: "Card number",
  cardExpiryDateAriaLabel: "Card expiry date",
  
  // Delete modal configuration
  deleteModal: {
    dialogAriaLabel: "Delete card dialog",
    bodyText: "Are you sure you want to delete this payment method?",
    cancelButtonText: "No, keep it",
    deleteButtonText: 'Yes, delete it',
    class: "custom-modal-class"
  },
  
  // Message styling
  successMessageClass: "alert alert-success",
  errorMessageClass: "alert alert-danger"
});
```

| Property | Description |
|  --- | --- |
| `styles`CSSProperties | Custom styling for the component container. Defaults to `null`. |
| `inputStyles`CSSProperties | Custom input styles. Defaults to `null`. |
| `tokenItemClass`string | Custom class for the token item. Defaults to `null`. |
| `cardBrandImages`object | Details about the card brand images. Defaults to `null`. |
| `cardBrandImages.visaSrc`string | The URL for the Visa card brand image. Defaults to `null`. |
| `cardBrandImages.mastercardSrc`string | The URL for the Mastercard card brand image. Defaults to `null`. |
| `cardBrandImages.amexSrc`string | The URL for the Amex card brand image. Defaults to `null`. |
| `cardBrandImages.cupSrc`string | The URL for the CUP card brand image. Defaults to `null`. |
| `cardBrandImages.dinersSrc`string | The URL for the Diners card brand image. Defaults to `null`. |
| `cardBrandImages.discoverSrc`string | The URL for the Discover card brand image. Defaults to `null`. |
| `cardBrandImages.jcbSrc`string | The URL for the JCB card brand image. Defaults to `null`. |
| `iconDeleteSrc`string | The URL for your custom delete icon. Defaults to `null`. |
| `iconSaveSrc`string | The URL for your custom save icon. Defaults to `null`. |
| `iconCancelSrc`string | The URL for your custom cancel icon. Defaults to `null`. |
| `iconEditSrc`string | The URL for your custom edit icon. Defaults to `null`. |
| `useTransparentCardBrandImage`boolean | Whether to use transparent card brand images. Defaults to `true`. |
| `expiredText`string | The text to display for expired cards. Defaults to `"Expired"`. |
| `validThruText`string | The text to display for the "valid thru" label. Defaults to `"Valid thru"`. |
| `deleteModal`object | Configuration for the deletion modal. Defaults to `null`. |
| `deleteModal.dialogAriaLabel`string | The aria label for the deletion modal. Defaults to `null`. |
| `deleteModal.bodyText`string | The body text for the deletion modal. Defaults to `null`. |
| `deleteModal.cancelButtonText`string | The cancel button text for the deletion modal. Defaults to `null`. |
| `deleteModal.deleteButtonText`string | The delete button text for the deletion modal. Defaults to `null`. |
| `deleteModal.class`string | The name of the class associated with the deletion modal. Defaults to `null`. |
| `deleteErrorMessage`string | The error message to display when a card deletion fails. Defaults to `null`. |
| `deleteSuccessMessage`string | The success message to display when a card deletion is successful. Defaults to `null`. |
| `updateErrorMessage`string | The error message to display when a card update fails. Defaults to `null`. |
| `updateSuccessMessage`string | The success message to display when a card update is successful. Defaults to `null`. |
| `successMessageClass`string | The name of the CSS class to apply to success messages. Defaults to `null`. |
| `errorMessageClass`string | The name of the CSS class to apply to error messages. Defaults to `null`. |
| `editCardInformationAriaLabel`string | The aria label for the edit card information button. Defaults to `null`. |
| `saveCardInformationAriaLabel`string | The aria label for the save card information button. Defaults to `null`. |
| `cancelEditCardInformationAriaLabel`string | The aria label for the cancel edit information button. Defaults to `null`. |
| `deleteCardButtonAriaLabel`string | The aria label for the delete card button. Defaults to `null`. |
| `cardNumberAriaLabel`string | The aria label for the card number. Defaults to `null`. |
| `cardExpiryDateAriaLabel`string | The aria label for the card expiry date. Defaults to `null`. |


## Event handling

The card-on-file component provides event handlers to manage token retrieval, rendering, updates, and deletions:


```typescript
const cardOnFileComponent = pxpCheckout.create('card-on-file', {
  onPreRenderTokens: (data: RetrieveCardTokensReponseSuccess) => {
    // Filter tokens before rendering
    return data.gatewayTokens
      .filter(token => token.issuerCountryCode === 'USA')
      .map(token => ({
        id: token.gatewayTokenId,
        isCvcRequired: true
      }));
  },
  
  onRetrieveTokensFailed: (data: RetrieveCardTokensReponseFailed) => {
    console.error('Failed to retrieve tokens:', data.errorMessage);
    showErrorMessage('Unable to load saved cards');
  },
  
  onSelectToken: (token: BaseCardToken) => {
    console.log('Token selected:', token);
    console.log('Selected card:', token.maskedPrimaryAccountNumber);
  },
  
  onPreDeleteToken: (token: BaseCardToken) => {
    return new Promise((resolve) => {
      const confirmed = confirm(
        `Are you sure you want to delete card ending in ${token.maskedPrimaryAccountNumber.slice(-4)}?`
      );
      resolve(confirmed);
    });
  },
  
  onDeleteTokenSuccess: (data: DeleteCardTokenResponseSuccess) => {
    console.log('Token deleted successfully:', data);
    showSuccessMessage('Card removed successfully');
    refreshTokenList();
  },
  
  onDeleteTokenFailed: (data: DeleteCardTokenResponseFailed) => {
    console.error('Delete failed:', data);
    showErrorMessage('Failed to delete card. Please try again.');
  },
  
  onUpdateTokenSuccess: (data: UpdateCardTokenResponseSuccess) => {
    console.log('Token updated successfully:', data);
    showSuccessMessage('Card information updated');
  },
  
  onUpdateTokenFailed: (data: UpdateCardTokenResponseFailed) => {
    console.error('Update failed:', data);
    showErrorMessage('Failed to update card information');
  },
  
  tokenItemBuilder: (elementIds: TokenBuilderElementIds) => {
    return `
      <div class="custom-token-layout">
        <div id="${elementIds.tokenImageId}"></div>
        <div id="${elementIds.tokenLabelId}"></div>
        <div id="${elementIds.editButtonId}"></div>
        <div id="${elementIds.deleteButtonId}"></div>
      </div>
    `;
  },
  
  tokenLabelBuilder: (token: BaseCardToken) => {
    return `${token.maskedPrimaryAccountNumber} - ${token.issuerName}`;
  }
});
```

| Callback | Description |
|  --- | --- |
| `onPreRenderTokens: (data: RetrieveCardTokensReponseSuccess) => CardTokenMapping[]` | Event handler for pre-processing tokens before rendering. Allows custom filtering and mapping of token data. |
| `onRetrieveTokensFailed: (data: RetrieveCardTokensReponseFailed) => void` | Event handler for when token retrieval from the API fails. |
| `onSelectToken: (token: BaseCardToken) => void` | Event handler triggered when a token is selected by the user. |
| `onPreDeleteToken: (token: BaseCardToken) => Promise<boolean>` | Event handler for before token deletion. Return `true` to proceed, `false` to cancel. |
| `onDeleteTokenSuccess: (data: DeleteCardTokenResponseSuccess) => void` | Event handler for after a token is successfully deleted. |
| `onDeleteTokenFailed: (data: DeleteCardTokenResponseFailed) => void` | Event handler for when token deletion fails. |
| `onUpdateTokenSuccess: (data: UpdateCardTokenResponseSuccess) => void` | Event handler for after a token is successfully updated. |
| `onUpdateTokenFailed: (data: UpdateCardTokenResponseFailed) => void` | Event handler for when a token update fails. |
| `tokenItemBuilder: (elementIds: TokenBuilderElementIds) => string` | Custom HTML builder for token item layout. Returns an HTML string with specific element IDs. |
| `tokenLabelBuilder: (token: BaseCardToken) => string` | Custom label builder for token display text. |


For more information about event data structures and usage patterns, see [Events](/guides/checkout/components/web/card/events).

## Methods

The card-on-file component provides methods for lifecycle management:

### `mount(containerId)`

Mounts the component to the DOM:


```typescript
cardOnFileComponent.mount('card-on-file-container');
```

**Parameters:**

- `containerId` (string) - The ID of the container element


### `unmount()`

Removes the component from the DOM and cleans up resources:


```typescript
cardOnFileComponent.unmount();
```

## Examples

### Basic saved cards display

A straightforward implementation showing saved payment methods:


```typescript
const cardOnFileComponent = pxpCheckout.create('card-on-file', {
  limitTokens: 5,
  filterBy: {
    excludeExpiredTokens: true
  },
  
  onSelectToken: (token) => {
    console.log('Card selected:', token.maskedPrimaryAccountNumber);
  },
  
  onRetrieveTokensFailed: (error) => {
    console.error('Failed to load cards:', error);
    showErrorMessage('Unable to load saved cards');
  }
});

cardOnFileComponent.mount('card-on-file-container');
```

### Filtered and sorted cards

Display only specific card types in a custom order:


```typescript
const cardOnFileComponent = pxpCheckout.create('card-on-file', {
  // Show only Visa and Mastercard credit cards
  filterBy: {
    excludeExpiredTokens: true,
    schemes: ["Visa", "Mastercard"],
    fundingSource: "Credit",
    issuerCountryCode: "USA"
  },
  
  // Sort by most recently used
  orderBy: {
    lastUsageDate: { 
      direction: "desc",
      orderByField: "lastSuccessfulPurchaseDate",
      priority: 1
    },
    scheme: { 
      valuesOrder: ["Visa", "Mastercard"],
      priority: 2
    }
  },
  
  limitTokens: 3,
  
  onPreRenderTokens: (data) => {
    // Additional custom filtering if needed
    return data.gatewayTokens
      .filter(token => token.fundingSource === 'Credit')
      .map(token => ({
        id: token.gatewayTokenId,
        isCvcRequired: true
      }));
  }
});

cardOnFileComponent.mount('card-on-file-container');
```

### Editable cards with CVC requirement

Allow users to edit and delete their saved cards:


```typescript
const cardOnFileComponent = pxpCheckout.create('card-on-file', {
  isExpiryDateEditable: true,
  isCvcRequired: true,
  allowDeleteToken: true,
  
  cvcComponentConfig: {
    required: true,
    label: "Security code",
    applyMask: true,
    showMaskToggle: true,
    labelPosition: "left",
    errorMessage: "Please enter a valid security code",
    inputStyles: {
      base: {
        color: "#333",
        fontSize: "16px"
      }
    }
  },
  
  expiryDateComponentConfig: {
    label: "Expiry date",
    labelPosition: "left",
    formatOptions: "MM/YY",
    inputStyles: {
      base: {
        color: "#333",
        fontSize: "16px"
      }
    }
  },
  
  onSelectToken: (token) => {
    console.log('Card selected:', token);
    // Validate CVC when card is selected
  },
  
  onPreDeleteToken: (token) => {
    return new Promise((resolve) => {
      const confirmed = confirm(
        `Delete card ending in ${token.maskedPrimaryAccountNumber.slice(-4)}?`
      );
      resolve(confirmed);
    });
  },
  
  onDeleteTokenSuccess: (data) => {
    showSuccessMessage('Card deleted successfully');
  },
  
  onDeleteTokenFailed: (error) => {
    showErrorMessage('Failed to delete card');
  },
  
  onUpdateTokenSuccess: (data) => {
    showSuccessMessage('Card updated successfully');
  },
  
  onUpdateTokenFailed: (error) => {
    showErrorMessage('Failed to update card');
  }
});

cardOnFileComponent.mount('card-on-file-container');
```

### Custom styled cards with branding

Fully customised appearance with branded images and styles:


```typescript
const cardOnFileComponent = pxpCheckout.create('card-on-file', {
  limitTokens: 5,
  filterBy: {
    excludeExpiredTokens: true
  },
  
  // Custom card brand images
  cardBrandImages: {
    visaSrc: "https://example.com/images/visa-logo.png",
    mastercardSrc: "https://example.com/images/mastercard-logo.png",
    amexSrc: "https://example.com/images/amex-logo.png"
  },
  
  // Custom text labels
  expiredText: "Card expired",
  validThruText: "Valid until",
  deleteSuccessMessage: "Payment method removed",
  updateSuccessMessage: "Card details updated",
  
  // Custom styling
  styles: {
    backgroundColor: '#f8f9fa',
    border: '1px solid #dee2e6',
    borderRadius: '8px',
    padding: '20px'
  },
  
  inputStyles: {
    borderRadius: '5px',
    backgroundColor: '#ffffff'
  },
  
  tokenItemClass: "custom-payment-card",
  
  // Custom icons
  iconDeleteSrc: "https://example.com/icons/delete.svg",
  iconEditSrc: "https://example.com/icons/edit.svg",
  iconSaveSrc: "https://example.com/icons/save.svg",
  iconCancelSrc: "https://example.com/icons/cancel.svg",
  
  useTransparentCardBrandImage: true,
  
  // Custom delete modal
  deleteModal: {
    dialogAriaLabel: "Delete payment method",
    bodyText: "Are you sure you want to remove this payment method?",
    cancelButtonText: "No, keep it",
    deleteButtonText: 'Yes, remove it',
    class: "custom-delete-modal"
  },
  
  successMessageClass: "alert alert-success",
  errorMessageClass: "alert alert-danger",
  
  // Accessibility
  editCardInformationAriaLabel: "Edit payment method",
  saveCardInformationAriaLabel: "Save changes",
  cancelEditCardInformationAriaLabel: "Cancel editing",
  deleteCardButtonAriaLabel: "Remove payment method",
  
  onSelectToken: (token) => {
    console.log('Selected:', token.maskedPrimaryAccountNumber);
  }
});

cardOnFileComponent.mount('card-on-file-container');
```

### Custom token layout

Use custom HTML builders to create a unique token display:


```typescript
const cardOnFileComponent = pxpCheckout.create('card-on-file', {
  tokenItemBuilder: (elementIds) => {
    return `
      <div class="payment-card-item">
        <div class="card-header">
          <div id="${elementIds.tokenImageId}" class="brand-logo"></div>
          <div id="${elementIds.tokenLabelId}" class="card-info"></div>
        </div>
        <div class="card-actions">
          <div id="${elementIds.editButtonId}" class="edit-btn"></div>
          <div id="${elementIds.deleteButtonId}" class="delete-btn"></div>
        </div>
      </div>
    `;
  },
  
  tokenLabelBuilder: (token) => {
    const lastFour = token.maskedPrimaryAccountNumber.slice(-4);
    const expiryDate = token.expiryDate;
    return `
      <div>
        <strong>${token.scheme}</strong> •••• ${lastFour}
        <br>
        <small>Expires ${expiryDate}</small>
      </div>
    `;
  },
  
  onSelectToken: (token) => {
    console.log('Selected token:', token);
  }
});

cardOnFileComponent.mount('card-on-file-container');
```

### Enterprise implementation with all features

A comprehensive implementation with filtering, sorting, editing, and complete event handling:


```typescript
const cardOnFileComponent = pxpCheckout.create('card-on-file', {
  // Filtering and limiting
  limitTokens: 10,
  filterBy: {
    excludeExpiredTokens: true,
    schemes: ["Visa", "Mastercard", "Amex"],
    fundingSource: "Credit"
  },
  
  // Multi-level sorting
  orderBy: {
    lastUsageDate: { 
      direction: "desc",
      orderByField: "lastSuccessfulPurchaseDate",
      priority: 1
    },
    expiryDate: { 
      direction: "asc",
      priority: 2
    },
    scheme: { 
      valuesOrder: ["Visa", "Mastercard", "Amex"],
      priority: 3
    }
  },
  
  // Feature flags
  isExpiryDateEditable: true,
  isCvcRequired: true,
  allowDeleteToken: true,
  
  // Nested component configuration
  cvcComponentConfig: {
    required: true,
    label: "CVV/CVC",
    applyMask: true,
    showMaskToggle: true,
    labelPosition: "left",
    inputStyles: {
      base: { fontSize: "16px", color: "#333" }
    }
  },
  
  expiryDateComponentConfig: {
    label: "Expiry",
    formatOptions: "MM/YY",
    labelPosition: "left",
    inputStyles: {
      base: { fontSize: "16px", color: "#333" }
    }
  },
  
  // Comprehensive event handling
  onPreRenderTokens: (data) => {
    console.log('Retrieved tokens:', data.gatewayTokens.length);
    
    // Apply business logic filtering
    return data.gatewayTokens
      .filter(token => {
        // Only show cards from specific issuers
        return ['USA', 'CAN', 'GBR'].includes(token.issuerCountryCode);
      })
      .map(token => ({
        id: token.gatewayTokenId,
        isCvcRequired: token.scheme !== 'Amex' // Amex doesn't require CVC
      }));
  },
  
  onRetrieveTokensFailed: (error) => {
    console.error('Token retrieval failed:', error);
    logErrorToService(error);
    showUserMessage('Unable to load payment methods', 'error');
  },
  
  onSelectToken: (token) => {
    console.log('Token selected:', token);
    trackAnalyticsEvent('payment_method_selected', {
      scheme: token.scheme,
      fundingSource: token.fundingSource
    });
  },
  
  onPreDeleteToken: async (token) => {
    const lastFour = token.maskedPrimaryAccountNumber.slice(-4);
    const confirmed = await showCustomConfirmDialog({
      title: 'Remove Payment Method',
      message: `Remove card ending in ${lastFour}?`,
      confirmText: 'Remove',
      cancelText: 'Keep'
    });
    return confirmed;
  },
  
  onDeleteTokenSuccess: (data) => {
    console.log('Token deleted:', data);
    showUserMessage('Payment method removed', 'success');
    trackAnalyticsEvent('payment_method_deleted');
    refreshPaymentMethods();
  },
  
  onDeleteTokenFailed: (error) => {
    console.error('Delete failed:', error);
    showUserMessage('Unable to remove payment method', 'error');
    logErrorToService(error);
  },
  
  onUpdateTokenSuccess: (data) => {
    console.log('Token updated:', data);
    showUserMessage('Payment method updated', 'success');
    trackAnalyticsEvent('payment_method_updated');
  },
  
  onUpdateTokenFailed: (error) => {
    console.error('Update failed:', error);
    showUserMessage('Unable to update payment method', 'error');
    logErrorToService(error);
  },
  
  // Custom styling
  styles: {
    backgroundColor: '#ffffff',
    border: '1px solid #e5e7eb',
    borderRadius: '12px',
    padding: '24px',
    boxShadow: '0 1px 3px rgba(0,0,0,0.1)'
  },
  
  cardBrandImages: {
    visaSrc: "https://cdn.example.com/brands/visa.svg",
    mastercardSrc: "https://cdn.example.com/brands/mastercard.svg",
    amexSrc: "https://cdn.example.com/brands/amex.svg"
  },
  
  deleteModal: {
    dialogAriaLabel: "Remove payment method confirmation",
    bodyText: "This payment method will be permanently removed.",
    cancelButtonText: "Cancel",
    deleteButtonText: 'Remove',
    class: "enterprise-delete-modal"
  },
  
  successMessageClass: "toast toast-success",
  errorMessageClass: "toast toast-error"
});

cardOnFileComponent.mount('payment-methods-container');
```

For more information about integration and events, see [Events](/guides/checkout/components/web/card/events) and [Data validation](/guides/checkout/components/web/card/data-validation).