@vtex/faststore 0.0.5 → 0.0.6

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.
Files changed (232) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/dist/actions.json +181 -0
  3. package/dist/catalog.json +1543 -495
  4. package/dist/client.d.ts +2 -1
  5. package/dist/client.js +2 -1
  6. package/dist/components.d.ts +28 -7
  7. package/dist/components.js +31 -12
  8. package/dist/docs/access-code-sign-in.md +1 -1
  9. package/dist/docs/address-summary.md +24 -3
  10. package/dist/docs/alert-dialog.md +204 -0
  11. package/dist/docs/billing-address.md +284 -0
  12. package/dist/docs/card-entry.md +250 -0
  13. package/dist/docs/cardholder-document.md +142 -0
  14. package/dist/docs/client-preferences-fieldset.md +148 -0
  15. package/dist/docs/client-preferences.md +2 -1
  16. package/dist/docs/client-profile-fieldset.md +184 -0
  17. package/dist/docs/client-profile.md +1 -1
  18. package/dist/docs/document-field.md +58 -4
  19. package/dist/docs/field.md +317 -0
  20. package/dist/docs/form.md +307 -0
  21. package/dist/docs/identity-edit.md +6 -6
  22. package/dist/docs/identity-summary.md +5 -5
  23. package/dist/docs/installments.md +248 -0
  24. package/dist/docs/my-account-profile.md +1 -0
  25. package/dist/docs/order-placed-payment-summary.md +138 -0
  26. package/dist/docs/payment-method-badges.md +232 -0
  27. package/dist/docs/payment-methods.md +1 -0
  28. package/dist/docs/payment.md +218 -0
  29. package/dist/docs/phone-field.md +58 -4
  30. package/dist/docs/place-order.md +157 -0
  31. package/dist/docs/save-card.md +186 -0
  32. package/dist/docs/saved-cards.md +218 -0
  33. package/dist/docs/select.md +465 -0
  34. package/dist/docs/shipping-address.md +110 -258
  35. package/dist/index.d.ts +4 -1
  36. package/dist/internal/client.d.ts +3 -1
  37. package/dist/internal/client.js +3 -1
  38. package/dist/matter/access-code-sign-in/access-code-sign-in.js +9 -8
  39. package/dist/matter/access-code-sign-in/access-code-sign-in.js.map +1 -1
  40. package/dist/matter/billing-address/billing-address.d.ts +165 -0
  41. package/dist/matter/billing-address/billing-address.js +408 -0
  42. package/dist/matter/billing-address/billing-address.js.map +1 -0
  43. package/dist/matter/card-entry/card-capture.d.ts +25 -0
  44. package/dist/matter/card-entry/card-capture.js +25 -0
  45. package/dist/matter/card-entry/card-capture.js.map +1 -0
  46. package/dist/matter/card-entry/card-entry.d.ts +120 -0
  47. package/dist/matter/card-entry/card-entry.js +832 -0
  48. package/dist/matter/card-entry/card-entry.js.map +1 -0
  49. package/dist/matter/cardholder-document/cardholder-document.d.ts +45 -0
  50. package/dist/matter/cardholder-document/cardholder-document.js +70 -0
  51. package/dist/matter/cardholder-document/cardholder-document.js.map +1 -0
  52. package/dist/matter/client-preferences/client-preferences-fieldset.d.ts +77 -0
  53. package/dist/matter/client-preferences/client-preferences-fieldset.js +299 -0
  54. package/dist/matter/client-preferences/client-preferences-fieldset.js.map +1 -0
  55. package/dist/matter/client-preferences/client-preferences.d.ts +3 -5
  56. package/dist/matter/client-preferences/client-preferences.js +6 -6
  57. package/dist/matter/client-preferences/client-preferences.js.map +1 -1
  58. package/dist/matter/client-profile/client-profile.d.ts +4 -6
  59. package/dist/matter/client-profile/client-profile.js +9 -6
  60. package/dist/matter/client-profile/client-profile.js.map +1 -1
  61. package/dist/matter/client-profile-form/client-profile-fieldset.d.ts +119 -0
  62. package/dist/matter/client-profile-form/client-profile-fieldset.js +488 -0
  63. package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -0
  64. package/dist/matter/identity-edit/identity-edit.js +2 -2
  65. package/dist/matter/identity-edit/identity-edit.js.map +1 -1
  66. package/dist/matter/identity-summary/identity-summary.js +2 -2
  67. package/dist/matter/identity-summary/identity-summary.js.map +1 -1
  68. package/dist/matter/installments/installments-select.d.ts +42 -0
  69. package/dist/matter/installments/installments-select.js +167 -0
  70. package/dist/matter/installments/installments-select.js.map +1 -0
  71. package/dist/matter/installments/installments.d.ts +58 -0
  72. package/dist/matter/installments/installments.js +176 -0
  73. package/dist/matter/installments/installments.js.map +1 -0
  74. package/dist/matter/installments/use-installments-selection.d.ts +29 -0
  75. package/dist/matter/installments/use-installments-selection.js +95 -0
  76. package/dist/matter/installments/use-installments-selection.js.map +1 -0
  77. package/dist/matter/my-account-profile/my-account-profile.js +4 -4
  78. package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
  79. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +63 -0
  80. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +305 -0
  81. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -0
  82. package/dist/matter/payment/payment-card-capture.d.ts +19 -0
  83. package/dist/matter/payment/payment-card-capture.js +129 -0
  84. package/dist/matter/payment/payment-card-capture.js.map +1 -0
  85. package/dist/matter/payment/payment-controller.d.ts +24 -0
  86. package/dist/matter/payment/payment-controller.js +107 -0
  87. package/dist/matter/payment/payment-controller.js.map +1 -0
  88. package/dist/matter/payment/payment-method-badges.d.ts +57 -0
  89. package/dist/matter/payment/payment-method-badges.js +192 -0
  90. package/dist/matter/payment/payment-method-badges.js.map +1 -0
  91. package/dist/matter/payment/payment.d.ts +89 -0
  92. package/dist/matter/payment/payment.js +263 -0
  93. package/dist/matter/payment/payment.js.map +1 -0
  94. package/dist/matter/payment/use-payment-method-selection.d.ts +302 -0
  95. package/dist/matter/payment/use-payment-method-selection.js +458 -0
  96. package/dist/matter/payment/use-payment-method-selection.js.map +1 -0
  97. package/dist/matter/payment/use-payment-submit-gate.d.ts +111 -0
  98. package/dist/matter/payment/use-payment-submit-gate.js +144 -0
  99. package/dist/matter/payment/use-payment-submit-gate.js.map +1 -0
  100. package/dist/matter/place-order/place-order.d.ts +74 -0
  101. package/dist/matter/place-order/place-order.js +379 -0
  102. package/dist/matter/place-order/place-order.js.map +1 -0
  103. package/dist/matter/product-list/product-list.d.ts +1 -0
  104. package/dist/matter/product-list/product-list.js.map +1 -1
  105. package/dist/matter/product-shelf/product-shelf.d.ts +1 -0
  106. package/dist/matter/product-shelf/product-shelf.js +2 -0
  107. package/dist/matter/product-shelf/product-shelf.js.map +1 -1
  108. package/dist/matter/region/region.js +1 -1
  109. package/dist/matter/region/region.js.map +1 -1
  110. package/dist/matter/save-card/save-card.d.ts +49 -0
  111. package/dist/matter/save-card/save-card.js +188 -0
  112. package/dist/matter/save-card/save-card.js.map +1 -0
  113. package/dist/matter/saved-cards/saved-cards.d.ts +79 -0
  114. package/dist/matter/saved-cards/saved-cards.js +387 -0
  115. package/dist/matter/saved-cards/saved-cards.js.map +1 -0
  116. package/dist/matter/shipping-address/country-descriptors.js +20 -10
  117. package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
  118. package/dist/matter/shipping-address/shipping-address.d.ts +113 -174
  119. package/dist/matter/shipping-address/shipping-address.js +480 -791
  120. package/dist/matter/shipping-address/shipping-address.js.map +1 -1
  121. package/dist/matter/variant-selector/variant-selector.js +1 -1
  122. package/dist/particles/address-summary/address-summary.d.ts +24 -0
  123. package/dist/particles/address-summary/address-summary.js +83 -2
  124. package/dist/particles/address-summary/address-summary.js.map +1 -1
  125. package/dist/particles/alert-dialog/alert-dialog.d.ts +68 -0
  126. package/dist/particles/alert-dialog/alert-dialog.js +187 -0
  127. package/dist/particles/alert-dialog/alert-dialog.js.map +1 -0
  128. package/dist/particles/checkbox/checkbox.d.ts +7 -3
  129. package/dist/particles/checkbox/checkbox.js +4 -1
  130. package/dist/particles/checkbox/checkbox.js.map +1 -1
  131. package/dist/particles/document-field/document-field.d.ts +48 -5
  132. package/dist/particles/document-field/document-field.js +189 -32
  133. package/dist/particles/document-field/document-field.js.map +1 -1
  134. package/dist/particles/field/bound-field-registry.js +52 -0
  135. package/dist/particles/field/bound-field-registry.js.map +1 -0
  136. package/dist/particles/field/field.d.ts +116 -0
  137. package/dist/particles/field/field.js +497 -6
  138. package/dist/particles/field/field.js.map +1 -1
  139. package/dist/particles/fieldset/fieldset.js +2 -2
  140. package/dist/particles/fieldset/fieldset.js.map +1 -1
  141. package/dist/particles/form/form.d.ts +104 -0
  142. package/dist/particles/form/form.js +485 -0
  143. package/dist/particles/form/form.js.map +1 -0
  144. package/dist/particles/phone-field/phone-field.d.ts +38 -10
  145. package/dist/particles/phone-field/phone-field.js +183 -39
  146. package/dist/particles/phone-field/phone-field.js.map +1 -1
  147. package/dist/particles/postal-code-field/postal-code-field.js +2 -2
  148. package/dist/particles/postal-code-field/postal-code-field.js.map +1 -1
  149. package/dist/particles/select/field-select.d.ts +43 -0
  150. package/dist/particles/select/field-select.js +150 -0
  151. package/dist/particles/select/field-select.js.map +1 -0
  152. package/dist/particles/select/select.d.ts +2 -0
  153. package/dist/particles/select/select.js.map +1 -1
  154. package/dist/particles/shared/compose-refs.js +21 -0
  155. package/dist/particles/shared/compose-refs.js.map +1 -0
  156. package/dist/schema.graphql +701 -2
  157. package/dist/sdk/actions/analytics-action-provider.d.ts +15 -0
  158. package/dist/sdk/actions/analytics-action-provider.js +19 -0
  159. package/dist/sdk/actions/analytics-action-provider.js.map +1 -0
  160. package/dist/sdk/actions/index.d.ts +3 -1
  161. package/dist/sdk/actions/index.js +3 -1
  162. package/dist/sdk/actions/payment-action-provider.d.ts +22 -0
  163. package/dist/sdk/actions/payment-action-provider.js +26 -0
  164. package/dist/sdk/actions/payment-action-provider.js.map +1 -0
  165. package/dist/sdk/actions/types.d.ts +6 -2
  166. package/dist/sdk/analytics/analytics-destination.d.ts +43 -0
  167. package/dist/sdk/analytics/analytics-destination.js +90 -0
  168. package/dist/sdk/analytics/analytics-destination.js.map +1 -0
  169. package/dist/sdk/analytics/use-analytics-actions.d.ts +57 -0
  170. package/dist/sdk/analytics/use-analytics-actions.js +108 -0
  171. package/dist/sdk/analytics/use-analytics-actions.js.map +1 -0
  172. package/dist/sdk/cart/use-cart-actions.js +1 -1
  173. package/dist/sdk/data/entity-resolution-context.js +31 -0
  174. package/dist/sdk/data/entity-resolution-context.js.map +1 -0
  175. package/dist/sdk/data/entity-subscriber.js +18 -8
  176. package/dist/sdk/data/entity-subscriber.js.map +1 -1
  177. package/dist/sdk/data/index.js +1 -0
  178. package/dist/sdk/data/page-reactive-data-root.d.ts +36 -0
  179. package/dist/sdk/data/page-reactive-data-root.js +4 -2
  180. package/dist/sdk/data/page-reactive-data-root.js.map +1 -1
  181. package/dist/sdk/data/reactive-data-provider.js +7 -3
  182. package/dist/sdk/data/reactive-data-provider.js.map +1 -1
  183. package/dist/sdk/data/reactive-list-item-data-provider.js +12 -4
  184. package/dist/sdk/data/reactive-list-item-data-provider.js.map +1 -1
  185. package/dist/sdk/data/use-reactive-data-settled.js +39 -0
  186. package/dist/sdk/data/use-reactive-data-settled.js.map +1 -0
  187. package/dist/sdk/data/use-reactive-entity.js +5 -1
  188. package/dist/sdk/data/use-reactive-entity.js.map +1 -1
  189. package/dist/sdk/generated/fragment-types.js +2 -0
  190. package/dist/sdk/generated/fragment-types.js.map +1 -1
  191. package/dist/sdk/generated/graphql.js.map +1 -1
  192. package/dist/sdk/i18n/messages/en-US.js +3 -0
  193. package/dist/sdk/i18n/messages/en-US.json +3 -0
  194. package/dist/sdk/i18n/messages/en-US.json.d.ts +3 -0
  195. package/dist/sdk/i18n/messages/es-ES.js +3 -0
  196. package/dist/sdk/i18n/messages/es-ES.json +3 -0
  197. package/dist/sdk/i18n/messages/pt-BR.js +3 -0
  198. package/dist/sdk/i18n/messages/pt-BR.json +3 -0
  199. package/dist/sdk/identity/use-identity-actions.js +3 -2
  200. package/dist/sdk/identity/use-identity-actions.js.map +1 -1
  201. package/dist/sdk/payment/gateway-origin.js +35 -0
  202. package/dist/sdk/payment/gateway-origin.js.map +1 -0
  203. package/dist/sdk/payment/gateway.d.ts +85 -0
  204. package/dist/sdk/payment/gateway.js +183 -0
  205. package/dist/sdk/payment/gateway.js.map +1 -0
  206. package/dist/sdk/payment/operations.d.ts +52 -0
  207. package/dist/sdk/payment/operations.js +223 -0
  208. package/dist/sdk/payment/operations.js.map +1 -0
  209. package/dist/sdk/payment/security-code-mask.js +71 -0
  210. package/dist/sdk/payment/security-code-mask.js.map +1 -0
  211. package/dist/sdk/payment/submission-registry.d.ts +33 -0
  212. package/dist/sdk/payment/submission-registry.js +58 -0
  213. package/dist/sdk/payment/submission-registry.js.map +1 -0
  214. package/dist/sdk/payment/use-payment-actions.d.ts +78 -0
  215. package/dist/sdk/payment/use-payment-actions.js +276 -0
  216. package/dist/sdk/payment/use-payment-actions.js.map +1 -0
  217. package/dist/sdk/payment/use-place-order.d.ts +65 -0
  218. package/dist/sdk/payment/use-place-order.js +640 -0
  219. package/dist/sdk/payment/use-place-order.js.map +1 -0
  220. package/dist/sdk/shipping/use-shipping-actions.js +1 -1
  221. package/dist/utils/loggable-error-name.js +49 -0
  222. package/dist/utils/loggable-error-name.js.map +1 -0
  223. package/dist/utils/resolve-authored-copy.js +18 -0
  224. package/dist/utils/resolve-authored-copy.js.map +1 -0
  225. package/dist/utils/substitute-template.js +33 -0
  226. package/dist/utils/substitute-template.js.map +1 -0
  227. package/package.json +2 -1
  228. package/src/styles/tailwind.css +34 -0
  229. package/dist/docs/client-profile-form.md +0 -192
  230. package/dist/matter/client-profile-form/client-profile-form.d.ts +0 -126
  231. package/dist/matter/client-profile-form/client-profile-form.js +0 -662
  232. package/dist/matter/client-profile-form/client-profile-form.js.map +0 -1
