@vtex/faststore 0.0.10 → 0.0.12
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 +55 -0
- package/README.md +0 -1
- package/dist/_virtual/_rolldown/runtime.js +4 -0
- package/dist/actions.json +6 -1
- package/dist/catalog.json +789 -1701
- 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 +63 -57
- package/dist/components.js +60 -54
- package/dist/content-types.json +5785 -754
- package/dist/core/dist/define-component.d.ts +1 -1
- 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-menu.md +14 -15
- package/dist/docs/account-saved-cards.md +44 -39
- 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 +5 -2
- package/dist/docs/buy-button.md +7 -8
- package/dist/docs/card-entry.md +39 -26
- package/dist/docs/card-summary.md +18 -8
- package/dist/docs/cardholder-document.md +5 -3
- package/dist/docs/carousel.md +5 -4
- package/dist/docs/cart-destination.md +39 -26
- package/dist/docs/cart-item.md +29 -14
- package/dist/docs/cart-totalizer.md +7 -5
- package/dist/docs/cart.md +135 -41
- 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/form.md +54 -18
- package/dist/docs/free-shipping-progress.md +6 -5
- package/dist/docs/identity-edit.md +8 -2
- package/dist/docs/identity-summary.md +18 -5
- package/dist/docs/installments.md +46 -32
- 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 +30 -4
- package/dist/docs/payment-methods.md +1 -1
- 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 +13 -9
- package/dist/docs/product-list.md +7 -6
- package/dist/docs/product-shelf.md +0 -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/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 +4 -2
- package/dist/docs/sign-in.md +173 -0
- package/dist/docs/toast.md +15 -4
- package/dist/docs/variant-selector.md +15 -11
- package/dist/domain-logic/dist/checkout/rules.js +33 -0
- package/dist/domain-logic/dist/checkout/rules.js.map +1 -0
- package/dist/graphql/types.d.ts +4 -14
- package/dist/index.d.ts +2 -2
- package/dist/internal/client.d.ts +1 -3
- package/dist/internal/client.js +1 -1
- package/dist/internal/server.d.ts +7 -4
- package/dist/internal/server.js +7 -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 +108 -28
- package/dist/matter/account-saved-cards/account-saved-cards.js +177 -122
- package/dist/matter/account-saved-cards/account-saved-cards.js.map +1 -1
- 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 +7 -1
- package/dist/matter/cart/cart-namespace.js +7 -1
- package/dist/matter/cart/cart-namespace.js.map +1 -1
- package/dist/matter/cart/cart.d.ts +402 -61
- package/dist/matter/cart/cart.js +624 -153
- package/dist/matter/cart/cart.js.map +1 -1
- package/dist/matter/cart-destination/cart-destination.d.ts +30 -19
- package/dist/matter/cart-destination/cart-destination.js +160 -70
- package/dist/matter/cart-destination/cart-destination.js.map +1 -1
- package/dist/matter/cart-item/cart-item.d.ts +144 -17
- package/dist/matter/cart-item/cart-item.js +166 -49
- 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 +46 -17
- 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 +79 -7
- package/dist/matter/free-shipping-progress/free-shipping-progress.js +77 -20
- 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 +1 -3
- package/dist/matter/product-shelf/product-shelf.js +2 -15
- 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 +250 -24
- package/dist/matter/shipping-simulator/shipping-simulator.js +257 -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 +29 -8
- package/dist/particles/binding-switcher/binding-switcher.js +37 -26
- package/dist/particles/binding-switcher/binding-switcher.js.map +1 -1
- package/dist/particles/card-summary/card-summary.d.ts +38 -8
- package/dist/particles/card-summary/card-summary.js +55 -22
- package/dist/particles/card-summary/card-summary.js.map +1 -1
- 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/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/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/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 +29 -3
- package/dist/particles/toast/toast.js +34 -10
- package/dist/particles/toast/toast.js.map +1 -1
- package/dist/schema.graphql +164 -56
- 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/cart/use-cart-actions.js.map +1 -1
- 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 +1 -1
- package/dist/sdk/generated/gql.js.map +1 -1
- package/dist/sdk/generated/graphql.d.ts +20 -5
- package/dist/sdk/generated/graphql.js +6 -0
- 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/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 +21 -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 -4
- 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/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 +3 -2
- package/dist/sdk/seo/page-alternates.js +4 -2
- 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/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/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 +8 -0
- 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 -183
- package/dist/sdk/i18n/messages/en-US.js.map +0 -1
- package/dist/sdk/i18n/messages/en-US.json +0 -178
- package/dist/sdk/i18n/messages/en-US.json.d.ts +0 -182
- package/dist/sdk/i18n/messages/es-ES.js +0 -183
- package/dist/sdk/i18n/messages/es-ES.js.map +0 -1
- package/dist/sdk/i18n/messages/es-ES.json +0 -178
- package/dist/sdk/i18n/messages/pt-BR.js +0 -183
- package/dist/sdk/i18n/messages/pt-BR.js.map +0 -1
- package/dist/sdk/i18n/messages/pt-BR.json +0 -178
- 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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ShippingOption } from "../shipping-simulator/shipping-simulator.js";
|
|
2
|
+
import "../../sdk/shipping/option-select-operations.js";
|
|
2
3
|
import "../../sdk/actions/types.js";
|
|
3
4
|
//#region src/matter/delivery-options/use-delivery-option-selection.d.ts
|
|
4
5
|
export type RawDeliveryOptionsData = {
|
|
@@ -49,7 +49,7 @@ function useDeliveryOptionSelection({ $data: $dataProp, $actions, mockOptions })
|
|
|
49
49
|
if (selectionToken.current !== token) return;
|
|
50
50
|
const [firstError] = userErrors;
|
|
51
51
|
if (firstError) {
|
|
52
|
-
setSelectionError(firstError
|
|
52
|
+
setSelectionError(firstError);
|
|
53
53
|
callbacks?.onSettled?.(false);
|
|
54
54
|
} else callbacks?.onSettled?.(true);
|
|
55
55
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-delivery-option-selection.js","names":[],"sources":["../../../src/matter/delivery-options/use-delivery-option-selection.ts"],"sourcesContent":["'use client';\n\nimport { useMemo, useRef, useState } from 'react';\nimport type { ComponentActions } from '../../sdk/actions/types.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport type { ShippingOption, ShippingSimulatorContextValue } from '../shipping-simulator/shipping-simulator.js';\n\n// ---------------------------------------------------------------------------\n// Raw data type (shape of the reactive fragment result). `$data` is the unwrapped\n// `Shipping` entity the reactive runtime forwards (Decision 7 / INV-7), not `{ shipping: … }`.\n// Shared by DeliveryOptionsRoot and its collapsed variants (Accordion/Dialog/Drawer), all of\n// which read the same `shipping { options … selectedOptionId }` selection.\n// ---------------------------------------------------------------------------\n\nexport type RawDeliveryOptionsData = {\n options: ShippingOption[];\n selectedOptionId: string | null;\n};\n\nconst EMPTY_OPTIONS: ShippingOption[] = [];\n\n/**\n * Joins the structural classes a collapsed variant always applies (positioning, sizing, animation)\n * with the page-supplied visual override, dropping empty slots. Keeps the visual layer out of the\n * component (Free Particle Model) while guaranteeing the overlay still positions itself.\n */\nexport function cx(...classes: Array<string | undefined>): string {\n return classes.filter(Boolean).join(' ');\n}\n\nexport type DeliveryOptionSelection = {\n /** Real options when the fetch has any, else the `mockOptions` fallback, else empty. */\n options: ShippingOption[];\n /** Group value: the persisted `selectedOptionId` for real data, local state under mock. */\n selectedOptionId: string | null;\n /** True while the mock fallback is showing (no real options + `mockOptions` present). */\n usingMockOptions: boolean;\n /**
|
|
1
|
+
{"version":3,"file":"use-delivery-option-selection.js","names":[],"sources":["../../../src/matter/delivery-options/use-delivery-option-selection.ts"],"sourcesContent":["'use client';\n\nimport { useMemo, useRef, useState } from 'react';\nimport type { ComponentActions } from '../../sdk/actions/types.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport type { ShippingOptionSelectUserError } from '../../sdk/shipping/option-select-operations.js';\nimport type { ShippingOption, ShippingSimulatorContextValue } from '../shipping-simulator/shipping-simulator.js';\n\n// ---------------------------------------------------------------------------\n// Raw data type (shape of the reactive fragment result). `$data` is the unwrapped\n// `Shipping` entity the reactive runtime forwards (Decision 7 / INV-7), not `{ shipping: … }`.\n// Shared by DeliveryOptionsRoot and its collapsed variants (Accordion/Dialog/Drawer), all of\n// which read the same `shipping { options … selectedOptionId }` selection.\n// ---------------------------------------------------------------------------\n\nexport type RawDeliveryOptionsData = {\n options: ShippingOption[];\n selectedOptionId: string | null;\n};\n\nconst EMPTY_OPTIONS: ShippingOption[] = [];\n\n/**\n * The codes a selection can resolve: `ShippingOptionSelectErrorCode` (the sdk types `code` as a string)\n * plus the client-minted transport failure. Each surface words them from its own `$content`.\n */\nexport type DeliveryOptionSelectErrorCode =\n | 'MISSING_CART_CONTEXT'\n | 'CART_NOT_FOUND'\n | 'OPTION_UNAVAILABLE'\n | 'MISSING_SHIPPING_ADDRESS'\n | 'NETWORK_ERROR';\n\n/**\n * Joins the structural classes a collapsed variant always applies (positioning, sizing, animation)\n * with the page-supplied visual override, dropping empty slots. Keeps the visual layer out of the\n * component (Free Particle Model) while guaranteeing the overlay still positions itself.\n */\nexport function cx(...classes: Array<string | undefined>): string {\n return classes.filter(Boolean).join(' ');\n}\n\nexport type DeliveryOptionSelection = {\n /** Real options when the fetch has any, else the `mockOptions` fallback, else empty. */\n options: ShippingOption[];\n /** Group value: the persisted `selectedOptionId` for real data, local state under mock. */\n selectedOptionId: string | null;\n /** True while the mock fallback is showing (no real options + `mockOptions` present). */\n usingMockOptions: boolean;\n /** The first `userError` from the latest real selection, or `null`. */\n selectionError: ShippingOptionSelectUserError | null;\n /**\n * Selects an option. Under mock data the choice is local-only and never dispatches the action.\n * Under real data it dispatches `shipping.selectOption`, request-sequenced so only the latest\n * click wins the error state. `onSettled(ok)` fires once the selection resolves — `ok` is `false`\n * when the mutation surfaced a `userError` (or no action was injected) — letting collapsed\n * variants close only on success.\n */\n selectOption: (optionId: string, callbacks?: { onSettled?: (ok: boolean) => void }) => void;\n /** The FSPG-832 simulator context value (inert simulation fields) providers must supply. */\n contextValue: ShippingSimulatorContextValue;\n};\n\n/**\n * Shared selection engine behind `DeliveryOptionsRoot` and its collapsed variants\n * (`DeliveryOptionsAccordion` / `Dialog` / `Drawer`). It owns the four behaviours the spec\n * requires identically across every surface, so they cannot drift apart:\n *\n * - real-vs-mock option resolution — real options of any length always win (INV-8);\n * - the local mock selection, reset whenever the real↔mock boundary flips so a stale mock\n * choice from before a real-options interlude never reappears (Decision 7);\n * - the reactive `selectedOptionId` binding (Decision 5 — no local state for real data);\n * - the request-sequenced `selectOption` dispatch that resolves `userErrors` for inline display\n * (US-4), guarding against an earlier click's result overwriting a later one.\n *\n * Callers render `selectionError` (as `role=\"alert\"`) and wire `contextValue` themselves; the\n * collapsed variants additionally use `onSettled` to close their panel only on success.\n */\nexport function useDeliveryOptionSelection({\n $data: $dataProp,\n $actions,\n mockOptions,\n}: {\n $data?: RawDeliveryOptionsData | null;\n $actions?: ComponentActions;\n mockOptions?: ShippingOption[];\n}): DeliveryOptionSelection {\n const $data = useDataOverride($dataProp);\n const realOptions = $data?.options;\n const usingMockOptions = !realOptions?.length && !!mockOptions?.length;\n const options = realOptions?.length ? realOptions : (mockOptions ?? EMPTY_OPTIONS);\n\n const [mockSelectedOptionId, setMockSelectedOptionId] = useState<string | null>(null);\n const [wasUsingMockOptions, setWasUsingMockOptions] = useState(usingMockOptions);\n if (usingMockOptions !== wasUsingMockOptions) {\n setWasUsingMockOptions(usingMockOptions);\n setMockSelectedOptionId(null);\n }\n const selectedOptionId = usingMockOptions ? mockSelectedOptionId : ($data?.selectedOptionId ?? null);\n\n const [selectionError, setSelectionError] = useState<ShippingOptionSelectUserError | null>(null);\n const selectionToken = useRef(0);\n\n function selectOption(optionId: string, callbacks?: { onSettled?: (ok: boolean) => void }) {\n if (usingMockOptions) {\n setMockSelectedOptionId(optionId);\n callbacks?.onSettled?.(true);\n return;\n }\n setSelectionError(null);\n const dispatch = $actions?.shipping?.selectOption;\n if (!dispatch) {\n callbacks?.onSettled?.(false);\n return;\n }\n const token = ++selectionToken.current;\n dispatch(optionId).then((userErrors) => {\n if (selectionToken.current !== token) return;\n const [firstError] = userErrors;\n if (firstError) {\n setSelectionError(firstError);\n callbacks?.onSettled?.(false);\n } else {\n callbacks?.onSettled?.(true);\n }\n });\n }\n\n const contextValue = useMemo<ShippingSimulatorContextValue>(\n () => ({\n postalCode: '',\n setPostalCode: () => {},\n status: 'idle',\n shippingOptions: options,\n userErrors: [],\n submit: () => {},\n }),\n [options],\n );\n\n return { options, selectedOptionId, usingMockOptions, selectionError, selectOption, contextValue };\n}\n"],"mappings":";;;;AAoBA,MAAM,gBAAkC,CAAC;;;;;;;;;;;;;;;;AA0DzC,SAAgB,2BAA2B,EACzC,OAAO,WACP,UACA,eAK0B;CAC1B,MAAM,QAAQ,gBAAgB,SAAS;CACvC,MAAM,cAAc,OAAO;CAC3B,MAAM,mBAAmB,CAAC,aAAa,UAAU,CAAC,CAAC,aAAa;CAChE,MAAM,UAAU,aAAa,SAAS,cAAe,eAAe;CAEpE,MAAM,CAAC,sBAAsB,2BAA2B,SAAwB,IAAI;CACpF,MAAM,CAAC,qBAAqB,0BAA0B,SAAS,gBAAgB;CAC/E,IAAI,qBAAqB,qBAAqB;EAC5C,uBAAuB,gBAAgB;EACvC,wBAAwB,IAAI;CAC9B;CACA,MAAM,mBAAmB,mBAAmB,uBAAwB,OAAO,oBAAoB;CAE/F,MAAM,CAAC,gBAAgB,qBAAqB,SAA+C,IAAI;CAC/F,MAAM,iBAAiB,OAAO,CAAC;CAE/B,SAAS,aAAa,UAAkB,WAAmD;EACzF,IAAI,kBAAkB;GACpB,wBAAwB,QAAQ;GAChC,WAAW,YAAY,IAAI;GAC3B;EACF;EACA,kBAAkB,IAAI;EACtB,MAAM,WAAW,UAAU,UAAU;EACrC,IAAI,CAAC,UAAU;GACb,WAAW,YAAY,KAAK;GAC5B;EACF;EACA,MAAM,QAAQ,EAAE,eAAe;EAC/B,SAAS,QAAQ,CAAC,CAAC,MAAM,eAAe;GACtC,IAAI,eAAe,YAAY,OAAO;GACtC,MAAM,CAAC,cAAc;GACrB,IAAI,YAAY;IACd,kBAAkB,UAAU;IAC5B,WAAW,YAAY,KAAK;GAC9B,OACE,WAAW,YAAY,IAAI;EAE/B,CAAC;CACH;CAcA,OAAO;EAAE;EAAS;EAAkB;EAAkB;EAAgB;EAAc,cAZ/D,eACZ;GACL,YAAY;GACZ,qBAAqB,CAAC;GACtB,QAAQ;GACR,iBAAiB;GACjB,YAAY,CAAC;GACb,cAAc,CAAC;EACjB,IACA,CAAC,OAAO,CAGqF;CAAE;AACnG"}
|
|
@@ -1,19 +1,40 @@
|
|
|
1
|
+
import { ContentValue, MessageLocaleProp } from "../../core/dist/define-content-type.js";
|
|
1
2
|
import { ComponentDefinition } from "../../core/dist/define-component.js";
|
|
2
3
|
import "../../core/dist/index.js";
|
|
3
4
|
import { ComponentActions } from "../../sdk/actions/types.js";
|
|
4
5
|
import { ComponentPropsWithRef } from "react";
|
|
5
6
|
//#region src/matter/email-identification/email-identification.d.ts
|
|
7
|
+
export declare const EmailIdentificationControlContent: {
|
|
8
|
+
readonly id: "email-identification-control";
|
|
9
|
+
readonly title: "Email Identification Control";
|
|
10
|
+
readonly description: "The inline message shown when saving the email fails.";
|
|
11
|
+
readonly schema: {
|
|
12
|
+
readonly type: "object";
|
|
13
|
+
readonly additionalProperties: false;
|
|
14
|
+
readonly properties: {
|
|
15
|
+
readonly genericErrorMessage: {
|
|
16
|
+
readonly type: "string";
|
|
17
|
+
readonly title: "Save failure message";
|
|
18
|
+
readonly description: "Shown for a network failure and for any refusal the shopper cannot act on.";
|
|
19
|
+
readonly format: "icu-message";
|
|
20
|
+
readonly messageSource: "Unable to save your details. Please try again.";
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
};
|
|
6
25
|
/** ClientProfile slice forwarded by the reactive runtime — only `email` is consumed for pre-fill. */
|
|
7
26
|
export type EmailIdentificationSlice = {
|
|
8
27
|
email?: string | null;
|
|
9
28
|
};
|
|
10
|
-
export type EmailIdentificationControlProps = Omit<ComponentPropsWithRef<'div'>, 'onChange'> & {
|
|
29
|
+
export type EmailIdentificationControlProps = Omit<ComponentPropsWithRef<'div'>, 'onChange'> & MessageLocaleProp & {
|
|
11
30
|
/** Accessible label passed to the EmailField. */
|
|
12
31
|
label?: string;
|
|
13
32
|
/** Input placeholder passed to the EmailField. */
|
|
14
33
|
placeholder?: string;
|
|
15
34
|
/** Inline error text for an invalid email format (port of `checkout/form-messages.invalid-email`). */
|
|
16
35
|
invalidEmailMessage?: string;
|
|
36
|
+
/** The inline message for a refused save. */
|
|
37
|
+
$content?: ContentValue<typeof EmailIdentificationControlContent>;
|
|
17
38
|
/** ClientProfile slice forwarded by the reactive runtime; `null` until the entity resolves. */
|
|
18
39
|
$data?: EmailIdentificationSlice | null;
|
|
19
40
|
/** Compiler-injected action surface; carries `identity.clientProfileUpdate`. */
|
|
@@ -29,9 +50,10 @@ export declare const EmailIdentificationControlDefinition: ComponentDefinition<E
|
|
|
29
50
|
* flight the field is disabled and `data-fs-email-identification-pending` is present so a
|
|
30
51
|
* checkout-CTA guard can block. When the session reports `canEditData: false` (identified but
|
|
31
52
|
* unauthenticated claimed profile — VTEX refuses the write server-side) the field renders disabled
|
|
32
|
-
* with `data-fs-email-identification-readonly`. Server `userErrors` are surfaced inline
|
|
53
|
+
* with `data-fs-email-identification-readonly`. Server `userErrors` are surfaced inline, worded by the
|
|
54
|
+
* `$content` field for their code (genericErrorMessage for a code it does not know); the
|
|
33
55
|
* session state is never computed locally.
|
|
34
56
|
*/
|
|
35
|
-
export declare function EmailIdentificationControl({ label, placeholder, invalidEmailMessage, $data: $dataProp, $actions: $actionsProp, className, ...props }: EmailIdentificationControlProps): import("react/jsx-runtime").JSX.Element;
|
|
57
|
+
export declare function EmailIdentificationControl({ label, placeholder, invalidEmailMessage, $content, $locale, $data: $dataProp, $actions: $actionsProp, className, ...props }: EmailIdentificationControlProps): import("react/jsx-runtime").JSX.Element;
|
|
36
58
|
//#endregion
|
|
37
59
|
//# sourceMappingURL=email-identification.d.ts.map
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { defineComponent } from "../../core/dist/define-component.js";
|
|
3
|
+
import { defineContentType } from "../../core/dist/define-content-type.js";
|
|
3
4
|
import "../../core/dist/index.js";
|
|
5
|
+
import { useMessageFormatter } from "../../sdk/i18n/use-message-formatter.js";
|
|
4
6
|
import { EmailField, isValidEmail } from "../../particles/email-field/email-field.js";
|
|
5
7
|
import { useActionsOverride } from "../../sdk/actions/actions-override-context.js";
|
|
8
|
+
import { formatErrorCode } from "../../sdk/i18n/format-error-code.js";
|
|
6
9
|
import { useDataOverride } from "../../sdk/data/data-override-context.js";
|
|
7
10
|
import { useSession } from "../session/session.js";
|
|
8
11
|
import { useEffect, useState } from "react";
|
|
9
12
|
import { jsx } from "react/jsx-runtime";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
importPath: "@vtex/faststore/components",
|
|
13
|
-
component: EmailIdentificationControl,
|
|
14
|
-
fragment: `
|
|
13
|
+
//#region src/matter/email-identification/email-identification.tsx
|
|
14
|
+
const fragment = `
|
|
15
15
|
fragment EmailIdentificationData on Query {
|
|
16
16
|
clientProfile {
|
|
17
17
|
__typename
|
|
@@ -19,7 +19,39 @@ const EmailIdentificationControlDefinition = defineComponent({
|
|
|
19
19
|
email
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
`;
|
|
23
|
+
const EmailIdentificationControlContent = defineContentType({
|
|
24
|
+
id: "email-identification-control",
|
|
25
|
+
title: "Email Identification Control",
|
|
26
|
+
description: "The inline message shown when saving the email fails.",
|
|
27
|
+
schema: {
|
|
28
|
+
type: "object",
|
|
29
|
+
additionalProperties: false,
|
|
30
|
+
properties: { genericErrorMessage: {
|
|
31
|
+
type: "string",
|
|
32
|
+
title: "Save failure message",
|
|
33
|
+
description: "Shown for a network failure and for any refusal the shopper cannot act on.",
|
|
34
|
+
format: "icu-message",
|
|
35
|
+
messageSource: "Unable to save your details. Please try again."
|
|
36
|
+
} }
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* `ClientProfileUpdateErrorCode` of API Core's schema plus the client-minted transport failure. None is
|
|
41
|
+
* something the shopper can fix by editing the email, so all share the generic message.
|
|
42
|
+
*/
|
|
43
|
+
const EMAIL_IDENTIFICATION_ERROR_FIELDS = {
|
|
44
|
+
MISSING_CART_CONTEXT: "genericErrorMessage",
|
|
45
|
+
CART_NOT_FOUND: "genericErrorMessage",
|
|
46
|
+
NO_PROFILE_FIELD_PROVIDED: "genericErrorMessage",
|
|
47
|
+
NETWORK_ERROR: "genericErrorMessage"
|
|
48
|
+
};
|
|
49
|
+
const EmailIdentificationControlDefinition = defineComponent({
|
|
50
|
+
name: "EmailIdentificationControl",
|
|
51
|
+
importPath: "@vtex/faststore/components",
|
|
52
|
+
component: EmailIdentificationControl,
|
|
53
|
+
content: EmailIdentificationControlContent,
|
|
54
|
+
fragment,
|
|
23
55
|
fetchStrategy: "reactive",
|
|
24
56
|
actions: { identity: ["clientProfileUpdate"] },
|
|
25
57
|
requiresContext: "session",
|
|
@@ -41,7 +73,7 @@ const EmailIdentificationControlDefinition = defineComponent({
|
|
|
41
73
|
label: "Invalid email message"
|
|
42
74
|
}
|
|
43
75
|
},
|
|
44
|
-
guideline: "Checkout-bound email field: pre-fills from clientProfile.email and persists a valid changed email via $actions.identity.clientProfileUpdate (anonymous→identified). Must be inside SessionRoot. See email-identification.md."
|
|
76
|
+
guideline: "Checkout-bound email field: pre-fills from clientProfile.email and persists a valid changed email via $actions.identity.clientProfileUpdate (anonymous→identified); a refused save shows the $content field genericErrorMessage. Must be inside SessionRoot. See email-identification.md."
|
|
45
77
|
});
|
|
46
78
|
/**
|
|
47
79
|
* Matter that binds the presentational `EmailField` to the User Identity foundation. It reads
|
|
@@ -52,12 +84,14 @@ const EmailIdentificationControlDefinition = defineComponent({
|
|
|
52
84
|
* flight the field is disabled and `data-fs-email-identification-pending` is present so a
|
|
53
85
|
* checkout-CTA guard can block. When the session reports `canEditData: false` (identified but
|
|
54
86
|
* unauthenticated claimed profile — VTEX refuses the write server-side) the field renders disabled
|
|
55
|
-
* with `data-fs-email-identification-readonly`. Server `userErrors` are surfaced inline
|
|
87
|
+
* with `data-fs-email-identification-readonly`. Server `userErrors` are surfaced inline, worded by the
|
|
88
|
+
* `$content` field for their code (genericErrorMessage for a code it does not know); the
|
|
56
89
|
* session state is never computed locally.
|
|
57
90
|
*/
|
|
58
|
-
function EmailIdentificationControl({ label, placeholder, invalidEmailMessage, $data: $dataProp, $actions: $actionsProp, className, ...props }) {
|
|
91
|
+
function EmailIdentificationControl({ label, placeholder, invalidEmailMessage, $content, $locale, $data: $dataProp, $actions: $actionsProp, className, ...props }) {
|
|
59
92
|
const $data = useDataOverride($dataProp);
|
|
60
93
|
const $actions = useActionsOverride($actionsProp);
|
|
94
|
+
const { format } = useMessageFormatter(EmailIdentificationControlContent, $content);
|
|
61
95
|
const { canEditData } = useSession();
|
|
62
96
|
const readOnly = !canEditData;
|
|
63
97
|
const savedEmail = $data?.email ?? "";
|
|
@@ -67,6 +101,9 @@ function EmailIdentificationControl({ label, placeholder, invalidEmailMessage, $
|
|
|
67
101
|
useEffect(() => {
|
|
68
102
|
setValue(savedEmail);
|
|
69
103
|
}, [savedEmail]);
|
|
104
|
+
function serverErrorMessage(error) {
|
|
105
|
+
return formatErrorCode(EmailIdentificationControlContent, EMAIL_IDENTIFICATION_ERROR_FIELDS, error, format, "genericErrorMessage");
|
|
106
|
+
}
|
|
70
107
|
function handleValueChange(next) {
|
|
71
108
|
setValue(next);
|
|
72
109
|
if (serverError) setServerError(null);
|
|
@@ -83,7 +120,7 @@ function EmailIdentificationControl({ label, placeholder, invalidEmailMessage, $
|
|
|
83
120
|
setServerError(null);
|
|
84
121
|
try {
|
|
85
122
|
const errors = await $actions?.identity?.clientProfileUpdate?.({ email: trimmed }) ?? [];
|
|
86
|
-
if (errors.length > 0) setServerError(errors[0]
|
|
123
|
+
if (errors.length > 0) setServerError(errors[0] ?? null);
|
|
87
124
|
} finally {
|
|
88
125
|
setPending(false);
|
|
89
126
|
}
|
|
@@ -100,7 +137,7 @@ function EmailIdentificationControl({ label, placeholder, invalidEmailMessage, $
|
|
|
100
137
|
value,
|
|
101
138
|
disabled: pending || readOnly,
|
|
102
139
|
invalid: serverError != null,
|
|
103
|
-
errorMessage: serverError
|
|
140
|
+
errorMessage: serverError ? serverErrorMessage(serverError) : invalidEmailMessage,
|
|
104
141
|
onValueChange: handleValueChange,
|
|
105
142
|
onBlur: handleBlur,
|
|
106
143
|
required: true
|
|
@@ -108,6 +145,6 @@ function EmailIdentificationControl({ label, placeholder, invalidEmailMessage, $
|
|
|
108
145
|
});
|
|
109
146
|
}
|
|
110
147
|
//#endregion
|
|
111
|
-
export { EmailIdentificationControl, EmailIdentificationControlDefinition };
|
|
148
|
+
export { EMAIL_IDENTIFICATION_ERROR_FIELDS, EmailIdentificationControl, EmailIdentificationControlContent, EmailIdentificationControlDefinition };
|
|
112
149
|
|
|
113
150
|
//# sourceMappingURL=email-identification.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email-identification.js","names":[],"sources":["../../../src/matter/email-identification/email-identification.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\nimport { useEffect, useState } from 'react';\nimport { EmailField, isValidEmail } from '../../particles/email-field/email-field.js';\nimport { useActionsOverride } from '../../sdk/actions/actions-override-context.js';\nimport type { ComponentActions } from '../../sdk/actions/types.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport { useSession } from '../session/session.js';\n\n// ---------------------------------------------------------------------------\n// GraphQL Fragment (colocated, ADR-0011) — reads only clientProfile.email.\n// Authored as a raw string (not the codegen graphql() factory), mirroring the ShippingSimulator\n// matter: the compiler derives the entity fragment on `clientProfile` and subscribes reactively.\n// ---------------------------------------------------------------------------\n\nconst fragment = /* GraphQL */ `\n fragment EmailIdentificationData on Query {\n clientProfile {\n __typename\n id\n email\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** ClientProfile slice forwarded by the reactive runtime — only `email` is consumed for pre-fill. */\nexport type EmailIdentificationSlice = {\n email?: string | null;\n};\n\nexport type EmailIdentificationControlProps = Omit<ComponentPropsWithRef<'div'>, 'onChange'> & {\n /** Accessible label passed to the EmailField. */\n label?: string;\n /** Input placeholder passed to the EmailField. */\n placeholder?: string;\n /** Inline error text for an invalid email format (port of `checkout/form-messages.invalid-email`). */\n invalidEmailMessage?: string;\n /** ClientProfile slice forwarded by the reactive runtime; `null` until the entity resolves. */\n $data?: EmailIdentificationSlice | null;\n /** Compiler-injected action surface; carries `identity.clientProfileUpdate`. */\n $actions?: ComponentActions;\n};\n\n// ---------------------------------------------------------------------------\n// Definition\n// ---------------------------------------------------------------------------\n\nexport const EmailIdentificationControlDefinition = defineComponent<EmailIdentificationControlProps>({\n name: 'EmailIdentificationControl',\n importPath: '@vtex/faststore/components',\n component: EmailIdentificationControl,\n fragment,\n fetchStrategy: 'reactive',\n actions: { identity: ['clientProfileUpdate'] },\n requiresContext: 'session',\n editor: { label: 'Email Identification', category: 'identity' },\n schema: {\n label: { type: 'string', label: 'Label' },\n placeholder: { type: 'string', label: 'Placeholder' },\n invalidEmailMessage: { type: 'string', label: 'Invalid email message' },\n },\n guideline:\n 'Checkout-bound email field: pre-fills from clientProfile.email and persists a valid changed email via $actions.identity.clientProfileUpdate (anonymous→identified). Must be inside SessionRoot. See email-identification.md.',\n});\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Matter that binds the presentational `EmailField` to the User Identity foundation. It reads\n * `clientProfile.email` (colocated reactive fragment) for the pre-fill, reads the identification\n * tri-state and `canEditData` from `useSession()` (which also enforces the `SessionRoot` ancestor),\n * and on a **valid, changed** email persists only the `email` field through\n * `$actions.identity.clientProfileUpdate` (async / pessimistic, Decision 1). While the write is in\n * flight the field is disabled and `data-fs-email-identification-pending` is present so a\n * checkout-CTA guard can block. When the session reports `canEditData: false` (identified but\n * unauthenticated claimed profile — VTEX refuses the write server-side) the field renders disabled\n * with `data-fs-email-identification-readonly`. Server `userErrors` are surfaced inline; the\n * session state is never computed locally.\n */\nexport function EmailIdentificationControl({\n label,\n placeholder,\n invalidEmailMessage,\n $data: $dataProp,\n $actions: $actionsProp,\n className,\n ...props\n}: EmailIdentificationControlProps) {\n const $data = useDataOverride($dataProp);\n const $actions = useActionsOverride($actionsProp);\n // Also enforces the SessionRoot ancestor: useSession() throws when rendered outside one.\n const { canEditData } = useSession();\n // VTEX refuses profile edits for an identified-but-unauthenticated claimed profile; render the\n // field read-only instead of accepting a write that is doomed server-side.\n const readOnly = !canEditData;\n\n const savedEmail = $data?.email ?? '';\n const [value, setValue] = useState(savedEmail);\n const [pending, setPending] = useState(false);\n const [serverError, setServerError] = useState<string | null>(null);\n\n // Sync the pre-fill when the saved profile email resolves or changes (identified/logged-in shopper).\n // Does not fire while the shopper is typing, since `savedEmail` only changes when the profile does.\n useEffect(() => {\n setValue(savedEmail);\n }, [savedEmail]);\n\n function handleValueChange(next: string) {\n setValue(next);\n if (serverError) setServerError(null);\n }\n\n async function handleBlur() {\n const trimmed = value.trim();\n // Cleared field → re-fill with the saved email; clearing must not visually \"un-identify\"\n // (changing email = switching user is a deliberate act, done by typing a new one).\n if (trimmed === '' && savedEmail !== '') {\n setValue(savedEmail);\n return;\n }\n // Invalid format → EmailField shows its own inline error; no persist, no step advance.\n if (!isValidEmail(trimmed)) return;\n // Unchanged → nothing to persist.\n if (trimmed === savedEmail) return;\n\n setPending(true);\n setServerError(null);\n try {\n const errors = (await $actions?.identity?.clientProfileUpdate?.({ email: trimmed })) ?? [];\n if (errors.length > 0) setServerError(errors[0]?.message ?? null);\n } finally {\n setPending(false);\n }\n }\n\n return (\n <div\n {...props}\n className={className}\n data-fs-email-identification-control=\"\"\n {...(pending ? { 'data-fs-email-identification-pending': '' } : {})}\n {...(readOnly ? { 'data-fs-email-identification-readonly': '' } : {})}\n >\n <EmailField\n label={label}\n placeholder={placeholder}\n value={value}\n disabled={pending || readOnly}\n invalid={serverError != null}\n errorMessage={serverError ?? invalidEmailMessage}\n onValueChange={handleValueChange}\n onBlur={handleBlur}\n required\n />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAqDA,MAAa,uCAAuC,gBAAiD;CACnG,MAAM;CACN,YAAY;CACZ,WAAW;CACX;;;;;;;;;CACA,eAAe;CACf,SAAS,EAAE,UAAU,CAAC,qBAAqB,EAAE;CAC7C,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAAwB,UAAU;CAAW;CAC9D,QAAQ;EACN,OAAO;GAAE,MAAM;GAAU,OAAO;EAAQ;EACxC,aAAa;GAAE,MAAM;GAAU,OAAO;EAAc;EACpD,qBAAqB;GAAE,MAAM;GAAU,OAAO;EAAwB;CACxE;CACA,WACE;AACJ,CAAC;;;;;;;;;;;;;AAkBD,SAAgB,2BAA2B,EACzC,OACA,aACA,qBACA,OAAO,WACP,UAAU,cACV,WACA,GAAG,SAC+B;CAClC,MAAM,QAAQ,gBAAgB,SAAS;CACvC,MAAM,WAAW,mBAAmB,YAAY;CAEhD,MAAM,EAAE,gBAAgB,WAAW;CAGnC,MAAM,WAAW,CAAC;CAElB,MAAM,aAAa,OAAO,SAAS;CACnC,MAAM,CAAC,OAAO,YAAY,SAAS,UAAU;CAC7C,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAC5C,MAAM,CAAC,aAAa,kBAAkB,SAAwB,IAAI;CAIlE,gBAAgB;EACd,SAAS,UAAU;CACrB,GAAG,CAAC,UAAU,CAAC;CAEf,SAAS,kBAAkB,MAAc;EACvC,SAAS,IAAI;EACb,IAAI,aAAa,eAAe,IAAI;CACtC;CAEA,eAAe,aAAa;EAC1B,MAAM,UAAU,MAAM,KAAK;EAG3B,IAAI,YAAY,MAAM,eAAe,IAAI;GACvC,SAAS,UAAU;GACnB;EACF;EAEA,IAAI,CAAC,aAAa,OAAO,GAAG;EAE5B,IAAI,YAAY,YAAY;EAE5B,WAAW,IAAI;EACf,eAAe,IAAI;EACnB,IAAI;GACF,MAAM,SAAU,MAAM,UAAU,UAAU,sBAAsB,EAAE,OAAO,QAAQ,CAAC,KAAM,CAAC;GACzF,IAAI,OAAO,SAAS,GAAG,eAAe,OAAO,EAAE,EAAE,WAAW,IAAI;EAClE,UAAU;GACR,WAAW,KAAK;EAClB;CACF;CAEA,OACE,oBAAC,OAAD;EACE,GAAI;EACO;EACX,wCAAqC;EACrC,GAAK,UAAU,EAAE,wCAAwC,GAAG,IAAI,CAAC;EACjE,GAAK,WAAW,EAAE,yCAAyC,GAAG,IAAI,CAAC;EAEnE,UAAA,oBAAC,YAAD;GACS;GACM;GACN;GACP,UAAU,WAAW;GACrB,SAAS,eAAe;GACxB,cAAc,eAAe;GAC7B,eAAe;GACf,QAAQ;GACR,UAAA;EACD,CAAA;CACE,CAAA;AAET"}
|
|
1
|
+
{"version":3,"file":"email-identification.js","names":[],"sources":["../../../src/matter/email-identification/email-identification.tsx"],"sourcesContent":["'use client';\n\nimport {\n type ContentValue,\n defineComponent,\n defineContentType,\n type MessageFieldName,\n type MessageLocaleProp,\n} from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\nimport { useEffect, useState } from 'react';\nimport { EmailField, isValidEmail } from '../../particles/email-field/email-field.js';\nimport { useActionsOverride } from '../../sdk/actions/actions-override-context.js';\nimport type { ComponentActions } from '../../sdk/actions/types.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport { formatErrorCode } from '../../sdk/i18n/format-error-code.js';\nimport { useMessageFormatter } from '../../sdk/i18n/use-message-formatter.js';\nimport type { ClientProfileUserError } from '../../sdk/identity/operations.js';\nimport { useSession } from '../session/session.js';\n\n// ---------------------------------------------------------------------------\n// GraphQL Fragment (colocated, ADR-0011) — reads only clientProfile.email.\n// Authored as a raw string (not the codegen graphql() factory), mirroring the ShippingSimulator\n// matter: the compiler derives the entity fragment on `clientProfile` and subscribes reactively.\n// ---------------------------------------------------------------------------\n\nconst fragment = /* GraphQL */ `\n fragment EmailIdentificationData on Query {\n clientProfile {\n __typename\n id\n email\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Content model\n// ---------------------------------------------------------------------------\n\nexport const EmailIdentificationControlContent = defineContentType({\n id: 'email-identification-control',\n title: 'Email Identification Control',\n description: 'The inline message shown when saving the email fails.',\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n genericErrorMessage: {\n type: 'string',\n title: 'Save failure message',\n description: 'Shown for a network failure and for any refusal the shopper cannot act on.',\n format: 'icu-message',\n messageSource: 'Unable to save your details. Please try again.',\n },\n },\n },\n});\n\n/**\n * `ClientProfileUpdateErrorCode` of API Core's schema plus the client-minted transport failure. None is\n * something the shopper can fix by editing the email, so all share the generic message.\n */\nexport const EMAIL_IDENTIFICATION_ERROR_FIELDS = {\n MISSING_CART_CONTEXT: 'genericErrorMessage',\n CART_NOT_FOUND: 'genericErrorMessage',\n NO_PROFILE_FIELD_PROVIDED: 'genericErrorMessage',\n NETWORK_ERROR: 'genericErrorMessage',\n} as const satisfies Record<string, MessageFieldName<typeof EmailIdentificationControlContent>>;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** ClientProfile slice forwarded by the reactive runtime — only `email` is consumed for pre-fill. */\nexport type EmailIdentificationSlice = {\n email?: string | null;\n};\n\nexport type EmailIdentificationControlProps = Omit<ComponentPropsWithRef<'div'>, 'onChange'> &\n MessageLocaleProp & {\n /** Accessible label passed to the EmailField. */\n label?: string;\n /** Input placeholder passed to the EmailField. */\n placeholder?: string;\n /** Inline error text for an invalid email format (port of `checkout/form-messages.invalid-email`). */\n invalidEmailMessage?: string;\n /** The inline message for a refused save. */\n $content?: ContentValue<typeof EmailIdentificationControlContent>;\n /** ClientProfile slice forwarded by the reactive runtime; `null` until the entity resolves. */\n $data?: EmailIdentificationSlice | null;\n /** Compiler-injected action surface; carries `identity.clientProfileUpdate`. */\n $actions?: ComponentActions;\n };\n\n// ---------------------------------------------------------------------------\n// Definition\n// ---------------------------------------------------------------------------\n\nexport const EmailIdentificationControlDefinition = defineComponent<EmailIdentificationControlProps>({\n name: 'EmailIdentificationControl',\n importPath: '@vtex/faststore/components',\n component: EmailIdentificationControl,\n content: EmailIdentificationControlContent,\n fragment,\n fetchStrategy: 'reactive',\n actions: { identity: ['clientProfileUpdate'] },\n requiresContext: 'session',\n editor: { label: 'Email Identification', category: 'identity' },\n schema: {\n label: { type: 'string', label: 'Label' },\n placeholder: { type: 'string', label: 'Placeholder' },\n invalidEmailMessage: { type: 'string', label: 'Invalid email message' },\n },\n guideline:\n 'Checkout-bound email field: pre-fills from clientProfile.email and persists a valid changed email via $actions.identity.clientProfileUpdate (anonymous→identified); a refused save shows the $content field genericErrorMessage. Must be inside SessionRoot. See email-identification.md.',\n});\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Matter that binds the presentational `EmailField` to the User Identity foundation. It reads\n * `clientProfile.email` (colocated reactive fragment) for the pre-fill, reads the identification\n * tri-state and `canEditData` from `useSession()` (which also enforces the `SessionRoot` ancestor),\n * and on a **valid, changed** email persists only the `email` field through\n * `$actions.identity.clientProfileUpdate` (async / pessimistic, Decision 1). While the write is in\n * flight the field is disabled and `data-fs-email-identification-pending` is present so a\n * checkout-CTA guard can block. When the session reports `canEditData: false` (identified but\n * unauthenticated claimed profile — VTEX refuses the write server-side) the field renders disabled\n * with `data-fs-email-identification-readonly`. Server `userErrors` are surfaced inline, worded by the\n * `$content` field for their code (genericErrorMessage for a code it does not know); the\n * session state is never computed locally.\n */\nexport function EmailIdentificationControl({\n label,\n placeholder,\n invalidEmailMessage,\n $content,\n $locale,\n $data: $dataProp,\n $actions: $actionsProp,\n className,\n ...props\n}: EmailIdentificationControlProps) {\n const $data = useDataOverride($dataProp);\n const $actions = useActionsOverride($actionsProp);\n const { format } = useMessageFormatter(EmailIdentificationControlContent, $content);\n // Also enforces the SessionRoot ancestor: useSession() throws when rendered outside one.\n const { canEditData } = useSession();\n // VTEX refuses profile edits for an identified-but-unauthenticated claimed profile; render the\n // field read-only instead of accepting a write that is doomed server-side.\n const readOnly = !canEditData;\n\n const savedEmail = $data?.email ?? '';\n const [value, setValue] = useState(savedEmail);\n const [pending, setPending] = useState(false);\n const [serverError, setServerError] = useState<ClientProfileUserError | null>(null);\n\n // Sync the pre-fill when the saved profile email resolves or changes (identified/logged-in shopper).\n // Does not fire while the shopper is typing, since `savedEmail` only changes when the profile does.\n useEffect(() => {\n setValue(savedEmail);\n }, [savedEmail]);\n\n function serverErrorMessage(error: ClientProfileUserError): string {\n return formatErrorCode(\n EmailIdentificationControlContent,\n EMAIL_IDENTIFICATION_ERROR_FIELDS,\n error,\n format,\n 'genericErrorMessage',\n );\n }\n\n function handleValueChange(next: string) {\n setValue(next);\n if (serverError) setServerError(null);\n }\n\n async function handleBlur() {\n const trimmed = value.trim();\n // Cleared field → re-fill with the saved email; clearing must not visually \"un-identify\"\n // (changing email = switching user is a deliberate act, done by typing a new one).\n if (trimmed === '' && savedEmail !== '') {\n setValue(savedEmail);\n return;\n }\n // Invalid format → EmailField shows its own inline error; no persist, no step advance.\n if (!isValidEmail(trimmed)) return;\n // Unchanged → nothing to persist.\n if (trimmed === savedEmail) return;\n\n setPending(true);\n setServerError(null);\n try {\n const errors = (await $actions?.identity?.clientProfileUpdate?.({ email: trimmed })) ?? [];\n if (errors.length > 0) setServerError(errors[0] ?? null);\n } finally {\n setPending(false);\n }\n }\n\n return (\n <div\n {...props}\n className={className}\n data-fs-email-identification-control=\"\"\n {...(pending ? { 'data-fs-email-identification-pending': '' } : {})}\n {...(readOnly ? { 'data-fs-email-identification-readonly': '' } : {})}\n >\n <EmailField\n label={label}\n placeholder={placeholder}\n value={value}\n disabled={pending || readOnly}\n invalid={serverError != null}\n errorMessage={serverError ? serverErrorMessage(serverError) : invalidEmailMessage}\n onValueChange={handleValueChange}\n onBlur={handleBlur}\n required\n />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AA0BA,MAAM,WAAyB;;;;;;;;;AAc/B,MAAa,oCAAoC,kBAAkB;CACjE,IAAI;CACJ,OAAO;CACP,aAAa;CACb,QAAQ;EACN,MAAM;EACN,sBAAsB;EACtB,YAAY,EACV,qBAAqB;GACnB,MAAM;GACN,OAAO;GACP,aAAa;GACb,QAAQ;GACR,eAAe;EACjB,EACF;CACF;AACF,CAAC;;;;;AAMD,MAAa,oCAAoC;CAC/C,sBAAsB;CACtB,gBAAgB;CAChB,2BAA2B;CAC3B,eAAe;AACjB;AA+BA,MAAa,uCAAuC,gBAAiD;CACnG,MAAM;CACN,YAAY;CACZ,WAAW;CACX,SAAS;CACT;CACA,eAAe;CACf,SAAS,EAAE,UAAU,CAAC,qBAAqB,EAAE;CAC7C,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAAwB,UAAU;CAAW;CAC9D,QAAQ;EACN,OAAO;GAAE,MAAM;GAAU,OAAO;EAAQ;EACxC,aAAa;GAAE,MAAM;GAAU,OAAO;EAAc;EACpD,qBAAqB;GAAE,MAAM;GAAU,OAAO;EAAwB;CACxE;CACA,WACE;AACJ,CAAC;;;;;;;;;;;;;;AAmBD,SAAgB,2BAA2B,EACzC,OACA,aACA,qBACA,UACA,SACA,OAAO,WACP,UAAU,cACV,WACA,GAAG,SAC+B;CAClC,MAAM,QAAQ,gBAAgB,SAAS;CACvC,MAAM,WAAW,mBAAmB,YAAY;CAChD,MAAM,EAAE,WAAW,oBAAoB,mCAAmC,QAAQ;CAElF,MAAM,EAAE,gBAAgB,WAAW;CAGnC,MAAM,WAAW,CAAC;CAElB,MAAM,aAAa,OAAO,SAAS;CACnC,MAAM,CAAC,OAAO,YAAY,SAAS,UAAU;CAC7C,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAC5C,MAAM,CAAC,aAAa,kBAAkB,SAAwC,IAAI;CAIlF,gBAAgB;EACd,SAAS,UAAU;CACrB,GAAG,CAAC,UAAU,CAAC;CAEf,SAAS,mBAAmB,OAAuC;EACjE,OAAO,gBACL,mCACA,mCACA,OACA,QACA,qBACF;CACF;CAEA,SAAS,kBAAkB,MAAc;EACvC,SAAS,IAAI;EACb,IAAI,aAAa,eAAe,IAAI;CACtC;CAEA,eAAe,aAAa;EAC1B,MAAM,UAAU,MAAM,KAAK;EAG3B,IAAI,YAAY,MAAM,eAAe,IAAI;GACvC,SAAS,UAAU;GACnB;EACF;EAEA,IAAI,CAAC,aAAa,OAAO,GAAG;EAE5B,IAAI,YAAY,YAAY;EAE5B,WAAW,IAAI;EACf,eAAe,IAAI;EACnB,IAAI;GACF,MAAM,SAAU,MAAM,UAAU,UAAU,sBAAsB,EAAE,OAAO,QAAQ,CAAC,KAAM,CAAC;GACzF,IAAI,OAAO,SAAS,GAAG,eAAe,OAAO,MAAM,IAAI;EACzD,UAAU;GACR,WAAW,KAAK;EAClB;CACF;CAEA,OACE,oBAAC,OAAD;EACE,GAAI;EACO;EACX,wCAAqC;EACrC,GAAK,UAAU,EAAE,wCAAwC,GAAG,IAAI,CAAC;EACjE,GAAK,WAAW,EAAE,yCAAyC,GAAG,IAAI,CAAC;EAEnE,UAAA,oBAAC,YAAD;GACS;GACM;GACN;GACP,UAAU,WAAW;GACrB,SAAS,eAAe;GACxB,cAAc,cAAc,mBAAmB,WAAW,IAAI;GAC9D,eAAe;GACf,QAAQ;GACR,UAAA;EACD,CAAA;CACE,CAAA;AAET"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ContentValue, MessageLocaleProp } from "../../core/dist/define-content-type.js";
|
|
1
2
|
import { ComponentDefinition } from "../../core/dist/define-component.js";
|
|
2
3
|
import "../../core/dist/index.js";
|
|
3
4
|
import { ComponentPropsWithRef } from "react";
|
|
@@ -27,17 +28,88 @@ export type FreeShippingProgressRootProps = ComponentPropsWithRef<'div'> & {
|
|
|
27
28
|
itemsTotal?: number;
|
|
28
29
|
$data?: FreeShippingProgressData['cart'] | null;
|
|
29
30
|
};
|
|
30
|
-
export
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
export declare const FreeShippingProgressMessageContent: {
|
|
32
|
+
readonly id: "free-shipping-progress-message";
|
|
33
|
+
readonly title: "Free Shipping Progress Message";
|
|
34
|
+
readonly description: "The below-threshold and earned free-shipping messages.";
|
|
35
|
+
readonly schema: {
|
|
36
|
+
readonly type: "object";
|
|
37
|
+
readonly additionalProperties: false;
|
|
38
|
+
readonly properties: {
|
|
39
|
+
readonly label: {
|
|
40
|
+
readonly type: "string";
|
|
41
|
+
readonly title: "Below-threshold label";
|
|
42
|
+
readonly description: "Shown while the cart is below the threshold; value is the formatted amount still missing.";
|
|
43
|
+
readonly format: "icu-message";
|
|
44
|
+
readonly messageSource: "{value} away from free shipping";
|
|
45
|
+
readonly messageArguments: {
|
|
46
|
+
readonly type: "object";
|
|
47
|
+
readonly properties: {
|
|
48
|
+
readonly value: {
|
|
49
|
+
readonly type: "string";
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
readonly messageExample: {
|
|
54
|
+
readonly value: "$25.00";
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
readonly qualifiedLabel: {
|
|
58
|
+
readonly type: "string";
|
|
59
|
+
readonly title: "Qualified label";
|
|
60
|
+
readonly format: "icu-message";
|
|
61
|
+
readonly messageSource: "You got free shipping!";
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
export declare const FreeShippingProgressBarContent: {
|
|
67
|
+
readonly id: "free-shipping-progress-bar";
|
|
68
|
+
readonly title: "Free Shipping Progress Bar";
|
|
69
|
+
readonly description: "The value text a screen reader announces for the progress bar.";
|
|
70
|
+
readonly schema: {
|
|
71
|
+
readonly type: "object";
|
|
72
|
+
readonly additionalProperties: false;
|
|
73
|
+
readonly properties: {
|
|
74
|
+
readonly valueText: {
|
|
75
|
+
readonly type: "string";
|
|
76
|
+
readonly title: "Below-threshold value text";
|
|
77
|
+
readonly description: "Announced while the cart is below the threshold; value is the formatted amount still missing.";
|
|
78
|
+
readonly format: "icu-message";
|
|
79
|
+
readonly messageSource: "{value} left for free shipping";
|
|
80
|
+
readonly messageArguments: {
|
|
81
|
+
readonly type: "object";
|
|
82
|
+
readonly properties: {
|
|
83
|
+
readonly value: {
|
|
84
|
+
readonly type: "string";
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
readonly messageExample: {
|
|
89
|
+
readonly value: "$25.00";
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
readonly qualifiedValueText: {
|
|
93
|
+
readonly type: "string";
|
|
94
|
+
readonly title: "Qualified value text";
|
|
95
|
+
readonly format: "icu-message";
|
|
96
|
+
readonly messageSource: "Free shipping earned";
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
export type FreeShippingProgressBarProps = ComponentPropsWithRef<'div'> & MessageLocaleProp & {
|
|
102
|
+
$content?: ContentValue<typeof FreeShippingProgressBarContent>;
|
|
103
|
+
};
|
|
104
|
+
export type FreeShippingProgressMessageProps = ComponentPropsWithRef<'div'> & MessageLocaleProp & {
|
|
105
|
+
$content?: ContentValue<typeof FreeShippingProgressMessageContent>;
|
|
34
106
|
};
|
|
35
107
|
export declare const FreeShippingProgressRootDefinition: ComponentDefinition<FreeShippingProgressRootProps>;
|
|
36
|
-
export declare const FreeShippingProgressBarDefinition: ComponentDefinition<
|
|
108
|
+
export declare const FreeShippingProgressBarDefinition: ComponentDefinition<FreeShippingProgressBarProps>;
|
|
37
109
|
export declare const FreeShippingProgressMessageDefinition: ComponentDefinition<FreeShippingProgressMessageProps>;
|
|
38
110
|
export declare function FreeShippingProgressRoot({ threshold, remaining, qualified, itemsTotal, $data: $dataProp, className, children, ...props }: FreeShippingProgressRootProps): import("react/jsx-runtime").JSX.Element | null;
|
|
39
|
-
export declare function FreeShippingProgressBar({ className, ...props }: FreeShippingProgressBarProps): import("react/jsx-runtime").JSX.Element;
|
|
40
|
-
export declare function FreeShippingProgressMessage({
|
|
111
|
+
export declare function FreeShippingProgressBar({ $content, $locale, className, ...props }: FreeShippingProgressBarProps): import("react/jsx-runtime").JSX.Element;
|
|
112
|
+
export declare function FreeShippingProgressMessage({ $content, $locale, className, children, ...props }: FreeShippingProgressMessageProps): import("react/jsx-runtime").JSX.Element;
|
|
41
113
|
export declare const FreeShippingProgress: {
|
|
42
114
|
Root: typeof FreeShippingProgressRoot;
|
|
43
115
|
Bar: typeof FreeShippingProgressBar;
|
|
@@ -1,13 +1,73 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { defineComponent } from "../../core/dist/define-component.js";
|
|
3
|
+
import { defineContentType } from "../../core/dist/define-content-type.js";
|
|
3
4
|
import "../../core/dist/index.js";
|
|
4
5
|
import { useStorefrontContext } from "../../sdk/context/storefront-context.js";
|
|
6
|
+
import { useMessageFormatter } from "../../sdk/i18n/use-message-formatter.js";
|
|
5
7
|
import { useDataOverride } from "../../sdk/data/data-override-context.js";
|
|
6
8
|
import { isFiniteAmount } from "../cart/cart.js";
|
|
7
9
|
import { Meter } from "../../particles/meter/meter.js";
|
|
8
10
|
import { createContext, useContext } from "react";
|
|
9
11
|
import { jsx } from "react/jsx-runtime";
|
|
10
12
|
//#region src/matter/free-shipping-progress/free-shipping-progress.tsx
|
|
13
|
+
const FreeShippingProgressMessageContent = defineContentType({
|
|
14
|
+
id: "free-shipping-progress-message",
|
|
15
|
+
title: "Free Shipping Progress Message",
|
|
16
|
+
description: "The below-threshold and earned free-shipping messages.",
|
|
17
|
+
schema: {
|
|
18
|
+
type: "object",
|
|
19
|
+
additionalProperties: false,
|
|
20
|
+
properties: {
|
|
21
|
+
label: {
|
|
22
|
+
type: "string",
|
|
23
|
+
title: "Below-threshold label",
|
|
24
|
+
description: "Shown while the cart is below the threshold; value is the formatted amount still missing.",
|
|
25
|
+
format: "icu-message",
|
|
26
|
+
messageSource: "{value} away from free shipping",
|
|
27
|
+
messageArguments: {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: { value: { type: "string" } }
|
|
30
|
+
},
|
|
31
|
+
messageExample: { value: "$25.00" }
|
|
32
|
+
},
|
|
33
|
+
qualifiedLabel: {
|
|
34
|
+
type: "string",
|
|
35
|
+
title: "Qualified label",
|
|
36
|
+
format: "icu-message",
|
|
37
|
+
messageSource: "You got free shipping!"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
const FreeShippingProgressBarContent = defineContentType({
|
|
43
|
+
id: "free-shipping-progress-bar",
|
|
44
|
+
title: "Free Shipping Progress Bar",
|
|
45
|
+
description: "The value text a screen reader announces for the progress bar.",
|
|
46
|
+
schema: {
|
|
47
|
+
type: "object",
|
|
48
|
+
additionalProperties: false,
|
|
49
|
+
properties: {
|
|
50
|
+
valueText: {
|
|
51
|
+
type: "string",
|
|
52
|
+
title: "Below-threshold value text",
|
|
53
|
+
description: "Announced while the cart is below the threshold; value is the formatted amount still missing.",
|
|
54
|
+
format: "icu-message",
|
|
55
|
+
messageSource: "{value} left for free shipping",
|
|
56
|
+
messageArguments: {
|
|
57
|
+
type: "object",
|
|
58
|
+
properties: { value: { type: "string" } }
|
|
59
|
+
},
|
|
60
|
+
messageExample: { value: "$25.00" }
|
|
61
|
+
},
|
|
62
|
+
qualifiedValueText: {
|
|
63
|
+
type: "string",
|
|
64
|
+
title: "Qualified value text",
|
|
65
|
+
format: "icu-message",
|
|
66
|
+
messageSource: "Free shipping earned"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
11
71
|
const fragment = `
|
|
12
72
|
fragment FreeShippingProgressData on Query {
|
|
13
73
|
cart {
|
|
@@ -122,34 +182,25 @@ const FreeShippingProgressBarDefinition = defineComponent({
|
|
|
122
182
|
name: "FreeShippingProgressBar",
|
|
123
183
|
importPath: "@vtex/faststore/components",
|
|
124
184
|
component: FreeShippingProgressBar,
|
|
185
|
+
content: FreeShippingProgressBarContent,
|
|
125
186
|
editor: {
|
|
126
187
|
label: "Free Shipping Progress Bar",
|
|
127
188
|
category: "commerce"
|
|
128
189
|
},
|
|
129
190
|
schema: {},
|
|
130
|
-
guideline: "Meter bar that fills toward the free-shipping goal, full when earned. Must be inside FreeShippingProgressRoot. See free-shipping-progress.md."
|
|
191
|
+
guideline: "Meter bar that fills toward the free-shipping goal, full when earned; screen readers announce the $content fields valueText ({value} is the formatted remaining amount) and qualifiedValueText. Must be inside FreeShippingProgressRoot. See free-shipping-progress.md."
|
|
131
192
|
});
|
|
132
193
|
const FreeShippingProgressMessageDefinition = defineComponent({
|
|
133
194
|
name: "FreeShippingProgressMessage",
|
|
134
195
|
importPath: "@vtex/faststore/components",
|
|
135
196
|
component: FreeShippingProgressMessage,
|
|
197
|
+
content: FreeShippingProgressMessageContent,
|
|
136
198
|
editor: {
|
|
137
199
|
label: "Free Shipping Progress Message",
|
|
138
200
|
category: "commerce"
|
|
139
201
|
},
|
|
140
|
-
schema: {
|
|
141
|
-
|
|
142
|
-
type: "string",
|
|
143
|
-
default: "faltam {value} para frete grátis",
|
|
144
|
-
label: "Below-threshold Label"
|
|
145
|
-
},
|
|
146
|
-
qualifiedLabel: {
|
|
147
|
-
type: "string",
|
|
148
|
-
default: "você ganhou frete grátis!",
|
|
149
|
-
label: "Qualified Label"
|
|
150
|
-
}
|
|
151
|
-
},
|
|
152
|
-
guideline: "Below-threshold vs earned copy, front-formatted from the active storefront context. Must be inside FreeShippingProgressRoot. See free-shipping-progress.md."
|
|
202
|
+
schema: {},
|
|
203
|
+
guideline: "Below-threshold vs earned copy from the $content fields label ({value} is the formatted remaining amount) and qualifiedLabel; children replace both. Must be inside FreeShippingProgressRoot. See free-shipping-progress.md."
|
|
153
204
|
});
|
|
154
205
|
function FreeShippingProgressRoot({ threshold, remaining, qualified, itemsTotal, $data: $dataProp, className, children, ...props }) {
|
|
155
206
|
const { currency } = useStorefrontContext();
|
|
@@ -176,11 +227,13 @@ function FreeShippingProgressRoot({ threshold, remaining, qualified, itemsTotal,
|
|
|
176
227
|
})
|
|
177
228
|
});
|
|
178
229
|
}
|
|
179
|
-
function FreeShippingProgressBar({ className, ...props }) {
|
|
230
|
+
function FreeShippingProgressBar({ $content, $locale, className, ...props }) {
|
|
180
231
|
const { fill, isQualified, liveRemaining } = useFreeShippingProgress();
|
|
181
232
|
const { locale, currency } = useStorefrontContext();
|
|
182
|
-
const
|
|
233
|
+
const { format } = useMessageFormatter(FreeShippingProgressBarContent, $content);
|
|
234
|
+
const ariaValueText = isQualified ? format("qualifiedValueText") : format("valueText", { value: formatCurrency(liveRemaining, locale, currency) });
|
|
183
235
|
return /* @__PURE__ */ jsx(Meter.Root, {
|
|
236
|
+
"aria-label": "Progresso para frete grátis",
|
|
184
237
|
...props,
|
|
185
238
|
value: Math.round(fill * 100),
|
|
186
239
|
min: 0,
|
|
@@ -191,15 +244,19 @@ function FreeShippingProgressBar({ className, ...props }) {
|
|
|
191
244
|
children: /* @__PURE__ */ jsx(Meter.Track, { children: /* @__PURE__ */ jsx(Meter.Indicator, {}) })
|
|
192
245
|
});
|
|
193
246
|
}
|
|
194
|
-
function FreeShippingProgressMessage({
|
|
247
|
+
function FreeShippingProgressMessage({ $content, $locale, className, children, ...props }) {
|
|
195
248
|
const { isQualified, liveRemaining } = useFreeShippingProgress();
|
|
196
249
|
const { locale, currency } = useStorefrontContext();
|
|
197
|
-
const
|
|
250
|
+
const { format } = useMessageFormatter(FreeShippingProgressMessageContent, $content);
|
|
251
|
+
function message() {
|
|
252
|
+
if (isQualified) return format("qualifiedLabel");
|
|
253
|
+
return format("label", { value: formatCurrency(liveRemaining, locale, currency) });
|
|
254
|
+
}
|
|
198
255
|
return /* @__PURE__ */ jsx("div", {
|
|
199
256
|
...props,
|
|
200
257
|
className,
|
|
201
258
|
"data-fs-free-shipping-progress-message": "",
|
|
202
|
-
children: children ??
|
|
259
|
+
children: children ?? message()
|
|
203
260
|
});
|
|
204
261
|
}
|
|
205
262
|
const FreeShippingProgress = {
|
|
@@ -208,6 +265,6 @@ const FreeShippingProgress = {
|
|
|
208
265
|
Message: FreeShippingProgressMessage
|
|
209
266
|
};
|
|
210
267
|
//#endregion
|
|
211
|
-
export { FreeShippingProgress, FreeShippingProgressBar, FreeShippingProgressBarDefinition, FreeShippingProgressMessage, FreeShippingProgressMessageDefinition, FreeShippingProgressRoot, FreeShippingProgressRootDefinition };
|
|
268
|
+
export { FreeShippingProgress, FreeShippingProgressBar, FreeShippingProgressBarContent, FreeShippingProgressBarDefinition, FreeShippingProgressMessage, FreeShippingProgressMessageContent, FreeShippingProgressMessageDefinition, FreeShippingProgressRoot, FreeShippingProgressRootDefinition };
|
|
212
269
|
|
|
213
270
|
//# sourceMappingURL=free-shipping-progress.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"free-shipping-progress.js","names":[],"sources":["../../../src/matter/free-shipping-progress/free-shipping-progress.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport { type ComponentPropsWithRef, createContext, useContext } from 'react';\nimport { Meter } from '../../particles/meter/meter.js';\nimport { useStorefrontContext } from '../../sdk/context/storefront-context.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport { isFiniteAmount } from '../cart/cart.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype MoneyValue = { amount: number | string; currencyCode: string };\n\ntype FreeShippingProgressData = {\n cart?: {\n id: string;\n totalizers?: { id: string; value: MoneyValue }[] | null;\n freeShippingProgress?: {\n threshold: MoneyValue | null;\n remaining: MoneyValue;\n qualified: boolean;\n } | null;\n } | null;\n};\n\ntype FreeShippingProgressContextValue = {\n isQualified: boolean;\n fill: number;\n liveRemaining: number;\n};\n\nexport type FreeShippingProgressRootProps = ComponentPropsWithRef<'div'> & {\n threshold?: number;\n remaining?: number;\n qualified?: boolean;\n itemsTotal?: number;\n $data?: FreeShippingProgressData['cart'] | null;\n};\n\nexport type FreeShippingProgressBarProps = ComponentPropsWithRef<'div'>;\nexport type FreeShippingProgressMessageProps = ComponentPropsWithRef<'div'> & {\n label?: string;\n qualifiedLabel?: string;\n};\n\n// ---------------------------------------------------------------------------\n// GraphQL Fragment — narrow cart slice (Items totalizer + freeShippingProgress)\n// ---------------------------------------------------------------------------\n\nconst fragment = /* GraphQL */ `\n fragment FreeShippingProgressData on Query {\n cart {\n id\n totalizers {\n id\n value {\n amount\n currencyCode\n }\n }\n freeShippingProgress {\n threshold {\n amount\n currencyCode\n }\n remaining {\n amount\n currencyCode\n }\n qualified\n }\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst FSP_CONTEXT_UNSET = Symbol('FreeShippingProgressContextUnset');\n\nconst FreeShippingProgressContext = createContext<FreeShippingProgressContextValue | typeof FSP_CONTEXT_UNSET>(\n FSP_CONTEXT_UNSET,\n);\n\nfunction useFreeShippingProgress(): FreeShippingProgressContextValue {\n const ctx = useContext(FreeShippingProgressContext);\n if (ctx === FSP_CONTEXT_UNSET) {\n throw new Error('useFreeShippingProgress() must be used inside a <FreeShippingProgressRoot> subtree.');\n }\n return ctx;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction formatCurrency(value: number, locale: string, currency: string): string {\n return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(value);\n}\n\nfunction clamp01(value: number): number {\n return Math.min(Math.max(value, 0), 1);\n}\n\ntype FreeShippingProgressCart = NonNullable<FreeShippingProgressData['cart']>;\ntype FreeShippingProgressState = NonNullable<FreeShippingProgressCart['freeShippingProgress']>;\n\nfunction previewCart(\n {\n threshold,\n remaining,\n qualified,\n itemsTotal,\n }: Pick<FreeShippingProgressRootProps, 'threshold' | 'remaining' | 'qualified' | 'itemsTotal'>,\n currency: string,\n): FreeShippingProgressCart | null {\n if (qualified === undefined && threshold === undefined && remaining === undefined && itemsTotal === undefined) {\n return null;\n }\n return {\n id: 'preview',\n totalizers:\n itemsTotal === undefined ? [] : [{ id: 'Items', value: { amount: itemsTotal, currencyCode: currency } }],\n freeShippingProgress: {\n threshold: threshold == null ? null : { amount: threshold, currencyCode: currency },\n remaining: { amount: remaining ?? threshold ?? 0, currencyCode: currency },\n qualified: qualified ?? false,\n },\n };\n}\n\n// The server measures the Items totalizer, never the grand total (shipping and discounts do not count).\nfunction itemsSubtotal(cart: FreeShippingProgressCart): number | null {\n const itemsAmount = cart.totalizers?.find((totalizer) => totalizer.id === 'Items')?.value.amount;\n return isFiniteAmount(itemsAmount) ? Number(itemsAmount) : null;\n}\n\n// Usable threshold: present, finite, positive. Null/NaN/zero → no fill, no remaining.\nfunction usableThreshold(threshold: MoneyValue | null): number | null {\n if (threshold == null) return null;\n const parsed = Number(threshold.amount);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : null;\n}\n\nfunction fillRatio(isQualified: boolean, thresholdAmount: number | null, covered: number): number {\n if (isQualified) return 1;\n if (thresholdAmount === null) return 0;\n return clamp01(covered / thresholdAmount);\n}\n\nfunction computeProgress(\n fsp: FreeShippingProgressState,\n items: number | null,\n thresholdAmount: number | null,\n): FreeShippingProgressContextValue {\n if (items === null) {\n // No usable Items amount: show the server's own answer rather than guess.\n const isQualified = fsp.qualified;\n const liveRemaining =\n !isQualified && isFiniteAmount(fsp.remaining.amount) ? Math.max(Number(fsp.remaining.amount), 0) : 0;\n const fill = fillRatio(isQualified, thresholdAmount, (thresholdAmount ?? 0) - liveRemaining);\n return { isQualified, fill, liveRemaining };\n }\n\n const isQualified = fsp.qualified || (thresholdAmount !== null && items >= thresholdAmount);\n const liveRemaining = isQualified || thresholdAmount === null ? 0 : Math.max(thresholdAmount - items, 0);\n return { isQualified, fill: fillRatio(isQualified, thresholdAmount, items), liveRemaining };\n}\n\n// ---------------------------------------------------------------------------\n// Definitions\n// ---------------------------------------------------------------------------\n\nexport const FreeShippingProgressRootDefinition = defineComponent<FreeShippingProgressRootProps>({\n name: 'FreeShippingProgressRoot',\n importPath: '@vtex/faststore/components',\n component: FreeShippingProgressRoot,\n fragment,\n fetchStrategy: 'reactive',\n editor: { label: 'Free Shipping Progress', category: 'commerce' },\n schema: {},\n guideline:\n 'Free-shipping progress bar for the top of a cart/mini-cart drawer: shows how much more to spend for free shipping and flips to an earned state when met. Renders nothing until a destination and an eligible promotion exist (self-hides on null). See free-shipping-progress.md.',\n});\n\nexport const FreeShippingProgressBarDefinition = defineComponent<FreeShippingProgressBarProps>({\n name: 'FreeShippingProgressBar',\n importPath: '@vtex/faststore/components',\n component: FreeShippingProgressBar,\n editor: { label: 'Free Shipping Progress Bar', category: 'commerce' },\n schema: {},\n guideline:\n 'Meter bar that fills toward the free-shipping goal, full when earned. Must be inside FreeShippingProgressRoot. See free-shipping-progress.md.',\n});\n\nexport const FreeShippingProgressMessageDefinition = defineComponent<FreeShippingProgressMessageProps>({\n name: 'FreeShippingProgressMessage',\n importPath: '@vtex/faststore/components',\n component: FreeShippingProgressMessage,\n editor: { label: 'Free Shipping Progress Message', category: 'commerce' },\n schema: {\n label: { type: 'string', default: 'faltam {value} para frete grátis', label: 'Below-threshold Label' },\n qualifiedLabel: { type: 'string', default: 'você ganhou frete grátis!', label: 'Qualified Label' },\n },\n guideline:\n 'Below-threshold vs earned copy, front-formatted from the active storefront context. Must be inside FreeShippingProgressRoot. See free-shipping-progress.md.',\n});\n\n// ---------------------------------------------------------------------------\n// Implementations\n// ---------------------------------------------------------------------------\n\nexport function FreeShippingProgressRoot({\n threshold,\n remaining,\n qualified,\n itemsTotal,\n $data: $dataProp,\n className,\n children,\n ...props\n}: FreeShippingProgressRootProps) {\n // Only the synthesized preview cart below needs it; the leaves read the context where they format.\n const { currency } = useStorefrontContext();\n const $data = useDataOverride($dataProp);\n\n // Story / presentational overrides synthesize the field when no live cart is present.\n const cart = $data ?? previewCart({ threshold, remaining, qualified, itemsTotal }, currency);\n\n const fsp = cart?.freeShippingProgress;\n if (!cart || fsp == null) return null;\n\n const { isQualified, fill, liveRemaining } = computeProgress(\n fsp,\n itemsSubtotal(cart),\n usableThreshold(fsp.threshold),\n );\n\n const value: FreeShippingProgressContextValue = { isQualified, fill, liveRemaining };\n\n return (\n <FreeShippingProgressContext value={value}>\n <div {...props} className={className} data-fs-free-shipping-progress-root=\"\">\n {children}\n </div>\n </FreeShippingProgressContext>\n );\n}\n\nexport function FreeShippingProgressBar({ className, ...props }: FreeShippingProgressBarProps) {\n const { fill, isQualified, liveRemaining } = useFreeShippingProgress();\n const { locale, currency } = useStorefrontContext();\n const ariaValueText = isQualified\n ? 'frete grátis conquistado'\n : `${formatCurrency(liveRemaining, locale, currency)} restantes para frete grátis`;\n\n return (\n <Meter.Root\n {...props}\n value={Math.round(fill * 100)}\n min={0}\n max={100}\n getAriaValueText={() => ariaValueText}\n className={className}\n data-fs-free-shipping-progress-bar=\"\"\n >\n <Meter.Track>\n <Meter.Indicator />\n </Meter.Track>\n </Meter.Root>\n );\n}\n\nexport function FreeShippingProgressMessage({\n label = 'faltam {value} para frete grátis',\n qualifiedLabel = 'você ganhou frete grátis!',\n className,\n children,\n ...props\n}: FreeShippingProgressMessageProps) {\n const { isQualified, liveRemaining } = useFreeShippingProgress();\n const { locale, currency } = useStorefrontContext();\n const text = isQualified ? qualifiedLabel : label.replace('{value}', formatCurrency(liveRemaining, locale, currency));\n\n return (\n <div {...props} className={className} data-fs-free-shipping-progress-message=\"\">\n {children ?? text}\n </div>\n );\n}\n\nexport const FreeShippingProgress = {\n Root: FreeShippingProgressRoot,\n Bar: FreeShippingProgressBar,\n Message: FreeShippingProgressMessage,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"free-shipping-progress.js","names":[],"sources":["../../../src/matter/free-shipping-progress/free-shipping-progress.tsx"],"sourcesContent":["'use client';\n\nimport { type ContentValue, defineComponent, defineContentType, type MessageLocaleProp } from '@vtex/fs-core';\nimport { type ComponentPropsWithRef, createContext, useContext } from 'react';\nimport { Meter } from '../../particles/meter/meter.js';\nimport { useStorefrontContext } from '../../sdk/context/storefront-context.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport { useMessageFormatter } from '../../sdk/i18n/use-message-formatter.js';\nimport { isFiniteAmount } from '../cart/cart.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype MoneyValue = { amount: number | string; currencyCode: string };\n\ntype FreeShippingProgressData = {\n cart?: {\n id: string;\n totalizers?: { id: string; value: MoneyValue }[] | null;\n freeShippingProgress?: {\n threshold: MoneyValue | null;\n remaining: MoneyValue;\n qualified: boolean;\n } | null;\n } | null;\n};\n\ntype FreeShippingProgressContextValue = {\n isQualified: boolean;\n fill: number;\n liveRemaining: number;\n};\n\nexport type FreeShippingProgressRootProps = ComponentPropsWithRef<'div'> & {\n threshold?: number;\n remaining?: number;\n qualified?: boolean;\n itemsTotal?: number;\n $data?: FreeShippingProgressData['cart'] | null;\n};\n\nexport const FreeShippingProgressMessageContent = defineContentType({\n id: 'free-shipping-progress-message',\n title: 'Free Shipping Progress Message',\n description: 'The below-threshold and earned free-shipping messages.',\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n label: {\n type: 'string',\n title: 'Below-threshold label',\n description: 'Shown while the cart is below the threshold; value is the formatted amount still missing.',\n format: 'icu-message',\n messageSource: '{value} away from free shipping',\n messageArguments: { type: 'object', properties: { value: { type: 'string' } } },\n messageExample: { value: '$25.00' },\n },\n qualifiedLabel: {\n type: 'string',\n title: 'Qualified label',\n format: 'icu-message',\n messageSource: 'You got free shipping!',\n },\n },\n },\n});\n\nexport const FreeShippingProgressBarContent = defineContentType({\n id: 'free-shipping-progress-bar',\n title: 'Free Shipping Progress Bar',\n description: 'The value text a screen reader announces for the progress bar.',\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n valueText: {\n type: 'string',\n title: 'Below-threshold value text',\n description: 'Announced while the cart is below the threshold; value is the formatted amount still missing.',\n format: 'icu-message',\n messageSource: '{value} left for free shipping',\n messageArguments: { type: 'object', properties: { value: { type: 'string' } } },\n messageExample: { value: '$25.00' },\n },\n qualifiedValueText: {\n type: 'string',\n title: 'Qualified value text',\n format: 'icu-message',\n messageSource: 'Free shipping earned',\n },\n },\n },\n});\n\nexport type FreeShippingProgressBarProps = ComponentPropsWithRef<'div'> &\n MessageLocaleProp & {\n $content?: ContentValue<typeof FreeShippingProgressBarContent>;\n };\nexport type FreeShippingProgressMessageProps = ComponentPropsWithRef<'div'> &\n MessageLocaleProp & {\n $content?: ContentValue<typeof FreeShippingProgressMessageContent>;\n };\n\n// ---------------------------------------------------------------------------\n// GraphQL Fragment — narrow cart slice (Items totalizer + freeShippingProgress)\n// ---------------------------------------------------------------------------\n\nconst fragment = /* GraphQL */ `\n fragment FreeShippingProgressData on Query {\n cart {\n id\n totalizers {\n id\n value {\n amount\n currencyCode\n }\n }\n freeShippingProgress {\n threshold {\n amount\n currencyCode\n }\n remaining {\n amount\n currencyCode\n }\n qualified\n }\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst FSP_CONTEXT_UNSET = Symbol('FreeShippingProgressContextUnset');\n\nconst FreeShippingProgressContext = createContext<FreeShippingProgressContextValue | typeof FSP_CONTEXT_UNSET>(\n FSP_CONTEXT_UNSET,\n);\n\nfunction useFreeShippingProgress(): FreeShippingProgressContextValue {\n const ctx = useContext(FreeShippingProgressContext);\n if (ctx === FSP_CONTEXT_UNSET) {\n throw new Error('useFreeShippingProgress() must be used inside a <FreeShippingProgressRoot> subtree.');\n }\n return ctx;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction formatCurrency(value: number, locale: string, currency: string): string {\n return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(value);\n}\n\nfunction clamp01(value: number): number {\n return Math.min(Math.max(value, 0), 1);\n}\n\ntype FreeShippingProgressCart = NonNullable<FreeShippingProgressData['cart']>;\ntype FreeShippingProgressState = NonNullable<FreeShippingProgressCart['freeShippingProgress']>;\n\nfunction previewCart(\n {\n threshold,\n remaining,\n qualified,\n itemsTotal,\n }: Pick<FreeShippingProgressRootProps, 'threshold' | 'remaining' | 'qualified' | 'itemsTotal'>,\n currency: string,\n): FreeShippingProgressCart | null {\n if (qualified === undefined && threshold === undefined && remaining === undefined && itemsTotal === undefined) {\n return null;\n }\n return {\n id: 'preview',\n totalizers:\n itemsTotal === undefined ? [] : [{ id: 'Items', value: { amount: itemsTotal, currencyCode: currency } }],\n freeShippingProgress: {\n threshold: threshold == null ? null : { amount: threshold, currencyCode: currency },\n remaining: { amount: remaining ?? threshold ?? 0, currencyCode: currency },\n qualified: qualified ?? false,\n },\n };\n}\n\n// The server measures the Items totalizer, never the grand total (shipping and discounts do not count).\nfunction itemsSubtotal(cart: FreeShippingProgressCart): number | null {\n const itemsAmount = cart.totalizers?.find((totalizer) => totalizer.id === 'Items')?.value.amount;\n return isFiniteAmount(itemsAmount) ? Number(itemsAmount) : null;\n}\n\n// Usable threshold: present, finite, positive. Null/NaN/zero → no fill, no remaining.\nfunction usableThreshold(threshold: MoneyValue | null): number | null {\n if (threshold == null) return null;\n const parsed = Number(threshold.amount);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : null;\n}\n\nfunction fillRatio(isQualified: boolean, thresholdAmount: number | null, covered: number): number {\n if (isQualified) return 1;\n if (thresholdAmount === null) return 0;\n return clamp01(covered / thresholdAmount);\n}\n\nfunction computeProgress(\n fsp: FreeShippingProgressState,\n items: number | null,\n thresholdAmount: number | null,\n): FreeShippingProgressContextValue {\n if (items === null) {\n // No usable Items amount: show the server's own answer rather than guess.\n const isQualified = fsp.qualified;\n const liveRemaining =\n !isQualified && isFiniteAmount(fsp.remaining.amount) ? Math.max(Number(fsp.remaining.amount), 0) : 0;\n const fill = fillRatio(isQualified, thresholdAmount, (thresholdAmount ?? 0) - liveRemaining);\n return { isQualified, fill, liveRemaining };\n }\n\n const isQualified = fsp.qualified || (thresholdAmount !== null && items >= thresholdAmount);\n const liveRemaining = isQualified || thresholdAmount === null ? 0 : Math.max(thresholdAmount - items, 0);\n return { isQualified, fill: fillRatio(isQualified, thresholdAmount, items), liveRemaining };\n}\n\n// ---------------------------------------------------------------------------\n// Definitions\n// ---------------------------------------------------------------------------\n\nexport const FreeShippingProgressRootDefinition = defineComponent<FreeShippingProgressRootProps>({\n name: 'FreeShippingProgressRoot',\n importPath: '@vtex/faststore/components',\n component: FreeShippingProgressRoot,\n fragment,\n fetchStrategy: 'reactive',\n editor: { label: 'Free Shipping Progress', category: 'commerce' },\n schema: {},\n guideline:\n 'Free-shipping progress bar for the top of a cart/mini-cart drawer: shows how much more to spend for free shipping and flips to an earned state when met. Renders nothing until a destination and an eligible promotion exist (self-hides on null). See free-shipping-progress.md.',\n});\n\nexport const FreeShippingProgressBarDefinition = defineComponent<FreeShippingProgressBarProps>({\n name: 'FreeShippingProgressBar',\n importPath: '@vtex/faststore/components',\n component: FreeShippingProgressBar,\n content: FreeShippingProgressBarContent,\n editor: { label: 'Free Shipping Progress Bar', category: 'commerce' },\n schema: {},\n guideline:\n 'Meter bar that fills toward the free-shipping goal, full when earned; screen readers announce the $content fields valueText ({value} is the formatted remaining amount) and qualifiedValueText. Must be inside FreeShippingProgressRoot. See free-shipping-progress.md.',\n});\n\nexport const FreeShippingProgressMessageDefinition = defineComponent<FreeShippingProgressMessageProps>({\n name: 'FreeShippingProgressMessage',\n importPath: '@vtex/faststore/components',\n component: FreeShippingProgressMessage,\n content: FreeShippingProgressMessageContent,\n editor: { label: 'Free Shipping Progress Message', category: 'commerce' },\n schema: {},\n guideline:\n 'Below-threshold vs earned copy from the $content fields label ({value} is the formatted remaining amount) and qualifiedLabel; children replace both. Must be inside FreeShippingProgressRoot. See free-shipping-progress.md.',\n});\n\n// ---------------------------------------------------------------------------\n// Implementations\n// ---------------------------------------------------------------------------\n\nexport function FreeShippingProgressRoot({\n threshold,\n remaining,\n qualified,\n itemsTotal,\n $data: $dataProp,\n className,\n children,\n ...props\n}: FreeShippingProgressRootProps) {\n // Only the synthesized preview cart below needs it; the leaves read the context where they format.\n const { currency } = useStorefrontContext();\n const $data = useDataOverride($dataProp);\n\n // Story / presentational overrides synthesize the field when no live cart is present.\n const cart = $data ?? previewCart({ threshold, remaining, qualified, itemsTotal }, currency);\n\n const fsp = cart?.freeShippingProgress;\n if (!cart || fsp == null) return null;\n\n const { isQualified, fill, liveRemaining } = computeProgress(\n fsp,\n itemsSubtotal(cart),\n usableThreshold(fsp.threshold),\n );\n\n const value: FreeShippingProgressContextValue = { isQualified, fill, liveRemaining };\n\n return (\n <FreeShippingProgressContext value={value}>\n <div {...props} className={className} data-fs-free-shipping-progress-root=\"\">\n {children}\n </div>\n </FreeShippingProgressContext>\n );\n}\n\nexport function FreeShippingProgressBar({ $content, $locale, className, ...props }: FreeShippingProgressBarProps) {\n const { fill, isQualified, liveRemaining } = useFreeShippingProgress();\n const { locale, currency } = useStorefrontContext();\n const { format } = useMessageFormatter(FreeShippingProgressBarContent, $content);\n const ariaValueText = isQualified\n ? format('qualifiedValueText')\n : format('valueText', { value: formatCurrency(liveRemaining, locale, currency) });\n\n return (\n <Meter.Root\n aria-label=\"Progresso para frete grátis\"\n {...props}\n value={Math.round(fill * 100)}\n min={0}\n max={100}\n getAriaValueText={() => ariaValueText}\n className={className}\n data-fs-free-shipping-progress-bar=\"\"\n >\n <Meter.Track>\n <Meter.Indicator />\n </Meter.Track>\n </Meter.Root>\n );\n}\n\nexport function FreeShippingProgressMessage({\n $content,\n $locale,\n className,\n children,\n ...props\n}: FreeShippingProgressMessageProps) {\n const { isQualified, liveRemaining } = useFreeShippingProgress();\n const { locale, currency } = useStorefrontContext();\n const { format } = useMessageFormatter(FreeShippingProgressMessageContent, $content);\n\n function message(): string {\n if (isQualified) return format('qualifiedLabel');\n return format('label', { value: formatCurrency(liveRemaining, locale, currency) });\n }\n\n return (\n <div {...props} className={className} data-fs-free-shipping-progress-message=\"\">\n {children ?? message()}\n </div>\n );\n}\n\nexport const FreeShippingProgress = {\n Root: FreeShippingProgressRoot,\n Bar: FreeShippingProgressBar,\n Message: FreeShippingProgressMessage,\n};\n"],"mappings":"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"}
|