@vtex/faststore 0.0.1
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 +18 -0
- package/LICENSE +21 -0
- package/README.md +95 -0
- package/dist/actions.json +334 -0
- package/dist/catalog.json +6615 -0
- package/dist/client.d.ts +17 -0
- package/dist/client.js +8 -0
- package/dist/components.d.ts +87 -0
- package/dist/components.js +87 -0
- package/dist/content-types.json +684 -0
- package/dist/core/dist/actions/mock-action.d.ts +24 -0
- package/dist/core/dist/actions/mock-action.js +28 -0
- package/dist/core/dist/actions/mock-action.js.map +1 -0
- package/dist/core/dist/actions/registry.d.ts +24 -0
- package/dist/core/dist/actions/registry.js +28 -0
- package/dist/core/dist/actions/registry.js.map +1 -0
- package/dist/core/dist/define-component.d.ts +100 -0
- package/dist/core/dist/define-component.js +8 -0
- package/dist/core/dist/define-component.js.map +1 -0
- package/dist/core/dist/define-content-type.d.ts +95 -0
- package/dist/core/dist/define-content-type.js +283 -0
- package/dist/core/dist/define-content-type.js.map +1 -0
- package/dist/core/dist/index.d.ts +7 -0
- package/dist/core/dist/index.js +5 -0
- package/dist/core/dist/schema/generated/schema.d.ts +28 -0
- package/dist/core/dist/types.d.ts +1 -0
- package/dist/docs/access-code-field.md +100 -0
- package/dist/docs/access-code-sign-in.md +174 -0
- package/dist/docs/account-entry-point.md +155 -0
- package/dist/docs/address-summary.md +50 -0
- package/dist/docs/buy-button.md +162 -0
- package/dist/docs/carousel.md +105 -0
- package/dist/docs/cart-item.md +162 -0
- package/dist/docs/cart-totalizer.md +197 -0
- package/dist/docs/cart.md +495 -0
- package/dist/docs/client-preferences.md +184 -0
- package/dist/docs/client-profile-form.md +192 -0
- package/dist/docs/client-profile.md +117 -0
- package/dist/docs/container.md +97 -0
- package/dist/docs/document-field.md +97 -0
- package/dist/docs/email-field.md +93 -0
- package/dist/docs/email-identification.md +102 -0
- package/dist/docs/footer-copyright.md +112 -0
- package/dist/docs/footer-link-group.md +162 -0
- package/dist/docs/footer-root.md +145 -0
- package/dist/docs/footer-social.md +151 -0
- package/dist/docs/free-shipping-progress.md +87 -0
- package/dist/docs/gallery.md +84 -0
- package/dist/docs/header-root.md +150 -0
- package/dist/docs/identity-edit.md +88 -0
- package/dist/docs/identity-summary.md +106 -0
- package/dist/docs/incentives.md +151 -0
- package/dist/docs/logo.md +135 -0
- package/dist/docs/meter.md +67 -0
- package/dist/docs/navigation-link-list.md +171 -0
- package/dist/docs/navigation-link.md +163 -0
- package/dist/docs/navigation-menu.md +264 -0
- package/dist/docs/payment-methods.md +139 -0
- package/dist/docs/phone-field.md +106 -0
- package/dist/docs/postal-code-field.md +126 -0
- package/dist/docs/pricing.md +499 -0
- package/dist/docs/product-gallery.md +409 -0
- package/dist/docs/product-information.md +295 -0
- package/dist/docs/product-list.md +170 -0
- package/dist/docs/product-quantity.md +88 -0
- package/dist/docs/product-shelf.md +141 -0
- package/dist/docs/promotion.md +109 -0
- package/dist/docs/region.md +225 -0
- package/dist/docs/session.md +123 -0
- package/dist/docs/shipping-address.md +390 -0
- package/dist/docs/shipping-simulator.md +147 -0
- package/dist/docs/sign-in-form.md +117 -0
- package/dist/docs/tabs.md +176 -0
- package/dist/docs/toast.md +124 -0
- package/dist/docs/variant-selector.md +450 -0
- package/dist/graphql/define-subgraph.d.ts +12 -0
- package/dist/graphql/define-subgraph.js +15 -0
- package/dist/graphql/define-subgraph.js.map +1 -0
- package/dist/graphql/gql.d.ts +10 -0
- package/dist/graphql/gql.js +16 -0
- package/dist/graphql/gql.js.map +1 -0
- package/dist/graphql/types.d.ts +88 -0
- package/dist/graphql.d.ts +4 -0
- package/dist/graphql.js +3 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +5 -0
- package/dist/internal/client.d.ts +24 -0
- package/dist/internal/client.js +23 -0
- package/dist/internal/content.d.ts +2 -0
- package/dist/internal/content.js +2 -0
- package/dist/internal/server.d.ts +7 -0
- package/dist/internal/server.js +6 -0
- package/dist/matter/access-code-sign-in/access-code-sign-in.d.ts +111 -0
- package/dist/matter/access-code-sign-in/access-code-sign-in.js +387 -0
- package/dist/matter/access-code-sign-in/access-code-sign-in.js.map +1 -0
- package/dist/matter/account-entry-point/account-entry-point.d.ts +64 -0
- package/dist/matter/account-entry-point/account-entry-point.js +151 -0
- package/dist/matter/account-entry-point/account-entry-point.js.map +1 -0
- package/dist/matter/breadcrumb/breadcrumb.d.ts +40 -0
- package/dist/matter/breadcrumb/breadcrumb.js +155 -0
- package/dist/matter/breadcrumb/breadcrumb.js.map +1 -0
- package/dist/matter/buy-button/buy-button.d.ts +95 -0
- package/dist/matter/buy-button/buy-button.js +259 -0
- package/dist/matter/buy-button/buy-button.js.map +1 -0
- package/dist/matter/cart/cart-namespace.d.ts +48 -0
- package/dist/matter/cart/cart-namespace.js +50 -0
- package/dist/matter/cart/cart-namespace.js.map +1 -0
- package/dist/matter/cart/cart.d.ts +312 -0
- package/dist/matter/cart/cart.js +1034 -0
- package/dist/matter/cart/cart.js.map +1 -0
- package/dist/matter/cart-item/cart-item.d.ts +103 -0
- package/dist/matter/cart-item/cart-item.js +672 -0
- package/dist/matter/cart-item/cart-item.js.map +1 -0
- package/dist/matter/cart-item-compositions/cart-item-compositions.d.ts +49 -0
- package/dist/matter/cart-item-compositions/cart-item-compositions.js +165 -0
- package/dist/matter/cart-item-compositions/cart-item-compositions.js.map +1 -0
- package/dist/matter/cart-item-customizations/cart-item-customizations.d.ts +28 -0
- package/dist/matter/cart-item-customizations/cart-item-customizations.js +73 -0
- package/dist/matter/cart-item-customizations/cart-item-customizations.js.map +1 -0
- package/dist/matter/cart-item-discounts/cart-item-discounts.d.ts +33 -0
- package/dist/matter/cart-item-discounts/cart-item-discounts.js +70 -0
- package/dist/matter/cart-item-discounts/cart-item-discounts.js.map +1 -0
- package/dist/matter/cart-item-seller-info/cart-item-seller-info.d.ts +24 -0
- package/dist/matter/cart-item-seller-info/cart-item-seller-info.js +54 -0
- package/dist/matter/cart-item-seller-info/cart-item-seller-info.js.map +1 -0
- package/dist/matter/cart-item-variations/cart-item-variations.d.ts +27 -0
- package/dist/matter/cart-item-variations/cart-item-variations.js +69 -0
- package/dist/matter/cart-item-variations/cart-item-variations.js.map +1 -0
- package/dist/matter/cart-totalizer/cart-totalizer.d.ts +78 -0
- package/dist/matter/cart-totalizer/cart-totalizer.js +220 -0
- package/dist/matter/cart-totalizer/cart-totalizer.js.map +1 -0
- package/dist/matter/client-preferences/client-preferences.d.ts +50 -0
- package/dist/matter/client-preferences/client-preferences.js +206 -0
- package/dist/matter/client-preferences/client-preferences.js.map +1 -0
- package/dist/matter/client-profile/client-profile.d.ts +59 -0
- package/dist/matter/client-profile/client-profile.js +185 -0
- package/dist/matter/client-profile/client-profile.js.map +1 -0
- package/dist/matter/client-profile-form/client-profile-form.d.ts +126 -0
- package/dist/matter/client-profile-form/client-profile-form.js +660 -0
- package/dist/matter/client-profile-form/client-profile-form.js.map +1 -0
- package/dist/matter/delivery-options/delivery-options-accordion.d.ts +30 -0
- package/dist/matter/delivery-options/delivery-options-accordion.js +189 -0
- package/dist/matter/delivery-options/delivery-options-accordion.js.map +1 -0
- package/dist/matter/delivery-options/delivery-options-controller.d.ts +49 -0
- package/dist/matter/delivery-options/delivery-options-controller.js +203 -0
- package/dist/matter/delivery-options/delivery-options-controller.js.map +1 -0
- package/dist/matter/delivery-options/delivery-options.d.ts +31 -0
- package/dist/matter/delivery-options/delivery-options.js +103 -0
- package/dist/matter/delivery-options/delivery-options.js.map +1 -0
- package/dist/matter/delivery-options/use-delivery-option-selection.d.ts +9 -0
- package/dist/matter/delivery-options/use-delivery-option-selection.js +76 -0
- package/dist/matter/delivery-options/use-delivery-option-selection.js.map +1 -0
- package/dist/matter/email-identification/email-identification.d.ts +37 -0
- package/dist/matter/email-identification/email-identification.js +111 -0
- package/dist/matter/email-identification/email-identification.js.map +1 -0
- package/dist/matter/free-shipping-progress/free-shipping-progress.d.ts +44 -0
- package/dist/matter/free-shipping-progress/free-shipping-progress.js +170 -0
- package/dist/matter/free-shipping-progress/free-shipping-progress.js.map +1 -0
- package/dist/matter/identity-edit/identity-edit.d.ts +52 -0
- package/dist/matter/identity-edit/identity-edit.js +148 -0
- package/dist/matter/identity-edit/identity-edit.js.map +1 -0
- package/dist/matter/identity-summary/identity-summary.d.ts +128 -0
- package/dist/matter/identity-summary/identity-summary.js +344 -0
- package/dist/matter/identity-summary/identity-summary.js.map +1 -0
- package/dist/matter/pricing/pricing.d.ts +162 -0
- package/dist/matter/pricing/pricing.js +793 -0
- package/dist/matter/pricing/pricing.js.map +1 -0
- package/dist/matter/product-gallery/product-gallery.d.ts +23 -0
- package/dist/matter/product-gallery/product-gallery.js +188 -0
- package/dist/matter/product-gallery/product-gallery.js.map +1 -0
- package/dist/matter/product-information/product-information.d.ts +61 -0
- package/dist/matter/product-information/product-information.js +355 -0
- package/dist/matter/product-information/product-information.js.map +1 -0
- package/dist/matter/product-list/product-list.d.ts +86 -0
- package/dist/matter/product-list/product-list.js +342 -0
- package/dist/matter/product-list/product-list.js.map +1 -0
- package/dist/matter/product-quantity/product-quantity.d.ts +50 -0
- package/dist/matter/product-quantity/product-quantity.js +111 -0
- package/dist/matter/product-quantity/product-quantity.js.map +1 -0
- package/dist/matter/product-shelf/product-shelf.d.ts +125 -0
- package/dist/matter/product-shelf/product-shelf.js +376 -0
- package/dist/matter/product-shelf/product-shelf.js.map +1 -0
- package/dist/matter/region/region.d.ts +211 -0
- package/dist/matter/region/region.js +579 -0
- package/dist/matter/region/region.js.map +1 -0
- package/dist/matter/session/session.d.ts +58 -0
- package/dist/matter/session/session.js +112 -0
- package/dist/matter/session/session.js.map +1 -0
- package/dist/matter/shipping-address/country-descriptors.js +101 -0
- package/dist/matter/shipping-address/country-descriptors.js.map +1 -0
- package/dist/matter/shipping-address/shipping-address.d.ts +284 -0
- package/dist/matter/shipping-address/shipping-address.js +1036 -0
- package/dist/matter/shipping-address/shipping-address.js.map +1 -0
- package/dist/matter/shipping-simulator/shipping-simulator.d.ts +143 -0
- package/dist/matter/shipping-simulator/shipping-simulator.js +644 -0
- package/dist/matter/shipping-simulator/shipping-simulator.js.map +1 -0
- package/dist/matter/sign-in-form/sign-in-form.d.ts +79 -0
- package/dist/matter/sign-in-form/sign-in-form.js +226 -0
- package/dist/matter/sign-in-form/sign-in-form.js.map +1 -0
- package/dist/matter/variant-selector/variant-selector.d.ts +183 -0
- package/dist/matter/variant-selector/variant-selector.js +840 -0
- package/dist/matter/variant-selector/variant-selector.js.map +1 -0
- package/dist/message-locales.json +7 -0
- package/dist/particles/access-code-field/access-code-field.d.ts +33 -0
- package/dist/particles/access-code-field/access-code-field.js +95 -0
- package/dist/particles/access-code-field/access-code-field.js.map +1 -0
- package/dist/particles/accordion/accordion.d.ts +45 -0
- package/dist/particles/accordion/accordion.js +156 -0
- package/dist/particles/accordion/accordion.js.map +1 -0
- package/dist/particles/address-summary/address-summary.d.ts +50 -0
- package/dist/particles/address-summary/address-summary.js +129 -0
- package/dist/particles/address-summary/address-summary.js.map +1 -0
- package/dist/particles/badge/badge.d.ts +10 -0
- package/dist/particles/badge/badge.js +27 -0
- package/dist/particles/badge/badge.js.map +1 -0
- package/dist/particles/button/button.d.ts +18 -0
- package/dist/particles/button/button.js +37 -0
- package/dist/particles/button/button.js.map +1 -0
- package/dist/particles/carousel/carousel.d.ts +60 -0
- package/dist/particles/carousel/carousel.js +335 -0
- package/dist/particles/carousel/carousel.js.map +1 -0
- package/dist/particles/checkbox/checkbox.d.ts +40 -0
- package/dist/particles/checkbox/checkbox.js +82 -0
- package/dist/particles/checkbox/checkbox.js.map +1 -0
- package/dist/particles/container/container.d.ts +20 -0
- package/dist/particles/container/container.js +36 -0
- package/dist/particles/container/container.js.map +1 -0
- package/dist/particles/dialog/dialog.d.ts +54 -0
- package/dist/particles/dialog/dialog.js +192 -0
- package/dist/particles/dialog/dialog.js.map +1 -0
- package/dist/particles/document-field/document-field.d.ts +61 -0
- package/dist/particles/document-field/document-field.js +146 -0
- package/dist/particles/document-field/document-field.js.map +1 -0
- package/dist/particles/drawer/drawer.d.ts +52 -0
- package/dist/particles/drawer/drawer.js +183 -0
- package/dist/particles/drawer/drawer.js.map +1 -0
- package/dist/particles/email-field/email-field.d.ts +37 -0
- package/dist/particles/email-field/email-field.js +106 -0
- package/dist/particles/email-field/email-field.js.map +1 -0
- package/dist/particles/field/field.d.ts +50 -0
- package/dist/particles/field/field.js +133 -0
- package/dist/particles/field/field.js.map +1 -0
- package/dist/particles/fieldset/fieldset.d.ts +16 -0
- package/dist/particles/fieldset/fieldset.js +52 -0
- package/dist/particles/fieldset/fieldset.js.map +1 -0
- package/dist/particles/footer-copyright/footer-copyright.d.ts +32 -0
- package/dist/particles/footer-copyright/footer-copyright.js +50 -0
- package/dist/particles/footer-copyright/footer-copyright.js.map +1 -0
- package/dist/particles/footer-link-group/footer-link-group.d.ts +66 -0
- package/dist/particles/footer-link-group/footer-link-group.js +154 -0
- package/dist/particles/footer-link-group/footer-link-group.js.map +1 -0
- package/dist/particles/footer-root/footer-root.d.ts +21 -0
- package/dist/particles/footer-root/footer-root.js +38 -0
- package/dist/particles/footer-root/footer-root.js.map +1 -0
- package/dist/particles/footer-social/footer-social.d.ts +79 -0
- package/dist/particles/footer-social/footer-social.js +176 -0
- package/dist/particles/footer-social/footer-social.js.map +1 -0
- package/dist/particles/gallery/gallery.d.ts +181 -0
- package/dist/particles/gallery/gallery.js +920 -0
- package/dist/particles/gallery/gallery.js.map +1 -0
- package/dist/particles/header-root/header-root.d.ts +21 -0
- package/dist/particles/header-root/header-root.js +38 -0
- package/dist/particles/header-root/header-root.js.map +1 -0
- package/dist/particles/icon/icon.d.ts +22 -0
- package/dist/particles/icon/icon.js +48 -0
- package/dist/particles/icon/icon.js.map +1 -0
- package/dist/particles/image/image.d.ts +13 -0
- package/dist/particles/image/image.js +59 -0
- package/dist/particles/image/image.js.map +1 -0
- package/dist/particles/incentives/incentives.d.ts +85 -0
- package/dist/particles/incentives/incentives.js +200 -0
- package/dist/particles/incentives/incentives.js.map +1 -0
- package/dist/particles/input/input.d.ts +9 -0
- package/dist/particles/input/input.js +28 -0
- package/dist/particles/input/input.js.map +1 -0
- package/dist/particles/logo/logo.d.ts +55 -0
- package/dist/particles/logo/logo.js +96 -0
- package/dist/particles/logo/logo.js.map +1 -0
- package/dist/particles/menu/menu.d.ts +103 -0
- package/dist/particles/menu/menu.js +409 -0
- package/dist/particles/menu/menu.js.map +1 -0
- package/dist/particles/menubar/menubar.d.ts +18 -0
- package/dist/particles/menubar/menubar.js +42 -0
- package/dist/particles/menubar/menubar.js.map +1 -0
- package/dist/particles/meter/meter.d.ts +36 -0
- package/dist/particles/meter/meter.js +132 -0
- package/dist/particles/meter/meter.js.map +1 -0
- package/dist/particles/navigation-link/navigation-link.d.ts +43 -0
- package/dist/particles/navigation-link/navigation-link.js +82 -0
- package/dist/particles/navigation-link/navigation-link.js.map +1 -0
- package/dist/particles/navigation-link-list/navigation-link-list.d.ts +59 -0
- package/dist/particles/navigation-link-list/navigation-link-list.js +103 -0
- package/dist/particles/navigation-link-list/navigation-link-list.js.map +1 -0
- package/dist/particles/navigation-menu/navigation-menu.d.ts +78 -0
- package/dist/particles/navigation-menu/navigation-menu.js +295 -0
- package/dist/particles/navigation-menu/navigation-menu.js.map +1 -0
- package/dist/particles/number-field/number-field.d.ts +46 -0
- package/dist/particles/number-field/number-field.js +169 -0
- package/dist/particles/number-field/number-field.js.map +1 -0
- package/dist/particles/password-field/password-field.d.ts +31 -0
- package/dist/particles/password-field/password-field.js +109 -0
- package/dist/particles/password-field/password-field.js.map +1 -0
- package/dist/particles/payment-methods/payment-methods.d.ts +72 -0
- package/dist/particles/payment-methods/payment-methods.js +151 -0
- package/dist/particles/payment-methods/payment-methods.js.map +1 -0
- package/dist/particles/phone-field/phone-field.d.ts +67 -0
- package/dist/particles/phone-field/phone-field.js +250 -0
- package/dist/particles/phone-field/phone-field.js.map +1 -0
- package/dist/particles/popover/popover.d.ts +68 -0
- package/dist/particles/popover/popover.js +284 -0
- package/dist/particles/popover/popover.js.map +1 -0
- package/dist/particles/postal-code-field/postal-code-field.d.ts +75 -0
- package/dist/particles/postal-code-field/postal-code-field.js +169 -0
- package/dist/particles/postal-code-field/postal-code-field.js.map +1 -0
- package/dist/particles/promotion/promotion.d.ts +46 -0
- package/dist/particles/promotion/promotion.js +78 -0
- package/dist/particles/promotion/promotion.js.map +1 -0
- package/dist/particles/quantity-selector/quantity-selector.d.ts +30 -0
- package/dist/particles/quantity-selector/quantity-selector.js +116 -0
- package/dist/particles/quantity-selector/quantity-selector.js.map +1 -0
- package/dist/particles/radio/radio.d.ts +36 -0
- package/dist/particles/radio/radio.js +76 -0
- package/dist/particles/radio/radio.js.map +1 -0
- package/dist/particles/scroll-area/scroll-area.d.ts +36 -0
- package/dist/particles/scroll-area/scroll-area.js +145 -0
- package/dist/particles/scroll-area/scroll-area.js.map +1 -0
- package/dist/particles/select/select.d.ts +125 -0
- package/dist/particles/select/select.js +478 -0
- package/dist/particles/select/select.js.map +1 -0
- package/dist/particles/separator/separator.d.ts +12 -0
- package/dist/particles/separator/separator.js +33 -0
- package/dist/particles/separator/separator.js.map +1 -0
- package/dist/particles/shared/input-mask.d.ts +5 -0
- package/dist/particles/shared/input-mask.js +58 -0
- package/dist/particles/shared/input-mask.js.map +1 -0
- package/dist/particles/spinner/spinner.d.ts +13 -0
- package/dist/particles/spinner/spinner.js +31 -0
- package/dist/particles/spinner/spinner.js.map +1 -0
- package/dist/particles/switch/switch.d.ts +27 -0
- package/dist/particles/switch/switch.js +59 -0
- package/dist/particles/switch/switch.js.map +1 -0
- package/dist/particles/tabs/tabs.d.ts +45 -0
- package/dist/particles/tabs/tabs.js +164 -0
- package/dist/particles/tabs/tabs.js.map +1 -0
- package/dist/particles/text/text.d.ts +24 -0
- package/dist/particles/text/text.js +40 -0
- package/dist/particles/text/text.js.map +1 -0
- package/dist/particles/toast/toast.d.ts +83 -0
- package/dist/particles/toast/toast.js +194 -0
- package/dist/particles/toast/toast.js.map +1 -0
- package/dist/particles/toggle/toggle.d.ts +26 -0
- package/dist/particles/toggle/toggle.js +61 -0
- package/dist/particles/toggle/toggle.js.map +1 -0
- package/dist/particles/tooltip/tooltip.d.ts +61 -0
- package/dist/particles/tooltip/tooltip.js +240 -0
- package/dist/particles/tooltip/tooltip.js.map +1 -0
- package/dist/schema.graphql +2953 -0
- package/dist/sdk/actions/cart-action-provider.d.ts +19 -0
- package/dist/sdk/actions/cart-action-provider.js +23 -0
- package/dist/sdk/actions/cart-action-provider.js.map +1 -0
- package/dist/sdk/actions/identity-action-provider.d.ts +15 -0
- package/dist/sdk/actions/identity-action-provider.js +19 -0
- package/dist/sdk/actions/identity-action-provider.js.map +1 -0
- package/dist/sdk/actions/index.d.ts +7 -0
- package/dist/sdk/actions/index.js +6 -0
- package/dist/sdk/actions/inject-actions.d.ts +14 -0
- package/dist/sdk/actions/inject-actions.js +36 -0
- package/dist/sdk/actions/inject-actions.js.map +1 -0
- package/dist/sdk/actions/region-action-provider.d.ts +15 -0
- package/dist/sdk/actions/region-action-provider.js +19 -0
- package/dist/sdk/actions/region-action-provider.js.map +1 -0
- package/dist/sdk/actions/session-action-provider.d.ts +15 -0
- package/dist/sdk/actions/session-action-provider.js +19 -0
- package/dist/sdk/actions/session-action-provider.js.map +1 -0
- package/dist/sdk/actions/shipping-action-provider.d.ts +15 -0
- package/dist/sdk/actions/shipping-action-provider.js +19 -0
- package/dist/sdk/actions/shipping-action-provider.js.map +1 -0
- package/dist/sdk/actions/types.d.ts +21 -0
- package/dist/sdk/cache/storefront-cache.js +35 -0
- package/dist/sdk/cache/storefront-cache.js.map +1 -0
- package/dist/sdk/cart/operations.d.ts +31 -0
- package/dist/sdk/cart/operations.js +215 -0
- package/dist/sdk/cart/operations.js.map +1 -0
- package/dist/sdk/cart/optimistic.d.ts +24 -0
- package/dist/sdk/cart/optimistic.js +164 -0
- package/dist/sdk/cart/optimistic.js.map +1 -0
- package/dist/sdk/cart/use-cart-actions.d.ts +56 -0
- package/dist/sdk/cart/use-cart-actions.js +348 -0
- package/dist/sdk/cart/use-cart-actions.js.map +1 -0
- package/dist/sdk/cart/use-cart-validate-on-open.js +50 -0
- package/dist/sdk/cart/use-cart-validate-on-open.js.map +1 -0
- package/dist/sdk/cart/write-gate.js +54 -0
- package/dist/sdk/cart/write-gate.js.map +1 -0
- package/dist/sdk/client/assert-api-url.js +20 -0
- package/dist/sdk/client/assert-api-url.js.map +1 -0
- package/dist/sdk/client/create-client.d.ts +23 -0
- package/dist/sdk/client/create-client.js +46 -0
- package/dist/sdk/client/create-client.js.map +1 -0
- package/dist/sdk/client/fetch-page-data.d.ts +39 -0
- package/dist/sdk/client/fetch-page-data.js +33 -0
- package/dist/sdk/client/fetch-page-data.js.map +1 -0
- package/dist/sdk/client/register-preload-query.d.ts +24 -0
- package/dist/sdk/client/register-preload-query.js +33 -0
- package/dist/sdk/client/register-preload-query.js.map +1 -0
- package/dist/sdk/content/create-content-runtime.d.ts +68 -0
- package/dist/sdk/content/create-content-runtime.js +503 -0
- package/dist/sdk/content/create-content-runtime.js.map +1 -0
- package/dist/sdk/context/headers.d.ts +15 -0
- package/dist/sdk/context/headers.js +21 -0
- package/dist/sdk/context/headers.js.map +1 -0
- package/dist/sdk/context/storefront-context.d.ts +11 -0
- package/dist/sdk/context/storefront-context.js +29 -0
- package/dist/sdk/context/storefront-context.js.map +1 -0
- package/dist/sdk/data/data-override-context.d.ts +12 -0
- package/dist/sdk/data/data-override-context.js +19 -0
- package/dist/sdk/data/data-override-context.js.map +1 -0
- package/dist/sdk/data/entity-subscriber.js +28 -0
- package/dist/sdk/data/entity-subscriber.js.map +1 -0
- package/dist/sdk/data/hot-data-provider.d.ts +19 -0
- package/dist/sdk/data/hot-data-provider.js +33 -0
- package/dist/sdk/data/hot-data-provider.js.map +1 -0
- package/dist/sdk/data/index.d.ts +8 -0
- package/dist/sdk/data/index.js +8 -0
- package/dist/sdk/data/list-item-ref-context.d.ts +20 -0
- package/dist/sdk/data/list-item-ref-context.js +11 -0
- package/dist/sdk/data/list-item-ref-context.js.map +1 -0
- package/dist/sdk/data/multiple-reactive-data-provider.d.ts +32 -0
- package/dist/sdk/data/multiple-reactive-data-provider.js +20 -0
- package/dist/sdk/data/multiple-reactive-data-provider.js.map +1 -0
- package/dist/sdk/data/page-reactive-data-root.d.ts +53 -0
- package/dist/sdk/data/page-reactive-data-root.js +153 -0
- package/dist/sdk/data/page-reactive-data-root.js.map +1 -0
- package/dist/sdk/data/reactive-data-provider.d.ts +25 -0
- package/dist/sdk/data/reactive-data-provider.js +24 -0
- package/dist/sdk/data/reactive-data-provider.js.map +1 -0
- package/dist/sdk/data/reactive-list-item-data-provider.d.ts +26 -0
- package/dist/sdk/data/reactive-list-item-data-provider.js +42 -0
- package/dist/sdk/data/reactive-list-item-data-provider.js.map +1 -0
- package/dist/sdk/data/use-reactive-entity.js +40 -0
- package/dist/sdk/data/use-reactive-entity.js.map +1 -0
- package/dist/sdk/format/client.d.ts +12 -0
- package/dist/sdk/format/client.js +20 -0
- package/dist/sdk/format/client.js.map +1 -0
- package/dist/sdk/format/formatters.d.ts +32 -0
- package/dist/sdk/format/formatters.js +45 -0
- package/dist/sdk/format/formatters.js.map +1 -0
- package/dist/sdk/generated/fragment-types.js +23 -0
- package/dist/sdk/generated/fragment-types.js.map +1 -0
- package/dist/sdk/generated/gql.js +51 -0
- package/dist/sdk/generated/gql.js.map +1 -0
- package/dist/sdk/generated/graphql.d.ts +622 -0
- package/dist/sdk/generated/graphql.js +11917 -0
- package/dist/sdk/generated/graphql.js.map +1 -0
- package/dist/sdk/graphql-tag.d.ts +10 -0
- package/dist/sdk/graphql-tag.js +21 -0
- package/dist/sdk/graphql-tag.js.map +1 -0
- package/dist/sdk/i18n/client.d.ts +4 -0
- package/dist/sdk/i18n/client.js +4 -0
- package/dist/sdk/i18n/locales.d.ts +8 -0
- package/dist/sdk/i18n/locales.js +57 -0
- package/dist/sdk/i18n/locales.js.map +1 -0
- package/dist/sdk/i18n/messages/en-US.js +24 -0
- package/dist/sdk/i18n/messages/en-US.js.map +1 -0
- package/dist/sdk/i18n/messages/en-US.json +19 -0
- package/dist/sdk/i18n/messages/en-US.json.d.ts +23 -0
- package/dist/sdk/i18n/messages/es-ES.js +24 -0
- package/dist/sdk/i18n/messages/es-ES.js.map +1 -0
- package/dist/sdk/i18n/messages/es-ES.json +19 -0
- package/dist/sdk/i18n/messages/pt-BR.js +24 -0
- package/dist/sdk/i18n/messages/pt-BR.js.map +1 -0
- package/dist/sdk/i18n/messages/pt-BR.json +19 -0
- package/dist/sdk/i18n/provider.d.ts +1 -0
- package/dist/sdk/i18n/provider.js +30 -0
- package/dist/sdk/i18n/provider.js.map +1 -0
- package/dist/sdk/i18n/server.d.ts +28 -0
- package/dist/sdk/i18n/server.js +59 -0
- package/dist/sdk/i18n/server.js.map +1 -0
- package/dist/sdk/identity/operations.d.ts +34 -0
- package/dist/sdk/identity/operations.js +78 -0
- package/dist/sdk/identity/operations.js.map +1 -0
- package/dist/sdk/identity/use-identity-actions.d.ts +62 -0
- package/dist/sdk/identity/use-identity-actions.js +180 -0
- package/dist/sdk/identity/use-identity-actions.js.map +1 -0
- package/dist/sdk/provider/index.d.ts +2 -0
- package/dist/sdk/provider/index.js +2 -0
- package/dist/sdk/provider/storefront-provider.d.ts +32 -0
- package/dist/sdk/provider/storefront-provider.js +111 -0
- package/dist/sdk/provider/storefront-provider.js.map +1 -0
- package/dist/sdk/region/operations.d.ts +6 -0
- package/dist/sdk/region/region-operations.d.ts +30 -0
- package/dist/sdk/region/region-operations.js +23 -0
- package/dist/sdk/region/region-operations.js.map +1 -0
- package/dist/sdk/region/use-region-actions.d.ts +23 -0
- package/dist/sdk/region/use-region-actions.js +66 -0
- package/dist/sdk/region/use-region-actions.js.map +1 -0
- package/dist/sdk/seller.js +11 -0
- package/dist/sdk/seller.js.map +1 -0
- package/dist/sdk/session/auth-operations.d.ts +47 -0
- package/dist/sdk/session/auth-operations.js +79 -0
- package/dist/sdk/session/auth-operations.js.map +1 -0
- package/dist/sdk/session/operations.d.ts +6 -0
- package/dist/sdk/session/use-session-actions.d.ts +27 -0
- package/dist/sdk/session/use-session-actions.js +126 -0
- package/dist/sdk/session/use-session-actions.js.map +1 -0
- package/dist/sdk/shipping/cart-operations.d.ts +3 -0
- package/dist/sdk/shipping/cart-operations.js +33 -0
- package/dist/sdk/shipping/cart-operations.js.map +1 -0
- package/dist/sdk/shipping/operations.d.ts +3 -0
- package/dist/sdk/shipping/operations.js +33 -0
- package/dist/sdk/shipping/operations.js.map +1 -0
- package/dist/sdk/shipping/option-select-operations.d.ts +24 -0
- package/dist/sdk/shipping/option-select-operations.js +45 -0
- package/dist/sdk/shipping/option-select-operations.js.map +1 -0
- package/dist/sdk/shipping/request-timeout.js +41 -0
- package/dist/sdk/shipping/request-timeout.js.map +1 -0
- package/dist/sdk/shipping/shipping-operations.d.ts +38 -0
- package/dist/sdk/shipping/shipping-operations.js +77 -0
- package/dist/sdk/shipping/shipping-operations.js.map +1 -0
- package/dist/sdk/shipping/use-cart-shipping-simulation.d.ts +7 -0
- package/dist/sdk/shipping/use-cart-shipping-simulation.js +72 -0
- package/dist/sdk/shipping/use-cart-shipping-simulation.js.map +1 -0
- package/dist/sdk/shipping/use-shipping-actions.d.ts +27 -0
- package/dist/sdk/shipping/use-shipping-actions.js +113 -0
- package/dist/sdk/shipping/use-shipping-actions.js.map +1 -0
- package/dist/sdk/shipping/use-shipping-simulation.d.ts +7 -0
- package/dist/sdk/shipping/use-shipping-simulation.js +72 -0
- package/dist/sdk/shipping/use-shipping-simulation.js.map +1 -0
- package/dist/sdk/state/cart.d.ts +42 -0
- package/dist/sdk/state/cart.js +64 -0
- package/dist/sdk/state/cart.js.map +1 -0
- package/dist/sdk/state/index.js +3 -0
- package/dist/sdk/state/variant-selector.d.ts +17 -0
- package/dist/sdk/state/variant-selector.js +14 -0
- package/dist/sdk/state/variant-selector.js.map +1 -0
- package/dist/utils/safe-href.js +63 -0
- package/dist/utils/safe-href.js.map +1 -0
- package/package.json +84 -0
- package/src/styles/tailwind.css +32 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { mockAction } from "./actions/mock-action.js";
|
|
2
|
+
import { defineActions } from "./actions/registry.js";
|
|
3
|
+
import { defineComponent } from "./define-component.js";
|
|
4
|
+
import { defineContentType } from "./define-content-type.js";
|
|
5
|
+
export { defineActions, defineComponent, defineContentType, mockAction };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region ../core/dist/schema/generated/schema.d.ts
|
|
2
|
+
/** Arbitrary JSON — the value type of the flattened catch-alls. */
|
|
3
|
+
export type JsonValue = number | string | boolean | Array<JsonValue> | {
|
|
4
|
+
[key: string]: JsonValue;
|
|
5
|
+
} | null;
|
|
6
|
+
/**
|
|
7
|
+
* The immutable per-request storefront context — the public name of the contract.
|
|
8
|
+
* `Readonly` because the compiler emits it as a frozen module-level constant: one mutation
|
|
9
|
+
* would leak across every request a server process handles.
|
|
10
|
+
*/
|
|
11
|
+
export type StorefrontContext = Readonly<StorefrontContextShape>;
|
|
12
|
+
export type Direction = "ltr" | "rtl";
|
|
13
|
+
export type StorefrontContextShape = {
|
|
14
|
+
bindingId: string;
|
|
15
|
+
locale: string;
|
|
16
|
+
currency: string;
|
|
17
|
+
salesChannel: string;
|
|
18
|
+
country?: string;
|
|
19
|
+
timezone?: string;
|
|
20
|
+
direction: Direction;
|
|
21
|
+
/**
|
|
22
|
+
* Resolution-only, so absent while nothing resolves. Never an empty string.
|
|
23
|
+
*/
|
|
24
|
+
origin?: string;
|
|
25
|
+
basePath: string;
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
28
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "./define-component.js";
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# AccessCodeField
|
|
2
|
+
|
|
3
|
+
**Category:** content
|
|
4
|
+
**Purpose:** A presentational one-time-code input that composes the `Field` particle (label + native `<input>` + inline error), mirroring `EmailField`'s shape. Unlike `EmailField`, it performs **no** client-side format validation — a code's validity is entirely server-decided. It is data-agnostic — value flows through props; it consumes no GraphQL and no domain context.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Visual cues (how to identify in an image)
|
|
9
|
+
|
|
10
|
+
- A single-line text input labelled something like **"Enter the code we sent you"**, **"Verification code"**, or **"Access code"**, usually the second step of a passwordless / access-code sign-in flow, right after an email or "send code" step.
|
|
11
|
+
- Often shows a placeholder like `000000`.
|
|
12
|
+
- When invalid, an inline error message below the input (e.g. *"That code is incorrect or expired."*).
|
|
13
|
+
- Never rendered as a six-box segmented widget in this catalog — always a single text input.
|
|
14
|
+
|
|
15
|
+
If the image shows a checkout sign-in step whose only field is a numeric/alphanumeric code entered after requesting it by email, use `AccessCodeField` — or, for the full request/validate flow wired to the session, use `AccessCodeSignIn.Validate`.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## When to use
|
|
20
|
+
|
|
21
|
+
- A standalone, presentational one-time-code input where the host owns the value and the validation outcome.
|
|
22
|
+
- As the field rendered by `AccessCodeSignIn.Validate` (the checkout-bound wrapper).
|
|
23
|
+
|
|
24
|
+
## When NOT to use
|
|
25
|
+
|
|
26
|
+
- When the field must dispatch the validate mutation and hold the stepper's `authenticationToken` → use `AccessCodeSignIn.Validate`, which wraps this particle.
|
|
27
|
+
- For an email or generic text field → use `EmailField` or the `Field` particle directly.
|
|
28
|
+
- For a segmented, per-digit box input → out of scope for this catalog; this particle is always a single `<input>`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Composition
|
|
33
|
+
|
|
34
|
+
`AccessCodeField` is a single leaf particle. Internally it renders:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
AccessCodeField (data-fs-access-code-field + inherited data-fs-field-root)
|
|
38
|
+
├── Field.Label (data-fs-field-label; the `label` prop)
|
|
39
|
+
├── Field.Control (data-fs-field-control; native <input type="text" autocomplete="one-time-code">)
|
|
40
|
+
└── Field.Error (data-fs-field-error; the `errorMessage`, shown when invalid)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Props
|
|
46
|
+
|
|
47
|
+
| Prop | Type | Default | Notes |
|
|
48
|
+
|------|------|---------|-------|
|
|
49
|
+
| `value` | string | — | Controlled value. Omit for uncontrolled use. |
|
|
50
|
+
| `defaultValue` | string | `''` | Uncontrolled initial value. |
|
|
51
|
+
| `onValueChange` | `(value: string) => void` | — | Fires on every input change. |
|
|
52
|
+
| `onBlur` | `(event) => void` | — | Fires on blur. |
|
|
53
|
+
| `invalid` | boolean | `false` | Host-driven invalid state — **never** self-derived. |
|
|
54
|
+
| `errorMessage` | string | — | Inline error text, shown when `invalid` is true. |
|
|
55
|
+
| `label` | string | — | Accessible label. |
|
|
56
|
+
| `placeholder` | string | — | Input placeholder. |
|
|
57
|
+
| `disabled` | boolean | `false` | Disables the input (e.g. while a dispatch is in flight). |
|
|
58
|
+
| `required` | boolean | `true` | A code is always required at this step. |
|
|
59
|
+
| `name` | string | `'accessCode'` | Field/input name. |
|
|
60
|
+
| `autoComplete` | string | `'one-time-code'` | Enables OS/browser code autofill despite the single-line shape. |
|
|
61
|
+
| `inputMode` | string | `'numeric'` | Mobile keypad hint; override (e.g. `'text'`) for alphanumeric codes. |
|
|
62
|
+
| `maxLength` | number | — | Caps the entered length (the wrapper passes its `codeLength`). Not a validity check. |
|
|
63
|
+
|
|
64
|
+
**Validation:** none, by design. A code's correctness (does it match what was emailed, is it still live) is exclusively decidable server-side; `invalid`/`errorMessage` are entirely host-driven, fed from `validateAccessCode`'s `userErrors`.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Accessibility
|
|
69
|
+
|
|
70
|
+
The label is associated with the input and the error is linked via `aria-describedby` automatically by the Base UI `Field` primitive (WCAG 2.1 AA). Standard text-input keyboard editing; nothing blocks typing.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Styling
|
|
75
|
+
|
|
76
|
+
`AccessCodeField` owns no CSS. Style it via compound swatches / Tailwind targeting the `data-fs-*` attributes:
|
|
77
|
+
|
|
78
|
+
| Target | What you style |
|
|
79
|
+
|---|---|
|
|
80
|
+
| `data-fs-access-code-field` | The field container (stack the label, input, error). |
|
|
81
|
+
| `data-fs-field-label` | The label typography. |
|
|
82
|
+
| `data-fs-field-control` | The input box; use `data-invalid:` for the error border. |
|
|
83
|
+
| `data-fs-field-error` | The inline error text (small, red). |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Common mistakes
|
|
88
|
+
|
|
89
|
+
- **Adding client-side format validation.** A code's validity is server-only; `invalid`/`errorMessage` must come from `userErrors`, never a local regex.
|
|
90
|
+
- **Wiring GraphQL into this particle.** It is data-agnostic; use `AccessCodeSignIn.Validate` for the checkout-bound binding.
|
|
91
|
+
- **Replacing it with a segmented multi-box widget.** This catalog deliberately composes `Field` + `Input` into a single-line input.
|
|
92
|
+
- **Localizing via a message id.** There is no `react-intl`; pass `label` / `placeholder` / `errorMessage` as strings.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Related
|
|
97
|
+
|
|
98
|
+
- [[access-code-sign-in]] — the checkout-bound matter family (Root + Request + Validate) that composes this particle into the two-step sign-in flow.
|
|
99
|
+
- [[email-field]] — the sibling particle for the email step; the shape this particle mirrors.
|
|
100
|
+
- [[field]] — the underlying form-field particle this composes.
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# AccessCodeSignIn (Root + Email + Request + Validate)
|
|
2
|
+
|
|
3
|
+
**Category:** identity
|
|
4
|
+
**Purpose:** A self-gating, cart-independent passwordless sign-in flow, available from the `anonymous` state onward. `AccessCodeSignInRoot` owns a locally-typed draft email (never written to the cart) and reads the account's provider config (`sessionAuthProviders.accessKeyAuthentication`); it renders nothing once the shopper is already `loggedIn` or the account disables the method. `AccessCodeEmailControl` collects the draft email; `AccessCodeRequestControl` sends the code; `AccessCodeValidateControl` collects and validates it. A successful validate flips `useSession()` to `loggedIn` (and the server persists the validated email onto the cart's profile as a side effect), which makes the whole Root disappear on its own.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Visual cues (how to identify in an image)
|
|
9
|
+
|
|
10
|
+
- An **email input + "send a sign-in code" button**, usable with no prior identification step — this is `AccessCodeEmailControl` + `AccessCodeRequestControl`.
|
|
11
|
+
- A **one-time-code input + submit button** shown right after activating the send-code button — this is `AccessCodeValidateControl` composing `AccessCodeField`.
|
|
12
|
+
- Lives inside the checkout User Identity step as an optional method — never a step the shopper must complete to continue as a guest.
|
|
13
|
+
- No third "blocked" or "rate limited" full-screen error state: those outcomes appear as small inline text under the button/field instead.
|
|
14
|
+
|
|
15
|
+
Use `AccessCodeSignIn.*` whenever the image shows a passwordless "email me a code" affordance, distinct from a password field, especially one usable before any other identification step.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## When to use
|
|
20
|
+
|
|
21
|
+
- The access-code (passwordless) sign-in method in the checkout User Identity step, for a shopper at any session state short of `loggedIn` — including fully `anonymous`, with no prior email identification.
|
|
22
|
+
- Alongside the password `SignInForm` (FSPG-865), as one of possibly several sign-in methods a page composes — this family never assumes it's the only one.
|
|
23
|
+
|
|
24
|
+
## When NOT to use
|
|
25
|
+
|
|
26
|
+
- A blocking, must-complete-to-continue login gate → this flow is always optional; it self-gates to hidden and never blocks guest checkout.
|
|
27
|
+
- Persisting the draft email as profile data on its own → `AccessCodeEmailControl` never writes to the cart; only a successful `validateAccessCode` does, server-side, as a side effect of authentication. Don't pair it with `EmailIdentificationControl` for the same field — that control's blur-triggered `clientProfileUpdate` is a different, cart-writing identification path.
|
|
28
|
+
- Composing "sign in with a password instead" or "use another email" switch affordances → those are the hosting component's job (FSPG-865), not this family's.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Composition
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
SessionRoot (provides the session tri-state; required ancestor)
|
|
36
|
+
└── AccessCodeSignInRoot (data-fs-access-code-sign-in-root; self-gates; owns draft email + step + authenticationToken)
|
|
37
|
+
├── AccessCodeEmailControl (visible only in step 'request'; local draft email, never persisted)
|
|
38
|
+
├── AccessCodeRequestControl (visible only in step 'request')
|
|
39
|
+
│ └── (button) (dispatches $actions.session.requestAccessCode with the draft email)
|
|
40
|
+
└── AccessCodeValidateControl (visible only in step 'validate')
|
|
41
|
+
├── AccessCodeField (the code input; value/invalid/errorMessage bound)
|
|
42
|
+
└── (submit button) (dispatches $actions.session.validateAccessCode)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`AccessCodeSignInRoot` **must** have a `SessionRoot` ancestor — `useSession()` throws otherwise. `AccessCodeEmailControl`, `AccessCodeRequestControl`, and `AccessCodeValidateControl` **must** be descendants of `AccessCodeSignInRoot` — all three throw a descriptive error otherwise (runtime-only guard, not compiler-checked).
|
|
46
|
+
|
|
47
|
+
`AccessCodeEmailControl` is optional: an identified shopper's `clientProfile.email` pre-fills the Root's draft even without it composed, so a page that only wants the identified-shopper case (skipping straight to `AccessCodeRequestControl`) may omit it — but then an anonymous shopper has no way to type an email, so the request control stays disabled (empty draft never passes its valid-email gate).
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Props
|
|
52
|
+
|
|
53
|
+
### `AccessCodeSignInRoot`
|
|
54
|
+
|
|
55
|
+
| Prop | Type | Default | Notes |
|
|
56
|
+
|------|------|---------|-------|
|
|
57
|
+
| `$data` | `{ clientProfile: { email } \| null, sessionAuthProviders: { accessKeyAuthentication } \| null } \| null` | injected | Colocated `on Query` fragment slice. An unresolved (`null`) read is treated the same as "provider disabled" — the flow stays hidden rather than flashing. |
|
|
58
|
+
|
|
59
|
+
**Data:** declares `fragment AccessCodeSignInData on Query { clientProfile { email } sessionAuthProviders { accessKeyAuthentication } }` with `fetchStrategy: 'reactive'` and `requiresContext: 'session'`.
|
|
60
|
+
|
|
61
|
+
**Gate:** renders its children whenever **both** hold: `useSession().state !== 'loggedIn'` and `sessionAuthProviders.accessKeyAuthentication === true`. Available from `anonymous` through `identified`; hides once `loggedIn` or when the account disables the method or the fragment hasn't resolved yet.
|
|
62
|
+
|
|
63
|
+
### `AccessCodeEmailControl`
|
|
64
|
+
|
|
65
|
+
| Prop | Type | Default | Notes |
|
|
66
|
+
|------|------|---------|-------|
|
|
67
|
+
| `label` | string | — | Passed to `EmailField`. |
|
|
68
|
+
| `placeholder` | string | — | Passed to `EmailField`. |
|
|
69
|
+
| `invalidEmailMessage` | string | — | `EmailField`'s inline error text; format validation itself is `EmailField`'s own blur-triggered check, never per-keystroke. |
|
|
70
|
+
|
|
71
|
+
Renders only at the request step. Declares no actions — it never dispatches a mutation, it only writes the Root's local draft state.
|
|
72
|
+
|
|
73
|
+
### `AccessCodeRequestControl`
|
|
74
|
+
|
|
75
|
+
| Prop | Type | Default | Notes |
|
|
76
|
+
|------|------|---------|-------|
|
|
77
|
+
| `label` | string | — | Send-code button label. |
|
|
78
|
+
| `pendingLabel` | string | — | Label while the request is in flight. |
|
|
79
|
+
| `sendLimitMessage` | string | — | Inline message for `ACCESS_CODE_SEND_LIMIT`. |
|
|
80
|
+
| `blockedMessage` | string | — | Inline message for `BLOCKED`. |
|
|
81
|
+
| `networkErrorMessage` | string | — | Inline message for the synthetic `NETWORK_ERROR`. |
|
|
82
|
+
| `onRequested` | `(authenticationToken: string) => void` | — | Fires after a successful request, alongside the Root's own step advance. |
|
|
83
|
+
| `$actions` | injected | — | Carries `session.requestAccessCode` (compiler-injected, narrowed to that one method). |
|
|
84
|
+
|
|
85
|
+
The button is disabled until the Root's draft email is a valid, non-empty address (checked with the same rule `EmailIdentificationControl` uses) — never a blocking error state, just an inert affordance.
|
|
86
|
+
|
|
87
|
+
### `AccessCodeValidateControl`
|
|
88
|
+
|
|
89
|
+
| Prop | Type | Default | Notes |
|
|
90
|
+
|------|------|---------|-------|
|
|
91
|
+
| `label` | string | — | Passed to `AccessCodeField`. |
|
|
92
|
+
| `placeholder` | string | — | Passed to `AccessCodeField`. |
|
|
93
|
+
| `submitLabel` | string | — | Submit button label. |
|
|
94
|
+
| `codeLength` | number | `6` | Disables submit below this length and caps the field maxLength — a UX gate, never a validity claim. |
|
|
95
|
+
| `invalidCodeMessage` | string | — | Inline message for `INVALID_ACCESS_CODE`. |
|
|
96
|
+
| `blockedMessage` | string | — | Inline message for `BLOCKED`. |
|
|
97
|
+
| `missingAuthContextMessage` | string | — | Inline message for `MISSING_AUTH_CONTEXT` (should not occur on a correct flow). |
|
|
98
|
+
| `networkErrorMessage` | string | — | Inline message for the synthetic `NETWORK_ERROR`. |
|
|
99
|
+
| `onValidated` | `() => void` | — | Fires after a successful validate. No local "success" UI is needed — the session flip hides the Root. |
|
|
100
|
+
| `$actions` | injected | — | Carries `session.validateAccessCode` (compiler-injected, narrowed to that one method). |
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Behavior
|
|
105
|
+
|
|
106
|
+
- **Draft email ownership:** the Root owns a local `email` string (`useState`), never the cart. It pre-fills from `clientProfile.email` when known (a convenience for an already-identified shopper) — untouched-field re-seed, mirroring `ClientProfileForm`'s draft/dirty tracking: the re-seed only runs while the flow is still at the `request` step and the draft is untouched, so once the shopper edits the draft or the flow advances past `request`, further profile-email updates never clobber it (and the email can't diverge between `requestAccessCode` and `validateAccessCode`). Editing it dispatches nothing; it is purely the argument `requestAccessCode`/`validateAccessCode` are called with.
|
|
107
|
+
- **Profile persistence happens server-side, on success:** a successful `validateAccessCode` sets the cart's `clientProfileData.email` to the validated email as a side effect of authentication (see the auth module's `completeLoginWithEmail`) — this family itself never calls `clientProfileUpdate`.
|
|
108
|
+
- **No account-existence pre-check:** `AccessCodeRequestControl` dispatches unconditionally once the draft email is valid — no separate lookup call.
|
|
109
|
+
- **Stepper:** the Root owns `step: 'request' | 'validate'` and `authenticationToken: string | null` as local state — the session-action namespace itself holds none of this (a deliberate choice in the FSPG-880 session-actions design).
|
|
110
|
+
- **Every failure is inline:** `ACCESS_CODE_SEND_LIMIT` / `BLOCKED` / `NETWORK_ERROR` surface at the request control; `INVALID_ACCESS_CODE` / `BLOCKED` / `MISSING_AUTH_CONTEXT` / `NETWORK_ERROR` surface on the `AccessCodeField` inside the validate control. The step never changes on error — the shopper can retry or abandon the method and continue as a guest.
|
|
111
|
+
- **Success is entirely reactive:** on a successful validate, the mutation's normalized cache write flips `useSession().state` to `loggedIn` with no refetch and no imperative cache write; the Root's own `useSession()` read reacts and self-gates back to hidden.
|
|
112
|
+
- **Pending states:** both controls expose `data-fs-access-code-request-pending` / `data-fs-access-code-validate-pending` while their dispatch is in flight, disabling their interactive elements — mirrors `CartCouponForm`'s `data-fs-cart-coupon-pending`.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Canonical schema example
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"type": "SessionRoot",
|
|
121
|
+
"children": [
|
|
122
|
+
{
|
|
123
|
+
"type": "AccessCodeSignInRoot",
|
|
124
|
+
"children": [
|
|
125
|
+
{
|
|
126
|
+
"type": "AccessCodeEmailControl",
|
|
127
|
+
"props": {
|
|
128
|
+
"label": "Email",
|
|
129
|
+
"placeholder": "you@example.com",
|
|
130
|
+
"invalidEmailMessage": "Enter a valid email address."
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"type": "AccessCodeRequestControl",
|
|
135
|
+
"props": {
|
|
136
|
+
"label": "Send a sign-in code",
|
|
137
|
+
"sendLimitMessage": "Too many codes requested. Try again later.",
|
|
138
|
+
"blockedMessage": "This account is blocked. Contact support.",
|
|
139
|
+
"networkErrorMessage": "Something went wrong. Please try again."
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"type": "AccessCodeValidateControl",
|
|
144
|
+
"props": {
|
|
145
|
+
"label": "Enter the code we sent you",
|
|
146
|
+
"placeholder": "000000",
|
|
147
|
+
"submitLabel": "Sign in",
|
|
148
|
+
"invalidCodeMessage": "That code is incorrect or expired.",
|
|
149
|
+
"networkErrorMessage": "Something went wrong. Please try again."
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Common mistakes
|
|
161
|
+
|
|
162
|
+
- **Rendering the controls outside `AccessCodeSignInRoot`.** All three throw a descriptive error immediately.
|
|
163
|
+
- **Persisting the draft email yourself, or pairing this with `EmailIdentificationControl` for the same field.** `AccessCodeEmailControl` never writes to the cart; the server sets the profile email on a successful validate, not before.
|
|
164
|
+
- **Adding a blocking error screen for send-limit/blocked outcomes.** Every failure is inline at the control that produced it — there is no third "error" step.
|
|
165
|
+
- **Manually unmounting or resetting the flow after login.** The Root's own `useSession()` read is what hides it; no explicit call is needed.
|
|
166
|
+
- **Persisting or logging the `authenticationToken` or the entered code.** Both flow through mutation variables only.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Related
|
|
171
|
+
|
|
172
|
+
- [[access-code-field]] — the presentational one-time-code particle this family composes.
|
|
173
|
+
- [[session]] — provides the identification tri-state and the required `SessionRoot` ancestor; also what makes the Root disappear post-login.
|
|
174
|
+
- [[email-identification]] — a separate, cart-writing identification path (blur-triggered `clientProfileUpdate`); do not compose it for the same email field as this family.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# AccountEntryPoint
|
|
2
|
+
|
|
3
|
+
**Category:** identity
|
|
4
|
+
**Purpose:** Header control that reads the session and renders one link — sign in, or the shopper's account.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Visual cues (how to identify in an image)
|
|
9
|
+
|
|
10
|
+
- A small icon-plus-label pair at the right end of a header row, beside the cart.
|
|
11
|
+
- The label reads as an invitation to sign in ("Entrar", "Sign In") or as a destination ("Minha conta", "My Account"), never both.
|
|
12
|
+
- Rendered as one clickable unit; the icon is decorative and the label carries the meaning.
|
|
13
|
+
- A grey bar in that slot, with no label, is the resolving state rather than a separate control.
|
|
14
|
+
|
|
15
|
+
The image is the source of truth for layout.
|
|
16
|
+
|
|
17
|
+
## When to use
|
|
18
|
+
|
|
19
|
+
- For the header's single account entry, when it must adapt to whether the shopper is signed in.
|
|
20
|
+
|
|
21
|
+
## When NOT to use
|
|
22
|
+
|
|
23
|
+
- For a plain link to a fixed destination → use [[navigation-link]].
|
|
24
|
+
- For showing or hiding an arbitrary subtree by session state → use `SessionGuard`, which gates on the tri-state declaratively.
|
|
25
|
+
- For an account menu with logout and sub-destinations → out of scope; this is a link, not a dropdown.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Composition
|
|
30
|
+
|
|
31
|
+
`AccountEntryPoint` is a leaf element in the PageSchema. It owns its internal composition — a navigation link wrapping an icon and a label — and takes no children.
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
AccountEntryPoint
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
It requires a `SessionRoot` ancestor. The compiler rejects a placement without one, and at runtime `useSession()` throws rather than degrading to a silently wrong state.
|
|
38
|
+
|
|
39
|
+
## Components
|
|
40
|
+
|
|
41
|
+
### AccountEntryPoint
|
|
42
|
+
|
|
43
|
+
| Prop | Type | Default | Notes |
|
|
44
|
+
|------|------|---------|-------|
|
|
45
|
+
| `signedOutLabel` | string | — | Label for anonymous and identified shoppers. Optional, so an element can be authored from the CMS alone. |
|
|
46
|
+
| `signedInLabel` | string | — | Label for logged-in shoppers. Optional for the same reason. |
|
|
47
|
+
| `icon` | string | — | Icon reference for the glyph. Absent renders the label alone. |
|
|
48
|
+
| `loadingLabel` | string | — | Text announced while the session resolves. |
|
|
49
|
+
|
|
50
|
+
Content model (`account-entry-point`) fields, edited in the CMS:
|
|
51
|
+
|
|
52
|
+
| Field | Type | Required | Notes |
|
|
53
|
+
|-------|------|----------|-------|
|
|
54
|
+
| `signedOutLabel` | string | no | Cleared or absent keeps the authored prop |
|
|
55
|
+
| `signedInLabel` | string | no | Same |
|
|
56
|
+
| `icon` | string | no | Same, but the name must be listed in `global.json → icons.include` — see below |
|
|
57
|
+
| `loadingLabel` | string | no | Same |
|
|
58
|
+
|
|
59
|
+
**An icon chosen in the CMS has to be declared in the store first.** Icon references resolve at compile time: the compiler collects every value of every `icon`-typed prop across the page and layout schemas and emits one sprite per route. A name that arrives at runtime from a CMS entry is never seen by that pass, so it renders a `<use>` pointing at a symbol the route's sprite does not carry — no build error, no runtime error, no glyph. For a merchant to be able to pick the icon in the Admin, the store must list the candidates under `global.json → icons.include`, which puts them in the root sprite regardless of what any schema references.
|
|
60
|
+
|
|
61
|
+
**One element, two links, chosen by the session.** `loggedIn` renders the signed-in link; `anonymous` and `identified` both render the signed-out one, because an identified but unauthenticated shopper cannot reach their account yet. There is no prop that selects between them — the merchant authors one element and the session decides.
|
|
62
|
+
|
|
63
|
+
**The destinations are not authored.** Sign in goes to `/login`, carrying a `returnUrl` with the current path so the deferred proxy can return the shopper where they started; the account link goes to the platform's account route. Both are module constants, so no schema edit and no CMS entry can misroute the auth flow. The `returnUrl` value is constrained to a same-origin relative path and dropped otherwise, which keeps the proxy from being turned into an open redirect — though the proxy has to validate it again on its own side. The signed-out link also opts out of Next.js prefetching: a header control is always in the viewport, and the destination is an auth proxy that may set a cookie or redirect, so the default would fire that request on every page view.
|
|
64
|
+
|
|
65
|
+
**`returnUrl` carries the path only — not the query string, not the hash.** A shopper signing in from `/s?q=tenis` or a filtered listing returns to the bare path. This is a deliberate narrowing rather than a limitation of the router: recovering the query would mean reading it through `useSearchParams()` and wrapping the header in a Suspense boundary, and the hash never leaves the browser at all. Search and filter state is cheap to re-apply and the sign-in round trip is rare, so the entry point keeps the simpler shape. Revisit it if merchants report losing filters across sign-in.
|
|
66
|
+
|
|
67
|
+
**Nothing renders without a resolved label for the active state.** Both label props are optional and neither is required in the model, so an element can author nothing and take everything from the CMS. Presence is enforced once, at render, on the resolved value: an unauthored state renders no element at all, because a focusable link a screen reader announces as its bare URL is worse than no control. The gate is per state, so an element authoring only `signedOutLabel` still serves logged-out shoppers and renders nothing for logged-in ones.
|
|
68
|
+
|
|
69
|
+
The placeholder does not know which state is coming, so it renders for the whole wait either way. A control that authors only `signedOutLabel` therefore shows the placeholder to a logged-in shopper and then removes it, reflowing the header once. Author both labels to avoid it — the half-authored control is supported, not recommended.
|
|
70
|
+
|
|
71
|
+
**The resolving state is announced, not hidden.** The component renders a polite live region that stays mounted through the whole exchange: it is empty on the first pass, receives `loadingLabel` once mounted, and is cleared again when the session resolves. The order matters and is the entire reason the region is not part of the placeholder. Assistive technology reports changes *within* a region already in the tree, so a region that appears with its text already inside says nothing, and one that is removed along with the placeholder can never report that the wait ended. The visible bar beside it is `aria-hidden`, so the wait is spoken once rather than twice. All of this only pays off with a layout-hosted `SessionRoot` — a page-hosted one is seeded server-side without the shopper cookie, never reports loading, and sticks on the signed-out label.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Canonical schema example
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"header-account": {
|
|
80
|
+
"type": "AccountEntryPoint",
|
|
81
|
+
"props": {
|
|
82
|
+
"signedOutLabel": "Entrar",
|
|
83
|
+
"signedInLabel": "Minha conta",
|
|
84
|
+
"loadingLabel": "Carregando conta…",
|
|
85
|
+
"icon": "lucide:user"
|
|
86
|
+
},
|
|
87
|
+
"style": ["$account-entry-point"]
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Bound to a CMS entry, the element authors no content props at all — the entry supplies all four fields.
|
|
93
|
+
|
|
94
|
+
## Common mistakes
|
|
95
|
+
|
|
96
|
+
- **Wrapping it in a `SessionGuard`.** The component reads the session itself; a guard around it would hide the resolving state and reintroduce the wrong-label flash.
|
|
97
|
+
- **Wrapping it in a `NavigationLink`.** It already composes its own link; nesting it in another is invalid.
|
|
98
|
+
- **Placing it outside a `SessionRoot`.** The compiler rejects it, and the runtime throws.
|
|
99
|
+
- **Authoring `$content` in the schema.** `$content` is compiler-injected from the page's or layout's content entry; naming it in `props` fails the build.
|
|
100
|
+
- **Expecting a default glyph.** The base icon dialect has no account icon, so a store that authors no `icon` gets a label-only link. Author one from the store's own collection.
|
|
101
|
+
- **Letting a merchant pick the icon without declaring it.** An `icon` supplied by a CMS entry renders nothing at all unless the store lists the name in `global.json → icons.include`: the compiler builds each route's sprite from the schemas, and a runtime value never reaches that pass.
|
|
102
|
+
- **Hiding the announced text with `display:none`.** That removes it from the accessibility tree and defeats the announcement; use a clipping technique instead.
|
|
103
|
+
- **Hosting the `SessionRoot` on the page.** The session then resolves server-side without the shopper cookie, and every shopper sees the signed-out label.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Styling
|
|
108
|
+
|
|
109
|
+
| Component | What you style | Plausible classes |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| `AccountEntryPoint` | The control as a whole; `data-fs-account-entry-point` is the root and `data-fs-account-entry-point-state` switches on which link rendered | `inline-flex items-center gap-2 px-3 py-2` |
|
|
112
|
+
| Label | `data-fs-account-entry-point-label` reaches the text apart from the glyph | `text-sm font-medium` |
|
|
113
|
+
| Placeholder | `data-fs-account-entry-point-loading` sizes the resolving state; match the resolved control so the header does not reflow | `h-9 w-24 animate-pulse rounded-md bg-gray-100` |
|
|
114
|
+
| Announcement | `data-fs-account-entry-point-announcement` reaches the live region carrying `loadingLabel`. It is a *following sibling* of the control, not a descendant, so reach it with `~` rather than a descendant selector | `sr-only` |
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"header-account": {
|
|
119
|
+
"type": "AccountEntryPoint",
|
|
120
|
+
"props": { "signedOutLabel": "Entrar", "signedInLabel": "Minha conta", "icon": "lucide:user" },
|
|
121
|
+
"style": ["inline-flex", "items-center", "gap-2", "text-sm"]
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The glyph carries a fixed intrinsic size, so reach it through the root when the header needs another.
|
|
127
|
+
Author that once per store as the `AccountEntryPoint` base swatch in `global.json → styles`:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"AccountEntryPoint": {
|
|
132
|
+
"base": ["[&_[data-fs-icon]]:w-5", "[&_[data-fs-icon]]:h-5"]
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Hide the announced text visually without dropping it from the accessibility tree. The region trails
|
|
138
|
+
the control as a sibling, so this one is `~` rather than a descendant selector:
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"AccountEntryPoint": {
|
|
143
|
+
"base": ["[&~[data-fs-account-entry-point-announcement]]:sr-only"]
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Related
|
|
151
|
+
|
|
152
|
+
- `SessionRoot` — the provider this component requires; host it at the root of the shared layout.
|
|
153
|
+
- `SessionGuard` — the declarative gate for showing an arbitrary subtree by session state.
|
|
154
|
+
- [[navigation-link]] — the client-side link this component composes.
|
|
155
|
+
- [[icon]] — the glyph renderer it composes.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Address Summary
|
|
2
|
+
|
|
3
|
+
**Category:** content
|
|
4
|
+
**Purpose:** Reusable, context-driven formatted display of a postal address.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Composition
|
|
9
|
+
|
|
10
|
+
`AddressSummaryRoot` (provides address via context) → `AddressSummary` (reads and renders the address).
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Components
|
|
15
|
+
|
|
16
|
+
| Component | Props | Notes |
|
|
17
|
+
|-----------|-------|-------|
|
|
18
|
+
| `AddressSummaryRoot` | `address: AddressSummaryFields` (required), `children?: ReactNode` | Provides the address to descendant components via context (no business coupling). Must wrap `AddressSummary` or another presentation component. |
|
|
19
|
+
| `AddressSummary` | `className?: string`, `children?: ReactNode` | Read-only formatted display: recipient name, street/number/complement, neighborhood/city/state/postal code. Lines with no content are omitted. Composed `children` render inside the container in place of the default lines. Must be a descendant of `AddressSummaryRoot`. |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Lines are composed, not fixed
|
|
24
|
+
|
|
25
|
+
`AddressSummary` is a **shortcut** for the default order (recipient, street line, locality line). Each line
|
|
26
|
+
is also its own component reading the same `AddressSummaryRoot` context, so a page that wants another order,
|
|
27
|
+
or only one of them, composes the leaves instead:
|
|
28
|
+
|
|
29
|
+
| Leaf | Renders | Nothing when |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `AddressSummaryRecipient` | who the delivery is addressed to | no recipient |
|
|
32
|
+
| `AddressSummaryStreet` | street, number, complement | all three absent |
|
|
33
|
+
| `AddressSummaryLocality` | neighborhood, city, state, postal code | all absent |
|
|
34
|
+
|
|
35
|
+
## Known gaps
|
|
36
|
+
|
|
37
|
+
Found by review and deliberately left for the dedicated revision of these components.
|
|
38
|
+
|
|
39
|
+
- **`AddressSummary` no longer enforces its own context requirement.** It stopped reading the context when
|
|
40
|
+
the lines became composable, so only the leaves throw now. `<AddressSummary><CustomLine /></AddressSummary>`
|
|
41
|
+
outside an `AddressSummaryRoot` renders an empty styled block instead of failing loudly, while the
|
|
42
|
+
definition still declares `requiresContext: 'address-summary'` — the declared contract and the runtime
|
|
43
|
+
check no longer agree.
|
|
44
|
+
- **`AddressSummaryRecipient`, `AddressSummaryStreet` and `AddressSummaryLocality` have no stories and no
|
|
45
|
+
test file of their own.** They are registered in the catalog but covered only indirectly, from
|
|
46
|
+
`shipping-address.test.tsx`. The `create-base-component` contract asks for both.
|
|
47
|
+
|
|
48
|
+
## Extensibility
|
|
49
|
+
|
|
50
|
+
A future alternative presentation (e.g., `LeanAddressSummary` or `AddressSummaryCompact`) could read the same `AddressSummaryRoot` context and be swapped in its place without any changes to the matter component that provides the `AddressSummaryRoot`. This is a composition change, not a new data-binding, and exemplifies the Free Particle Model (ADR-0001) — presentational components reused via context, uncoupled from business logic.
|