@vtex/faststore 0.0.7 → 0.0.10
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 +102 -0
- package/dist/actions.json +194 -1
- package/dist/catalog.json +3449 -1612
- package/dist/cli/index.d.ts +512 -63
- package/dist/cli/index.js +2098 -686
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/server-runtime.js +44 -24
- package/dist/cli/server-runtime.js.map +1 -1
- package/dist/client.d.ts +5 -1
- package/dist/client.js +5 -1
- package/dist/components.d.ts +42 -10
- package/dist/components.js +47 -15
- package/dist/content-types.json +823 -0
- package/dist/core/dist/define-component.d.ts +12 -2
- package/dist/docs/account-access-gate.md +4 -4
- package/dist/docs/account-address-book.md +519 -0
- package/dist/docs/account-entry-point.md +5 -5
- package/dist/docs/account-menu.md +7 -7
- package/dist/docs/account-saved-cards.md +301 -0
- package/dist/docs/alert-dialog.md +2 -2
- package/dist/docs/billing-address.md +17 -9
- package/dist/docs/binding-switcher.md +154 -0
- package/dist/docs/card-entry.md +38 -7
- package/dist/docs/card-summary.md +175 -0
- package/dist/docs/cardholder-document.md +16 -14
- package/dist/docs/cart-destination.md +238 -0
- package/dist/docs/cart-item.md +22 -4
- package/dist/docs/cart-totalizer.md +1 -1
- package/dist/docs/cart.md +126 -19
- package/dist/docs/client-profile-fieldset.md +7 -5
- package/dist/docs/copy-text.md +84 -0
- package/dist/docs/document-field.md +8 -8
- package/dist/docs/footer-link-group.md +2 -2
- package/dist/docs/footer-social.md +1 -1
- package/dist/docs/free-shipping-progress.md +13 -9
- package/dist/docs/header-root.md +1 -1
- package/dist/docs/incentives.md +4 -4
- package/dist/docs/logo.md +6 -6
- package/dist/docs/my-account-profile.md +4 -4
- package/dist/docs/navigation-link-list.md +2 -2
- package/dist/docs/navigation-link.md +3 -3
- package/dist/docs/order-cancel.md +52 -0
- package/dist/docs/order-delivery-address.md +63 -0
- package/dist/docs/order-delivery-group.md +83 -0
- package/dist/docs/order-details-back.md +41 -0
- package/dist/docs/order-details-header.md +48 -0
- package/dist/docs/order-list-row.md +46 -0
- package/dist/docs/order-list-search.md +101 -0
- package/dist/docs/order-list-views.md +97 -0
- package/dist/docs/order-list.md +94 -0
- package/dist/docs/order-payment.md +94 -0
- package/dist/docs/order-placed-date.md +49 -0
- package/dist/docs/order-placed-payment-summary.md +13 -15
- package/dist/docs/order-placed.md +225 -0
- package/dist/docs/order-progress.md +88 -0
- package/dist/docs/order-status-badge.md +91 -0
- package/dist/docs/order-summary.md +53 -0
- package/dist/docs/payment-method-badges.md +16 -5
- package/dist/docs/payment-methods.md +1 -1
- package/dist/docs/place-order.md +13 -9
- package/dist/docs/product-information.md +2 -2
- package/dist/docs/product-shelf.md +7 -0
- package/dist/docs/saved-cards.md +2 -2
- package/dist/docs/select.md +22 -10
- package/dist/docs/session.md +1 -1
- package/dist/docs/shipping-address.md +1 -1
- package/dist/docs/sign-in-redirect.md +7 -7
- package/dist/docs/toast.md +35 -13
- package/dist/index.d.ts +7 -2
- package/dist/index.js +2 -1
- package/dist/internal/client.d.ts +9 -1
- package/dist/internal/client.js +10 -2
- package/dist/internal/server.d.ts +8 -2
- package/dist/internal/server.js +8 -2
- package/dist/matter/account-access-gate/account-access-gate.d.ts +2 -1
- package/dist/matter/account-access-gate/account-access-gate.js +19 -16
- package/dist/matter/account-access-gate/account-access-gate.js.map +1 -1
- package/dist/matter/account-address-book/account-address-book-delete.d.ts +60 -0
- package/dist/matter/account-address-book/account-address-book-delete.js +184 -0
- package/dist/matter/account-address-book/account-address-book-delete.js.map +1 -0
- package/dist/matter/account-address-book/account-address-book-deliverability.d.ts +19 -0
- package/dist/matter/account-address-book/account-address-book-deliverability.js +50 -0
- package/dist/matter/account-address-book/account-address-book-deliverability.js.map +1 -0
- package/dist/matter/account-address-book/account-address-book-form-parts.d.ts +42 -0
- package/dist/matter/account-address-book/account-address-book-form-parts.js +146 -0
- package/dist/matter/account-address-book/account-address-book-form-parts.js.map +1 -0
- package/dist/matter/account-address-book/account-address-book-profile-notice.d.ts +25 -0
- package/dist/matter/account-address-book/account-address-book-profile-notice.js +72 -0
- package/dist/matter/account-address-book/account-address-book-profile-notice.js.map +1 -0
- package/dist/matter/account-address-book/account-address-book.d.ts +120 -0
- package/dist/matter/account-address-book/account-address-book.js +469 -0
- package/dist/matter/account-address-book/account-address-book.js.map +1 -0
- package/dist/matter/account-address-book/account-address-country-switch.js +59 -0
- package/dist/matter/account-address-book/account-address-country-switch.js.map +1 -0
- package/dist/matter/account-address-book/account-address-country.d.ts +36 -0
- package/dist/matter/account-address-book/account-address-country.js +151 -0
- package/dist/matter/account-address-book/account-address-country.js.map +1 -0
- package/dist/matter/account-address-book/account-address-first-line.js +11 -0
- package/dist/matter/account-address-book/account-address-first-line.js.map +1 -0
- package/dist/matter/account-address-book/account-address-form-context.d.ts +55 -0
- package/dist/matter/account-address-book/account-address-form-context.js +14 -0
- package/dist/matter/account-address-book/account-address-form-context.js.map +1 -0
- package/dist/matter/account-address-book/account-address-form.d.ts +85 -0
- package/dist/matter/account-address-book/account-address-form.js +946 -0
- package/dist/matter/account-address-book/account-address-form.js.map +1 -0
- package/dist/matter/account-address-book/account-address-postal-autofill.js +189 -0
- package/dist/matter/account-address-book/account-address-postal-autofill.js.map +1 -0
- package/dist/matter/account-address-book/account-address-record.d.ts +26 -0
- package/dist/matter/account-address-book/account-address-record.js +138 -0
- package/dist/matter/account-address-book/account-address-record.js.map +1 -0
- package/dist/matter/account-entry-point/account-entry-point.js +11 -11
- package/dist/matter/account-entry-point/account-entry-point.js.map +1 -1
- package/dist/matter/account-menu/account-menu.d.ts +7 -3
- package/dist/matter/account-menu/account-menu.js +69 -28
- package/dist/matter/account-menu/account-menu.js.map +1 -1
- package/dist/matter/account-saved-cards/account-saved-cards.d.ts +383 -0
- package/dist/matter/account-saved-cards/account-saved-cards.js +956 -0
- package/dist/matter/account-saved-cards/account-saved-cards.js.map +1 -0
- package/dist/matter/billing-address/billing-address.d.ts +30 -17
- package/dist/matter/billing-address/billing-address.js +128 -33
- package/dist/matter/billing-address/billing-address.js.map +1 -1
- package/dist/matter/breadcrumb/breadcrumb.js +2 -2
- package/dist/matter/breadcrumb/breadcrumb.js.map +1 -1
- package/dist/matter/card-entry/card-capture.js +4 -3
- package/dist/matter/card-entry/card-capture.js.map +1 -1
- package/dist/matter/card-entry/card-entry.d.ts +5 -3
- package/dist/matter/card-entry/card-entry.js +77 -27
- package/dist/matter/card-entry/card-entry.js.map +1 -1
- package/dist/matter/cardholder-document/cardholder-document.d.ts +10 -9
- package/dist/matter/cardholder-document/cardholder-document.js +36 -16
- package/dist/matter/cardholder-document/cardholder-document.js.map +1 -1
- package/dist/matter/cart/cart-namespace.d.ts +5 -1
- package/dist/matter/cart/cart-namespace.js +5 -1
- package/dist/matter/cart/cart-namespace.js.map +1 -1
- package/dist/matter/cart/cart.d.ts +41 -6
- package/dist/matter/cart/cart.js +267 -54
- package/dist/matter/cart/cart.js.map +1 -1
- package/dist/matter/cart-destination/cart-destination.d.ts +222 -0
- package/dist/matter/cart-destination/cart-destination.js +613 -0
- package/dist/matter/cart-destination/cart-destination.js.map +1 -0
- package/dist/matter/cart-item/cart-item.d.ts +4 -2
- package/dist/matter/cart-item/cart-item.js +76 -17
- package/dist/matter/cart-item/cart-item.js.map +1 -1
- package/dist/matter/cart-totalizer/cart-totalizer.js +3 -2
- package/dist/matter/cart-totalizer/cart-totalizer.js.map +1 -1
- package/dist/matter/client-preferences/client-preferences-fieldset.js +1 -1
- package/dist/matter/client-profile-form/client-profile-fieldset.js +8 -5
- package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -1
- package/dist/matter/free-shipping-progress/free-shipping-progress.d.ts +6 -3
- package/dist/matter/free-shipping-progress/free-shipping-progress.js +76 -33
- package/dist/matter/free-shipping-progress/free-shipping-progress.js.map +1 -1
- package/dist/matter/identity-edit/identity-edit.js +3 -3
- package/dist/matter/identity-edit/identity-edit.js.map +1 -1
- package/dist/matter/identity-summary/identity-summary.js +2 -2
- package/dist/matter/identity-summary/identity-summary.js.map +1 -1
- package/dist/matter/my-account-profile/my-account-profile.d.ts +3 -3
- package/dist/matter/my-account-profile/my-account-profile.js +4 -4
- package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
- package/dist/matter/order-cancel/order-cancel.d.ts +110 -0
- package/dist/matter/order-cancel/order-cancel.js +344 -0
- package/dist/matter/order-cancel/order-cancel.js.map +1 -0
- package/dist/matter/order-delivery-address/order-delivery-address.d.ts +73 -0
- package/dist/matter/order-delivery-address/order-delivery-address.js +172 -0
- package/dist/matter/order-delivery-address/order-delivery-address.js.map +1 -0
- package/dist/matter/order-delivery-group/order-delivery-group.d.ts +128 -0
- package/dist/matter/order-delivery-group/order-delivery-group.js +408 -0
- package/dist/matter/order-delivery-group/order-delivery-group.js.map +1 -0
- package/dist/matter/order-details-header/order-details-header.d.ts +104 -0
- package/dist/matter/order-details-header/order-details-header.js +190 -0
- package/dist/matter/order-details-header/order-details-header.js.map +1 -0
- package/dist/matter/order-list/customer-orders-filter.d.ts +12 -0
- package/dist/matter/order-list/customer-orders-filter.js +30 -0
- package/dist/matter/order-list/customer-orders-filter.js.map +1 -0
- package/dist/matter/order-list/order-list.d.ts +121 -0
- package/dist/matter/order-list/order-list.js +395 -0
- package/dist/matter/order-list/order-list.js.map +1 -0
- package/dist/matter/order-list-row/order-list-row.d.ts +44 -0
- package/dist/matter/order-list-row/order-list-row.js +127 -0
- package/dist/matter/order-list-row/order-list-row.js.map +1 -0
- package/dist/matter/order-list-search/order-list-search.d.ts +72 -0
- package/dist/matter/order-list-search/order-list-search.js +296 -0
- package/dist/matter/order-list-search/order-list-search.js.map +1 -0
- package/dist/matter/order-list-views/order-list-views.d.ts +65 -0
- package/dist/matter/order-list-views/order-list-views.js +154 -0
- package/dist/matter/order-list-views/order-list-views.js.map +1 -0
- package/dist/matter/order-payment/order-payment.d.ts +83 -0
- package/dist/matter/order-payment/order-payment.js +258 -0
- package/dist/matter/order-payment/order-payment.js.map +1 -0
- package/dist/matter/order-placed/order-placed-deliveries.d.ts +145 -0
- package/dist/matter/order-placed/order-placed-deliveries.js +380 -0
- package/dist/matter/order-placed/order-placed-deliveries.js.map +1 -0
- package/dist/matter/order-placed/order-placed.d.ts +122 -0
- package/dist/matter/order-placed/order-placed.js +452 -0
- package/dist/matter/order-placed/order-placed.js.map +1 -0
- package/dist/matter/order-placed-date/order-placed-date.d.ts +45 -0
- package/dist/matter/order-placed-date/order-placed-date.js +92 -0
- package/dist/matter/order-placed-date/order-placed-date.js.map +1 -0
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +5 -8
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +29 -81
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -1
- package/dist/matter/order-progress/order-progress.d.ts +85 -0
- package/dist/matter/order-progress/order-progress.js +203 -0
- package/dist/matter/order-progress/order-progress.js.map +1 -0
- package/dist/matter/order-summary/order-summary.d.ts +81 -0
- package/dist/matter/order-summary/order-summary.js +192 -0
- package/dist/matter/order-summary/order-summary.js.map +1 -0
- package/dist/matter/payment/cardholder-document-rule.d.ts +35 -0
- package/dist/matter/payment/cardholder-document-rule.js +35 -0
- package/dist/matter/payment/cardholder-document-rule.js.map +1 -0
- package/dist/matter/payment/payment-card-capture.js +38 -23
- package/dist/matter/payment/payment-card-capture.js.map +1 -1
- package/dist/matter/payment/payment-controller.js +11 -0
- package/dist/matter/payment/payment-controller.js.map +1 -1
- package/dist/matter/payment/payment-method-badges.js +4 -2
- package/dist/matter/payment/payment-method-badges.js.map +1 -1
- package/dist/matter/payment/payment.js +11 -0
- package/dist/matter/payment/payment.js.map +1 -1
- package/dist/matter/payment/use-payment-method-selection.d.ts +39 -0
- package/dist/matter/payment/use-payment-method-selection.js +30 -2
- package/dist/matter/payment/use-payment-method-selection.js.map +1 -1
- package/dist/matter/payment/use-payment-submit-gate.d.ts +16 -2
- package/dist/matter/payment/use-payment-submit-gate.js +42 -14
- package/dist/matter/payment/use-payment-submit-gate.js.map +1 -1
- package/dist/matter/place-order/place-order.d.ts +12 -7
- package/dist/matter/place-order/place-order.js +126 -103
- package/dist/matter/place-order/place-order.js.map +1 -1
- package/dist/matter/pricing/pricing.js +5 -5
- package/dist/matter/pricing/pricing.js.map +1 -1
- package/dist/matter/product-shelf/product-shelf.d.ts +7 -0
- package/dist/matter/product-shelf/product-shelf.js +115 -1
- package/dist/matter/product-shelf/product-shelf.js.map +1 -1
- package/dist/matter/region/region.js +1 -1
- package/dist/matter/saved-cards/saved-cards.js +26 -15
- package/dist/matter/saved-cards/saved-cards.js.map +1 -1
- package/dist/matter/session/session.js +2 -2
- package/dist/matter/session/session.js.map +1 -1
- package/dist/matter/shipping-address/country-descriptors.d.ts +1 -0
- package/dist/matter/shipping-address/country-descriptors.js +23 -1
- package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
- package/dist/matter/shipping-address/shipping-address.js +62 -14
- package/dist/matter/shipping-address/shipping-address.js.map +1 -1
- package/dist/matter/shipping-simulator/shipping-simulator.d.ts +2 -2
- package/dist/matter/shipping-simulator/shipping-simulator.js +6 -2
- package/dist/matter/shipping-simulator/shipping-simulator.js.map +1 -1
- package/dist/matter/sign-in-redirect/sign-in-redirect.js +48 -10
- package/dist/matter/sign-in-redirect/sign-in-redirect.js.map +1 -1
- package/dist/matter/variant-selector/variant-selector.js +2 -2
- package/dist/matter/variant-selector/variant-selector.js.map +1 -1
- package/dist/particles/address-summary/address-summary.js +2 -2
- package/dist/particles/address-summary/address-summary.js.map +1 -1
- package/dist/particles/alert-dialog/alert-dialog.d.ts +5 -1
- package/dist/particles/alert-dialog/alert-dialog.js +5 -2
- package/dist/particles/alert-dialog/alert-dialog.js.map +1 -1
- package/dist/particles/binding-switcher/binding-switcher.d.ts +38 -0
- package/dist/particles/binding-switcher/binding-switcher.js +183 -0
- package/dist/particles/binding-switcher/binding-switcher.js.map +1 -0
- package/dist/particles/card-summary/card-network.d.ts +17 -0
- package/dist/particles/card-summary/card-network.js +25 -0
- package/dist/particles/card-summary/card-network.js.map +1 -0
- package/dist/particles/card-summary/card-summary.d.ts +83 -0
- package/dist/particles/card-summary/card-summary.js +188 -0
- package/dist/particles/card-summary/card-summary.js.map +1 -0
- package/dist/particles/copy-text/copy-text.d.ts +28 -0
- package/dist/particles/copy-text/copy-text.js +140 -0
- package/dist/particles/copy-text/copy-text.js.map +1 -0
- package/dist/particles/document-field/document-field.d.ts +34 -5
- package/dist/particles/document-field/document-field.js +115 -19
- package/dist/particles/document-field/document-field.js.map +1 -1
- package/dist/particles/field/field.js +1 -1
- package/dist/particles/field/field.js.map +1 -1
- package/dist/particles/footer-link-group/footer-link-group.d.ts +6 -2
- package/dist/particles/footer-link-group/footer-link-group.js +18 -7
- package/dist/particles/footer-link-group/footer-link-group.js.map +1 -1
- package/dist/particles/footer-social/footer-social.d.ts +1 -1
- package/dist/particles/footer-social/footer-social.js +1 -1
- package/dist/particles/footer-social/footer-social.js.map +1 -1
- package/dist/particles/incentives/incentives.d.ts +7 -3
- package/dist/particles/incentives/incentives.js +8 -3
- package/dist/particles/incentives/incentives.js.map +1 -1
- package/dist/particles/logo/logo.d.ts +3 -2
- package/dist/particles/logo/logo.js +20 -8
- package/dist/particles/logo/logo.js.map +1 -1
- package/dist/particles/navigation-link/navigation-link.d.ts +2 -3
- package/dist/particles/navigation-link/navigation-link.js +4 -4
- package/dist/particles/navigation-link/navigation-link.js.map +1 -1
- package/dist/particles/navigation-link-list/navigation-link-list.d.ts +6 -2
- package/dist/particles/navigation-link-list/navigation-link-list.js +18 -7
- package/dist/particles/navigation-link-list/navigation-link-list.js.map +1 -1
- package/dist/particles/order-details-back/order-details-back.d.ts +28 -0
- package/dist/particles/order-details-back/order-details-back.js +52 -0
- package/dist/particles/order-details-back/order-details-back.js.map +1 -0
- package/dist/particles/order-status-badge/order-status-badge.d.ts +19 -0
- package/dist/particles/order-status-badge/order-status-badge.js +50 -0
- package/dist/particles/order-status-badge/order-status-badge.js.map +1 -0
- package/dist/particles/payment-methods/payment-methods.d.ts +1 -1
- package/dist/particles/payment-methods/payment-methods.js +1 -1
- package/dist/particles/payment-methods/payment-methods.js.map +1 -1
- package/dist/particles/phone-field/phone-field.js +2 -2
- package/dist/particles/phone-field/phone-field.js.map +1 -1
- package/dist/particles/select/select.js +6 -6
- package/dist/particles/select/select.js.map +1 -1
- package/dist/particles/toast/toast.d.ts +21 -7
- package/dist/particles/toast/toast.js +76 -8
- package/dist/particles/toast/toast.js.map +1 -1
- package/dist/schema.graphql +1376 -126
- package/dist/sdk/actions/address-action-provider.d.ts +16 -0
- package/dist/sdk/actions/address-action-provider.js +20 -0
- package/dist/sdk/actions/address-action-provider.js.map +1 -0
- package/dist/sdk/actions/analytics-action-provider.js +1 -1
- package/dist/sdk/actions/index.d.ts +5 -1
- package/dist/sdk/actions/index.js +5 -1
- package/dist/sdk/actions/locale-action-provider.d.ts +16 -0
- package/dist/sdk/actions/locale-action-provider.js +20 -0
- package/dist/sdk/actions/locale-action-provider.js.map +1 -0
- package/dist/sdk/actions/order-action-provider.d.ts +12 -0
- package/dist/sdk/actions/order-action-provider.js +16 -0
- package/dist/sdk/actions/order-action-provider.js.map +1 -0
- package/dist/sdk/actions/saved-card-action-provider.d.ts +12 -0
- package/dist/sdk/actions/saved-card-action-provider.js +16 -0
- package/dist/sdk/actions/saved-card-action-provider.js.map +1 -0
- package/dist/sdk/actions/types.d.ts +10 -2
- package/dist/sdk/address/address-fields.js +38 -0
- package/dist/sdk/address/address-fields.js.map +1 -0
- package/dist/sdk/address/checkout-readiness.js +17 -0
- package/dist/sdk/address/checkout-readiness.js.map +1 -0
- package/dist/sdk/address/constants.js +60 -0
- package/dist/sdk/address/constants.js.map +1 -0
- package/dist/sdk/address/country-display.js +19 -0
- package/dist/sdk/address/country-display.js.map +1 -0
- package/dist/sdk/address/country-rules.js +30 -0
- package/dist/sdk/address/country-rules.js.map +1 -0
- package/dist/sdk/address/format-address.js +18 -0
- package/dist/sdk/address/format-address.js.map +1 -0
- package/dist/sdk/address/iso-countries.js +262 -0
- package/dist/sdk/address/iso-countries.js.map +1 -0
- package/dist/sdk/address/layouts.js +56 -0
- package/dist/sdk/address/layouts.js.map +1 -0
- package/dist/sdk/address/messages.js +97 -0
- package/dist/sdk/address/messages.js.map +1 -0
- package/dist/sdk/address/operations.d.ts +54 -0
- package/dist/sdk/address/operations.js +83 -0
- package/dist/sdk/address/operations.js.map +1 -0
- package/dist/sdk/address/postal-code-lookup-operations.js +23 -0
- package/dist/sdk/address/postal-code-lookup-operations.js.map +1 -0
- package/dist/sdk/address/postal-code.js +11 -0
- package/dist/sdk/address/postal-code.js.map +1 -0
- package/dist/sdk/address/schema.js +14 -0
- package/dist/sdk/address/schema.js.map +1 -0
- package/dist/sdk/address/server-fields.js +25 -0
- package/dist/sdk/address/server-fields.js.map +1 -0
- package/dist/sdk/address/switch-country.js +57 -0
- package/dist/sdk/address/switch-country.js.map +1 -0
- package/dist/sdk/address/types.d.ts +26 -0
- package/dist/sdk/address/use-address-actions.d.ts +29 -0
- package/dist/sdk/address/use-address-actions.js +247 -0
- package/dist/sdk/address/use-address-actions.js.map +1 -0
- package/dist/sdk/address/use-address-by-postal-code.js +57 -0
- package/dist/sdk/address/use-address-by-postal-code.js.map +1 -0
- package/dist/sdk/address/validate-address.js +62 -0
- package/dist/sdk/address/validate-address.js.map +1 -0
- package/dist/sdk/cache/storefront-cache.js +30 -4
- package/dist/sdk/cache/storefront-cache.js.map +1 -1
- package/dist/sdk/cart/operations.d.ts +2 -1
- package/dist/sdk/cart/operations.js +55 -1
- package/dist/sdk/cart/operations.js.map +1 -1
- package/dist/sdk/cart/optimistic.d.ts +30 -7
- package/dist/sdk/cart/optimistic.js +78 -41
- package/dist/sdk/cart/optimistic.js.map +1 -1
- package/dist/sdk/cart/use-cart-actions.d.ts +7 -0
- package/dist/sdk/cart/use-cart-actions.js +61 -15
- package/dist/sdk/cart/use-cart-actions.js.map +1 -1
- package/dist/sdk/cart/use-cart-sync-sales-channel.js +70 -0
- package/dist/sdk/cart/use-cart-sync-sales-channel.js.map +1 -0
- package/dist/sdk/client/fetch-page-data.d.ts +11 -0
- package/dist/sdk/client/fetch-page-data.js +12 -1
- package/dist/sdk/client/fetch-page-data.js.map +1 -1
- package/dist/sdk/content/create-content-runtime.js +1 -8
- package/dist/sdk/content/create-content-runtime.js.map +1 -1
- package/dist/sdk/data/failed-fields.js +23 -0
- package/dist/sdk/data/failed-fields.js.map +1 -0
- package/dist/sdk/data/index.js +2 -2
- package/dist/sdk/data/page-reactive-data-root.d.ts +45 -7
- package/dist/sdk/data/page-reactive-data-root.js +88 -12
- package/dist/sdk/data/page-reactive-data-root.js.map +1 -1
- package/dist/sdk/data/reactive-list-item-data-provider.js +2 -2
- 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 +17 -11
- package/dist/sdk/generated/gql.js.map +1 -1
- package/dist/sdk/generated/graphql.d.ts +185 -46
- package/dist/sdk/generated/graphql.js +2587 -155
- package/dist/sdk/generated/graphql.js.map +1 -1
- package/dist/sdk/i18n/messages/en-US.js +157 -1
- package/dist/sdk/i18n/messages/en-US.json +157 -1
- package/dist/sdk/i18n/messages/en-US.json.d.ts +156 -0
- package/dist/sdk/i18n/messages/es-ES.js +157 -1
- package/dist/sdk/i18n/messages/es-ES.json +157 -1
- package/dist/sdk/i18n/messages/pt-BR.js +157 -1
- package/dist/sdk/i18n/messages/pt-BR.json +157 -1
- package/dist/sdk/i18n/provider.js +1 -1
- package/dist/sdk/i18n/provider.js.map +1 -1
- package/dist/sdk/locale/binding-switch-provider.d.ts +13 -0
- package/dist/sdk/locale/binding-switch-provider.js +20 -0
- package/dist/sdk/locale/binding-switch-provider.js.map +1 -0
- package/dist/sdk/locale/use-locale-actions.d.ts +16 -0
- package/dist/sdk/locale/use-locale-actions.js +70 -0
- package/dist/sdk/locale/use-locale-actions.js.map +1 -0
- package/dist/sdk/navigation/binding-switch.d.ts +39 -0
- package/dist/sdk/navigation/binding-switch.js +129 -0
- package/dist/sdk/navigation/binding-switch.js.map +1 -0
- package/dist/sdk/navigation/current-page.js +30 -0
- package/dist/sdk/navigation/current-page.js.map +1 -0
- package/dist/sdk/navigation/decode-route-params.d.ts +11 -0
- package/dist/sdk/navigation/decode-route-params.js +32 -0
- package/dist/sdk/navigation/decode-route-params.js.map +1 -0
- package/dist/sdk/navigation/not-found-log.d.ts +28 -0
- package/dist/sdk/navigation/not-found-log.js +133 -0
- package/dist/sdk/navigation/not-found-log.js.map +1 -0
- package/dist/sdk/navigation/path.js +25 -0
- package/dist/sdk/navigation/path.js.map +1 -0
- package/dist/sdk/navigation/redirect.d.ts +11 -0
- package/dist/sdk/navigation/redirect.js +22 -0
- package/dist/sdk/navigation/redirect.js.map +1 -0
- package/dist/sdk/navigation/report.js +70 -0
- package/dist/sdk/navigation/report.js.map +1 -0
- package/dist/sdk/navigation/resolve-storefront-href.d.ts +12 -0
- package/dist/sdk/navigation/resolve-storefront-href.js +214 -0
- package/dist/sdk/navigation/resolve-storefront-href.js.map +1 -0
- package/dist/sdk/navigation/route-identity-provider.d.ts +11 -0
- package/dist/sdk/navigation/route-identity-provider.js +20 -0
- package/dist/sdk/navigation/route-identity-provider.js.map +1 -0
- package/dist/sdk/navigation/route-map-provider.d.ts +19 -0
- package/dist/sdk/navigation/route-map-provider.js +29 -0
- package/dist/sdk/navigation/route-map-provider.js.map +1 -0
- package/dist/sdk/navigation/storefront-link.d.ts +16 -0
- package/dist/sdk/navigation/storefront-link.js +66 -0
- package/dist/sdk/navigation/storefront-link.js.map +1 -0
- package/dist/sdk/navigation/types.d.ts +45 -0
- package/dist/sdk/navigation/use-storefront-navigation.d.ts +26 -0
- package/dist/sdk/navigation/use-storefront-navigation.js +73 -0
- package/dist/sdk/navigation/use-storefront-navigation.js.map +1 -0
- package/dist/sdk/navigation/use-storefront-route.d.ts +26 -0
- package/dist/sdk/navigation/use-storefront-route.js +87 -0
- package/dist/sdk/navigation/use-storefront-route.js.map +1 -0
- package/dist/sdk/navigation/use-storefront-search-params.d.ts +11 -0
- package/dist/sdk/navigation/use-storefront-search-params.js +16 -0
- package/dist/sdk/navigation/use-storefront-search-params.js.map +1 -0
- package/dist/sdk/orders/completion-badge.d.ts +8 -0
- package/dist/sdk/orders/completion-badge.js +47 -0
- package/dist/sdk/orders/completion-badge.js.map +1 -0
- package/dist/sdk/orders/order-operations.d.ts +19 -0
- package/dist/sdk/orders/order-operations.js +21 -0
- package/dist/sdk/orders/order-operations.js.map +1 -0
- package/dist/sdk/orders/use-order-actions.d.ts +23 -0
- package/dist/sdk/orders/use-order-actions.js +62 -0
- package/dist/sdk/orders/use-order-actions.js.map +1 -0
- package/dist/sdk/payment/gateway-origin.js +26 -13
- package/dist/sdk/payment/gateway-origin.js.map +1 -1
- package/dist/sdk/payment/gateway.d.ts +14 -2
- package/dist/sdk/payment/gateway.js +32 -14
- package/dist/sdk/payment/gateway.js.map +1 -1
- package/dist/sdk/payment/operations.js +11 -0
- package/dist/sdk/payment/operations.js.map +1 -1
- package/dist/sdk/payment/submission-registry.d.ts +2 -1
- package/dist/sdk/payment/submission-registry.js +12 -8
- package/dist/sdk/payment/submission-registry.js.map +1 -1
- package/dist/sdk/payment/use-payment-actions.d.ts +5 -3
- package/dist/sdk/payment/use-payment-actions.js +5 -2
- package/dist/sdk/payment/use-payment-actions.js.map +1 -1
- package/dist/sdk/payment/use-place-order.d.ts +6 -3
- package/dist/sdk/payment/use-place-order.js +333 -143
- package/dist/sdk/payment/use-place-order.js.map +1 -1
- package/dist/sdk/saved-cards/operations.d.ts +16 -0
- package/dist/sdk/saved-cards/operations.js +41 -0
- package/dist/sdk/saved-cards/operations.js.map +1 -0
- package/dist/sdk/saved-cards/use-saved-card-actions.d.ts +26 -0
- package/dist/sdk/saved-cards/use-saved-card-actions.js +86 -0
- package/dist/sdk/saved-cards/use-saved-card-actions.js.map +1 -0
- package/dist/sdk/seo/page-alternates.d.ts +57 -0
- package/dist/sdk/seo/page-alternates.js +127 -0
- package/dist/sdk/seo/page-alternates.js.map +1 -0
- package/dist/sdk/shipping/shipping-operations.d.ts +1 -1
- package/dist/sdk/shipping/shipping-operations.js +13 -0
- package/dist/sdk/shipping/shipping-operations.js.map +1 -1
- package/dist/sdk/state/cart.d.ts +9 -2
- package/dist/sdk/state/cart.js +9 -2
- package/dist/sdk/state/cart.js.map +1 -1
- package/dist/utils/own-value.js +19 -0
- package/dist/utils/own-value.js.map +1 -0
- package/dist/utils/safe-href.d.ts +4 -4
- package/dist/utils/safe-href.js +31 -22
- package/dist/utils/safe-href.js.map +1 -1
- package/package.json +5 -1
- package/skills/storefront-asset/SKILL.md +111 -0
- package/skills/storefront-asset/references/api-side.md +153 -0
- package/skills/storefront-asset/references/findings.md +40 -0
- package/skills/storefront-asset/references/ui-side.md +94 -0
- package/src/styles/tailwind.css +28 -2
|
@@ -53,14 +53,14 @@ Content model (`account-entry-point`) fields, edited in the CMS:
|
|
|
53
53
|
|-------|------|----------|-------|
|
|
54
54
|
| `signedOutLabel` | string | no | Cleared or absent keeps the authored prop |
|
|
55
55
|
| `signedInLabel` | string | no | Same |
|
|
56
|
-
| `icon` | string | no | Same, but the name must be listed in `
|
|
56
|
+
| `icon` | string | no | Same, but the name must be listed in `foundation.json → icons.include` — see below |
|
|
57
57
|
| `loadingLabel` | string | no | Same |
|
|
58
58
|
|
|
59
|
-
**An icon chosen in the CMS has to be declared in the store first.** Icon references resolve at compile time: the compiler collects every value of every `icon`-typed prop across the page and layout schemas and emits one sprite per route. A name that arrives at runtime from a CMS entry is never seen by that pass, so it renders a `<use>` pointing at a symbol the route's sprite does not carry — no build error, no runtime error, no glyph. For a merchant to be able to pick the icon in the Admin, the store must list the candidates under `
|
|
59
|
+
**An icon chosen in the CMS has to be declared in the store first.** Icon references resolve at compile time: the compiler collects every value of every `icon`-typed prop across the page and layout schemas and emits one sprite per route. A name that arrives at runtime from a CMS entry is never seen by that pass, so it renders a `<use>` pointing at a symbol the route's sprite does not carry — no build error, no runtime error, no glyph. For a merchant to be able to pick the icon in the Admin, the store must list the candidates under `foundation.json → icons.include`, which puts them in the root sprite regardless of what any schema references.
|
|
60
60
|
|
|
61
61
|
**One element, two links, chosen by the session.** `loggedIn` renders the signed-in link; `anonymous` and `identified` both render the signed-out one, because an identified but unauthenticated shopper cannot reach their account yet. There is no prop that selects between them — the merchant authors one element and the session decides.
|
|
62
62
|
|
|
63
|
-
**The destinations are not authored.** Sign in goes to
|
|
63
|
+
**The destinations are not authored.** Sign in goes to the sign-in page `{ standard: 'sign-in' }`, carrying a `returnUrl` with the current logical path so the shopper returns where they started; the sign-in page prefixes it on the way back. The account link goes to the account page `{ standard: 'account' }`. The route map resolves both for the current binding, for example `/pt-BR/login` and `/pt-BR/pvt/account`. Both are fixed constants, so no schema edit and no CMS entry can misroute the auth flow. The sign-in destination comes from the shared `signInTarget` (`utils/safe-href.ts`) rather than from this component, so any other surface that has to send a signed-out shopper to sign in reaches the same place by the same rule. The `returnUrl` value is constrained to a same-origin relative path, which keeps the sign-in route from being turned into an open redirect; a path the narrowing refuses drops the parameter, and so does a router reporting no path, leaving a bare sign-in page rather than a broken link. That is the sender's half of the guarantee. Nothing stops a hand-crafted link, so the receiving half — narrowing the parameter through `resolveSiteRelativeHref` on arrival — belongs to the route that serves the sign-in page. The signed-out link also opts out of Next.js prefetching: a header control is always in the viewport, and the destination is an auth route rather than a page, so it can set a cookie or redirect and the default would fire that request on every page view.
|
|
64
64
|
|
|
65
65
|
**`returnUrl` carries the path only — not the query string, not the hash.** A shopper signing in from `/s?q=tenis` or a filtered listing returns to the bare path. This is a deliberate narrowing rather than a limitation of the router: recovering the query would mean reading it through `useSearchParams()` and wrapping the header in a Suspense boundary, and the hash never leaves the browser at all. Search and filter state is cheap to re-apply and the sign-in round trip is rare, so the entry point keeps the simpler shape. Revisit it if merchants report losing filters across sign-in.
|
|
66
66
|
|
|
@@ -98,7 +98,7 @@ Bound to a CMS entry, the element authors no content props at all — the entry
|
|
|
98
98
|
- **Placing it outside a `SessionRoot`.** The compiler rejects it, and the runtime throws.
|
|
99
99
|
- **Authoring `$content` in the schema.** `$content` is compiler-injected from the page's or layout's content entry; naming it in `props` fails the build.
|
|
100
100
|
- **Expecting a default glyph.** The base icon dialect has no account icon, so a store that authors no `icon` gets a label-only link. Author one from the store's own collection.
|
|
101
|
-
- **Letting a merchant pick the icon without declaring it.** An `icon` supplied by a CMS entry renders nothing at all unless the store lists the name in `
|
|
101
|
+
- **Letting a merchant pick the icon without declaring it.** An `icon` supplied by a CMS entry renders nothing at all unless the store lists the name in `foundation.json → icons.include`: the compiler builds each route's sprite from the schemas, and a runtime value never reaches that pass.
|
|
102
102
|
- **Hiding the announced text with `display:none`.** That removes it from the accessibility tree and defeats the announcement; use a clipping technique instead.
|
|
103
103
|
|
|
104
104
|
---
|
|
@@ -123,7 +123,7 @@ Bound to a CMS entry, the element authors no content props at all — the entry
|
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
The glyph carries a fixed intrinsic size, so reach it through the root when the header needs another.
|
|
126
|
-
Author that once per store as the `AccountEntryPoint` base swatch in `
|
|
126
|
+
Author that once per store as the `AccountEntryPoint` base swatch in `foundation.json → styles`:
|
|
127
127
|
|
|
128
128
|
```json
|
|
129
129
|
{
|
|
@@ -35,7 +35,7 @@ AccountMenuRoot
|
|
|
35
35
|
├── AccountMenuList
|
|
36
36
|
├── AccountMenuSignOut ← beside the list, outside the landmark
|
|
37
37
|
└── Slot ← the section's own page
|
|
38
|
-
└── AccountMenuIndexRedirect ← on
|
|
38
|
+
└── AccountMenuIndexRedirect ← on the account page only
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
**The Root wraps the section's content; the landmark does not.** The Root's context has to reach consumers that live inside the slot — the account root's redirect, the sibling breadcrumb — and a context reaches only its descendants. A `<nav>` stretched that far would put every section's content inside a navigation region: a screen reader would announce the page as navigation and "skip to navigation" would skip nothing. So the Root wraps, and the `<nav>` stays around the items alone.
|
|
@@ -57,12 +57,12 @@ Content model (`account-menu`) fields, edited in the CMS:
|
|
|
57
57
|
|-------|------|----------|-------|
|
|
58
58
|
| `items` | array | no | One entry per section, in the order they should appear |
|
|
59
59
|
| `items[].label` | string | yes | The section's name |
|
|
60
|
-
| `items[].href` | string | yes | Its destination; `http(s)`, `mailto:`, `tel:`, or a site-relative path |
|
|
60
|
+
| `items[].href` | page reference or string | yes | Its destination; a page reference such as `{ "page": "orders" }`, or `http(s)`, `mailto:`, `tel:`, or a logical site-relative path |
|
|
61
61
|
| `items[].external` | boolean | no | The entry leaves the account; it is never marked current |
|
|
62
62
|
|
|
63
|
-
**The list comes from three channels, in order: a published entry, the authored `items` prop, then the library's five.** The default is Profile, Orders, Address, Payments, and Security,
|
|
63
|
+
**The list comes from three channels, in order: a published entry, the authored `items` prop, then the library's five.** The default is Profile, Orders, Address, Payments, and Security, the page references `{ standard: 'profile' }` and its siblings — the set the PRD names. The route map resolves each one for the current binding, for example `/pt-BR/pvt/profile`. Presence decides, not emptiness: a channel supplying an empty list resolves to empty rather than falling through, because a merchant who cleared the list cleared it and the defaults must not override a deliberate publication.
|
|
64
64
|
|
|
65
|
-
**The current section is derived, never authored.** The component reads the current path and matches each entry's destination on segment boundaries. At most one entry is current: among the matches, the one with the longest destination wins, which makes an exact match beat every ancestor without a second rule. `/pvt/order` is not a match for `/pvt/orders` — a prefix that does not land on a segment boundary is not a match at all.
|
|
65
|
+
**The current section is derived, never authored.** The component reads the current logical path, without the binding's base path, and matches each entry's logical destination on segment boundaries. At most one entry is current: among the matches, the one with the longest destination wins, which makes an exact match beat every ancestor without a second rule. `/pvt/order` is not a match for `/pvt/orders` — a prefix that does not land on a segment boundary is not a match at all.
|
|
66
66
|
|
|
67
67
|
**An exact match announces `aria-current="page"`; an ancestor match announces `aria-current="true"`.** Inside `/pvt/orders/123`, Orders is the current item of its set but not the current page. That claim belongs to the breadcrumb's deep entry, and two surfaces announcing "current page" for two different things is worse than the menu claiming only its set.
|
|
68
68
|
|
|
@@ -161,7 +161,7 @@ Returns `{ items, current }` — the resolved sections and the current one as `{
|
|
|
161
161
|
|
|
162
162
|
Bound to a CMS entry, the Root authors no `items` at all — the entry supplies the whole list.
|
|
163
163
|
|
|
164
|
-
No part carries a `style` reference: each takes its type's `base` swatch from `
|
|
164
|
+
No part carries a `style` reference: each takes its type's `base` swatch from `foundation.json → styles` on its own. Reference a named swatch only when the store defines one, since a `$name` the store does not define expands to nothing, without an error.
|
|
165
165
|
|
|
166
166
|
The account root's page, whose only content is the redirect:
|
|
167
167
|
|
|
@@ -181,7 +181,7 @@ The account root's page, whose only content is the redirect:
|
|
|
181
181
|
- **Leaving `label` unauthored.** The default is `Account`; a store with its own wording should say so, because a landmark's name is how a screen-reader user tells it from every other one.
|
|
182
182
|
- **Styling the current item and nothing else.** The hook exists beside `aria-current`, never instead of it. Removing the programmatic signal leaves position conveyed by appearance alone.
|
|
183
183
|
- **Publishing an empty list and expecting the defaults.** Empty is a configuration, not an absence. The account's root then has no section to open, and says so.
|
|
184
|
-
- **Placing `AccountMenuIndexRedirect` on a section's page.** It navigates away from whatever page hosts it; it belongs on
|
|
184
|
+
- **Placing `AccountMenuIndexRedirect` on a section's page.** It navigates away from whatever page hosts it; it belongs on the account page alone.
|
|
185
185
|
- **Putting an external entry first and expecting the root to follow it.** It is skipped, as is an absolute destination left unflagged; the root opens the first section that stays in the account.
|
|
186
186
|
- **Placing `AccountMenuSignOut` outside the gate.** Nothing stands down while the logout runs, so the page shows the signed-out session for the moment before it leaves. Compose it under the `my-account` layout's gate.
|
|
187
187
|
- **Signing out with the router, or adding `pageshow` handling to the control.** The document load is what keeps the account off the back control, and the gate owns the back-forward cache.
|
|
@@ -207,7 +207,7 @@ The account root's page, whose only content is the redirect:
|
|
|
207
207
|
| Sign-out button | `data-fs-account-menu-sign-out-button` is the `<button>`; style `:disabled` for the wait | `text-left text-sm underline` |
|
|
208
208
|
| Sign-out failure | `data-fs-account-menu-sign-out-error` is the alert | `text-sm text-red-600` |
|
|
209
209
|
|
|
210
|
-
The vertical-to-horizontal switch and the scroll affordance are one DOM styled two ways, in CSS alone. A store authors them as `AccountMenuList.base` in `
|
|
210
|
+
The vertical-to-horizontal switch and the scroll affordance are one DOM styled two ways, in CSS alone. A store authors them as `AccountMenuList.base` in `foundation.json → styles`, abridged here:
|
|
211
211
|
|
|
212
212
|
```json
|
|
213
213
|
{
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# Account Saved Cards
|
|
2
|
+
|
|
3
|
+
**Category:** identity
|
|
4
|
+
**Purpose:** The signed-in shopper's saved cards in their account: a list of card summaries, or a statement that there are none, with loading and failure states, and a confirmed removal for each card. Needs no cart.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Visual cues (how to identify in an image)
|
|
9
|
+
|
|
10
|
+
- A section heading such as "Saved cards", "Payment methods", or "My cards" inside an account page.
|
|
11
|
+
- A vertical list of rows, each a card-network logo, a network name, and `•••• 1234`, with a line such as "Expires 05/28" under it.
|
|
12
|
+
- A dimmed row reading "Expired 05/24" or "This card can't be used".
|
|
13
|
+
- A "Remove" link or button in each row, opening a confirmation such as "Remove this card?" with Cancel and "Remove card".
|
|
14
|
+
- Or a single sentence such as "You have no saved cards yet." where the list would be.
|
|
15
|
+
- Usually beside the account's side navigation, never inside a checkout step.
|
|
16
|
+
|
|
17
|
+
The image is the source of truth for layout.
|
|
18
|
+
|
|
19
|
+
## When to use
|
|
20
|
+
|
|
21
|
+
- Showing the shopper the cards saved to their account, outside any purchase: the account's Payments page, or a block inside another account page.
|
|
22
|
+
|
|
23
|
+
## When NOT to use
|
|
24
|
+
|
|
25
|
+
- Picking a saved card to pay with during checkout → [[saved-cards]] (`SavedCards`, cart-scoped, with CVV entry).
|
|
26
|
+
- Describing one card on its own → [[card-summary]].
|
|
27
|
+
- The store's accepted payment methods as a strip of logos → [[payment-methods]].
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Composition
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
AccountSavedCardsRoot ← requires 'session'; provides 'account-saved-cards'; declares savedCard.remove
|
|
35
|
+
├── AccountSavedCardsHeading
|
|
36
|
+
├── AccountSavedCardsRemoveFeedback
|
|
37
|
+
├── AccountSavedCardsLoading
|
|
38
|
+
├── AccountSavedCardsError
|
|
39
|
+
├── AccountSavedCardsEmpty
|
|
40
|
+
└── AccountSavedCardsList ← provides 'account-saved-card'
|
|
41
|
+
└── AccountSavedCardItem ← one row per card; provides 'card-summary', 'account-saved-card-data'
|
|
42
|
+
├── CardSummary (default when the row has no children)
|
|
43
|
+
├── AccountSavedCardExpiry (default when the row has no children)
|
|
44
|
+
└── AccountSavedCardRemove (default when the row has no children) ← provides 'account-saved-card-remove'
|
|
45
|
+
└── AlertDialogRoot
|
|
46
|
+
├── AccountSavedCardRemoveTrigger
|
|
47
|
+
└── AlertDialogPortal > AlertDialogBackdrop + AlertDialogViewport > AlertDialogPopup
|
|
48
|
+
├── AccountSavedCardRemoveTitle
|
|
49
|
+
├── AccountSavedCardRemoveDescription
|
|
50
|
+
├── AccountSavedCardRemoveCancel
|
|
51
|
+
└── AccountSavedCardRemoveConfirm
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`AccountSavedCardRemove` with no children renders the prompt shown under it.
|
|
55
|
+
|
|
56
|
+
The Root renders nothing unless the session is `loggedIn`, and no chrome: no navigation, no page title, no landmark. It derives one state and exposes it on `data-fs-account-saved-cards-state`:
|
|
57
|
+
|
|
58
|
+
| State | When | Renders |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| `loading` | No cards yet and the read is in flight | `AccountSavedCardsLoading` |
|
|
61
|
+
| `error` | No cards and the read failed | `AccountSavedCardsError` |
|
|
62
|
+
| `empty` | The read resolved with no card | `AccountSavedCardsEmpty` |
|
|
63
|
+
| `ready` | The read resolved with cards | `AccountSavedCardsList` |
|
|
64
|
+
| `idle` | No cards and nothing in flight | Nothing but the heading |
|
|
65
|
+
|
|
66
|
+
The heading and the removal feedback render in every state. Every part except the Item must be inside the Root; the Item must be inside the List; the CardSummary parts, `AccountSavedCardExpiry`, and `AccountSavedCardRemove` inside the Item; and the five prompt parts inside `AccountSavedCardRemove`. A part outside its provider fails the build with a `ContextConstraintError`.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Components
|
|
71
|
+
|
|
72
|
+
### AccountSavedCardsRoot
|
|
73
|
+
|
|
74
|
+
Reads the card ids (`customerSavedCards`, reactive) and publishes the section state. No schema props.
|
|
75
|
+
|
|
76
|
+
It also holds the section's removal: which card is being removed (one at a time) and how the last removal ended. It declares `actions: { savedCard: ['remove'] }`, so every remove control inside reaches the action, including the one a bare Item renders.
|
|
77
|
+
|
|
78
|
+
### AccountSavedCardsHeading
|
|
79
|
+
|
|
80
|
+
| Prop | Type | Default | Notes |
|
|
81
|
+
|------|------|---------|-------|
|
|
82
|
+
| `as` | `'h2' \| 'h3' \| 'h4' \| 'h5' \| 'h6'` | `h2` | No `h1`: the page title belongs to the page shell. |
|
|
83
|
+
|
|
84
|
+
### AccountSavedCardsLoading
|
|
85
|
+
|
|
86
|
+
| Prop | Type | Default | Notes |
|
|
87
|
+
|------|------|---------|-------|
|
|
88
|
+
| `skeletonCount` | number | `2` | Placeholder rows (`data-fs-account-saved-cards-loading-row`), hidden from assistive technology. |
|
|
89
|
+
|
|
90
|
+
A polite live region (`data-fs-account-saved-cards-loading-announcement`) stays mounted and announces the wait.
|
|
91
|
+
|
|
92
|
+
### AccountSavedCardsError
|
|
93
|
+
|
|
94
|
+
An alert. An expired session (`UNAUTHORIZED`) says so and links to sign-in (`data-fs-account-saved-cards-sign-in`), returning the shopper to the current page; any other failure says the cards could not be loaded. `data-fs-account-saved-cards-error-code` is `unauthorized` or `failed`. The server's message never renders. Children replace the message for every failure and drop the link.
|
|
95
|
+
|
|
96
|
+
### AccountSavedCardsEmpty
|
|
97
|
+
|
|
98
|
+
The statement that no card is saved. Renders only once the read resolved with none.
|
|
99
|
+
|
|
100
|
+
### AccountSavedCardsList
|
|
101
|
+
|
|
102
|
+
A `<ul>` repeating its child once per card.
|
|
103
|
+
|
|
104
|
+
### AccountSavedCardItem
|
|
105
|
+
|
|
106
|
+
A `<li>` that provides its card to the CardSummary parts, `AccountSavedCardExpiry`, and `AccountSavedCardRemove`. With no children it renders `CardSummary`'s default (mark, network name, mask, last four digits), then `AccountSavedCardExpiry`, then `AccountSavedCardRemove`. It shows no label: the account's read does not return one.
|
|
107
|
+
|
|
108
|
+
An expired card's row carries `data-fs-account-saved-card-expired`, and an unusable one's `data-fs-account-saved-card-unusable`, so a swatch can dim it. A working card's row carries neither. While its card is being removed, the row carries `data-fs-account-saved-card-removing`. Compose the three parts as children to rearrange the row or to reword it from the CMS. Leave `AccountSavedCardRemove` out only for a read-only list.
|
|
109
|
+
|
|
110
|
+
### AccountSavedCardExpiry
|
|
111
|
+
|
|
112
|
+
The line that says when the card expires, from the API's `status` and `expiry`. No schema props and no children.
|
|
113
|
+
|
|
114
|
+
| Card | Line | `data-fs-account-saved-card-expiry-status` |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| Working, with a date | "Expires 05/28" | `usable` |
|
|
117
|
+
| Expired, with a date | "Expired 05/24" | `expired` |
|
|
118
|
+
| Expired, no date | "Expired" | `expired` |
|
|
119
|
+
| Unusable (any other status) | "This card can't be used", never a date | `unusable` |
|
|
120
|
+
| Working, no date | Nothing | — |
|
|
121
|
+
|
|
122
|
+
The label is in `data-fs-account-saved-card-expiry-label`, the `MM/YY` date in `data-fs-account-saved-card-expiry-date` (a `<time>`). The short date is hidden from assistive technology; a visually hidden span reads the month and year in full ("May 2028") in the store's locale. A month outside 1–12 or a year outside four digits counts as no date.
|
|
123
|
+
|
|
124
|
+
### AccountSavedCardRemove
|
|
125
|
+
|
|
126
|
+
The controller for one row's removal prompt. It owns the prompt's open state and passes it to its single `AlertDialogRoot` child; the schema never sets `open`. With no children it renders the default prompt. No schema props.
|
|
127
|
+
|
|
128
|
+
Opening the prompt dispatches nothing. Confirm dispatches `savedCard.remove` with the row's card id. The prompt then stays open until the server answers, and Escape and Cancel cannot close it meanwhile. On success the row leaves the list, and the prompt goes with it. On failure the prompt closes, focus returns to the trigger, and the row stays. An expired or unusable card is removed like any other.
|
|
129
|
+
|
|
130
|
+
### AccountSavedCardRemoveTrigger
|
|
131
|
+
|
|
132
|
+
The row's control that opens the prompt. Its visible text is short ("Remove"); a visually hidden span adds the card ("Visa ending in 1234"), so each trigger has its own accessible name. Disabled while any removal in the section is pending.
|
|
133
|
+
|
|
134
|
+
### AccountSavedCardRemoveTitle, AccountSavedCardRemoveDescription
|
|
135
|
+
|
|
136
|
+
The prompt's title and accessible description. With no children, the description renders the card's `CardSummary` before its text, so the prompt names the card it removes.
|
|
137
|
+
|
|
138
|
+
### AccountSavedCardRemoveCancel
|
|
139
|
+
|
|
140
|
+
Closes the prompt and keeps the card. Opened with a mouse or the keyboard, the prompt focuses it first, so the safe action is the default; opened by touch, the popup takes focus itself. Disabled while the removal is pending.
|
|
141
|
+
|
|
142
|
+
### AccountSavedCardRemoveConfirm
|
|
143
|
+
|
|
144
|
+
Removes the card. While the removal is pending it carries `aria-disabled="true"`, `aria-busy="true"`, and `data-fs-account-saved-card-remove-confirm-pending`, and shows its pending text ("Removing…"). It stays focusable, so focus does not leave the prompt.
|
|
145
|
+
|
|
146
|
+
### AccountSavedCardsRemoveFeedback
|
|
147
|
+
|
|
148
|
+
Tells the shopper how the last removal ended. Place it once in the Root, outside the list, because a removed card's row unmounts. No schema props and no children.
|
|
149
|
+
|
|
150
|
+
| Outcome | Renders | `data-fs-account-saved-cards-remove-feedback-outcome` |
|
|
151
|
+
|---|---|---|
|
|
152
|
+
| Removed | "The card was removed." in a polite status region, which takes focus | `removed` |
|
|
153
|
+
| Session expired (`UNAUTHORIZED`) | An alert saying so, with a sign-in link (`data-fs-account-saved-cards-remove-feedback-sign-in`) that returns to the page | `unauthorized` |
|
|
154
|
+
| Any other failure | An alert: "We couldn't remove the card. Please try again." | `failed` |
|
|
155
|
+
| None yet, or a new removal started | Nothing | — |
|
|
156
|
+
|
|
157
|
+
The status region stays mounted so screen readers announce it. No message disappears on its own, and the server's message never renders.
|
|
158
|
+
|
|
159
|
+
## Text
|
|
160
|
+
|
|
161
|
+
Every text resolves in this order: `children`, then the part's CMS entry (`$content`, a blank field counts as unset), then the catalog message in the store's locale.
|
|
162
|
+
|
|
163
|
+
| Part | CMS fields | Catalog ids |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| `AccountSavedCardsHeading` | `text` | `fs/saved-cards.heading` |
|
|
166
|
+
| `AccountSavedCardsEmpty` | `text` | `fs/saved-cards.empty` |
|
|
167
|
+
| `AccountSavedCardsLoading` | `text` | `fs/saved-cards.loading` |
|
|
168
|
+
| `AccountSavedCardsError` | `text`, `sessionExpiredText`, `signInLabel` | `fs/saved-cards.load-failed`, `fs/saved-cards.session-expired`, `fs/saved-cards.sign-in` |
|
|
169
|
+
| `AccountSavedCardExpiry` | `expiresLabel`, `expiredLabel`, `expiredText`, `unusableText` | `fs/saved-cards.expires`, `fs/saved-cards.expired`, `fs/saved-cards.expired-no-date`, `fs/saved-cards.unusable` |
|
|
170
|
+
| `AccountSavedCardRemoveTrigger` | `text` | `fs/saved-cards.remove.trigger` |
|
|
171
|
+
| `AccountSavedCardRemoveTitle` | `text` | `fs/saved-cards.remove.title` |
|
|
172
|
+
| `AccountSavedCardRemoveDescription` | `text` | `fs/saved-cards.remove.description` |
|
|
173
|
+
| `AccountSavedCardRemoveCancel` | `text` | `fs/saved-cards.remove.cancel` |
|
|
174
|
+
| `AccountSavedCardRemoveConfirm` | `text`, `pendingText` | `fs/saved-cards.remove.confirm`, `fs/saved-cards.remove.pending` |
|
|
175
|
+
| `AccountSavedCardsRemoveFeedback` | `successText`, `failureText`, `sessionExpiredText`, `signInLabel` | `fs/saved-cards.remove.success`, `fs/saved-cards.remove.failed`, `fs/saved-cards.session-expired`, `fs/saved-cards.sign-in` |
|
|
176
|
+
|
|
177
|
+
`AccountSavedCardExpiry` and `AccountSavedCardsRemoveFeedback` take no children. `expiresLabel` and `expiredLabel` precede the date, which the component always places; `expiredText` and `unusableText` stand alone. The trigger's hidden card name follows its text whatever the source. Children on the Confirm replace only its idle label. Only a part placed in the schema reads its CMS entry: the expiry line and the prompt an Item renders by default always show the catalog wording.
|
|
178
|
+
|
|
179
|
+
## Canonical schema example
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
{
|
|
183
|
+
"saved-cards": {
|
|
184
|
+
"type": "AccountSavedCardsRoot",
|
|
185
|
+
"children": [
|
|
186
|
+
"saved-cards-heading",
|
|
187
|
+
"saved-cards-remove-feedback",
|
|
188
|
+
"saved-cards-loading",
|
|
189
|
+
"saved-cards-error",
|
|
190
|
+
"saved-cards-empty",
|
|
191
|
+
"saved-cards-list"
|
|
192
|
+
]
|
|
193
|
+
},
|
|
194
|
+
"saved-cards-heading": { "type": "AccountSavedCardsHeading" },
|
|
195
|
+
"saved-cards-remove-feedback": { "type": "AccountSavedCardsRemoveFeedback" },
|
|
196
|
+
"saved-cards-loading": { "type": "AccountSavedCardsLoading" },
|
|
197
|
+
"saved-cards-error": { "type": "AccountSavedCardsError" },
|
|
198
|
+
"saved-cards-empty": { "type": "AccountSavedCardsEmpty" },
|
|
199
|
+
"saved-cards-list": { "type": "AccountSavedCardsList", "children": ["saved-card-item"] },
|
|
200
|
+
"saved-card-item": { "type": "AccountSavedCardItem" }
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Nested inside another account page, with a lower heading:
|
|
205
|
+
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"saved-cards-heading": { "type": "AccountSavedCardsHeading", "props": { "as": "h3" } }
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
With the row composed, so the expiry line and the removal prompt can be reworded from the CMS:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"saved-card-item": {
|
|
217
|
+
"type": "AccountSavedCardItem",
|
|
218
|
+
"children": ["saved-card-summary", "saved-card-expiry", "saved-card-remove"]
|
|
219
|
+
},
|
|
220
|
+
"saved-card-summary": { "type": "CardSummary" },
|
|
221
|
+
"saved-card-expiry": { "type": "AccountSavedCardExpiry" },
|
|
222
|
+
"saved-card-remove": { "type": "AccountSavedCardRemove", "children": ["saved-card-remove-dialog"] },
|
|
223
|
+
"saved-card-remove-dialog": {
|
|
224
|
+
"type": "AlertDialogRoot",
|
|
225
|
+
"children": ["saved-card-remove-trigger", "saved-card-remove-portal"]
|
|
226
|
+
},
|
|
227
|
+
"saved-card-remove-trigger": { "type": "AccountSavedCardRemoveTrigger" },
|
|
228
|
+
"saved-card-remove-portal": {
|
|
229
|
+
"type": "AlertDialogPortal",
|
|
230
|
+
"children": ["saved-card-remove-backdrop", "saved-card-remove-viewport"]
|
|
231
|
+
},
|
|
232
|
+
"saved-card-remove-backdrop": { "type": "AlertDialogBackdrop" },
|
|
233
|
+
"saved-card-remove-viewport": { "type": "AlertDialogViewport", "children": ["saved-card-remove-popup"] },
|
|
234
|
+
"saved-card-remove-popup": {
|
|
235
|
+
"type": "AlertDialogPopup",
|
|
236
|
+
"children": [
|
|
237
|
+
"saved-card-remove-title",
|
|
238
|
+
"saved-card-remove-description",
|
|
239
|
+
"saved-card-remove-cancel",
|
|
240
|
+
"saved-card-remove-confirm"
|
|
241
|
+
]
|
|
242
|
+
},
|
|
243
|
+
"saved-card-remove-title": { "type": "AccountSavedCardRemoveTitle" },
|
|
244
|
+
"saved-card-remove-description": { "type": "AccountSavedCardRemoveDescription" },
|
|
245
|
+
"saved-card-remove-cancel": { "type": "AccountSavedCardRemoveCancel" },
|
|
246
|
+
"saved-card-remove-confirm": { "type": "AccountSavedCardRemoveConfirm" }
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Common mistakes
|
|
251
|
+
|
|
252
|
+
- **`AccountSavedCards`, `SavedCardsList`, `MyCards`.** The Root is `AccountSavedCardsRoot`; the list is `AccountSavedCardsList`.
|
|
253
|
+
- **Using `SavedCards` or `SavedCardOption` in the account.** Those are the checkout's cart-scoped picker and need a payment section.
|
|
254
|
+
- **Placing `AccountSavedCardItem` directly in the Root.** It must be inside `AccountSavedCardsList`.
|
|
255
|
+
- **Composing `AccountSavedCardsEmpty` as the only state part.** Compose Loading and Error too, or a slow or failed read shows nothing under the heading.
|
|
256
|
+
- **Setting `as: "h1"`.** Not accepted; the page title belongs to the page shell.
|
|
257
|
+
- **Passing `text` as a schema prop.** Text comes from children, the CMS entry, or the catalog.
|
|
258
|
+
- **Placing the Root outside the `my-account` layout.** It requires `session`; without a `SessionRoot` the build fails.
|
|
259
|
+
- **Giving the Item custom children without `AccountSavedCardExpiry`.** The row then hides when the card expires and whether it can be used.
|
|
260
|
+
- **Expecting CMS wording on an Item with no children.** Its default expiry line and removal prompt are not in the schema, so they read only the catalog; place `AccountSavedCardExpiry` and the `AccountSavedCardRemove` composition explicitly.
|
|
261
|
+
- **Giving the Item custom children without `AccountSavedCardRemove`.** The shopper can no longer remove the card. Do it only for a read-only list.
|
|
262
|
+
- **Leaving out `AccountSavedCardsRemoveFeedback`.** A removal then ends with no message: a success only drops the row, and a failure says nothing.
|
|
263
|
+
- **Placing the feedback inside the Item.** A removed card's row unmounts, taking the message with it.
|
|
264
|
+
- **Setting `open` on the `AlertDialogRoot` inside `AccountSavedCardRemove`.** The controller owns it.
|
|
265
|
+
- **Adding a plain button as the confirm control.** Only `AccountSavedCardRemoveConfirm` dispatches the removal.
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Styling
|
|
270
|
+
|
|
271
|
+
| Component | What you style | Plausible classes |
|
|
272
|
+
|---|---|---|
|
|
273
|
+
| `AccountSavedCardsRoot` | Section spacing | `flex flex-col gap-[16px]` |
|
|
274
|
+
| `AccountSavedCardsHeading` | Heading typography | `text-[20px] font-semibold text-[#1F1F1F]` |
|
|
275
|
+
| `AccountSavedCardsList` | Row stack | `flex flex-col gap-[8px]` |
|
|
276
|
+
| `AccountSavedCardItem` | Row box; dim expired and unusable rows | `rounded-[8px] border border-[#E5E5E5] p-[12px] data-[fs-account-saved-card-expired]:opacity-60 data-[fs-account-saved-card-unusable]:opacity-60` |
|
|
277
|
+
| `AccountSavedCardExpiry` | Line typography; color by state | `mt-[4px] text-[13px] text-[#6B6B6B] data-[fs-account-saved-card-expiry-status=expired]:text-[#B42318] data-[fs-account-saved-card-expiry-status=unusable]:text-[#B42318]` |
|
|
278
|
+
| `AccountSavedCardsEmpty` | Statement typography | `text-[14px] text-[#6B6B6B]` |
|
|
279
|
+
| `AccountSavedCardsLoading` | Placeholder stack; rows via `[&_[data-fs-account-saved-cards-loading-row]]` | `flex flex-col gap-[8px] [&_[data-fs-account-saved-cards-loading-row]]:h-[48px] [&_[data-fs-account-saved-cards-loading-row]]:rounded-[8px] [&_[data-fs-account-saved-cards-loading-row]]:bg-[#F0F0F0]` |
|
|
280
|
+
| `AccountSavedCardsError` | Alert box and link | `rounded-[8px] bg-[#FDECEC] p-[12px] text-[14px] text-[#B42318] [&_a]:underline` |
|
|
281
|
+
| `AccountSavedCardItem` (removing) | Fade the row while it is removed | `data-[fs-account-saved-card-removing]:opacity-60` |
|
|
282
|
+
| `AccountSavedCardRemoveTrigger` | Link-like control | `mt-[8px] text-[13px] text-[#B42318] underline disabled:opacity-50` |
|
|
283
|
+
| `AlertDialogPopup` | Prompt box (style the AlertDialog parts directly) | `w-full max-w-[420px] rounded-[12px] bg-white p-[24px] shadow-xl` |
|
|
284
|
+
| `AccountSavedCardRemoveConfirm` | Destructive button; dim while pending | `rounded-[6px] bg-[#B42318] px-[16px] py-[8px] text-white aria-disabled:opacity-70` |
|
|
285
|
+
| `AccountSavedCardsRemoveFeedback` | Message typography; alert color | `text-[14px] [&_[role=alert]]:text-[#B42318] [&_a]:underline` |
|
|
286
|
+
|
|
287
|
+
```json
|
|
288
|
+
{
|
|
289
|
+
"saved-cards": { "type": "AccountSavedCardsRoot", "style": ["flex", "flex-col", "gap-[16px]"] },
|
|
290
|
+
"saved-card-item": { "type": "AccountSavedCardItem", "style": ["rounded-[8px]", "border", "border-[#E5E5E5]", "p-[12px]"] }
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Related
|
|
297
|
+
|
|
298
|
+
- [[card-summary]]: the card description each row renders.
|
|
299
|
+
- [[alert-dialog]]: the overlay the removal prompt is built on.
|
|
300
|
+
- [[saved-cards]]: the checkout's saved-card picker; cart-scoped.
|
|
301
|
+
- [[my-account-profile]]: the account's other session-scoped matter.
|
|
@@ -72,9 +72,9 @@ No props.
|
|
|
72
72
|
|
|
73
73
|
### AlertDialogPortal
|
|
74
74
|
|
|
75
|
-
Teleports its children to `<body>`.
|
|
75
|
+
Teleports its children. With no `container`, they go to `<body>`. Pass `container` when a parent swatch has to reach the overlay.
|
|
76
76
|
|
|
77
|
-
No
|
|
77
|
+
No `className`.
|
|
78
78
|
|
|
79
79
|
### AlertDialogBackdrop
|
|
80
80
|
|
|
@@ -108,6 +108,7 @@ a form the shopper cannot see.
|
|
|
108
108
|
| `billingMatchNoticeLabel` | string | `"Your billing address must match the one on your card or bank statement, or your bank may decline the order."` | Always-on billing-match disclaimer. Gated only by this prop and `billingMatchNoticeVisible` — unlike the two notices above, it never changes with the toggle, the form, `billingAddressRequired`, or a saved address. |
|
|
109
109
|
| `billingMatchNoticeVisible` | boolean | `true` | Switches the billing-match disclaimer above on or off. A blank `billingMatchNoticeLabel` also renders nothing, even while this is `true` — the two rules never combine into an empty element. |
|
|
110
110
|
| `fieldRequiredMessage` | string | `"This field is required."` | Shown as an inline field error under a required, blank address field once it has been touched (T38) — see Accessibility Contract below. One prop, not one per field: every rendered field but `complement` shares the same rule. An authored empty or whitespace-only string falls back to this default. |
|
|
111
|
+
| `postalCodeInvalidMessage` | string | `"Enter a valid postal code."` | Shown as an inline field error under a touched, non-blank postal code that does not match the selected country's format (the descriptor's `rule.pattern`, the same one the delivery form enforces). Only the postal code reads this prop; the English default matches every other default on this form, so an author localises it with the rest. A blank postal code reads `fieldRequiredMessage` instead, never this. The message never contains the typed value. An authored empty or whitespace-only string falls back to this default. |
|
|
111
112
|
| `disabled` | boolean | `false` | Disables the toggle, every form field, the country selector, and the submit button. |
|
|
112
113
|
|
|
113
114
|
**Data:** declares no fragment and no `fetchStrategy`, so it fetches no shopper data. It reads only the
|
|
@@ -132,9 +133,9 @@ fields does not prevent that either — there is no `<form>` element anywhere in
|
|
|
132
133
|
`required` is real for assistive technology but not wired to anything that blocks a click on a
|
|
133
134
|
different button in a different component. Since T38 each rendered field (all but `complement`) does
|
|
134
135
|
announce its own validity once touched — see Accessibility Contract below — but that announcement is
|
|
135
|
-
driven by a local
|
|
136
|
-
gate the submit control; the submit gate is
|
|
137
|
-
own `disabled`.
|
|
136
|
+
driven by a local touched-field state (blur, or a refused submit focusing the field), never by
|
|
137
|
+
`required`'s own native validity, and it still does not gate the submit control; the submit gate is
|
|
138
|
+
`isBillingAddressFormValid`, read at the submit button's own `disabled`.
|
|
138
139
|
|
|
139
140
|
**The hard block itself lives elsewhere.** This component also publishes the exact same fact the notice
|
|
140
141
|
renders from onto the shared payment draft (`billingAddressUnsaved`), and T24's submit gate
|
|
@@ -154,10 +155,13 @@ stays checked and the shopper never opens the form. It never reacts to the toggl
|
|
|
154
155
|
`data-fs-billing-address-match-notice`, and renders as a plain paragraph with no ARIA role — it is a
|
|
155
156
|
static disclaimer, not a live region reacting to an event.
|
|
156
157
|
|
|
158
|
+
**Focus on refusal:** while the custom-address form is open, it registers itself so that when `PlaceOrder` refuses an order because the address was never saved, keyboard focus moves into the form: to the first rendered required field that is still blank; if none is blank, to the first rendered field whose value fails its country's format (a postal code `123` for BRA); and only when every field is filled and well-formed, to the submit control. The field the focus lands on, blank or malformed, is marked touched, so its message (`required` for a blank field, `format` for a malformed one) shows with the focus and no blur is needed. The country selector is never the target, and a disabled field or a disabled submit control (for example while saving) takes no focus. The reason stays in `PlaceOrder`'s existing alert and this component's unsaved-address notice. Focus moves only on the refused click.
|
|
159
|
+
|
|
157
160
|
**Country adaptivity is entirely data-driven**, reusing the same country descriptors the delivery
|
|
158
161
|
address step uses: Brazil shows a neighborhood/bairro field, the United States does not, and adding a
|
|
159
162
|
new country anywhere in this codebase is a data-only change that this component picks up automatically
|
|
160
|
-
— never a code change here.
|
|
163
|
+
— never a code change here. The postal code's format is the same data: the descriptor's `rule.pattern`
|
|
164
|
+
gates the submit button and the field error, so a country's format is defined once for both forms.
|
|
161
165
|
|
|
162
166
|
---
|
|
163
167
|
|
|
@@ -228,7 +232,7 @@ while the box is unchecked, and an optional inline error.
|
|
|
228
232
|
| Required-billing-address note (`data-fs-billing-address-required-note`) | De-emphasized helper text | `text-[12px] text-[#666666]` |
|
|
229
233
|
| Unsaved-address notice (`data-fs-billing-address-unsaved-notice`) | De-emphasized, non-error helper text | `text-[12px] text-[#666666]` |
|
|
230
234
|
| Billing-match disclaimer (`data-fs-billing-address-match-notice`) | De-emphasized helper text, first child of the root | `text-[12px] text-[#666666]` |
|
|
231
|
-
| Field error (`data-fs-field-error`) | Per-field validation message, shown once a
|
|
235
|
+
| Field error (`data-fs-field-error`) | Per-field validation message, shown once a field is touched: a blank required field, or a non-blank postal code that fails the country's format (T38); a refused submit that focuses the field touches it without a blur | `text-[12px] font-medium text-[#B00020]` |
|
|
232
236
|
| Inline error (`data-fs-billing-address-error`) | Warning-toned alert text | `text-[12px] font-medium text-[#B00020]` |
|
|
233
237
|
| Placing (`data-fs-billing-address-placing`) | Present while an order-placement sequence is in flight (T28) — distinct from `data-fs-billing-address-pending`, which this component already emits for its own local submit dispatch; the root is also `inert` and `aria-disabled` while placing | `opacity-60 cursor-not-allowed` |
|
|
234
238
|
|
|
@@ -252,10 +256,14 @@ There is no per-field styling hook beyond the particles' own `data-fs-checkbox-*
|
|
|
252
256
|
## Accessibility Contract
|
|
253
257
|
|
|
254
258
|
**What the platform promises:** every rendered custom-address field (all but `complement`) announces
|
|
255
|
-
its own validity once the shopper has touched it
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
+
its own validity once the shopper has touched it. A field is touched when the shopper blurs it, or when a
|
|
260
|
+
refused submit moves focus to it (no blur ever comes there). Focus, type nothing, and blur a required
|
|
261
|
+
field, and it carries `aria-invalid="true"` plus an error message (`fieldRequiredMessage`) associated
|
|
262
|
+
through `aria-describedby`; nothing is marked invalid before it is touched, and `complement` — the one
|
|
263
|
+
optional field — is never marked invalid. A postal code that is non-blank but not in the selected country's format
|
|
264
|
+
is marked the same way, with `postalCodeInvalidMessage` as its error; switching country re-judges the
|
|
265
|
+
typed value at once. Blank wins over format: a blank postal code reads `fieldRequiredMessage`, never the
|
|
266
|
+
format message. This mirrors `CardEntry`'s own field-level validity mechanism exactly.
|
|
259
267
|
Each field also carries its own `Field.Label`, authorable per field. A default `:focus-visible` outline
|
|
260
268
|
is painted from the platform's own stylesheet on every field in this component.
|
|
261
269
|
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# BindingSwitcher
|
|
2
|
+
|
|
3
|
+
**Category:** action
|
|
4
|
+
**Purpose:** Lists the store's bindings and starts a binding switch (locale, currency, and sales channel) through `locale.set`.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Visual cues (how to identify in an image)
|
|
9
|
+
|
|
10
|
+
A closed dropdown whose visible value is a language name, a chevron, and sometimes one short sentence in a status line. The image is the source of truth for layout.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
|
|
16
|
+
A store that declares two or more bindings and wants the shopper to switch the whole binding. Pass `bindings` as `$data.Global.localization.bindings`. With fewer than two counted bindings the component renders nothing.
|
|
17
|
+
|
|
18
|
+
## When NOT to use
|
|
19
|
+
|
|
20
|
+
- A country list, a currency picker, or a CMS language field.
|
|
21
|
+
- A store with one binding. It renders nothing and should not reserve an empty control.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Composition
|
|
26
|
+
|
|
27
|
+
The schema tree is one node. `BindingSwitcher` has no children. The `Select` parts are internal and are not schema children.
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
BindingSwitcher
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Components
|
|
36
|
+
|
|
37
|
+
### BindingSwitcher
|
|
38
|
+
|
|
39
|
+
Renders a host `div` (`data-fs-binding-switcher`). No fragment. Declares `actions: { locale: ['set'] }`. Choosing another binding calls `$actions.locale.set({ bindingId })`.
|
|
40
|
+
|
|
41
|
+
| Prop | Type | Default | Notes |
|
|
42
|
+
|------|------|---------|-------|
|
|
43
|
+
| `bindings` | object | — | `foundation.json` `localization.bindings`, keyed by binding id. No library default. The store passes `$data.Global.localization.bindings`. |
|
|
44
|
+
| `label` | string | `"Language"` | Accessible name, rendered as the select label. |
|
|
45
|
+
| `notice` | string | `"This page isn't available in the selected language."` | Shown when the page loaded with `fs_notice=no-equivalent`. Inline `<output>` (implicit `status` role). |
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Canonical schema example
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"binding-switcher": {
|
|
54
|
+
"type": "BindingSwitcher",
|
|
55
|
+
"props": {
|
|
56
|
+
"bindings": "$data.Global.localization.bindings"
|
|
57
|
+
},
|
|
58
|
+
"style": [
|
|
59
|
+
"flex",
|
|
60
|
+
"flex-col",
|
|
61
|
+
"gap-2",
|
|
62
|
+
"text-[14px]",
|
|
63
|
+
"[&_[data-fs-binding-switcher-notice]]:text-[13px]",
|
|
64
|
+
"[&_[data-fs-select-trigger]]:inline-flex",
|
|
65
|
+
"[&_[data-fs-select-trigger]]:items-center",
|
|
66
|
+
"[&_[data-fs-select-trigger]]:gap-2",
|
|
67
|
+
"[&_[data-fs-select-trigger]]:rounded-md",
|
|
68
|
+
"[&_[data-fs-select-trigger]]:border",
|
|
69
|
+
"[&_[data-fs-select-trigger]]:border-neutral-300",
|
|
70
|
+
"[&_[data-fs-select-trigger]]:bg-white",
|
|
71
|
+
"[&_[data-fs-select-trigger]]:px-3",
|
|
72
|
+
"[&_[data-fs-select-trigger]]:py-1.5",
|
|
73
|
+
"[&_[data-fs-select-positioner]]:z-50",
|
|
74
|
+
"[&_[data-fs-select-popup]]:min-w-[var(--anchor-width)]",
|
|
75
|
+
"[&_[data-fs-select-popup]]:overflow-hidden",
|
|
76
|
+
"[&_[data-fs-select-popup]]:rounded-md",
|
|
77
|
+
"[&_[data-fs-select-popup]]:border",
|
|
78
|
+
"[&_[data-fs-select-popup]]:border-neutral-200",
|
|
79
|
+
"[&_[data-fs-select-popup]]:bg-white",
|
|
80
|
+
"[&_[data-fs-select-popup]]:shadow-lg",
|
|
81
|
+
"[&_[data-fs-select-list]]:py-1",
|
|
82
|
+
"[&_[data-fs-select-item]]:cursor-pointer",
|
|
83
|
+
"[&_[data-fs-select-item]]:px-3",
|
|
84
|
+
"[&_[data-fs-select-item]]:py-2",
|
|
85
|
+
"[&_[data-fs-select-item][data-highlighted]]:bg-neutral-100"
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Common mistakes
|
|
94
|
+
|
|
95
|
+
- **LocaleSelector** or **LanguagePicker.** The name is `BindingSwitcher`.
|
|
96
|
+
- **A toast for the notice.** The notice is an inline `<output>`.
|
|
97
|
+
- **A default bindings list.** The store passes `$data.Global.localization.bindings`.
|
|
98
|
+
- **Children that rebuild Select.** The schema element has no children.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Styling
|
|
103
|
+
|
|
104
|
+
The host stacks the notice above the control. The popup stays in the host and opens below the trigger, 4px clear of it, so the element `style` reaches `[data-fs-select-popup]`. Give that popup an opaque surface. A parent locked to a fixed height lets the notice paint outside the bar; `min-h-16` on that parent keeps the notice inside it.
|
|
105
|
+
|
|
106
|
+
| Component | What you style | Plausible classes |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| `BindingSwitcher` | Stacks the notice and the control. The notice line is `text-[13px]`. The popup is `[data-fs-select-popup]`. | `flex flex-col gap-2 text-[14px] [&_[data-fs-binding-switcher-notice]]:text-[13px] [&_[data-fs-select-popup]]:bg-white [&_[data-fs-select-popup]]:border [&_[data-fs-select-popup]]:border-neutral-200 [&_[data-fs-select-popup]]:rounded-md [&_[data-fs-select-popup]]:shadow-lg` |
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"binding-switcher": {
|
|
113
|
+
"type": "BindingSwitcher",
|
|
114
|
+
"props": {
|
|
115
|
+
"bindings": "$data.Global.localization.bindings"
|
|
116
|
+
},
|
|
117
|
+
"style": [
|
|
118
|
+
"flex",
|
|
119
|
+
"flex-col",
|
|
120
|
+
"gap-2",
|
|
121
|
+
"text-[14px]",
|
|
122
|
+
"[&_[data-fs-binding-switcher-notice]]:text-[13px]",
|
|
123
|
+
"[&_[data-fs-select-trigger]]:inline-flex",
|
|
124
|
+
"[&_[data-fs-select-trigger]]:items-center",
|
|
125
|
+
"[&_[data-fs-select-trigger]]:gap-2",
|
|
126
|
+
"[&_[data-fs-select-trigger]]:rounded-md",
|
|
127
|
+
"[&_[data-fs-select-trigger]]:border",
|
|
128
|
+
"[&_[data-fs-select-trigger]]:border-neutral-300",
|
|
129
|
+
"[&_[data-fs-select-trigger]]:bg-white",
|
|
130
|
+
"[&_[data-fs-select-trigger]]:px-3",
|
|
131
|
+
"[&_[data-fs-select-trigger]]:py-1.5",
|
|
132
|
+
"[&_[data-fs-select-positioner]]:z-50",
|
|
133
|
+
"[&_[data-fs-select-popup]]:min-w-[var(--anchor-width)]",
|
|
134
|
+
"[&_[data-fs-select-popup]]:overflow-hidden",
|
|
135
|
+
"[&_[data-fs-select-popup]]:rounded-md",
|
|
136
|
+
"[&_[data-fs-select-popup]]:border",
|
|
137
|
+
"[&_[data-fs-select-popup]]:border-neutral-200",
|
|
138
|
+
"[&_[data-fs-select-popup]]:bg-white",
|
|
139
|
+
"[&_[data-fs-select-popup]]:shadow-lg",
|
|
140
|
+
"[&_[data-fs-select-list]]:py-1",
|
|
141
|
+
"[&_[data-fs-select-item]]:cursor-pointer",
|
|
142
|
+
"[&_[data-fs-select-item]]:px-3",
|
|
143
|
+
"[&_[data-fs-select-item]]:py-2",
|
|
144
|
+
"[&_[data-fs-select-item][data-highlighted]]:bg-neutral-100"
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Related
|
|
153
|
+
|
|
154
|
+
- [[select]] — the empty dropdown this component composes. `Select` does not know about bindings.
|