@vtex/faststore 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +101 -0
- package/dist/actions.json +181 -0
- package/dist/catalog.json +1673 -484
- package/dist/cli/UnreachableCaseError-Crd168Vu.js +10 -0
- package/dist/cli/UnreachableCaseError-Crd168Vu.js.map +1 -0
- package/dist/cli/cacheControl-CEojH_TM.js +158 -0
- package/dist/cli/cacheControl-CEojH_TM.js.map +1 -0
- package/dist/cli/cachePolicy-m2vASMRW.js +26 -0
- package/dist/cli/cachePolicy-m2vASMRW.js.map +1 -0
- package/dist/cli/computeCoreSchemaHash-DPJZj-qJ.js +10 -0
- package/dist/cli/computeCoreSchemaHash-DPJZj-qJ.js.map +1 -0
- package/dist/cli/default-BCQHcwbL.js +253 -0
- package/dist/cli/default-BCQHcwbL.js.map +1 -0
- package/dist/cli/disableSuggestions-yO9UqiWn.js +21 -0
- package/dist/cli/disableSuggestions-yO9UqiWn.js.map +1 -0
- package/dist/cli/dist-C1JhdHfo.js +2001 -0
- package/dist/cli/dist-C1JhdHfo.js.map +1 -0
- package/dist/cli/graphql-DG9thCDG.js +14589 -0
- package/dist/cli/graphql-DG9thCDG.js.map +1 -0
- package/dist/cli/index.d.ts +350 -0
- package/dist/cli/index.js +35047 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/index.min-BsIHDfFK.js +613 -0
- package/dist/cli/index.min-BsIHDfFK.js.map +1 -0
- package/dist/cli/inlineTrace-uLgOJ3TH.js +52 -0
- package/dist/cli/inlineTrace-uLgOJ3TH.js.map +1 -0
- package/dist/cli/internalPlugin-DnuwN4_4.js +11 -0
- package/dist/cli/internalPlugin-DnuwN4_4.js.map +1 -0
- package/dist/cli/packageVersion-DQAnIEil.js +6 -0
- package/dist/cli/packageVersion-DQAnIEil.js.map +1 -0
- package/dist/cli/rolldown-runtime-BMI-E3GI.js +44 -0
- package/dist/cli/schemaIsSubgraph-DoGh3OYj.js +17 -0
- package/dist/cli/schemaIsSubgraph-DoGh3OYj.js.map +1 -0
- package/dist/cli/schemaReporting-K-me-3-v.js +199 -0
- package/dist/cli/schemaReporting-K-me-3-v.js.map +1 -0
- package/dist/cli/server-runtime.js +49859 -0
- package/dist/cli/server-runtime.js.map +1 -0
- package/dist/cli/traceTreeBuilder-BIcV2U7b.js +9118 -0
- package/dist/cli/traceTreeBuilder-BIcV2U7b.js.map +1 -0
- package/dist/cli/usageReporting-Bpl8vSZX.js +10201 -0
- package/dist/cli/usageReporting-Bpl8vSZX.js.map +1 -0
- package/dist/cli/v4-CBhFvC49.js +42 -0
- package/dist/cli/v4-CBhFvC49.js.map +1 -0
- package/dist/client.d.ts +2 -1
- package/dist/client.js +2 -1
- package/dist/components.d.ts +32 -9
- package/dist/components.js +35 -14
- package/dist/content-types.json +93 -0
- package/dist/core/dist/define-component.d.ts +37 -0
- package/dist/core/dist/index.d.ts +2 -2
- package/dist/docs/access-code-sign-in.md +1 -1
- package/dist/docs/account-entry-point.md +1 -1
- package/dist/docs/account-menu-identity.md +160 -0
- package/dist/docs/account-menu.md +106 -23
- package/dist/docs/address-summary.md +24 -3
- package/dist/docs/alert-dialog.md +204 -0
- package/dist/docs/avatar.md +103 -0
- package/dist/docs/billing-address.md +284 -0
- package/dist/docs/card-entry.md +250 -0
- package/dist/docs/cardholder-document.md +142 -0
- package/dist/docs/client-preferences-fieldset.md +148 -0
- package/dist/docs/client-preferences.md +2 -1
- package/dist/docs/client-profile-fieldset.md +184 -0
- package/dist/docs/client-profile.md +1 -1
- package/dist/docs/document-field.md +58 -4
- package/dist/docs/field.md +317 -0
- package/dist/docs/form.md +307 -0
- package/dist/docs/identity-edit.md +6 -6
- package/dist/docs/identity-summary.md +5 -5
- package/dist/docs/installments.md +248 -0
- package/dist/docs/my-account-profile.md +2 -1
- package/dist/docs/order-placed-payment-summary.md +138 -0
- package/dist/docs/payment-method-badges.md +232 -0
- package/dist/docs/payment-methods.md +1 -0
- package/dist/docs/payment.md +218 -0
- package/dist/docs/phone-field.md +58 -4
- package/dist/docs/place-order.md +157 -0
- package/dist/docs/product-shelf.md +20 -13
- package/dist/docs/save-card.md +186 -0
- package/dist/docs/saved-cards.md +218 -0
- package/dist/docs/select.md +465 -0
- package/dist/docs/shipping-address.md +110 -258
- package/dist/index.d.ts +5 -2
- package/dist/internal/client.d.ts +3 -1
- package/dist/internal/client.js +4 -2
- package/dist/internal/content.d.ts +2 -2
- package/dist/internal/server.d.ts +4 -1
- package/dist/internal/server.js +4 -1
- package/dist/matter/access-code-sign-in/access-code-sign-in.js +9 -8
- package/dist/matter/access-code-sign-in/access-code-sign-in.js.map +1 -1
- package/dist/matter/account-access-gate/account-access-gate.js.map +1 -1
- package/dist/matter/account-entry-point/account-entry-point.js +1 -1
- package/dist/matter/account-entry-point/account-entry-point.js.map +1 -1
- package/dist/matter/account-menu/account-menu.d.ts +70 -0
- package/dist/matter/account-menu/account-menu.js +201 -9
- package/dist/matter/account-menu/account-menu.js.map +1 -1
- package/dist/matter/account-menu/sign-out-failure.js +50 -0
- package/dist/matter/account-menu/sign-out-failure.js.map +1 -0
- package/dist/matter/account-menu-identity/account-menu-identity.d.ts +21 -0
- package/dist/matter/account-menu-identity/account-menu-identity.js +88 -0
- package/dist/matter/account-menu-identity/account-menu-identity.js.map +1 -0
- package/dist/matter/billing-address/billing-address.d.ts +165 -0
- package/dist/matter/billing-address/billing-address.js +408 -0
- package/dist/matter/billing-address/billing-address.js.map +1 -0
- package/dist/matter/card-entry/card-capture.d.ts +25 -0
- package/dist/matter/card-entry/card-capture.js +25 -0
- package/dist/matter/card-entry/card-capture.js.map +1 -0
- package/dist/matter/card-entry/card-entry.d.ts +120 -0
- package/dist/matter/card-entry/card-entry.js +833 -0
- package/dist/matter/card-entry/card-entry.js.map +1 -0
- package/dist/matter/cardholder-document/cardholder-document.d.ts +45 -0
- package/dist/matter/cardholder-document/cardholder-document.js +70 -0
- package/dist/matter/cardholder-document/cardholder-document.js.map +1 -0
- package/dist/matter/cart/cart.js +1 -1
- package/dist/matter/client-preferences/client-preferences-fieldset.d.ts +77 -0
- package/dist/matter/client-preferences/client-preferences-fieldset.js +299 -0
- package/dist/matter/client-preferences/client-preferences-fieldset.js.map +1 -0
- package/dist/matter/client-preferences/client-preferences.d.ts +3 -5
- package/dist/matter/client-preferences/client-preferences.js +6 -6
- package/dist/matter/client-preferences/client-preferences.js.map +1 -1
- package/dist/matter/client-profile/client-profile.d.ts +4 -6
- package/dist/matter/client-profile/client-profile.js +9 -6
- package/dist/matter/client-profile/client-profile.js.map +1 -1
- package/dist/matter/client-profile-form/client-profile-fieldset.d.ts +119 -0
- package/dist/matter/client-profile-form/client-profile-fieldset.js +488 -0
- package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -0
- package/dist/matter/identity-edit/identity-edit.js +2 -2
- package/dist/matter/identity-edit/identity-edit.js.map +1 -1
- package/dist/matter/identity-summary/identity-summary.js +3 -2
- package/dist/matter/identity-summary/identity-summary.js.map +1 -1
- package/dist/matter/installments/installments-select.d.ts +42 -0
- package/dist/matter/installments/installments-select.js +167 -0
- package/dist/matter/installments/installments-select.js.map +1 -0
- package/dist/matter/installments/installments.d.ts +58 -0
- package/dist/matter/installments/installments.js +176 -0
- package/dist/matter/installments/installments.js.map +1 -0
- package/dist/matter/installments/use-installments-selection.d.ts +29 -0
- package/dist/matter/installments/use-installments-selection.js +95 -0
- package/dist/matter/installments/use-installments-selection.js.map +1 -0
- package/dist/matter/my-account-profile/my-account-profile.d.ts +3 -0
- package/dist/matter/my-account-profile/my-account-profile.js +6 -5
- package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +63 -0
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +305 -0
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -0
- package/dist/matter/payment/payment-card-capture.d.ts +19 -0
- package/dist/matter/payment/payment-card-capture.js +129 -0
- package/dist/matter/payment/payment-card-capture.js.map +1 -0
- package/dist/matter/payment/payment-controller.d.ts +24 -0
- package/dist/matter/payment/payment-controller.js +108 -0
- package/dist/matter/payment/payment-controller.js.map +1 -0
- package/dist/matter/payment/payment-method-badges.d.ts +57 -0
- package/dist/matter/payment/payment-method-badges.js +192 -0
- package/dist/matter/payment/payment-method-badges.js.map +1 -0
- package/dist/matter/payment/payment.d.ts +89 -0
- package/dist/matter/payment/payment.js +264 -0
- package/dist/matter/payment/payment.js.map +1 -0
- package/dist/matter/payment/use-payment-method-selection.d.ts +302 -0
- package/dist/matter/payment/use-payment-method-selection.js +458 -0
- package/dist/matter/payment/use-payment-method-selection.js.map +1 -0
- package/dist/matter/payment/use-payment-submit-gate.d.ts +111 -0
- package/dist/matter/payment/use-payment-submit-gate.js +144 -0
- package/dist/matter/payment/use-payment-submit-gate.js.map +1 -0
- package/dist/matter/place-order/place-order.d.ts +74 -0
- package/dist/matter/place-order/place-order.js +379 -0
- package/dist/matter/place-order/place-order.js.map +1 -0
- package/dist/matter/product-list/product-list.d.ts +1 -0
- package/dist/matter/product-list/product-list.js.map +1 -1
- package/dist/matter/product-shelf/product-shelf.d.ts +62 -31
- package/dist/matter/product-shelf/product-shelf.js +159 -57
- package/dist/matter/product-shelf/product-shelf.js.map +1 -1
- package/dist/matter/region/region.js +1 -1
- package/dist/matter/region/region.js.map +1 -1
- package/dist/matter/save-card/save-card.d.ts +49 -0
- package/dist/matter/save-card/save-card.js +188 -0
- package/dist/matter/save-card/save-card.js.map +1 -0
- package/dist/matter/saved-cards/saved-cards.d.ts +79 -0
- package/dist/matter/saved-cards/saved-cards.js +388 -0
- package/dist/matter/saved-cards/saved-cards.js.map +1 -0
- package/dist/matter/shipping-address/country-descriptors.js +20 -10
- package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
- package/dist/matter/shipping-address/shipping-address.d.ts +113 -174
- package/dist/matter/shipping-address/shipping-address.js +480 -791
- package/dist/matter/shipping-address/shipping-address.js.map +1 -1
- package/dist/matter/variant-selector/variant-selector.js +1 -1
- package/dist/particles/address-summary/address-summary.d.ts +24 -0
- package/dist/particles/address-summary/address-summary.js +83 -2
- package/dist/particles/address-summary/address-summary.js.map +1 -1
- package/dist/particles/alert-dialog/alert-dialog.d.ts +68 -0
- package/dist/particles/alert-dialog/alert-dialog.js +187 -0
- package/dist/particles/alert-dialog/alert-dialog.js.map +1 -0
- package/dist/particles/avatar/avatar.d.ts +17 -0
- package/dist/particles/avatar/avatar.js +65 -0
- package/dist/particles/avatar/avatar.js.map +1 -0
- package/dist/particles/checkbox/checkbox.d.ts +7 -3
- package/dist/particles/checkbox/checkbox.js +4 -1
- package/dist/particles/checkbox/checkbox.js.map +1 -1
- package/dist/particles/document-field/document-field.d.ts +48 -5
- package/dist/particles/document-field/document-field.js +189 -32
- package/dist/particles/document-field/document-field.js.map +1 -1
- package/dist/particles/field/bound-field-registry.js +52 -0
- package/dist/particles/field/bound-field-registry.js.map +1 -0
- package/dist/particles/field/field.d.ts +116 -0
- package/dist/particles/field/field.js +497 -6
- package/dist/particles/field/field.js.map +1 -1
- package/dist/particles/fieldset/fieldset.js +2 -2
- package/dist/particles/fieldset/fieldset.js.map +1 -1
- package/dist/particles/form/form.d.ts +104 -0
- package/dist/particles/form/form.js +485 -0
- package/dist/particles/form/form.js.map +1 -0
- package/dist/particles/phone-field/phone-field.d.ts +38 -10
- package/dist/particles/phone-field/phone-field.js +183 -39
- package/dist/particles/phone-field/phone-field.js.map +1 -1
- package/dist/particles/postal-code-field/postal-code-field.js +2 -2
- package/dist/particles/postal-code-field/postal-code-field.js.map +1 -1
- package/dist/particles/select/field-select.d.ts +43 -0
- package/dist/particles/select/field-select.js +150 -0
- package/dist/particles/select/field-select.js.map +1 -0
- package/dist/particles/select/select.d.ts +2 -0
- package/dist/particles/select/select.js.map +1 -1
- package/dist/particles/shared/compose-refs.js +21 -0
- package/dist/particles/shared/compose-refs.js.map +1 -0
- package/dist/schema.graphql +766 -28
- package/dist/sdk/actions/analytics-action-provider.d.ts +15 -0
- package/dist/sdk/actions/analytics-action-provider.js +19 -0
- package/dist/sdk/actions/analytics-action-provider.js.map +1 -0
- package/dist/sdk/actions/index.d.ts +3 -1
- package/dist/sdk/actions/index.js +3 -1
- package/dist/sdk/actions/payment-action-provider.d.ts +22 -0
- package/dist/sdk/actions/payment-action-provider.js +26 -0
- package/dist/sdk/actions/payment-action-provider.js.map +1 -0
- package/dist/sdk/actions/types.d.ts +6 -2
- package/dist/sdk/analytics/analytics-destination.d.ts +43 -0
- package/dist/sdk/analytics/analytics-destination.js +90 -0
- package/dist/sdk/analytics/analytics-destination.js.map +1 -0
- package/dist/sdk/analytics/use-analytics-actions.d.ts +57 -0
- package/dist/sdk/analytics/use-analytics-actions.js +109 -0
- package/dist/sdk/analytics/use-analytics-actions.js.map +1 -0
- package/dist/sdk/cart/use-cart-actions.js +10 -9
- package/dist/sdk/cart/use-cart-actions.js.map +1 -1
- package/dist/sdk/cart/use-cart-validate-on-open.js +2 -1
- package/dist/sdk/cart/use-cart-validate-on-open.js.map +1 -1
- package/dist/sdk/content/create-content-runtime.d.ts +22 -1
- package/dist/sdk/content/create-content-runtime.js +89 -1
- package/dist/sdk/content/create-content-runtime.js.map +1 -1
- package/dist/sdk/data/empty-content-value.js +16 -0
- package/dist/sdk/data/empty-content-value.js.map +1 -0
- package/dist/sdk/data/entity-resolution-context.js +31 -0
- package/dist/sdk/data/entity-resolution-context.js.map +1 -0
- package/dist/sdk/data/entity-subscriber.js +18 -8
- package/dist/sdk/data/entity-subscriber.js.map +1 -1
- package/dist/sdk/data/hot-data-provider.js +2 -1
- package/dist/sdk/data/hot-data-provider.js.map +1 -1
- package/dist/sdk/data/index.js +2 -1
- package/dist/sdk/data/page-reactive-data-root.d.ts +36 -0
- package/dist/sdk/data/page-reactive-data-root.js +4 -2
- package/dist/sdk/data/page-reactive-data-root.js.map +1 -1
- package/dist/sdk/data/reactive-data-provider.js +7 -3
- package/dist/sdk/data/reactive-data-provider.js.map +1 -1
- package/dist/sdk/data/reactive-list-item-data-provider.js +12 -4
- package/dist/sdk/data/reactive-list-item-data-provider.js.map +1 -1
- package/dist/sdk/data/use-reactive-data-settled.js +39 -0
- package/dist/sdk/data/use-reactive-data-settled.js.map +1 -0
- package/dist/sdk/data/use-reactive-entity.js +5 -1
- package/dist/sdk/data/use-reactive-entity.js.map +1 -1
- package/dist/sdk/data/variables-from-content.d.ts +43 -0
- package/dist/sdk/data/variables-from-content.js +57 -0
- package/dist/sdk/data/variables-from-content.js.map +1 -0
- package/dist/sdk/generated/fragment-types.js +2 -0
- package/dist/sdk/generated/fragment-types.js.map +1 -1
- package/dist/sdk/generated/gql.js +2 -1
- package/dist/sdk/generated/gql.js.map +1 -1
- package/dist/sdk/generated/graphql.js +85 -1
- package/dist/sdk/generated/graphql.js.map +1 -1
- package/dist/sdk/i18n/messages/en-US.js +3 -0
- package/dist/sdk/i18n/messages/en-US.json +3 -0
- package/dist/sdk/i18n/messages/en-US.json.d.ts +3 -0
- package/dist/sdk/i18n/messages/es-ES.js +3 -0
- package/dist/sdk/i18n/messages/es-ES.json +3 -0
- package/dist/sdk/i18n/messages/pt-BR.js +3 -0
- package/dist/sdk/i18n/messages/pt-BR.json +3 -0
- package/dist/sdk/identity/use-identity-actions.js +8 -6
- package/dist/sdk/identity/use-identity-actions.js.map +1 -1
- package/dist/sdk/payment/gateway-origin.js +35 -0
- package/dist/sdk/payment/gateway-origin.js.map +1 -0
- package/dist/sdk/payment/gateway.d.ts +85 -0
- package/dist/sdk/payment/gateway.js +183 -0
- package/dist/sdk/payment/gateway.js.map +1 -0
- package/dist/sdk/payment/operations.d.ts +52 -0
- package/dist/sdk/payment/operations.js +223 -0
- package/dist/sdk/payment/operations.js.map +1 -0
- package/dist/sdk/payment/security-code-mask.js +71 -0
- package/dist/sdk/payment/security-code-mask.js.map +1 -0
- package/dist/sdk/payment/submission-registry.d.ts +33 -0
- package/dist/sdk/payment/submission-registry.js +58 -0
- package/dist/sdk/payment/submission-registry.js.map +1 -0
- package/dist/sdk/payment/use-payment-actions.d.ts +78 -0
- package/dist/sdk/payment/use-payment-actions.js +276 -0
- package/dist/sdk/payment/use-payment-actions.js.map +1 -0
- package/dist/sdk/payment/use-place-order.d.ts +65 -0
- package/dist/sdk/payment/use-place-order.js +640 -0
- package/dist/sdk/payment/use-place-order.js.map +1 -0
- package/dist/sdk/region/use-region-actions.js +2 -1
- package/dist/sdk/region/use-region-actions.js.map +1 -1
- package/dist/sdk/session/read-server-session.d.ts +21 -0
- package/dist/sdk/session/read-server-session.js +61 -0
- package/dist/sdk/session/read-server-session.js.map +1 -0
- package/dist/sdk/session/use-session-actions.js +5 -4
- package/dist/sdk/session/use-session-actions.js.map +1 -1
- package/dist/sdk/session/use-session-revalidation.js +2 -1
- package/dist/sdk/session/use-session-revalidation.js.map +1 -1
- package/dist/sdk/shipping/use-shipping-actions.js +4 -3
- package/dist/sdk/shipping/use-shipping-actions.js.map +1 -1
- package/dist/utils/loggable-error-name.js +49 -0
- package/dist/utils/loggable-error-name.js.map +1 -0
- package/dist/utils/resolve-authored-copy.js +18 -0
- package/dist/utils/resolve-authored-copy.js.map +1 -0
- package/dist/utils/safe-href.d.ts +11 -0
- package/dist/utils/substitute-template.js +33 -0
- package/dist/utils/substitute-template.js.map +1 -0
- package/package.json +14 -2
- package/src/styles/tailwind.css +34 -0
- package/dist/docs/client-profile-form.md +0 -192
- package/dist/matter/client-profile-form/client-profile-form.d.ts +0 -126
- package/dist/matter/client-profile-form/client-profile-form.js +0 -662
- package/dist/matter/client-profile-form/client-profile-form.js.map +0 -1
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# SavedCards
|
|
2
|
+
|
|
3
|
+
**Category:** commerce
|
|
4
|
+
**Purpose:** Renders the checkout payment step's saved-card picker — a radio list of a shopper's stored cards (network, last four digits, label), with expired cards shown but disabled, and a CVV field that appears once a card is selected.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Visual cues (how to identify in an image)
|
|
9
|
+
|
|
10
|
+
Use these signals to detect that a SavedCards block is present. Position on the page is irrelevant for detection — it can appear anywhere in a payment/checkout step. The image is the source of truth for layout.
|
|
11
|
+
|
|
12
|
+
A SavedCards block contains any combination of:
|
|
13
|
+
|
|
14
|
+
- A **list of radio rows**, each showing a **card network name or logo** (Visa, Mastercard, …) plus a **masked number** like `•••• 4242` or `**** 4242`.
|
|
15
|
+
- A **custom label** next to a row, e.g. *"Meu cartão"* / *"Personal card"* — shopper-assigned, not always present.
|
|
16
|
+
- A row rendered **visually muted or with a "expired" tag**, still present in the list but not clickable.
|
|
17
|
+
- A **short numeric input appearing next to or below the selected row**, typically labeled *"CVV"* / *"Security code"* / *"CVC"* — this appears only once a row is checked. Its digits render **obscured** (dots), same visual family as a password field, even though it is not one under the hood (see Components below, `SavedCardCvvField`, for why).
|
|
18
|
+
- A **"pay with a new card" link or button** rendered as a sibling entry, not a row inside this list — that sibling is a different component (`CardEntry`), not part of this block.
|
|
19
|
+
|
|
20
|
+
If the image shows a **radio list of masked card numbers with network names**, use `SavedCards`. Do not use it for a single card-entry form (no radio choice) — that is `CardEntry`.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## When to use
|
|
25
|
+
|
|
26
|
+
- The checkout/payment step, for an authenticated shopper with one or more stored cards.
|
|
27
|
+
- Anywhere a shopper picks among previously saved payment methods before completing a purchase.
|
|
28
|
+
|
|
29
|
+
## When NOT to use
|
|
30
|
+
|
|
31
|
+
- A blank new-card entry form (number, expiry, holder name fields) → use `CardEntry` instead; `SavedCards` never renders those fields.
|
|
32
|
+
- A payment-method picker across networks/methods (Visa vs. Pix vs. Cash) → use `PaymentMethodList`, the sibling method-level picker under the same `PaymentSectionRoot`. `SavedCards` only distinguishes stored *cards*, not payment *methods*.
|
|
33
|
+
- An address book / saved shipping addresses list → use the equivalent shipping-address components; visually similar (a radio list of saved records) but a different domain.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Composition
|
|
38
|
+
|
|
39
|
+
`SavedCards` is the list root and must be a descendant of `PaymentSectionRoot` or `PaymentSectionController`. `SavedCardOption` is the per-card row template placed directly inside it. `SavedCardCvvField` is placed inside `SavedCardOption` so the CVV appears once that row is selected.
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
PaymentSectionRoot (or PaymentSectionController)
|
|
43
|
+
├── PaymentMethodList (sibling — network/method picker)
|
|
44
|
+
├── SavedCards
|
|
45
|
+
│ └── SavedCardOption (per-card template, repeated once per stored card)
|
|
46
|
+
│ └── SavedCardCvvField (appears only for the selected, CVV-required row)
|
|
47
|
+
└── CardEntry (sibling — "use a new card", not a child of SavedCards)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Child order reflects visual order. `SavedCardOption` and `SavedCardCvvField` are the only two valid parent/child pairs this block defines; everything else (`PaymentMethodList`, `CardEntry`) is a sibling under the same `PaymentSectionRoot`, never nested inside `SavedCards`.
|
|
51
|
+
|
|
52
|
+
**Composition rules:**
|
|
53
|
+
|
|
54
|
+
- `SavedCards` must be inside `PaymentSectionRoot` or `PaymentSectionController`. Outside either, it throws.
|
|
55
|
+
- `SavedCardOption` must be a direct child of `SavedCards`. It renders `null` when its row's data has not resolved.
|
|
56
|
+
- `SavedCardCvvField` must be inside `SavedCardOption`. Outside it, it throws. Omitting it means a shopper can select that card but never submit a payment with it — always include it.
|
|
57
|
+
- `CardEntry` ("use a new card") is a **sibling** of `SavedCards`, never a child or a row inside it — there is no "toggle" prop that switches this list into new-card mode.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Components
|
|
62
|
+
|
|
63
|
+
### SavedCards
|
|
64
|
+
|
|
65
|
+
List root. Renders a radio group of the shopper's saved cards. Renders its container even when the list is empty or still loading (a hooked, not zero-height, region). It renders nothing at all while the card payment is collapsed — the persisted selection is a method that is not a card, or one the section does not serve, and a composed `PaymentMethodList` can bring the card form back (see [[payment]]). Its rows' CVV fields unmount with it, which clears any code typed there. To reach a saved card from a method that is not a card, the shopper chooses the card option first, which brings the list back.
|
|
66
|
+
|
|
67
|
+
| Prop | Type | Default | Notes |
|
|
68
|
+
|------|------|---------|-------|
|
|
69
|
+
| `legend` | string | `"Saved cards"` | The radio group's accessible name, rendered as a visible fieldset legend above the rows (T38). An authored empty or whitespace-only string falls back to this default rather than rendering a nameless group. |
|
|
70
|
+
|
|
71
|
+
Which cards exist is always real data (`Query.payment.savedCards`) — never author them as props.
|
|
72
|
+
|
|
73
|
+
**Data:** declares `fragment SavedCardsListData on Query`. The compiler merges it into the page query — no explicit `dataSources` entry needed.
|
|
74
|
+
|
|
75
|
+
### SavedCardOption
|
|
76
|
+
|
|
77
|
+
One saved card as a radio row: network name, masked last four (`•••• 4242`), and the shopper's own label when set. Disabled (not selectable) when the card is expired — the row still renders so the shopper knows the card exists.
|
|
78
|
+
|
|
79
|
+
No props beyond standard container attributes (`className`, `children`). Must be a direct child of `SavedCards`.
|
|
80
|
+
|
|
81
|
+
**Data:** declares `fragment SavedCardOptionData on Query`, independently resolved per row (a write to one saved card only re-renders that row, not the whole list).
|
|
82
|
+
|
|
83
|
+
### SavedCardCvvField
|
|
84
|
+
|
|
85
|
+
The CVV re-entry field for its row. Renders nothing until that specific row is selected and the card requires a CVV; then renders a numeric input (digits only, capped at 4 characters) whose digits render **obscured** (dots) via an inline `-webkit-text-security: disc` style once the code is fully typed, with a helper line underneath it (`securityCodeDescription`, defaulting to "The 3-4 digit number on your card"; an empty string renders nothing). Wires the direct-to-gateway payment submission for the saved-card path the moment it is composed — the CVV is never sent to the storefront's own backend. A blank or under-three-digit code refuses before the place-order sequence opens a transaction, moving focus back to this input; the message reaches the shopper through the place-order CTA's own alert, not an inline field error here.
|
|
86
|
+
|
|
87
|
+
The mask engages on the third digit and stays on for a fourth. Three, because a saved card carries no per-network security-code length — the row's data has a display network name, not a `cvvMask` — so there is no signal here that tells a 3-digit network apart from Amex's 4, and the field's own accept-either floor is the only length available. Masking at the floor never leaves a complete code legible on either kind of card; a 4-digit code is simply already masked when its last digit arrives. Below three digits the code renders in the clear, so a shopper can read back what they just typed, and backspacing below three reveals what is left. Same rule and same shared predicate as `CardEntry`'s CVV field, which resolves its length from the detected method instead.
|
|
88
|
+
|
|
89
|
+
`type="password"` was tried first and reverted: a real Chrome browser offered to save the security code to its password manager (synced to the signed-in account) the instant the field carried that type, which PCI-DSS forbids for a value that must not be retained past authorization. The input stays `type="text"`, and no caller-passed `type` can override that. The CSS property above obscures the digits without tripping that heuristic, since it never touches `type`; a caller-passed `style` cannot remove it either — once the code is complete the mask always merges in last, so no caller can hold it off past that point. Supported in Chromium and WebKit (and, per T70's spec, Firefox 114+ — unverified on this branch); an engine without it renders the digits in the clear, same as before this mechanism existed — not a regression. The declaration is an inline style, which outranks a class-based rule from a compound swatch at normal importance — but not one that reaches for Tailwind's `!` important modifier: swatch tokens reach `className` verbatim with no validation, so a store that authors an arbitrary-property utility ending in `!` can still unmask the field. Nothing in this package closes that hole; it is accepted rather than fixed (masking spec, OQ-1).
|
|
90
|
+
|
|
91
|
+
No props beyond standard input attributes (`className`), `securityCodeLabel` (accessible name), and `securityCodeDescription` (helper text). Must be inside `SavedCardOption`.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Canonical schema example
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"saved-cards": {
|
|
100
|
+
"type": "SavedCards",
|
|
101
|
+
"children": ["saved-card-option"]
|
|
102
|
+
},
|
|
103
|
+
"saved-card-option": {
|
|
104
|
+
"type": "SavedCardOption",
|
|
105
|
+
"children": ["saved-card-cvv"]
|
|
106
|
+
},
|
|
107
|
+
"saved-card-cvv": { "type": "SavedCardCvvField" }
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### In context (inside a payment section, alongside the method picker and "use a new card")
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"payment-section": {
|
|
116
|
+
"type": "PaymentSectionRoot",
|
|
117
|
+
"children": ["payment-method-list", "saved-cards", "card-entry"]
|
|
118
|
+
},
|
|
119
|
+
"payment-method-list": { "type": "PaymentMethodList" },
|
|
120
|
+
"saved-cards": {
|
|
121
|
+
"type": "SavedCards",
|
|
122
|
+
"children": ["saved-card-option"]
|
|
123
|
+
},
|
|
124
|
+
"saved-card-option": {
|
|
125
|
+
"type": "SavedCardOption",
|
|
126
|
+
"children": ["saved-card-cvv"]
|
|
127
|
+
},
|
|
128
|
+
"saved-card-cvv": { "type": "SavedCardCvvField" },
|
|
129
|
+
"card-entry": { "type": "CardEntry" }
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Common mistakes
|
|
136
|
+
|
|
137
|
+
- **Nesting `CardEntry` ("use a new card") inside `SavedCards`.** It is a sibling under the same `PaymentSectionRoot`, never a row or a child of this list.
|
|
138
|
+
- **Inventing a `mode` or `showNewCard` prop on `SavedCards` to switch to new-card entry.** There is no such prop — "use a new card" is a separate component composed alongside this one, not a display mode of it.
|
|
139
|
+
- **Omitting `SavedCardCvvField` inside `SavedCardOption`.** Without it, a shopper can select a saved card but the place-order flow has nothing to submit with — always include it.
|
|
140
|
+
- **Placing `SavedCardOption` or `SavedCardCvvField` outside their required ancestor.** `SavedCardOption` must be inside `SavedCards`; `SavedCardCvvField` must be inside `SavedCardOption`. Only `SavedCardCvvField` throws when misplaced. A misplaced `SavedCardOption` does **not** throw — it silently renders `null` (no ancestry check of its own; it just has no resolved row data to show), so a page can ship with a silently empty saved-cards list. This is an authoring convention, not a compiler or runtime guarantee: `requiresContext` is satisfied by *any* ancestor providing that context at *any* depth, not specifically a direct parent, and there is no mechanism that forbids a given ancestor either.
|
|
141
|
+
- **Passing a `savedCards` prop, a card list, or a `cvv` value as an authored prop.** Every field here is real data from `Query.payment.savedCards` or shopper-typed local state — never a schema-bindable prop. Neither component in this block declares a `cvv`, `cardNumber`, or `bin` prop of any kind.
|
|
142
|
+
- **Using `SavedCards` for the network/method picker.** That is `PaymentMethodList` — a sibling under the same root, distinguishing payment *methods* (Visa vs. Pix), not stored *cards*.
|
|
143
|
+
- **Wrapping `SavedCards` in a page with no `PaymentSectionRoot` ancestor.** It requires the payment context; use only inside a composed payment section.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Known limitations
|
|
148
|
+
|
|
149
|
+
- **A saved card with `cvvRequired: false` can be selected but never paid with — open item, not fixed in this pass.** `SavedCardCvvField` renders nothing when `cvvRequired` is `false`, and it is the only component that registers the `'saved-card'` submission continuation. For such a card, today: the row renders selected (`data-fs-saved-card-option-selected` present, `aria-checked="true"`), but `usePaymentSubmission().resolve('saved-card')` returns `null`, so `usePlaceOrder` resolves `MISSING_PAYMENT_SUBMISSION` and Place Order fails — with no CVV field ever offered and no way for the shopper to proceed. This is data-driven (`SavedCard.cvvRequired` passes through the account's own `useCvvForAuthorization`), not an authoring mistake, and it is deliberately left open rather than guessed at: the fix depends on whether the payment gateway's direct-to-gateway POST accepts `fields.validationCode: ''` for a `useCvvForAuthorization: false` account, or whether that account type needs the legacy's separate no-CVV mutation instead — a payments question this repository cannot answer on its own. See `specs/saved-cards.md`'s Open Questions and Assumptions for the full record.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Styling
|
|
154
|
+
|
|
155
|
+
Style `SavedCards` as a vertical stack of rows, each row as a horizontal line (radio indicator, network, last four, label), and the CVV field as a small, short numeric input that appears inline with the selected row.
|
|
156
|
+
|
|
157
|
+
| Component | What you style | Plausible classes |
|
|
158
|
+
|---|---|---|
|
|
159
|
+
| `SavedCards` | Stacks the rows | `flex flex-col gap-[8px] w-full` |
|
|
160
|
+
| Fieldset (`data-fs-saved-cards-fieldset`, native `<fieldset>`) | Wraps the legend and the radio rows (T38) — gives the group its visible, accessible name | usually left unstyled; a merchant border/padding choice |
|
|
161
|
+
| Legend (`data-fs-fieldset-legend`, native `<legend>`) | The group's visible name, from `legend` | `text-[14px] font-medium text-[#1A1A1A]` |
|
|
162
|
+
| `SavedCardOption` | One row — indicator, network, last four, label in a line; muted/dashed when expired | `flex items-center gap-[8px] p-[12px] border border-[#E0E0E0] rounded-[8px] data-[fs-saved-card-option-expired]:opacity-50 data-[fs-saved-card-option-selected]:border-[#000000]` |
|
|
163
|
+
| `SavedCardCvvField` | The short CVV input | `w-[64px] text-[14px] px-[8px] py-[6px] border border-[#CCCCCC] rounded-[4px]` |
|
|
164
|
+
| CVV helper text (`data-fs-saved-card-cvv-description`) | Small muted line next to/under the CVV input | `text-[12px] text-[#666666]` |
|
|
165
|
+
| Placing (`data-fs-saved-cards-placing`) | Present on `SavedCards`' own root while an order-placement sequence is in flight (T28); the whole list — including every `SavedCardOption` row and its `SavedCardCvvField` — is `inert` and `aria-disabled` at that point, transitively, with no attribute of their own | `opacity-60 cursor-not-allowed` |
|
|
166
|
+
|
|
167
|
+
Styled example:
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"saved-cards": {
|
|
172
|
+
"type": "SavedCards",
|
|
173
|
+
"children": ["saved-card-option"],
|
|
174
|
+
"style": ["flex", "flex-col", "gap-[8px]", "w-full"]
|
|
175
|
+
},
|
|
176
|
+
"saved-card-option": {
|
|
177
|
+
"type": "SavedCardOption",
|
|
178
|
+
"children": ["saved-card-cvv"],
|
|
179
|
+
"style": [
|
|
180
|
+
"flex", "items-center", "gap-[8px]", "p-[12px]",
|
|
181
|
+
"border", "border-[#E0E0E0]", "rounded-[8px]",
|
|
182
|
+
"data-[fs-saved-card-option-expired]:opacity-50",
|
|
183
|
+
"data-[fs-saved-card-option-selected]:border-[#000000]"
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
"saved-card-cvv": {
|
|
187
|
+
"type": "SavedCardCvvField",
|
|
188
|
+
"style": ["w-[64px]", "text-[14px]", "px-[8px]", "py-[6px]", "border", "border-[#CCCCCC]", "rounded-[4px]"]
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Accessibility Contract
|
|
196
|
+
|
|
197
|
+
**What the platform promises:** `SavedCards`' radio group carries a visible, programmatic accessible
|
|
198
|
+
name (`legend`, default `"Saved cards"`) — a screen-reader user hears these rows are a choice between
|
|
199
|
+
stored cards, not payment methods. An authored empty or whitespace-only `legend` falls back to the
|
|
200
|
+
default rather than shipping a nameless group. Each row keeps its own accessible name from its network
|
|
201
|
+
and masked last four; the CVV re-entry field carries its own `securityCodeLabel` as an `aria-label`
|
|
202
|
+
and, when `securityCodeDescription` is set, an `aria-describedby` association to the helper text. The
|
|
203
|
+
group is a native `<fieldset>`/`<legend>` pair, not only `aria-label`. Keyboard: the group is one Tab
|
|
204
|
+
stop — Tab lands on the checked row, and the arrow keys move the checked row and change the selection.
|
|
205
|
+
A default `:focus-visible` outline is painted from the platform's own stylesheet.
|
|
206
|
+
|
|
207
|
+
**What the platform does not promise:** colour contrast. `SavedCards` (and every other payment
|
|
208
|
+
component) exposes `data-fs-*` hooks so a merchant can author contrast-compliant swatches, but no
|
|
209
|
+
component in this package measures or guarantees any contrast ratio — that is the merchant's theme, not
|
|
210
|
+
this platform.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Related
|
|
215
|
+
|
|
216
|
+
- [[payment]] — `PaymentSectionRoot` / `PaymentMethodList`: the required ancestor and the sibling network/method picker. `SavedCards` cannot render outside a `PaymentSectionRoot` (or `PaymentSectionController`).
|
|
217
|
+
- `CardEntry` — the "use a new card" entry point (new-card capture, a different task's deliverable). Always a sibling of `SavedCards`, never nested inside it.
|
|
218
|
+
- [[shipping-address]] — its saved-address list is the closest visual precedent (a radio list of stored records with an expired/non-selectable-style state), from a different domain (addresses, not cards).
|