@vtex/faststore 0.0.8 → 0.0.11
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/README.md +0 -1
- package/dist/actions.json +48 -1
- package/dist/catalog.json +1397 -1594
- package/dist/cli/index.d.ts +66 -28
- package/dist/cli/index.js +7371 -512
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/server-runtime.js +41 -60
- package/dist/cli/server-runtime.js.map +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/client.js +2 -2
- package/dist/components.d.ts +67 -56
- package/dist/components.js +64 -53
- package/dist/content-types.json +5886 -555
- package/dist/core/dist/define-component.d.ts +7 -2
- package/dist/core/dist/define-content-type.d.ts +50 -2
- package/dist/core/dist/define-content-type.js +107 -3
- package/dist/core/dist/define-content-type.js.map +1 -1
- package/dist/core/dist/index.d.ts +2 -2
- package/dist/docs/access-code-field.md +1 -1
- package/dist/docs/access-code-sign-in.md +126 -77
- package/dist/docs/account-address-book.md +210 -95
- package/dist/docs/account-entry-point.md +4 -4
- package/dist/docs/account-menu.md +16 -17
- package/dist/docs/account-saved-cards.md +306 -0
- package/dist/docs/alert-dialog.md +3 -1
- package/dist/docs/avatar.md +4 -2
- package/dist/docs/billing-address.md +99 -30
- package/dist/docs/binding-switcher.md +157 -0
- package/dist/docs/buy-button.md +7 -8
- package/dist/docs/card-entry.md +42 -29
- package/dist/docs/card-summary.md +185 -0
- package/dist/docs/cardholder-document.md +5 -3
- package/dist/docs/carousel.md +5 -4
- package/dist/docs/cart-destination.md +251 -0
- package/dist/docs/cart-item.md +48 -15
- package/dist/docs/cart-totalizer.md +8 -6
- package/dist/docs/cart.md +240 -39
- package/dist/docs/challenge-return.md +135 -0
- package/dist/docs/client-preferences-fieldset.md +10 -5
- package/dist/docs/client-preferences.md +31 -8
- package/dist/docs/client-profile-fieldset.md +20 -6
- package/dist/docs/client-profile.md +12 -3
- package/dist/docs/copy-text.md +9 -7
- package/dist/docs/document-field.md +1 -1
- package/dist/docs/email-field.md +2 -1
- package/dist/docs/email-identification.md +12 -2
- package/dist/docs/footer-copyright.md +4 -2
- package/dist/docs/footer-social.md +1 -1
- package/dist/docs/form.md +54 -18
- package/dist/docs/free-shipping-progress.md +18 -13
- package/dist/docs/identity-edit.md +8 -2
- package/dist/docs/identity-summary.md +18 -5
- package/dist/docs/incentives.md +2 -2
- package/dist/docs/installments.md +46 -32
- package/dist/docs/logo.md +1 -1
- package/dist/docs/my-account-profile.md +16 -11
- package/dist/docs/navigation-link.md +5 -3
- package/dist/docs/order-cancel.md +3 -1
- package/dist/docs/order-delivery-address.md +7 -5
- package/dist/docs/order-delivery-group.md +1 -3
- package/dist/docs/order-details-back.md +1 -1
- package/dist/docs/order-details-header.md +1 -4
- package/dist/docs/order-invoice-download.md +60 -0
- package/dist/docs/order-list-row.md +1 -1
- package/dist/docs/order-list-search.md +13 -20
- package/dist/docs/order-list-views.md +11 -17
- package/dist/docs/order-list.md +12 -5
- package/dist/docs/order-payment.md +9 -7
- package/dist/docs/order-placed-date.md +1 -1
- package/dist/docs/order-placed-payment-summary.md +28 -15
- package/dist/docs/order-placed.md +49 -14
- package/dist/docs/order-progress.md +1 -1
- package/dist/docs/order-status-badge.md +20 -9
- package/dist/docs/order-summary.md +2 -2
- package/dist/docs/order-tracking-link.md +58 -0
- package/dist/docs/payment-method-badges.md +32 -6
- package/dist/docs/payment-methods.md +2 -2
- package/dist/docs/payment.md +36 -17
- package/dist/docs/phone-field.md +4 -4
- package/dist/docs/place-order.md +84 -36
- package/dist/docs/postal-code-field.md +3 -1
- package/dist/docs/pricing.md +21 -23
- package/dist/docs/product-gallery.md +19 -20
- package/dist/docs/product-information.md +14 -10
- package/dist/docs/product-list.md +7 -6
- package/dist/docs/product-shelf.md +7 -1
- package/dist/docs/promotion.md +4 -2
- package/dist/docs/region.md +23 -15
- package/dist/docs/save-card.md +7 -6
- package/dist/docs/saved-cards.md +65 -36
- package/dist/docs/select.md +3 -4
- package/dist/docs/shipping-address.md +57 -21
- package/dist/docs/shipping-simulator.md +53 -15
- package/dist/docs/sign-in-disclosure.md +176 -0
- package/dist/docs/sign-in-form.md +78 -47
- package/dist/docs/sign-in-redirect.md +5 -3
- package/dist/docs/sign-in.md +173 -0
- package/dist/docs/toast.md +45 -16
- package/dist/docs/variant-selector.md +15 -11
- package/dist/graphql/types.d.ts +4 -14
- package/dist/index.d.ts +3 -2
- package/dist/internal/client.d.ts +4 -3
- package/dist/internal/client.js +5 -2
- package/dist/internal/server.d.ts +10 -5
- package/dist/internal/server.js +9 -4
- package/dist/matter/access-code-sign-in/access-code-sign-in.d.ts +250 -66
- package/dist/matter/access-code-sign-in/access-code-sign-in.js +459 -188
- package/dist/matter/access-code-sign-in/access-code-sign-in.js.map +1 -1
- package/dist/matter/account-address-book/account-address-book-delete.d.ts +78 -40
- package/dist/matter/account-address-book/account-address-book-delete.js +86 -50
- package/dist/matter/account-address-book/account-address-book-delete.js.map +1 -1
- package/dist/matter/account-address-book/account-address-book-deliverability.d.ts +21 -4
- package/dist/matter/account-address-book/account-address-book-deliverability.js +45 -17
- package/dist/matter/account-address-book/account-address-book-deliverability.js.map +1 -1
- package/dist/matter/account-address-book/account-address-book-form-parts.d.ts +74 -19
- package/dist/matter/account-address-book/account-address-book-form-parts.js +77 -26
- package/dist/matter/account-address-book/account-address-book-form-parts.js.map +1 -1
- package/dist/matter/account-address-book/account-address-book-profile-notice.d.ts +27 -6
- package/dist/matter/account-address-book/account-address-book-profile-notice.js +55 -28
- package/dist/matter/account-address-book/account-address-book-profile-notice.js.map +1 -1
- package/dist/matter/account-address-book/account-address-book.d.ts +67 -14
- package/dist/matter/account-address-book/account-address-book.js +74 -33
- package/dist/matter/account-address-book/account-address-book.js.map +1 -1
- package/dist/matter/account-address-book/account-address-country-switch.js +3 -3
- package/dist/matter/account-address-book/account-address-country-switch.js.map +1 -1
- package/dist/matter/account-address-book/account-address-country.d.ts +66 -20
- package/dist/matter/account-address-book/account-address-country.js +83 -49
- package/dist/matter/account-address-book/account-address-country.js.map +1 -1
- package/dist/matter/account-address-book/account-address-form-context.d.ts +8 -4
- package/dist/matter/account-address-book/account-address-form-context.js.map +1 -1
- package/dist/matter/account-address-book/account-address-form.d.ts +468 -45
- package/dist/matter/account-address-book/account-address-form.js +518 -155
- package/dist/matter/account-address-book/account-address-form.js.map +1 -1
- package/dist/matter/account-address-book/account-address-record.d.ts +27 -6
- package/dist/matter/account-address-book/account-address-record.js +32 -17
- package/dist/matter/account-address-book/account-address-record.js.map +1 -1
- package/dist/matter/account-menu/account-menu.d.ts +34 -17
- package/dist/matter/account-menu/account-menu.js +46 -54
- package/dist/matter/account-menu/account-menu.js.map +1 -1
- package/dist/matter/account-menu-identity/account-menu-identity.js +1 -1
- package/dist/matter/account-saved-cards/account-saved-cards.d.ts +463 -0
- package/dist/matter/account-saved-cards/account-saved-cards.js +1011 -0
- package/dist/matter/account-saved-cards/account-saved-cards.js.map +1 -0
- package/dist/matter/billing-address/billing-address.d.ts +156 -74
- package/dist/matter/billing-address/billing-address.js +227 -156
- package/dist/matter/billing-address/billing-address.js.map +1 -1
- package/dist/matter/breadcrumb/breadcrumb.d.ts +21 -3
- package/dist/matter/breadcrumb/breadcrumb.js +24 -9
- package/dist/matter/breadcrumb/breadcrumb.js.map +1 -1
- package/dist/matter/buy-button/buy-button.d.ts +8 -11
- package/dist/matter/buy-button/buy-button.js +10 -19
- package/dist/matter/buy-button/buy-button.js.map +1 -1
- package/dist/matter/card-entry/card-capture.js +12 -4
- package/dist/matter/card-entry/card-capture.js.map +1 -1
- package/dist/matter/card-entry/card-entry.d.ts +123 -32
- package/dist/matter/card-entry/card-entry.js +348 -221
- package/dist/matter/card-entry/card-entry.js.map +1 -1
- package/dist/matter/cart/cart-namespace.d.ts +11 -1
- package/dist/matter/cart/cart-namespace.js +11 -1
- package/dist/matter/cart/cart-namespace.js.map +1 -1
- package/dist/matter/cart/cart.d.ts +416 -45
- package/dist/matter/cart/cart.js +782 -101
- package/dist/matter/cart/cart.js.map +1 -1
- package/dist/matter/cart-destination/cart-destination.d.ts +233 -0
- package/dist/matter/cart-destination/cart-destination.js +703 -0
- package/dist/matter/cart-destination/cart-destination.js.map +1 -0
- package/dist/matter/cart-item/cart-item.d.ts +145 -16
- package/dist/matter/cart-item/cart-item.js +230 -54
- package/dist/matter/cart-item/cart-item.js.map +1 -1
- package/dist/matter/cart-item-compositions/cart-item-compositions.js +1 -1
- package/dist/matter/cart-item-compositions/cart-item-compositions.js.map +1 -1
- package/dist/matter/cart-item-customizations/cart-item-customizations.js +1 -1
- package/dist/matter/cart-item-customizations/cart-item-customizations.js.map +1 -1
- package/dist/matter/cart-item-discounts/cart-item-discounts.js +1 -1
- package/dist/matter/cart-item-discounts/cart-item-discounts.js.map +1 -1
- package/dist/matter/cart-item-seller-info/cart-item-seller-info.js +1 -1
- package/dist/matter/cart-item-seller-info/cart-item-seller-info.js.map +1 -1
- package/dist/matter/cart-item-variations/cart-item-variations.js +1 -1
- package/dist/matter/cart-item-variations/cart-item-variations.js.map +1 -1
- package/dist/matter/cart-totalizer/cart-totalizer.d.ts +43 -9
- package/dist/matter/cart-totalizer/cart-totalizer.js +49 -19
- package/dist/matter/cart-totalizer/cart-totalizer.js.map +1 -1
- package/dist/matter/challenge-return/challenge-return.d.ts +62 -0
- package/dist/matter/challenge-return/challenge-return.js +241 -0
- package/dist/matter/challenge-return/challenge-return.js.map +1 -0
- package/dist/matter/client-preferences/client-preferences-fieldset.d.ts +86 -17
- package/dist/matter/client-preferences/client-preferences-fieldset.js +126 -54
- package/dist/matter/client-preferences/client-preferences-fieldset.js.map +1 -1
- package/dist/matter/client-preferences/client-preferences.d.ts +50 -7
- package/dist/matter/client-preferences/client-preferences.js +84 -15
- package/dist/matter/client-preferences/client-preferences.js.map +1 -1
- package/dist/matter/client-profile/client-profile.d.ts +44 -9
- package/dist/matter/client-profile/client-profile.js +64 -24
- package/dist/matter/client-profile/client-profile.js.map +1 -1
- package/dist/matter/client-profile-form/client-profile-fieldset.d.ts +119 -22
- package/dist/matter/client-profile-form/client-profile-fieldset.js +161 -73
- package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -1
- package/dist/matter/delivery-options/delivery-options-accordion.d.ts +49 -4
- package/dist/matter/delivery-options/delivery-options-accordion.js +67 -14
- package/dist/matter/delivery-options/delivery-options-accordion.js.map +1 -1
- package/dist/matter/delivery-options/delivery-options-controller.d.ts +69 -9
- package/dist/matter/delivery-options/delivery-options-controller.js +80 -14
- package/dist/matter/delivery-options/delivery-options-controller.js.map +1 -1
- package/dist/matter/delivery-options/delivery-options.d.ts +37 -2
- package/dist/matter/delivery-options/delivery-options.js +75 -12
- package/dist/matter/delivery-options/delivery-options.js.map +1 -1
- package/dist/matter/delivery-options/use-delivery-option-selection.d.ts +1 -0
- package/dist/matter/delivery-options/use-delivery-option-selection.js +1 -1
- package/dist/matter/delivery-options/use-delivery-option-selection.js.map +1 -1
- package/dist/matter/email-identification/email-identification.d.ts +25 -3
- package/dist/matter/email-identification/email-identification.js +49 -12
- package/dist/matter/email-identification/email-identification.js.map +1 -1
- package/dist/matter/free-shipping-progress/free-shipping-progress.d.ts +85 -10
- package/dist/matter/free-shipping-progress/free-shipping-progress.js +153 -53
- package/dist/matter/free-shipping-progress/free-shipping-progress.js.map +1 -1
- package/dist/matter/identity-edit/identity-edit.d.ts +52 -10
- package/dist/matter/identity-edit/identity-edit.js +47 -19
- package/dist/matter/identity-edit/identity-edit.js.map +1 -1
- package/dist/matter/identity-summary/identity-summary.d.ts +76 -22
- package/dist/matter/identity-summary/identity-summary.js +95 -45
- package/dist/matter/identity-summary/identity-summary.js.map +1 -1
- package/dist/matter/installments/installments-select.d.ts +98 -16
- package/dist/matter/installments/installments-select.js +156 -48
- package/dist/matter/installments/installments-select.js.map +1 -1
- package/dist/matter/installments/installments.d.ts +96 -16
- package/dist/matter/installments/installments.js +115 -40
- package/dist/matter/installments/installments.js.map +1 -1
- package/dist/matter/installments/use-installments-selection.d.ts +1 -0
- package/dist/matter/installments/use-installments-selection.js +8 -3
- package/dist/matter/installments/use-installments-selection.js.map +1 -1
- package/dist/matter/my-account-profile/my-account-profile.d.ts +358 -103
- package/dist/matter/my-account-profile/my-account-profile.js +370 -174
- package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
- package/dist/matter/order-cancel/order-cancel.d.ts +65 -19
- package/dist/matter/order-cancel/order-cancel.js +118 -51
- package/dist/matter/order-cancel/order-cancel.js.map +1 -1
- package/dist/matter/order-delivery-address/order-delivery-address.d.ts +8 -18
- package/dist/matter/order-delivery-address/order-delivery-address.js +14 -23
- package/dist/matter/order-delivery-address/order-delivery-address.js.map +1 -1
- package/dist/matter/order-delivery-group/order-delivery-group.d.ts +40 -24
- package/dist/matter/order-delivery-group/order-delivery-group.js +64 -74
- package/dist/matter/order-delivery-group/order-delivery-group.js.map +1 -1
- package/dist/matter/order-details-header/order-details-header.d.ts +32 -15
- package/dist/matter/order-details-header/order-details-header.js +66 -58
- package/dist/matter/order-details-header/order-details-header.js.map +1 -1
- package/dist/matter/order-invoice-download/order-invoice-download.d.ts +78 -0
- package/dist/matter/order-invoice-download/order-invoice-download.js +173 -0
- package/dist/matter/order-invoice-download/order-invoice-download.js.map +1 -0
- package/dist/matter/order-list/order-list.d.ts +164 -19
- package/dist/matter/order-list/order-list.js +229 -87
- package/dist/matter/order-list/order-list.js.map +1 -1
- package/dist/matter/order-list-row/order-list-row.d.ts +6 -1
- package/dist/matter/order-list-row/order-list-row.js +3 -2
- package/dist/matter/order-list-row/order-list-row.js.map +1 -1
- package/dist/matter/order-list-search/order-list-search.d.ts +18 -26
- package/dist/matter/order-list-search/order-list-search.js +30 -69
- package/dist/matter/order-list-search/order-list-search.js.map +1 -1
- package/dist/matter/order-list-views/order-list-views.d.ts +15 -22
- package/dist/matter/order-list-views/order-list-views.js +22 -68
- package/dist/matter/order-list-views/order-list-views.js.map +1 -1
- package/dist/matter/order-payment/order-payment.d.ts +33 -10
- package/dist/matter/order-payment/order-payment.js +44 -39
- package/dist/matter/order-payment/order-payment.js.map +1 -1
- package/dist/matter/order-placed/order-placed-deliveries.d.ts +144 -12
- package/dist/matter/order-placed/order-placed-deliveries.js +115 -40
- package/dist/matter/order-placed/order-placed-deliveries.js.map +1 -1
- package/dist/matter/order-placed/order-placed.d.ts +198 -31
- package/dist/matter/order-placed/order-placed.js +230 -139
- package/dist/matter/order-placed/order-placed.js.map +1 -1
- package/dist/matter/order-placed-date/order-placed-date.d.ts +5 -8
- package/dist/matter/order-placed-date/order-placed-date.js +7 -8
- package/dist/matter/order-placed-date/order-placed-date.js.map +1 -1
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +90 -17
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +93 -117
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -1
- package/dist/matter/order-progress/order-progress.d.ts +19 -8
- package/dist/matter/order-progress/order-progress.js +37 -45
- package/dist/matter/order-progress/order-progress.js.map +1 -1
- package/dist/matter/order-summary/order-summary.d.ts +19 -9
- package/dist/matter/order-summary/order-summary.js +38 -44
- package/dist/matter/order-summary/order-summary.js.map +1 -1
- package/dist/matter/order-tracking-link/order-tracking-link.d.ts +43 -0
- package/dist/matter/order-tracking-link/order-tracking-link.js +107 -0
- package/dist/matter/order-tracking-link/order-tracking-link.js.map +1 -0
- package/dist/matter/payment/payment-card-capture.js +17 -10
- package/dist/matter/payment/payment-card-capture.js.map +1 -1
- package/dist/matter/payment/payment-controller.d.ts +4 -2
- package/dist/matter/payment/payment-controller.js +30 -9
- package/dist/matter/payment/payment-controller.js.map +1 -1
- package/dist/matter/payment/payment-method-badges.js +1 -1
- package/dist/matter/payment/payment.d.ts +69 -19
- package/dist/matter/payment/payment.js +101 -35
- package/dist/matter/payment/payment.js.map +1 -1
- package/dist/matter/payment/use-payment-method-selection.d.ts +25 -4
- package/dist/matter/payment/use-payment-method-selection.js +94 -32
- package/dist/matter/payment/use-payment-method-selection.js.map +1 -1
- package/dist/matter/payment/use-payment-submit-gate.d.ts +14 -3
- package/dist/matter/payment/use-payment-submit-gate.js +47 -8
- package/dist/matter/payment/use-payment-submit-gate.js.map +1 -1
- package/dist/matter/place-order/place-order.d.ts +171 -57
- package/dist/matter/place-order/place-order.js +376 -185
- package/dist/matter/place-order/place-order.js.map +1 -1
- package/dist/matter/pricing/pricing.d.ts +152 -13
- package/dist/matter/pricing/pricing.js +153 -52
- package/dist/matter/pricing/pricing.js.map +1 -1
- package/dist/matter/product-information/product-information.d.ts +27 -4
- package/dist/matter/product-information/product-information.js +32 -15
- package/dist/matter/product-information/product-information.js.map +1 -1
- package/dist/matter/product-list/product-list.d.ts +24 -6
- package/dist/matter/product-list/product-list.js +32 -26
- package/dist/matter/product-list/product-list.js.map +1 -1
- package/dist/matter/product-shelf/product-shelf.d.ts +8 -3
- package/dist/matter/product-shelf/product-shelf.js +111 -10
- package/dist/matter/product-shelf/product-shelf.js.map +1 -1
- package/dist/matter/region/region.d.ts +33 -16
- package/dist/matter/region/region.js +59 -52
- package/dist/matter/region/region.js.map +1 -1
- package/dist/matter/save-card/save-card.d.ts +43 -8
- package/dist/matter/save-card/save-card.js +61 -23
- package/dist/matter/save-card/save-card.js.map +1 -1
- package/dist/matter/saved-cards/saved-cards.d.ts +113 -21
- package/dist/matter/saved-cards/saved-cards.js +349 -77
- package/dist/matter/saved-cards/saved-cards.js.map +1 -1
- package/dist/matter/shipping-address/address-payload.js +25 -0
- package/dist/matter/shipping-address/address-payload.js.map +1 -0
- package/dist/matter/shipping-address/country-descriptors.js +71 -71
- package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
- package/dist/matter/shipping-address/library-country-descriptors.js +136 -0
- package/dist/matter/shipping-address/library-country-descriptors.js.map +1 -0
- package/dist/matter/shipping-address/shipping-address.d.ts +312 -45
- package/dist/matter/shipping-address/shipping-address.js +443 -188
- package/dist/matter/shipping-address/shipping-address.js.map +1 -1
- package/dist/matter/shipping-simulator/shipping-simulator.d.ts +251 -25
- package/dist/matter/shipping-simulator/shipping-simulator.js +261 -51
- package/dist/matter/shipping-simulator/shipping-simulator.js.map +1 -1
- package/dist/matter/sign-in/sign-in.d.ts +108 -0
- package/dist/matter/sign-in/sign-in.js +285 -0
- package/dist/matter/sign-in/sign-in.js.map +1 -0
- package/dist/matter/sign-in-disclosure/sign-in-disclosure.d.ts +81 -0
- package/dist/matter/sign-in-disclosure/sign-in-disclosure.js +232 -0
- package/dist/matter/sign-in-disclosure/sign-in-disclosure.js.map +1 -0
- package/dist/matter/sign-in-form/sign-in-form.d.ts +93 -62
- package/dist/matter/sign-in-form/sign-in-form.js +134 -144
- package/dist/matter/sign-in-form/sign-in-form.js.map +1 -1
- package/dist/particles/binding-switcher/binding-switcher.d.ts +59 -0
- package/dist/particles/binding-switcher/binding-switcher.js +194 -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 +113 -0
- package/dist/particles/card-summary/card-summary.js +221 -0
- package/dist/particles/card-summary/card-summary.js.map +1 -0
- package/dist/particles/carousel/carousel.d.ts +99 -11
- package/dist/particles/carousel/carousel.js +103 -35
- package/dist/particles/carousel/carousel.js.map +1 -1
- package/dist/particles/copy-text/copy-text.js +5 -15
- package/dist/particles/copy-text/copy-text.js.map +1 -1
- package/dist/particles/dialog/dialog.d.ts +14 -6
- package/dist/particles/dialog/dialog.js +6 -3
- package/dist/particles/dialog/dialog.js.map +1 -1
- package/dist/particles/drawer/drawer.js +1 -1
- package/dist/particles/drawer/drawer.js.map +1 -1
- package/dist/particles/email-field/email-field.d.ts +2 -1
- package/dist/particles/email-field/email-field.js +2 -1
- package/dist/particles/email-field/email-field.js.map +1 -1
- package/dist/particles/footer-link-group/footer-link-group.js +1 -0
- 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/form/form.d.ts +85 -13
- package/dist/particles/form/form.js +91 -42
- package/dist/particles/form/form.js.map +1 -1
- package/dist/particles/gallery/gallery.d.ts +129 -12
- package/dist/particles/gallery/gallery.js +121 -34
- package/dist/particles/gallery/gallery.js.map +1 -1
- package/dist/particles/incentives/incentives.d.ts +1 -1
- package/dist/particles/incentives/incentives.js +1 -1
- package/dist/particles/incentives/incentives.js.map +1 -1
- package/dist/particles/order-details-back/order-details-back.d.ts +5 -3
- package/dist/particles/order-details-back/order-details-back.js +8 -10
- package/dist/particles/order-details-back/order-details-back.js.map +1 -1
- package/dist/particles/order-status-badge/order-status-badge.d.ts +3 -3
- package/dist/particles/order-status-badge/order-status-badge.js +4 -20
- package/dist/particles/order-status-badge/order-status-badge.js.map +1 -1
- package/dist/particles/password-field/password-field.d.ts +1 -1
- package/dist/particles/password-field/password-field.js +2 -4
- package/dist/particles/password-field/password-field.js.map +1 -1
- 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.d.ts +4 -4
- package/dist/particles/phone-field/phone-field.js +8 -11
- package/dist/particles/phone-field/phone-field.js.map +1 -1
- package/dist/particles/spinner/spinner.d.ts +24 -4
- package/dist/particles/spinner/spinner.js +25 -9
- package/dist/particles/spinner/spinner.js.map +1 -1
- package/dist/particles/switch/switch.d.ts +4 -1
- package/dist/particles/switch/switch.js +3 -1
- package/dist/particles/switch/switch.js.map +1 -1
- package/dist/particles/toast/toast.d.ts +49 -9
- package/dist/particles/toast/toast.js +81 -15
- package/dist/particles/toast/toast.js.map +1 -1
- package/dist/schema.graphql +461 -89
- package/dist/sdk/actions/index.d.ts +3 -1
- package/dist/sdk/actions/index.js +3 -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/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 +6 -2
- package/dist/sdk/address/address-fields.js +4 -4
- package/dist/sdk/address/address-fields.js.map +1 -1
- package/dist/sdk/address/constants.js +1 -6
- package/dist/sdk/address/constants.js.map +1 -1
- package/dist/sdk/address/messages.js +44 -44
- package/dist/sdk/address/messages.js.map +1 -1
- package/dist/sdk/address/postal-code.js +15 -2
- package/dist/sdk/address/postal-code.js.map +1 -1
- package/dist/sdk/address/types.d.ts +5 -3
- package/dist/sdk/address/validate-address.js +3 -3
- package/dist/sdk/address/validate-address.js.map +1 -1
- package/dist/sdk/analytics/use-analytics-actions.d.ts +1 -1
- package/dist/sdk/analytics/use-analytics-actions.js.map +1 -1
- package/dist/sdk/cache/storefront-cache.js +2 -1
- 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/data/index.js +2 -2
- package/dist/sdk/data/reactive-list-item-data-provider.js +2 -2
- package/dist/sdk/generated/gql.js +16 -12
- package/dist/sdk/generated/gql.js.map +1 -1
- package/dist/sdk/generated/graphql.d.ts +197 -51
- package/dist/sdk/generated/graphql.js +2318 -91
- package/dist/sdk/generated/graphql.js.map +1 -1
- package/dist/sdk/i18n/format-error-code.js +23 -0
- package/dist/sdk/i18n/format-error-code.js.map +1 -0
- package/dist/sdk/i18n/message-formatter.d.ts +22 -0
- package/dist/sdk/i18n/message-formatter.js +140 -0
- package/dist/sdk/i18n/message-formatter.js.map +1 -0
- package/dist/sdk/i18n/use-message-formatter.d.ts +8 -0
- package/dist/sdk/i18n/use-message-formatter.js +18 -0
- package/dist/sdk/i18n/use-message-formatter.js.map +1 -0
- package/dist/sdk/identity/use-identity-actions.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/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/redirect.d.ts +2 -0
- package/dist/sdk/navigation/redirect.js +19 -1
- package/dist/sdk/navigation/redirect.js.map +1 -1
- package/dist/sdk/navigation/types.d.ts +13 -0
- package/dist/sdk/payment/bin-format.js +20 -0
- package/dist/sdk/payment/bin-format.js.map +1 -0
- package/dist/sdk/payment/challenge-return.js +37 -0
- package/dist/sdk/payment/challenge-return.js.map +1 -0
- package/dist/sdk/payment/confirmation-last-four.js +39 -0
- package/dist/sdk/payment/confirmation-last-four.js.map +1 -0
- package/dist/sdk/payment/gateway.d.ts +1 -1
- package/dist/sdk/payment/gateway.js +8 -2
- package/dist/sdk/payment/gateway.js.map +1 -1
- package/dist/sdk/payment/operations.d.ts +1 -0
- package/dist/sdk/payment/operations.js +28 -6
- package/dist/sdk/payment/operations.js.map +1 -1
- package/dist/sdk/payment/resumed-purchase.d.ts +1 -0
- package/dist/sdk/payment/resumed-purchase.js +119 -0
- package/dist/sdk/payment/resumed-purchase.js.map +1 -0
- package/dist/sdk/payment/security-code-mask.js +16 -23
- package/dist/sdk/payment/security-code-mask.js.map +1 -1
- package/dist/sdk/payment/submission-registry.js +6 -2
- package/dist/sdk/payment/submission-registry.js.map +1 -1
- package/dist/sdk/payment/use-payment-actions.d.ts +18 -3
- package/dist/sdk/payment/use-payment-actions.js +23 -3
- package/dist/sdk/payment/use-payment-actions.js.map +1 -1
- package/dist/sdk/payment/use-place-order.d.ts +10 -2
- package/dist/sdk/payment/use-place-order.js +138 -76
- package/dist/sdk/payment/use-place-order.js.map +1 -1
- package/dist/sdk/provider/storefront-provider.d.ts +1 -7
- package/dist/sdk/provider/storefront-provider.js +4 -11
- package/dist/sdk/provider/storefront-provider.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/entity-landing.d.ts +24 -0
- package/dist/sdk/seo/entity-landing.js +30 -0
- package/dist/sdk/seo/entity-landing.js.map +1 -0
- package/dist/sdk/seo/page-alternates.d.ts +8 -5
- package/dist/sdk/seo/page-alternates.js +11 -14
- package/dist/sdk/seo/page-alternates.js.map +1 -1
- package/dist/sdk/seo/search-landing.d.ts +42 -0
- package/dist/sdk/seo/search-landing.js +85 -0
- package/dist/sdk/seo/search-landing.js.map +1 -0
- package/dist/sdk/session/mock-session.d.ts +9 -0
- package/dist/sdk/session/mock-session.js +31 -0
- package/dist/sdk/session/mock-session.js.map +1 -0
- package/dist/sdk/session/read-server-session.d.ts +3 -0
- package/dist/sdk/session/read-server-session.js +5 -0
- package/dist/sdk/session/read-server-session.js.map +1 -1
- package/dist/sdk/session/return-path-segment.d.ts +10 -0
- package/dist/sdk/session/return-path-segment.js +15 -0
- package/dist/sdk/session/return-path-segment.js.map +1 -0
- package/dist/sdk/session/use-session-actions.js.map +1 -1
- 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/shipping/use-cart-shipping-simulation.js.map +1 -1
- package/dist/sdk/shipping/use-shipping-actions.js.map +1 -1
- package/dist/sdk/shipping/use-shipping-simulation.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/safe-href.d.ts +2 -0
- package/package.json +4 -3
- package/skills/storefront-asset/SKILL.md +2 -2
- package/skills/storefront-asset/references/api-side.md +27 -14
- package/skills/storefront-asset/references/findings.md +5 -2
- package/src/styles/tailwind.css +9 -2
- package/dist/matter/shipping-address/country-descriptors.d.ts +0 -1
- package/dist/message-locales.json +0 -7
- package/dist/sdk/i18n/client.d.ts +0 -4
- package/dist/sdk/i18n/client.js +0 -4
- package/dist/sdk/i18n/locales.d.ts +0 -8
- package/dist/sdk/i18n/locales.js +0 -57
- package/dist/sdk/i18n/locales.js.map +0 -1
- package/dist/sdk/i18n/messages/en-US.js +0 -164
- package/dist/sdk/i18n/messages/en-US.js.map +0 -1
- package/dist/sdk/i18n/messages/en-US.json +0 -159
- package/dist/sdk/i18n/messages/en-US.json.d.ts +0 -163
- package/dist/sdk/i18n/messages/es-ES.js +0 -164
- package/dist/sdk/i18n/messages/es-ES.js.map +0 -1
- package/dist/sdk/i18n/messages/es-ES.json +0 -159
- package/dist/sdk/i18n/messages/pt-BR.js +0 -164
- package/dist/sdk/i18n/messages/pt-BR.js.map +0 -1
- package/dist/sdk/i18n/messages/pt-BR.json +0 -159
- package/dist/sdk/i18n/provider.d.ts +0 -1
- package/dist/sdk/i18n/provider.js +0 -30
- package/dist/sdk/i18n/provider.js.map +0 -1
- package/dist/sdk/i18n/server.d.ts +0 -28
- package/dist/sdk/i18n/server.js +0 -59
- package/dist/sdk/i18n/server.js.map +0 -1
- package/dist/utils/resolve-authored-copy.js +0 -18
- package/dist/utils/resolve-authored-copy.js.map +0 -1
- package/dist/utils/substitute-template.js +0 -33
- package/dist/utils/substitute-template.js.map +0 -1
package/dist/docs/saved-cards.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# SavedCards
|
|
2
2
|
|
|
3
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.
|
|
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 that needs a security code is selected. A card that needs none shows no field and is placed with one action.
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -11,7 +11,7 @@ Use these signals to detect that a SavedCards block is present. Position on the
|
|
|
11
11
|
|
|
12
12
|
A SavedCards block contains any combination of:
|
|
13
13
|
|
|
14
|
-
- A **list of radio rows**, each showing a **card network
|
|
14
|
+
- A **list of radio rows**, each showing a **card network mark or name** (Visa, Mastercard, …) plus a **masked number** like `•••• 4242` or `**** 4242`, the facts separated by a dot.
|
|
15
15
|
- A **custom label** next to a row, e.g. *"Meu cartão"* / *"Personal card"* — shopper-assigned, not always present.
|
|
16
16
|
- A row rendered **visually muted or with a "expired" tag**, still present in the list but not clickable.
|
|
17
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).
|
|
@@ -36,24 +36,26 @@ If the image shows a **radio list of masked card numbers with network names**, u
|
|
|
36
36
|
|
|
37
37
|
## Composition
|
|
38
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.
|
|
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, for a card that needs one. `SavedCardRemove` is placed inside `SavedCardOption` too, so an expired card can be removed from the list.
|
|
40
40
|
|
|
41
41
|
```
|
|
42
42
|
PaymentSectionRoot (or PaymentSectionController)
|
|
43
43
|
├── PaymentMethodList (sibling — network/method picker)
|
|
44
44
|
├── SavedCards
|
|
45
45
|
│ └── SavedCardOption (per-card template, repeated once per stored card)
|
|
46
|
-
│
|
|
46
|
+
│ ├── SavedCardCvvField (appears only for the selected, non-expired row that needs a CVV)
|
|
47
|
+
│ └── SavedCardRemove (appears only for an expired row: removes the card)
|
|
47
48
|
└── CardEntry (sibling — "use a new card", not a child of SavedCards)
|
|
48
49
|
```
|
|
49
50
|
|
|
50
|
-
Child order reflects visual order. `
|
|
51
|
+
Child order reflects visual order. `SavedCardCvvField` and `SavedCardRemove` are the only two children this block defines for `SavedCardOption`; everything else (`PaymentMethodList`, `CardEntry`) is a sibling under the same `PaymentSectionRoot`, never nested inside `SavedCards`.
|
|
51
52
|
|
|
52
53
|
**Composition rules:**
|
|
53
54
|
|
|
54
55
|
- `SavedCards` must be inside `PaymentSectionRoot` or `PaymentSectionController`. Outside either, it throws.
|
|
55
56
|
- `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.
|
|
57
|
+
- `SavedCardCvvField` must be inside `SavedCardOption`. Outside it, it throws. It is only needed for cards that need a security code: omitting it means a shopper can select such a card but never submit a payment with it, so include it. A card that needs no code is payable through `SavedCardOption` alone.
|
|
58
|
+
- `SavedCardRemove` must be inside `SavedCardOption`. Outside it, it throws an error that names `SavedCardRemove`. It renders only for an expired row, so composing it in the one row template is safe for every card.
|
|
57
59
|
- `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
60
|
|
|
59
61
|
---
|
|
@@ -64,9 +66,7 @@ Child order reflects visual order. `SavedCardOption` and `SavedCardCvvField` are
|
|
|
64
66
|
|
|
65
67
|
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
68
|
|
|
67
|
-
|
|
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. |
|
|
69
|
+
No copy props. **Content model** (`saved-cards`): `legend`, the radio group's accessible name, rendered as a visible fieldset legend above the rows (T38); `savedCardUnavailableMessage`, the inline alert when the server no longer matches the picked card (`INVALID_SAVED_CARD_ACCOUNT_ID`, `MISMATCHED_BIN_FOR_SAVED_CARD`); and `genericErrorMessage`, the alert for every other selection code and `NETWORK_ERROR`. A code the package does not know (one a newer server added) also shows `genericErrorMessage` and logs `message.unknown-code`.
|
|
70
70
|
|
|
71
71
|
Which cards exist is always real data (`Query.payment.savedCards`) — never author them as props.
|
|
72
72
|
|
|
@@ -74,7 +74,11 @@ Which cards exist is always real data (`Query.payment.savedCards`) — never aut
|
|
|
74
74
|
|
|
75
75
|
### SavedCardOption
|
|
76
76
|
|
|
77
|
-
One saved card as a radio row: network
|
|
77
|
+
One saved card as a radio row: the network's mark (the card entry's icon for that network), the masked last four (`•••• 4242`), and the shopper's own label when set, separated by a dot (`data-fs-saved-card-option-separator`, hidden from assistive tech; none renders after the last fact). A network the icon table does not know shows its name as text instead. The mark keeps the network in the radio's accessible name (`role="img"`, `aria-label` set to the network).
|
|
78
|
+
|
|
79
|
+
Disabled (not selectable) when the card is expired — the row still renders so the shopper knows the card exists. An expired card is never the selection, even when it is the persisted one: no row is checked or marked selected, the radio group has no value, no security-code field mounts and nothing is registered to submit.
|
|
80
|
+
|
|
81
|
+
A card whose `cvvRequired` is a literal `false` needs no security code. Selected and not expired, it shows no field and `SavedCardOption` itself registers a `'saved-card'` submission that sends nothing: placing the order opens the transaction, skips Send Payments and the gateway callback, and takes the order group as the order id, and the client treats the attempt as terminal (ruled 2026-10-14). That is the client's state, not confirmed platform order creation: the live proof is pending (PEXP-2194, ADR-0023). Any other flag value (absent, `null`, non-boolean) keeps the field and the coded path: an unknown never becomes a silent skip.
|
|
78
82
|
|
|
79
83
|
No props beyond standard container attributes (`className`, `children`). Must be a direct child of `SavedCards`.
|
|
80
84
|
|
|
@@ -82,13 +86,37 @@ No props beyond standard container attributes (`className`, `children`). Must be
|
|
|
82
86
|
|
|
83
87
|
### SavedCardCvvField
|
|
84
88
|
|
|
85
|
-
The CVV re-entry field for its row. Renders nothing until that specific row is selected and
|
|
89
|
+
The CVV re-entry field for its row. Renders nothing until that specific row is selected, is not expired and its card requires a CVV (only a literal `cvvRequired: false` skips it); then renders a numeric input (digits only, capped at 4 characters) whose digits render **obscured** (dots) via an inline `-webkit-text-security: disc` style whenever the field does not have focus, with a helper line underneath it (the `securityCodeDescription` message; a blank one 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. The typed code is cleared when the submission settles, by any route except that format refusal (which keeps it for the shopper to fix).
|
|
90
|
+
|
|
91
|
+
The code is readable while the field has focus and obscured when it does not, so a shopper can read back what they just typed and catch a typo, and nothing is left legible once they move on. No length is involved: a saved card carries no per-network security-code length (the row's data has a display network name, not a `cvvMask`), and a partial code is hidden on blur like a full one. Re-focusing a hidden code reveals it again, so a typo can be read and corrected. A disabled field counts as unfocused, because a browser fires no `blur` when a focused input becomes disabled, and the focus flag dies with the input when deselecting the row unmounts it. A caller's `onFocus` and `onBlur` still run: they are composed with the field's own. Same rule and same shared predicate (`isSecurityCodeMasked`) as `CardEntry`'s CVV field.
|
|
92
|
+
|
|
93
|
+
`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 — whenever the code is hidden the mask merges in last, so a caller's style can hold it off only while the field has focus, never while the code is obscured. 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).
|
|
94
|
+
|
|
95
|
+
No props beyond standard input attributes (`className`). **Content model** (`saved-card-cvv-field`): `securityCodeLabel` (accessible name) and `securityCodeDescription` (helper text). Must be inside `SavedCardOption`.
|
|
96
|
+
|
|
97
|
+
The input carries no `name` attribute, on purpose. Changing a field's signature without evidence was ruled out on 2026-08-14 (R1's T100 block, commit `d284f9736`) and no evidence has been produced since; a test pins the absence, so adding one later is a deliberate edit of that test.
|
|
98
|
+
|
|
99
|
+
### SavedCardRemove
|
|
100
|
+
|
|
101
|
+
A button that removes an expired saved card from the shopper's account and from the checkout list. It renders **only for an expired row**: a row whose card can still be used has no control, and a row whose data lacks the expired flag has none either. Its visible text is the `label` message; its accessible name starts with that text and adds the card (`Remove card Visa •••• 0002`), so several expired rows are not announced alike. The network and the digits drop out of the name when the row has none.
|
|
102
|
+
|
|
103
|
+
**Content model** (`saved-card-remove`): `label`, the visible text of the button, and `failureMessage`, shown in the row when the removal did not complete.
|
|
104
|
+
|
|
105
|
+
Activating it calls the `savedCard.remove` action once for that card and nothing else. When the action resolves with no errors the row leaves the list. When it resolves with errors, rejects, or is not wired, the row stays and a `role="alert"` paragraph (`data-fs-saved-card-remove-error`) shows the `failureMessage` message. The message is always the authored copy, never the server's text, and the next attempt clears it. While a removal is pending the button is `aria-busy` and `aria-disabled` (`data-fs-saved-card-remove-pending`), ignores further clicks and keeps focus: it is not `disabled`.
|
|
106
|
+
|
|
107
|
+
The action is `savedCard.remove`, which calls the `customerSavedCardRemove` mutation (`sdk/saved-cards/use-saved-card-actions.ts`). That mutation takes the account-side card id, the opaque `CustomerSavedCard` id. The checkout row is a different entity, `SavedCard`, with its own opaque id, so passing the row's id would be answered with `CARD_NOT_FOUND`. Both ids wrap the same platform `accountId`, so the control derives the account-side id from the row's `accountId` (base64 of `CustomerSavedCard:<accountId>`, the encoding of the server's `encodeOpaqueId`) and sends nothing else. A change in that encoding makes the server refuse the removal, which lands on the failure path below instead of removing the wrong card (`saved-cards.test.tsx` pins the exact id for a fixed `accountId`, including a non-ASCII one).
|
|
86
108
|
|
|
87
|
-
The
|
|
109
|
+
The action's own cache write updates the account's `CustomerSavedCards` entity, which the checkout list does not read, so a success changes nothing on screen by itself. The control therefore evicts the row's `SavedCard` entity from the Apollo cache and Apollo drops the dangling reference from `Payment.savedCards`: the row leaves every subscriber at once, with no refetch. Outside `SavedCards` there is no list-item ref to evict, so nothing leaves and no message shows. The eviction is local to the cache. If the platform still lists the card in the order form, a later response that returns the order form's saved cards writes the row again; whether the platform drops it was not measured against a live account.
|
|
88
110
|
|
|
89
|
-
|
|
111
|
+
The failure path is deliberately conservative. Only a resolution with an empty `userErrors` list counts as a removal; one or more errors, a rejection and a missing `savedCard.remove` action all leave the `SavedCard` entity untouched, so the card stays listed and the shopper never reads a failure as a success. The message is authored copy because a server message can carry text the store did not write. A caught rejection logs only the error's name, never the card or the thrown message. The pending button stays `aria-disabled` rather than `disabled` because a `disabled` button loses focus in browsers, which strands a keyboard user after a failed removal.
|
|
90
112
|
|
|
91
|
-
|
|
113
|
+
It never changes the selection: no payment method, no card and no draft is touched, whatever the outcome. There is no built-in confirmation step (a store adds one through `onClick`, below) and no success message, and the row's removal does not clear a persisted selection that names the card (an expired persisted selection already counts as no selection). Composing it in a store's page is a separate step: nothing shows it until the page adds it.
|
|
114
|
+
|
|
115
|
+
No props beyond standard button attributes (`className`, `onClick`). Must be inside `SavedCardOption`.
|
|
116
|
+
|
|
117
|
+
Every message of these components is read only from `$content`. A missing message renders empty and logs `message.missing`.
|
|
118
|
+
|
|
119
|
+
A store's `onClick` runs before the removal and can cancel it: call `event.preventDefault()` in it (for example when the shopper answers Cancel in the store's own confirmation dialog) and nothing is removed, no message is shown and the button does not go busy. A click while a removal is already pending is ignored, and the store's `onClick` does not run for it.
|
|
92
120
|
|
|
93
121
|
---
|
|
94
122
|
|
|
@@ -102,9 +130,10 @@ No props beyond standard input attributes (`className`), `securityCodeLabel` (ac
|
|
|
102
130
|
},
|
|
103
131
|
"saved-card-option": {
|
|
104
132
|
"type": "SavedCardOption",
|
|
105
|
-
"children": ["saved-card-cvv"]
|
|
133
|
+
"children": ["saved-card-cvv", "saved-card-remove"]
|
|
106
134
|
},
|
|
107
|
-
"saved-card-cvv": { "type": "SavedCardCvvField" }
|
|
135
|
+
"saved-card-cvv": { "type": "SavedCardCvvField" },
|
|
136
|
+
"saved-card-remove": { "type": "SavedCardRemove" }
|
|
108
137
|
}
|
|
109
138
|
```
|
|
110
139
|
|
|
@@ -136,20 +165,16 @@ No props beyond standard input attributes (`className`), `securityCodeLabel` (ac
|
|
|
136
165
|
|
|
137
166
|
- **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
167
|
- **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`.**
|
|
140
|
-
- **Placing `SavedCardOption` or `
|
|
141
|
-
- **
|
|
168
|
+
- **Omitting `SavedCardCvvField` inside `SavedCardOption`.** For a card that needs a security code, without it a shopper can select the card but the place-order flow has nothing to submit with — include it. A card that needs no code does not depend on it.
|
|
169
|
+
- **Placing `SavedCardOption`, `SavedCardCvvField` or `SavedCardRemove` outside their required ancestor.** `SavedCardOption` must be inside `SavedCards`; `SavedCardCvvField` and `SavedCardRemove` must be inside `SavedCardOption`. Only those two throw 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.
|
|
170
|
+
- **Reusing the account's `AccountSavedCardRemove` parts in the checkout list.** They need `AccountSavedCardsRoot` and the `CustomerSavedCard` entity, and a checkout row is neither. Compose `SavedCardRemove` there.
|
|
171
|
+
- **Expecting `SavedCardRemove` on a card that can still be used, or to ask for confirmation.** It renders only for an expired row and removes on the first activation unless the store's `onClick` cancels it with `preventDefault()`; there is no built-in confirmation. There is no prop to widen it to other cards.
|
|
172
|
+
- **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. No component in this block declares a `cvv`, `cardNumber`, or `bin` prop of any kind.
|
|
142
173
|
- **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
174
|
- **Wrapping `SavedCards` in a page with no `PaymentSectionRoot` ancestor.** It requires the payment context; use only inside a composed payment section.
|
|
144
175
|
|
|
145
176
|
---
|
|
146
177
|
|
|
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
178
|
## Styling
|
|
154
179
|
|
|
155
180
|
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.
|
|
@@ -158,12 +183,16 @@ Style `SavedCards` as a vertical stack of rows, each row as a horizontal line (r
|
|
|
158
183
|
|---|---|---|
|
|
159
184
|
| `SavedCards` | Stacks the rows | `flex flex-col gap-[8px] w-full` |
|
|
160
185
|
| 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-[
|
|
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-[
|
|
163
|
-
| `SavedCardCvvField` | The short CVV input | `w-[64px] text-[14px] px-[8px] py-[6px] border border-[
|
|
164
|
-
| CVV helper text (`data-fs-saved-card-cvv-description`) | Small muted line next to/under the CVV input | `text-[12px] text-[
|
|
186
|
+
| Legend (`data-fs-fieldset-legend`, native `<legend>`) | The group's visible name, from `legend` | `text-[14px] font-medium text-[var(--color-ink)]` |
|
|
187
|
+
| `SavedCardOption` | One row — indicator, network mark (`data-fs-saved-card-option-network-icon`), separators (`data-fs-saved-card-option-separator`), last four, label in a line; muted/dashed when expired | `flex items-center gap-[8px] p-[12px] border border-[color-mix(in_srgb,var(--color-ink)_20%,transparent)] rounded-[var(--radius-base)] data-[fs-saved-card-option-expired]:opacity-50 data-[fs-saved-card-option-selected]:border-[var(--color-primary)]` |
|
|
188
|
+
| `SavedCardCvvField` | The short CVV input | `w-[64px] text-[14px] px-[8px] py-[6px] border border-[color-mix(in_srgb,var(--color-ink)_20%,transparent)] rounded-[var(--radius-base)]` |
|
|
189
|
+
| CVV helper text (`data-fs-saved-card-cvv-description`) | Small muted line next to/under the CVV input | `text-[12px] text-[color-mix(in_srgb,var(--color-ink)_60%,transparent)]` |
|
|
190
|
+
| `SavedCardRemove` (`data-fs-saved-card-remove`, native `<button>`) | The remove control in an expired row; pending state is `data-fs-saved-card-remove-pending` | `text-[12px] underline data-[fs-saved-card-remove-pending]:opacity-60` |
|
|
191
|
+
| Remove failure (`data-fs-saved-card-remove-error`, `role="alert"`) | The message under a row whose removal did not complete | `text-[12px] font-medium` |
|
|
165
192
|
| Placing (`data-fs-saved-cards-placing`) | Present on `SavedCards`' own root while an order-placement sequence is in flight (T28), and while the order attempt is resume-only (its card may already have been sent, so the fields do not accept input) until the attempt is freed; 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
193
|
|
|
194
|
+
A status color is a `visualIdentity` feedback role of the foundation: when the store declares it, color the Remove failure row `text-[var(--color-feedback-danger)]`, never with a hex.
|
|
195
|
+
|
|
167
196
|
Styled example:
|
|
168
197
|
|
|
169
198
|
```json
|
|
@@ -178,14 +207,14 @@ Styled example:
|
|
|
178
207
|
"children": ["saved-card-cvv"],
|
|
179
208
|
"style": [
|
|
180
209
|
"flex", "items-center", "gap-[8px]", "p-[12px]",
|
|
181
|
-
"border", "border-[
|
|
210
|
+
"border", "border-[color-mix(in_srgb,var(--color-ink)_20%,transparent)]", "rounded-[var(--radius-base)]",
|
|
182
211
|
"data-[fs-saved-card-option-expired]:opacity-50",
|
|
183
|
-
"data-[fs-saved-card-option-selected]:border-[
|
|
212
|
+
"data-[fs-saved-card-option-selected]:border-[var(--color-primary)]"
|
|
184
213
|
]
|
|
185
214
|
},
|
|
186
215
|
"saved-card-cvv": {
|
|
187
216
|
"type": "SavedCardCvvField",
|
|
188
|
-
"style": ["w-[64px]", "text-[14px]", "px-[8px]", "py-[6px]", "border", "border-[
|
|
217
|
+
"style": ["w-[64px]", "text-[14px]", "px-[8px]", "py-[6px]", "border", "border-[color-mix(in_srgb,var(--color-ink)_20%,transparent)]", "rounded-[var(--radius-base)]"]
|
|
189
218
|
}
|
|
190
219
|
}
|
|
191
220
|
```
|
|
@@ -195,10 +224,10 @@ Styled example:
|
|
|
195
224
|
## Accessibility Contract
|
|
196
225
|
|
|
197
226
|
**What the platform promises:** `SavedCards`' radio group carries a visible, programmatic accessible
|
|
198
|
-
name (`legend
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
and masked last four; the CVV re-entry field carries its own `securityCodeLabel` as an `aria-label`
|
|
227
|
+
name (the `legend` message) — a screen-reader user hears these rows are a choice between stored
|
|
228
|
+
cards, not payment methods. A store that leaves `legend` unauthored ships a nameless group, and the
|
|
229
|
+
formatter logs `message.missing`. Each row keeps its own accessible name from its network
|
|
230
|
+
(the mark carries it as an `aria-label`) and masked last four, with the separators hidden from assistive tech; the CVV re-entry field carries its own `securityCodeLabel` as an `aria-label`
|
|
202
231
|
and, when `securityCodeDescription` is set, an `aria-describedby` association to the helper text. The
|
|
203
232
|
group is a native `<fieldset>`/`<legend>` pair, not only `aria-label`. Keyboard: the group is one Tab
|
|
204
233
|
stop — Tab lands on the checked row, and the arrow keys move the checked row and change the selection.
|
package/dist/docs/select.md
CHANGED
|
@@ -26,10 +26,9 @@ Signals that distinguish it from other controls:
|
|
|
26
26
|
- A **country/region selector** (ISO codes resolved to display names), a **sort-order dropdown**, or a
|
|
27
27
|
**quantity/unit picker** are the most common PDP/checkout uses.
|
|
28
28
|
|
|
29
|
-
This particle
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
visual pattern for a human reader; it is not wired into image→schema detection.
|
|
29
|
+
This particle is a leaf control with no distinct visual region of its own, and the bound `FieldSelect.*`
|
|
30
|
+
parts cannot be generated from a screenshot without the bound Control that consumes them
|
|
31
|
+
(`ShippingAddressCountryControl`). This section documents the visual pattern for a human reader.
|
|
33
32
|
|
|
34
33
|
---
|
|
35
34
|
|
|
@@ -11,11 +11,11 @@ Use these signals to detect that a ShippingAddress block is present. Position on
|
|
|
11
11
|
|
|
12
12
|
A ShippingAddress block contains any combination of:
|
|
13
13
|
|
|
14
|
-
- A **country dropdown** listing country names (e.g. "Brazil", "United States").
|
|
14
|
+
- A **country dropdown** listing country names (e.g. "Brazil", "United States", "Canada", "Mexico").
|
|
15
15
|
- Labeled **input fields** for street, number, city, state, and postal code.
|
|
16
16
|
- A **recipient name** field, often showing a pre-filled name as its value.
|
|
17
17
|
- An optional **"Complement"** field (apartment, suite, unit).
|
|
18
|
-
- A **"Neighborhood"** field — present only for Brazil-shaped forms, absent for US-shaped forms.
|
|
18
|
+
- A **"Neighborhood"** field — present only for Brazil- and Mexico-shaped forms, absent for US- and Canada-shaped forms.
|
|
19
19
|
- A **submit button** shared with the rest of the page's form, possibly showing a pending label while a write is in flight.
|
|
20
20
|
- An **error banner** showing domain validation messages or a generic failure state.
|
|
21
21
|
|
|
@@ -50,7 +50,7 @@ FormRoot
|
|
|
50
50
|
│ ├── StreetControl
|
|
51
51
|
│ ├── NumberControl
|
|
52
52
|
│ ├── ComplementControl
|
|
53
|
-
│ ├── NeighborhoodControl (renders only for countries whose descriptor includes it, e.g. Brazil)
|
|
53
|
+
│ ├── NeighborhoodControl (renders only for countries whose descriptor includes it, e.g. Brazil or Mexico)
|
|
54
54
|
│ ├── CityControl
|
|
55
55
|
│ └── StateControl / PostalCodeControl
|
|
56
56
|
├── FormError (sibling of the fieldset, not a child)
|
|
@@ -63,7 +63,7 @@ Child order reflects visual order — place Controls in the same sequence they a
|
|
|
63
63
|
|
|
64
64
|
- Every Control must be a descendant of `ShippingAddressFieldset` — each throws if rendered outside it.
|
|
65
65
|
- `ShippingAddressFieldset` must be a descendant of `FormRoot` — it throws its own named error otherwise.
|
|
66
|
-
- `NeighborhoodControl` renders `null` when the active country's descriptor omits it (e.g. United States
|
|
66
|
+
- `NeighborhoodControl` renders `null` when the active country's descriptor omits it (e.g. United States or Canada) — safe to include speculatively, but only place it in the schema if the target country is expected to show it.
|
|
67
67
|
- Only one `ShippingAddressFieldset` per `FormRoot`; a second one under the same `shippingAddress` namespace throws at mount.
|
|
68
68
|
|
|
69
69
|
---
|
|
@@ -78,9 +78,21 @@ Registers under the `shippingAddress` namespace with an ancestor `FormRoot`; ren
|
|
|
78
78
|
|------|------|---------|-------|
|
|
79
79
|
| `defaultCountry` | string | `"BRA"` | ISO alpha-3 country code used when no address exists yet |
|
|
80
80
|
| `skeletonCount` | number | `9` | Placeholder rows drawn while the address resolves. Set it to the number of Controls composed. |
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
|
|
82
|
+
**Content (`shipping-address-fieldset`):** message fields the store authors in `$content`; a missing one renders empty and logs `message.missing`.
|
|
83
|
+
|
|
84
|
+
| Field | Source (English) | Notes |
|
|
85
|
+
|-------|------------------|-------|
|
|
86
|
+
| `loadingLabel` | `Loading your delivery address` | Announced politely while the address resolves. Blank means no announcement. |
|
|
87
|
+
| `loadedLabel` | `Your delivery address is ready` | Announced politely once the Controls mount. Blank means no announcement. |
|
|
88
|
+
| `groupLabel` | `Your delivery address` | Accessible name of the `<fieldset>` group. Blank means no name is exposed. |
|
|
89
|
+
| `requiredMessage` | `{label} is required` | Shown under a required field left blank. `label` is that field's own label message. |
|
|
90
|
+
| `missingRecipientNameMessage` | `Enter the recipient's name.` | Shown by `FormError` for `MISSING_RECIPIENT_NAME`. |
|
|
91
|
+
| `invalidPostalCodeMessage` | `Enter a valid postal code.` | Shown by `FormError` for `INVALID_POSTAL_CODE`. |
|
|
92
|
+
| `invalidAddressMessage` | `Check the address and try again.` | Shown by `FormError` for `INVALID_ADDRESS`. |
|
|
93
|
+
| `genericErrorMessage` | `Unable to save your delivery address. Please try again.` | Shown by `FormError` for a network failure and for the refusals the shopper cannot fix: `MISSING_CART_CONTEXT`, `CART_NOT_FOUND`, `INVALID_SAVED_ADDRESS_ID`, `INVALID_COUNTRY_CODE`. |
|
|
94
|
+
|
|
95
|
+
A refused write reaches `FormError` worded from these fields, keyed on the error's `code`. The server's English `message` never shows: a code this fieldset has no field for, one a newer server added, shows `genericErrorMessage` and logs `message.unknown-code`.
|
|
84
96
|
|
|
85
97
|
**Data:** declares `fragment ShippingAddressFieldsetData on Query` (`shipping { address }` + `clientProfile { id firstName lastName }`), `fetchStrategy: 'reactive'`. The compiler merges it into the page query — no explicit `dataSources` entry needed.
|
|
86
98
|
|
|
@@ -93,25 +105,25 @@ Registers under the `shippingAddress` namespace with an ancestor `FormRoot`; ren
|
|
|
93
105
|
- Compose `FormSubmit` and `FormError` as siblings, not children — the fieldset renders no submit or error part.
|
|
94
106
|
- Only one `ShippingAddressFieldset` per `FormRoot`; a second one under the same `shippingAddress` namespace throws at mount.
|
|
95
107
|
|
|
96
|
-
**
|
|
108
|
+
**A control's text:** every field Control has its own content type, `shipping-address-<field>` (`-recipient-name`, `-street`, `-number`, `-complement`, `-neighborhood`, `-city`, `-state`, `-postal-code`, `-country`), with one `label` message field; `placeholder` stays a plain prop with no default. The descriptors hold no copy, so the store's locale is the form's language whatever country is selected. Wording that differs by country takes a `country` select argument (the active country's ISO alpha-3 code, one of `BRA`, `USA`, `CAN`, `MEX`, with an `other` case): `shipping-address-state › label` (`{country, select, CAN {province} other {state}}`), and `shipping-address-postal-code › label` and `invalidMessage` (`{country, select, USA {zip code} other {postal code}}`, `{country, select, USA {invalid zip code} other {invalid postal code}}`). The required message names the field with its label message, so a store renames the field in its message too. Country names in the selector come from `Intl.DisplayNames` in the store locale ("Brazil" in `en-US`, "Brasil" in `pt-BR`).
|
|
97
109
|
|
|
98
110
|
**Recomposing a control's anatomy:** every field Control declares `providesContext: 'field'` (RFC:503), so a `Field.*` part composed inside one is not a context-constraint-violation. Given children, a field Control renders them in place of its default `Field.Label` / `Field.Control` / `Field.Error` (or, for `CountryControl`, `Field.Label` / `FieldSelect.Root` / `Field.Error`) — useful to reorder the label against the input or insert an icon. The binding underneath is unchanged either way.
|
|
99
111
|
|
|
100
112
|
### RecipientNameControl
|
|
101
113
|
|
|
102
|
-
The recipient-name input. The only required field: submit is blocked while it is blank. Defaults from `clientProfile.firstName`/`lastName` (joined) as a real, editable value — not a placeholder hint — whenever the stored address has no recipient name yet; degrades to an empty required field when the profile has neither part. No props beyond `className`, `label
|
|
114
|
+
The recipient-name input. The only required field: submit is blocked while it is blank. Defaults from `clientProfile.firstName`/`lastName` (joined) as a real, editable value — not a placeholder hint — whenever the stored address has no recipient name yet; degrades to an empty required field when the profile has neither part. No props beyond `className`, `placeholder`; its label is `shipping-address-recipient-name › label`.
|
|
103
115
|
|
|
104
116
|
### StreetControl / NumberControl / CityControl / StateControl / PostalCodeControl / ComplementControl
|
|
105
117
|
|
|
106
|
-
Thin field Controls; each renders `null` when the active country's descriptor omits that field. `PostalCodeControl` is additionally client-validated against the active country's format (CEP for Brazil, ZIP/ZIP+4 for the United States) — a malformed value blocks submit even though the field is not required
|
|
118
|
+
Thin field Controls; each renders `null` when the active country's descriptor omits that field. `PostalCodeControl` is additionally client-validated against the active country's format (CEP for Brazil, ZIP/ZIP+4 for the United States, the library's own rule for Canada and Mexico) — a malformed value blocks submit even though the field is not required, and shows `shipping-address-postal-code › invalidMessage`. No props beyond `className`, `placeholder`.
|
|
107
119
|
|
|
108
120
|
### NeighborhoodControl
|
|
109
121
|
|
|
110
|
-
Same shape as the other field Controls. Renders only for countries whose descriptor includes a neighborhood field (Brazil
|
|
122
|
+
Same shape as the other field Controls. Renders only for countries whose descriptor includes a neighborhood field (Brazil and Mexico); renders `null` for others (United States and Canada). Its draft value is retained (not cleared) when hidden, so it reappears with the same value if the shopper switches back to a country that shows it.
|
|
111
123
|
|
|
112
124
|
### CountryControl
|
|
113
125
|
|
|
114
|
-
Country selector. Lists only countries with
|
|
126
|
+
Country selector. Lists only countries with a descriptor — Brazil and the United States, written in the descriptor table, then Canada and Mexico once their rules have loaded from `@vtex/country-forms` — a descriptor-less country is unreachable. A stored or default `CAN` or `MEX` address keeps the fieldset in its skeleton until that country has loaded. Switching country preserves the values of fields the two descriptors share (keyed by canonical field name) and only adds/removes country-specific fields. No props beyond `className`, `placeholder` (absent, the trigger shows the active country's name).
|
|
115
127
|
|
|
116
128
|
---
|
|
117
129
|
|
|
@@ -127,6 +139,16 @@ The nine field Controls, batched behind a form-level submit:
|
|
|
127
139
|
},
|
|
128
140
|
"shipping-address-fieldset": {
|
|
129
141
|
"type": "ShippingAddressFieldset",
|
|
142
|
+
"props": {
|
|
143
|
+
"loadingLabel": "Loading your delivery address",
|
|
144
|
+
"loadedLabel": "Your delivery address is ready",
|
|
145
|
+
"groupLabel": "Your delivery address",
|
|
146
|
+
"requiredMessage": "{label} is required",
|
|
147
|
+
"missingRecipientNameMessage": "Enter the recipient's name.",
|
|
148
|
+
"invalidPostalCodeMessage": "Enter a valid postal code.",
|
|
149
|
+
"invalidAddressMessage": "Check the address and try again.",
|
|
150
|
+
"genericErrorMessage": "Unable to save your delivery address. Please try again."
|
|
151
|
+
},
|
|
130
152
|
"children": [
|
|
131
153
|
"fieldset-country",
|
|
132
154
|
"fieldset-recipient",
|
|
@@ -139,15 +161,27 @@ The nine field Controls, batched behind a form-level submit:
|
|
|
139
161
|
"fieldset-postal-code"
|
|
140
162
|
]
|
|
141
163
|
},
|
|
142
|
-
"fieldset-country": { "type": "ShippingAddressCountryControl" },
|
|
143
|
-
"fieldset-recipient": { "type": "ShippingAddressRecipientNameControl" },
|
|
144
|
-
"fieldset-street": { "type": "ShippingAddressStreetControl" },
|
|
145
|
-
"fieldset-number": { "type": "ShippingAddressNumberControl" },
|
|
146
|
-
"fieldset-complement": {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
"fieldset-
|
|
164
|
+
"fieldset-country": { "type": "ShippingAddressCountryControl", "props": { "label": "country" } },
|
|
165
|
+
"fieldset-recipient": { "type": "ShippingAddressRecipientNameControl", "props": { "label": "recipient name" } },
|
|
166
|
+
"fieldset-street": { "type": "ShippingAddressStreetControl", "props": { "label": "street" } },
|
|
167
|
+
"fieldset-number": { "type": "ShippingAddressNumberControl", "props": { "label": "number" } },
|
|
168
|
+
"fieldset-complement": {
|
|
169
|
+
"type": "ShippingAddressComplementControl",
|
|
170
|
+
"props": { "label": "apartment, suite, etc. (optional)" }
|
|
171
|
+
},
|
|
172
|
+
"fieldset-neighborhood": { "type": "ShippingAddressNeighborhoodControl", "props": { "label": "neighborhood" } },
|
|
173
|
+
"fieldset-city": { "type": "ShippingAddressCityControl", "props": { "label": "city" } },
|
|
174
|
+
"fieldset-state": {
|
|
175
|
+
"type": "ShippingAddressStateControl",
|
|
176
|
+
"props": { "label": "{country, select, CAN {province} other {state}}" }
|
|
177
|
+
},
|
|
178
|
+
"fieldset-postal-code": {
|
|
179
|
+
"type": "ShippingAddressPostalCodeControl",
|
|
180
|
+
"props": {
|
|
181
|
+
"label": "{country, select, USA {zip code} other {postal code}}",
|
|
182
|
+
"invalidMessage": "{country, select, USA {invalid zip code} other {invalid postal code}}"
|
|
183
|
+
}
|
|
184
|
+
},
|
|
151
185
|
"form-error": { "type": "FormError" },
|
|
152
186
|
"form-submit": { "type": "FormSubmit", "props": { "label": "Continue" } }
|
|
153
187
|
}
|
|
@@ -155,6 +189,8 @@ The nine field Controls, batched behind a form-level submit:
|
|
|
155
189
|
|
|
156
190
|
### Minimal variant (manual entry only)
|
|
157
191
|
|
|
192
|
+
The variants below leave out the message fields for brevity; author them on each element as the canonical example does.
|
|
193
|
+
|
|
158
194
|
```json
|
|
159
195
|
{
|
|
160
196
|
"checkout-form": {
|
|
@@ -45,9 +45,9 @@ The context distinguishes three states via `shippingOptions`:
|
|
|
45
45
|
- **`[]`** — a simulation ran and returned an empty list. `Empty` renders its message; `Options` renders nothing.
|
|
46
46
|
- **`[...]`** — options available. `Options` renders one `Option` per row; `Empty` renders nothing.
|
|
47
47
|
|
|
48
|
-
`ShippingSimulatorError`
|
|
48
|
+
`ShippingSimulatorError` words the first `userError` by its code from its own fields, never from the error's `message`: `INVALID_POSTAL_CODE` → `invalidPostalCode`, `UNKNOWN` → `genericErrorMessage`, `CALCULATION_FAILED` → `calculationFailed`. The default hooks keep `INVALID_POSTAL_CODE` and collapse every other server code and every transport failure into `UNKNOWN`. When `onSimulate` rejects, the Root records a client-side `CALCULATION_FAILED` error with an empty `message` (`onResult` receives it as is). A code outside the three (a store's own `onSimulate`) shows its `message`; composed `children` replace the message.
|
|
49
49
|
|
|
50
|
-
`Empty` renders **only** for `[]` with no `userErrors` — so it never flashes on first paint, and an error path defers to `ShippingSimulatorError`. Its copy
|
|
50
|
+
`Empty` renders **only** for `[]` with no `userErrors` — so it never flashes on first paint, and an error path defers to `ShippingSimulatorError`. Its copy is its `text` field, and `children` overrides it. It renders a polite live region (an `<output aria-live="polite">`, matching `Loading`), so it is announced when it appears.
|
|
51
51
|
|
|
52
52
|
---
|
|
53
53
|
|
|
@@ -58,14 +58,14 @@ CartShippingSimulatorRoot ← whole-cart calculator (no fragment, no Ca
|
|
|
58
58
|
├── ShippingSimulatorForm ← wraps input + submit
|
|
59
59
|
│ ├── ShippingSimulatorInput props: format (auto-hyphenate CEP)
|
|
60
60
|
│ └── ShippingSimulatorSubmit children: "Calcular"
|
|
61
|
-
├── ShippingSimulatorLoading ← shows while a simulation is pending
|
|
61
|
+
├── ShippingSimulatorLoading ← shows while a simulation is pending
|
|
62
62
|
├── ShippingSimulatorError ← shows a validation/transport error
|
|
63
63
|
├── ShippingSimulatorOptions ← renders one Option per available option
|
|
64
64
|
│ │ props: sortBy ("price" | "estimate"), maxOptions
|
|
65
65
|
│ └── ShippingSimulatorOption
|
|
66
66
|
│ ├── ShippingSimulatorOptionName
|
|
67
|
-
│ ├── ShippingSimulatorOptionEstimate ← one whole sentence per unit
|
|
68
|
-
│ └── ShippingSimulatorOptionPrice ←
|
|
67
|
+
│ ├── ShippingSimulatorOptionEstimate ← one whole sentence per unit
|
|
68
|
+
│ └── ShippingSimulatorOptionPrice ← its `freeLabel` when the amount is 0
|
|
69
69
|
└── ShippingSimulatorEmpty ← shows only when a simulation returned []
|
|
70
70
|
```
|
|
71
71
|
|
|
@@ -77,11 +77,28 @@ The PDP composition is identical, with `ShippingSimulatorRoot` in place of `Cart
|
|
|
77
77
|
|---|---|---|
|
|
78
78
|
| `ShippingSimulatorRoot` | `country`, `quantity` | PDP Root; carries a product fragment + `fetchStrategy: 'reactive'`; needs a `$slug` page |
|
|
79
79
|
| `CartShippingSimulatorRoot` | `country` | Cart Root; no fragment, no `fetchStrategy`, no `CartRoot` ancestor; submits `{ postalCode, country }` only |
|
|
80
|
-
| `ShippingSimulatorInput` | `format` | `format` auto-hyphenates the CEP (01310-100). The
|
|
80
|
+
| `ShippingSimulatorInput` | `format` | `format` auto-hyphenates the CEP (01310-100). The `aria-label` and the placeholder are its `ariaLabel` and `placeholder` fields; neither is a prop |
|
|
81
81
|
| `ShippingSimulatorOptions` | `sortBy`, `maxOptions` | Both optional; omitted = every option in API order. `sortBy="price"` orders cheapest first, `"estimate"` fastest first (business days weigh as calendar days); `maxOptions` caps the rendered rows — `sortBy="price"` + `maxOptions=1` shows only the cheapest option. Works identically under either Root |
|
|
82
|
-
| `ShippingSimulatorOptionEstimate` | — | One whole sentence per unit (`
|
|
83
|
-
| `ShippingSimulatorOptionPrice` | — | Renders `
|
|
84
|
-
| `ShippingSimulatorEmpty` | — | Renders only for a simulated-empty result
|
|
82
|
+
| `ShippingSimulatorOptionEstimate` | — | One whole sentence per unit (`inBusinessDays`, `inDays`, `inHours`, `inMinutes`), so the plural agrees with the locale; a zero value reads `today`. `children` overrides it |
|
|
83
|
+
| `ShippingSimulatorOptionPrice` | — | Renders `freeLabel` when the amount is 0; otherwise formats via `Intl` from the active storefront context. `children` overrides it |
|
|
84
|
+
| `ShippingSimulatorEmpty` | — | Renders only for a simulated-empty result; `children` overrides it |
|
|
85
|
+
|
|
86
|
+
Each part with copy reads it only from its own `$content`, whose fields are ICU messages. A missing message renders empty and logs an error. `children` replaces the copy of `Loading`, `Error`, `OptionEstimate`, `OptionPrice`, `OptionFreeBadge` and `Empty`, and then no message is formatted.
|
|
87
|
+
|
|
88
|
+
| Component | Content type | Content fields |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `ShippingSimulatorInput` | `shipping-simulator-input` | ariaLabel, placeholder |
|
|
91
|
+
| `ShippingSimulatorLoading` | `shipping-simulator-loading` | text |
|
|
92
|
+
| `ShippingSimulatorError` | `shipping-simulator-error` | calculationFailed, invalidPostalCode, genericErrorMessage |
|
|
93
|
+
| `ShippingSimulatorOptionEstimate` | `shipping-simulator-option-estimate` | today, inBusinessDays, inDays (plural on `days`), inHours (`hours`), inMinutes (`minutes`) |
|
|
94
|
+
| `ShippingSimulatorOptionPrice` | `shipping-simulator-option-price` | freeLabel |
|
|
95
|
+
| `ShippingSimulatorOptionFreeBadge` | `shipping-simulator-option-free-badge` | text |
|
|
96
|
+
| `ShippingSimulatorEmpty` | `shipping-simulator-empty` | text |
|
|
97
|
+
| `DeliveryOptionsRoot` / `DeliveryOptionsList` | `delivery-options-root` / `delivery-options-list` | optionUnavailableMessage (`OPTION_UNAVAILABLE`), missingAddressMessage (`MISSING_SHIPPING_ADDRESS`), genericErrorMessage (`NETWORK_ERROR`, `MISSING_CART_CONTEXT`, `CART_NOT_FOUND`): the inline selection error; an unknown code shows genericErrorMessage |
|
|
98
|
+
| `DeliveryOptionsAccordion` | `delivery-options-accordion` | placeholder (the trigger while nothing is selected), freeLabel (the trigger echo of a free selected option), and the same three selection-error fields as `delivery-options-root` |
|
|
99
|
+
| `DeliveryOptionsSummary` | `delivery-options-summary` | placeholder (the summary while nothing is selected), freeLabel (the summary echo of a free selected option) |
|
|
100
|
+
|
|
101
|
+
The delivery-options echoes reuse `ShippingSimulatorOptionPrice` and word a free price with their own `freeLabel`, never with the price part's.
|
|
85
102
|
|
|
86
103
|
Prices format from the **active storefront context's currency** (not the payload `currencyCode`); the binding's currency must match the payload currency.
|
|
87
104
|
|
|
@@ -112,11 +129,18 @@ Place the calculator inside `cart-filled` (an empty cart has nothing to ship), b
|
|
|
112
129
|
},
|
|
113
130
|
"cart-shipping-input": {
|
|
114
131
|
"type": "ShippingSimulatorInput",
|
|
115
|
-
"props": { "format": true }
|
|
132
|
+
"props": { "format": true, "ariaLabel": "CEP", "placeholder": "Digite seu CEP" }
|
|
116
133
|
},
|
|
117
134
|
"cart-shipping-submit": { "type": "ShippingSimulatorSubmit", "props": { "children": "Calcular" } },
|
|
118
|
-
"cart-shipping-loading": { "type": "ShippingSimulatorLoading" },
|
|
119
|
-
"cart-shipping-error": {
|
|
135
|
+
"cart-shipping-loading": { "type": "ShippingSimulatorLoading", "props": { "text": "Calculando…" } },
|
|
136
|
+
"cart-shipping-error": {
|
|
137
|
+
"type": "ShippingSimulatorError",
|
|
138
|
+
"props": {
|
|
139
|
+
"calculationFailed": "Não foi possível calcular o frete. Tente novamente.",
|
|
140
|
+
"invalidPostalCode": "CEP inválido. Verifique e tente novamente.",
|
|
141
|
+
"genericErrorMessage": "Não foi possível calcular o frete. Tente novamente."
|
|
142
|
+
}
|
|
143
|
+
},
|
|
120
144
|
"cart-shipping-options": {
|
|
121
145
|
"type": "ShippingSimulatorOptions",
|
|
122
146
|
"children": ["cart-shipping-option"]
|
|
@@ -126,12 +150,26 @@ Place the calculator inside `cart-filled` (an empty cart has nothing to ship), b
|
|
|
126
150
|
"children": ["cart-shipping-option-name", "cart-shipping-option-estimate", "cart-shipping-option-price"]
|
|
127
151
|
},
|
|
128
152
|
"cart-shipping-option-name": { "type": "ShippingSimulatorOptionName" },
|
|
129
|
-
"cart-shipping-option-estimate": {
|
|
130
|
-
|
|
131
|
-
|
|
153
|
+
"cart-shipping-option-estimate": {
|
|
154
|
+
"type": "ShippingSimulatorOptionEstimate",
|
|
155
|
+
"props": {
|
|
156
|
+
"today": "vai ser entregue hoje",
|
|
157
|
+
"inBusinessDays": "em {days, plural, one {# dia útil} other {# dias úteis}}",
|
|
158
|
+
"inDays": "em {days, plural, one {# dia} other {# dias}}",
|
|
159
|
+
"inHours": "em {hours, plural, one {# hora} other {# horas}}",
|
|
160
|
+
"inMinutes": "em {minutes, plural, one {# minuto} other {# minutos}}"
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
"cart-shipping-option-price": { "type": "ShippingSimulatorOptionPrice", "props": { "freeLabel": "Grátis" } },
|
|
164
|
+
"cart-shipping-empty": {
|
|
165
|
+
"type": "ShippingSimulatorEmpty",
|
|
166
|
+
"props": { "text": "Nenhuma opção de entrega disponível para este endereço." }
|
|
167
|
+
}
|
|
132
168
|
}
|
|
133
169
|
```
|
|
134
170
|
|
|
171
|
+
A store without CMS authors the message fields on the element, as above; a CMS-bound store keeps them in content.
|
|
172
|
+
|
|
135
173
|
### Product page preview (single product)
|
|
136
174
|
|
|
137
175
|
Identical shape, with `ShippingSimulatorRoot` as the Root and `quantity` available as a prop. It lives on a PDP where a `$slug` variable resolves the product fragment.
|