@vtex/faststore 0.0.8 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +101 -0
- package/README.md +0 -1
- package/dist/actions.json +48 -1
- package/dist/catalog.json +1397 -1594
- package/dist/cli/index.d.ts +66 -28
- package/dist/cli/index.js +7371 -512
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/server-runtime.js +41 -60
- package/dist/cli/server-runtime.js.map +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/client.js +2 -2
- package/dist/components.d.ts +67 -56
- package/dist/components.js +64 -53
- package/dist/content-types.json +5886 -555
- package/dist/core/dist/define-component.d.ts +7 -2
- package/dist/core/dist/define-content-type.d.ts +50 -2
- package/dist/core/dist/define-content-type.js +107 -3
- package/dist/core/dist/define-content-type.js.map +1 -1
- package/dist/core/dist/index.d.ts +2 -2
- package/dist/docs/access-code-field.md +1 -1
- package/dist/docs/access-code-sign-in.md +126 -77
- package/dist/docs/account-address-book.md +210 -95
- package/dist/docs/account-entry-point.md +4 -4
- package/dist/docs/account-menu.md +16 -17
- package/dist/docs/account-saved-cards.md +306 -0
- package/dist/docs/alert-dialog.md +3 -1
- package/dist/docs/avatar.md +4 -2
- package/dist/docs/billing-address.md +99 -30
- package/dist/docs/binding-switcher.md +157 -0
- package/dist/docs/buy-button.md +7 -8
- package/dist/docs/card-entry.md +42 -29
- package/dist/docs/card-summary.md +185 -0
- package/dist/docs/cardholder-document.md +5 -3
- package/dist/docs/carousel.md +5 -4
- package/dist/docs/cart-destination.md +251 -0
- package/dist/docs/cart-item.md +48 -15
- package/dist/docs/cart-totalizer.md +8 -6
- package/dist/docs/cart.md +240 -39
- package/dist/docs/challenge-return.md +135 -0
- package/dist/docs/client-preferences-fieldset.md +10 -5
- package/dist/docs/client-preferences.md +31 -8
- package/dist/docs/client-profile-fieldset.md +20 -6
- package/dist/docs/client-profile.md +12 -3
- package/dist/docs/copy-text.md +9 -7
- package/dist/docs/document-field.md +1 -1
- package/dist/docs/email-field.md +2 -1
- package/dist/docs/email-identification.md +12 -2
- package/dist/docs/footer-copyright.md +4 -2
- package/dist/docs/footer-social.md +1 -1
- package/dist/docs/form.md +54 -18
- package/dist/docs/free-shipping-progress.md +18 -13
- package/dist/docs/identity-edit.md +8 -2
- package/dist/docs/identity-summary.md +18 -5
- package/dist/docs/incentives.md +2 -2
- package/dist/docs/installments.md +46 -32
- package/dist/docs/logo.md +1 -1
- package/dist/docs/my-account-profile.md +16 -11
- package/dist/docs/navigation-link.md +5 -3
- package/dist/docs/order-cancel.md +3 -1
- package/dist/docs/order-delivery-address.md +7 -5
- package/dist/docs/order-delivery-group.md +1 -3
- package/dist/docs/order-details-back.md +1 -1
- package/dist/docs/order-details-header.md +1 -4
- package/dist/docs/order-invoice-download.md +60 -0
- package/dist/docs/order-list-row.md +1 -1
- package/dist/docs/order-list-search.md +13 -20
- package/dist/docs/order-list-views.md +11 -17
- package/dist/docs/order-list.md +12 -5
- package/dist/docs/order-payment.md +9 -7
- package/dist/docs/order-placed-date.md +1 -1
- package/dist/docs/order-placed-payment-summary.md +28 -15
- package/dist/docs/order-placed.md +49 -14
- package/dist/docs/order-progress.md +1 -1
- package/dist/docs/order-status-badge.md +20 -9
- package/dist/docs/order-summary.md +2 -2
- package/dist/docs/order-tracking-link.md +58 -0
- package/dist/docs/payment-method-badges.md +32 -6
- package/dist/docs/payment-methods.md +2 -2
- package/dist/docs/payment.md +36 -17
- package/dist/docs/phone-field.md +4 -4
- package/dist/docs/place-order.md +84 -36
- package/dist/docs/postal-code-field.md +3 -1
- package/dist/docs/pricing.md +21 -23
- package/dist/docs/product-gallery.md +19 -20
- package/dist/docs/product-information.md +14 -10
- package/dist/docs/product-list.md +7 -6
- package/dist/docs/product-shelf.md +7 -1
- package/dist/docs/promotion.md +4 -2
- package/dist/docs/region.md +23 -15
- package/dist/docs/save-card.md +7 -6
- package/dist/docs/saved-cards.md +65 -36
- package/dist/docs/select.md +3 -4
- package/dist/docs/shipping-address.md +57 -21
- package/dist/docs/shipping-simulator.md +53 -15
- package/dist/docs/sign-in-disclosure.md +176 -0
- package/dist/docs/sign-in-form.md +78 -47
- package/dist/docs/sign-in-redirect.md +5 -3
- package/dist/docs/sign-in.md +173 -0
- package/dist/docs/toast.md +45 -16
- package/dist/docs/variant-selector.md +15 -11
- package/dist/graphql/types.d.ts +4 -14
- package/dist/index.d.ts +3 -2
- package/dist/internal/client.d.ts +4 -3
- package/dist/internal/client.js +5 -2
- package/dist/internal/server.d.ts +10 -5
- package/dist/internal/server.js +9 -4
- package/dist/matter/access-code-sign-in/access-code-sign-in.d.ts +250 -66
- package/dist/matter/access-code-sign-in/access-code-sign-in.js +459 -188
- package/dist/matter/access-code-sign-in/access-code-sign-in.js.map +1 -1
- package/dist/matter/account-address-book/account-address-book-delete.d.ts +78 -40
- package/dist/matter/account-address-book/account-address-book-delete.js +86 -50
- package/dist/matter/account-address-book/account-address-book-delete.js.map +1 -1
- package/dist/matter/account-address-book/account-address-book-deliverability.d.ts +21 -4
- package/dist/matter/account-address-book/account-address-book-deliverability.js +45 -17
- package/dist/matter/account-address-book/account-address-book-deliverability.js.map +1 -1
- package/dist/matter/account-address-book/account-address-book-form-parts.d.ts +74 -19
- package/dist/matter/account-address-book/account-address-book-form-parts.js +77 -26
- package/dist/matter/account-address-book/account-address-book-form-parts.js.map +1 -1
- package/dist/matter/account-address-book/account-address-book-profile-notice.d.ts +27 -6
- package/dist/matter/account-address-book/account-address-book-profile-notice.js +55 -28
- package/dist/matter/account-address-book/account-address-book-profile-notice.js.map +1 -1
- package/dist/matter/account-address-book/account-address-book.d.ts +67 -14
- package/dist/matter/account-address-book/account-address-book.js +74 -33
- package/dist/matter/account-address-book/account-address-book.js.map +1 -1
- package/dist/matter/account-address-book/account-address-country-switch.js +3 -3
- package/dist/matter/account-address-book/account-address-country-switch.js.map +1 -1
- package/dist/matter/account-address-book/account-address-country.d.ts +66 -20
- package/dist/matter/account-address-book/account-address-country.js +83 -49
- package/dist/matter/account-address-book/account-address-country.js.map +1 -1
- package/dist/matter/account-address-book/account-address-form-context.d.ts +8 -4
- package/dist/matter/account-address-book/account-address-form-context.js.map +1 -1
- package/dist/matter/account-address-book/account-address-form.d.ts +468 -45
- package/dist/matter/account-address-book/account-address-form.js +518 -155
- package/dist/matter/account-address-book/account-address-form.js.map +1 -1
- package/dist/matter/account-address-book/account-address-record.d.ts +27 -6
- package/dist/matter/account-address-book/account-address-record.js +32 -17
- package/dist/matter/account-address-book/account-address-record.js.map +1 -1
- package/dist/matter/account-menu/account-menu.d.ts +34 -17
- package/dist/matter/account-menu/account-menu.js +46 -54
- package/dist/matter/account-menu/account-menu.js.map +1 -1
- package/dist/matter/account-menu-identity/account-menu-identity.js +1 -1
- package/dist/matter/account-saved-cards/account-saved-cards.d.ts +463 -0
- package/dist/matter/account-saved-cards/account-saved-cards.js +1011 -0
- package/dist/matter/account-saved-cards/account-saved-cards.js.map +1 -0
- package/dist/matter/billing-address/billing-address.d.ts +156 -74
- package/dist/matter/billing-address/billing-address.js +227 -156
- package/dist/matter/billing-address/billing-address.js.map +1 -1
- package/dist/matter/breadcrumb/breadcrumb.d.ts +21 -3
- package/dist/matter/breadcrumb/breadcrumb.js +24 -9
- package/dist/matter/breadcrumb/breadcrumb.js.map +1 -1
- package/dist/matter/buy-button/buy-button.d.ts +8 -11
- package/dist/matter/buy-button/buy-button.js +10 -19
- package/dist/matter/buy-button/buy-button.js.map +1 -1
- package/dist/matter/card-entry/card-capture.js +12 -4
- package/dist/matter/card-entry/card-capture.js.map +1 -1
- package/dist/matter/card-entry/card-entry.d.ts +123 -32
- package/dist/matter/card-entry/card-entry.js +348 -221
- package/dist/matter/card-entry/card-entry.js.map +1 -1
- package/dist/matter/cart/cart-namespace.d.ts +11 -1
- package/dist/matter/cart/cart-namespace.js +11 -1
- package/dist/matter/cart/cart-namespace.js.map +1 -1
- package/dist/matter/cart/cart.d.ts +416 -45
- package/dist/matter/cart/cart.js +782 -101
- package/dist/matter/cart/cart.js.map +1 -1
- package/dist/matter/cart-destination/cart-destination.d.ts +233 -0
- package/dist/matter/cart-destination/cart-destination.js +703 -0
- package/dist/matter/cart-destination/cart-destination.js.map +1 -0
- package/dist/matter/cart-item/cart-item.d.ts +145 -16
- package/dist/matter/cart-item/cart-item.js +230 -54
- package/dist/matter/cart-item/cart-item.js.map +1 -1
- package/dist/matter/cart-item-compositions/cart-item-compositions.js +1 -1
- package/dist/matter/cart-item-compositions/cart-item-compositions.js.map +1 -1
- package/dist/matter/cart-item-customizations/cart-item-customizations.js +1 -1
- package/dist/matter/cart-item-customizations/cart-item-customizations.js.map +1 -1
- package/dist/matter/cart-item-discounts/cart-item-discounts.js +1 -1
- package/dist/matter/cart-item-discounts/cart-item-discounts.js.map +1 -1
- package/dist/matter/cart-item-seller-info/cart-item-seller-info.js +1 -1
- package/dist/matter/cart-item-seller-info/cart-item-seller-info.js.map +1 -1
- package/dist/matter/cart-item-variations/cart-item-variations.js +1 -1
- package/dist/matter/cart-item-variations/cart-item-variations.js.map +1 -1
- package/dist/matter/cart-totalizer/cart-totalizer.d.ts +43 -9
- package/dist/matter/cart-totalizer/cart-totalizer.js +49 -19
- package/dist/matter/cart-totalizer/cart-totalizer.js.map +1 -1
- package/dist/matter/challenge-return/challenge-return.d.ts +62 -0
- package/dist/matter/challenge-return/challenge-return.js +241 -0
- package/dist/matter/challenge-return/challenge-return.js.map +1 -0
- package/dist/matter/client-preferences/client-preferences-fieldset.d.ts +86 -17
- package/dist/matter/client-preferences/client-preferences-fieldset.js +126 -54
- package/dist/matter/client-preferences/client-preferences-fieldset.js.map +1 -1
- package/dist/matter/client-preferences/client-preferences.d.ts +50 -7
- package/dist/matter/client-preferences/client-preferences.js +84 -15
- package/dist/matter/client-preferences/client-preferences.js.map +1 -1
- package/dist/matter/client-profile/client-profile.d.ts +44 -9
- package/dist/matter/client-profile/client-profile.js +64 -24
- package/dist/matter/client-profile/client-profile.js.map +1 -1
- package/dist/matter/client-profile-form/client-profile-fieldset.d.ts +119 -22
- package/dist/matter/client-profile-form/client-profile-fieldset.js +161 -73
- package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -1
- package/dist/matter/delivery-options/delivery-options-accordion.d.ts +49 -4
- package/dist/matter/delivery-options/delivery-options-accordion.js +67 -14
- package/dist/matter/delivery-options/delivery-options-accordion.js.map +1 -1
- package/dist/matter/delivery-options/delivery-options-controller.d.ts +69 -9
- package/dist/matter/delivery-options/delivery-options-controller.js +80 -14
- package/dist/matter/delivery-options/delivery-options-controller.js.map +1 -1
- package/dist/matter/delivery-options/delivery-options.d.ts +37 -2
- package/dist/matter/delivery-options/delivery-options.js +75 -12
- package/dist/matter/delivery-options/delivery-options.js.map +1 -1
- package/dist/matter/delivery-options/use-delivery-option-selection.d.ts +1 -0
- package/dist/matter/delivery-options/use-delivery-option-selection.js +1 -1
- package/dist/matter/delivery-options/use-delivery-option-selection.js.map +1 -1
- package/dist/matter/email-identification/email-identification.d.ts +25 -3
- package/dist/matter/email-identification/email-identification.js +49 -12
- package/dist/matter/email-identification/email-identification.js.map +1 -1
- package/dist/matter/free-shipping-progress/free-shipping-progress.d.ts +85 -10
- package/dist/matter/free-shipping-progress/free-shipping-progress.js +153 -53
- package/dist/matter/free-shipping-progress/free-shipping-progress.js.map +1 -1
- package/dist/matter/identity-edit/identity-edit.d.ts +52 -10
- package/dist/matter/identity-edit/identity-edit.js +47 -19
- package/dist/matter/identity-edit/identity-edit.js.map +1 -1
- package/dist/matter/identity-summary/identity-summary.d.ts +76 -22
- package/dist/matter/identity-summary/identity-summary.js +95 -45
- package/dist/matter/identity-summary/identity-summary.js.map +1 -1
- package/dist/matter/installments/installments-select.d.ts +98 -16
- package/dist/matter/installments/installments-select.js +156 -48
- package/dist/matter/installments/installments-select.js.map +1 -1
- package/dist/matter/installments/installments.d.ts +96 -16
- package/dist/matter/installments/installments.js +115 -40
- package/dist/matter/installments/installments.js.map +1 -1
- package/dist/matter/installments/use-installments-selection.d.ts +1 -0
- package/dist/matter/installments/use-installments-selection.js +8 -3
- package/dist/matter/installments/use-installments-selection.js.map +1 -1
- package/dist/matter/my-account-profile/my-account-profile.d.ts +358 -103
- package/dist/matter/my-account-profile/my-account-profile.js +370 -174
- package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
- package/dist/matter/order-cancel/order-cancel.d.ts +65 -19
- package/dist/matter/order-cancel/order-cancel.js +118 -51
- package/dist/matter/order-cancel/order-cancel.js.map +1 -1
- package/dist/matter/order-delivery-address/order-delivery-address.d.ts +8 -18
- package/dist/matter/order-delivery-address/order-delivery-address.js +14 -23
- package/dist/matter/order-delivery-address/order-delivery-address.js.map +1 -1
- package/dist/matter/order-delivery-group/order-delivery-group.d.ts +40 -24
- package/dist/matter/order-delivery-group/order-delivery-group.js +64 -74
- package/dist/matter/order-delivery-group/order-delivery-group.js.map +1 -1
- package/dist/matter/order-details-header/order-details-header.d.ts +32 -15
- package/dist/matter/order-details-header/order-details-header.js +66 -58
- package/dist/matter/order-details-header/order-details-header.js.map +1 -1
- package/dist/matter/order-invoice-download/order-invoice-download.d.ts +78 -0
- package/dist/matter/order-invoice-download/order-invoice-download.js +173 -0
- package/dist/matter/order-invoice-download/order-invoice-download.js.map +1 -0
- package/dist/matter/order-list/order-list.d.ts +164 -19
- package/dist/matter/order-list/order-list.js +229 -87
- package/dist/matter/order-list/order-list.js.map +1 -1
- package/dist/matter/order-list-row/order-list-row.d.ts +6 -1
- package/dist/matter/order-list-row/order-list-row.js +3 -2
- package/dist/matter/order-list-row/order-list-row.js.map +1 -1
- package/dist/matter/order-list-search/order-list-search.d.ts +18 -26
- package/dist/matter/order-list-search/order-list-search.js +30 -69
- package/dist/matter/order-list-search/order-list-search.js.map +1 -1
- package/dist/matter/order-list-views/order-list-views.d.ts +15 -22
- package/dist/matter/order-list-views/order-list-views.js +22 -68
- package/dist/matter/order-list-views/order-list-views.js.map +1 -1
- package/dist/matter/order-payment/order-payment.d.ts +33 -10
- package/dist/matter/order-payment/order-payment.js +44 -39
- package/dist/matter/order-payment/order-payment.js.map +1 -1
- package/dist/matter/order-placed/order-placed-deliveries.d.ts +144 -12
- package/dist/matter/order-placed/order-placed-deliveries.js +115 -40
- package/dist/matter/order-placed/order-placed-deliveries.js.map +1 -1
- package/dist/matter/order-placed/order-placed.d.ts +198 -31
- package/dist/matter/order-placed/order-placed.js +230 -139
- package/dist/matter/order-placed/order-placed.js.map +1 -1
- package/dist/matter/order-placed-date/order-placed-date.d.ts +5 -8
- package/dist/matter/order-placed-date/order-placed-date.js +7 -8
- package/dist/matter/order-placed-date/order-placed-date.js.map +1 -1
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +90 -17
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +93 -117
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -1
- package/dist/matter/order-progress/order-progress.d.ts +19 -8
- package/dist/matter/order-progress/order-progress.js +37 -45
- package/dist/matter/order-progress/order-progress.js.map +1 -1
- package/dist/matter/order-summary/order-summary.d.ts +19 -9
- package/dist/matter/order-summary/order-summary.js +38 -44
- package/dist/matter/order-summary/order-summary.js.map +1 -1
- package/dist/matter/order-tracking-link/order-tracking-link.d.ts +43 -0
- package/dist/matter/order-tracking-link/order-tracking-link.js +107 -0
- package/dist/matter/order-tracking-link/order-tracking-link.js.map +1 -0
- package/dist/matter/payment/payment-card-capture.js +17 -10
- package/dist/matter/payment/payment-card-capture.js.map +1 -1
- package/dist/matter/payment/payment-controller.d.ts +4 -2
- package/dist/matter/payment/payment-controller.js +30 -9
- package/dist/matter/payment/payment-controller.js.map +1 -1
- package/dist/matter/payment/payment-method-badges.js +1 -1
- package/dist/matter/payment/payment.d.ts +69 -19
- package/dist/matter/payment/payment.js +101 -35
- package/dist/matter/payment/payment.js.map +1 -1
- package/dist/matter/payment/use-payment-method-selection.d.ts +25 -4
- package/dist/matter/payment/use-payment-method-selection.js +94 -32
- package/dist/matter/payment/use-payment-method-selection.js.map +1 -1
- package/dist/matter/payment/use-payment-submit-gate.d.ts +14 -3
- package/dist/matter/payment/use-payment-submit-gate.js +47 -8
- package/dist/matter/payment/use-payment-submit-gate.js.map +1 -1
- package/dist/matter/place-order/place-order.d.ts +171 -57
- package/dist/matter/place-order/place-order.js +376 -185
- package/dist/matter/place-order/place-order.js.map +1 -1
- package/dist/matter/pricing/pricing.d.ts +152 -13
- package/dist/matter/pricing/pricing.js +153 -52
- package/dist/matter/pricing/pricing.js.map +1 -1
- package/dist/matter/product-information/product-information.d.ts +27 -4
- package/dist/matter/product-information/product-information.js +32 -15
- package/dist/matter/product-information/product-information.js.map +1 -1
- package/dist/matter/product-list/product-list.d.ts +24 -6
- package/dist/matter/product-list/product-list.js +32 -26
- package/dist/matter/product-list/product-list.js.map +1 -1
- package/dist/matter/product-shelf/product-shelf.d.ts +8 -3
- package/dist/matter/product-shelf/product-shelf.js +111 -10
- package/dist/matter/product-shelf/product-shelf.js.map +1 -1
- package/dist/matter/region/region.d.ts +33 -16
- package/dist/matter/region/region.js +59 -52
- package/dist/matter/region/region.js.map +1 -1
- package/dist/matter/save-card/save-card.d.ts +43 -8
- package/dist/matter/save-card/save-card.js +61 -23
- package/dist/matter/save-card/save-card.js.map +1 -1
- package/dist/matter/saved-cards/saved-cards.d.ts +113 -21
- package/dist/matter/saved-cards/saved-cards.js +349 -77
- package/dist/matter/saved-cards/saved-cards.js.map +1 -1
- package/dist/matter/shipping-address/address-payload.js +25 -0
- package/dist/matter/shipping-address/address-payload.js.map +1 -0
- package/dist/matter/shipping-address/country-descriptors.js +71 -71
- package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
- package/dist/matter/shipping-address/library-country-descriptors.js +136 -0
- package/dist/matter/shipping-address/library-country-descriptors.js.map +1 -0
- package/dist/matter/shipping-address/shipping-address.d.ts +312 -45
- package/dist/matter/shipping-address/shipping-address.js +443 -188
- package/dist/matter/shipping-address/shipping-address.js.map +1 -1
- package/dist/matter/shipping-simulator/shipping-simulator.d.ts +251 -25
- package/dist/matter/shipping-simulator/shipping-simulator.js +261 -51
- package/dist/matter/shipping-simulator/shipping-simulator.js.map +1 -1
- package/dist/matter/sign-in/sign-in.d.ts +108 -0
- package/dist/matter/sign-in/sign-in.js +285 -0
- package/dist/matter/sign-in/sign-in.js.map +1 -0
- package/dist/matter/sign-in-disclosure/sign-in-disclosure.d.ts +81 -0
- package/dist/matter/sign-in-disclosure/sign-in-disclosure.js +232 -0
- package/dist/matter/sign-in-disclosure/sign-in-disclosure.js.map +1 -0
- package/dist/matter/sign-in-form/sign-in-form.d.ts +93 -62
- package/dist/matter/sign-in-form/sign-in-form.js +134 -144
- package/dist/matter/sign-in-form/sign-in-form.js.map +1 -1
- package/dist/particles/binding-switcher/binding-switcher.d.ts +59 -0
- package/dist/particles/binding-switcher/binding-switcher.js +194 -0
- package/dist/particles/binding-switcher/binding-switcher.js.map +1 -0
- package/dist/particles/card-summary/card-network.d.ts +17 -0
- package/dist/particles/card-summary/card-network.js +25 -0
- package/dist/particles/card-summary/card-network.js.map +1 -0
- package/dist/particles/card-summary/card-summary.d.ts +113 -0
- package/dist/particles/card-summary/card-summary.js +221 -0
- package/dist/particles/card-summary/card-summary.js.map +1 -0
- package/dist/particles/carousel/carousel.d.ts +99 -11
- package/dist/particles/carousel/carousel.js +103 -35
- package/dist/particles/carousel/carousel.js.map +1 -1
- package/dist/particles/copy-text/copy-text.js +5 -15
- package/dist/particles/copy-text/copy-text.js.map +1 -1
- package/dist/particles/dialog/dialog.d.ts +14 -6
- package/dist/particles/dialog/dialog.js +6 -3
- package/dist/particles/dialog/dialog.js.map +1 -1
- package/dist/particles/drawer/drawer.js +1 -1
- package/dist/particles/drawer/drawer.js.map +1 -1
- package/dist/particles/email-field/email-field.d.ts +2 -1
- package/dist/particles/email-field/email-field.js +2 -1
- package/dist/particles/email-field/email-field.js.map +1 -1
- package/dist/particles/footer-link-group/footer-link-group.js +1 -0
- package/dist/particles/footer-link-group/footer-link-group.js.map +1 -1
- package/dist/particles/footer-social/footer-social.d.ts +1 -1
- package/dist/particles/footer-social/footer-social.js +1 -1
- package/dist/particles/footer-social/footer-social.js.map +1 -1
- package/dist/particles/form/form.d.ts +85 -13
- package/dist/particles/form/form.js +91 -42
- package/dist/particles/form/form.js.map +1 -1
- package/dist/particles/gallery/gallery.d.ts +129 -12
- package/dist/particles/gallery/gallery.js +121 -34
- package/dist/particles/gallery/gallery.js.map +1 -1
- package/dist/particles/incentives/incentives.d.ts +1 -1
- package/dist/particles/incentives/incentives.js +1 -1
- package/dist/particles/incentives/incentives.js.map +1 -1
- package/dist/particles/order-details-back/order-details-back.d.ts +5 -3
- package/dist/particles/order-details-back/order-details-back.js +8 -10
- package/dist/particles/order-details-back/order-details-back.js.map +1 -1
- package/dist/particles/order-status-badge/order-status-badge.d.ts +3 -3
- package/dist/particles/order-status-badge/order-status-badge.js +4 -20
- package/dist/particles/order-status-badge/order-status-badge.js.map +1 -1
- package/dist/particles/password-field/password-field.d.ts +1 -1
- package/dist/particles/password-field/password-field.js +2 -4
- package/dist/particles/password-field/password-field.js.map +1 -1
- package/dist/particles/payment-methods/payment-methods.d.ts +1 -1
- package/dist/particles/payment-methods/payment-methods.js +1 -1
- package/dist/particles/payment-methods/payment-methods.js.map +1 -1
- package/dist/particles/phone-field/phone-field.d.ts +4 -4
- package/dist/particles/phone-field/phone-field.js +8 -11
- package/dist/particles/phone-field/phone-field.js.map +1 -1
- package/dist/particles/spinner/spinner.d.ts +24 -4
- package/dist/particles/spinner/spinner.js +25 -9
- package/dist/particles/spinner/spinner.js.map +1 -1
- package/dist/particles/switch/switch.d.ts +4 -1
- package/dist/particles/switch/switch.js +3 -1
- package/dist/particles/switch/switch.js.map +1 -1
- package/dist/particles/toast/toast.d.ts +49 -9
- package/dist/particles/toast/toast.js +81 -15
- package/dist/particles/toast/toast.js.map +1 -1
- package/dist/schema.graphql +461 -89
- package/dist/sdk/actions/index.d.ts +3 -1
- package/dist/sdk/actions/index.js +3 -1
- package/dist/sdk/actions/locale-action-provider.d.ts +16 -0
- package/dist/sdk/actions/locale-action-provider.js +20 -0
- package/dist/sdk/actions/locale-action-provider.js.map +1 -0
- package/dist/sdk/actions/saved-card-action-provider.d.ts +12 -0
- package/dist/sdk/actions/saved-card-action-provider.js +16 -0
- package/dist/sdk/actions/saved-card-action-provider.js.map +1 -0
- package/dist/sdk/actions/types.d.ts +6 -2
- package/dist/sdk/address/address-fields.js +4 -4
- package/dist/sdk/address/address-fields.js.map +1 -1
- package/dist/sdk/address/constants.js +1 -6
- package/dist/sdk/address/constants.js.map +1 -1
- package/dist/sdk/address/messages.js +44 -44
- package/dist/sdk/address/messages.js.map +1 -1
- package/dist/sdk/address/postal-code.js +15 -2
- package/dist/sdk/address/postal-code.js.map +1 -1
- package/dist/sdk/address/types.d.ts +5 -3
- package/dist/sdk/address/validate-address.js +3 -3
- package/dist/sdk/address/validate-address.js.map +1 -1
- package/dist/sdk/analytics/use-analytics-actions.d.ts +1 -1
- package/dist/sdk/analytics/use-analytics-actions.js.map +1 -1
- package/dist/sdk/cache/storefront-cache.js +2 -1
- package/dist/sdk/cache/storefront-cache.js.map +1 -1
- package/dist/sdk/cart/operations.d.ts +2 -1
- package/dist/sdk/cart/operations.js +55 -1
- package/dist/sdk/cart/operations.js.map +1 -1
- package/dist/sdk/cart/optimistic.d.ts +30 -7
- package/dist/sdk/cart/optimistic.js +78 -41
- package/dist/sdk/cart/optimistic.js.map +1 -1
- package/dist/sdk/cart/use-cart-actions.d.ts +7 -0
- package/dist/sdk/cart/use-cart-actions.js +61 -15
- package/dist/sdk/cart/use-cart-actions.js.map +1 -1
- package/dist/sdk/cart/use-cart-sync-sales-channel.js +70 -0
- package/dist/sdk/cart/use-cart-sync-sales-channel.js.map +1 -0
- package/dist/sdk/data/index.js +2 -2
- package/dist/sdk/data/reactive-list-item-data-provider.js +2 -2
- package/dist/sdk/generated/gql.js +16 -12
- package/dist/sdk/generated/gql.js.map +1 -1
- package/dist/sdk/generated/graphql.d.ts +197 -51
- package/dist/sdk/generated/graphql.js +2318 -91
- package/dist/sdk/generated/graphql.js.map +1 -1
- package/dist/sdk/i18n/format-error-code.js +23 -0
- package/dist/sdk/i18n/format-error-code.js.map +1 -0
- package/dist/sdk/i18n/message-formatter.d.ts +22 -0
- package/dist/sdk/i18n/message-formatter.js +140 -0
- package/dist/sdk/i18n/message-formatter.js.map +1 -0
- package/dist/sdk/i18n/use-message-formatter.d.ts +8 -0
- package/dist/sdk/i18n/use-message-formatter.js +18 -0
- package/dist/sdk/i18n/use-message-formatter.js.map +1 -0
- package/dist/sdk/identity/use-identity-actions.js.map +1 -1
- package/dist/sdk/locale/binding-switch-provider.d.ts +13 -0
- package/dist/sdk/locale/binding-switch-provider.js +20 -0
- package/dist/sdk/locale/binding-switch-provider.js.map +1 -0
- package/dist/sdk/locale/use-locale-actions.d.ts +16 -0
- package/dist/sdk/locale/use-locale-actions.js +70 -0
- package/dist/sdk/locale/use-locale-actions.js.map +1 -0
- package/dist/sdk/navigation/binding-switch.d.ts +39 -0
- package/dist/sdk/navigation/binding-switch.js +129 -0
- package/dist/sdk/navigation/binding-switch.js.map +1 -0
- package/dist/sdk/navigation/decode-route-params.d.ts +11 -0
- package/dist/sdk/navigation/decode-route-params.js +32 -0
- package/dist/sdk/navigation/decode-route-params.js.map +1 -0
- package/dist/sdk/navigation/redirect.d.ts +2 -0
- package/dist/sdk/navigation/redirect.js +19 -1
- package/dist/sdk/navigation/redirect.js.map +1 -1
- package/dist/sdk/navigation/types.d.ts +13 -0
- package/dist/sdk/payment/bin-format.js +20 -0
- package/dist/sdk/payment/bin-format.js.map +1 -0
- package/dist/sdk/payment/challenge-return.js +37 -0
- package/dist/sdk/payment/challenge-return.js.map +1 -0
- package/dist/sdk/payment/confirmation-last-four.js +39 -0
- package/dist/sdk/payment/confirmation-last-four.js.map +1 -0
- package/dist/sdk/payment/gateway.d.ts +1 -1
- package/dist/sdk/payment/gateway.js +8 -2
- package/dist/sdk/payment/gateway.js.map +1 -1
- package/dist/sdk/payment/operations.d.ts +1 -0
- package/dist/sdk/payment/operations.js +28 -6
- package/dist/sdk/payment/operations.js.map +1 -1
- package/dist/sdk/payment/resumed-purchase.d.ts +1 -0
- package/dist/sdk/payment/resumed-purchase.js +119 -0
- package/dist/sdk/payment/resumed-purchase.js.map +1 -0
- package/dist/sdk/payment/security-code-mask.js +16 -23
- package/dist/sdk/payment/security-code-mask.js.map +1 -1
- package/dist/sdk/payment/submission-registry.js +6 -2
- package/dist/sdk/payment/submission-registry.js.map +1 -1
- package/dist/sdk/payment/use-payment-actions.d.ts +18 -3
- package/dist/sdk/payment/use-payment-actions.js +23 -3
- package/dist/sdk/payment/use-payment-actions.js.map +1 -1
- package/dist/sdk/payment/use-place-order.d.ts +10 -2
- package/dist/sdk/payment/use-place-order.js +138 -76
- package/dist/sdk/payment/use-place-order.js.map +1 -1
- package/dist/sdk/provider/storefront-provider.d.ts +1 -7
- package/dist/sdk/provider/storefront-provider.js +4 -11
- package/dist/sdk/provider/storefront-provider.js.map +1 -1
- package/dist/sdk/saved-cards/operations.d.ts +16 -0
- package/dist/sdk/saved-cards/operations.js +41 -0
- package/dist/sdk/saved-cards/operations.js.map +1 -0
- package/dist/sdk/saved-cards/use-saved-card-actions.d.ts +26 -0
- package/dist/sdk/saved-cards/use-saved-card-actions.js +86 -0
- package/dist/sdk/saved-cards/use-saved-card-actions.js.map +1 -0
- package/dist/sdk/seo/entity-landing.d.ts +24 -0
- package/dist/sdk/seo/entity-landing.js +30 -0
- package/dist/sdk/seo/entity-landing.js.map +1 -0
- package/dist/sdk/seo/page-alternates.d.ts +8 -5
- package/dist/sdk/seo/page-alternates.js +11 -14
- package/dist/sdk/seo/page-alternates.js.map +1 -1
- package/dist/sdk/seo/search-landing.d.ts +42 -0
- package/dist/sdk/seo/search-landing.js +85 -0
- package/dist/sdk/seo/search-landing.js.map +1 -0
- package/dist/sdk/session/mock-session.d.ts +9 -0
- package/dist/sdk/session/mock-session.js +31 -0
- package/dist/sdk/session/mock-session.js.map +1 -0
- package/dist/sdk/session/read-server-session.d.ts +3 -0
- package/dist/sdk/session/read-server-session.js +5 -0
- package/dist/sdk/session/read-server-session.js.map +1 -1
- package/dist/sdk/session/return-path-segment.d.ts +10 -0
- package/dist/sdk/session/return-path-segment.js +15 -0
- package/dist/sdk/session/return-path-segment.js.map +1 -0
- package/dist/sdk/session/use-session-actions.js.map +1 -1
- package/dist/sdk/shipping/shipping-operations.d.ts +1 -1
- package/dist/sdk/shipping/shipping-operations.js +13 -0
- package/dist/sdk/shipping/shipping-operations.js.map +1 -1
- package/dist/sdk/shipping/use-cart-shipping-simulation.js.map +1 -1
- package/dist/sdk/shipping/use-shipping-actions.js.map +1 -1
- package/dist/sdk/shipping/use-shipping-simulation.js.map +1 -1
- package/dist/sdk/state/cart.d.ts +9 -2
- package/dist/sdk/state/cart.js +9 -2
- package/dist/sdk/state/cart.js.map +1 -1
- package/dist/utils/safe-href.d.ts +2 -0
- package/package.json +4 -3
- package/skills/storefront-asset/SKILL.md +2 -2
- package/skills/storefront-asset/references/api-side.md +27 -14
- package/skills/storefront-asset/references/findings.md +5 -2
- package/src/styles/tailwind.css +9 -2
- package/dist/matter/shipping-address/country-descriptors.d.ts +0 -1
- package/dist/message-locales.json +0 -7
- package/dist/sdk/i18n/client.d.ts +0 -4
- package/dist/sdk/i18n/client.js +0 -4
- package/dist/sdk/i18n/locales.d.ts +0 -8
- package/dist/sdk/i18n/locales.js +0 -57
- package/dist/sdk/i18n/locales.js.map +0 -1
- package/dist/sdk/i18n/messages/en-US.js +0 -164
- package/dist/sdk/i18n/messages/en-US.js.map +0 -1
- package/dist/sdk/i18n/messages/en-US.json +0 -159
- package/dist/sdk/i18n/messages/en-US.json.d.ts +0 -163
- package/dist/sdk/i18n/messages/es-ES.js +0 -164
- package/dist/sdk/i18n/messages/es-ES.js.map +0 -1
- package/dist/sdk/i18n/messages/es-ES.json +0 -159
- package/dist/sdk/i18n/messages/pt-BR.js +0 -164
- package/dist/sdk/i18n/messages/pt-BR.js.map +0 -1
- package/dist/sdk/i18n/messages/pt-BR.json +0 -159
- package/dist/sdk/i18n/provider.d.ts +0 -1
- package/dist/sdk/i18n/provider.js +0 -30
- package/dist/sdk/i18n/provider.js.map +0 -1
- package/dist/sdk/i18n/server.d.ts +0 -28
- package/dist/sdk/i18n/server.js +0 -59
- package/dist/sdk/i18n/server.js.map +0 -1
- package/dist/utils/resolve-authored-copy.js +0 -18
- package/dist/utils/resolve-authored-copy.js.map +0 -1
- package/dist/utils/substitute-template.js +0 -33
- package/dist/utils/substitute-template.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"password-field.js","names":[],"sources":["../../../src/particles/password-field/password-field.tsx"],"sourcesContent":["'use client';\nimport { defineComponent } from '@vtex/fs-core';\nimport { type ChangeEvent, useState } from 'react';\nimport { Field } from '../field/field.js';\nimport { Icon } from '../icon/icon.js';\nimport { Input } from '../input/input.js';\nimport { Toggle } from '../toggle/toggle.js';\n\nexport type PasswordFieldRequirement = 'mandatory' | 'optional';\n\nexport type PasswordFieldAutoComplete = 'current-password' | 'new-password';\n\nexport type PasswordFieldProps = {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n invalid?: boolean;\n errorMessage?: string;\n label?: string;\n placeholder?: string;\n requirement?: PasswordFieldRequirement;\n autoComplete?: PasswordFieldAutoComplete;\n showPasswordLabel?: string;\n hidePasswordLabel?: string;\n disabled?: boolean;\n name?: string;\n id?: string;\n className?: string;\n};\n\nexport const PasswordFieldDefinition = defineComponent<PasswordFieldProps>({\n name: 'PasswordField',\n importPath: '@vtex/faststore/components',\n component: PasswordField,\n editor: { label: 'Password Field', category: 'action' },\n schema: {\n label: { type: 'string', label: 'Label' },\n placeholder: { type: 'string', label: 'Placeholder' },\n requirement: { type: ['mandatory', 'optional'] as const, default: 'mandatory', label: 'Requirement' },\n autoComplete: {\n type: ['current-password', 'new-password'] as const,\n default: 'current-password',\n label: 'Autocomplete',\n },\n showPasswordLabel: { type: 'string',
|
|
1
|
+
{"version":3,"file":"password-field.js","names":[],"sources":["../../../src/particles/password-field/password-field.tsx"],"sourcesContent":["'use client';\nimport { defineComponent } from '@vtex/fs-core';\nimport { type ChangeEvent, useState } from 'react';\nimport { Field } from '../field/field.js';\nimport { Icon } from '../icon/icon.js';\nimport { Input } from '../input/input.js';\nimport { Toggle } from '../toggle/toggle.js';\n\nexport type PasswordFieldRequirement = 'mandatory' | 'optional';\n\nexport type PasswordFieldAutoComplete = 'current-password' | 'new-password';\n\nexport type PasswordFieldProps = {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n invalid?: boolean;\n errorMessage?: string;\n label?: string;\n placeholder?: string;\n requirement?: PasswordFieldRequirement;\n autoComplete?: PasswordFieldAutoComplete;\n showPasswordLabel?: string;\n hidePasswordLabel?: string;\n disabled?: boolean;\n name?: string;\n id?: string;\n className?: string;\n};\n\nexport const PasswordFieldDefinition = defineComponent<PasswordFieldProps>({\n name: 'PasswordField',\n importPath: '@vtex/faststore/components',\n component: PasswordField,\n editor: { label: 'Password Field', category: 'action' },\n schema: {\n label: { type: 'string', label: 'Label' },\n placeholder: { type: 'string', label: 'Placeholder' },\n requirement: { type: ['mandatory', 'optional'] as const, default: 'mandatory', label: 'Requirement' },\n autoComplete: {\n type: ['current-password', 'new-password'] as const,\n default: 'current-password',\n label: 'Autocomplete',\n },\n showPasswordLabel: { type: 'string', label: 'Show password label' },\n hidePasswordLabel: { type: 'string', label: 'Hide password label' },\n disabled: { type: 'boolean', default: false, label: 'Disabled' },\n },\n guideline:\n 'Presentational password input with a show/hide reveal toggle. Set autoComplete=\"new-password\" for recovery/set-password screens (default is \"current-password\" for sign-in). The owner passes showPasswordLabel and hidePasswordLabel already formatted; they have no default. No validation beyond presence — invalid/errorMessage are caller-driven. No data layer: does not call login, does not read session.',\n});\n\n/**\n * Composes Field + Input + Toggle + Icon into a password input with a show/hide reveal\n * toggle. Presence-only validation is caller-driven via `invalid`/`errorMessage` — this\n * particle computes no validity of its own. `revealed` is local, uncontrolled UI state.\n */\nexport function PasswordField({\n value,\n defaultValue,\n onValueChange,\n invalid = false,\n errorMessage,\n label,\n placeholder,\n requirement = 'mandatory',\n autoComplete = 'current-password',\n showPasswordLabel,\n hidePasswordLabel,\n disabled = false,\n name,\n id,\n className,\n}: Readonly<PasswordFieldProps>) {\n const [revealed, setRevealed] = useState(false);\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n onValueChange?.(event.target.value);\n }\n\n return (\n <Field.Root invalid={invalid} disabled={disabled} name={name} className={className} data-fs-password-field=\"\">\n {label ? <Field.Label>{label}</Field.Label> : null}\n <div data-fs-password-field-group=\"\">\n <Input\n id={id}\n type={revealed ? 'text' : 'password'}\n autoComplete={autoComplete}\n // `aria-required`, not native `required`: `Input` is a Base UI `Field.Control`, and native\n // constraint tracking would flip `aria-invalid` on its own — validity here is caller-driven.\n aria-required={requirement === 'mandatory' ? 'true' : undefined}\n spellCheck={false}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n placeholder={placeholder}\n disabled={disabled}\n value={value}\n defaultValue={value === undefined ? defaultValue : undefined}\n onChange={handleChange}\n />\n <Toggle\n type=\"button\"\n pressed={revealed}\n onPressedChange={setRevealed}\n disabled={disabled}\n aria-label={revealed ? hidePasswordLabel : showPasswordLabel}\n data-fs-password-field-toggle=\"\"\n >\n <Icon name={revealed ? 'eye-off' : 'eye'} />\n </Toggle>\n </div>\n <Field.Error match={invalid ? true : 'customError'}>{errorMessage}</Field.Error>\n </Field.Root>\n );\n}\n"],"mappings":";;;;;;;;;;AA8BA,MAAa,0BAA0B,gBAAoC;CACzE,MAAM;CACN,YAAY;CACZ,WAAW;CACX,QAAQ;EAAE,OAAO;EAAkB,UAAU;CAAS;CACtD,QAAQ;EACN,OAAO;GAAE,MAAM;GAAU,OAAO;EAAQ;EACxC,aAAa;GAAE,MAAM;GAAU,OAAO;EAAc;EACpD,aAAa;GAAE,MAAM,CAAC,aAAa,UAAU;GAAY,SAAS;GAAa,OAAO;EAAc;EACpG,cAAc;GACZ,MAAM,CAAC,oBAAoB,cAAc;GACzC,SAAS;GACT,OAAO;EACT;EACA,mBAAmB;GAAE,MAAM;GAAU,OAAO;EAAsB;EAClE,mBAAmB;GAAE,MAAM;GAAU,OAAO;EAAsB;EAClE,UAAU;GAAE,MAAM;GAAW,SAAS;GAAO,OAAO;EAAW;CACjE;CACA,WACE;AACJ,CAAC;;;;;;AAOD,SAAgB,cAAc,EAC5B,OACA,cACA,eACA,UAAU,OACV,cACA,OACA,aACA,cAAc,aACd,eAAe,oBACf,mBACA,mBACA,WAAW,OACX,MACA,IACA,aAC+B;CAC/B,MAAM,CAAC,UAAU,eAAe,SAAS,KAAK;CAE9C,SAAS,aAAa,OAAsC;EAC1D,gBAAgB,MAAM,OAAO,KAAK;CACpC;CAEA,OACE,qBAAC,MAAM,MAAP;EAAqB;EAAmB;EAAgB;EAAiB;EAAW,0BAAuB;EAA3G,UAAA;GACG,QAAQ,oBAAC,MAAM,OAAP,EAAA,UAAc,MAAmB,CAAA,IAAI;GAC9C,qBAAC,OAAD;IAAK,gCAA6B;IAAlC,UAAA,CACE,oBAAC,OAAD;KACM;KACJ,MAAM,WAAW,SAAS;KACZ;KAGd,iBAAe,gBAAgB,cAAc,SAAS,KAAA;KACtD,YAAY;KACZ,gBAAe;KACf,aAAY;KACC;KACH;KACH;KACP,cAAc,UAAU,KAAA,IAAY,eAAe,KAAA;KACnD,UAAU;IACX,CAAA,GACD,oBAAC,QAAD;KACE,MAAK;KACL,SAAS;KACT,iBAAiB;KACP;KACV,cAAY,WAAW,oBAAoB;KAC3C,iCAA8B;KAE9B,UAAA,oBAAC,MAAD,EAAM,MAAM,WAAW,YAAY,MAAQ,CAAA;IACrC,CAAA,CACL;;GACL,oBAAC,MAAM,OAAP;IAAa,OAAO,UAAU,OAAO;IAAgB,UAAA;GAA0B,CAAA;EACrE;;AAEhB"}
|
|
@@ -50,7 +50,7 @@ export declare const PaymentMethodsContent: {
|
|
|
50
50
|
};
|
|
51
51
|
/**
|
|
52
52
|
* The payment glyphs the base icon dialect carries, and so the only names `method` admits. Exported
|
|
53
|
-
* because a store's
|
|
53
|
+
* because a store's foundation has to list them under `icons.include` for a CMS-chosen name to
|
|
54
54
|
* resolve at runtime — one import there instead of ten retyped strings. Reading it off the model
|
|
55
55
|
* rather than declaring it beside one makes the two impossible to drift apart.
|
|
56
56
|
*/
|
|
@@ -61,7 +61,7 @@ const PaymentMethodsContent = defineContentType({
|
|
|
61
61
|
});
|
|
62
62
|
/**
|
|
63
63
|
* The payment glyphs the base icon dialect carries, and so the only names `method` admits. Exported
|
|
64
|
-
* because a store's
|
|
64
|
+
* because a store's foundation has to list them under `icons.include` for a CMS-chosen name to
|
|
65
65
|
* resolve at runtime — one import there instead of ten retyped strings. Reading it off the model
|
|
66
66
|
* rather than declaring it beside one makes the two impossible to drift apart.
|
|
67
67
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payment-methods.js","names":[],"sources":["../../../src/particles/payment-methods/payment-methods.tsx"],"sourcesContent":["import { type ContentValue, defineComponent, defineContentType } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\nimport { Icon } from '../icon/icon.js';\nimport { Image } from '../image/image.js';\n\n// ---------------------------------------------------------------------------\n// Content model\n// ---------------------------------------------------------------------------\n\nexport const PaymentMethodsContent = defineContentType({\n id: 'payment-methods',\n title: 'Payment Methods',\n description: 'Accepted payment methods shown as a strip of icons.',\n schema: {\n type: 'object',\n additionalProperties: false,\n // Neither property is required. A missing element key already omits the component before any\n // required check runs, so requiring them would buy nothing and cost the prop fallback: an entry\n // authoring one field alone would be shape-invalid and take the whole element down with it.\n properties: {\n heading: { type: 'string', title: 'Heading' },\n methods: {\n type: 'array',\n title: 'Payment methods',\n // Author-time guidance only: no read-time gate enforces item bounds, so its one consumer is\n // the Content Platform Admin's form. An empty list still reaches the component, which\n // self-hides on it. No ceiling — a merchant lists every method they accept.\n minItems: 1,\n items: {\n type: 'object',\n additionalProperties: false,\n required: ['label'],\n properties: {\n // Inline rather than a named constant: the catalog scanner reads this file statically\n // and rejects an identifier it cannot evaluate. `PAYMENT_METHOD_NAMES` derives from here.\n method: {\n type: 'string',\n enum: [\n 'visa',\n 'amex',\n 'apple-pay',\n 'elo-card',\n 'diners',\n 'google-pay',\n 'mastercard',\n 'paypal',\n 'pix',\n 'stripe',\n ],\n title: 'Method',\n },\n label: { type: 'string', minLength: 1, title: 'Label' },\n iconUrl: {\n type: 'string',\n format: 'uri',\n title: 'Custom icon',\n widget: { 'ui:widget': 'media-gallery' },\n },\n },\n },\n },\n },\n },\n});\n\n/**\n * The payment glyphs the base icon dialect carries, and so the only names `method` admits. Exported\n * because a store's `global.json` has to list them under `icons.include` for a CMS-chosen name to\n * resolve at runtime — one import there instead of ten retyped strings. Reading it off the model\n * rather than declaring it beside one makes the two impossible to drift apart.\n */\nexport const PAYMENT_METHOD_NAMES = PaymentMethodsContent.schema.properties.methods.items.properties.method.enum;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype PaymentMethodsContentValue = ContentValue<typeof PaymentMethodsContent>;\n\n/** One row of the strip. Derived from the model so the prop and content channels cannot drift. */\nexport type PaymentMethodItem = NonNullable<PaymentMethodsContentValue['methods']>[number];\n\ntype PaymentMethodName = NonNullable<PaymentMethodItem['method']>;\n\nexport type PaymentMethodsProps = ComponentPropsWithRef<'div'> & {\n /** Authored fallback for the section heading, used when no CMS entry supplies one. */\n heading?: string;\n /** Authored fallback for the accepted set, used when no CMS entry supplies one. */\n methods?: readonly PaymentMethodItem[];\n /** Injected by the compiler, sliced from the page's or layout's composite content entry. */\n $content?: PaymentMethodsContentValue;\n};\n\n// ---------------------------------------------------------------------------\n// Definition\n// ---------------------------------------------------------------------------\n\nexport const PaymentMethodsDefinition = defineComponent({\n name: 'PaymentMethods',\n importPath: '@vtex/faststore/components',\n component: PaymentMethods,\n content: PaymentMethodsContent,\n editor: { label: 'Payment Methods', category: 'content' },\n schema: {\n heading: { type: 'string', label: 'Heading' },\n methods: { type: 'array', label: 'Payment methods' },\n },\n guideline:\n \"The store's accepted payment methods as a strip of flags, both the heading and the list CMS-editable. Not PricingPaymentMethodsList, which renders a product's installment plans from commerce data. Every predefined method name must be listed in the store's icons.include. See payment-methods.md.\",\n});\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * A method that can render: a non-blank label plus exactly one glyph source. The two members are\n * what the union encodes — an upload names itself through `alt`, while a sprite glyph is decorative\n * and needs the label alongside it.\n */\ntype ResolvedMethod =\n | { label: string; method: PaymentMethodName; src?: undefined }\n | { label: string; method?: PaymentMethodName; src: string };\n\n/**\n * Drops every item that cannot render both a glyph and an accessible name. Neither read-time gate\n * enforces `minLength`, so a blank label reaches the component, and `method` is optional so that\n * Boleto can arrive through `iconUrl` — which leaves an item carrying neither, also legal and also\n * unrenderable. An icon with no name is the one thing F5 must not ship.\n */\nfunction resolveMethods(methods: readonly PaymentMethodItem[]): ResolvedMethod[] {\n const resolved: ResolvedMethod[] = [];\n\n for (const item of methods) {\n if (!item.label.trim()) continue;\n\n if (item.iconUrl?.trim()) {\n resolved.push({ label: item.label, method: item.method, src: item.iconUrl });\n } else if (item.method) {\n resolved.push({ label: item.label, method: item.method });\n }\n }\n\n return resolved;\n}\n\nexport function PaymentMethods({ heading, methods, $content, className, ...props }: PaymentMethodsProps) {\n const sectionHeading = $content?.heading ?? heading;\n const resolved = resolveMethods($content?.methods ?? methods ?? []);\n\n if (resolved.length === 0) return null;\n\n // A blank heading is unconfigured, not an empty value: no element and no group name, rather than\n // an empty one. Trim to decide, never to render.\n const named = Boolean(sectionHeading?.trim());\n\n return (\n <div {...props} className={className} data-fs-payment-methods=\"\">\n {named ? (\n <h3 data-fs-text=\"\" data-fs-payment-methods-heading=\"\">\n {sectionHeading}\n </h3>\n ) : null}\n {/* biome-ignore lint/a11y/noRedundantRoles: WebKit drops the implicit list role from a ul whose\n computed `list-style` is `none` — exactly what this component's swatch sets — so the explicit\n role is what holds the semantics the named list was chosen for. */}\n <ul role=\"list\" data-fs-payment-methods-list=\"\" aria-label={named ? sectionHeading : undefined}>\n {resolved.map((item, index) => (\n <li key={index} data-fs-payment-method=\"\" data-fs-payment-method-name={item.method}>\n {item.src === undefined ? (\n <>\n <Icon name={item.method} data-fs-payment-method-icon=\"\" />\n <span data-fs-sr-only=\"\" className=\"sr-only\">\n {item.label}\n </span>\n </>\n ) : (\n <Image src={item.src} alt={item.label} data-fs-payment-method-icon=\"\" />\n )}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n"],"mappings":";;;;;;;AASA,MAAa,wBAAwB,kBAAkB;CACrD,IAAI;CACJ,OAAO;CACP,aAAa;CACb,QAAQ;EACN,MAAM;EACN,sBAAsB;EAItB,YAAY;GACV,SAAS;IAAE,MAAM;IAAU,OAAO;GAAU;GAC5C,SAAS;IACP,MAAM;IACN,OAAO;IAIP,UAAU;IACV,OAAO;KACL,MAAM;KACN,sBAAsB;KACtB,UAAU,CAAC,OAAO;KAClB,YAAY;MAGV,QAAQ;OACN,MAAM;OACN,MAAM;QACJ;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;OACF;OACA,OAAO;MACT;MACA,OAAO;OAAE,MAAM;OAAU,WAAW;OAAG,OAAO;MAAQ;MACtD,SAAS;OACP,MAAM;OACN,QAAQ;OACR,OAAO;OACP,QAAQ,EAAE,aAAa,gBAAgB;MACzC;KACF;IACF;GACF;EACF;CACF;AACF,CAAC;;;;;;;AAQD,MAAa,uBAAuB,sBAAsB,OAAO,WAAW,QAAQ,MAAM,WAAW,OAAO;AA0B5G,MAAa,2BAA2B,gBAAgB;CACtD,MAAM;CACN,YAAY;CACZ,WAAW;CACX,SAAS;CACT,QAAQ;EAAE,OAAO;EAAmB,UAAU;CAAU;CACxD,QAAQ;EACN,SAAS;GAAE,MAAM;GAAU,OAAO;EAAU;EAC5C,SAAS;GAAE,MAAM;GAAS,OAAO;EAAkB;CACrD;CACA,WACE;AACJ,CAAC;;;;;;;AAqBD,SAAS,eAAe,SAAyD;CAC/E,MAAM,WAA6B,CAAC;CAEpC,KAAK,MAAM,QAAQ,SAAS;EAC1B,IAAI,CAAC,KAAK,MAAM,KAAK,GAAG;EAExB,IAAI,KAAK,SAAS,KAAK,GACrB,SAAS,KAAK;GAAE,OAAO,KAAK;GAAO,QAAQ,KAAK;GAAQ,KAAK,KAAK;EAAQ,CAAC;OACtE,IAAI,KAAK,QACd,SAAS,KAAK;GAAE,OAAO,KAAK;GAAO,QAAQ,KAAK;EAAO,CAAC;CAE5D;CAEA,OAAO;AACT;AAEA,SAAgB,eAAe,EAAE,SAAS,SAAS,UAAU,WAAW,GAAG,SAA8B;CACvG,MAAM,iBAAiB,UAAU,WAAW;CAC5C,MAAM,WAAW,eAAe,UAAU,WAAW,WAAW,CAAC,CAAC;CAElE,IAAI,SAAS,WAAW,GAAG,OAAO;CAIlC,MAAM,QAAQ,QAAQ,gBAAgB,KAAK,CAAC;CAE5C,OACE,qBAAC,OAAD;EAAK,GAAI;EAAkB;EAAW,2BAAwB;EAA9D,UAAA,CACG,QACC,oBAAC,MAAD;GAAI,gBAAa;GAAG,mCAAgC;GACjD,UAAA;EACC,CAAA,IACF,MAIJ,oBAAC,MAAD;GAAI,MAAK;GAAO,gCAA6B;GAAG,cAAY,QAAQ,iBAAiB,KAAA;GAClF,UAAA,SAAS,KAAK,MAAM,UACnB,oBAAC,MAAD;IAAgB,0BAAuB;IAAG,+BAA6B,KAAK;IACzE,UAAA,KAAK,QAAQ,KAAA,IACZ,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,MAAD;KAAM,MAAM,KAAK;KAAQ,+BAA4B;IAAI,CAAA,GACzD,oBAAC,QAAD;KAAM,mBAAgB;KAAG,WAAU;KAChC,UAAA,KAAK;IACF,CAAA,CACN,EAAA,CAAA,IAEF,oBAAC,OAAD;KAAO,KAAK,KAAK;KAAK,KAAK,KAAK;KAAO,+BAA4B;IAAI,CAAA;GAEvE,GAXK,KAWL,CACL;EACC,CAAA,CACD;;AAET"}
|
|
1
|
+
{"version":3,"file":"payment-methods.js","names":[],"sources":["../../../src/particles/payment-methods/payment-methods.tsx"],"sourcesContent":["import { type ContentValue, defineComponent, defineContentType } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\nimport { Icon } from '../icon/icon.js';\nimport { Image } from '../image/image.js';\n\n// ---------------------------------------------------------------------------\n// Content model\n// ---------------------------------------------------------------------------\n\nexport const PaymentMethodsContent = defineContentType({\n id: 'payment-methods',\n title: 'Payment Methods',\n description: 'Accepted payment methods shown as a strip of icons.',\n schema: {\n type: 'object',\n additionalProperties: false,\n // Neither property is required. A missing element key already omits the component before any\n // required check runs, so requiring them would buy nothing and cost the prop fallback: an entry\n // authoring one field alone would be shape-invalid and take the whole element down with it.\n properties: {\n heading: { type: 'string', title: 'Heading' },\n methods: {\n type: 'array',\n title: 'Payment methods',\n // Author-time guidance only: no read-time gate enforces item bounds, so its one consumer is\n // the Content Platform Admin's form. An empty list still reaches the component, which\n // self-hides on it. No ceiling — a merchant lists every method they accept.\n minItems: 1,\n items: {\n type: 'object',\n additionalProperties: false,\n required: ['label'],\n properties: {\n // Inline rather than a named constant: the catalog scanner reads this file statically\n // and rejects an identifier it cannot evaluate. `PAYMENT_METHOD_NAMES` derives from here.\n method: {\n type: 'string',\n enum: [\n 'visa',\n 'amex',\n 'apple-pay',\n 'elo-card',\n 'diners',\n 'google-pay',\n 'mastercard',\n 'paypal',\n 'pix',\n 'stripe',\n ],\n title: 'Method',\n },\n label: { type: 'string', minLength: 1, title: 'Label' },\n iconUrl: {\n type: 'string',\n format: 'uri',\n title: 'Custom icon',\n widget: { 'ui:widget': 'media-gallery' },\n },\n },\n },\n },\n },\n },\n});\n\n/**\n * The payment glyphs the base icon dialect carries, and so the only names `method` admits. Exported\n * because a store's foundation has to list them under `icons.include` for a CMS-chosen name to\n * resolve at runtime — one import there instead of ten retyped strings. Reading it off the model\n * rather than declaring it beside one makes the two impossible to drift apart.\n */\nexport const PAYMENT_METHOD_NAMES = PaymentMethodsContent.schema.properties.methods.items.properties.method.enum;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype PaymentMethodsContentValue = ContentValue<typeof PaymentMethodsContent>;\n\n/** One row of the strip. Derived from the model so the prop and content channels cannot drift. */\nexport type PaymentMethodItem = NonNullable<PaymentMethodsContentValue['methods']>[number];\n\ntype PaymentMethodName = NonNullable<PaymentMethodItem['method']>;\n\nexport type PaymentMethodsProps = ComponentPropsWithRef<'div'> & {\n /** Authored fallback for the section heading, used when no CMS entry supplies one. */\n heading?: string;\n /** Authored fallback for the accepted set, used when no CMS entry supplies one. */\n methods?: readonly PaymentMethodItem[];\n /** Injected by the compiler, sliced from the page's or layout's composite content entry. */\n $content?: PaymentMethodsContentValue;\n};\n\n// ---------------------------------------------------------------------------\n// Definition\n// ---------------------------------------------------------------------------\n\nexport const PaymentMethodsDefinition = defineComponent({\n name: 'PaymentMethods',\n importPath: '@vtex/faststore/components',\n component: PaymentMethods,\n content: PaymentMethodsContent,\n editor: { label: 'Payment Methods', category: 'content' },\n schema: {\n heading: { type: 'string', label: 'Heading' },\n methods: { type: 'array', label: 'Payment methods' },\n },\n guideline:\n \"The store's accepted payment methods as a strip of flags, both the heading and the list CMS-editable. Not PricingPaymentMethodsList, which renders a product's installment plans from commerce data. Every predefined method name must be listed in the store's icons.include. See payment-methods.md.\",\n});\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * A method that can render: a non-blank label plus exactly one glyph source. The two members are\n * what the union encodes — an upload names itself through `alt`, while a sprite glyph is decorative\n * and needs the label alongside it.\n */\ntype ResolvedMethod =\n | { label: string; method: PaymentMethodName; src?: undefined }\n | { label: string; method?: PaymentMethodName; src: string };\n\n/**\n * Drops every item that cannot render both a glyph and an accessible name. Neither read-time gate\n * enforces `minLength`, so a blank label reaches the component, and `method` is optional so that\n * Boleto can arrive through `iconUrl` — which leaves an item carrying neither, also legal and also\n * unrenderable. An icon with no name is the one thing F5 must not ship.\n */\nfunction resolveMethods(methods: readonly PaymentMethodItem[]): ResolvedMethod[] {\n const resolved: ResolvedMethod[] = [];\n\n for (const item of methods) {\n if (!item.label.trim()) continue;\n\n if (item.iconUrl?.trim()) {\n resolved.push({ label: item.label, method: item.method, src: item.iconUrl });\n } else if (item.method) {\n resolved.push({ label: item.label, method: item.method });\n }\n }\n\n return resolved;\n}\n\nexport function PaymentMethods({ heading, methods, $content, className, ...props }: PaymentMethodsProps) {\n const sectionHeading = $content?.heading ?? heading;\n const resolved = resolveMethods($content?.methods ?? methods ?? []);\n\n if (resolved.length === 0) return null;\n\n // A blank heading is unconfigured, not an empty value: no element and no group name, rather than\n // an empty one. Trim to decide, never to render.\n const named = Boolean(sectionHeading?.trim());\n\n return (\n <div {...props} className={className} data-fs-payment-methods=\"\">\n {named ? (\n <h3 data-fs-text=\"\" data-fs-payment-methods-heading=\"\">\n {sectionHeading}\n </h3>\n ) : null}\n {/* biome-ignore lint/a11y/noRedundantRoles: WebKit drops the implicit list role from a ul whose\n computed `list-style` is `none` — exactly what this component's swatch sets — so the explicit\n role is what holds the semantics the named list was chosen for. */}\n <ul role=\"list\" data-fs-payment-methods-list=\"\" aria-label={named ? sectionHeading : undefined}>\n {resolved.map((item, index) => (\n <li key={index} data-fs-payment-method=\"\" data-fs-payment-method-name={item.method}>\n {item.src === undefined ? (\n <>\n <Icon name={item.method} data-fs-payment-method-icon=\"\" />\n <span data-fs-sr-only=\"\" className=\"sr-only\">\n {item.label}\n </span>\n </>\n ) : (\n <Image src={item.src} alt={item.label} data-fs-payment-method-icon=\"\" />\n )}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n"],"mappings":";;;;;;;AASA,MAAa,wBAAwB,kBAAkB;CACrD,IAAI;CACJ,OAAO;CACP,aAAa;CACb,QAAQ;EACN,MAAM;EACN,sBAAsB;EAItB,YAAY;GACV,SAAS;IAAE,MAAM;IAAU,OAAO;GAAU;GAC5C,SAAS;IACP,MAAM;IACN,OAAO;IAIP,UAAU;IACV,OAAO;KACL,MAAM;KACN,sBAAsB;KACtB,UAAU,CAAC,OAAO;KAClB,YAAY;MAGV,QAAQ;OACN,MAAM;OACN,MAAM;QACJ;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;OACF;OACA,OAAO;MACT;MACA,OAAO;OAAE,MAAM;OAAU,WAAW;OAAG,OAAO;MAAQ;MACtD,SAAS;OACP,MAAM;OACN,QAAQ;OACR,OAAO;OACP,QAAQ,EAAE,aAAa,gBAAgB;MACzC;KACF;IACF;GACF;EACF;CACF;AACF,CAAC;;;;;;;AAQD,MAAa,uBAAuB,sBAAsB,OAAO,WAAW,QAAQ,MAAM,WAAW,OAAO;AA0B5G,MAAa,2BAA2B,gBAAgB;CACtD,MAAM;CACN,YAAY;CACZ,WAAW;CACX,SAAS;CACT,QAAQ;EAAE,OAAO;EAAmB,UAAU;CAAU;CACxD,QAAQ;EACN,SAAS;GAAE,MAAM;GAAU,OAAO;EAAU;EAC5C,SAAS;GAAE,MAAM;GAAS,OAAO;EAAkB;CACrD;CACA,WACE;AACJ,CAAC;;;;;;;AAqBD,SAAS,eAAe,SAAyD;CAC/E,MAAM,WAA6B,CAAC;CAEpC,KAAK,MAAM,QAAQ,SAAS;EAC1B,IAAI,CAAC,KAAK,MAAM,KAAK,GAAG;EAExB,IAAI,KAAK,SAAS,KAAK,GACrB,SAAS,KAAK;GAAE,OAAO,KAAK;GAAO,QAAQ,KAAK;GAAQ,KAAK,KAAK;EAAQ,CAAC;OACtE,IAAI,KAAK,QACd,SAAS,KAAK;GAAE,OAAO,KAAK;GAAO,QAAQ,KAAK;EAAO,CAAC;CAE5D;CAEA,OAAO;AACT;AAEA,SAAgB,eAAe,EAAE,SAAS,SAAS,UAAU,WAAW,GAAG,SAA8B;CACvG,MAAM,iBAAiB,UAAU,WAAW;CAC5C,MAAM,WAAW,eAAe,UAAU,WAAW,WAAW,CAAC,CAAC;CAElE,IAAI,SAAS,WAAW,GAAG,OAAO;CAIlC,MAAM,QAAQ,QAAQ,gBAAgB,KAAK,CAAC;CAE5C,OACE,qBAAC,OAAD;EAAK,GAAI;EAAkB;EAAW,2BAAwB;EAA9D,UAAA,CACG,QACC,oBAAC,MAAD;GAAI,gBAAa;GAAG,mCAAgC;GACjD,UAAA;EACC,CAAA,IACF,MAIJ,oBAAC,MAAD;GAAI,MAAK;GAAO,gCAA6B;GAAG,cAAY,QAAQ,iBAAiB,KAAA;GAClF,UAAA,SAAS,KAAK,MAAM,UACnB,oBAAC,MAAD;IAAgB,0BAAuB;IAAG,+BAA6B,KAAK;IACzE,UAAA,KAAK,QAAQ,KAAA,IACZ,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,MAAD;KAAM,MAAM,KAAK;KAAQ,+BAA4B;IAAI,CAAA,GACzD,oBAAC,QAAD;KAAM,mBAAgB;KAAG,WAAU;KAChC,UAAA,KAAK;IACF,CAAA,CACN,EAAA,CAAA,IAEF,oBAAC,OAAD;KAAO,KAAK,KAAK;KAAK,KAAK,KAAK;KAAO,+BAA4B;IAAI,CAAA;GAEvE,GAXK,KAWL,CACL;EACC,CAAA,CACD;;AAET"}
|
|
@@ -19,8 +19,8 @@ export type PhoneFieldProps = {
|
|
|
19
19
|
/** Selects the phone mask and validation rule. */
|
|
20
20
|
country?: PhoneCountry;
|
|
21
21
|
/**
|
|
22
|
-
* Visible field label. No
|
|
23
|
-
*
|
|
22
|
+
* Visible field label, formatted by the owner. No default: an omitted label falls back to the field
|
|
23
|
+
* contract's `label` when bound, and renders empty when not.
|
|
24
24
|
*/
|
|
25
25
|
label?: string;
|
|
26
26
|
/** Disables the field when true. Falls back to the field contract's `disabled` when bound. */
|
|
@@ -37,9 +37,9 @@ export type PhoneFieldProps = {
|
|
|
37
37
|
* particle's internal error string.
|
|
38
38
|
*/
|
|
39
39
|
error?: string;
|
|
40
|
-
/** Error string shown when the input format is invalid. */
|
|
40
|
+
/** Error string shown when the input format is invalid, formatted by the owner. No default. */
|
|
41
41
|
errorInvalid?: string;
|
|
42
|
-
/** Error string shown when the mandatory field is left empty. */
|
|
42
|
+
/** Error string shown when the mandatory field is left empty, formatted by the owner. No default. */
|
|
43
43
|
errorRequired?: string;
|
|
44
44
|
/**
|
|
45
45
|
* Raises the field to required. It only ever raises: bound to a fieldset whose rule already says
|
|
@@ -151,7 +151,6 @@ const PhoneFieldDefinition = defineComponent({
|
|
|
151
151
|
},
|
|
152
152
|
label: {
|
|
153
153
|
type: "string",
|
|
154
|
-
default: "Phone",
|
|
155
154
|
label: "Label"
|
|
156
155
|
},
|
|
157
156
|
requirement: {
|
|
@@ -160,16 +159,14 @@ const PhoneFieldDefinition = defineComponent({
|
|
|
160
159
|
},
|
|
161
160
|
errorInvalid: {
|
|
162
161
|
type: "string",
|
|
163
|
-
default: "Invalid phone number",
|
|
164
162
|
label: "Invalid error message"
|
|
165
163
|
},
|
|
166
164
|
errorRequired: {
|
|
167
165
|
type: "string",
|
|
168
|
-
default: "Phone number is required",
|
|
169
166
|
label: "Required error message"
|
|
170
167
|
}
|
|
171
168
|
},
|
|
172
|
-
guideline: "Locale-aware, business-agnostic phone number input composed from the field + input particles. Applies country masking, validates on blur, and exposes its value via onValueChange. Bind it to a data source (e.g. ClientProfilePhoneControl for checkout) to persist the value. Recomposable (RFC:503): given children, they replace the default Field.Label + PhoneFieldInput + Field.Error anatomy, in any order."
|
|
169
|
+
guideline: "Locale-aware, business-agnostic phone number input composed from the field + input particles. Applies country masking, validates on blur, and exposes its value via onValueChange. Bind it to a data source (e.g. ClientProfilePhoneControl for checkout) to persist the value; the owner supplies label, errorInvalid and errorRequired, which have no default. Recomposable (RFC:503): given children, they replace the default Field.Label + PhoneFieldInput + Field.Error anatomy, in any order."
|
|
173
170
|
});
|
|
174
171
|
/**
|
|
175
172
|
* Presentational, business-agnostic phone field. Composes the `field` and `input` particles: the
|
|
@@ -275,7 +272,7 @@ function PhoneFieldView({ ref, country, className, label, isDisabled, placeholde
|
|
|
275
272
|
})
|
|
276
273
|
});
|
|
277
274
|
}
|
|
278
|
-
function UnboundPhoneField({ value, defaultValue = "", onValueChange, country = "US", label, isDisabled = false, placeholder, invalid, error, errorInvalid
|
|
275
|
+
function UnboundPhoneField({ value, defaultValue = "", onValueChange, country = "US", label, isDisabled = false, placeholder, invalid, error, errorInvalid, errorRequired, requirement, onBlur, className, ref, children }) {
|
|
279
276
|
const isControlled = value !== void 0;
|
|
280
277
|
const [internalRaw, setInternalRaw] = useState(defaultValue);
|
|
281
278
|
const [localInvalid, setLocalInvalid] = useState(false);
|
|
@@ -288,7 +285,7 @@ function UnboundPhoneField({ value, defaultValue = "", onValueChange, country =
|
|
|
288
285
|
}
|
|
289
286
|
const rawValue = isControlled ? value : internalRaw;
|
|
290
287
|
const maskedValue = applyPhoneMask(rawValue, country);
|
|
291
|
-
const resolvedLabel = label ?? "
|
|
288
|
+
const resolvedLabel = label ?? "";
|
|
292
289
|
const effectiveInvalid = invalid !== void 0 ? invalid : localInvalid;
|
|
293
290
|
const effectiveError = error !== void 0 ? error : effectiveInvalid ? localError : "";
|
|
294
291
|
function handleChange(event) {
|
|
@@ -303,11 +300,11 @@ function UnboundPhoneField({ value, defaultValue = "", onValueChange, country =
|
|
|
303
300
|
let fieldError = "";
|
|
304
301
|
if (requirement === "mandatory" && !rawValue.trim()) {
|
|
305
302
|
isFieldInvalid = true;
|
|
306
|
-
fieldError = errorRequired;
|
|
303
|
+
fieldError = errorRequired ?? "";
|
|
307
304
|
} else if (rawValue.trim()) {
|
|
308
305
|
const valid = validatePhoneNumber(rawValue, country);
|
|
309
306
|
isFieldInvalid = !valid;
|
|
310
|
-
fieldError = valid ? "" : errorInvalid;
|
|
307
|
+
fieldError = valid ? "" : errorInvalid ?? "";
|
|
311
308
|
}
|
|
312
309
|
setLocalInvalid(isFieldInvalid);
|
|
313
310
|
setLocalError(fieldError);
|
|
@@ -329,10 +326,10 @@ function UnboundPhoneField({ value, defaultValue = "", onValueChange, country =
|
|
|
329
326
|
children
|
|
330
327
|
});
|
|
331
328
|
}
|
|
332
|
-
function BoundPhoneField({ value: _value, defaultValue: _defaultValue, onValueChange, country = "US", label, isDisabled, placeholder, invalid, error, errorInvalid
|
|
329
|
+
function BoundPhoneField({ value: _value, defaultValue: _defaultValue, onValueChange, country = "US", label, isDisabled, placeholder, invalid, error, errorInvalid, errorRequired, requirement, onBlur, className, ref: callerRef, contract, children }) {
|
|
333
330
|
const rule = useMemo(() => mergeFieldValidator(contract.rule, "phoneFormat", (rawValue) => {
|
|
334
331
|
const raw = typeof rawValue === "string" ? rawValue : String(rawValue ?? "");
|
|
335
|
-
return !raw.trim() || validatePhoneNumber(raw, country) || errorInvalid;
|
|
332
|
+
return !raw.trim() || validatePhoneNumber(raw, country) || (errorInvalid ?? false);
|
|
336
333
|
}), [
|
|
337
334
|
contract.rule,
|
|
338
335
|
errorInvalid,
|
|
@@ -346,7 +343,7 @@ function BoundPhoneField({ value: _value, defaultValue: _defaultValue, onValueCh
|
|
|
346
343
|
const { invalid: rhfInvalid, error: rhfError } = getFieldState(contract.name, useFormState({ name: contract.name }));
|
|
347
344
|
const composedRef = useComposedRef(callerRef, field.ref);
|
|
348
345
|
const maskedValue = applyPhoneMask(typeof field.value === "string" ? field.value : String(field.value ?? ""), country);
|
|
349
|
-
const resolvedLabel = label ?? contract.label ?? "
|
|
346
|
+
const resolvedLabel = label ?? contract.label ?? "";
|
|
350
347
|
const resolvedPlaceholder = placeholder ?? contract.placeholder;
|
|
351
348
|
const resolvedIsDisabled = isDisabled ?? contract.disabled ?? false;
|
|
352
349
|
const effectiveInvalid = invalid !== void 0 ? invalid : rhfInvalid;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"phone-field.js","names":["BaseField"],"sources":["../../../src/particles/phone-field/phone-field.tsx"],"sourcesContent":["'use client';\nimport { Field as BaseField } from '@base-ui/react/field';\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ChangeEvent, FocusEvent, ReactNode, Ref } from 'react';\nimport { createContext, useContext, useMemo, useState } from 'react';\nimport { useFormContext, useFormState } from 'react-hook-form';\nimport {\n FieldBinding,\n type FieldContract,\n type FieldRule,\n mergeFieldValidator,\n TEXT_FIELD_VALUE,\n useBoundField,\n useField,\n} from '../field/field.js';\nimport { Input } from '../input/input.js';\nimport { useComposedRef } from '../shared/compose-refs.js';\n\n// ---------------------------------------------------------------------------\n// Country masks\n// ---------------------------------------------------------------------------\n\n/**\n * Country codes supported by PhoneField.\n * Only US and BR are implemented; every other ISO-2 code falls back to the US\n * format (Gap-06 in the PhoneField spec).\n */\nexport type PhoneCountry = 'US' | 'BR';\n\n/**\n * Returns true when `value` starts with the E.164 or bare country-code prefix\n * for the given country.\n *\n * US country code: 1 → \"+1…\" or \"1…\"\n * BR country code: 55 → \"+55…\" or \"55…\"\n */\nfunction isValidCountryCode(value: string, country: PhoneCountry): boolean {\n switch (country) {\n case 'US':\n return value.startsWith('+1') || value.startsWith('1');\n case 'BR':\n return value.startsWith('+55') || value.startsWith('55');\n default:\n return false;\n }\n}\n\n/**\n * Strips phone mask formatting from `value`.\n *\n * When the raw string carries a valid country-code prefix (e.g. \"+55…\"), the\n * returned value preserves the leading \"+\" so callers can detect E.164 intent.\n * Otherwise only digits are returned.\n *\n * `removePhoneMask(applyPhoneMask(raw, country), country) === raw` for all\n * valid raw values that do NOT carry a country-code prefix.\n */\nexport function removePhoneMask(value: string, country: PhoneCountry): string {\n const onlyDigits = value.replace(/\\D/g, '');\n\n // Only treat as E.164 when the raw string explicitly carries a \"+\" prefix.\n // A bare digit string that starts with the country-code digits (e.g. \"1234567890\"\n // starting with \"1\") is a local number, not a country-code-prefixed one.\n if (value.startsWith('+') && isValidCountryCode(value, country)) {\n return `+${onlyDigits}`;\n }\n\n return onlyDigits;\n}\n\n/**\n * Formats `value` into the mask pattern for `country`, applying as many mask\n * characters as the digit count allows (progressive masking while typing).\n *\n * US: (123) 456-7890 or +1 (123) 456-7890\n * BR: (11) 99999-9999 or +55 (11) 99999-9999\n *\n * Non-US/BR countries fall back to the US mask.\n */\nexport function applyPhoneMask(value: string, country: PhoneCountry): string {\n switch (country) {\n case 'US':\n return applyUSPhoneMask(value);\n case 'BR':\n return applyBRPhoneMask(value);\n default:\n return applyUSPhoneMask(value);\n }\n}\n\nfunction applyUSPhoneMask(value: string): string {\n const onlyDigits = value.replace(/\\D/g, '');\n\n // E.164 with explicit \"+\" prefix and full country code\n if (value.startsWith('+1') && onlyDigits.length >= 11) {\n const local = value.replace('+1', '').replace(/\\D/g, '');\n return `+1 ${formatUSNumber(local)}`;\n }\n\n // Bare country-code prefix (e.g. \"11234567890\")\n if (onlyDigits.startsWith('1') && onlyDigits.length === 11) {\n return `+1 ${formatUSNumber(onlyDigits.substring(1))}`;\n }\n\n return formatUSNumber(onlyDigits);\n}\n\nfunction formatUSNumber(digits: string): string {\n // US local numbers cap at 10 digits — drop the overflow instead of growing the mask unbounded.\n const local = digits.slice(0, 10);\n if (local.length === 0) return '';\n if (local.length <= 3) return `(${local}`;\n if (local.length <= 6) return `(${local.slice(0, 3)}) ${local.slice(3)}`;\n return `(${local.slice(0, 3)}) ${local.slice(3, 6)}-${local.slice(6)}`;\n}\n\nfunction applyBRPhoneMask(value: string): string {\n const onlyDigits = value.replace(/\\D/g, '');\n\n // E.164 with explicit \"+55\" prefix. 12 digits is a landline (+55 + 10 local),\n // 13 is a mobile (+55 + 11 local); both strip the \"55\" country code.\n if (value.startsWith('+55') && onlyDigits.length >= 12) {\n const local = value.replace('+55', '').replace(/\\D/g, '');\n return `+55 ${formatBRNumber(local)}`;\n }\n\n // Bare country-code prefix (e.g. \"5511999998888\" mobile, \"551133334444\" landline)\n if (onlyDigits.startsWith('55') && (onlyDigits.length === 12 || onlyDigits.length === 13)) {\n return `+55 ${formatBRNumber(onlyDigits.substring(2))}`;\n }\n\n return formatBRNumber(onlyDigits);\n}\n\nfunction formatBRNumber(digits: string): string {\n // BR local numbers cap at 11 digits (mobile) — drop the overflow instead of growing the mask unbounded.\n const local = digits.slice(0, 11);\n if (local.length === 0) return '';\n if (local.length <= 2) return `(${local}`;\n if (local.length <= 6) return `(${local.slice(0, 2)}) ${local.slice(2)}`;\n // 7-10 digits: landline format (XX) XXXX-XXXX\n if (local.length <= 10) return `(${local.slice(0, 2)}) ${local.slice(2, 6)}-${local.slice(6)}`;\n // 11 digits: mobile format (XX) XXXXX-XXXX\n return `(${local.slice(0, 2)}) ${local.slice(2, 7)}-${local.slice(7)}`;\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/**\n * BR local part: 10 digits is a landline; 11 digits is a mobile, which must carry the mandatory\n * ninth digit \"9\" right after the two-digit DDD (the `phone` library rule the spec's Gap-05\n * reimplements — \"11899998888\" is mobile-shaped but not a real BR number).\n */\nfunction isValidBRLocal(digits: string): boolean {\n if (digits.length === 10) return true;\n return digits.length === 11 && digits[2] === '9';\n}\n\n/**\n * Validates a raw (unmasked) phone number string for the given country.\n *\n * NOTE: The spec (KD-3) calls for using the `phone` npm library for validation.\n * The library is listed in Gap-05 as a new dependency to add when available.\n * Until that dependency is installed, this implements an equivalent\n * digit-count validation that covers all spec key-scenarios for US and BR.\n * Country-code and non-country-code inputs are both handled.\n *\n * US valid forms:\n * - 10 digits (local, e.g. \"1234567890\")\n * - 11 raw digits with country code \"1\" (e.g. \"11234567890\")\n * - E.164 \"+1\" + 10 digits (e.g. \"+11234567890\")\n *\n * BR valid forms:\n * - 10 digits (landline, e.g. \"1133334444\")\n * - 11 digits (mobile, e.g. \"11999998888\"; the ninth digit after the DDD must be \"9\")\n * - E.164 \"+55\" + 10 or 11 digits (e.g. \"+5511999998888\")\n */\nexport function validatePhoneNumber(input: string, country: PhoneCountry): boolean {\n if (!input || !input.trim()) return false;\n\n const digits = input.replace(/\\D/g, '');\n\n if (isValidCountryCode(input, country)) {\n // Country-code branch: validate digit count including the country code digits.\n if (country === 'US') {\n // \"+1\" or \"1\" prefix + exactly 10 local digits = 11 raw digits\n if (digits.length === 11) return true;\n // Fall through: could be a 10-digit local number that starts with \"1\"\n } else {\n // BR: \"+55\" or \"55\" prefix + 10 or 11 local digits = 12 or 13 raw digits\n if (digits.length === 12 || digits.length === 13) return isValidBRLocal(digits.slice(2));\n // Fall through: could be local digits that happen to start with \"55\"\n }\n }\n\n // Local (no country code) validation\n if (country === 'US') {\n return digits.length === 10;\n }\n\n return isValidBRLocal(digits);\n}\n\n/**\n * Normalizes a valid raw phone value to E.164 for persistence (legacy checkout parity): the\n * particle emits local digits (\"2015551234\") or a \"+\"-prefixed string; the profile stores\n * \"+12015551234\". Only call this on values `validatePhoneNumber` has already accepted — shared by\n * every binding that persists a phone value (`ClientProfilePhoneControl`, `ClientProfileFieldset`)\n * so there is exactly one normalization implementation.\n */\nexport function toE164(raw: string, country: PhoneCountry): string {\n const unmasked = removePhoneMask(raw, country);\n if (unmasked.startsWith('+')) return unmasked;\n const code = country === 'BR' ? '55' : '1';\n const localMax = country === 'BR' ? 11 : 10;\n // A bare country-code prefix (\"12015551234\", \"5511999998888\") only needs the \"+\".\n return unmasked.startsWith(code) && unmasked.length > localMax ? `+${unmasked}` : `+${code}${unmasked}`;\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype PhoneFieldRequirement = 'mandatory' | 'optional';\n\nexport type PhoneFieldProps = {\n /** Controlled raw (unmasked) phone value. Unused on the bound path — react-hook-form owns the value. */\n value?: string;\n /** Uncontrolled initial raw value. Unused on the bound path — the field contract's `defaultValue` seeds it instead. */\n defaultValue?: string;\n /** Called with the raw (unmasked) value on every change. */\n onValueChange?: (value: string) => void;\n /** Selects the phone mask and validation rule. */\n country?: PhoneCountry;\n /**\n * Visible field label. No signature default (Decision 5 of the wrapped-field-particles spec) — an\n * omitted label falls back to the field contract's `label` when bound, and to `'Phone'` when not.\n */\n label?: string;\n /** Disables the field when true. Falls back to the field contract's `disabled` when bound. */\n isDisabled?: boolean;\n /** Input placeholder text. Falls back to the field contract's `placeholder` when bound. */\n placeholder?: string;\n /**\n * Externally-controlled invalid state. When provided, overrides the\n * particle's internal blur-triggered validation result.\n */\n invalid?: boolean;\n /**\n * Externally-supplied error message. When provided, overrides the\n * particle's internal error string.\n */\n error?: string;\n /** Error string shown when the input format is invalid. */\n errorInvalid?: string;\n /** Error string shown when the mandatory field is left empty. */\n errorRequired?: string;\n /**\n * Raises the field to required. It only ever raises: bound to a fieldset whose rule already says\n * required, `'optional'` does not lower it.\n *\n * - `'mandatory'`: empty input blocks submission.\n * - `'optional'`: empty input is allowed; format is still checked when a\n * value is present.\n * - unset: no opinion, so a phone with no baseline is optional.\n */\n requirement?: PhoneFieldRequirement;\n /** Called after the field loses focus (post-validation). */\n onBlur?: () => void;\n /** Additional class applied to the root element. */\n className?: string;\n /**\n * Lands on the masked `<input type=\"tel\">` the particle renders. Composed with react-hook-form's own\n * ref on the bound path — a caller ref and react-hook-form's ref are both honoured.\n */\n ref?: Ref<HTMLInputElement>;\n /**\n * Given, replaces the default `Field.Label` + `PhoneFieldInput` + `Field.Error` anatomy — any order,\n * any subset. `PhoneFieldInput` is the one part that carries the mask, the composed ref and the\n * particle's own value/handlers; a composed generic `Field.Control` would call `useController` a\n * second time for the same name (RFC's named, accepted double-binder hole).\n */\n children?: ReactNode;\n};\n\n// ---------------------------------------------------------------------------\n// Definition\n// ---------------------------------------------------------------------------\n\nexport const PhoneFieldDefinition = defineComponent<PhoneFieldProps>({\n name: 'PhoneField',\n importPath: '@vtex/faststore/components',\n component: PhoneField,\n providesContext: 'phone-field',\n editor: { label: 'Phone Field', category: 'action' },\n schema: {\n country: { type: 'string', default: 'US', label: 'Country (US or BR)' },\n label: { type: 'string', default: 'Phone', label: 'Label' },\n // No default: an unset requirement is no opinion, not a raise to mandatory.\n requirement: { type: ['mandatory', 'optional'] as const, label: 'Requirement' },\n errorInvalid: { type: 'string', default: 'Invalid phone number', label: 'Invalid error message' },\n errorRequired: { type: 'string', default: 'Phone number is required', label: 'Required error message' },\n },\n guideline:\n 'Locale-aware, business-agnostic phone number input composed from the field + input particles. Applies country masking, validates on blur, and exposes its value via onValueChange. Bind it to a data source (e.g. ClientProfilePhoneControl for checkout) to persist the value. Recomposable (RFC:503): given children, they replace the default Field.Label + PhoneFieldInput + Field.Error anatomy, in any order.',\n});\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * Presentational, business-agnostic phone field. Composes the `field` and `input` particles: the\n * `Field.Root` owns the invalid/disabled state and the `Field.Error match` slot, while the `Input`\n * particle renders the masked `<tel>` control. The particle stays reusable (checkout binding today,\n * MyAccount / extensions later); a binding owns the data source and persistence.\n *\n * US/BR masking, blur validation, and the `data-fs-phone-field*` attributes (plus the country variant\n * attribute) are kept; error strings remain props (a documented i18n divergence — the country tables\n * are internal, the copy is owner-supplied).\n *\n * Reads the field contract through `useField()` and `useFormContext()` and dispatches to a bound or an\n * unbound sub-component — \"bound\" means both are present. Every react-hook-form hook lives in\n * `BoundPhoneField`, so hook order never changes under a mounted component. Both sub-components render\n * the same `PhoneFieldView`, so the two paths cannot drift into different DOM.\n */\nexport function PhoneField({ requirement, ...props }: PhoneFieldProps): ReactNode {\n const contract = useField();\n const formContext = useFormContext();\n\n if (contract && formContext) {\n return <BoundPhoneField {...props} requirement={requirement} contract={contract} />;\n }\n\n return <UnboundPhoneField {...props} requirement={requirement} />;\n}\n\n// ---------------------------------------------------------------------------\n// Input part — catalogued, placeable (Decision 4). Carries the mask, the composed ref, and the\n// particle's own onChange/onBlur; a generic Field.Control cannot be this part, because the mask and\n// the country/requirement validator belong to PhoneField, not to react-hook-form's own registration.\n// ---------------------------------------------------------------------------\n\ntype PhoneFieldInputContextValue = {\n ref?: Ref<HTMLInputElement>;\n value: string;\n placeholder?: string;\n /** Resolved by the binder, threaded here because this part is not the one that binds. */\n required: boolean;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: (event: FocusEvent<HTMLInputElement>) => void;\n};\n\nconst PhoneFieldInputContext = createContext<PhoneFieldInputContextValue | null>(null);\n\nfunction usePhoneFieldInputContext(): PhoneFieldInputContextValue {\n const context = useContext(PhoneFieldInputContext);\n if (!context) {\n throw new Error('PhoneFieldInput must be a descendant of PhoneField.');\n }\n return context;\n}\n\nexport type PhoneFieldInputProps = { className?: string };\n\nexport const PhoneFieldInputDefinition = defineComponent<PhoneFieldInputProps>({\n name: 'PhoneFieldInput',\n importPath: '@vtex/faststore/components',\n component: PhoneFieldInput,\n requiresContext: 'phone-field',\n editor: { label: 'Phone Field Input', category: 'action' },\n schema: {},\n guideline:\n \"The masked <input type=\\\"tel\\\"> PhoneField owns. Must sit inside PhoneField, in either the default anatomy or an author's composed children. Carries the country mask, the composed ref, and PhoneField's own onChange/onBlur — a composed Field.Control here instead re-registers the field with react-hook-form and loses the mask (unsupported, RFC's named double-binder hole).\",\n});\n\n/** Renders the masked `<input>`, reading its value/handlers/ref from the enclosing `PhoneField`. */\nexport function PhoneFieldInput({ className }: PhoneFieldInputProps): ReactNode {\n const { ref, value, placeholder, required, onChange, onBlur } = usePhoneFieldInputContext();\n\n return (\n <Input\n ref={ref}\n data-fs-phone-field-input=\"\"\n type=\"tel\"\n inputMode=\"numeric\"\n // `aria-required`, not native `required`, for the reason password-field.tsx:89-91 records:\n // `Input` is a Base UI `Field.Control`, and native constraint tracking would flip\n // `aria-invalid` on its own, ahead of react-hook-form's own validation.\n aria-required={required || undefined}\n value={value}\n onChange={onChange}\n onBlur={onBlur}\n placeholder={placeholder}\n className={className}\n />\n );\n}\n\n// ---------------------------------------------------------------------------\n// Shared view — identical DOM whether bound or unbound\n// ---------------------------------------------------------------------------\n\ntype PhoneFieldViewProps = {\n ref?: Ref<HTMLInputElement>;\n country: PhoneCountry;\n className?: string;\n label: string;\n isDisabled: boolean;\n placeholder?: string;\n required: boolean;\n maskedValue: string;\n effectiveInvalid: boolean;\n effectiveError: string;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: (event: FocusEvent<HTMLInputElement>) => void;\n children?: ReactNode;\n};\n\nfunction PhoneFieldView({\n ref,\n country,\n className,\n label,\n isDisabled,\n placeholder,\n required,\n maskedValue,\n effectiveInvalid,\n effectiveError,\n onChange,\n onBlur,\n children,\n}: PhoneFieldViewProps) {\n const inputContext = useMemo<PhoneFieldInputContextValue>(\n () => ({ ref, value: maskedValue, placeholder, required, onChange, onBlur }),\n [ref, maskedValue, placeholder, required, onChange, onBlur],\n );\n\n return (\n // Deliberately the RAW Base UI Field primitives, not this package's own Field.Root/Label/Error\n // wrapper, for the default anatomy: this reproduces exactly what rendered before Decision 3\n // (when FieldContractBoundary shielded this subtree from the ambient contract) — the resolved\n // `label`/`effectiveError` text renders unconditionally, and Field.Root's own dirty/touched\n // fallback tracking stays in charge, rather than react-hook-form's. Composed children, below,\n // use the package's own Field.* parts on purpose — that is what makes a childless Field.Label /\n // Field.Error resolve real text (FR-5).\n <BaseField.Root\n data-fs-phone-field-root=\"\"\n data-fs-phone-field-root-country={country}\n data-fs-field-root=\"\"\n className={className}\n invalid={effectiveInvalid}\n disabled={isDisabled}\n >\n <PhoneFieldInputContext.Provider value={inputContext}>\n {children ?? (\n <>\n <BaseField.Label data-fs-phone-field-label=\"\" data-fs-field-label=\"\">\n {label}\n </BaseField.Label>\n <PhoneFieldInput />\n {effectiveError ? (\n <BaseField.Error match data-fs-phone-field-error=\"\" data-fs-field-error=\"\">\n {effectiveError}\n </BaseField.Error>\n ) : null}\n </>\n )}\n </PhoneFieldInputContext.Provider>\n </BaseField.Root>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Unbound — today's body, moved verbatim\n// ---------------------------------------------------------------------------\n\ntype UnboundPhoneFieldProps = PhoneFieldProps;\n\nfunction UnboundPhoneField({\n value,\n defaultValue = '',\n onValueChange,\n country = 'US',\n label,\n isDisabled = false,\n placeholder,\n invalid,\n error,\n errorInvalid = 'Invalid phone number',\n errorRequired = 'Phone number is required',\n requirement,\n onBlur,\n className,\n ref,\n children,\n}: UnboundPhoneFieldProps) {\n const isControlled = value !== undefined;\n\n const [internalRaw, setInternalRaw] = useState(defaultValue);\n const [localInvalid, setLocalInvalid] = useState(false);\n const [localError, setLocalError] = useState('');\n\n // Clear local validation state when country changes so the next blur re-validates against the new\n // country's rules. The comparison baseline lives in state, not a ref, and the compare-and-set runs\n // during render (before paint), so a render React abandons without committing — a suspended\n // transition, a Suspense retry — never leaves a stale baseline behind the way a ref write would.\n const [prevCountry, setPrevCountry] = useState(country);\n if (prevCountry !== country) {\n setPrevCountry(country);\n setLocalInvalid(false);\n setLocalError('');\n }\n\n const rawValue = isControlled ? (value as string) : internalRaw;\n const maskedValue = applyPhoneMask(rawValue, country);\n const resolvedLabel = label ?? 'Phone';\n\n // External props take precedence over internal validation state.\n // When `invalid` is externally controlled, the error display is also fully\n // controlled: use the explicit `error` prop, or fall back to empty string so\n // no stale local error leaks through when the parent says the field is valid.\n const effectiveInvalid = invalid !== undefined ? invalid : localInvalid;\n const effectiveError = error !== undefined ? error : effectiveInvalid ? localError : '';\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n if (isDisabled) return;\n const raw = removePhoneMask(event.target.value, country);\n if (!isControlled) {\n setInternalRaw(raw);\n }\n onValueChange?.(raw);\n }\n\n function handleBlur(_event: FocusEvent<HTMLInputElement>) {\n if (isDisabled) return;\n\n let isFieldInvalid = false;\n let fieldError = '';\n\n if (requirement === 'mandatory' && !rawValue.trim()) {\n isFieldInvalid = true;\n fieldError = errorRequired;\n } else if (rawValue.trim()) {\n const valid = validatePhoneNumber(rawValue, country);\n isFieldInvalid = !valid;\n fieldError = valid ? '' : errorInvalid;\n }\n // optional + empty → no error, keep isFieldInvalid = false / fieldError = ''\n\n setLocalInvalid(isFieldInvalid);\n setLocalError(fieldError);\n onBlur?.();\n }\n\n return (\n <PhoneFieldView\n ref={ref}\n country={country}\n className={className}\n label={resolvedLabel}\n isDisabled={isDisabled}\n placeholder={placeholder}\n required={requirement === 'mandatory'}\n maskedValue={maskedValue}\n effectiveInvalid={effectiveInvalid}\n effectiveError={effectiveError}\n onChange={handleChange}\n onBlur={handleBlur}\n >\n {children}\n </PhoneFieldView>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Bound — reads the field contract, binds through useController\n// ---------------------------------------------------------------------------\n\ntype BoundPhoneFieldProps = UnboundPhoneFieldProps & { contract: FieldContract };\n\nfunction BoundPhoneField({\n value: _value,\n defaultValue: _defaultValue,\n onValueChange,\n country = 'US',\n label,\n isDisabled,\n placeholder,\n invalid,\n error,\n errorInvalid = 'Invalid phone number',\n errorRequired = 'Phone number is required',\n requirement,\n onBlur,\n className,\n ref: callerRef,\n contract,\n children,\n}: BoundPhoneFieldProps) {\n // Format only. Requiredness is not decided here: `useBoundField` resolves it from the fieldset's\n // baseline and the raise below, and installs the blank check, so the announcement and the\n // validation cannot disagree. The check composes alongside whatever the fieldset validates —\n // before this merge, any contract validator discarded the particle's own validation whole.\n const rule = useMemo<FieldRule>(\n () =>\n mergeFieldValidator(contract.rule, 'phoneFormat', (rawValue) => {\n const raw = typeof rawValue === 'string' ? rawValue : String(rawValue ?? '');\n return !raw.trim() || validatePhoneNumber(raw, country) || errorInvalid;\n }),\n [contract.rule, errorInvalid, country],\n );\n\n const field = useBoundField(contract, TEXT_FIELD_VALUE, rule, {\n required: requirement === 'mandatory',\n message: errorRequired,\n });\n const { getFieldState } = useFormContext();\n const { invalid: rhfInvalid, error: rhfError } = getFieldState(contract.name, useFormState({ name: contract.name }));\n\n const composedRef = useComposedRef<HTMLInputElement>(callerRef, field.ref);\n\n const rawValue = typeof field.value === 'string' ? field.value : String(field.value ?? '');\n const maskedValue = applyPhoneMask(rawValue, country);\n const resolvedLabel = label ?? contract.label ?? 'Phone';\n const resolvedPlaceholder = placeholder ?? contract.placeholder;\n const resolvedIsDisabled = isDisabled ?? contract.disabled ?? false;\n\n const effectiveInvalid = invalid !== undefined ? invalid : rhfInvalid;\n const effectiveError = error !== undefined ? error : effectiveInvalid ? (rhfError?.message ?? '') : '';\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n const raw = removePhoneMask(event.target.value, country);\n field.onChange(raw);\n onValueChange?.(raw);\n }\n\n function handleBlur(_event: FocusEvent<HTMLInputElement>) {\n field.onBlur();\n onBlur?.();\n }\n\n return (\n // Decision 3: replaces the empty-contract FieldContractBoundary with a re-provided contract\n // carrying the RESOLVED name/label/placeholder — the values a composed childless Field.Label /\n // Field.Error actually need, as opposed to the raw (possibly-undefined) ones the ambient\n // contract from the enclosing FieldBinding carries. useBoundField above remains the sole binder\n // for contract.name; this FieldBinding never registers anything itself.\n <FieldBinding\n name={contract.name}\n label={resolvedLabel}\n placeholder={resolvedPlaceholder}\n defaultValue={contract.defaultValue}\n rule={contract.rule}\n options={contract.options}\n disabled={resolvedIsDisabled}\n readOnly={contract.readOnly}\n autoComplete={contract.autoComplete}\n inputMode={contract.inputMode}\n >\n <PhoneFieldView\n ref={composedRef}\n country={country}\n className={className}\n label={resolvedLabel}\n isDisabled={resolvedIsDisabled}\n placeholder={resolvedPlaceholder}\n required={field.required}\n maskedValue={maskedValue}\n effectiveInvalid={effectiveInvalid}\n effectiveError={effectiveError}\n onChange={handleChange}\n onBlur={handleBlur}\n >\n {children}\n </PhoneFieldView>\n </FieldBinding>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"phone-field.js","names":["BaseField"],"sources":["../../../src/particles/phone-field/phone-field.tsx"],"sourcesContent":["'use client';\nimport { Field as BaseField } from '@base-ui/react/field';\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ChangeEvent, FocusEvent, ReactNode, Ref } from 'react';\nimport { createContext, useContext, useMemo, useState } from 'react';\nimport { useFormContext, useFormState } from 'react-hook-form';\nimport {\n FieldBinding,\n type FieldContract,\n type FieldRule,\n mergeFieldValidator,\n TEXT_FIELD_VALUE,\n useBoundField,\n useField,\n} from '../field/field.js';\nimport { Input } from '../input/input.js';\nimport { useComposedRef } from '../shared/compose-refs.js';\n\n// ---------------------------------------------------------------------------\n// Country masks\n// ---------------------------------------------------------------------------\n\n/**\n * Country codes supported by PhoneField.\n * Only US and BR are implemented; every other ISO-2 code falls back to the US\n * format (Gap-06 in the PhoneField spec).\n */\nexport type PhoneCountry = 'US' | 'BR';\n\n/**\n * Returns true when `value` starts with the E.164 or bare country-code prefix\n * for the given country.\n *\n * US country code: 1 → \"+1…\" or \"1…\"\n * BR country code: 55 → \"+55…\" or \"55…\"\n */\nfunction isValidCountryCode(value: string, country: PhoneCountry): boolean {\n switch (country) {\n case 'US':\n return value.startsWith('+1') || value.startsWith('1');\n case 'BR':\n return value.startsWith('+55') || value.startsWith('55');\n default:\n return false;\n }\n}\n\n/**\n * Strips phone mask formatting from `value`.\n *\n * When the raw string carries a valid country-code prefix (e.g. \"+55…\"), the\n * returned value preserves the leading \"+\" so callers can detect E.164 intent.\n * Otherwise only digits are returned.\n *\n * `removePhoneMask(applyPhoneMask(raw, country), country) === raw` for all\n * valid raw values that do NOT carry a country-code prefix.\n */\nexport function removePhoneMask(value: string, country: PhoneCountry): string {\n const onlyDigits = value.replace(/\\D/g, '');\n\n // Only treat as E.164 when the raw string explicitly carries a \"+\" prefix.\n // A bare digit string that starts with the country-code digits (e.g. \"1234567890\"\n // starting with \"1\") is a local number, not a country-code-prefixed one.\n if (value.startsWith('+') && isValidCountryCode(value, country)) {\n return `+${onlyDigits}`;\n }\n\n return onlyDigits;\n}\n\n/**\n * Formats `value` into the mask pattern for `country`, applying as many mask\n * characters as the digit count allows (progressive masking while typing).\n *\n * US: (123) 456-7890 or +1 (123) 456-7890\n * BR: (11) 99999-9999 or +55 (11) 99999-9999\n *\n * Non-US/BR countries fall back to the US mask.\n */\nexport function applyPhoneMask(value: string, country: PhoneCountry): string {\n switch (country) {\n case 'US':\n return applyUSPhoneMask(value);\n case 'BR':\n return applyBRPhoneMask(value);\n default:\n return applyUSPhoneMask(value);\n }\n}\n\nfunction applyUSPhoneMask(value: string): string {\n const onlyDigits = value.replace(/\\D/g, '');\n\n // E.164 with explicit \"+\" prefix and full country code\n if (value.startsWith('+1') && onlyDigits.length >= 11) {\n const local = value.replace('+1', '').replace(/\\D/g, '');\n return `+1 ${formatUSNumber(local)}`;\n }\n\n // Bare country-code prefix (e.g. \"11234567890\")\n if (onlyDigits.startsWith('1') && onlyDigits.length === 11) {\n return `+1 ${formatUSNumber(onlyDigits.substring(1))}`;\n }\n\n return formatUSNumber(onlyDigits);\n}\n\nfunction formatUSNumber(digits: string): string {\n // US local numbers cap at 10 digits — drop the overflow instead of growing the mask unbounded.\n const local = digits.slice(0, 10);\n if (local.length === 0) return '';\n if (local.length <= 3) return `(${local}`;\n if (local.length <= 6) return `(${local.slice(0, 3)}) ${local.slice(3)}`;\n return `(${local.slice(0, 3)}) ${local.slice(3, 6)}-${local.slice(6)}`;\n}\n\nfunction applyBRPhoneMask(value: string): string {\n const onlyDigits = value.replace(/\\D/g, '');\n\n // E.164 with explicit \"+55\" prefix. 12 digits is a landline (+55 + 10 local),\n // 13 is a mobile (+55 + 11 local); both strip the \"55\" country code.\n if (value.startsWith('+55') && onlyDigits.length >= 12) {\n const local = value.replace('+55', '').replace(/\\D/g, '');\n return `+55 ${formatBRNumber(local)}`;\n }\n\n // Bare country-code prefix (e.g. \"5511999998888\" mobile, \"551133334444\" landline)\n if (onlyDigits.startsWith('55') && (onlyDigits.length === 12 || onlyDigits.length === 13)) {\n return `+55 ${formatBRNumber(onlyDigits.substring(2))}`;\n }\n\n return formatBRNumber(onlyDigits);\n}\n\nfunction formatBRNumber(digits: string): string {\n // BR local numbers cap at 11 digits (mobile) — drop the overflow instead of growing the mask unbounded.\n const local = digits.slice(0, 11);\n if (local.length === 0) return '';\n if (local.length <= 2) return `(${local}`;\n if (local.length <= 6) return `(${local.slice(0, 2)}) ${local.slice(2)}`;\n // 7-10 digits: landline format (XX) XXXX-XXXX\n if (local.length <= 10) return `(${local.slice(0, 2)}) ${local.slice(2, 6)}-${local.slice(6)}`;\n // 11 digits: mobile format (XX) XXXXX-XXXX\n return `(${local.slice(0, 2)}) ${local.slice(2, 7)}-${local.slice(7)}`;\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/**\n * BR local part: 10 digits is a landline; 11 digits is a mobile, which must carry the mandatory\n * ninth digit \"9\" right after the two-digit DDD (the `phone` library rule the spec's Gap-05\n * reimplements — \"11899998888\" is mobile-shaped but not a real BR number).\n */\nfunction isValidBRLocal(digits: string): boolean {\n if (digits.length === 10) return true;\n return digits.length === 11 && digits[2] === '9';\n}\n\n/**\n * Validates a raw (unmasked) phone number string for the given country.\n *\n * NOTE: The spec (KD-3) calls for using the `phone` npm library for validation.\n * The library is listed in Gap-05 as a new dependency to add when available.\n * Until that dependency is installed, this implements an equivalent\n * digit-count validation that covers all spec key-scenarios for US and BR.\n * Country-code and non-country-code inputs are both handled.\n *\n * US valid forms:\n * - 10 digits (local, e.g. \"1234567890\")\n * - 11 raw digits with country code \"1\" (e.g. \"11234567890\")\n * - E.164 \"+1\" + 10 digits (e.g. \"+11234567890\")\n *\n * BR valid forms:\n * - 10 digits (landline, e.g. \"1133334444\")\n * - 11 digits (mobile, e.g. \"11999998888\"; the ninth digit after the DDD must be \"9\")\n * - E.164 \"+55\" + 10 or 11 digits (e.g. \"+5511999998888\")\n */\nexport function validatePhoneNumber(input: string, country: PhoneCountry): boolean {\n if (!input || !input.trim()) return false;\n\n const digits = input.replace(/\\D/g, '');\n\n if (isValidCountryCode(input, country)) {\n // Country-code branch: validate digit count including the country code digits.\n if (country === 'US') {\n // \"+1\" or \"1\" prefix + exactly 10 local digits = 11 raw digits\n if (digits.length === 11) return true;\n // Fall through: could be a 10-digit local number that starts with \"1\"\n } else {\n // BR: \"+55\" or \"55\" prefix + 10 or 11 local digits = 12 or 13 raw digits\n if (digits.length === 12 || digits.length === 13) return isValidBRLocal(digits.slice(2));\n // Fall through: could be local digits that happen to start with \"55\"\n }\n }\n\n // Local (no country code) validation\n if (country === 'US') {\n return digits.length === 10;\n }\n\n return isValidBRLocal(digits);\n}\n\n/**\n * Normalizes a valid raw phone value to E.164 for persistence (legacy checkout parity): the\n * particle emits local digits (\"2015551234\") or a \"+\"-prefixed string; the profile stores\n * \"+12015551234\". Only call this on values `validatePhoneNumber` has already accepted — shared by\n * every binding that persists a phone value (`ClientProfilePhoneControl`, `ClientProfileFieldset`)\n * so there is exactly one normalization implementation.\n */\nexport function toE164(raw: string, country: PhoneCountry): string {\n const unmasked = removePhoneMask(raw, country);\n if (unmasked.startsWith('+')) return unmasked;\n const code = country === 'BR' ? '55' : '1';\n const localMax = country === 'BR' ? 11 : 10;\n // A bare country-code prefix (\"12015551234\", \"5511999998888\") only needs the \"+\".\n return unmasked.startsWith(code) && unmasked.length > localMax ? `+${unmasked}` : `+${code}${unmasked}`;\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype PhoneFieldRequirement = 'mandatory' | 'optional';\n\nexport type PhoneFieldProps = {\n /** Controlled raw (unmasked) phone value. Unused on the bound path — react-hook-form owns the value. */\n value?: string;\n /** Uncontrolled initial raw value. Unused on the bound path — the field contract's `defaultValue` seeds it instead. */\n defaultValue?: string;\n /** Called with the raw (unmasked) value on every change. */\n onValueChange?: (value: string) => void;\n /** Selects the phone mask and validation rule. */\n country?: PhoneCountry;\n /**\n * Visible field label, formatted by the owner. No default: an omitted label falls back to the field\n * contract's `label` when bound, and renders empty when not.\n */\n label?: string;\n /** Disables the field when true. Falls back to the field contract's `disabled` when bound. */\n isDisabled?: boolean;\n /** Input placeholder text. Falls back to the field contract's `placeholder` when bound. */\n placeholder?: string;\n /**\n * Externally-controlled invalid state. When provided, overrides the\n * particle's internal blur-triggered validation result.\n */\n invalid?: boolean;\n /**\n * Externally-supplied error message. When provided, overrides the\n * particle's internal error string.\n */\n error?: string;\n /** Error string shown when the input format is invalid, formatted by the owner. No default. */\n errorInvalid?: string;\n /** Error string shown when the mandatory field is left empty, formatted by the owner. No default. */\n errorRequired?: string;\n /**\n * Raises the field to required. It only ever raises: bound to a fieldset whose rule already says\n * required, `'optional'` does not lower it.\n *\n * - `'mandatory'`: empty input blocks submission.\n * - `'optional'`: empty input is allowed; format is still checked when a\n * value is present.\n * - unset: no opinion, so a phone with no baseline is optional.\n */\n requirement?: PhoneFieldRequirement;\n /** Called after the field loses focus (post-validation). */\n onBlur?: () => void;\n /** Additional class applied to the root element. */\n className?: string;\n /**\n * Lands on the masked `<input type=\"tel\">` the particle renders. Composed with react-hook-form's own\n * ref on the bound path — a caller ref and react-hook-form's ref are both honoured.\n */\n ref?: Ref<HTMLInputElement>;\n /**\n * Given, replaces the default `Field.Label` + `PhoneFieldInput` + `Field.Error` anatomy — any order,\n * any subset. `PhoneFieldInput` is the one part that carries the mask, the composed ref and the\n * particle's own value/handlers; a composed generic `Field.Control` would call `useController` a\n * second time for the same name (RFC's named, accepted double-binder hole).\n */\n children?: ReactNode;\n};\n\n// ---------------------------------------------------------------------------\n// Definition\n// ---------------------------------------------------------------------------\n\nexport const PhoneFieldDefinition = defineComponent<PhoneFieldProps>({\n name: 'PhoneField',\n importPath: '@vtex/faststore/components',\n component: PhoneField,\n providesContext: 'phone-field',\n editor: { label: 'Phone Field', category: 'action' },\n schema: {\n country: { type: 'string', default: 'US', label: 'Country (US or BR)' },\n // Copy props carry no default: the owner formats them from its own message fields.\n label: { type: 'string', label: 'Label' },\n // No default: an unset requirement is no opinion, not a raise to mandatory.\n requirement: { type: ['mandatory', 'optional'] as const, label: 'Requirement' },\n errorInvalid: { type: 'string', label: 'Invalid error message' },\n errorRequired: { type: 'string', label: 'Required error message' },\n },\n guideline:\n 'Locale-aware, business-agnostic phone number input composed from the field + input particles. Applies country masking, validates on blur, and exposes its value via onValueChange. Bind it to a data source (e.g. ClientProfilePhoneControl for checkout) to persist the value; the owner supplies label, errorInvalid and errorRequired, which have no default. Recomposable (RFC:503): given children, they replace the default Field.Label + PhoneFieldInput + Field.Error anatomy, in any order.',\n});\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * Presentational, business-agnostic phone field. Composes the `field` and `input` particles: the\n * `Field.Root` owns the invalid/disabled state and the `Field.Error match` slot, while the `Input`\n * particle renders the masked `<tel>` control. The particle stays reusable (checkout binding today,\n * MyAccount / extensions later); a binding owns the data source and persistence.\n *\n * US/BR masking, blur validation, and the `data-fs-phone-field*` attributes (plus the country variant\n * attribute) are kept; error strings remain props (a documented i18n divergence — the country tables\n * are internal, the copy is owner-supplied).\n *\n * Reads the field contract through `useField()` and `useFormContext()` and dispatches to a bound or an\n * unbound sub-component — \"bound\" means both are present. Every react-hook-form hook lives in\n * `BoundPhoneField`, so hook order never changes under a mounted component. Both sub-components render\n * the same `PhoneFieldView`, so the two paths cannot drift into different DOM.\n */\nexport function PhoneField({ requirement, ...props }: PhoneFieldProps): ReactNode {\n const contract = useField();\n const formContext = useFormContext();\n\n if (contract && formContext) {\n return <BoundPhoneField {...props} requirement={requirement} contract={contract} />;\n }\n\n return <UnboundPhoneField {...props} requirement={requirement} />;\n}\n\n// ---------------------------------------------------------------------------\n// Input part — catalogued, placeable (Decision 4). Carries the mask, the composed ref, and the\n// particle's own onChange/onBlur; a generic Field.Control cannot be this part, because the mask and\n// the country/requirement validator belong to PhoneField, not to react-hook-form's own registration.\n// ---------------------------------------------------------------------------\n\ntype PhoneFieldInputContextValue = {\n ref?: Ref<HTMLInputElement>;\n value: string;\n placeholder?: string;\n /** Resolved by the binder, threaded here because this part is not the one that binds. */\n required: boolean;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: (event: FocusEvent<HTMLInputElement>) => void;\n};\n\nconst PhoneFieldInputContext = createContext<PhoneFieldInputContextValue | null>(null);\n\nfunction usePhoneFieldInputContext(): PhoneFieldInputContextValue {\n const context = useContext(PhoneFieldInputContext);\n if (!context) {\n throw new Error('PhoneFieldInput must be a descendant of PhoneField.');\n }\n return context;\n}\n\nexport type PhoneFieldInputProps = { className?: string };\n\nexport const PhoneFieldInputDefinition = defineComponent<PhoneFieldInputProps>({\n name: 'PhoneFieldInput',\n importPath: '@vtex/faststore/components',\n component: PhoneFieldInput,\n requiresContext: 'phone-field',\n editor: { label: 'Phone Field Input', category: 'action' },\n schema: {},\n guideline:\n \"The masked <input type=\\\"tel\\\"> PhoneField owns. Must sit inside PhoneField, in either the default anatomy or an author's composed children. Carries the country mask, the composed ref, and PhoneField's own onChange/onBlur — a composed Field.Control here instead re-registers the field with react-hook-form and loses the mask (unsupported, RFC's named double-binder hole).\",\n});\n\n/** Renders the masked `<input>`, reading its value/handlers/ref from the enclosing `PhoneField`. */\nexport function PhoneFieldInput({ className }: PhoneFieldInputProps): ReactNode {\n const { ref, value, placeholder, required, onChange, onBlur } = usePhoneFieldInputContext();\n\n return (\n <Input\n ref={ref}\n data-fs-phone-field-input=\"\"\n type=\"tel\"\n inputMode=\"numeric\"\n // `aria-required`, not native `required`, for the reason password-field.tsx:89-91 records:\n // `Input` is a Base UI `Field.Control`, and native constraint tracking would flip\n // `aria-invalid` on its own, ahead of react-hook-form's own validation.\n aria-required={required || undefined}\n value={value}\n onChange={onChange}\n onBlur={onBlur}\n placeholder={placeholder}\n className={className}\n />\n );\n}\n\n// ---------------------------------------------------------------------------\n// Shared view — identical DOM whether bound or unbound\n// ---------------------------------------------------------------------------\n\ntype PhoneFieldViewProps = {\n ref?: Ref<HTMLInputElement>;\n country: PhoneCountry;\n className?: string;\n label: string;\n isDisabled: boolean;\n placeholder?: string;\n required: boolean;\n maskedValue: string;\n effectiveInvalid: boolean;\n effectiveError: string;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: (event: FocusEvent<HTMLInputElement>) => void;\n children?: ReactNode;\n};\n\nfunction PhoneFieldView({\n ref,\n country,\n className,\n label,\n isDisabled,\n placeholder,\n required,\n maskedValue,\n effectiveInvalid,\n effectiveError,\n onChange,\n onBlur,\n children,\n}: PhoneFieldViewProps) {\n const inputContext = useMemo<PhoneFieldInputContextValue>(\n () => ({ ref, value: maskedValue, placeholder, required, onChange, onBlur }),\n [ref, maskedValue, placeholder, required, onChange, onBlur],\n );\n\n return (\n // Deliberately the RAW Base UI Field primitives, not this package's own Field.Root/Label/Error\n // wrapper, for the default anatomy: this reproduces exactly what rendered before Decision 3\n // (when FieldContractBoundary shielded this subtree from the ambient contract) — the resolved\n // `label`/`effectiveError` text renders unconditionally, and Field.Root's own dirty/touched\n // fallback tracking stays in charge, rather than react-hook-form's. Composed children, below,\n // use the package's own Field.* parts on purpose — that is what makes a childless Field.Label /\n // Field.Error resolve real text (FR-5).\n <BaseField.Root\n data-fs-phone-field-root=\"\"\n data-fs-phone-field-root-country={country}\n data-fs-field-root=\"\"\n className={className}\n invalid={effectiveInvalid}\n disabled={isDisabled}\n >\n <PhoneFieldInputContext.Provider value={inputContext}>\n {children ?? (\n <>\n <BaseField.Label data-fs-phone-field-label=\"\" data-fs-field-label=\"\">\n {label}\n </BaseField.Label>\n <PhoneFieldInput />\n {effectiveError ? (\n <BaseField.Error match data-fs-phone-field-error=\"\" data-fs-field-error=\"\">\n {effectiveError}\n </BaseField.Error>\n ) : null}\n </>\n )}\n </PhoneFieldInputContext.Provider>\n </BaseField.Root>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Unbound — today's body, moved verbatim\n// ---------------------------------------------------------------------------\n\ntype UnboundPhoneFieldProps = PhoneFieldProps;\n\nfunction UnboundPhoneField({\n value,\n defaultValue = '',\n onValueChange,\n country = 'US',\n label,\n isDisabled = false,\n placeholder,\n invalid,\n error,\n errorInvalid,\n errorRequired,\n requirement,\n onBlur,\n className,\n ref,\n children,\n}: Readonly<UnboundPhoneFieldProps>) {\n const isControlled = value !== undefined;\n\n const [internalRaw, setInternalRaw] = useState(defaultValue);\n const [localInvalid, setLocalInvalid] = useState(false);\n const [localError, setLocalError] = useState('');\n\n // Clear local validation state when country changes so the next blur re-validates against the new\n // country's rules. The comparison baseline lives in state, not a ref, and the compare-and-set runs\n // during render (before paint), so a render React abandons without committing — a suspended\n // transition, a Suspense retry — never leaves a stale baseline behind the way a ref write would.\n const [prevCountry, setPrevCountry] = useState(country);\n if (prevCountry !== country) {\n setPrevCountry(country);\n setLocalInvalid(false);\n setLocalError('');\n }\n\n const rawValue = isControlled ? (value as string) : internalRaw;\n const maskedValue = applyPhoneMask(rawValue, country);\n const resolvedLabel = label ?? '';\n\n // External props take precedence over internal validation state.\n // When `invalid` is externally controlled, the error display is also fully\n // controlled: use the explicit `error` prop, or fall back to empty string so\n // no stale local error leaks through when the parent says the field is valid.\n const effectiveInvalid = invalid !== undefined ? invalid : localInvalid;\n const effectiveError = error !== undefined ? error : effectiveInvalid ? localError : '';\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n if (isDisabled) return;\n const raw = removePhoneMask(event.target.value, country);\n if (!isControlled) {\n setInternalRaw(raw);\n }\n onValueChange?.(raw);\n }\n\n function handleBlur(_event: FocusEvent<HTMLInputElement>) {\n if (isDisabled) return;\n\n let isFieldInvalid = false;\n let fieldError = '';\n\n if (requirement === 'mandatory' && !rawValue.trim()) {\n isFieldInvalid = true;\n fieldError = errorRequired ?? '';\n } else if (rawValue.trim()) {\n const valid = validatePhoneNumber(rawValue, country);\n isFieldInvalid = !valid;\n fieldError = valid ? '' : (errorInvalid ?? '');\n }\n // optional + empty → no error, keep isFieldInvalid = false / fieldError = ''\n\n setLocalInvalid(isFieldInvalid);\n setLocalError(fieldError);\n onBlur?.();\n }\n\n return (\n <PhoneFieldView\n ref={ref}\n country={country}\n className={className}\n label={resolvedLabel}\n isDisabled={isDisabled}\n placeholder={placeholder}\n required={requirement === 'mandatory'}\n maskedValue={maskedValue}\n effectiveInvalid={effectiveInvalid}\n effectiveError={effectiveError}\n onChange={handleChange}\n onBlur={handleBlur}\n >\n {children}\n </PhoneFieldView>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Bound — reads the field contract, binds through useController\n// ---------------------------------------------------------------------------\n\ntype BoundPhoneFieldProps = UnboundPhoneFieldProps & { contract: FieldContract };\n\nfunction BoundPhoneField({\n value: _value,\n defaultValue: _defaultValue,\n onValueChange,\n country = 'US',\n label,\n isDisabled,\n placeholder,\n invalid,\n error,\n errorInvalid,\n errorRequired,\n requirement,\n onBlur,\n className,\n ref: callerRef,\n contract,\n children,\n}: BoundPhoneFieldProps) {\n // Format only. Requiredness is not decided here: `useBoundField` resolves it from the fieldset's\n // baseline and the raise below, and installs the blank check, so the announcement and the\n // validation cannot disagree. The check composes alongside whatever the fieldset validates —\n // before this merge, any contract validator discarded the particle's own validation whole.\n const rule = useMemo<FieldRule>(\n () =>\n mergeFieldValidator(contract.rule, 'phoneFormat', (rawValue) => {\n const raw = typeof rawValue === 'string' ? rawValue : String(rawValue ?? '');\n // `false`, never undefined: react-hook-form reads an undefined result as valid.\n return !raw.trim() || validatePhoneNumber(raw, country) || (errorInvalid ?? false);\n }),\n [contract.rule, errorInvalid, country],\n );\n\n const field = useBoundField(contract, TEXT_FIELD_VALUE, rule, {\n required: requirement === 'mandatory',\n message: errorRequired,\n });\n const { getFieldState } = useFormContext();\n const { invalid: rhfInvalid, error: rhfError } = getFieldState(contract.name, useFormState({ name: contract.name }));\n\n const composedRef = useComposedRef<HTMLInputElement>(callerRef, field.ref);\n\n const rawValue = typeof field.value === 'string' ? field.value : String(field.value ?? '');\n const maskedValue = applyPhoneMask(rawValue, country);\n const resolvedLabel = label ?? contract.label ?? '';\n const resolvedPlaceholder = placeholder ?? contract.placeholder;\n const resolvedIsDisabled = isDisabled ?? contract.disabled ?? false;\n\n const effectiveInvalid = invalid !== undefined ? invalid : rhfInvalid;\n const effectiveError = error !== undefined ? error : effectiveInvalid ? (rhfError?.message ?? '') : '';\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n const raw = removePhoneMask(event.target.value, country);\n field.onChange(raw);\n onValueChange?.(raw);\n }\n\n function handleBlur(_event: FocusEvent<HTMLInputElement>) {\n field.onBlur();\n onBlur?.();\n }\n\n return (\n // Decision 3: replaces the empty-contract FieldContractBoundary with a re-provided contract\n // carrying the RESOLVED name/label/placeholder — the values a composed childless Field.Label /\n // Field.Error actually need, as opposed to the raw (possibly-undefined) ones the ambient\n // contract from the enclosing FieldBinding carries. useBoundField above remains the sole binder\n // for contract.name; this FieldBinding never registers anything itself.\n <FieldBinding\n name={contract.name}\n label={resolvedLabel}\n placeholder={resolvedPlaceholder}\n defaultValue={contract.defaultValue}\n rule={contract.rule}\n options={contract.options}\n disabled={resolvedIsDisabled}\n readOnly={contract.readOnly}\n autoComplete={contract.autoComplete}\n inputMode={contract.inputMode}\n >\n <PhoneFieldView\n ref={composedRef}\n country={country}\n className={className}\n label={resolvedLabel}\n isDisabled={resolvedIsDisabled}\n placeholder={resolvedPlaceholder}\n required={field.required}\n maskedValue={maskedValue}\n effectiveInvalid={effectiveInvalid}\n effectiveError={effectiveError}\n onChange={handleChange}\n onBlur={handleBlur}\n >\n {children}\n </PhoneFieldView>\n </FieldBinding>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoCA,SAAS,mBAAmB,OAAe,SAAgC;CACzE,QAAQ,SAAR;EACE,KAAK,MACH,OAAO,MAAM,WAAW,IAAI,KAAK,MAAM,WAAW,GAAG;EACvD,KAAK,MACH,OAAO,MAAM,WAAW,KAAK,KAAK,MAAM,WAAW,IAAI;EACzD,SACE,OAAO;CACX;AACF;;;;;;;;;;;AAYA,SAAgB,gBAAgB,OAAe,SAA+B;CAC5E,MAAM,aAAa,MAAM,QAAQ,OAAO,EAAE;CAK1C,IAAI,MAAM,WAAW,GAAG,KAAK,mBAAmB,OAAO,OAAO,GAC5D,OAAO,IAAI;CAGb,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,eAAe,OAAe,SAA+B;CAC3E,QAAQ,SAAR;EACE,KAAK,MACH,OAAO,iBAAiB,KAAK;EAC/B,KAAK,MACH,OAAO,iBAAiB,KAAK;EAC/B,SACE,OAAO,iBAAiB,KAAK;CACjC;AACF;AAEA,SAAS,iBAAiB,OAAuB;CAC/C,MAAM,aAAa,MAAM,QAAQ,OAAO,EAAE;CAG1C,IAAI,MAAM,WAAW,IAAI,KAAK,WAAW,UAAU,IAEjD,OAAO,MAAM,eADC,MAAM,QAAQ,MAAM,EAAE,CAAC,CAAC,QAAQ,OAAO,EACrB,CAAC;CAInC,IAAI,WAAW,WAAW,GAAG,KAAK,WAAW,WAAW,IACtD,OAAO,MAAM,eAAe,WAAW,UAAU,CAAC,CAAC;CAGrD,OAAO,eAAe,UAAU;AAClC;AAEA,SAAS,eAAe,QAAwB;CAE9C,MAAM,QAAQ,OAAO,MAAM,GAAG,EAAE;CAChC,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,IAAI,MAAM,UAAU,GAAG,OAAO,IAAI;CAClC,IAAI,MAAM,UAAU,GAAG,OAAO,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,MAAM,MAAM,CAAC;CACrE,OAAO,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,GAAG,MAAM,MAAM,CAAC;AACrE;AAEA,SAAS,iBAAiB,OAAuB;CAC/C,MAAM,aAAa,MAAM,QAAQ,OAAO,EAAE;CAI1C,IAAI,MAAM,WAAW,KAAK,KAAK,WAAW,UAAU,IAElD,OAAO,OAAO,eADA,MAAM,QAAQ,OAAO,EAAE,CAAC,CAAC,QAAQ,OAAO,EACrB,CAAC;CAIpC,IAAI,WAAW,WAAW,IAAI,MAAM,WAAW,WAAW,MAAM,WAAW,WAAW,KACpF,OAAO,OAAO,eAAe,WAAW,UAAU,CAAC,CAAC;CAGtD,OAAO,eAAe,UAAU;AAClC;AAEA,SAAS,eAAe,QAAwB;CAE9C,MAAM,QAAQ,OAAO,MAAM,GAAG,EAAE;CAChC,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,IAAI,MAAM,UAAU,GAAG,OAAO,IAAI;CAClC,IAAI,MAAM,UAAU,GAAG,OAAO,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,MAAM,MAAM,CAAC;CAErE,IAAI,MAAM,UAAU,IAAI,OAAO,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,GAAG,MAAM,MAAM,CAAC;CAE3F,OAAO,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,GAAG,MAAM,MAAM,CAAC;AACrE;;;;;;AAWA,SAAS,eAAe,QAAyB;CAC/C,IAAI,OAAO,WAAW,IAAI,OAAO;CACjC,OAAO,OAAO,WAAW,MAAM,OAAO,OAAO;AAC/C;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,oBAAoB,OAAe,SAAgC;CACjF,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,GAAG,OAAO;CAEpC,MAAM,SAAS,MAAM,QAAQ,OAAO,EAAE;CAEtC,IAAI,mBAAmB,OAAO,OAAO,GAAG;EAEtC,IAAI,YAAY,MAEV;OAAA,OAAO,WAAW,IAAI,OAAO;EAAA,OAIjC,IAAI,OAAO,WAAW,MAAM,OAAO,WAAW,IAAI,OAAO,eAAe,OAAO,MAAM,CAAC,CAAC;CAG3F;CAGA,IAAI,YAAY,MACd,OAAO,OAAO,WAAW;CAG3B,OAAO,eAAe,MAAM;AAC9B;;;;;;;;AASA,SAAgB,OAAO,KAAa,SAA+B;CACjE,MAAM,WAAW,gBAAgB,KAAK,OAAO;CAC7C,IAAI,SAAS,WAAW,GAAG,GAAG,OAAO;CACrC,MAAM,OAAO,YAAY,OAAO,OAAO;CACvC,MAAM,WAAW,YAAY,OAAO,KAAK;CAEzC,OAAO,SAAS,WAAW,IAAI,KAAK,SAAS,SAAS,WAAW,IAAI,aAAa,IAAI,OAAO;AAC/F;AAwEA,MAAa,uBAAuB,gBAAiC;CACnE,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAAe,UAAU;CAAS;CACnD,QAAQ;EACN,SAAS;GAAE,MAAM;GAAU,SAAS;GAAM,OAAO;EAAqB;EAEtE,OAAO;GAAE,MAAM;GAAU,OAAO;EAAQ;EAExC,aAAa;GAAE,MAAM,CAAC,aAAa,UAAU;GAAY,OAAO;EAAc;EAC9E,cAAc;GAAE,MAAM;GAAU,OAAO;EAAwB;EAC/D,eAAe;GAAE,MAAM;GAAU,OAAO;EAAyB;CACnE;CACA,WACE;AACJ,CAAC;;;;;;;;;;;;;;;;AAqBD,SAAgB,WAAW,EAAE,aAAa,GAAG,SAAqC;CAChF,MAAM,WAAW,SAAS;CAC1B,MAAM,cAAc,eAAe;CAEnC,IAAI,YAAY,aACd,OAAO,oBAAC,iBAAD;EAAiB,GAAI;EAAoB;EAAuB;CAAW,CAAA;CAGpF,OAAO,oBAAC,mBAAD;EAAmB,GAAI;EAAoB;CAAc,CAAA;AAClE;AAkBA,MAAM,yBAAyB,cAAkD,IAAI;AAErF,SAAS,4BAAyD;CAChE,MAAM,UAAU,WAAW,sBAAsB;CACjD,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,qDAAqD;CAEvE,OAAO;AACT;AAIA,MAAa,4BAA4B,gBAAsC;CAC7E,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAAqB,UAAU;CAAS;CACzD,QAAQ,CAAC;CACT,WACE;AACJ,CAAC;;AAGD,SAAgB,gBAAgB,EAAE,aAA8C;CAC9E,MAAM,EAAE,KAAK,OAAO,aAAa,UAAU,UAAU,WAAW,0BAA0B;CAE1F,OACE,oBAAC,OAAD;EACO;EACL,6BAA0B;EAC1B,MAAK;EACL,WAAU;EAIV,iBAAe,YAAY,KAAA;EACpB;EACG;EACF;EACK;EACF;CACZ,CAAA;AAEL;AAsBA,SAAS,eAAe,EACtB,KACA,SACA,WACA,OACA,YACA,aACA,UACA,aACA,kBACA,gBACA,UACA,QACA,YACsB;CACtB,MAAM,eAAe,eACZ;EAAE;EAAK,OAAO;EAAa;EAAa;EAAU;EAAU;CAAO,IAC1E;EAAC;EAAK;EAAa;EAAa;EAAU;EAAU;CAAM,CAC5D;CAEA,OAQE,oBAACA,MAAU,MAAX;EACE,4BAAyB;EACzB,oCAAkC;EAClC,sBAAmB;EACR;EACX,SAAS;EACT,UAAU;EAEV,UAAA,oBAAC,uBAAuB,UAAxB;GAAiC,OAAO;GACrC,UAAA,YACC,qBAAA,YAAA,EAAA,UAAA;IACE,oBAACA,MAAU,OAAX;KAAiB,6BAA0B;KAAG,uBAAoB;KAC/D,UAAA;IACc,CAAA;IACjB,oBAAC,iBAAD,CAAkB,CAAA;IACjB,iBACC,oBAACA,MAAU,OAAX;KAAiB,OAAA;KAAM,6BAA0B;KAAG,uBAAoB;KACrE,UAAA;IACc,CAAA,IACf;GACJ,EAAA,CAAA;EAE2B,CAAA;CACnB,CAAA;AAEpB;AAQA,SAAS,kBAAkB,EACzB,OACA,eAAe,IACf,eACA,UAAU,MACV,OACA,aAAa,OACb,aACA,SACA,OACA,cACA,eACA,aACA,QACA,WACA,KACA,YACmC;CACnC,MAAM,eAAe,UAAU,KAAA;CAE/B,MAAM,CAAC,aAAa,kBAAkB,SAAS,YAAY;CAC3D,MAAM,CAAC,cAAc,mBAAmB,SAAS,KAAK;CACtD,MAAM,CAAC,YAAY,iBAAiB,SAAS,EAAE;CAM/C,MAAM,CAAC,aAAa,kBAAkB,SAAS,OAAO;CACtD,IAAI,gBAAgB,SAAS;EAC3B,eAAe,OAAO;EACtB,gBAAgB,KAAK;EACrB,cAAc,EAAE;CAClB;CAEA,MAAM,WAAW,eAAgB,QAAmB;CACpD,MAAM,cAAc,eAAe,UAAU,OAAO;CACpD,MAAM,gBAAgB,SAAS;CAM/B,MAAM,mBAAmB,YAAY,KAAA,IAAY,UAAU;CAC3D,MAAM,iBAAiB,UAAU,KAAA,IAAY,QAAQ,mBAAmB,aAAa;CAErF,SAAS,aAAa,OAAsC;EAC1D,IAAI,YAAY;EAChB,MAAM,MAAM,gBAAgB,MAAM,OAAO,OAAO,OAAO;EACvD,IAAI,CAAC,cACH,eAAe,GAAG;EAEpB,gBAAgB,GAAG;CACrB;CAEA,SAAS,WAAW,QAAsC;EACxD,IAAI,YAAY;EAEhB,IAAI,iBAAiB;EACrB,IAAI,aAAa;EAEjB,IAAI,gBAAgB,eAAe,CAAC,SAAS,KAAK,GAAG;GACnD,iBAAiB;GACjB,aAAa,iBAAiB;EAChC,OAAO,IAAI,SAAS,KAAK,GAAG;GAC1B,MAAM,QAAQ,oBAAoB,UAAU,OAAO;GACnD,iBAAiB,CAAC;GAClB,aAAa,QAAQ,KAAM,gBAAgB;EAC7C;EAGA,gBAAgB,cAAc;EAC9B,cAAc,UAAU;EACxB,SAAS;CACX;CAEA,OACE,oBAAC,gBAAD;EACO;EACI;EACE;EACX,OAAO;EACK;EACC;EACb,UAAU,gBAAgB;EACb;EACK;EACF;EAChB,UAAU;EACV,QAAQ;EAEP;CACa,CAAA;AAEpB;AAQA,SAAS,gBAAgB,EACvB,OAAO,QACP,cAAc,eACd,eACA,UAAU,MACV,OACA,YACA,aACA,SACA,OACA,cACA,eACA,aACA,QACA,WACA,KAAK,WACL,UACA,YACuB;CAKvB,MAAM,OAAO,cAET,oBAAoB,SAAS,MAAM,gBAAgB,aAAa;EAC9D,MAAM,MAAM,OAAO,aAAa,WAAW,WAAW,OAAO,YAAY,EAAE;EAE3E,OAAO,CAAC,IAAI,KAAK,KAAK,oBAAoB,KAAK,OAAO,MAAM,gBAAgB;CAC9E,CAAC,GACH;EAAC,SAAS;EAAM;EAAc;CAAO,CACvC;CAEA,MAAM,QAAQ,cAAc,UAAU,kBAAkB,MAAM;EAC5D,UAAU,gBAAgB;EAC1B,SAAS;CACX,CAAC;CACD,MAAM,EAAE,kBAAkB,eAAe;CACzC,MAAM,EAAE,SAAS,YAAY,OAAO,aAAa,cAAc,SAAS,MAAM,aAAa,EAAE,MAAM,SAAS,KAAK,CAAC,CAAC;CAEnH,MAAM,cAAc,eAAiC,WAAW,MAAM,GAAG;CAGzE,MAAM,cAAc,eADH,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ,OAAO,MAAM,SAAS,EAAE,GAC5C,OAAO;CACpD,MAAM,gBAAgB,SAAS,SAAS,SAAS;CACjD,MAAM,sBAAsB,eAAe,SAAS;CACpD,MAAM,qBAAqB,cAAc,SAAS,YAAY;CAE9D,MAAM,mBAAmB,YAAY,KAAA,IAAY,UAAU;CAC3D,MAAM,iBAAiB,UAAU,KAAA,IAAY,QAAQ,mBAAoB,UAAU,WAAW,KAAM;CAEpG,SAAS,aAAa,OAAsC;EAC1D,MAAM,MAAM,gBAAgB,MAAM,OAAO,OAAO,OAAO;EACvD,MAAM,SAAS,GAAG;EAClB,gBAAgB,GAAG;CACrB;CAEA,SAAS,WAAW,QAAsC;EACxD,MAAM,OAAO;EACb,SAAS;CACX;CAEA,OAME,oBAAC,cAAD;EACE,MAAM,SAAS;EACf,OAAO;EACP,aAAa;EACb,cAAc,SAAS;EACvB,MAAM,SAAS;EACf,SAAS,SAAS;EAClB,UAAU;EACV,UAAU,SAAS;EACnB,cAAc,SAAS;EACvB,WAAW,SAAS;EAEpB,UAAA,oBAAC,gBAAD;GACE,KAAK;GACI;GACE;GACX,OAAO;GACP,YAAY;GACZ,aAAa;GACb,UAAU,MAAM;GACH;GACK;GACF;GAChB,UAAU;GACV,QAAQ;GAEP;EACa,CAAA;CACJ,CAAA;AAElB"}
|
|
@@ -1,13 +1,33 @@
|
|
|
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";
|
|
4
5
|
//#region src/particles/spinner/spinner.d.ts
|
|
6
|
+
export declare const SpinnerContent: {
|
|
7
|
+
readonly id: "spinner";
|
|
8
|
+
readonly title: "Spinner";
|
|
9
|
+
readonly description: "Accessible name of the loading indicator.";
|
|
10
|
+
readonly schema: {
|
|
11
|
+
readonly type: "object";
|
|
12
|
+
readonly additionalProperties: false;
|
|
13
|
+
readonly properties: {
|
|
14
|
+
readonly label: {
|
|
15
|
+
readonly type: "string";
|
|
16
|
+
readonly title: "Accessible label";
|
|
17
|
+
readonly format: "icu-message";
|
|
18
|
+
readonly messageSource: "Loading";
|
|
19
|
+
readonly messageOptional: true;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export type SpinnerContentValue = ContentValue<typeof SpinnerContent>;
|
|
5
25
|
/** Props for {@link Spinner}. Extends all native `<output>` attributes. */
|
|
6
|
-
export type SpinnerProps = Omit<ComponentPropsWithRef<'output'>, 'children'> & {
|
|
7
|
-
/** Accessible label
|
|
8
|
-
|
|
26
|
+
export type SpinnerProps = Omit<ComponentPropsWithRef<'output'>, 'children'> & MessageLocaleProp & {
|
|
27
|
+
/** Accessible label, from the `label` message field. */
|
|
28
|
+
$content?: SpinnerContentValue;
|
|
9
29
|
};
|
|
10
30
|
export declare const SpinnerDefinition: ComponentDefinition<SpinnerProps>;
|
|
11
|
-
export declare function Spinner({
|
|
31
|
+
export declare function Spinner({ $locale, $content, className, ...props }: SpinnerProps): import("react/jsx-runtime").JSX.Element;
|
|
12
32
|
//#endregion
|
|
13
33
|
//# sourceMappingURL=spinner.d.ts.map
|
|
@@ -1,31 +1,47 @@
|
|
|
1
1
|
import { defineComponent } from "../../core/dist/define-component.js";
|
|
2
|
+
import { defineContentType } from "../../core/dist/define-content-type.js";
|
|
2
3
|
import "../../core/dist/index.js";
|
|
4
|
+
import { createMessageFormatter } from "../../sdk/i18n/message-formatter.js";
|
|
3
5
|
import { jsx } from "react/jsx-runtime";
|
|
4
6
|
//#region src/particles/spinner/spinner.tsx
|
|
7
|
+
const SpinnerContent = defineContentType({
|
|
8
|
+
id: "spinner",
|
|
9
|
+
title: "Spinner",
|
|
10
|
+
description: "Accessible name of the loading indicator.",
|
|
11
|
+
schema: {
|
|
12
|
+
type: "object",
|
|
13
|
+
additionalProperties: false,
|
|
14
|
+
properties: { label: {
|
|
15
|
+
type: "string",
|
|
16
|
+
title: "Accessible label",
|
|
17
|
+
format: "icu-message",
|
|
18
|
+
messageSource: "Loading",
|
|
19
|
+
messageOptional: true
|
|
20
|
+
} }
|
|
21
|
+
}
|
|
22
|
+
});
|
|
5
23
|
const SpinnerDefinition = defineComponent({
|
|
6
24
|
name: "Spinner",
|
|
7
25
|
importPath: "@vtex/faststore/components",
|
|
8
26
|
component: Spinner,
|
|
27
|
+
content: SpinnerContent,
|
|
9
28
|
editor: {
|
|
10
29
|
label: "Spinner",
|
|
11
30
|
category: "feedback"
|
|
12
31
|
},
|
|
13
|
-
schema: {
|
|
14
|
-
|
|
15
|
-
default: "Loading",
|
|
16
|
-
label: "Label"
|
|
17
|
-
} },
|
|
18
|
-
guideline: "Loading indicator — use standalone or composed inside Button for loading states. Purely structural with no built-in animation CSS."
|
|
32
|
+
schema: {},
|
|
33
|
+
guideline: "Loading indicator — use standalone or composed inside Button for loading states. Its accessible name comes from the $content field label: a blank label renders no aria-label, and an explicit aria-label prop applies when the label is blank. Purely structural with no built-in animation CSS."
|
|
19
34
|
});
|
|
20
|
-
function Spinner({
|
|
35
|
+
function Spinner({ $locale, $content, className, ...props }) {
|
|
36
|
+
const label = createMessageFormatter($locale, SpinnerContent, $content).format("label");
|
|
21
37
|
return /* @__PURE__ */ jsx("output", {
|
|
22
38
|
...props,
|
|
23
|
-
"aria-label": label,
|
|
39
|
+
"aria-label": label || props["aria-label"],
|
|
24
40
|
className,
|
|
25
41
|
"data-fs-spinner": ""
|
|
26
42
|
});
|
|
27
43
|
}
|
|
28
44
|
//#endregion
|
|
29
|
-
export { Spinner, SpinnerDefinition };
|
|
45
|
+
export { Spinner, SpinnerContent, SpinnerDefinition };
|
|
30
46
|
|
|
31
47
|
//# sourceMappingURL=spinner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.js","names":[],"sources":["../../../src/particles/spinner/spinner.tsx"],"sourcesContent":["import { defineComponent } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\n\n/** Props for {@link Spinner}. Extends all native `<output>` attributes. */\nexport type SpinnerProps = Omit<ComponentPropsWithRef<'output'>, 'children'> & {\n
|
|
1
|
+
{"version":3,"file":"spinner.js","names":[],"sources":["../../../src/particles/spinner/spinner.tsx"],"sourcesContent":["import { type ContentValue, defineComponent, defineContentType, type MessageLocaleProp } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\nimport { createMessageFormatter } from '../../sdk/i18n/message-formatter.js';\n\nexport const SpinnerContent = defineContentType({\n id: 'spinner',\n title: 'Spinner',\n description: 'Accessible name of the loading indicator.',\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n label: {\n type: 'string',\n title: 'Accessible label',\n format: 'icu-message',\n messageSource: 'Loading',\n messageOptional: true,\n },\n },\n },\n});\n\nexport type SpinnerContentValue = ContentValue<typeof SpinnerContent>;\n\n/** Props for {@link Spinner}. Extends all native `<output>` attributes. */\nexport type SpinnerProps = Omit<ComponentPropsWithRef<'output'>, 'children'> &\n MessageLocaleProp & {\n /** Accessible label, from the `label` message field. */\n $content?: SpinnerContentValue;\n };\n\nexport const SpinnerDefinition = defineComponent<SpinnerProps>({\n name: 'Spinner',\n importPath: '@vtex/faststore/components',\n component: Spinner,\n content: SpinnerContent,\n editor: { label: 'Spinner', category: 'feedback' },\n schema: {},\n guideline:\n 'Loading indicator — use standalone or composed inside Button for loading states. Its accessible name comes from the $content field label: a blank label renders no aria-label, and an explicit aria-label prop applies when the label is blank. Purely structural with no built-in animation CSS.',\n});\n\nexport function Spinner({ $locale, $content, className, ...props }: SpinnerProps) {\n const label = createMessageFormatter($locale, SpinnerContent, $content).format('label');\n return <output {...props} aria-label={label || props['aria-label']} className={className} data-fs-spinner=\"\" />;\n}\n"],"mappings":";;;;;;AAIA,MAAa,iBAAiB,kBAAkB;CAC9C,IAAI;CACJ,OAAO;CACP,aAAa;CACb,QAAQ;EACN,MAAM;EACN,sBAAsB;EACtB,YAAY,EACV,OAAO;GACL,MAAM;GACN,OAAO;GACP,QAAQ;GACR,eAAe;GACf,iBAAiB;EACnB,EACF;CACF;AACF,CAAC;AAWD,MAAa,oBAAoB,gBAA8B;CAC7D,MAAM;CACN,YAAY;CACZ,WAAW;CACX,SAAS;CACT,QAAQ;EAAE,OAAO;EAAW,UAAU;CAAW;CACjD,QAAQ,CAAC;CACT,WACE;AACJ,CAAC;AAED,SAAgB,QAAQ,EAAE,SAAS,UAAU,WAAW,GAAG,SAAuB;CAChF,MAAM,QAAQ,uBAAuB,SAAS,gBAAgB,QAAQ,CAAC,CAAC,OAAO,OAAO;CACtF,OAAO,oBAAC,UAAD;EAAQ,GAAI;EAAO,cAAY,SAAS,MAAM;EAA0B;EAAW,mBAAgB;CAAI,CAAA;AAChH"}
|
|
@@ -11,13 +11,16 @@ export type SwitchRootProps = {
|
|
|
11
11
|
required?: boolean;
|
|
12
12
|
name?: string;
|
|
13
13
|
id?: string;
|
|
14
|
+
/** Accessible name when no visible label is bound to the switch. */
|
|
15
|
+
'aria-label'?: string;
|
|
16
|
+
'aria-labelledby'?: string;
|
|
14
17
|
className?: string;
|
|
15
18
|
children?: ReactNode;
|
|
16
19
|
};
|
|
17
20
|
export type SwitchThumbProps = ComponentPropsWithRef<'span'>;
|
|
18
21
|
export declare const SwitchRootDefinition: ComponentDefinition<SwitchRootProps>;
|
|
19
22
|
export declare const SwitchThumbDefinition: ComponentDefinition<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>;
|
|
20
|
-
export declare function SwitchRoot({ checked, defaultChecked, onCheckedChange, disabled, readOnly, required, name, id, className, children }: SwitchRootProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export declare function SwitchRoot({ checked, defaultChecked, onCheckedChange, disabled, readOnly, required, name, id, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, className, children }: Readonly<SwitchRootProps>): import("react/jsx-runtime").JSX.Element;
|
|
21
24
|
export declare function SwitchThumb({ className, children, ...props }: SwitchThumbProps): import("react/jsx-runtime").JSX.Element;
|
|
22
25
|
export declare const Switch: {
|
|
23
26
|
Root: typeof SwitchRoot;
|
|
@@ -26,7 +26,7 @@ const SwitchThumbDefinition = defineComponent({
|
|
|
26
26
|
schema: {},
|
|
27
27
|
guideline: "Sliding visual indicator inside Switch.Root. Moves position based on the checked state managed by Base UI."
|
|
28
28
|
});
|
|
29
|
-
function SwitchRoot({ checked, defaultChecked, onCheckedChange, disabled, readOnly, required, name, id, className, children }) {
|
|
29
|
+
function SwitchRoot({ checked, defaultChecked, onCheckedChange, disabled, readOnly, required, name, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, className, children }) {
|
|
30
30
|
return /* @__PURE__ */ jsx(Switch.Root, {
|
|
31
31
|
checked,
|
|
32
32
|
defaultChecked,
|
|
@@ -36,6 +36,8 @@ function SwitchRoot({ checked, defaultChecked, onCheckedChange, disabled, readOn
|
|
|
36
36
|
required,
|
|
37
37
|
name,
|
|
38
38
|
id,
|
|
39
|
+
"aria-label": ariaLabel,
|
|
40
|
+
"aria-labelledby": ariaLabelledBy,
|
|
39
41
|
className,
|
|
40
42
|
"data-fs-switch-root": "",
|
|
41
43
|
children
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"switch.js","names":["BaseSwitch","Switch"],"sources":["../../../src/particles/switch/switch.tsx"],"sourcesContent":["'use client';\nimport { Switch as BaseSwitch } from '@base-ui/react/switch';\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef, ReactNode } from 'react';\n\nexport type SwitchRootProps = {\n checked?: boolean;\n defaultChecked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n disabled?: boolean;\n readOnly?: boolean;\n required?: boolean;\n name?: string;\n id?: string;\n className?: string;\n children?: ReactNode;\n};\n\nexport type SwitchThumbProps = ComponentPropsWithRef<'span'>;\n\nexport const SwitchRootDefinition = defineComponent<SwitchRootProps>({\n name: 'SwitchRoot',\n importPath: '@vtex/faststore/components',\n component: SwitchRoot,\n editor: { label: 'Switch Root', category: 'action' },\n schema: {},\n guideline:\n 'On/off control for settings and preferences. Always wraps a Switch.Thumb. Unlike Checkbox, implies immediate effect without form submission. Style the checked state via data-checked.',\n});\n\nexport const SwitchThumbDefinition = defineComponent<SwitchThumbProps>({\n name: 'SwitchThumb',\n importPath: '@vtex/faststore/components',\n component: SwitchThumb,\n editor: { label: 'Switch Thumb', category: 'layout' },\n schema: {},\n guideline:\n 'Sliding visual indicator inside Switch.Root. Moves position based on the checked state managed by Base UI.',\n});\n\nexport function SwitchRoot({\n checked,\n defaultChecked,\n onCheckedChange,\n disabled,\n readOnly,\n required,\n name,\n id,\n className,\n children,\n}: SwitchRootProps) {\n return (\n <BaseSwitch.Root\n checked={checked}\n defaultChecked={defaultChecked}\n onCheckedChange={onCheckedChange}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n name={name}\n id={id}\n className={className}\n data-fs-switch-root=\"\"\n >\n {children}\n </BaseSwitch.Root>\n );\n}\n\nexport function SwitchThumb({ className, children, ...props }: SwitchThumbProps) {\n return (\n <BaseSwitch.Thumb {...props} className={className} data-fs-switch-thumb=\"\">\n {children}\n </BaseSwitch.Thumb>\n );\n}\n\nexport const Switch = {\n Root: SwitchRoot,\n Thumb: SwitchThumb,\n};\n"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"switch.js","names":["BaseSwitch","Switch"],"sources":["../../../src/particles/switch/switch.tsx"],"sourcesContent":["'use client';\nimport { Switch as BaseSwitch } from '@base-ui/react/switch';\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef, ReactNode } from 'react';\n\nexport type SwitchRootProps = {\n checked?: boolean;\n defaultChecked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n disabled?: boolean;\n readOnly?: boolean;\n required?: boolean;\n name?: string;\n id?: string;\n /** Accessible name when no visible label is bound to the switch. */\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n className?: string;\n children?: ReactNode;\n};\n\nexport type SwitchThumbProps = ComponentPropsWithRef<'span'>;\n\nexport const SwitchRootDefinition = defineComponent<SwitchRootProps>({\n name: 'SwitchRoot',\n importPath: '@vtex/faststore/components',\n component: SwitchRoot,\n editor: { label: 'Switch Root', category: 'action' },\n schema: {},\n guideline:\n 'On/off control for settings and preferences. Always wraps a Switch.Thumb. Unlike Checkbox, implies immediate effect without form submission. Style the checked state via data-checked.',\n});\n\nexport const SwitchThumbDefinition = defineComponent<SwitchThumbProps>({\n name: 'SwitchThumb',\n importPath: '@vtex/faststore/components',\n component: SwitchThumb,\n editor: { label: 'Switch Thumb', category: 'layout' },\n schema: {},\n guideline:\n 'Sliding visual indicator inside Switch.Root. Moves position based on the checked state managed by Base UI.',\n});\n\nexport function SwitchRoot({\n checked,\n defaultChecked,\n onCheckedChange,\n disabled,\n readOnly,\n required,\n name,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n className,\n children,\n}: Readonly<SwitchRootProps>) {\n return (\n <BaseSwitch.Root\n checked={checked}\n defaultChecked={defaultChecked}\n onCheckedChange={onCheckedChange}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n name={name}\n id={id}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n className={className}\n data-fs-switch-root=\"\"\n >\n {children}\n </BaseSwitch.Root>\n );\n}\n\nexport function SwitchThumb({ className, children, ...props }: SwitchThumbProps) {\n return (\n <BaseSwitch.Thumb {...props} className={className} data-fs-switch-thumb=\"\">\n {children}\n </BaseSwitch.Thumb>\n );\n}\n\nexport const Switch = {\n Root: SwitchRoot,\n Thumb: SwitchThumb,\n};\n"],"mappings":";;;;;;AAuBA,MAAa,uBAAuB,gBAAiC;CACnE,MAAM;CACN,YAAY;CACZ,WAAW;CACX,QAAQ;EAAE,OAAO;EAAe,UAAU;CAAS;CACnD,QAAQ,CAAC;CACT,WACE;AACJ,CAAC;AAED,MAAa,wBAAwB,gBAAkC;CACrE,MAAM;CACN,YAAY;CACZ,WAAW;CACX,QAAQ;EAAE,OAAO;EAAgB,UAAU;CAAS;CACpD,QAAQ,CAAC;CACT,WACE;AACJ,CAAC;AAED,SAAgB,WAAW,EACzB,SACA,gBACA,iBACA,UACA,UACA,UACA,MACA,IACA,cAAc,WACd,mBAAmB,gBACnB,WACA,YAC4B;CAC5B,OACE,oBAACA,OAAW,MAAZ;EACW;EACO;EACC;EACP;EACA;EACA;EACJ;EACF;EACJ,cAAY;EACZ,mBAAiB;EACN;EACX,uBAAoB;EAEnB;CACc,CAAA;AAErB;AAEA,SAAgB,YAAY,EAAE,WAAW,UAAU,GAAG,SAA2B;CAC/E,OACE,oBAACA,OAAW,OAAZ;EAAkB,GAAI;EAAkB;EAAW,wBAAqB;EACrE;CACe,CAAA;AAEtB;AAEA,MAAaC,WAAS;CACpB,MAAM;CACN,OAAO;AACT"}
|