@vtex/faststore 0.0.7 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +102 -0
- package/dist/actions.json +194 -1
- package/dist/catalog.json +3449 -1612
- package/dist/cli/index.d.ts +512 -63
- package/dist/cli/index.js +2098 -686
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/server-runtime.js +44 -24
- package/dist/cli/server-runtime.js.map +1 -1
- package/dist/client.d.ts +5 -1
- package/dist/client.js +5 -1
- package/dist/components.d.ts +42 -10
- package/dist/components.js +47 -15
- package/dist/content-types.json +823 -0
- package/dist/core/dist/define-component.d.ts +12 -2
- package/dist/docs/account-access-gate.md +4 -4
- package/dist/docs/account-address-book.md +519 -0
- package/dist/docs/account-entry-point.md +5 -5
- package/dist/docs/account-menu.md +7 -7
- package/dist/docs/account-saved-cards.md +301 -0
- package/dist/docs/alert-dialog.md +2 -2
- package/dist/docs/billing-address.md +17 -9
- package/dist/docs/binding-switcher.md +154 -0
- package/dist/docs/card-entry.md +38 -7
- package/dist/docs/card-summary.md +175 -0
- package/dist/docs/cardholder-document.md +16 -14
- package/dist/docs/cart-destination.md +238 -0
- package/dist/docs/cart-item.md +22 -4
- package/dist/docs/cart-totalizer.md +1 -1
- package/dist/docs/cart.md +126 -19
- package/dist/docs/client-profile-fieldset.md +7 -5
- package/dist/docs/copy-text.md +84 -0
- package/dist/docs/document-field.md +8 -8
- package/dist/docs/footer-link-group.md +2 -2
- package/dist/docs/footer-social.md +1 -1
- package/dist/docs/free-shipping-progress.md +13 -9
- package/dist/docs/header-root.md +1 -1
- package/dist/docs/incentives.md +4 -4
- package/dist/docs/logo.md +6 -6
- package/dist/docs/my-account-profile.md +4 -4
- package/dist/docs/navigation-link-list.md +2 -2
- package/dist/docs/navigation-link.md +3 -3
- package/dist/docs/order-cancel.md +52 -0
- package/dist/docs/order-delivery-address.md +63 -0
- package/dist/docs/order-delivery-group.md +83 -0
- package/dist/docs/order-details-back.md +41 -0
- package/dist/docs/order-details-header.md +48 -0
- package/dist/docs/order-list-row.md +46 -0
- package/dist/docs/order-list-search.md +101 -0
- package/dist/docs/order-list-views.md +97 -0
- package/dist/docs/order-list.md +94 -0
- package/dist/docs/order-payment.md +94 -0
- package/dist/docs/order-placed-date.md +49 -0
- package/dist/docs/order-placed-payment-summary.md +13 -15
- package/dist/docs/order-placed.md +225 -0
- package/dist/docs/order-progress.md +88 -0
- package/dist/docs/order-status-badge.md +91 -0
- package/dist/docs/order-summary.md +53 -0
- package/dist/docs/payment-method-badges.md +16 -5
- package/dist/docs/payment-methods.md +1 -1
- package/dist/docs/place-order.md +13 -9
- package/dist/docs/product-information.md +2 -2
- package/dist/docs/product-shelf.md +7 -0
- package/dist/docs/saved-cards.md +2 -2
- package/dist/docs/select.md +22 -10
- package/dist/docs/session.md +1 -1
- package/dist/docs/shipping-address.md +1 -1
- package/dist/docs/sign-in-redirect.md +7 -7
- package/dist/docs/toast.md +35 -13
- package/dist/index.d.ts +7 -2
- package/dist/index.js +2 -1
- package/dist/internal/client.d.ts +9 -1
- package/dist/internal/client.js +10 -2
- package/dist/internal/server.d.ts +8 -2
- package/dist/internal/server.js +8 -2
- package/dist/matter/account-access-gate/account-access-gate.d.ts +2 -1
- package/dist/matter/account-access-gate/account-access-gate.js +19 -16
- package/dist/matter/account-access-gate/account-access-gate.js.map +1 -1
- package/dist/matter/account-address-book/account-address-book-delete.d.ts +60 -0
- package/dist/matter/account-address-book/account-address-book-delete.js +184 -0
- package/dist/matter/account-address-book/account-address-book-delete.js.map +1 -0
- package/dist/matter/account-address-book/account-address-book-deliverability.d.ts +19 -0
- package/dist/matter/account-address-book/account-address-book-deliverability.js +50 -0
- package/dist/matter/account-address-book/account-address-book-deliverability.js.map +1 -0
- package/dist/matter/account-address-book/account-address-book-form-parts.d.ts +42 -0
- package/dist/matter/account-address-book/account-address-book-form-parts.js +146 -0
- package/dist/matter/account-address-book/account-address-book-form-parts.js.map +1 -0
- package/dist/matter/account-address-book/account-address-book-profile-notice.d.ts +25 -0
- package/dist/matter/account-address-book/account-address-book-profile-notice.js +72 -0
- package/dist/matter/account-address-book/account-address-book-profile-notice.js.map +1 -0
- package/dist/matter/account-address-book/account-address-book.d.ts +120 -0
- package/dist/matter/account-address-book/account-address-book.js +469 -0
- package/dist/matter/account-address-book/account-address-book.js.map +1 -0
- package/dist/matter/account-address-book/account-address-country-switch.js +59 -0
- package/dist/matter/account-address-book/account-address-country-switch.js.map +1 -0
- package/dist/matter/account-address-book/account-address-country.d.ts +36 -0
- package/dist/matter/account-address-book/account-address-country.js +151 -0
- package/dist/matter/account-address-book/account-address-country.js.map +1 -0
- package/dist/matter/account-address-book/account-address-first-line.js +11 -0
- package/dist/matter/account-address-book/account-address-first-line.js.map +1 -0
- package/dist/matter/account-address-book/account-address-form-context.d.ts +55 -0
- package/dist/matter/account-address-book/account-address-form-context.js +14 -0
- package/dist/matter/account-address-book/account-address-form-context.js.map +1 -0
- package/dist/matter/account-address-book/account-address-form.d.ts +85 -0
- package/dist/matter/account-address-book/account-address-form.js +946 -0
- package/dist/matter/account-address-book/account-address-form.js.map +1 -0
- package/dist/matter/account-address-book/account-address-postal-autofill.js +189 -0
- package/dist/matter/account-address-book/account-address-postal-autofill.js.map +1 -0
- package/dist/matter/account-address-book/account-address-record.d.ts +26 -0
- package/dist/matter/account-address-book/account-address-record.js +138 -0
- package/dist/matter/account-address-book/account-address-record.js.map +1 -0
- package/dist/matter/account-entry-point/account-entry-point.js +11 -11
- package/dist/matter/account-entry-point/account-entry-point.js.map +1 -1
- package/dist/matter/account-menu/account-menu.d.ts +7 -3
- package/dist/matter/account-menu/account-menu.js +69 -28
- package/dist/matter/account-menu/account-menu.js.map +1 -1
- package/dist/matter/account-saved-cards/account-saved-cards.d.ts +383 -0
- package/dist/matter/account-saved-cards/account-saved-cards.js +956 -0
- package/dist/matter/account-saved-cards/account-saved-cards.js.map +1 -0
- package/dist/matter/billing-address/billing-address.d.ts +30 -17
- package/dist/matter/billing-address/billing-address.js +128 -33
- package/dist/matter/billing-address/billing-address.js.map +1 -1
- package/dist/matter/breadcrumb/breadcrumb.js +2 -2
- package/dist/matter/breadcrumb/breadcrumb.js.map +1 -1
- package/dist/matter/card-entry/card-capture.js +4 -3
- package/dist/matter/card-entry/card-capture.js.map +1 -1
- package/dist/matter/card-entry/card-entry.d.ts +5 -3
- package/dist/matter/card-entry/card-entry.js +77 -27
- package/dist/matter/card-entry/card-entry.js.map +1 -1
- package/dist/matter/cardholder-document/cardholder-document.d.ts +10 -9
- package/dist/matter/cardholder-document/cardholder-document.js +36 -16
- package/dist/matter/cardholder-document/cardholder-document.js.map +1 -1
- package/dist/matter/cart/cart-namespace.d.ts +5 -1
- package/dist/matter/cart/cart-namespace.js +5 -1
- package/dist/matter/cart/cart-namespace.js.map +1 -1
- package/dist/matter/cart/cart.d.ts +41 -6
- package/dist/matter/cart/cart.js +267 -54
- package/dist/matter/cart/cart.js.map +1 -1
- package/dist/matter/cart-destination/cart-destination.d.ts +222 -0
- package/dist/matter/cart-destination/cart-destination.js +613 -0
- package/dist/matter/cart-destination/cart-destination.js.map +1 -0
- package/dist/matter/cart-item/cart-item.d.ts +4 -2
- package/dist/matter/cart-item/cart-item.js +76 -17
- package/dist/matter/cart-item/cart-item.js.map +1 -1
- package/dist/matter/cart-totalizer/cart-totalizer.js +3 -2
- package/dist/matter/cart-totalizer/cart-totalizer.js.map +1 -1
- package/dist/matter/client-preferences/client-preferences-fieldset.js +1 -1
- package/dist/matter/client-profile-form/client-profile-fieldset.js +8 -5
- package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -1
- package/dist/matter/free-shipping-progress/free-shipping-progress.d.ts +6 -3
- package/dist/matter/free-shipping-progress/free-shipping-progress.js +76 -33
- package/dist/matter/free-shipping-progress/free-shipping-progress.js.map +1 -1
- package/dist/matter/identity-edit/identity-edit.js +3 -3
- package/dist/matter/identity-edit/identity-edit.js.map +1 -1
- package/dist/matter/identity-summary/identity-summary.js +2 -2
- package/dist/matter/identity-summary/identity-summary.js.map +1 -1
- package/dist/matter/my-account-profile/my-account-profile.d.ts +3 -3
- package/dist/matter/my-account-profile/my-account-profile.js +4 -4
- package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
- package/dist/matter/order-cancel/order-cancel.d.ts +110 -0
- package/dist/matter/order-cancel/order-cancel.js +344 -0
- package/dist/matter/order-cancel/order-cancel.js.map +1 -0
- package/dist/matter/order-delivery-address/order-delivery-address.d.ts +73 -0
- package/dist/matter/order-delivery-address/order-delivery-address.js +172 -0
- package/dist/matter/order-delivery-address/order-delivery-address.js.map +1 -0
- package/dist/matter/order-delivery-group/order-delivery-group.d.ts +128 -0
- package/dist/matter/order-delivery-group/order-delivery-group.js +408 -0
- package/dist/matter/order-delivery-group/order-delivery-group.js.map +1 -0
- package/dist/matter/order-details-header/order-details-header.d.ts +104 -0
- package/dist/matter/order-details-header/order-details-header.js +190 -0
- package/dist/matter/order-details-header/order-details-header.js.map +1 -0
- package/dist/matter/order-list/customer-orders-filter.d.ts +12 -0
- package/dist/matter/order-list/customer-orders-filter.js +30 -0
- package/dist/matter/order-list/customer-orders-filter.js.map +1 -0
- package/dist/matter/order-list/order-list.d.ts +121 -0
- package/dist/matter/order-list/order-list.js +395 -0
- package/dist/matter/order-list/order-list.js.map +1 -0
- package/dist/matter/order-list-row/order-list-row.d.ts +44 -0
- package/dist/matter/order-list-row/order-list-row.js +127 -0
- package/dist/matter/order-list-row/order-list-row.js.map +1 -0
- package/dist/matter/order-list-search/order-list-search.d.ts +72 -0
- package/dist/matter/order-list-search/order-list-search.js +296 -0
- package/dist/matter/order-list-search/order-list-search.js.map +1 -0
- package/dist/matter/order-list-views/order-list-views.d.ts +65 -0
- package/dist/matter/order-list-views/order-list-views.js +154 -0
- package/dist/matter/order-list-views/order-list-views.js.map +1 -0
- package/dist/matter/order-payment/order-payment.d.ts +83 -0
- package/dist/matter/order-payment/order-payment.js +258 -0
- package/dist/matter/order-payment/order-payment.js.map +1 -0
- package/dist/matter/order-placed/order-placed-deliveries.d.ts +145 -0
- package/dist/matter/order-placed/order-placed-deliveries.js +380 -0
- package/dist/matter/order-placed/order-placed-deliveries.js.map +1 -0
- package/dist/matter/order-placed/order-placed.d.ts +122 -0
- package/dist/matter/order-placed/order-placed.js +452 -0
- package/dist/matter/order-placed/order-placed.js.map +1 -0
- package/dist/matter/order-placed-date/order-placed-date.d.ts +45 -0
- package/dist/matter/order-placed-date/order-placed-date.js +92 -0
- package/dist/matter/order-placed-date/order-placed-date.js.map +1 -0
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +5 -8
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +29 -81
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -1
- package/dist/matter/order-progress/order-progress.d.ts +85 -0
- package/dist/matter/order-progress/order-progress.js +203 -0
- package/dist/matter/order-progress/order-progress.js.map +1 -0
- package/dist/matter/order-summary/order-summary.d.ts +81 -0
- package/dist/matter/order-summary/order-summary.js +192 -0
- package/dist/matter/order-summary/order-summary.js.map +1 -0
- package/dist/matter/payment/cardholder-document-rule.d.ts +35 -0
- package/dist/matter/payment/cardholder-document-rule.js +35 -0
- package/dist/matter/payment/cardholder-document-rule.js.map +1 -0
- package/dist/matter/payment/payment-card-capture.js +38 -23
- package/dist/matter/payment/payment-card-capture.js.map +1 -1
- package/dist/matter/payment/payment-controller.js +11 -0
- package/dist/matter/payment/payment-controller.js.map +1 -1
- package/dist/matter/payment/payment-method-badges.js +4 -2
- package/dist/matter/payment/payment-method-badges.js.map +1 -1
- package/dist/matter/payment/payment.js +11 -0
- package/dist/matter/payment/payment.js.map +1 -1
- package/dist/matter/payment/use-payment-method-selection.d.ts +39 -0
- package/dist/matter/payment/use-payment-method-selection.js +30 -2
- package/dist/matter/payment/use-payment-method-selection.js.map +1 -1
- package/dist/matter/payment/use-payment-submit-gate.d.ts +16 -2
- package/dist/matter/payment/use-payment-submit-gate.js +42 -14
- package/dist/matter/payment/use-payment-submit-gate.js.map +1 -1
- package/dist/matter/place-order/place-order.d.ts +12 -7
- package/dist/matter/place-order/place-order.js +126 -103
- package/dist/matter/place-order/place-order.js.map +1 -1
- package/dist/matter/pricing/pricing.js +5 -5
- package/dist/matter/pricing/pricing.js.map +1 -1
- package/dist/matter/product-shelf/product-shelf.d.ts +7 -0
- package/dist/matter/product-shelf/product-shelf.js +115 -1
- package/dist/matter/product-shelf/product-shelf.js.map +1 -1
- package/dist/matter/region/region.js +1 -1
- package/dist/matter/saved-cards/saved-cards.js +26 -15
- package/dist/matter/saved-cards/saved-cards.js.map +1 -1
- package/dist/matter/session/session.js +2 -2
- package/dist/matter/session/session.js.map +1 -1
- package/dist/matter/shipping-address/country-descriptors.d.ts +1 -0
- package/dist/matter/shipping-address/country-descriptors.js +23 -1
- package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
- package/dist/matter/shipping-address/shipping-address.js +62 -14
- package/dist/matter/shipping-address/shipping-address.js.map +1 -1
- package/dist/matter/shipping-simulator/shipping-simulator.d.ts +2 -2
- package/dist/matter/shipping-simulator/shipping-simulator.js +6 -2
- package/dist/matter/shipping-simulator/shipping-simulator.js.map +1 -1
- package/dist/matter/sign-in-redirect/sign-in-redirect.js +48 -10
- package/dist/matter/sign-in-redirect/sign-in-redirect.js.map +1 -1
- package/dist/matter/variant-selector/variant-selector.js +2 -2
- package/dist/matter/variant-selector/variant-selector.js.map +1 -1
- package/dist/particles/address-summary/address-summary.js +2 -2
- package/dist/particles/address-summary/address-summary.js.map +1 -1
- package/dist/particles/alert-dialog/alert-dialog.d.ts +5 -1
- package/dist/particles/alert-dialog/alert-dialog.js +5 -2
- package/dist/particles/alert-dialog/alert-dialog.js.map +1 -1
- package/dist/particles/binding-switcher/binding-switcher.d.ts +38 -0
- package/dist/particles/binding-switcher/binding-switcher.js +183 -0
- package/dist/particles/binding-switcher/binding-switcher.js.map +1 -0
- package/dist/particles/card-summary/card-network.d.ts +17 -0
- package/dist/particles/card-summary/card-network.js +25 -0
- package/dist/particles/card-summary/card-network.js.map +1 -0
- package/dist/particles/card-summary/card-summary.d.ts +83 -0
- package/dist/particles/card-summary/card-summary.js +188 -0
- package/dist/particles/card-summary/card-summary.js.map +1 -0
- package/dist/particles/copy-text/copy-text.d.ts +28 -0
- package/dist/particles/copy-text/copy-text.js +140 -0
- package/dist/particles/copy-text/copy-text.js.map +1 -0
- package/dist/particles/document-field/document-field.d.ts +34 -5
- package/dist/particles/document-field/document-field.js +115 -19
- package/dist/particles/document-field/document-field.js.map +1 -1
- package/dist/particles/field/field.js +1 -1
- package/dist/particles/field/field.js.map +1 -1
- package/dist/particles/footer-link-group/footer-link-group.d.ts +6 -2
- package/dist/particles/footer-link-group/footer-link-group.js +18 -7
- package/dist/particles/footer-link-group/footer-link-group.js.map +1 -1
- package/dist/particles/footer-social/footer-social.d.ts +1 -1
- package/dist/particles/footer-social/footer-social.js +1 -1
- package/dist/particles/footer-social/footer-social.js.map +1 -1
- package/dist/particles/incentives/incentives.d.ts +7 -3
- package/dist/particles/incentives/incentives.js +8 -3
- package/dist/particles/incentives/incentives.js.map +1 -1
- package/dist/particles/logo/logo.d.ts +3 -2
- package/dist/particles/logo/logo.js +20 -8
- package/dist/particles/logo/logo.js.map +1 -1
- package/dist/particles/navigation-link/navigation-link.d.ts +2 -3
- package/dist/particles/navigation-link/navigation-link.js +4 -4
- package/dist/particles/navigation-link/navigation-link.js.map +1 -1
- package/dist/particles/navigation-link-list/navigation-link-list.d.ts +6 -2
- package/dist/particles/navigation-link-list/navigation-link-list.js +18 -7
- package/dist/particles/navigation-link-list/navigation-link-list.js.map +1 -1
- package/dist/particles/order-details-back/order-details-back.d.ts +28 -0
- package/dist/particles/order-details-back/order-details-back.js +52 -0
- package/dist/particles/order-details-back/order-details-back.js.map +1 -0
- package/dist/particles/order-status-badge/order-status-badge.d.ts +19 -0
- package/dist/particles/order-status-badge/order-status-badge.js +50 -0
- package/dist/particles/order-status-badge/order-status-badge.js.map +1 -0
- package/dist/particles/payment-methods/payment-methods.d.ts +1 -1
- package/dist/particles/payment-methods/payment-methods.js +1 -1
- package/dist/particles/payment-methods/payment-methods.js.map +1 -1
- package/dist/particles/phone-field/phone-field.js +2 -2
- package/dist/particles/phone-field/phone-field.js.map +1 -1
- package/dist/particles/select/select.js +6 -6
- package/dist/particles/select/select.js.map +1 -1
- package/dist/particles/toast/toast.d.ts +21 -7
- package/dist/particles/toast/toast.js +76 -8
- package/dist/particles/toast/toast.js.map +1 -1
- package/dist/schema.graphql +1376 -126
- package/dist/sdk/actions/address-action-provider.d.ts +16 -0
- package/dist/sdk/actions/address-action-provider.js +20 -0
- package/dist/sdk/actions/address-action-provider.js.map +1 -0
- package/dist/sdk/actions/analytics-action-provider.js +1 -1
- package/dist/sdk/actions/index.d.ts +5 -1
- package/dist/sdk/actions/index.js +5 -1
- package/dist/sdk/actions/locale-action-provider.d.ts +16 -0
- package/dist/sdk/actions/locale-action-provider.js +20 -0
- package/dist/sdk/actions/locale-action-provider.js.map +1 -0
- package/dist/sdk/actions/order-action-provider.d.ts +12 -0
- package/dist/sdk/actions/order-action-provider.js +16 -0
- package/dist/sdk/actions/order-action-provider.js.map +1 -0
- package/dist/sdk/actions/saved-card-action-provider.d.ts +12 -0
- package/dist/sdk/actions/saved-card-action-provider.js +16 -0
- package/dist/sdk/actions/saved-card-action-provider.js.map +1 -0
- package/dist/sdk/actions/types.d.ts +10 -2
- package/dist/sdk/address/address-fields.js +38 -0
- package/dist/sdk/address/address-fields.js.map +1 -0
- package/dist/sdk/address/checkout-readiness.js +17 -0
- package/dist/sdk/address/checkout-readiness.js.map +1 -0
- package/dist/sdk/address/constants.js +60 -0
- package/dist/sdk/address/constants.js.map +1 -0
- package/dist/sdk/address/country-display.js +19 -0
- package/dist/sdk/address/country-display.js.map +1 -0
- package/dist/sdk/address/country-rules.js +30 -0
- package/dist/sdk/address/country-rules.js.map +1 -0
- package/dist/sdk/address/format-address.js +18 -0
- package/dist/sdk/address/format-address.js.map +1 -0
- package/dist/sdk/address/iso-countries.js +262 -0
- package/dist/sdk/address/iso-countries.js.map +1 -0
- package/dist/sdk/address/layouts.js +56 -0
- package/dist/sdk/address/layouts.js.map +1 -0
- package/dist/sdk/address/messages.js +97 -0
- package/dist/sdk/address/messages.js.map +1 -0
- package/dist/sdk/address/operations.d.ts +54 -0
- package/dist/sdk/address/operations.js +83 -0
- package/dist/sdk/address/operations.js.map +1 -0
- package/dist/sdk/address/postal-code-lookup-operations.js +23 -0
- package/dist/sdk/address/postal-code-lookup-operations.js.map +1 -0
- package/dist/sdk/address/postal-code.js +11 -0
- package/dist/sdk/address/postal-code.js.map +1 -0
- package/dist/sdk/address/schema.js +14 -0
- package/dist/sdk/address/schema.js.map +1 -0
- package/dist/sdk/address/server-fields.js +25 -0
- package/dist/sdk/address/server-fields.js.map +1 -0
- package/dist/sdk/address/switch-country.js +57 -0
- package/dist/sdk/address/switch-country.js.map +1 -0
- package/dist/sdk/address/types.d.ts +26 -0
- package/dist/sdk/address/use-address-actions.d.ts +29 -0
- package/dist/sdk/address/use-address-actions.js +247 -0
- package/dist/sdk/address/use-address-actions.js.map +1 -0
- package/dist/sdk/address/use-address-by-postal-code.js +57 -0
- package/dist/sdk/address/use-address-by-postal-code.js.map +1 -0
- package/dist/sdk/address/validate-address.js +62 -0
- package/dist/sdk/address/validate-address.js.map +1 -0
- package/dist/sdk/cache/storefront-cache.js +30 -4
- package/dist/sdk/cache/storefront-cache.js.map +1 -1
- package/dist/sdk/cart/operations.d.ts +2 -1
- package/dist/sdk/cart/operations.js +55 -1
- package/dist/sdk/cart/operations.js.map +1 -1
- package/dist/sdk/cart/optimistic.d.ts +30 -7
- package/dist/sdk/cart/optimistic.js +78 -41
- package/dist/sdk/cart/optimistic.js.map +1 -1
- package/dist/sdk/cart/use-cart-actions.d.ts +7 -0
- package/dist/sdk/cart/use-cart-actions.js +61 -15
- package/dist/sdk/cart/use-cart-actions.js.map +1 -1
- package/dist/sdk/cart/use-cart-sync-sales-channel.js +70 -0
- package/dist/sdk/cart/use-cart-sync-sales-channel.js.map +1 -0
- package/dist/sdk/client/fetch-page-data.d.ts +11 -0
- package/dist/sdk/client/fetch-page-data.js +12 -1
- package/dist/sdk/client/fetch-page-data.js.map +1 -1
- package/dist/sdk/content/create-content-runtime.js +1 -8
- package/dist/sdk/content/create-content-runtime.js.map +1 -1
- package/dist/sdk/data/failed-fields.js +23 -0
- package/dist/sdk/data/failed-fields.js.map +1 -0
- package/dist/sdk/data/index.js +2 -2
- package/dist/sdk/data/page-reactive-data-root.d.ts +45 -7
- package/dist/sdk/data/page-reactive-data-root.js +88 -12
- package/dist/sdk/data/page-reactive-data-root.js.map +1 -1
- package/dist/sdk/data/reactive-list-item-data-provider.js +2 -2
- package/dist/sdk/generated/fragment-types.js +2 -0
- package/dist/sdk/generated/fragment-types.js.map +1 -1
- package/dist/sdk/generated/gql.js +17 -11
- package/dist/sdk/generated/gql.js.map +1 -1
- package/dist/sdk/generated/graphql.d.ts +185 -46
- package/dist/sdk/generated/graphql.js +2587 -155
- package/dist/sdk/generated/graphql.js.map +1 -1
- package/dist/sdk/i18n/messages/en-US.js +157 -1
- package/dist/sdk/i18n/messages/en-US.json +157 -1
- package/dist/sdk/i18n/messages/en-US.json.d.ts +156 -0
- package/dist/sdk/i18n/messages/es-ES.js +157 -1
- package/dist/sdk/i18n/messages/es-ES.json +157 -1
- package/dist/sdk/i18n/messages/pt-BR.js +157 -1
- package/dist/sdk/i18n/messages/pt-BR.json +157 -1
- package/dist/sdk/i18n/provider.js +1 -1
- package/dist/sdk/i18n/provider.js.map +1 -1
- package/dist/sdk/locale/binding-switch-provider.d.ts +13 -0
- package/dist/sdk/locale/binding-switch-provider.js +20 -0
- package/dist/sdk/locale/binding-switch-provider.js.map +1 -0
- package/dist/sdk/locale/use-locale-actions.d.ts +16 -0
- package/dist/sdk/locale/use-locale-actions.js +70 -0
- package/dist/sdk/locale/use-locale-actions.js.map +1 -0
- package/dist/sdk/navigation/binding-switch.d.ts +39 -0
- package/dist/sdk/navigation/binding-switch.js +129 -0
- package/dist/sdk/navigation/binding-switch.js.map +1 -0
- package/dist/sdk/navigation/current-page.js +30 -0
- package/dist/sdk/navigation/current-page.js.map +1 -0
- package/dist/sdk/navigation/decode-route-params.d.ts +11 -0
- package/dist/sdk/navigation/decode-route-params.js +32 -0
- package/dist/sdk/navigation/decode-route-params.js.map +1 -0
- package/dist/sdk/navigation/not-found-log.d.ts +28 -0
- package/dist/sdk/navigation/not-found-log.js +133 -0
- package/dist/sdk/navigation/not-found-log.js.map +1 -0
- package/dist/sdk/navigation/path.js +25 -0
- package/dist/sdk/navigation/path.js.map +1 -0
- package/dist/sdk/navigation/redirect.d.ts +11 -0
- package/dist/sdk/navigation/redirect.js +22 -0
- package/dist/sdk/navigation/redirect.js.map +1 -0
- package/dist/sdk/navigation/report.js +70 -0
- package/dist/sdk/navigation/report.js.map +1 -0
- package/dist/sdk/navigation/resolve-storefront-href.d.ts +12 -0
- package/dist/sdk/navigation/resolve-storefront-href.js +214 -0
- package/dist/sdk/navigation/resolve-storefront-href.js.map +1 -0
- package/dist/sdk/navigation/route-identity-provider.d.ts +11 -0
- package/dist/sdk/navigation/route-identity-provider.js +20 -0
- package/dist/sdk/navigation/route-identity-provider.js.map +1 -0
- package/dist/sdk/navigation/route-map-provider.d.ts +19 -0
- package/dist/sdk/navigation/route-map-provider.js +29 -0
- package/dist/sdk/navigation/route-map-provider.js.map +1 -0
- package/dist/sdk/navigation/storefront-link.d.ts +16 -0
- package/dist/sdk/navigation/storefront-link.js +66 -0
- package/dist/sdk/navigation/storefront-link.js.map +1 -0
- package/dist/sdk/navigation/types.d.ts +45 -0
- package/dist/sdk/navigation/use-storefront-navigation.d.ts +26 -0
- package/dist/sdk/navigation/use-storefront-navigation.js +73 -0
- package/dist/sdk/navigation/use-storefront-navigation.js.map +1 -0
- package/dist/sdk/navigation/use-storefront-route.d.ts +26 -0
- package/dist/sdk/navigation/use-storefront-route.js +87 -0
- package/dist/sdk/navigation/use-storefront-route.js.map +1 -0
- package/dist/sdk/navigation/use-storefront-search-params.d.ts +11 -0
- package/dist/sdk/navigation/use-storefront-search-params.js +16 -0
- package/dist/sdk/navigation/use-storefront-search-params.js.map +1 -0
- package/dist/sdk/orders/completion-badge.d.ts +8 -0
- package/dist/sdk/orders/completion-badge.js +47 -0
- package/dist/sdk/orders/completion-badge.js.map +1 -0
- package/dist/sdk/orders/order-operations.d.ts +19 -0
- package/dist/sdk/orders/order-operations.js +21 -0
- package/dist/sdk/orders/order-operations.js.map +1 -0
- package/dist/sdk/orders/use-order-actions.d.ts +23 -0
- package/dist/sdk/orders/use-order-actions.js +62 -0
- package/dist/sdk/orders/use-order-actions.js.map +1 -0
- package/dist/sdk/payment/gateway-origin.js +26 -13
- package/dist/sdk/payment/gateway-origin.js.map +1 -1
- package/dist/sdk/payment/gateway.d.ts +14 -2
- package/dist/sdk/payment/gateway.js +32 -14
- package/dist/sdk/payment/gateway.js.map +1 -1
- package/dist/sdk/payment/operations.js +11 -0
- package/dist/sdk/payment/operations.js.map +1 -1
- package/dist/sdk/payment/submission-registry.d.ts +2 -1
- package/dist/sdk/payment/submission-registry.js +12 -8
- package/dist/sdk/payment/submission-registry.js.map +1 -1
- package/dist/sdk/payment/use-payment-actions.d.ts +5 -3
- package/dist/sdk/payment/use-payment-actions.js +5 -2
- package/dist/sdk/payment/use-payment-actions.js.map +1 -1
- package/dist/sdk/payment/use-place-order.d.ts +6 -3
- package/dist/sdk/payment/use-place-order.js +333 -143
- package/dist/sdk/payment/use-place-order.js.map +1 -1
- package/dist/sdk/saved-cards/operations.d.ts +16 -0
- package/dist/sdk/saved-cards/operations.js +41 -0
- package/dist/sdk/saved-cards/operations.js.map +1 -0
- package/dist/sdk/saved-cards/use-saved-card-actions.d.ts +26 -0
- package/dist/sdk/saved-cards/use-saved-card-actions.js +86 -0
- package/dist/sdk/saved-cards/use-saved-card-actions.js.map +1 -0
- package/dist/sdk/seo/page-alternates.d.ts +57 -0
- package/dist/sdk/seo/page-alternates.js +127 -0
- package/dist/sdk/seo/page-alternates.js.map +1 -0
- package/dist/sdk/shipping/shipping-operations.d.ts +1 -1
- package/dist/sdk/shipping/shipping-operations.js +13 -0
- package/dist/sdk/shipping/shipping-operations.js.map +1 -1
- package/dist/sdk/state/cart.d.ts +9 -2
- package/dist/sdk/state/cart.js +9 -2
- package/dist/sdk/state/cart.js.map +1 -1
- package/dist/utils/own-value.js +19 -0
- package/dist/utils/own-value.js.map +1 -0
- package/dist/utils/safe-href.d.ts +4 -4
- package/dist/utils/safe-href.js +31 -22
- package/dist/utils/safe-href.js.map +1 -1
- package/package.json +5 -1
- package/skills/storefront-asset/SKILL.md +111 -0
- package/skills/storefront-asset/references/api-side.md +153 -0
- package/skills/storefront-asset/references/findings.md +40 -0
- package/skills/storefront-asset/references/ui-side.md +94 -0
- package/src/styles/tailwind.css +28 -2
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { defineComponent } from "../../core/dist/define-component.js";
|
|
3
|
+
import "../../core/dist/index.js";
|
|
4
|
+
import { useIntl } from "../../sdk/i18n/client.js";
|
|
5
|
+
import { Button } from "../button/button.js";
|
|
6
|
+
import { useEffect, useRef, useState } from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
//#region src/particles/copy-text/copy-text.tsx
|
|
9
|
+
const CLEAR_AFTER_MS = 5e3;
|
|
10
|
+
function isBlank(text) {
|
|
11
|
+
return text.trim().length === 0;
|
|
12
|
+
}
|
|
13
|
+
const CopyTextDefinition = defineComponent({
|
|
14
|
+
name: "CopyText",
|
|
15
|
+
importPath: "@vtex/faststore/components",
|
|
16
|
+
component: CopyText,
|
|
17
|
+
editor: {
|
|
18
|
+
label: "Copy Text",
|
|
19
|
+
category: "action"
|
|
20
|
+
},
|
|
21
|
+
schema: {
|
|
22
|
+
accessibleName: {
|
|
23
|
+
type: "string",
|
|
24
|
+
default: "Copy",
|
|
25
|
+
label: "Accessible name"
|
|
26
|
+
},
|
|
27
|
+
successMessage: {
|
|
28
|
+
type: "string",
|
|
29
|
+
default: "Copied",
|
|
30
|
+
label: "Success message"
|
|
31
|
+
},
|
|
32
|
+
failureMessage: {
|
|
33
|
+
type: "string",
|
|
34
|
+
default: "Could not copy",
|
|
35
|
+
label: "Failure message"
|
|
36
|
+
},
|
|
37
|
+
dismissLabel: {
|
|
38
|
+
type: "string",
|
|
39
|
+
default: "Dismiss",
|
|
40
|
+
label: "Dismiss label"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
guideline: "Copies the text it is given and confirms the result inline. Pass the identifier as text and the visible icon or label as children. Do not pass surrounding heading text."
|
|
44
|
+
});
|
|
45
|
+
function CopyText({ text, accessibleName, successMessage, failureMessage, dismissLabel, children, className, ref }) {
|
|
46
|
+
const intl = useIntl();
|
|
47
|
+
const name = accessibleName ?? intl.formatMessage({ id: "fs/order.copy.action" });
|
|
48
|
+
const success = successMessage ?? intl.formatMessage({ id: "fs/order.copy.copied" });
|
|
49
|
+
const failure = failureMessage ?? intl.formatMessage({ id: "fs/order.copy.failure" });
|
|
50
|
+
const dismissText = dismissLabel ?? intl.formatMessage({ id: "fs/order.copy.dismiss" });
|
|
51
|
+
const [outcome, setOutcome] = useState("idle");
|
|
52
|
+
const actionRef = useRef(null);
|
|
53
|
+
const timerRef = useRef(null);
|
|
54
|
+
const generation = useRef(0);
|
|
55
|
+
const active = useRef(true);
|
|
56
|
+
function clearTimer() {
|
|
57
|
+
if (timerRef.current === null) return;
|
|
58
|
+
clearTimeout(timerRef.current);
|
|
59
|
+
timerRef.current = null;
|
|
60
|
+
}
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
active.current = true;
|
|
63
|
+
return () => {
|
|
64
|
+
active.current = false;
|
|
65
|
+
if (timerRef.current === null) return;
|
|
66
|
+
clearTimeout(timerRef.current);
|
|
67
|
+
timerRef.current = null;
|
|
68
|
+
};
|
|
69
|
+
}, []);
|
|
70
|
+
function scheduleClear(token) {
|
|
71
|
+
clearTimer();
|
|
72
|
+
if (!active.current) return;
|
|
73
|
+
timerRef.current = setTimeout(() => {
|
|
74
|
+
if (!active.current || generation.current !== token) return;
|
|
75
|
+
setOutcome("idle");
|
|
76
|
+
}, CLEAR_AFTER_MS);
|
|
77
|
+
}
|
|
78
|
+
async function copy() {
|
|
79
|
+
if (isBlank(text) || outcome === "pending") return;
|
|
80
|
+
const token = generation.current + 1;
|
|
81
|
+
generation.current = token;
|
|
82
|
+
clearTimer();
|
|
83
|
+
setOutcome("pending");
|
|
84
|
+
const write = navigator.clipboard?.writeText;
|
|
85
|
+
if (typeof write !== "function") {
|
|
86
|
+
if (!active.current || generation.current !== token) return;
|
|
87
|
+
setOutcome("failure");
|
|
88
|
+
scheduleClear(token);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
await write.call(navigator.clipboard, text);
|
|
93
|
+
if (!active.current || generation.current !== token) return;
|
|
94
|
+
setOutcome("success");
|
|
95
|
+
} catch {
|
|
96
|
+
if (!active.current || generation.current !== token) return;
|
|
97
|
+
setOutcome("failure");
|
|
98
|
+
}
|
|
99
|
+
scheduleClear(token);
|
|
100
|
+
}
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
if (outcome === "success" || outcome === "failure") actionRef.current?.focus();
|
|
103
|
+
}, [outcome]);
|
|
104
|
+
function dismiss() {
|
|
105
|
+
generation.current += 1;
|
|
106
|
+
clearTimer();
|
|
107
|
+
setOutcome("idle");
|
|
108
|
+
actionRef.current?.focus();
|
|
109
|
+
}
|
|
110
|
+
const message = outcome === "success" ? success : failure;
|
|
111
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
112
|
+
ref,
|
|
113
|
+
className,
|
|
114
|
+
"data-fs-copy-text": "",
|
|
115
|
+
"data-fs-copy-text-outcome": outcome,
|
|
116
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
117
|
+
ref: actionRef,
|
|
118
|
+
type: "button",
|
|
119
|
+
"aria-label": name,
|
|
120
|
+
"data-fs-copy-text-action": "",
|
|
121
|
+
disabled: isBlank(text) || outcome === "pending",
|
|
122
|
+
onClick: () => {
|
|
123
|
+
copy();
|
|
124
|
+
},
|
|
125
|
+
children
|
|
126
|
+
}), outcome === "success" || outcome === "failure" ? /* @__PURE__ */ jsxs("output", {
|
|
127
|
+
"data-fs-copy-text-message": "",
|
|
128
|
+
children: [message, /* @__PURE__ */ jsx(Button, {
|
|
129
|
+
type: "button",
|
|
130
|
+
"aria-label": dismissText,
|
|
131
|
+
onClick: dismiss,
|
|
132
|
+
children: dismissText
|
|
133
|
+
})]
|
|
134
|
+
}) : null]
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
export { CopyText, CopyTextDefinition };
|
|
139
|
+
|
|
140
|
+
//# sourceMappingURL=copy-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-text.js","names":[],"sources":["../../../src/particles/copy-text/copy-text.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport { type ReactNode, type Ref, useEffect, useRef, useState } from 'react';\nimport { useIntl } from '../../sdk/i18n/client.js';\nimport { Button } from '../button/button';\n\nconst CLEAR_AFTER_MS = 5000;\n\nexport type CopyTextOutcome = 'idle' | 'pending' | 'success' | 'failure';\n\nexport type CopyTextProps = Readonly<{\n text: string;\n accessibleName?: string;\n successMessage?: string;\n failureMessage?: string;\n dismissLabel?: string;\n children?: ReactNode;\n className?: string;\n ref?: Ref<HTMLSpanElement>;\n}>;\n\nfunction isBlank(text: string): boolean {\n return text.trim().length === 0;\n}\n\nexport const CopyTextDefinition = defineComponent<CopyTextProps>({\n name: 'CopyText',\n importPath: '@vtex/faststore/components',\n component: CopyText,\n editor: { label: 'Copy Text', category: 'action' },\n schema: {\n accessibleName: { type: 'string', default: 'Copy', label: 'Accessible name' },\n successMessage: { type: 'string', default: 'Copied', label: 'Success message' },\n failureMessage: { type: 'string', default: 'Could not copy', label: 'Failure message' },\n dismissLabel: { type: 'string', default: 'Dismiss', label: 'Dismiss label' },\n },\n guideline:\n 'Copies the text it is given and confirms the result inline. Pass the identifier as text and the visible icon or label as children. Do not pass surrounding heading text.',\n});\n\nexport function CopyText({\n text,\n accessibleName,\n successMessage,\n failureMessage,\n dismissLabel,\n children,\n className,\n ref,\n}: CopyTextProps) {\n const intl = useIntl();\n const name = accessibleName ?? intl.formatMessage({ id: 'fs/order.copy.action' });\n const success = successMessage ?? intl.formatMessage({ id: 'fs/order.copy.copied' });\n const failure = failureMessage ?? intl.formatMessage({ id: 'fs/order.copy.failure' });\n const dismissText = dismissLabel ?? intl.formatMessage({ id: 'fs/order.copy.dismiss' });\n const [outcome, setOutcome] = useState<CopyTextOutcome>('idle');\n const actionRef = useRef<HTMLButtonElement>(null);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const generation = useRef(0);\n const active = useRef(true);\n\n function clearTimer() {\n if (timerRef.current === null) return;\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n\n useEffect(() => {\n active.current = true;\n return () => {\n active.current = false;\n if (timerRef.current === null) return;\n clearTimeout(timerRef.current);\n timerRef.current = null;\n };\n }, []);\n\n function scheduleClear(token: number) {\n clearTimer();\n if (!active.current) return;\n timerRef.current = setTimeout(() => {\n if (!active.current || generation.current !== token) return;\n setOutcome('idle');\n }, CLEAR_AFTER_MS);\n }\n\n async function copy() {\n if (isBlank(text) || outcome === 'pending') return;\n const token = generation.current + 1;\n generation.current = token;\n clearTimer();\n setOutcome('pending');\n\n const write = navigator.clipboard?.writeText;\n if (typeof write !== 'function') {\n if (!active.current || generation.current !== token) return;\n setOutcome('failure');\n scheduleClear(token);\n return;\n }\n\n try {\n await write.call(navigator.clipboard, text);\n if (!active.current || generation.current !== token) return;\n setOutcome('success');\n } catch {\n if (!active.current || generation.current !== token) return;\n setOutcome('failure');\n }\n scheduleClear(token);\n }\n\n // The action is disabled while pending, and a disabled control ignores focus(). Focus moves back\n // once the outcome that re-enables it has committed.\n useEffect(() => {\n if (outcome === 'success' || outcome === 'failure') {\n actionRef.current?.focus();\n }\n }, [outcome]);\n\n function dismiss() {\n generation.current += 1;\n clearTimer();\n setOutcome('idle');\n actionRef.current?.focus();\n }\n\n const message = outcome === 'success' ? success : failure;\n\n return (\n <span ref={ref} className={className} data-fs-copy-text=\"\" data-fs-copy-text-outcome={outcome}>\n <Button\n ref={actionRef}\n type=\"button\"\n aria-label={name}\n data-fs-copy-text-action=\"\"\n disabled={isBlank(text) || outcome === 'pending'}\n onClick={() => {\n void copy();\n }}\n >\n {children}\n </Button>\n {outcome === 'success' || outcome === 'failure' ? (\n <output data-fs-copy-text-message=\"\">\n {message}\n <Button type=\"button\" aria-label={dismissText} onClick={dismiss}>\n {dismissText}\n </Button>\n </output>\n ) : null}\n </span>\n );\n}\n"],"mappings":"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"}
|
|
@@ -3,13 +3,18 @@ import "../../core/dist/index.js";
|
|
|
3
3
|
import { applyMask } from "../shared/input-mask.js";
|
|
4
4
|
import { ComponentPropsWithRef, FocusEvent, ReactNode, Ref } from "react";
|
|
5
5
|
//#region src/particles/document-field/document-field.d.ts
|
|
6
|
-
export type DocumentType = 'CPF';
|
|
6
|
+
export type DocumentType = 'CPF' | 'SSN' | 'SIN' | 'RFC';
|
|
7
7
|
type DocumentFieldRequirement = 'mandatory' | 'optional';
|
|
8
8
|
export type DocumentSpec = {
|
|
9
9
|
id: DocumentType;
|
|
10
10
|
name: string;
|
|
11
11
|
mask: string;
|
|
12
|
+
placeholder: string;
|
|
13
|
+
/** Strips what the type never holds, before the mask runs. */
|
|
14
|
+
sanitize: (raw: string) => string;
|
|
12
15
|
validate: (value: string) => boolean;
|
|
16
|
+
/** `'off'` for SSN and SIN, absent for CPF and RFC (Decision 9). */
|
|
17
|
+
autoComplete?: 'off';
|
|
13
18
|
};
|
|
14
19
|
export type DocumentFieldProps = Omit<ComponentPropsWithRef<'div'>, 'defaultValue' | 'value' | 'onChange' | 'onBlur' | 'ref' | 'dangerouslySetInnerHTML'> & {
|
|
15
20
|
/** Unused on the bound path — react-hook-form owns the value. */
|
|
@@ -54,9 +59,33 @@ export type DocumentFieldProps = Omit<ComponentPropsWithRef<'div'>, 'defaultValu
|
|
|
54
59
|
* digits. Runs on blur/submit only, never per keystroke.
|
|
55
60
|
*/
|
|
56
61
|
export declare function validateCPF(value: string): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* SSN validation, ported from `@vtex/country-forms` 1.2.0 (measured 2026-10-16). Strips non-digits,
|
|
64
|
+
* requires exactly 9 digits, refuses area `000`, `666` and `>= 900`, group `00` and serial `0000`.
|
|
65
|
+
*/
|
|
66
|
+
export declare function validateSSN(value: string): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* SIN validation, ported from `@vtex/country-forms` 1.2.0 (measured 2026-10-16). Strips non-digits,
|
|
69
|
+
* requires exactly 9 digits, refuses all zeros, and verifies the Luhn check.
|
|
70
|
+
*/
|
|
71
|
+
export declare function validateSIN(value: string): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* RFC (individual) validation, ported from `@vtex/country-forms` 1.2.0 (measured 2026-10-16): after
|
|
74
|
+
* uppercasing and stripping every non A-Z0-9 character it is four letters, six digits and three
|
|
75
|
+
* letters or digits, and characters 5-10 read as a plausible month (1-12) and day (1-31). The day check
|
|
76
|
+
* is not calendar-aware, as in the library. The library's set of refused four-letter prefixes is not
|
|
77
|
+
* carried (the structure and the date are what a typo breaks).
|
|
78
|
+
*/
|
|
79
|
+
export declare function validateRFC(value: string): boolean;
|
|
57
80
|
export declare const DOCUMENTS: Record<DocumentType, DocumentSpec>;
|
|
58
81
|
/**
|
|
59
|
-
*
|
|
82
|
+
* Turns the API's lower-case document id (`Payment.countries[].documents[].type`) into this table's key,
|
|
83
|
+
* or `null` for anything else, including a business document, a prototype key and a non-string.
|
|
84
|
+
*/
|
|
85
|
+
export declare function documentTypeFromId(id: unknown): DocumentType | null;
|
|
86
|
+
/**
|
|
87
|
+
* True when `type` is one of the table's upper-case keys (`CPF`, `SSN`, `SIN`, `RFC`); the API's lower-case
|
|
88
|
+
* ids go through `documentTypeFromId`. Lets a host gate the field by locale.
|
|
60
89
|
*
|
|
61
90
|
* `Object.hasOwn`, not the `in` operator: `in` walks the prototype chain, so `constructor`,
|
|
62
91
|
* `__proto__` and `toString` all satisfied it and were then trusted as a `DocumentType` by callers
|
|
@@ -66,9 +95,9 @@ export declare const DOCUMENTS: Record<DocumentType, DocumentSpec>;
|
|
|
66
95
|
*/
|
|
67
96
|
export declare function isSupportedDocumentType(type: unknown): type is DocumentType;
|
|
68
97
|
/**
|
|
69
|
-
* Apply a document type's mask to raw input:
|
|
70
|
-
*
|
|
71
|
-
*
|
|
98
|
+
* Apply a document type's mask to raw input: run the type's sanitiser, then truncate to the mask's slot
|
|
99
|
+
* count so excess characters never trail past the mask (e.g. a 15-digit paste into the 11-slot CPF mask
|
|
100
|
+
* yields `111.444.777-35`, not `111.444.777-358888`).
|
|
72
101
|
*/
|
|
73
102
|
export declare function maskDocumentValue(rawValue: string, documentType: DocumentType): string;
|
|
74
103
|
/**
|
|
@@ -5,7 +5,7 @@ import { FieldBinding, TEXT_FIELD_VALUE, mergeFieldValidator, useBoundField, use
|
|
|
5
5
|
import { useComposedRef } from "../shared/compose-refs.js";
|
|
6
6
|
import { applyMask, countSlots, isDigitOnly } from "../shared/input-mask.js";
|
|
7
7
|
import { createContext, useContext, useMemo, useState } from "react";
|
|
8
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
import { Field } from "@base-ui/react/field";
|
|
10
10
|
import { useFormContext, useFormState } from "react-hook-form";
|
|
11
11
|
//#region src/particles/document-field/document-field.tsx
|
|
@@ -15,20 +15,112 @@ import { useFormContext, useFormState } from "react-hook-form";
|
|
|
15
15
|
* digits. Runs on blur/submit only, never per keystroke.
|
|
16
16
|
*/
|
|
17
17
|
function validateCPF(value) {
|
|
18
|
-
const digits = value.
|
|
18
|
+
const digits = value.replaceAll(/[^\d]+/g, "");
|
|
19
19
|
if (digits.length !== 11 || /(\d)\1{10}/.test(digits)) return false;
|
|
20
20
|
const values = digits.split("").map((el) => +el);
|
|
21
21
|
const rest = (count) => values.slice(0, count - 12).reduce((sum, el, index) => sum + el * (count - index), 0) * 10 % 11 % 10;
|
|
22
22
|
return rest(10) === values[9] && rest(11) === values[10];
|
|
23
23
|
}
|
|
24
|
-
const DOCUMENTS = { CPF: {
|
|
25
|
-
id: "CPF",
|
|
26
|
-
name: "CPF",
|
|
27
|
-
mask: "999.999.999-99",
|
|
28
|
-
validate: validateCPF
|
|
29
|
-
} };
|
|
30
24
|
/**
|
|
31
|
-
*
|
|
25
|
+
* SSN validation, ported from `@vtex/country-forms` 1.2.0 (measured 2026-10-16). Strips non-digits,
|
|
26
|
+
* requires exactly 9 digits, refuses area `000`, `666` and `>= 900`, group `00` and serial `0000`.
|
|
27
|
+
*/
|
|
28
|
+
function validateSSN(value) {
|
|
29
|
+
const digits = value.replaceAll(/\D/g, "");
|
|
30
|
+
if (digits.length !== 9) return false;
|
|
31
|
+
const area = digits.slice(0, 3);
|
|
32
|
+
if (area === "000" || area === "666" || Number(area) >= 900) return false;
|
|
33
|
+
if (digits.slice(3, 5) === "00") return false;
|
|
34
|
+
return digits.slice(5) !== "0000";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* SIN validation, ported from `@vtex/country-forms` 1.2.0 (measured 2026-10-16). Strips non-digits,
|
|
38
|
+
* requires exactly 9 digits, refuses all zeros, and verifies the Luhn check.
|
|
39
|
+
*/
|
|
40
|
+
function validateSIN(value) {
|
|
41
|
+
const digits = value.replaceAll(/\D/g, "");
|
|
42
|
+
if (digits.length !== 9 || /^0+$/.test(digits)) return false;
|
|
43
|
+
let sum = 0;
|
|
44
|
+
for (let index = 0; index < 9; index += 1) {
|
|
45
|
+
let digit = Number(digits[index]);
|
|
46
|
+
if (index % 2 === 1) {
|
|
47
|
+
digit *= 2;
|
|
48
|
+
if (digit > 9) digit -= 9;
|
|
49
|
+
}
|
|
50
|
+
sum += digit;
|
|
51
|
+
}
|
|
52
|
+
return sum % 10 === 0;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* RFC (individual) validation, ported from `@vtex/country-forms` 1.2.0 (measured 2026-10-16): after
|
|
56
|
+
* uppercasing and stripping every non A-Z0-9 character it is four letters, six digits and three
|
|
57
|
+
* letters or digits, and characters 5-10 read as a plausible month (1-12) and day (1-31). The day check
|
|
58
|
+
* is not calendar-aware, as in the library. The library's set of refused four-letter prefixes is not
|
|
59
|
+
* carried (the structure and the date are what a typo breaks).
|
|
60
|
+
*/
|
|
61
|
+
function validateRFC(value) {
|
|
62
|
+
const rfc = value.toUpperCase().replaceAll(/[^A-Z0-9]/g, "");
|
|
63
|
+
if (!/^[A-Z]{4}\d{6}[A-Z0-9]{3}$/.test(rfc)) return false;
|
|
64
|
+
const month = Number(rfc.slice(6, 8));
|
|
65
|
+
const day = Number(rfc.slice(8, 10));
|
|
66
|
+
return month >= 1 && month <= 12 && day >= 1 && day <= 31;
|
|
67
|
+
}
|
|
68
|
+
function stripNonDigits(raw) {
|
|
69
|
+
return raw.replaceAll(/\D/g, "");
|
|
70
|
+
}
|
|
71
|
+
const DOCUMENTS = {
|
|
72
|
+
CPF: {
|
|
73
|
+
id: "CPF",
|
|
74
|
+
name: "CPF",
|
|
75
|
+
mask: "999.999.999-99",
|
|
76
|
+
placeholder: "000.000.000-00",
|
|
77
|
+
sanitize: stripNonDigits,
|
|
78
|
+
validate: validateCPF
|
|
79
|
+
},
|
|
80
|
+
SSN: {
|
|
81
|
+
id: "SSN",
|
|
82
|
+
name: "SSN",
|
|
83
|
+
mask: "999-99-9999",
|
|
84
|
+
placeholder: "000-00-0000",
|
|
85
|
+
sanitize: stripNonDigits,
|
|
86
|
+
validate: validateSSN,
|
|
87
|
+
autoComplete: "off"
|
|
88
|
+
},
|
|
89
|
+
SIN: {
|
|
90
|
+
id: "SIN",
|
|
91
|
+
name: "SIN",
|
|
92
|
+
mask: "999-999-999",
|
|
93
|
+
placeholder: "000-000-000",
|
|
94
|
+
sanitize: stripNonDigits,
|
|
95
|
+
validate: validateSIN,
|
|
96
|
+
autoComplete: "off"
|
|
97
|
+
},
|
|
98
|
+
RFC: {
|
|
99
|
+
id: "RFC",
|
|
100
|
+
name: "RFC",
|
|
101
|
+
mask: "SSSSSSSSSSSSS",
|
|
102
|
+
placeholder: "AAAA000000AAA",
|
|
103
|
+
sanitize: (raw) => raw.toUpperCase().replaceAll(/[^A-Z0-9]/g, ""),
|
|
104
|
+
validate: validateRFC
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const DOCUMENT_TYPE_BY_API_ID = {
|
|
108
|
+
cpf: "CPF",
|
|
109
|
+
ssn: "SSN",
|
|
110
|
+
sin: "SIN",
|
|
111
|
+
rfc: "RFC"
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Turns the API's lower-case document id (`Payment.countries[].documents[].type`) into this table's key,
|
|
115
|
+
* or `null` for anything else, including a business document, a prototype key and a non-string.
|
|
116
|
+
*/
|
|
117
|
+
function documentTypeFromId(id) {
|
|
118
|
+
if (typeof id !== "string" || !Object.hasOwn(DOCUMENT_TYPE_BY_API_ID, id)) return null;
|
|
119
|
+
return DOCUMENT_TYPE_BY_API_ID[id] ?? null;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* True when `type` is one of the table's upper-case keys (`CPF`, `SSN`, `SIN`, `RFC`); the API's lower-case
|
|
123
|
+
* ids go through `documentTypeFromId`. Lets a host gate the field by locale.
|
|
32
124
|
*
|
|
33
125
|
* `Object.hasOwn`, not the `in` operator: `in` walks the prototype chain, so `constructor`,
|
|
34
126
|
* `__proto__` and `toString` all satisfied it and were then trusted as a `DocumentType` by callers
|
|
@@ -40,15 +132,14 @@ function isSupportedDocumentType(type) {
|
|
|
40
132
|
return typeof type === "string" && Object.hasOwn(DOCUMENTS, type);
|
|
41
133
|
}
|
|
42
134
|
/**
|
|
43
|
-
* Apply a document type's mask to raw input:
|
|
44
|
-
*
|
|
45
|
-
*
|
|
135
|
+
* Apply a document type's mask to raw input: run the type's sanitiser, then truncate to the mask's slot
|
|
136
|
+
* count so excess characters never trail past the mask (e.g. a 15-digit paste into the 11-slot CPF mask
|
|
137
|
+
* yields `111.444.777-35`, not `111.444.777-358888`).
|
|
46
138
|
*/
|
|
47
139
|
function maskDocumentValue(rawValue, documentType) {
|
|
48
140
|
const spec = DOCUMENTS[documentType];
|
|
49
|
-
const sanitized = isDigitOnly(spec.mask) ? rawValue.replace(/\D/g, "") : rawValue;
|
|
50
141
|
const maxSlots = Math.max(...spec.mask.split("|").map(countSlots));
|
|
51
|
-
return applyMask(
|
|
142
|
+
return applyMask(spec.sanitize(rawValue).slice(0, maxSlots), spec.mask);
|
|
52
143
|
}
|
|
53
144
|
/**
|
|
54
145
|
* Check-digit validity for a document value. An **empty** value is valid (the field is optional),
|
|
@@ -96,7 +187,7 @@ const DocumentFieldDefinition = defineComponent({
|
|
|
96
187
|
label: "Disabled"
|
|
97
188
|
}
|
|
98
189
|
},
|
|
99
|
-
guideline: "Presentational tax-document input composing the Field particle; applies the
|
|
190
|
+
guideline: "Presentational tax-document input composing the Field particle; applies the mask of its document type on change and runs the matching validation on blur/submit; documentType is one of CPF, SSN, SIN or RFC. Data-agnostic (value/defaultValue/onValueChange); a host wires it to the shopper profile. The document is optional by default: requirement only ever raises the field to required, announced as aria-required, and bound to a fieldset whose rule already says required it cannot lower it back. Recomposable (RFC:503): given children, they replace the default Field.Label + DocumentFieldInput + Field.Error anatomy, in any order."
|
|
100
191
|
});
|
|
101
192
|
/**
|
|
102
193
|
* Presentational tax-document input (particle). Composes the `Field` particle (`Field.Root` +
|
|
@@ -141,7 +232,7 @@ const DocumentFieldInputDefinition = defineComponent({
|
|
|
141
232
|
});
|
|
142
233
|
/** Renders the masked document `<input>`, reading its value/handlers/ref from the enclosing `DocumentField`. */
|
|
143
234
|
function DocumentFieldInput({ className }) {
|
|
144
|
-
const { ref, name, value, placeholder, disabled, required, numericOnly, onChange, onBlur } = useDocumentFieldInputContext();
|
|
235
|
+
const { ref, name, value, placeholder, disabled, required, numericOnly, autoComplete, onChange, onBlur } = useDocumentFieldInputContext();
|
|
145
236
|
return /* @__PURE__ */ jsx(Field.Control, {
|
|
146
237
|
ref,
|
|
147
238
|
name,
|
|
@@ -149,6 +240,7 @@ function DocumentFieldInput({ className }) {
|
|
|
149
240
|
placeholder,
|
|
150
241
|
disabled,
|
|
151
242
|
value,
|
|
243
|
+
autoComplete,
|
|
152
244
|
...numericOnly ? { inputMode: "numeric" } : {},
|
|
153
245
|
onChange,
|
|
154
246
|
onBlur,
|
|
@@ -156,7 +248,7 @@ function DocumentFieldInput({ className }) {
|
|
|
156
248
|
"data-fs-field-control": ""
|
|
157
249
|
});
|
|
158
250
|
}
|
|
159
|
-
function DocumentFieldView({ className, name, label, placeholder, disabled, required, numericOnly, displayValue, showInvalid, errorMessage, onChange, onBlur, ref, children, ...props }) {
|
|
251
|
+
function DocumentFieldView({ className, name, label, placeholder, disabled, required, numericOnly, autoComplete, displayValue, showInvalid, errorMessage, onChange, onBlur, ref, children, ...props }) {
|
|
160
252
|
const inputContext = useMemo(() => ({
|
|
161
253
|
ref,
|
|
162
254
|
name,
|
|
@@ -165,6 +257,7 @@ function DocumentFieldView({ className, name, label, placeholder, disabled, requ
|
|
|
165
257
|
disabled,
|
|
166
258
|
required,
|
|
167
259
|
numericOnly,
|
|
260
|
+
autoComplete,
|
|
168
261
|
onChange,
|
|
169
262
|
onBlur
|
|
170
263
|
}), [
|
|
@@ -175,6 +268,7 @@ function DocumentFieldView({ className, name, label, placeholder, disabled, requ
|
|
|
175
268
|
disabled,
|
|
176
269
|
required,
|
|
177
270
|
numericOnly,
|
|
271
|
+
autoComplete,
|
|
178
272
|
onChange,
|
|
179
273
|
onBlur
|
|
180
274
|
]);
|
|
@@ -188,7 +282,7 @@ function DocumentFieldView({ className, name, label, placeholder, disabled, requ
|
|
|
188
282
|
"data-fs-field-root": "",
|
|
189
283
|
children: /* @__PURE__ */ jsx(DocumentFieldInputContext.Provider, {
|
|
190
284
|
value: inputContext,
|
|
191
|
-
children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
285
|
+
children: children ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
192
286
|
label ? /* @__PURE__ */ jsx(Field.Label, {
|
|
193
287
|
"data-fs-field-label": "",
|
|
194
288
|
children: label
|
|
@@ -231,6 +325,7 @@ function UnboundDocumentField({ value, defaultValue = "", onValueChange, onBlur,
|
|
|
231
325
|
disabled,
|
|
232
326
|
required: requirement === "mandatory",
|
|
233
327
|
numericOnly,
|
|
328
|
+
autoComplete: DOCUMENTS[documentType].autoComplete,
|
|
234
329
|
displayValue,
|
|
235
330
|
showInvalid,
|
|
236
331
|
errorMessage,
|
|
@@ -288,6 +383,7 @@ function BoundDocumentField({ value: _value, defaultValue: _defaultValue, onValu
|
|
|
288
383
|
disabled: resolvedDisabled,
|
|
289
384
|
required: field.required,
|
|
290
385
|
numericOnly,
|
|
386
|
+
autoComplete: DOCUMENTS[documentType].autoComplete,
|
|
291
387
|
displayValue,
|
|
292
388
|
showInvalid,
|
|
293
389
|
errorMessage,
|
|
@@ -298,6 +394,6 @@ function BoundDocumentField({ value: _value, defaultValue: _defaultValue, onValu
|
|
|
298
394
|
});
|
|
299
395
|
}
|
|
300
396
|
//#endregion
|
|
301
|
-
export { DOCUMENTS, DocumentField, DocumentFieldDefinition, DocumentFieldInput, DocumentFieldInputDefinition, applyMask, isSupportedDocumentType, isValidDocument, maskDocumentValue, validateCPF };
|
|
397
|
+
export { DOCUMENTS, DocumentField, DocumentFieldDefinition, DocumentFieldInput, DocumentFieldInputDefinition, applyMask, documentTypeFromId, isSupportedDocumentType, isValidDocument, maskDocumentValue, validateCPF, validateRFC, validateSIN, validateSSN };
|
|
302
398
|
|
|
303
399
|
//# sourceMappingURL=document-field.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-field.js","names":["BaseField"],"sources":["../../../src/particles/document-field/document-field.tsx"],"sourcesContent":["'use client';\nimport { Field as BaseField } from '@base-ui/react/field';\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ChangeEvent, ComponentPropsWithRef, 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 { useComposedRef } from '../shared/compose-refs.js';\nimport { applyMask, countSlots, isDigitOnly } from '../shared/input-mask.js';\n\n// `applyMask` was public from this module before the engine moved out; keep the export path stable.\nexport { applyMask } from '../shared/input-mask.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type DocumentType = 'CPF';\n\ntype DocumentFieldRequirement = 'mandatory' | 'optional';\n\nexport type DocumentSpec = {\n id: DocumentType;\n name: string;\n mask: string;\n validate: (value: string) => boolean;\n};\n\n// `dangerouslySetInnerHTML` is excluded — the rest spread this props type feeds forwards straight to\n// `Field.Root`, and a schema-authored `page.json` can supply it with no allowlist in between.\nexport type DocumentFieldProps = Omit<\n ComponentPropsWithRef<'div'>,\n 'defaultValue' | 'value' | 'onChange' | 'onBlur' | 'ref' | 'dangerouslySetInnerHTML'\n> & {\n /** Unused on the bound path — react-hook-form owns the value. */\n value?: string;\n /** Unused on the bound path — the field contract's `defaultValue` seeds it instead. */\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n onBlur?: (event: FocusEvent<HTMLInputElement>) => void;\n invalid?: boolean;\n errorMessage?: string;\n /** Falls back to the field contract's `label` when bound. */\n label?: string;\n /** Falls back to the field contract's `placeholder` when bound. */\n placeholder?: string;\n /** Falls back to the field contract's `disabled` when bound. */\n disabled?: boolean;\n /**\n * Raises the field to required, the same word `PhoneField` uses. It only ever raises: bound to a\n * fieldset whose rule already says required, `'optional'` does not lower it. Left unset it is no\n * opinion, which keeps CPF optional by recommendation.\n */\n requirement?: DocumentFieldRequirement;\n name?: string;\n documentType?: DocumentType;\n /**\n * Lands on the `<input>` `Field.Control` renders — not on the wrapper `<div>`, as it did before\n * (a deliberate, source-breaking re-route: the previous ref pointed at an untabbable div). Composed\n * with react-hook-form's own ref on the bound path.\n */\n ref?: Ref<HTMLInputElement>;\n /**\n * Given, replaces the default `Field.Label` + `DocumentFieldInput` + `Field.Error` anatomy — any\n * order, any subset. `DocumentFieldInput` is the one part that carries the mask, the composed ref\n * and the particle's own value/handlers; a composed generic `Field.Control` would call\n * `useController` a second time for the same name (RFC's named, accepted double-binder hole).\n */\n children?: ReactNode;\n};\n\n// ---------------------------------------------------------------------------\n// Ported check-digit validation (fastcheckout `packages/libs/validators/src/document`).\n// ---------------------------------------------------------------------------\n\n/**\n * CPF check-digit validation, ported from the legacy `validateCPF`. Strips non-digits, requires\n * exactly 11 digits, rejects all-equal sequences (e.g. `111.111.111-11`), and verifies both check\n * digits. Runs on blur/submit only, never per keystroke.\n */\nexport function validateCPF(value: string): boolean {\n const digits = value.replace(/[^\\d]+/g, '');\n\n if (digits.length !== 11 || /(\\d)\\1{10}/.test(digits)) {\n return false;\n }\n\n const values = digits.split('').map((el) => +el);\n const rest = (count: number) =>\n ((values.slice(0, count - 12).reduce((sum, el, index) => sum + el * (count - index), 0) * 10) % 11) % 10;\n\n return rest(10) === values[9] && rest(11) === values[10];\n}\n\n// ---------------------------------------------------------------------------\n// Document table (subset needed for the CPF launch). `documentType` selects the mask +\n// validator + digit-only input mode. Extendable later (SSN | SIN | CURP) without touching callers.\n// ---------------------------------------------------------------------------\n\nexport const DOCUMENTS: Record<DocumentType, DocumentSpec> = {\n CPF: {\n id: 'CPF',\n name: 'CPF',\n mask: '999.999.999-99',\n validate: validateCPF,\n },\n};\n\n/**\n * True when `type` is a document type this build supports (lets a host gate the field by locale).\n *\n * `Object.hasOwn`, not the `in` operator: `in` walks the prototype chain, so `constructor`,\n * `__proto__` and `toString` all satisfied it and were then trusted as a `DocumentType` by callers\n * (`client-profile-fieldset.tsx` renders the field on the strength of this narrowing). The value is\n * author-only — a literal written into `page.json`, never a runtime expression — so this is\n * robustness rather than a reachable defect, but the narrowing should not be able to lie.\n */\nexport function isSupportedDocumentType(type: unknown): type is DocumentType {\n return typeof type === 'string' && Object.hasOwn(DOCUMENTS, type);\n}\n\n/**\n * Apply a document type's mask to raw input: strip non-digits for digit-only masks, then truncate to\n * the mask's slot count so excess characters never trail past the mask (e.g. a 15-digit paste into\n * the 11-slot CPF mask yields `111.444.777-35`, not `111.444.777-358888`).\n */\nexport function maskDocumentValue(rawValue: string, documentType: DocumentType): string {\n const spec = DOCUMENTS[documentType];\n const sanitized = isDigitOnly(spec.mask) ? rawValue.replace(/\\D/g, '') : rawValue;\n const maxSlots = Math.max(...spec.mask.split('|').map(countSlots));\n return applyMask(sanitized.slice(0, maxSlots), spec.mask);\n}\n\n/**\n * Check-digit validity for a document value. An **empty** value is valid (the field is optional),\n * mirroring the legacy `validateCardholderDocument`; a non-empty value must pass the document\n * type's check-digit validation.\n */\nexport function isValidDocument(value: string, documentType: DocumentType): boolean {\n if (!value.trim()) return true;\n return DOCUMENTS[documentType].validate(value);\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport const DocumentFieldDefinition = defineComponent<DocumentFieldProps>({\n name: 'DocumentField',\n importPath: '@vtex/faststore/components',\n component: DocumentField,\n providesContext: 'document-field',\n editor: { label: 'Document Field', category: 'content' },\n schema: {\n label: { type: 'string', label: 'Label' },\n placeholder: { type: 'string', label: 'Placeholder' },\n errorMessage: { type: 'string', label: 'Error message' },\n documentType: { type: 'string', default: 'CPF', label: 'Document type' },\n requirement: { type: ['mandatory', 'optional'] as const, label: 'Requirement' },\n disabled: { type: 'boolean', default: false, label: 'Disabled' },\n },\n guideline:\n 'Presentational tax-document input composing the Field particle; applies the locale mask on change and runs check-digit validation on blur/submit. Data-agnostic (value/defaultValue/onValueChange); a host wires it to the shopper profile. CPF is optional by default: requirement only ever raises the field to required, announced as aria-required, and bound to a fieldset whose rule already says required it cannot lower it back. Recomposable (RFC:503): given children, they replace the default Field.Label + DocumentFieldInput + Field.Error anatomy, in any order.',\n});\n\n/**\n * Presentational tax-document input (particle). Composes the `Field` particle (`Field.Root` +\n * `Field.Label` + `Field.Control` + `Field.Error`) and owns the locale mask (applied progressively on\n * every change, never blocking typing) plus check-digit validation (run on blur/submit only — never\n * per keystroke). An empty value is valid (the field is optional). It surfaces `errorMessage` inline\n * when the check digit fails or when the host forces `invalid` (e.g. a server error surfaced by the\n * form that owns the write). It consumes no GraphQL and no domain context — value flows through\n * `value`/`defaultValue`/`onValueChange`, and `documentType` selects the mask + validator.\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 * `BoundDocumentField`, so hook order never changes under a mounted component. Both sub-components\n * render the same `DocumentFieldView`, so the two paths cannot drift into different DOM.\n */\nexport function DocumentField(props: DocumentFieldProps): ReactNode {\n const contract = useField();\n const formContext = useFormContext();\n\n if (contract && formContext) {\n return <BoundDocumentField {...props} contract={contract} />;\n }\n\n return <UnboundDocumentField {...props} />;\n}\n\n// ---------------------------------------------------------------------------\n// Input part — catalogued, placeable (Decision 4). Carries the mask, the composed ref, and the\n// particle's own onChange/onBlur. Renders the RAW Base UI Field.Control, not this package's own\n// Field.Control wrapper — the latter would see the real ambient contract Decision 3 now provides\n// and call useController a second time for the same name, overwriting the composite's masked value\n// (the exact double-registration bug the removed FieldContractBoundary used to prevent globally).\n// ---------------------------------------------------------------------------\n\ntype DocumentFieldInputContextValue = {\n ref?: Ref<HTMLInputElement>;\n name?: string;\n value: string;\n placeholder?: string;\n disabled: boolean;\n /** Resolved by the binder, threaded here because this part is not the one that binds. */\n required: boolean;\n numericOnly: boolean;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: (event: FocusEvent<HTMLInputElement>) => void;\n};\n\nconst DocumentFieldInputContext = createContext<DocumentFieldInputContextValue | null>(null);\n\nfunction useDocumentFieldInputContext(): DocumentFieldInputContextValue {\n const context = useContext(DocumentFieldInputContext);\n if (!context) {\n throw new Error('DocumentFieldInput must be a descendant of DocumentField.');\n }\n return context;\n}\n\nexport type DocumentFieldInputProps = { className?: string };\n\nexport const DocumentFieldInputDefinition = defineComponent<DocumentFieldInputProps>({\n name: 'DocumentFieldInput',\n importPath: '@vtex/faststore/components',\n component: DocumentFieldInput,\n requiresContext: 'document-field',\n editor: { label: 'Document Field Input', category: 'action' },\n schema: {},\n guideline:\n \"The masked document <input> DocumentField owns. Must sit inside DocumentField, in either the default anatomy or an author's composed children. Carries the locale mask, the composed ref, and DocumentField'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 document `<input>`, reading its value/handlers/ref from the enclosing `DocumentField`. */\nexport function DocumentFieldInput({ className }: DocumentFieldInputProps): ReactNode {\n const { ref, name, value, placeholder, disabled, required, numericOnly, onChange, onBlur } =\n useDocumentFieldInputContext();\n\n return (\n <BaseField.Control\n ref={ref}\n name={name}\n // `aria-required`, not native `required`, for the reason password-field.tsx:89-91 records:\n // this is a Base UI `Field.Control`, and native constraint tracking would flip `aria-invalid`\n // on its own, ahead of react-hook-form's own validation.\n aria-required={required || undefined}\n placeholder={placeholder}\n disabled={disabled}\n value={value}\n {...(numericOnly ? { inputMode: 'numeric' as const } : {})}\n onChange={onChange}\n onBlur={onBlur}\n className={className}\n data-fs-field-control=\"\"\n />\n );\n}\n\n// ---------------------------------------------------------------------------\n// Shared view — identical DOM whether bound or unbound\n// ---------------------------------------------------------------------------\n\ntype DocumentFieldViewProps = Omit<\n ComponentPropsWithRef<'div'>,\n 'defaultValue' | 'value' | 'onChange' | 'onBlur' | 'ref'\n> & {\n ref?: Ref<HTMLInputElement>;\n name?: string;\n label?: string;\n placeholder?: string;\n disabled: boolean;\n required: boolean;\n numericOnly: boolean;\n displayValue: string;\n showInvalid: boolean;\n errorMessage?: string;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: (event: FocusEvent<HTMLInputElement>) => void;\n children?: ReactNode;\n};\n\nfunction DocumentFieldView({\n className,\n name,\n label,\n placeholder,\n disabled,\n required,\n numericOnly,\n displayValue,\n showInvalid,\n errorMessage,\n onChange,\n onBlur,\n ref,\n children,\n ...props\n}: DocumentFieldViewProps) {\n const inputContext = useMemo<DocumentFieldInputContextValue>(\n () => ({ ref, name, value: displayValue, placeholder, disabled, required, numericOnly, onChange, onBlur }),\n [ref, name, displayValue, placeholder, disabled, required, numericOnly, onChange, onBlur],\n );\n\n return (\n // Deliberately the RAW Base UI Field.Root/Label/Error, not this package's own Field.* wrapper,\n // for the default anatomy — reproduces exactly what rendered before FieldContractBoundary was\n // removed (Decision 3), including the host `invalid`/`errorMessage` override working\n // unconditionally. Composed children, below, use the package's own Field.* parts on purpose —\n // that is what makes a childless Field.Label / Field.Error resolve real text (FR-5).\n <BaseField.Root\n {...props}\n className={className}\n name={name}\n invalid={showInvalid}\n disabled={disabled}\n data-fs-document-field=\"\"\n data-fs-field-root=\"\"\n >\n <DocumentFieldInputContext.Provider value={inputContext}>\n {children ?? (\n <>\n {label ? <BaseField.Label data-fs-field-label=\"\">{label}</BaseField.Label> : null}\n <DocumentFieldInput />\n {showInvalid && errorMessage ? (\n <BaseField.Error match data-fs-field-error=\"\">\n {errorMessage}\n </BaseField.Error>\n ) : null}\n </>\n )}\n </DocumentFieldInputContext.Provider>\n </BaseField.Root>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Unbound — today's body, moved verbatim\n// ---------------------------------------------------------------------------\n\nfunction UnboundDocumentField({\n value,\n defaultValue = '',\n onValueChange,\n onBlur,\n invalid = false,\n errorMessage,\n label,\n placeholder,\n disabled = false,\n requirement,\n name = 'document',\n documentType = 'CPF',\n className,\n ref,\n children,\n ...props\n}: DocumentFieldProps) {\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState(() => maskDocumentValue(defaultValue, documentType));\n const [checkInvalid, setCheckInvalid] = useState(false);\n\n const currentValue = isControlled ? value : internalValue;\n // Masking is idempotent, so masking here formats both a raw pre-fill (a controlled `value` seeded\n // from the saved profile) and an already-masked typed value identically.\n const displayValue = maskDocumentValue(currentValue, documentType);\n const showInvalid = invalid || checkInvalid;\n const numericOnly = isDigitOnly(DOCUMENTS[documentType].mask);\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n const masked = maskDocumentValue(event.target.value, documentType);\n if (!isControlled) setInternalValue(masked);\n // Clear a prior check-digit error while typing; it is re-evaluated on the next blur.\n if (checkInvalid) setCheckInvalid(false);\n onValueChange?.(masked);\n }\n\n function handleBlur(event: FocusEvent<HTMLInputElement>) {\n // Validation runs only after the complete number is entered; empty is valid (optional field).\n setCheckInvalid(!isValidDocument(currentValue, documentType));\n onBlur?.(event);\n }\n\n return (\n <DocumentFieldView\n {...props}\n ref={ref}\n className={className}\n name={name}\n label={label}\n placeholder={placeholder}\n disabled={disabled}\n required={requirement === 'mandatory'}\n numericOnly={numericOnly}\n displayValue={displayValue}\n showInvalid={showInvalid}\n errorMessage={errorMessage}\n onChange={handleChange}\n onBlur={handleBlur}\n >\n {children}\n </DocumentFieldView>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Bound — reads the field contract, binds through useController\n// ---------------------------------------------------------------------------\n\ntype BoundDocumentFieldProps = DocumentFieldProps & { contract: FieldContract };\n\nfunction BoundDocumentField({\n value: _value,\n defaultValue: _defaultValue,\n onValueChange,\n onBlur,\n invalid = false,\n errorMessage,\n label,\n placeholder,\n disabled,\n requirement,\n name,\n documentType = 'CPF',\n className,\n ref: callerRef,\n contract,\n children,\n ...props\n}: BoundDocumentFieldProps) {\n // Check digit only. Requiredness is not decided here: `useBoundField` resolves it from the\n // fieldset's baseline and the raise below. Returning the `errorMessage` prop (or a bare `false`\n // when it is unset) keeps today's behaviour: the field goes invalid, and — since the composite's\n // own inline text is driven by the `errorMessage` prop, not by react-hook-form's error message —\n // text renders only when supplied. 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, 'checkDigit', (rawValue) => {\n const raw = typeof rawValue === 'string' ? rawValue : String(rawValue ?? '');\n return isValidDocument(raw, documentType) || (errorMessage ?? false);\n }),\n [contract.rule, documentType, errorMessage],\n );\n\n const field = useBoundField(contract, TEXT_FIELD_VALUE, rule, { required: requirement === 'mandatory' });\n const { getFieldState } = useFormContext();\n const { invalid: rhfInvalid } = getFieldState(contract.name, useFormState({ name: contract.name }));\n\n const composedRef = useComposedRef<HTMLInputElement>(callerRef, field.ref);\n\n const currentValue = typeof field.value === 'string' ? field.value : String(field.value ?? '');\n const displayValue = maskDocumentValue(currentValue, documentType);\n const showInvalid = invalid || rhfInvalid;\n const numericOnly = isDigitOnly(DOCUMENTS[documentType].mask);\n const resolvedLabel = label ?? contract.label;\n const resolvedPlaceholder = placeholder ?? contract.placeholder;\n const resolvedDisabled = disabled ?? contract.disabled ?? false;\n // Unlike `UnboundDocumentField`, `name` carries no signature default here — a signature default\n // would always win over the contract's name (Decision 5), colliding two bound fieldsets (e.g.\n // `profile.document` and `billing.document`) on the same rendered `name=\"document\"`.\n const resolvedName = name ?? contract.name;\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n const masked = maskDocumentValue(event.target.value, documentType);\n field.onChange(masked);\n onValueChange?.(masked);\n }\n\n function handleBlur(event: FocusEvent<HTMLInputElement>) {\n field.onBlur();\n onBlur?.(event);\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={resolvedDisabled}\n readOnly={contract.readOnly}\n autoComplete={contract.autoComplete}\n inputMode={contract.inputMode}\n >\n <DocumentFieldView\n {...props}\n ref={composedRef}\n className={className}\n name={resolvedName}\n label={resolvedLabel}\n placeholder={resolvedPlaceholder}\n disabled={resolvedDisabled}\n required={field.required}\n numericOnly={numericOnly}\n displayValue={displayValue}\n showInvalid={showInvalid}\n errorMessage={errorMessage}\n onChange={handleChange}\n onBlur={handleBlur}\n >\n {children}\n </DocumentFieldView>\n </FieldBinding>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAwFA,SAAgB,YAAY,OAAwB;CAClD,MAAM,SAAS,MAAM,QAAQ,WAAW,EAAE;CAE1C,IAAI,OAAO,WAAW,MAAM,aAAa,KAAK,MAAM,GAClD,OAAO;CAGT,MAAM,SAAS,OAAO,MAAM,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,EAAE;CAC/C,MAAM,QAAQ,UACV,OAAO,MAAM,GAAG,QAAQ,EAAE,CAAC,CAAC,QAAQ,KAAK,IAAI,UAAU,MAAM,MAAM,QAAQ,QAAQ,CAAC,IAAI,KAAM,KAAM;CAExG,OAAO,KAAK,EAAE,MAAM,OAAO,MAAM,KAAK,EAAE,MAAM,OAAO;AACvD;AAOA,MAAa,YAAgD,EAC3D,KAAK;CACH,IAAI;CACJ,MAAM;CACN,MAAM;CACN,UAAU;AACZ,EACF;;;;;;;;;;AAWA,SAAgB,wBAAwB,MAAqC;CAC3E,OAAO,OAAO,SAAS,YAAY,OAAO,OAAO,WAAW,IAAI;AAClE;;;;;;AAOA,SAAgB,kBAAkB,UAAkB,cAAoC;CACtF,MAAM,OAAO,UAAU;CACvB,MAAM,YAAY,YAAY,KAAK,IAAI,IAAI,SAAS,QAAQ,OAAO,EAAE,IAAI;CACzE,MAAM,WAAW,KAAK,IAAI,GAAG,KAAK,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,UAAU,CAAC;CACjE,OAAO,UAAU,UAAU,MAAM,GAAG,QAAQ,GAAG,KAAK,IAAI;AAC1D;;;;;;AAOA,SAAgB,gBAAgB,OAAe,cAAqC;CAClF,IAAI,CAAC,MAAM,KAAK,GAAG,OAAO;CAC1B,OAAO,UAAU,aAAa,CAAC,SAAS,KAAK;AAC/C;AAMA,MAAa,0BAA0B,gBAAoC;CACzE,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAAkB,UAAU;CAAU;CACvD,QAAQ;EACN,OAAO;GAAE,MAAM;GAAU,OAAO;EAAQ;EACxC,aAAa;GAAE,MAAM;GAAU,OAAO;EAAc;EACpD,cAAc;GAAE,MAAM;GAAU,OAAO;EAAgB;EACvD,cAAc;GAAE,MAAM;GAAU,SAAS;GAAO,OAAO;EAAgB;EACvE,aAAa;GAAE,MAAM,CAAC,aAAa,UAAU;GAAY,OAAO;EAAc;EAC9E,UAAU;GAAE,MAAM;GAAW,SAAS;GAAO,OAAO;EAAW;CACjE;CACA,WACE;AACJ,CAAC;;;;;;;;;;;;;;;AAgBD,SAAgB,cAAc,OAAsC;CAClE,MAAM,WAAW,SAAS;CAC1B,MAAM,cAAc,eAAe;CAEnC,IAAI,YAAY,aACd,OAAO,oBAAC,oBAAD;EAAoB,GAAI;EAAiB;CAAW,CAAA;CAG7D,OAAO,oBAAC,sBAAD,EAAsB,GAAI,MAAQ,CAAA;AAC3C;AAuBA,MAAM,4BAA4B,cAAqD,IAAI;AAE3F,SAAS,+BAA+D;CACtE,MAAM,UAAU,WAAW,yBAAyB;CACpD,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,2DAA2D;CAE7E,OAAO;AACT;AAIA,MAAa,+BAA+B,gBAAyC;CACnF,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAAwB,UAAU;CAAS;CAC5D,QAAQ,CAAC;CACT,WACE;AACJ,CAAC;;AAGD,SAAgB,mBAAmB,EAAE,aAAiD;CACpF,MAAM,EAAE,KAAK,MAAM,OAAO,aAAa,UAAU,UAAU,aAAa,UAAU,WAChF,6BAA6B;CAE/B,OACE,oBAACA,MAAU,SAAX;EACO;EACC;EAIN,iBAAe,YAAY,KAAA;EACd;EACH;EACH;EACP,GAAK,cAAc,EAAE,WAAW,UAAmB,IAAI,CAAC;EAC9C;EACF;EACG;EACX,yBAAsB;CACvB,CAAA;AAEL;AAyBA,SAAS,kBAAkB,EACzB,WACA,MACA,OACA,aACA,UACA,UACA,aACA,cACA,aACA,cACA,UACA,QACA,KACA,UACA,GAAG,SACsB;CACzB,MAAM,eAAe,eACZ;EAAE;EAAK;EAAM,OAAO;EAAc;EAAa;EAAU;EAAU;EAAa;EAAU;CAAO,IACxG;EAAC;EAAK;EAAM;EAAc;EAAa;EAAU;EAAU;EAAa;EAAU;CAAM,CAC1F;CAEA,OAME,oBAACA,MAAU,MAAX;EACE,GAAI;EACO;EACL;EACN,SAAS;EACC;EACV,0BAAuB;EACvB,sBAAmB;EAEnB,UAAA,oBAAC,0BAA0B,UAA3B;GAAoC,OAAO;GACxC,UAAA,YACC,qBAAA,UAAA,EAAA,UAAA;IACG,QAAQ,oBAACA,MAAU,OAAX;KAAiB,uBAAoB;KAAI,UAAA;IAAuB,CAAA,IAAI;IAC7E,oBAAC,oBAAD,CAAqB,CAAA;IACpB,eAAe,eACd,oBAACA,MAAU,OAAX;KAAiB,OAAA;KAAM,uBAAoB;KACxC,UAAA;IACc,CAAA,IACf;GACJ,EAAA,CAAA;EAE8B,CAAA;CACtB,CAAA;AAEpB;AAMA,SAAS,qBAAqB,EAC5B,OACA,eAAe,IACf,eACA,QACA,UAAU,OACV,cACA,OACA,aACA,WAAW,OACX,aACA,OAAO,YACP,eAAe,OACf,WACA,KACA,UACA,GAAG,SACkB;CACrB,MAAM,eAAe,UAAU,KAAA;CAC/B,MAAM,CAAC,eAAe,oBAAoB,eAAe,kBAAkB,cAAc,YAAY,CAAC;CACtG,MAAM,CAAC,cAAc,mBAAmB,SAAS,KAAK;CAEtD,MAAM,eAAe,eAAe,QAAQ;CAG5C,MAAM,eAAe,kBAAkB,cAAc,YAAY;CACjE,MAAM,cAAc,WAAW;CAC/B,MAAM,cAAc,YAAY,UAAU,aAAa,CAAC,IAAI;CAE5D,SAAS,aAAa,OAAsC;EAC1D,MAAM,SAAS,kBAAkB,MAAM,OAAO,OAAO,YAAY;EACjE,IAAI,CAAC,cAAc,iBAAiB,MAAM;EAE1C,IAAI,cAAc,gBAAgB,KAAK;EACvC,gBAAgB,MAAM;CACxB;CAEA,SAAS,WAAW,OAAqC;EAEvD,gBAAgB,CAAC,gBAAgB,cAAc,YAAY,CAAC;EAC5D,SAAS,KAAK;CAChB;CAEA,OACE,oBAAC,mBAAD;EACE,GAAI;EACC;EACM;EACL;EACC;EACM;EACH;EACV,UAAU,gBAAgB;EACb;EACC;EACD;EACC;EACd,UAAU;EACV,QAAQ;EAEP;CACgB,CAAA;AAEvB;AAQA,SAAS,mBAAmB,EAC1B,OAAO,QACP,cAAc,eACd,eACA,QACA,UAAU,OACV,cACA,OACA,aACA,UACA,aACA,MACA,eAAe,OACf,WACA,KAAK,WACL,UACA,UACA,GAAG,SACuB;CAO1B,MAAM,OAAO,cAET,oBAAoB,SAAS,MAAM,eAAe,aAAa;EAE7D,OAAO,gBADK,OAAO,aAAa,WAAW,WAAW,OAAO,YAAY,EAAE,GAC/C,YAAY,MAAM,gBAAgB;CAChE,CAAC,GACH;EAAC,SAAS;EAAM;EAAc;CAAY,CAC5C;CAEA,MAAM,QAAQ,cAAc,UAAU,kBAAkB,MAAM,EAAE,UAAU,gBAAgB,YAAY,CAAC;CACvG,MAAM,EAAE,kBAAkB,eAAe;CACzC,MAAM,EAAE,SAAS,eAAe,cAAc,SAAS,MAAM,aAAa,EAAE,MAAM,SAAS,KAAK,CAAC,CAAC;CAElG,MAAM,cAAc,eAAiC,WAAW,MAAM,GAAG;CAGzE,MAAM,eAAe,kBADA,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ,OAAO,MAAM,SAAS,EAAE,GACxC,YAAY;CACjE,MAAM,cAAc,WAAW;CAC/B,MAAM,cAAc,YAAY,UAAU,aAAa,CAAC,IAAI;CAC5D,MAAM,gBAAgB,SAAS,SAAS;CACxC,MAAM,sBAAsB,eAAe,SAAS;CACpD,MAAM,mBAAmB,YAAY,SAAS,YAAY;CAI1D,MAAM,eAAe,QAAQ,SAAS;CAEtC,SAAS,aAAa,OAAsC;EAC1D,MAAM,SAAS,kBAAkB,MAAM,OAAO,OAAO,YAAY;EACjE,MAAM,SAAS,MAAM;EACrB,gBAAgB,MAAM;CACxB;CAEA,SAAS,WAAW,OAAqC;EACvD,MAAM,OAAO;EACb,SAAS,KAAK;CAChB;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,mBAAD;GACE,GAAI;GACJ,KAAK;GACM;GACX,MAAM;GACN,OAAO;GACP,aAAa;GACb,UAAU;GACV,UAAU,MAAM;GACH;GACC;GACD;GACC;GACd,UAAU;GACV,QAAQ;GAEP;EACgB,CAAA;CACP,CAAA;AAElB"}
|
|
1
|
+
{"version":3,"file":"document-field.js","names":["BaseField"],"sources":["../../../src/particles/document-field/document-field.tsx"],"sourcesContent":["'use client';\nimport { Field as BaseField } from '@base-ui/react/field';\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ChangeEvent, ComponentPropsWithRef, 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 { useComposedRef } from '../shared/compose-refs.js';\nimport { applyMask, countSlots, isDigitOnly } from '../shared/input-mask.js';\n\n// `applyMask` was public from this module before the engine moved out; keep the export path stable.\nexport { applyMask } from '../shared/input-mask.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type DocumentType = 'CPF' | 'SSN' | 'SIN' | 'RFC';\n\ntype DocumentFieldRequirement = 'mandatory' | 'optional';\n\nexport type DocumentSpec = {\n id: DocumentType;\n name: string;\n mask: string;\n placeholder: string;\n /** Strips what the type never holds, before the mask runs. */\n sanitize: (raw: string) => string;\n validate: (value: string) => boolean;\n /** `'off'` for SSN and SIN, absent for CPF and RFC (Decision 9). */\n autoComplete?: 'off';\n};\n\n// `dangerouslySetInnerHTML` is excluded — the rest spread this props type feeds forwards straight to\n// `Field.Root`, and a schema-authored `page.json` can supply it with no allowlist in between.\nexport type DocumentFieldProps = Omit<\n ComponentPropsWithRef<'div'>,\n 'defaultValue' | 'value' | 'onChange' | 'onBlur' | 'ref' | 'dangerouslySetInnerHTML'\n> & {\n /** Unused on the bound path — react-hook-form owns the value. */\n value?: string;\n /** Unused on the bound path — the field contract's `defaultValue` seeds it instead. */\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n onBlur?: (event: FocusEvent<HTMLInputElement>) => void;\n invalid?: boolean;\n errorMessage?: string;\n /** Falls back to the field contract's `label` when bound. */\n label?: string;\n /** Falls back to the field contract's `placeholder` when bound. */\n placeholder?: string;\n /** Falls back to the field contract's `disabled` when bound. */\n disabled?: boolean;\n /**\n * Raises the field to required, the same word `PhoneField` uses. It only ever raises: bound to a\n * fieldset whose rule already says required, `'optional'` does not lower it. Left unset it is no\n * opinion, which keeps CPF optional by recommendation.\n */\n requirement?: DocumentFieldRequirement;\n name?: string;\n documentType?: DocumentType;\n /**\n * Lands on the `<input>` `Field.Control` renders — not on the wrapper `<div>`, as it did before\n * (a deliberate, source-breaking re-route: the previous ref pointed at an untabbable div). Composed\n * with react-hook-form's own ref on the bound path.\n */\n ref?: Ref<HTMLInputElement>;\n /**\n * Given, replaces the default `Field.Label` + `DocumentFieldInput` + `Field.Error` anatomy — any\n * order, any subset. `DocumentFieldInput` is the one part that carries the mask, the composed ref\n * and the particle's own value/handlers; a composed generic `Field.Control` would call\n * `useController` a second time for the same name (RFC's named, accepted double-binder hole).\n */\n children?: ReactNode;\n};\n\n// ---------------------------------------------------------------------------\n// Ported check-digit validation (fastcheckout `packages/libs/validators/src/document`).\n// ---------------------------------------------------------------------------\n\n/**\n * CPF check-digit validation, ported from the legacy `validateCPF`. Strips non-digits, requires\n * exactly 11 digits, rejects all-equal sequences (e.g. `111.111.111-11`), and verifies both check\n * digits. Runs on blur/submit only, never per keystroke.\n */\nexport function validateCPF(value: string): boolean {\n const digits = value.replaceAll(/[^\\d]+/g, '');\n\n if (digits.length !== 11 || /(\\d)\\1{10}/.test(digits)) {\n return false;\n }\n\n const values = digits.split('').map((el) => +el);\n const rest = (count: number) =>\n ((values.slice(0, count - 12).reduce((sum, el, index) => sum + el * (count - index), 0) * 10) % 11) % 10;\n\n return rest(10) === values[9] && rest(11) === values[10];\n}\n\n/**\n * SSN validation, ported from `@vtex/country-forms` 1.2.0 (measured 2026-10-16). Strips non-digits,\n * requires exactly 9 digits, refuses area `000`, `666` and `>= 900`, group `00` and serial `0000`.\n */\nexport function validateSSN(value: string): boolean {\n const digits = value.replaceAll(/\\D/g, '');\n if (digits.length !== 9) return false;\n const area = digits.slice(0, 3);\n if (area === '000' || area === '666' || Number(area) >= 900) return false;\n if (digits.slice(3, 5) === '00') return false;\n return digits.slice(5) !== '0000';\n}\n\n/**\n * SIN validation, ported from `@vtex/country-forms` 1.2.0 (measured 2026-10-16). Strips non-digits,\n * requires exactly 9 digits, refuses all zeros, and verifies the Luhn check.\n */\nexport function validateSIN(value: string): boolean {\n const digits = value.replaceAll(/\\D/g, '');\n if (digits.length !== 9 || /^0+$/.test(digits)) return false;\n let sum = 0;\n for (let index = 0; index < 9; index += 1) {\n let digit = Number(digits[index]);\n if (index % 2 === 1) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n }\n return sum % 10 === 0;\n}\n\n/**\n * RFC (individual) validation, ported from `@vtex/country-forms` 1.2.0 (measured 2026-10-16): after\n * uppercasing and stripping every non A-Z0-9 character it is four letters, six digits and three\n * letters or digits, and characters 5-10 read as a plausible month (1-12) and day (1-31). The day check\n * is not calendar-aware, as in the library. The library's set of refused four-letter prefixes is not\n * carried (the structure and the date are what a typo breaks).\n */\nexport function validateRFC(value: string): boolean {\n const rfc = value.toUpperCase().replaceAll(/[^A-Z0-9]/g, '');\n if (!/^[A-Z]{4}\\d{6}[A-Z0-9]{3}$/.test(rfc)) return false;\n const month = Number(rfc.slice(6, 8));\n const day = Number(rfc.slice(8, 10));\n return month >= 1 && month <= 12 && day >= 1 && day <= 31;\n}\n\nfunction stripNonDigits(raw: string): string {\n return raw.replaceAll(/\\D/g, '');\n}\n\n// ---------------------------------------------------------------------------\n// Document table: the person documents of the four countries `Payment.countries` lists (CPF for BRA, SSN\n// for USA, SIN for CAN, RFC for MEX). Masks, rules and sanitisers follow `@vtex/country-forms` 1.2.0,\n// measured 2026-10-16; a later library release can drift from this hand port. `documentType` selects the\n// mask, the sanitiser, the validator and the digit-only input mode.\n// ---------------------------------------------------------------------------\n\nexport const DOCUMENTS: Record<DocumentType, DocumentSpec> = {\n CPF: {\n id: 'CPF',\n name: 'CPF',\n mask: '999.999.999-99',\n placeholder: '000.000.000-00',\n sanitize: stripNonDigits,\n validate: validateCPF,\n },\n SSN: {\n id: 'SSN',\n name: 'SSN',\n mask: '999-99-9999',\n placeholder: '000-00-0000',\n sanitize: stripNonDigits,\n validate: validateSSN,\n autoComplete: 'off',\n },\n SIN: {\n id: 'SIN',\n name: 'SIN',\n mask: '999-999-999',\n placeholder: '000-000-000',\n sanitize: stripNonDigits,\n validate: validateSIN,\n autoComplete: 'off',\n },\n RFC: {\n id: 'RFC',\n name: 'RFC',\n mask: 'SSSSSSSSSSSSS',\n placeholder: 'AAAA000000AAA',\n // Before `applyMask`, never after: its `S` slot spans `[A-ú]`, which accepts `é`, `_` and `~`.\n sanitize: (raw) => raw.toUpperCase().replaceAll(/[^A-Z0-9]/g, ''),\n validate: validateRFC,\n },\n};\n\nconst DOCUMENT_TYPE_BY_API_ID: Readonly<Record<string, DocumentType>> = {\n cpf: 'CPF',\n ssn: 'SSN',\n sin: 'SIN',\n rfc: 'RFC',\n};\n\n/**\n * Turns the API's lower-case document id (`Payment.countries[].documents[].type`) into this table's key,\n * or `null` for anything else, including a business document, a prototype key and a non-string.\n */\nexport function documentTypeFromId(id: unknown): DocumentType | null {\n if (typeof id !== 'string' || !Object.hasOwn(DOCUMENT_TYPE_BY_API_ID, id)) return null;\n return DOCUMENT_TYPE_BY_API_ID[id] ?? null;\n}\n\n/**\n * True when `type` is one of the table's upper-case keys (`CPF`, `SSN`, `SIN`, `RFC`); the API's lower-case\n * ids go through `documentTypeFromId`. Lets a host gate the field by locale.\n *\n * `Object.hasOwn`, not the `in` operator: `in` walks the prototype chain, so `constructor`,\n * `__proto__` and `toString` all satisfied it and were then trusted as a `DocumentType` by callers\n * (`client-profile-fieldset.tsx` renders the field on the strength of this narrowing). The value is\n * author-only — a literal written into `page.json`, never a runtime expression — so this is\n * robustness rather than a reachable defect, but the narrowing should not be able to lie.\n */\nexport function isSupportedDocumentType(type: unknown): type is DocumentType {\n return typeof type === 'string' && Object.hasOwn(DOCUMENTS, type);\n}\n\n/**\n * Apply a document type's mask to raw input: run the type's sanitiser, then truncate to the mask's slot\n * count so excess characters never trail past the mask (e.g. a 15-digit paste into the 11-slot CPF mask\n * yields `111.444.777-35`, not `111.444.777-358888`).\n */\nexport function maskDocumentValue(rawValue: string, documentType: DocumentType): string {\n const spec = DOCUMENTS[documentType];\n const maxSlots = Math.max(...spec.mask.split('|').map(countSlots));\n return applyMask(spec.sanitize(rawValue).slice(0, maxSlots), spec.mask);\n}\n\n/**\n * Check-digit validity for a document value. An **empty** value is valid (the field is optional),\n * mirroring the legacy `validateCardholderDocument`; a non-empty value must pass the document\n * type's check-digit validation.\n */\nexport function isValidDocument(value: string, documentType: DocumentType): boolean {\n if (!value.trim()) return true;\n return DOCUMENTS[documentType].validate(value);\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport const DocumentFieldDefinition = defineComponent<DocumentFieldProps>({\n name: 'DocumentField',\n importPath: '@vtex/faststore/components',\n component: DocumentField,\n providesContext: 'document-field',\n editor: { label: 'Document Field', category: 'content' },\n schema: {\n label: { type: 'string', label: 'Label' },\n placeholder: { type: 'string', label: 'Placeholder' },\n errorMessage: { type: 'string', label: 'Error message' },\n documentType: { type: 'string', default: 'CPF', label: 'Document type' },\n requirement: { type: ['mandatory', 'optional'] as const, label: 'Requirement' },\n disabled: { type: 'boolean', default: false, label: 'Disabled' },\n },\n guideline:\n 'Presentational tax-document input composing the Field particle; applies the mask of its document type on change and runs the matching validation on blur/submit; documentType is one of CPF, SSN, SIN or RFC. Data-agnostic (value/defaultValue/onValueChange); a host wires it to the shopper profile. The document is optional by default: requirement only ever raises the field to required, announced as aria-required, and bound to a fieldset whose rule already says required it cannot lower it back. Recomposable (RFC:503): given children, they replace the default Field.Label + DocumentFieldInput + Field.Error anatomy, in any order.',\n});\n\n/**\n * Presentational tax-document input (particle). Composes the `Field` particle (`Field.Root` +\n * `Field.Label` + `Field.Control` + `Field.Error`) and owns the locale mask (applied progressively on\n * every change, never blocking typing) plus check-digit validation (run on blur/submit only — never\n * per keystroke). An empty value is valid (the field is optional). It surfaces `errorMessage` inline\n * when the check digit fails or when the host forces `invalid` (e.g. a server error surfaced by the\n * form that owns the write). It consumes no GraphQL and no domain context — value flows through\n * `value`/`defaultValue`/`onValueChange`, and `documentType` selects the mask + validator.\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 * `BoundDocumentField`, so hook order never changes under a mounted component. Both sub-components\n * render the same `DocumentFieldView`, so the two paths cannot drift into different DOM.\n */\nexport function DocumentField(props: DocumentFieldProps): ReactNode {\n const contract = useField();\n const formContext = useFormContext();\n\n if (contract && formContext) {\n return <BoundDocumentField {...props} contract={contract} />;\n }\n\n return <UnboundDocumentField {...props} />;\n}\n\n// ---------------------------------------------------------------------------\n// Input part — catalogued, placeable (Decision 4). Carries the mask, the composed ref, and the\n// particle's own onChange/onBlur. Renders the RAW Base UI Field.Control, not this package's own\n// Field.Control wrapper — the latter would see the real ambient contract Decision 3 now provides\n// and call useController a second time for the same name, overwriting the composite's masked value\n// (the exact double-registration bug the removed FieldContractBoundary used to prevent globally).\n// ---------------------------------------------------------------------------\n\ntype DocumentFieldInputContextValue = {\n ref?: Ref<HTMLInputElement>;\n name?: string;\n value: string;\n placeholder?: string;\n disabled: boolean;\n /** Resolved by the binder, threaded here because this part is not the one that binds. */\n required: boolean;\n numericOnly: boolean;\n autoComplete?: 'off';\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: (event: FocusEvent<HTMLInputElement>) => void;\n};\n\nconst DocumentFieldInputContext = createContext<DocumentFieldInputContextValue | null>(null);\n\nfunction useDocumentFieldInputContext(): DocumentFieldInputContextValue {\n const context = useContext(DocumentFieldInputContext);\n if (!context) {\n throw new Error('DocumentFieldInput must be a descendant of DocumentField.');\n }\n return context;\n}\n\nexport type DocumentFieldInputProps = { className?: string };\n\nexport const DocumentFieldInputDefinition = defineComponent<DocumentFieldInputProps>({\n name: 'DocumentFieldInput',\n importPath: '@vtex/faststore/components',\n component: DocumentFieldInput,\n requiresContext: 'document-field',\n editor: { label: 'Document Field Input', category: 'action' },\n schema: {},\n guideline:\n \"The masked document <input> DocumentField owns. Must sit inside DocumentField, in either the default anatomy or an author's composed children. Carries the locale mask, the composed ref, and DocumentField'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 document `<input>`, reading its value/handlers/ref from the enclosing `DocumentField`. */\nexport function DocumentFieldInput({ className }: DocumentFieldInputProps): ReactNode {\n const { ref, name, value, placeholder, disabled, required, numericOnly, autoComplete, onChange, onBlur } =\n useDocumentFieldInputContext();\n\n return (\n <BaseField.Control\n ref={ref}\n name={name}\n // `aria-required`, not native `required`, for the reason password-field.tsx:89-91 records:\n // this is a Base UI `Field.Control`, and native constraint tracking would flip `aria-invalid`\n // on its own, ahead of react-hook-form's own validation.\n aria-required={required || undefined}\n placeholder={placeholder}\n disabled={disabled}\n value={value}\n autoComplete={autoComplete}\n {...(numericOnly ? { inputMode: 'numeric' as const } : {})}\n onChange={onChange}\n onBlur={onBlur}\n className={className}\n data-fs-field-control=\"\"\n />\n );\n}\n\n// ---------------------------------------------------------------------------\n// Shared view — identical DOM whether bound or unbound\n// ---------------------------------------------------------------------------\n\ntype DocumentFieldViewProps = Omit<\n ComponentPropsWithRef<'div'>,\n 'defaultValue' | 'value' | 'onChange' | 'onBlur' | 'ref'\n> & {\n ref?: Ref<HTMLInputElement>;\n name?: string;\n label?: string;\n placeholder?: string;\n disabled: boolean;\n required: boolean;\n numericOnly: boolean;\n autoComplete?: 'off';\n displayValue: string;\n showInvalid: boolean;\n errorMessage?: string;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: (event: FocusEvent<HTMLInputElement>) => void;\n children?: ReactNode;\n};\n\nfunction DocumentFieldView({\n className,\n name,\n label,\n placeholder,\n disabled,\n required,\n numericOnly,\n autoComplete,\n displayValue,\n showInvalid,\n errorMessage,\n onChange,\n onBlur,\n ref,\n children,\n ...props\n}: DocumentFieldViewProps) {\n const inputContext = useMemo<DocumentFieldInputContextValue>(\n () => ({\n ref,\n name,\n value: displayValue,\n placeholder,\n disabled,\n required,\n numericOnly,\n autoComplete,\n onChange,\n onBlur,\n }),\n [ref, name, displayValue, placeholder, disabled, required, numericOnly, autoComplete, onChange, onBlur],\n );\n\n return (\n // Deliberately the RAW Base UI Field.Root/Label/Error, not this package's own Field.* wrapper,\n // for the default anatomy — reproduces exactly what rendered before FieldContractBoundary was\n // removed (Decision 3), including the host `invalid`/`errorMessage` override working\n // unconditionally. Composed children, below, use the package's own Field.* parts on purpose —\n // that is what makes a childless Field.Label / Field.Error resolve real text (FR-5).\n <BaseField.Root\n {...props}\n className={className}\n name={name}\n invalid={showInvalid}\n disabled={disabled}\n data-fs-document-field=\"\"\n data-fs-field-root=\"\"\n >\n <DocumentFieldInputContext.Provider value={inputContext}>\n {children ?? (\n <>\n {label ? <BaseField.Label data-fs-field-label=\"\">{label}</BaseField.Label> : null}\n <DocumentFieldInput />\n {showInvalid && errorMessage ? (\n <BaseField.Error match data-fs-field-error=\"\">\n {errorMessage}\n </BaseField.Error>\n ) : null}\n </>\n )}\n </DocumentFieldInputContext.Provider>\n </BaseField.Root>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Unbound — today's body, moved verbatim\n// ---------------------------------------------------------------------------\n\nfunction UnboundDocumentField({\n value,\n defaultValue = '',\n onValueChange,\n onBlur,\n invalid = false,\n errorMessage,\n label,\n placeholder,\n disabled = false,\n requirement,\n name = 'document',\n documentType = 'CPF',\n className,\n ref,\n children,\n ...props\n}: DocumentFieldProps) {\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState(() => maskDocumentValue(defaultValue, documentType));\n const [checkInvalid, setCheckInvalid] = useState(false);\n\n const currentValue = isControlled ? value : internalValue;\n // Masking is idempotent, so masking here formats both a raw pre-fill (a controlled `value` seeded\n // from the saved profile) and an already-masked typed value identically.\n const displayValue = maskDocumentValue(currentValue, documentType);\n const showInvalid = invalid || checkInvalid;\n const numericOnly = isDigitOnly(DOCUMENTS[documentType].mask);\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n const masked = maskDocumentValue(event.target.value, documentType);\n if (!isControlled) setInternalValue(masked);\n // Clear a prior check-digit error while typing; it is re-evaluated on the next blur.\n if (checkInvalid) setCheckInvalid(false);\n onValueChange?.(masked);\n }\n\n function handleBlur(event: FocusEvent<HTMLInputElement>) {\n // Validation runs only after the complete number is entered; empty is valid (optional field).\n setCheckInvalid(!isValidDocument(currentValue, documentType));\n onBlur?.(event);\n }\n\n return (\n <DocumentFieldView\n {...props}\n ref={ref}\n className={className}\n name={name}\n label={label}\n placeholder={placeholder}\n disabled={disabled}\n required={requirement === 'mandatory'}\n numericOnly={numericOnly}\n autoComplete={DOCUMENTS[documentType].autoComplete}\n displayValue={displayValue}\n showInvalid={showInvalid}\n errorMessage={errorMessage}\n onChange={handleChange}\n onBlur={handleBlur}\n >\n {children}\n </DocumentFieldView>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Bound — reads the field contract, binds through useController\n// ---------------------------------------------------------------------------\n\ntype BoundDocumentFieldProps = DocumentFieldProps & { contract: FieldContract };\n\nfunction BoundDocumentField({\n value: _value,\n defaultValue: _defaultValue,\n onValueChange,\n onBlur,\n invalid = false,\n errorMessage,\n label,\n placeholder,\n disabled,\n requirement,\n name,\n documentType = 'CPF',\n className,\n ref: callerRef,\n contract,\n children,\n ...props\n}: BoundDocumentFieldProps) {\n // Check digit only. Requiredness is not decided here: `useBoundField` resolves it from the\n // fieldset's baseline and the raise below. Returning the `errorMessage` prop (or a bare `false`\n // when it is unset) keeps today's behaviour: the field goes invalid, and — since the composite's\n // own inline text is driven by the `errorMessage` prop, not by react-hook-form's error message —\n // text renders only when supplied. 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, 'checkDigit', (rawValue) => {\n const raw = typeof rawValue === 'string' ? rawValue : String(rawValue ?? '');\n return isValidDocument(raw, documentType) || (errorMessage ?? false);\n }),\n [contract.rule, documentType, errorMessage],\n );\n\n const field = useBoundField(contract, TEXT_FIELD_VALUE, rule, { required: requirement === 'mandatory' });\n const { getFieldState } = useFormContext();\n const { invalid: rhfInvalid } = getFieldState(contract.name, useFormState({ name: contract.name }));\n\n const composedRef = useComposedRef<HTMLInputElement>(callerRef, field.ref);\n\n const currentValue = typeof field.value === 'string' ? field.value : String(field.value ?? '');\n const displayValue = maskDocumentValue(currentValue, documentType);\n const showInvalid = invalid || rhfInvalid;\n const numericOnly = isDigitOnly(DOCUMENTS[documentType].mask);\n const resolvedLabel = label ?? contract.label;\n const resolvedPlaceholder = placeholder ?? contract.placeholder;\n const resolvedDisabled = disabled ?? contract.disabled ?? false;\n // Unlike `UnboundDocumentField`, `name` carries no signature default here — a signature default\n // would always win over the contract's name (Decision 5), colliding two bound fieldsets (e.g.\n // `profile.document` and `billing.document`) on the same rendered `name=\"document\"`.\n const resolvedName = name ?? contract.name;\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n const masked = maskDocumentValue(event.target.value, documentType);\n field.onChange(masked);\n onValueChange?.(masked);\n }\n\n function handleBlur(event: FocusEvent<HTMLInputElement>) {\n field.onBlur();\n onBlur?.(event);\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={resolvedDisabled}\n readOnly={contract.readOnly}\n autoComplete={contract.autoComplete}\n inputMode={contract.inputMode}\n >\n <DocumentFieldView\n {...props}\n ref={composedRef}\n className={className}\n name={resolvedName}\n label={resolvedLabel}\n placeholder={resolvedPlaceholder}\n disabled={resolvedDisabled}\n required={field.required}\n numericOnly={numericOnly}\n autoComplete={DOCUMENTS[documentType].autoComplete}\n displayValue={displayValue}\n showInvalid={showInvalid}\n errorMessage={errorMessage}\n onChange={handleChange}\n onBlur={handleBlur}\n >\n {children}\n </DocumentFieldView>\n </FieldBinding>\n );\n}\n"],"mappings":"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"}
|
|
@@ -619,6 +619,6 @@ const Field$1 = {
|
|
|
619
619
|
Checkbox: FieldCheckbox
|
|
620
620
|
};
|
|
621
621
|
//#endregion
|
|
622
|
-
export { BOOLEAN_FIELD_VALUE, Field$1 as Field, FieldBinding, FieldCheckbox, FieldCheckboxDefinition, FieldControl, FieldControlDefinition, FieldDescription, FieldDescriptionDefinition, FieldError, FieldErrorDefinition, FieldLabel, FieldLabelDefinition, FieldRoot, FieldRootDefinition, FieldValidity, FieldValidityDefinition, FieldsetFieldContext, TEXT_FIELD_VALUE, mergeFieldValidator, resolveRequiredness, useBoundField, useField, useFieldsetContext, useFieldsetField, useFieldsetFieldNames, useNoAncestorFieldset };
|
|
622
|
+
export { BOOLEAN_FIELD_VALUE, Field$1 as Field, FieldBinding, FieldCheckbox, FieldCheckboxDefinition, FieldControl, FieldControlDefinition, FieldDescription, FieldDescriptionDefinition, FieldError, FieldErrorDefinition, FieldLabel, FieldLabelDefinition, FieldRoot, FieldRootDefinition, FieldValidity, FieldValidityDefinition, FieldsetFieldContext, TEXT_FIELD_VALUE, mergeFieldValidator, readBaseline, resolveRequiredness, useBoundField, useField, useFieldsetContext, useFieldsetField, useFieldsetFieldNames, useNoAncestorFieldset };
|
|
623
623
|
|
|
624
624
|
//# sourceMappingURL=field.js.map
|