@@ -5,6 +5,7 @@ import { AccessCodeField } from "../../particles/access-code-field/access-code-f
5
5
  import { EmailField, isValidEmail } from "../../particles/email-field/email-field.js";
6
6
  import { useActionsOverride } from "../../sdk/actions/actions-override-context.js";
7
7
  import { useDataOverride } from "../../sdk/data/data-override-context.js";
8
+ import { resolveAuthoredCopy } from "../../utils/resolve-authored-copy.js";
8
9
  import { useSession } from "../session/session.js";
9
10
  import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
10
11
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -35,18 +36,18 @@ function useAccessCodeSignIn() {
35
36
  }
36
37
  function requestErrorMessage(error, props) {
37
38
  switch (error.code) {
38
- case "ACCESS_CODE_SEND_LIMIT": return props.sendLimitMessage ?? error.message;
39
- case "BLOCKED": return props.blockedMessage ?? error.message;
40
- case "NETWORK_ERROR": return props.networkErrorMessage ?? error.message;
39
+ case "ACCESS_CODE_SEND_LIMIT": return resolveAuthoredCopy(props.sendLimitMessage, error.message);
40
+ case "BLOCKED": return resolveAuthoredCopy(props.blockedMessage, error.message);
41
+ case "NETWORK_ERROR": return resolveAuthoredCopy(props.networkErrorMessage, error.message);
41
42
  default: return error.message;
42
43
  }
43
44
  }
44
45
  function validateErrorMessage(error, props) {
45
46
  switch (error.code) {
46
- case "INVALID_ACCESS_CODE": return props.invalidCodeMessage ?? error.message;
47
- case "BLOCKED": return props.blockedMessage ?? error.message;
48
- case "MISSING_AUTH_CONTEXT": return props.missingAuthContextMessage ?? error.message;
49
- case "NETWORK_ERROR": return props.networkErrorMessage ?? error.message;
47
+ case "INVALID_ACCESS_CODE": return resolveAuthoredCopy(props.invalidCodeMessage, error.message);
48
+ case "BLOCKED": return resolveAuthoredCopy(props.blockedMessage, error.message);
49
+ case "MISSING_AUTH_CONTEXT": return resolveAuthoredCopy(props.missingAuthContextMessage, error.message);
50
+ case "NETWORK_ERROR": return resolveAuthoredCopy(props.networkErrorMessage, error.message);
50
51
  default: return error.message;
51
52
  }
52
53
  }
@@ -295,7 +296,7 @@ function AccessCodeRequestControl({ label, pendingLabel, sendLimitMessage, block
295
296
  "aria-busy": pending || void 0,
296
297
  "data-fs-access-code-request-submit": "",
297
298
  "data-fs-button": "",
298
- children: pending ? pendingLabel ?? label : label
299
+ children: pending ? resolveAuthoredCopy(pendingLabel, label ?? "") : label
299
300
  }), message ? /* @__PURE__ */ jsx("div", {
300
301
  role: "alert",
301
302
  "data-fs-access-code-request-error": "",
@@ -1 +1 @@
1
- {"version":3,"file":"access-code-sign-in.js","names":[],"sources":["../../../src/matter/access-code-sign-in/access-code-sign-in.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef, FormEvent } from 'react';\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';\nimport { AccessCodeField } from '../../particles/access-code-field/access-code-field.js';\nimport { EmailField, isValidEmail } from '../../particles/email-field/email-field.js';\nimport { useActionsOverride } from '../../sdk/actions/actions-override-context.js';\nimport type { ComponentActions } from '../../sdk/actions/types.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport type { SessionUserError } from '../../sdk/session/auth-operations.js';\nimport { useSession } from '../session/session.js';\n\n// ---------------------------------------------------------------------------\n// GraphQL Fragment (colocated, ADR-0011) — clientProfile.email seeds the draft email as a\n// convenience pre-fill for an already-identified shopper; sessionAuthProviders.accessKeyAuthentication\n// is the account gate. Authored as a raw string, mirroring EmailIdentificationControl/ShippingSimulator.\n// ---------------------------------------------------------------------------\n\nconst fragment = /* GraphQL */ `\n fragment AccessCodeSignInData on Query {\n clientProfile {\n __typename\n id\n email\n }\n sessionAuthProviders {\n accessKeyAuthentication\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Colocated fragment slice forwarded by the reactive runtime — `null` until both fields resolve. */\nexport type AccessCodeSignInSlice = {\n clientProfile: { email: string | null } | null;\n sessionAuthProviders: { accessKeyAuthentication: boolean } | null;\n};\n\nexport type AccessCodeSignInStep = 'request' | 'validate';\n\nexport type AccessCodeSignInContextValue = Readonly<{\n /** The shopper's locally-typed draft email — never written to the cart; only ever an argument to\n * requestAccessCode/validateAccessCode. Pre-fills from `clientProfile.email` when known, but a\n * shopper edit is never persisted anywhere by this family. */\n email: string;\n /** Updates the draft email; marks it as shopper-touched so pre-fill no longer overwrites it. */\n setEmail: (email: string) => void;\n step: AccessCodeSignInStep;\n /** Opaque token round-tripped from requestAccessCode into validateAccessCode. */\n authenticationToken: string | null;\n /** Called by AccessCodeRequestControl on a successful requestAccessCode. */\n startValidation: (authenticationToken: string) => void;\n}>;\n\nexport type AccessCodeSignInRootProps = ComponentPropsWithRef<'div'> & {\n $data?: AccessCodeSignInSlice | null;\n};\n\nexport type AccessCodeEmailControlProps = ComponentPropsWithRef<'div'> & {\n label?: string;\n placeholder?: string;\n invalidEmailMessage?: string;\n};\n\nexport type AccessCodeRequestControlProps = ComponentPropsWithRef<'div'> & {\n label?: string;\n pendingLabel?: string;\n sendLimitMessage?: string;\n blockedMessage?: string;\n networkErrorMessage?: string;\n onRequested?: (authenticationToken: string) => void;\n $actions?: ComponentActions;\n};\n\nexport type AccessCodeValidateControlProps = ComponentPropsWithRef<'div'> & {\n label?: string;\n placeholder?: string;\n submitLabel?: string;\n codeLength?: number;\n invalidCodeMessage?: string;\n blockedMessage?: string;\n missingAuthContextMessage?: string;\n networkErrorMessage?: string;\n onValidated?: () => void;\n $actions?: ComponentActions;\n};\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst ACCESS_CODE_SIGN_IN_CONTEXT_UNSET = Symbol('AccessCodeSignInContextUnset');\n\nconst AccessCodeSignInContext = createContext<AccessCodeSignInContextValue | typeof ACCESS_CODE_SIGN_IN_CONTEXT_UNSET>(\n ACCESS_CODE_SIGN_IN_CONTEXT_UNSET,\n);\n\n/**\n * Read the stepper state (email, step, authenticationToken) from the nearest `AccessCodeSignInRoot`.\n * Throws when called outside that subtree — a misplaced control is a composition bug that should\n * surface immediately, mirroring `useShippingSimulator()`/`useSession()`.\n */\nfunction useAccessCodeSignIn(): AccessCodeSignInContextValue {\n const ctx = useContext(AccessCodeSignInContext);\n if (ctx === ACCESS_CODE_SIGN_IN_CONTEXT_UNSET) {\n throw new Error('AccessCodeSignIn components must be used inside AccessCodeSignInRoot.');\n }\n return ctx;\n}\n\n// ---------------------------------------------------------------------------\n// Error-code → message mapping — every failure surfaces inline, at the control that produced it;\n// an unmapped code falls back to the server-supplied message rather than being silent.\n// ---------------------------------------------------------------------------\n\nfunction requestErrorMessage(\n error: SessionUserError,\n props: Pick<AccessCodeRequestControlProps, 'sendLimitMessage' | 'blockedMessage' | 'networkErrorMessage'>,\n): string {\n switch (error.code) {\n case 'ACCESS_CODE_SEND_LIMIT':\n return props.sendLimitMessage ?? error.message;\n case 'BLOCKED':\n return props.blockedMessage ?? error.message;\n case 'NETWORK_ERROR':\n return props.networkErrorMessage ?? error.message;\n default:\n return error.message;\n }\n}\n\nfunction validateErrorMessage(\n error: SessionUserError,\n props: Pick<\n AccessCodeValidateControlProps,\n 'invalidCodeMessage' | 'blockedMessage' | 'missingAuthContextMessage' | 'networkErrorMessage'\n >,\n): string {\n switch (error.code) {\n case 'INVALID_ACCESS_CODE':\n return props.invalidCodeMessage ?? error.message;\n case 'BLOCKED':\n return props.blockedMessage ?? error.message;\n case 'MISSING_AUTH_CONTEXT':\n return props.missingAuthContextMessage ?? error.message;\n case 'NETWORK_ERROR':\n return props.networkErrorMessage ?? error.message;\n default:\n return error.message;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Definitions\n// ---------------------------------------------------------------------------\n\nexport const AccessCodeSignInRootDefinition = defineComponent<AccessCodeSignInRootProps>({\n name: 'AccessCodeSignInRoot',\n importPath: '@vtex/faststore/components',\n component: AccessCodeSignInRoot,\n fragment,\n fetchStrategy: 'reactive',\n requiresContext: 'session',\n editor: { label: 'Access Code Sign-In', category: 'identity' },\n schema: {},\n guideline:\n 'Self-gating root of the anonymous-or-identified, email + access-code sign-in: renders nothing once loggedIn or when the account disables accessKeyAuthentication, but is available from the anonymous state onward. Owns a locally-typed draft email (never written to the cart) and the request/validate stepper. Must be inside SessionRoot. See access-code-sign-in.md.',\n});\n\nexport const AccessCodeEmailControlDefinition = defineComponent<AccessCodeEmailControlProps>({\n name: 'AccessCodeEmailControl',\n importPath: '@vtex/faststore/components',\n component: AccessCodeEmailControl,\n editor: { label: 'Access Code Email', category: 'identity' },\n schema: {\n label: { type: 'string', label: 'Label' },\n placeholder: { type: 'string', label: 'Placeholder' },\n invalidEmailMessage: { type: 'string', label: 'Invalid email message' },\n },\n guideline:\n 'The draft email input for the access-code flow: visible only at the request step, pre-fills from clientProfile.email when known but never persists an edit anywhere — it is purely the argument requestAccessCode/validateAccessCode dispatch with. Must be inside AccessCodeSignInRoot. See access-code-sign-in.md.',\n});\n\nexport const AccessCodeRequestControlDefinition = defineComponent<AccessCodeRequestControlProps>({\n name: 'AccessCodeRequestControl',\n importPath: '@vtex/faststore/components',\n component: AccessCodeRequestControl,\n actions: { session: ['requestAccessCode'] },\n editor: { label: 'Access Code Request', category: 'identity' },\n schema: {\n label: { type: 'string', label: 'Label' },\n sendLimitMessage: { type: 'string', label: 'Send-limit message' },\n blockedMessage: { type: 'string', label: 'Blocked message' },\n networkErrorMessage: { type: 'string', label: 'Network error message' },\n },\n guideline:\n 'Send-code step: disabled until the Root-owned draft email is a valid, non-empty address; dispatches $actions.session.requestAccessCode with it and advances the stepper on success. Failures render inline, never as a blocking error. Must be inside AccessCodeSignInRoot. See access-code-sign-in.md.',\n});\n\nexport const AccessCodeValidateControlDefinition = defineComponent<AccessCodeValidateControlProps>({\n name: 'AccessCodeValidateControl',\n importPath: '@vtex/faststore/components',\n component: AccessCodeValidateControl,\n actions: { session: ['validateAccessCode'] },\n editor: { label: 'Access Code Validate', category: 'identity' },\n schema: {\n label: { type: 'string', label: 'Label' },\n placeholder: { type: 'string', label: 'Placeholder' },\n submitLabel: { type: 'string', label: 'Submit label' },\n codeLength: { type: 'number', default: 6, label: 'Code length' },\n invalidCodeMessage: { type: 'string', label: 'Invalid code message' },\n blockedMessage: { type: 'string', label: 'Blocked message' },\n networkErrorMessage: { type: 'string', label: 'Network error message' },\n },\n guideline:\n 'Code-entry step: composes AccessCodeField and dispatches $actions.session.validateAccessCode with the Root-owned email and authenticationToken; a successful validate flips the session reactively and hides the Root. Must be inside AccessCodeSignInRoot. See access-code-sign-in.md.',\n});\n\n// ---------------------------------------------------------------------------\n// Implementations\n// ---------------------------------------------------------------------------\n\n/**\n * Data-owning root of the access-code sign-in flow. Self-gates on two signals:\n * `useSession().state !== 'loggedIn'` (available from anonymous through identified; hides once\n * signed in) and `sessionAuthProviders.accessKeyAuthentication === true`. An unresolved fragment\n * read (`$data` still `null`) is treated as \"provider not enabled\" — the flow stays hidden rather\n * than flashing. Owns the `step`/`authenticationToken` stepper plus a locally-typed draft `email`\n * as local state, broadcasting all of it through context to its children. The draft email pre-fills\n * from `clientProfile.email` once (for an already-identified shopper) but a shopper edit is never\n * persisted anywhere by this family — it is purely the requestAccessCode/validateAccessCode\n * argument; the server sets clientProfileData.email as a side effect of a successful validate.\n * Reacts automatically once `useSession()` flips to `loggedIn` — no manual unmount call anywhere in\n * this family.\n */\nexport function AccessCodeSignInRoot({ $data: $dataProp, className, children, ...props }: AccessCodeSignInRootProps) {\n const $data = useDataOverride($dataProp);\n const { state } = useSession();\n\n const [step, setStep] = useState<AccessCodeSignInStep>('request');\n const [authenticationToken, setAuthenticationToken] = useState<string | null>(null);\n\n const startValidation = useCallback((token: string) => {\n setAuthenticationToken(token);\n setStep('validate');\n }, []);\n\n const savedEmail = $data?.clientProfile?.email ?? '';\n const [email, setEmailState] = useState('');\n const [touched, setTouched] = useState(false);\n\n // Pre-fill from the resolving/known profile email, but only while still at the request step and\n // until the shopper edits the draft — mirrors ClientProfileForm's untouched-field re-seed, never\n // clobbering an in-progress edit. Freezing the re-seed once the flow leaves 'request' keeps a\n // mid-flow profile-cache change from diverging the email between requestAccessCode and\n // validateAccessCode (the server rejects a validate whose email differs from the request).\n useEffect(() => {\n if (step === 'request' && !touched) setEmailState(savedEmail);\n }, [savedEmail, touched, step]);\n\n const setEmail = useCallback((next: string) => {\n setTouched(true);\n setEmailState(next);\n }, []);\n\n const providerEnabled = $data?.sessionAuthProviders?.accessKeyAuthentication ?? false;\n\n const contextValue = useMemo<AccessCodeSignInContextValue>(\n () => ({ email, setEmail, step, authenticationToken, startValidation }),\n [email, setEmail, step, authenticationToken, startValidation],\n );\n\n const gated = state !== 'loggedIn' && providerEnabled;\n if (!gated) return null;\n\n return (\n <AccessCodeSignInContext value={contextValue}>\n <div {...props} className={className} data-fs-access-code-sign-in-root=\"\">\n {children}\n </div>\n </AccessCodeSignInContext>\n );\n}\n\n/**\n * The draft email input for the access-code flow. Renders only at the request step. Bound to the\n * Root's local `email`/`setEmail` — never a fragment, never a mutation of its own; typing here\n * never touches the cart. Format validation is `EmailField`'s own blur-triggered check (never\n * per-keystroke); `invalidEmailMessage` is only its fallback text, mirroring how\n * `EmailIdentificationControl` defers to the same particle for the same reason.\n */\nexport function AccessCodeEmailControl({\n label,\n placeholder,\n invalidEmailMessage,\n className,\n ...props\n}: AccessCodeEmailControlProps) {\n const { step, email, setEmail } = useAccessCodeSignIn();\n\n if (step !== 'request') return null;\n\n return (\n <div {...props} className={className} data-fs-access-code-email-control=\"\">\n <EmailField\n label={label}\n placeholder={placeholder}\n value={email}\n onValueChange={setEmail}\n errorMessage={invalidEmailMessage}\n />\n </div>\n );\n}\n\n/**\n * Renders only while the Root's stepper is at `step === 'request'`. Reads the draft email from\n * context and dispatches `$actions.session.requestAccessCode({ email })` once it is a valid,\n * non-empty address (no account-existence pre-check beyond that format gate). On a result with a\n * non-null token and no `userErrors`, advances the Root's stepper. Every `userErrors` entry renders\n * inline via a host-supplied, per-code message; the step never changes on error, so the shopper can\n * retry or abandon the method and continue as a guest.\n */\nexport function AccessCodeRequestControl({\n label,\n pendingLabel,\n sendLimitMessage,\n blockedMessage,\n networkErrorMessage,\n onRequested,\n $actions: $actionsProp,\n className,\n ...props\n}: AccessCodeRequestControlProps) {\n const $actions = useActionsOverride($actionsProp);\n const { step, email, startValidation } = useAccessCodeSignIn();\n const [pending, setPending] = useState(false);\n const [error, setError] = useState<SessionUserError | null>(null);\n\n if (step !== 'request') return null;\n\n const canSubmit = !pending && isValidEmail(email);\n\n async function handleClick() {\n if (!canSubmit) return;\n setPending(true);\n setError(null);\n\n try {\n const result = (await $actions?.session?.requestAccessCode?.({ email })) ?? {\n authenticationToken: null,\n userErrors: [],\n };\n\n if (result.authenticationToken && result.userErrors.length === 0) {\n startValidation(result.authenticationToken);\n onRequested?.(result.authenticationToken);\n return;\n }\n\n const [firstError] = result.userErrors;\n if (firstError) setError(firstError);\n } finally {\n setPending(false);\n }\n }\n\n const message = error ? requestErrorMessage(error, { sendLimitMessage, blockedMessage, networkErrorMessage }) : null;\n\n return (\n <div\n {...props}\n className={className}\n data-fs-access-code-request-control=\"\"\n {...(pending ? { 'data-fs-access-code-request-pending': '' } : {})}\n >\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={!canSubmit}\n aria-busy={pending || undefined}\n data-fs-access-code-request-submit=\"\"\n data-fs-button=\"\"\n >\n {pending ? (pendingLabel ?? label) : label}\n </button>\n {message ? (\n <div role=\"alert\" data-fs-access-code-request-error=\"\">\n {message}\n </div>\n ) : null}\n </div>\n );\n}\n\n/**\n * Renders only while the Root's stepper is at `step === 'validate'`. Composes `AccessCodeField` for\n * the code value and a submit control, disabled below `codeLength` (a UX courtesy, never a\n * validity claim). Dispatches `$actions.session.validateAccessCode` with the email and\n * `authenticationToken` read from context. On a non-empty `userErrors` result, sets the field's\n * `invalid`/`errorMessage` from a host-supplied per-code message and retains the code/token so the\n * shopper can retry without re-requesting. On success it calls the optional `onValidated` and renders\n * no local \"success\" UI — `useSession()` flipping to `loggedIn` is what makes the whole Root\n * disappear.\n */\nexport function AccessCodeValidateControl({\n label,\n placeholder,\n submitLabel,\n codeLength = 6,\n invalidCodeMessage,\n blockedMessage,\n missingAuthContextMessage,\n networkErrorMessage,\n onValidated,\n $actions: $actionsProp,\n className,\n ...props\n}: AccessCodeValidateControlProps) {\n const $actions = useActionsOverride($actionsProp);\n const { step, email, authenticationToken } = useAccessCodeSignIn();\n const [code, setCode] = useState('');\n const [pending, setPending] = useState(false);\n const [error, setError] = useState<SessionUserError | null>(null);\n\n if (step !== 'validate') return null;\n\n const canSubmit = !pending && code.length >= codeLength && authenticationToken != null;\n\n async function handleSubmit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n if (!canSubmit || authenticationToken == null) return;\n\n setPending(true);\n setError(null);\n\n try {\n const errors =\n (await $actions?.session?.validateAccessCode?.({ email, accessCode: code, authenticationToken })) ?? [];\n\n const [firstError] = errors;\n if (firstError) {\n setError(firstError);\n return;\n }\n } finally {\n setPending(false);\n }\n\n onValidated?.();\n }\n\n function handleCodeChange(next: string) {\n setCode(next);\n if (error) setError(null);\n }\n\n const errorMessage = error\n ? validateErrorMessage(error, {\n invalidCodeMessage,\n blockedMessage,\n missingAuthContextMessage,\n networkErrorMessage,\n })\n : undefined;\n\n return (\n <div\n {...props}\n className={className}\n data-fs-access-code-validate-control=\"\"\n {...(pending ? { 'data-fs-access-code-validate-pending': '' } : {})}\n >\n <form onSubmit={handleSubmit}>\n <AccessCodeField\n label={label}\n placeholder={placeholder}\n value={code}\n maxLength={codeLength}\n onValueChange={handleCodeChange}\n disabled={pending}\n invalid={error != null}\n errorMessage={errorMessage}\n />\n <button\n type=\"submit\"\n disabled={!canSubmit}\n aria-busy={pending || undefined}\n data-fs-access-code-validate-submit=\"\"\n data-fs-button=\"\"\n >\n {submitLabel}\n </button>\n </form>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Namespace export\n// ---------------------------------------------------------------------------\n\nexport const AccessCodeSignIn = {\n Root: AccessCodeSignInRoot,\n Email: AccessCodeEmailControl,\n Request: AccessCodeRequestControl,\n Validate: AccessCodeValidateControl,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"access-code-sign-in.js","names":[],"sources":["../../../src/matter/access-code-sign-in/access-code-sign-in.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef, FormEvent } from 'react';\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';\nimport { AccessCodeField } from '../../particles/access-code-field/access-code-field.js';\nimport { EmailField, isValidEmail } from '../../particles/email-field/email-field.js';\nimport { useActionsOverride } from '../../sdk/actions/actions-override-context.js';\nimport type { ComponentActions } from '../../sdk/actions/types.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport type { SessionUserError } from '../../sdk/session/auth-operations.js';\nimport { resolveAuthoredCopy } from '../../utils/resolve-authored-copy.js';\nimport { useSession } from '../session/session.js';\n\n// ---------------------------------------------------------------------------\n// GraphQL Fragment (colocated, ADR-0011) — clientProfile.email seeds the draft email as a\n// convenience pre-fill for an already-identified shopper; sessionAuthProviders.accessKeyAuthentication\n// is the account gate. Authored as a raw string, mirroring EmailIdentificationControl/ShippingSimulator.\n// ---------------------------------------------------------------------------\n\nconst fragment = /* GraphQL */ `\n fragment AccessCodeSignInData on Query {\n clientProfile {\n __typename\n id\n email\n }\n sessionAuthProviders {\n accessKeyAuthentication\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Colocated fragment slice forwarded by the reactive runtime — `null` until both fields resolve. */\nexport type AccessCodeSignInSlice = {\n clientProfile: { email: string | null } | null;\n sessionAuthProviders: { accessKeyAuthentication: boolean } | null;\n};\n\nexport type AccessCodeSignInStep = 'request' | 'validate';\n\nexport type AccessCodeSignInContextValue = Readonly<{\n /** The shopper's locally-typed draft email — never written to the cart; only ever an argument to\n * requestAccessCode/validateAccessCode. Pre-fills from `clientProfile.email` when known, but a\n * shopper edit is never persisted anywhere by this family. */\n email: string;\n /** Updates the draft email; marks it as shopper-touched so pre-fill no longer overwrites it. */\n setEmail: (email: string) => void;\n step: AccessCodeSignInStep;\n /** Opaque token round-tripped from requestAccessCode into validateAccessCode. */\n authenticationToken: string | null;\n /** Called by AccessCodeRequestControl on a successful requestAccessCode. */\n startValidation: (authenticationToken: string) => void;\n}>;\n\nexport type AccessCodeSignInRootProps = ComponentPropsWithRef<'div'> & {\n $data?: AccessCodeSignInSlice | null;\n};\n\nexport type AccessCodeEmailControlProps = ComponentPropsWithRef<'div'> & {\n label?: string;\n placeholder?: string;\n invalidEmailMessage?: string;\n};\n\nexport type AccessCodeRequestControlProps = ComponentPropsWithRef<'div'> & {\n label?: string;\n pendingLabel?: string;\n sendLimitMessage?: string;\n blockedMessage?: string;\n networkErrorMessage?: string;\n onRequested?: (authenticationToken: string) => void;\n $actions?: ComponentActions;\n};\n\nexport type AccessCodeValidateControlProps = ComponentPropsWithRef<'div'> & {\n label?: string;\n placeholder?: string;\n submitLabel?: string;\n codeLength?: number;\n invalidCodeMessage?: string;\n blockedMessage?: string;\n missingAuthContextMessage?: string;\n networkErrorMessage?: string;\n onValidated?: () => void;\n $actions?: ComponentActions;\n};\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst ACCESS_CODE_SIGN_IN_CONTEXT_UNSET = Symbol('AccessCodeSignInContextUnset');\n\nconst AccessCodeSignInContext = createContext<AccessCodeSignInContextValue | typeof ACCESS_CODE_SIGN_IN_CONTEXT_UNSET>(\n ACCESS_CODE_SIGN_IN_CONTEXT_UNSET,\n);\n\n/**\n * Read the stepper state (email, step, authenticationToken) from the nearest `AccessCodeSignInRoot`.\n * Throws when called outside that subtree — a misplaced control is a composition bug that should\n * surface immediately, mirroring `useShippingSimulator()`/`useSession()`.\n */\nfunction useAccessCodeSignIn(): AccessCodeSignInContextValue {\n const ctx = useContext(AccessCodeSignInContext);\n if (ctx === ACCESS_CODE_SIGN_IN_CONTEXT_UNSET) {\n throw new Error('AccessCodeSignIn components must be used inside AccessCodeSignInRoot.');\n }\n return ctx;\n}\n\n// ---------------------------------------------------------------------------\n// Error-code → message mapping — every failure surfaces inline, at the control that produced it;\n// an unmapped code falls back to the server-supplied message rather than being silent. Each mapped\n// case is resolved through `resolveAuthoredCopy` (T38, FR-5): an authored empty or whitespace-only\n// message falls back to the server-supplied `error.message` rather than rendering a blank alert.\n// ---------------------------------------------------------------------------\n\nfunction requestErrorMessage(\n error: SessionUserError,\n props: Pick<AccessCodeRequestControlProps, 'sendLimitMessage' | 'blockedMessage' | 'networkErrorMessage'>,\n): string {\n switch (error.code) {\n case 'ACCESS_CODE_SEND_LIMIT':\n return resolveAuthoredCopy(props.sendLimitMessage, error.message);\n case 'BLOCKED':\n return resolveAuthoredCopy(props.blockedMessage, error.message);\n case 'NETWORK_ERROR':\n return resolveAuthoredCopy(props.networkErrorMessage, error.message);\n default:\n return error.message;\n }\n}\n\nfunction validateErrorMessage(\n error: SessionUserError,\n props: Pick<\n AccessCodeValidateControlProps,\n 'invalidCodeMessage' | 'blockedMessage' | 'missingAuthContextMessage' | 'networkErrorMessage'\n >,\n): string {\n switch (error.code) {\n case 'INVALID_ACCESS_CODE':\n return resolveAuthoredCopy(props.invalidCodeMessage, error.message);\n case 'BLOCKED':\n return resolveAuthoredCopy(props.blockedMessage, error.message);\n case 'MISSING_AUTH_CONTEXT':\n return resolveAuthoredCopy(props.missingAuthContextMessage, error.message);\n case 'NETWORK_ERROR':\n return resolveAuthoredCopy(props.networkErrorMessage, error.message);\n default:\n return error.message;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Definitions\n// ---------------------------------------------------------------------------\n\nexport const AccessCodeSignInRootDefinition = defineComponent<AccessCodeSignInRootProps>({\n name: 'AccessCodeSignInRoot',\n importPath: '@vtex/faststore/components',\n component: AccessCodeSignInRoot,\n fragment,\n fetchStrategy: 'reactive',\n requiresContext: 'session',\n editor: { label: 'Access Code Sign-In', category: 'identity' },\n schema: {},\n guideline:\n 'Self-gating root of the anonymous-or-identified, email + access-code sign-in: renders nothing once loggedIn or when the account disables accessKeyAuthentication, but is available from the anonymous state onward. Owns a locally-typed draft email (never written to the cart) and the request/validate stepper. Must be inside SessionRoot. See access-code-sign-in.md.',\n});\n\nexport const AccessCodeEmailControlDefinition = defineComponent<AccessCodeEmailControlProps>({\n name: 'AccessCodeEmailControl',\n importPath: '@vtex/faststore/components',\n component: AccessCodeEmailControl,\n editor: { label: 'Access Code Email', category: 'identity' },\n schema: {\n label: { type: 'string', label: 'Label' },\n placeholder: { type: 'string', label: 'Placeholder' },\n invalidEmailMessage: { type: 'string', label: 'Invalid email message' },\n },\n guideline:\n 'The draft email input for the access-code flow: visible only at the request step, pre-fills from clientProfile.email when known but never persists an edit anywhere — it is purely the argument requestAccessCode/validateAccessCode dispatch with. Must be inside AccessCodeSignInRoot. See access-code-sign-in.md.',\n});\n\nexport const AccessCodeRequestControlDefinition = defineComponent<AccessCodeRequestControlProps>({\n name: 'AccessCodeRequestControl',\n importPath: '@vtex/faststore/components',\n component: AccessCodeRequestControl,\n actions: { session: ['requestAccessCode'] },\n editor: { label: 'Access Code Request', category: 'identity' },\n schema: {\n label: { type: 'string', label: 'Label' },\n sendLimitMessage: { type: 'string', label: 'Send-limit message' },\n blockedMessage: { type: 'string', label: 'Blocked message' },\n networkErrorMessage: { type: 'string', label: 'Network error message' },\n },\n guideline:\n 'Send-code step: disabled until the Root-owned draft email is a valid, non-empty address; dispatches $actions.session.requestAccessCode with it and advances the stepper on success. Failures render inline, never as a blocking error. Must be inside AccessCodeSignInRoot. See access-code-sign-in.md.',\n});\n\nexport const AccessCodeValidateControlDefinition = defineComponent<AccessCodeValidateControlProps>({\n name: 'AccessCodeValidateControl',\n importPath: '@vtex/faststore/components',\n component: AccessCodeValidateControl,\n actions: { session: ['validateAccessCode'] },\n editor: { label: 'Access Code Validate', category: 'identity' },\n schema: {\n label: { type: 'string', label: 'Label' },\n placeholder: { type: 'string', label: 'Placeholder' },\n submitLabel: { type: 'string', label: 'Submit label' },\n codeLength: { type: 'number', default: 6, label: 'Code length' },\n invalidCodeMessage: { type: 'string', label: 'Invalid code message' },\n blockedMessage: { type: 'string', label: 'Blocked message' },\n networkErrorMessage: { type: 'string', label: 'Network error message' },\n },\n guideline:\n 'Code-entry step: composes AccessCodeField and dispatches $actions.session.validateAccessCode with the Root-owned email and authenticationToken; a successful validate flips the session reactively and hides the Root. Must be inside AccessCodeSignInRoot. See access-code-sign-in.md.',\n});\n\n// ---------------------------------------------------------------------------\n// Implementations\n// ---------------------------------------------------------------------------\n\n/**\n * Data-owning root of the access-code sign-in flow. Self-gates on two signals:\n * `useSession().state !== 'loggedIn'` (available from anonymous through identified; hides once\n * signed in) and `sessionAuthProviders.accessKeyAuthentication === true`. An unresolved fragment\n * read (`$data` still `null`) is treated as \"provider not enabled\" — the flow stays hidden rather\n * than flashing. Owns the `step`/`authenticationToken` stepper plus a locally-typed draft `email`\n * as local state, broadcasting all of it through context to its children. The draft email pre-fills\n * from `clientProfile.email` once (for an already-identified shopper) but a shopper edit is never\n * persisted anywhere by this family — it is purely the requestAccessCode/validateAccessCode\n * argument; the server sets clientProfileData.email as a side effect of a successful validate.\n * Reacts automatically once `useSession()` flips to `loggedIn` — no manual unmount call anywhere in\n * this family.\n */\nexport function AccessCodeSignInRoot({ $data: $dataProp, className, children, ...props }: AccessCodeSignInRootProps) {\n const $data = useDataOverride($dataProp);\n const { state } = useSession();\n\n const [step, setStep] = useState<AccessCodeSignInStep>('request');\n const [authenticationToken, setAuthenticationToken] = useState<string | null>(null);\n\n const startValidation = useCallback((token: string) => {\n setAuthenticationToken(token);\n setStep('validate');\n }, []);\n\n const savedEmail = $data?.clientProfile?.email ?? '';\n const [email, setEmailState] = useState('');\n const [touched, setTouched] = useState(false);\n\n // Pre-fill from the resolving/known profile email, but only while still at the request step and\n // until the shopper edits the draft — mirrors ClientProfileRoot's untouched-field re-seed, never\n // clobbering an in-progress edit. Freezing the re-seed once the flow leaves 'request' keeps a\n // mid-flow profile-cache change from diverging the email between requestAccessCode and\n // validateAccessCode (the server rejects a validate whose email differs from the request).\n useEffect(() => {\n if (step === 'request' && !touched) setEmailState(savedEmail);\n }, [savedEmail, touched, step]);\n\n const setEmail = useCallback((next: string) => {\n setTouched(true);\n setEmailState(next);\n }, []);\n\n const providerEnabled = $data?.sessionAuthProviders?.accessKeyAuthentication ?? false;\n\n const contextValue = useMemo<AccessCodeSignInContextValue>(\n () => ({ email, setEmail, step, authenticationToken, startValidation }),\n [email, setEmail, step, authenticationToken, startValidation],\n );\n\n const gated = state !== 'loggedIn' && providerEnabled;\n if (!gated) return null;\n\n return (\n <AccessCodeSignInContext value={contextValue}>\n <div {...props} className={className} data-fs-access-code-sign-in-root=\"\">\n {children}\n </div>\n </AccessCodeSignInContext>\n );\n}\n\n/**\n * The draft email input for the access-code flow. Renders only at the request step. Bound to the\n * Root's local `email`/`setEmail` — never a fragment, never a mutation of its own; typing here\n * never touches the cart. Format validation is `EmailField`'s own blur-triggered check (never\n * per-keystroke); `invalidEmailMessage` is only its fallback text, mirroring how\n * `EmailIdentificationControl` defers to the same particle for the same reason.\n */\nexport function AccessCodeEmailControl({\n label,\n placeholder,\n invalidEmailMessage,\n className,\n ...props\n}: AccessCodeEmailControlProps) {\n const { step, email, setEmail } = useAccessCodeSignIn();\n\n if (step !== 'request') return null;\n\n return (\n <div {...props} className={className} data-fs-access-code-email-control=\"\">\n <EmailField\n label={label}\n placeholder={placeholder}\n value={email}\n onValueChange={setEmail}\n errorMessage={invalidEmailMessage}\n />\n </div>\n );\n}\n\n/**\n * Renders only while the Root's stepper is at `step === 'request'`. Reads the draft email from\n * context and dispatches `$actions.session.requestAccessCode({ email })` once it is a valid,\n * non-empty address (no account-existence pre-check beyond that format gate). On a result with a\n * non-null token and no `userErrors`, advances the Root's stepper. Every `userErrors` entry renders\n * inline via a host-supplied, per-code message; the step never changes on error, so the shopper can\n * retry or abandon the method and continue as a guest.\n */\nexport function AccessCodeRequestControl({\n label,\n pendingLabel,\n sendLimitMessage,\n blockedMessage,\n networkErrorMessage,\n onRequested,\n $actions: $actionsProp,\n className,\n ...props\n}: AccessCodeRequestControlProps) {\n const $actions = useActionsOverride($actionsProp);\n const { step, email, startValidation } = useAccessCodeSignIn();\n const [pending, setPending] = useState(false);\n const [error, setError] = useState<SessionUserError | null>(null);\n\n if (step !== 'request') return null;\n\n const canSubmit = !pending && isValidEmail(email);\n\n async function handleClick() {\n if (!canSubmit) return;\n setPending(true);\n setError(null);\n\n try {\n const result = (await $actions?.session?.requestAccessCode?.({ email })) ?? {\n authenticationToken: null,\n userErrors: [],\n };\n\n if (result.authenticationToken && result.userErrors.length === 0) {\n startValidation(result.authenticationToken);\n onRequested?.(result.authenticationToken);\n return;\n }\n\n const [firstError] = result.userErrors;\n if (firstError) setError(firstError);\n } finally {\n setPending(false);\n }\n }\n\n const message = error ? requestErrorMessage(error, { sendLimitMessage, blockedMessage, networkErrorMessage }) : null;\n\n return (\n <div\n {...props}\n className={className}\n data-fs-access-code-request-control=\"\"\n {...(pending ? { 'data-fs-access-code-request-pending': '' } : {})}\n >\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={!canSubmit}\n aria-busy={pending || undefined}\n data-fs-access-code-request-submit=\"\"\n data-fs-button=\"\"\n >\n {/* T38, FR-5: resolveAuthoredCopy so an authored empty/whitespace-only pendingLabel falls\n back to `label` instead of blanking the button while the request is in flight. */}\n {pending ? resolveAuthoredCopy(pendingLabel, label ?? '') : label}\n </button>\n {message ? (\n <div role=\"alert\" data-fs-access-code-request-error=\"\">\n {message}\n </div>\n ) : null}\n </div>\n );\n}\n\n/**\n * Renders only while the Root's stepper is at `step === 'validate'`. Composes `AccessCodeField` for\n * the code value and a submit control, disabled below `codeLength` (a UX courtesy, never a\n * validity claim). Dispatches `$actions.session.validateAccessCode` with the email and\n * `authenticationToken` read from context. On a non-empty `userErrors` result, sets the field's\n * `invalid`/`errorMessage` from a host-supplied per-code message and retains the code/token so the\n * shopper can retry without re-requesting. On success it calls the optional `onValidated` and renders\n * no local \"success\" UI — `useSession()` flipping to `loggedIn` is what makes the whole Root\n * disappear.\n */\nexport function AccessCodeValidateControl({\n label,\n placeholder,\n submitLabel,\n codeLength = 6,\n invalidCodeMessage,\n blockedMessage,\n missingAuthContextMessage,\n networkErrorMessage,\n onValidated,\n $actions: $actionsProp,\n className,\n ...props\n}: AccessCodeValidateControlProps) {\n const $actions = useActionsOverride($actionsProp);\n const { step, email, authenticationToken } = useAccessCodeSignIn();\n const [code, setCode] = useState('');\n const [pending, setPending] = useState(false);\n const [error, setError] = useState<SessionUserError | null>(null);\n\n if (step !== 'validate') return null;\n\n const canSubmit = !pending && code.length >= codeLength && authenticationToken != null;\n\n async function handleSubmit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n if (!canSubmit || authenticationToken == null) return;\n\n setPending(true);\n setError(null);\n\n try {\n const errors =\n (await $actions?.session?.validateAccessCode?.({ email, accessCode: code, authenticationToken })) ?? [];\n\n const [firstError] = errors;\n if (firstError) {\n setError(firstError);\n return;\n }\n } finally {\n setPending(false);\n }\n\n onValidated?.();\n }\n\n function handleCodeChange(next: string) {\n setCode(next);\n if (error) setError(null);\n }\n\n const errorMessage = error\n ? validateErrorMessage(error, {\n invalidCodeMessage,\n blockedMessage,\n missingAuthContextMessage,\n networkErrorMessage,\n })\n : undefined;\n\n return (\n <div\n {...props}\n className={className}\n data-fs-access-code-validate-control=\"\"\n {...(pending ? { 'data-fs-access-code-validate-pending': '' } : {})}\n >\n <form onSubmit={handleSubmit}>\n <AccessCodeField\n label={label}\n placeholder={placeholder}\n value={code}\n maxLength={codeLength}\n onValueChange={handleCodeChange}\n disabled={pending}\n invalid={error != null}\n errorMessage={errorMessage}\n />\n <button\n type=\"submit\"\n disabled={!canSubmit}\n aria-busy={pending || undefined}\n data-fs-access-code-validate-submit=\"\"\n data-fs-button=\"\"\n >\n {submitLabel}\n </button>\n </form>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Namespace export\n// ---------------------------------------------------------------------------\n\nexport const AccessCodeSignIn = {\n Root: AccessCodeSignInRoot,\n Email: AccessCodeEmailControl,\n Request: AccessCodeRequestControl,\n Validate: AccessCodeValidateControl,\n};\n"],"mappings":"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"}
@@ -0,0 +1,165 @@
1
+ import { ComponentDefinition } from "../../core/dist/define-component.js";
2
+ import "../../core/dist/index.js";
3
+ import { ComponentActions } from "../../sdk/actions/types.js";
4
+ import { ComponentPropsWithRef } from "react";
5
+ //#region src/matter/billing-address/billing-address.d.ts
6
+ /**
7
+ * The `BillingAddress` matter (specs/billing-address.md, T11 of the Credit Card epic;
8
+ * docs/features/credit-card/rfc.md § D6). A "same as delivery" toggle (default on) plus, when off, a
9
+ * country-specific address form that persists via `$actions.payment.setBillingAddress`
10
+ * (already shipped by T4, zero consumers before this task).
11
+ *
12
+ * The shared `Address` composition RFC D6 names (shipping and billing as two control matters over
13
+ * one set of reusable particles) is DEFERRED — an implementation-time call the engineer resolved
14
+ * narrow (specs/billing-address.md Decision 1). This component builds its own controls and imports
15
+ * `countryDescriptors` from `../shipping-address/country-descriptors.js`; `matter/shipping-address/`
16
+ * is read, never modified — zero bytes of that directory change here.
17
+ *
18
+ * There is NO read-back path for a persisted billing address (specs/billing-address.md Decision 3):
19
+ * `type Payment` carries no `billingAddress` field, and `setBillingAddress` itself resolves only
20
+ * `userErrors`, discarding the mutation's own echo. This component declares no fragment and renders
21
+ * nothing below the toggle while "same as delivery" is checked, not even the delivery address
22
+ * (specs/stop-re-rendering-the-full-delivery.md, T175). The custom-address form always starts blank,
23
+ * and its own local state is the sole source of truth for what was typed.
24
+ *
25
+ * Only a boolean rides the shared `draft` (`billingAddressDifferent`, widened onto `PaymentDraft` by
26
+ * this task under sole ownership of `use-payment-method-selection.ts` — specs/billing-address.md
27
+ * Decision 5); the address itself is persisted server-side by this component's own action call, never
28
+ * passed through the draft. `setBillingAddress` is dispatched at exactly two points (Decision 9): the
29
+ * toggle's transition back to "same as delivery", and the custom form's explicit submit control —
30
+ * never on mount, never per keystroke.
31
+ *
32
+ * **`draft.billingAddressDifferent` only ever becomes `true` once `setBillingAddress` has actually
33
+ * persisted a different address (PR #544 N1).** Unchecking "same as delivery" opens the form
34
+ * (`formOpen`, local-only state below) but does not touch the draft — `gateway.ts`'s own doc comment
35
+ * ("`setBillingAddress` already persisted it … so the gateway reads it from there") is the contract
36
+ * this must not break: publishing `true` before anything is persisted would point the gateway at an
37
+ * `invoiceData` address nothing ever wrote. The engineer's own resolution for this (session of
38
+ * 2026-07-31): the new-address fields become required whenever "different" is selected, so this
39
+ * component's own submit blocks on an incomplete address (`isBillingAddressFormValid`) — but that
40
+ * alone cannot stop a shopper from declining "same as delivery" and clicking Place Order without ever
41
+ * opening the form's own submit control, which is why the draft write itself is gated on success, not
42
+ * merely the submit button.
43
+ *
44
+ * **The native `required` attribute below is cosmetic here, not an enforcement mechanism (PR #544
45
+ * N7).** This file renders no `aria-required` at all — only `required` (native HTML). There is no
46
+ * `<form>` in this render tree and the submit control is `type="button"`, so the browser's own
47
+ * constraint validation never runs — nothing in this file or its tests may claim this attribute itself
48
+ * prevents a shopper from placing an order with an unsaved address; the actual submit gate is
49
+ * `isBillingAddressFormValid`, read at the submit control's own `disabled` below. Since T38
50
+ * (specs/harden-and-verify-accessibility-across-the.md FR-6) each rendered field does carry a
51
+ * `Field.Error`, but it is driven by a local blur-tracked `touched` set and this same non-blank rule,
52
+ * never by `required`'s own native `ValidityState` — so this paragraph's point is unchanged: `required`
53
+ * itself still enforces nothing here. What this component owes, and
54
+ * does: make the gap **visible** — an inline `role="status"` notice while the form is open and nothing
55
+ * has been persisted yet — and publish that same fact (`setDraftBillingAddressUnsaved`) onto the
56
+ * shared draft, from the identical expression the notice renders from (T24,
57
+ * specs/cardholder-document-submit-gate.md FR-6). **The actual hard block lives elsewhere**: T24's
58
+ * `usePaymentSubmitGate()` reads that published fact and refuses Place Order client-side — this
59
+ * component's own job stops at publishing the fact and showing the notice, never at gating the CTA
60
+ * itself. See `specs/billing-address.md`'s Documentation Gaps #1 for the deferral this closes.
61
+ */
62
+ /**
63
+ * Local-only values for the "different" address form, keyed by the country descriptor's own
64
+ * canonical field names — a plain string index signature, not a closed set of properties, so a future
65
+ * country descriptor introducing a new field name needs no type change here (mirrors
66
+ * `FieldDescriptor.name: string`'s own deliberately untyped choice; specs/billing-address.md
67
+ * Decision 7). `postalCode` and `country` are named explicitly because this component's own logic
68
+ * reads both directly. Never carries a `recipientName` key: `PaymentBillingAddressUpdateInput` has no
69
+ * such field (Decision 4) — the render loop filters it out of whatever the descriptor lists.
70
+ */
71
+ export type BillingAddressFormDraft = Readonly<{
72
+ postalCode: string;
73
+ country: string;
74
+ [fieldName: string]: string;
75
+ }>;
76
+ export type BillingAddressProps = Omit<ComponentPropsWithRef<'div'>, 'children'> & {
77
+ /** The "same as delivery" toggle's own accessible label. */
78
+ sameAsDeliveryLabel?: string;
79
+ /** ISO 3166-1 alpha-3 default country for the custom-address form's country selector. */
80
+ defaultCountry?: string;
81
+ /** Label for the country selector inside the custom-address form. */
82
+ countryLabel?: string;
83
+ /** Label for the control that persists a custom billing address. */
84
+ submitLabel?: string;
85
+ /** Label on the submit control while the mutation is in flight. */
86
+ submitPendingLabel?: string;
87
+ /** Shown when the selected method's validator marks a billing address required. */
88
+ requiredNoticeLabel?: string;
89
+ /** Label for the recipient-name descriptor field. Not rendered by the custom-address form today
90
+ * (`OMITTED_FORM_FIELD_NAMES` — the write contract has no matching input slot, Decision 4); kept
91
+ * for parity with the other seven field labels this same map covers. */
92
+ recipientNameLabel?: string;
93
+ /** Label for the street descriptor field. */
94
+ streetLabel?: string;
95
+ /** Label for the street-number descriptor field. */
96
+ numberLabel?: string;
97
+ /** Label for the complement descriptor field. Its "(optional)" suffix is the only signal that the
98
+ * field is not required — `OPTIONAL_FORM_FIELD_NAMES` drives the actual `required` attribute
99
+ * independently, so authoring this without the suffix loses the optionality cue, not the behavior
100
+ * (R7). */
101
+ complementLabel?: string;
102
+ /** Label for the neighborhood descriptor field. Unused when the active country's descriptor has no
103
+ * `neighborhood` field (e.g. USA). */
104
+ neighborhoodLabel?: string;
105
+ /** Label for the city descriptor field. */
106
+ cityLabel?: string;
107
+ /** Label for the state descriptor field. */
108
+ stateLabel?: string;
109
+ /** Label for the postal-code descriptor field. */
110
+ postalCodeLabel?: string;
111
+ /** Shown while the form is open and no address has been persisted yet (PR #544 N7) — the shopper
112
+ * declined "same as delivery" but has not (or not yet again) had a submit succeed, so Place Order
113
+ * will bill the delivery address unless they save one first. Rendered `role="status"`, not
114
+ * `role="alert"`: it is a persistent, advisory condition of the form being open, not a one-off
115
+ * announcement reacting to a rejected action (see this file's own existing `-error` alert for that
116
+ * shape) — see `specs/billing-address.md`'s Accessibility Contract for the site count this choice is
117
+ * measured against. */
118
+ unsavedAddressNoticeLabel?: string;
119
+ /** Always-on billing-match disclaimer (requirement 12.20): tells the shopper their billing address
120
+ * must match the one their card issuer or bank statement holds, so an AVS mismatch does not get the
121
+ * order declined with no explanation on screen. Gated on this prop and `billingMatchNoticeVisible`
122
+ * only — reads no `usePayment()` value, no local state, no `$data` (FR-4), unlike the two notices
123
+ * above. */
124
+ billingMatchNoticeLabel?: string;
125
+ /** Switches the billing-match disclaimer above on or off. Defaults to `true` (Decision 5 — the
126
+ * requirement's own intent); subordinate to `billingMatchNoticeLabel.trim()`, which alone can still
127
+ * suppress an empty notice (FR-3) regardless of this prop's value. */
128
+ billingMatchNoticeVisible?: boolean;
129
+ /**
130
+ * Shown as a `Field.Error` under a required, blank, touched field (T38, FR-6/FR-7) — the same
131
+ * non-blank rule `isBillingAddressFormValid` already applies, except `complement`
132
+ * (`OPTIONAL_FORM_FIELD_NAMES`), which is never marked invalid. One prop, not one per field: every
133
+ * rendered field shares the same rule, so seven props would be seven ways to say the same sentence.
134
+ * Resolved through `resolveAuthoredCopy`.
135
+ */
136
+ fieldRequiredMessage?: string;
137
+ /** Disables the toggle, every form field, the country selector, and the submit control. */
138
+ disabled?: boolean;
139
+ /** Compiler-injected action surface; carries `payment.setBillingAddress`. */
140
+ $actions?: ComponentActions;
141
+ };
142
+ /**
143
+ * Whether the toggle reads as "same as delivery" — `true` whenever the published flag is `null`
144
+ * (never touched, the default) or `false` (explicitly reverted); only an explicit `true` means the
145
+ * shopper is on the custom-address path. Takes no closure over component state, so it is safe to call
146
+ * fresh on every render.
147
+ */
148
+ export declare function resolveSameAsDelivery(billingAddressDifferent: boolean | null | undefined): boolean;
149
+ /**
150
+ * Whether the custom-address form may be submitted. Stricter than the server's own
151
+ * `MISSING_BILLING_ADDRESS_FIELDS` floor ("sameAsDelivery is false but postalCode **or country** was
152
+ * omitted" [source: `core.graphql:2857-2858`]) — every field the active country's descriptor renders,
153
+ * except `complement` (`OPTIONAL_FORM_FIELD_NAMES`), must be non-blank (PR #544 N1 item 1: the
154
+ * engineer's own rule that the new-address fields are required once "different" is selected). Resolves
155
+ * the descriptor from `formDraft.country` itself rather than taking a second parameter, so this stays a
156
+ * single self-contained fact about one `BillingAddressFormDraft` value. `country` itself is not part of
157
+ * `descriptor.fields` (Decision 7) and is never checked here — it always carries a non-blank value from
158
+ * `defaultCountry` or the selector's own current value (review F12), so it can never be the field this
159
+ * gate would fail on.
160
+ */
161
+ export declare function isBillingAddressFormValid(formDraft: BillingAddressFormDraft): boolean;
162
+ export declare const BillingAddressDefinition: ComponentDefinition<BillingAddressProps>;
163
+ export declare function BillingAddress({ sameAsDeliveryLabel, defaultCountry, countryLabel, submitLabel, submitPendingLabel, requiredNoticeLabel, unsavedAddressNoticeLabel, billingMatchNoticeLabel, billingMatchNoticeVisible, recipientNameLabel, streetLabel, numberLabel, complementLabel, neighborhoodLabel, cityLabel, stateLabel, postalCodeLabel, fieldRequiredMessage, disabled, className, $actions: $actionsProp, ...props }: BillingAddressProps): import("react/jsx-runtime").JSX.Element | null;
164
+ //#endregion
165
+ //# sourceMappingURL=billing-address.d.ts.map