@thorprovider/blocks 4.0.0 → 4.1.0

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 (55) hide show
  1. package/dist/blocks/designs/checkout-commerce-v1/block.d.ts +49 -0
  2. package/dist/blocks/designs/checkout-commerce-v1/block.d.ts.map +1 -0
  3. package/dist/blocks/designs/checkout-commerce-v1/block.js +2487 -0
  4. package/dist/blocks/designs/checkout-commerce-v1/block.js.map +1 -0
  5. package/dist/blocks/designs/checkout-commerce-v1/block.mjs +2467 -0
  6. package/dist/blocks/designs/checkout-commerce-v1/block.mjs.map +1 -0
  7. package/dist/blocks/designs/checkout-commerce-v1/data-context.d.ts +8 -0
  8. package/dist/blocks/designs/checkout-commerce-v1/data-context.d.ts.map +1 -0
  9. package/dist/blocks/designs/checkout-commerce-v1/data-context.js +44 -0
  10. package/dist/blocks/designs/checkout-commerce-v1/data-context.js.map +1 -0
  11. package/dist/blocks/designs/checkout-commerce-v1/data-context.mjs +19 -0
  12. package/dist/blocks/designs/checkout-commerce-v1/data-context.mjs.map +1 -0
  13. package/dist/blocks/designs/checkout-commerce-v1/index.d.ts +3 -0
  14. package/dist/blocks/designs/checkout-commerce-v1/index.d.ts.map +1 -0
  15. package/dist/blocks/designs/checkout-commerce-v1/index.js +36 -0
  16. package/dist/blocks/designs/checkout-commerce-v1/index.js.map +1 -0
  17. package/dist/blocks/designs/checkout-commerce-v1/index.mjs +6 -0
  18. package/dist/blocks/designs/checkout-commerce-v1/index.mjs.map +1 -0
  19. package/dist/blocks/e-commerce/account/account-frame.d.ts +38 -0
  20. package/dist/blocks/e-commerce/account/account-frame.d.ts.map +1 -0
  21. package/dist/blocks/e-commerce/account/account-frame.js +102 -0
  22. package/dist/blocks/e-commerce/account/account-frame.js.map +1 -0
  23. package/dist/blocks/e-commerce/account/account-frame.mjs +78 -0
  24. package/dist/blocks/e-commerce/account/account-frame.mjs.map +1 -0
  25. package/dist/blocks/e-commerce/account/address-book.d.ts +79 -0
  26. package/dist/blocks/e-commerce/account/address-book.d.ts.map +1 -0
  27. package/dist/blocks/e-commerce/account/address-book.js +250 -0
  28. package/dist/blocks/e-commerce/account/address-book.js.map +1 -0
  29. package/dist/blocks/e-commerce/account/address-book.mjs +225 -0
  30. package/dist/blocks/e-commerce/account/address-book.mjs.map +1 -0
  31. package/dist/blocks/e-commerce/account/profile-form.d.ts +35 -0
  32. package/dist/blocks/e-commerce/account/profile-form.d.ts.map +1 -0
  33. package/dist/blocks/e-commerce/account/profile-form.js +100 -0
  34. package/dist/blocks/e-commerce/account/profile-form.js.map +1 -0
  35. package/dist/blocks/e-commerce/account/profile-form.mjs +76 -0
  36. package/dist/blocks/e-commerce/account/profile-form.mjs.map +1 -0
  37. package/dist/index.d.ts +10 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +14 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/index.mjs +9 -0
  42. package/dist/index.mjs.map +1 -1
  43. package/dist/lib/contracts/checkout-commerce-v1.d.ts +2350 -0
  44. package/dist/lib/contracts/checkout-commerce-v1.d.ts.map +1 -0
  45. package/dist/lib/contracts/checkout-commerce-v1.js +417 -0
  46. package/dist/lib/contracts/checkout-commerce-v1.js.map +1 -0
  47. package/dist/lib/contracts/checkout-commerce-v1.mjs +392 -0
  48. package/dist/lib/contracts/checkout-commerce-v1.mjs.map +1 -0
  49. package/dist/lib/contracts.d.ts +515 -177
  50. package/dist/lib/contracts.d.ts.map +1 -1
  51. package/dist/lib/contracts.js +81 -1
  52. package/dist/lib/contracts.js.map +1 -1
  53. package/dist/lib/contracts.mjs +70 -0
  54. package/dist/lib/contracts.mjs.map +1 -1
  55. package/package.json +1 -1
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var checkout_commerce_v1_exports = {};
31
+ __export(checkout_commerce_v1_exports, {
32
+ default: () => import_block.default
33
+ });
34
+ module.exports = __toCommonJS(checkout_commerce_v1_exports);
35
+ var import_block = __toESM(require("./block.js"));
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/blocks/designs/checkout-commerce-v1/index.tsx"],"sourcesContent":["'use client'\n\nexport { default } from './block'\nexport type { CheckoutCommerceV1Props } from './block'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,mBAAwB;","names":[]}
@@ -0,0 +1,6 @@
1
+ "use client";
2
+ import { default as default2 } from "./block.mjs";
3
+ export {
4
+ default2 as default
5
+ };
6
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/blocks/designs/checkout-commerce-v1/index.tsx"],"sourcesContent":["'use client'\n\nexport { default } from './block'\nexport type { CheckoutCommerceV1Props } from './block'\n"],"mappings":";AAEA,SAAS,WAAAA,gBAAe;","names":["default"]}
@@ -0,0 +1,38 @@
1
+ /** The bounded account page shapes. `sidebar` is deliberately not offered. */
2
+ export type AccountFramePresentation = 'stack' | 'tabs';
3
+ /** One account module the host has installed and mounted. */
4
+ export interface AccountModule {
5
+ /** Stable module id; used as the anchor/tab id and reported on selection. */
6
+ id: string;
7
+ /** Visible navigation label. */
8
+ label: string;
9
+ /** Optional explicit destination; the stacked shape defaults to `#<id>`. */
10
+ href?: string;
11
+ }
12
+ /** Every user-facing string the frame renders. */
13
+ export interface AccountFrameLabels {
14
+ title: string;
15
+ navLabel: string;
16
+ }
17
+ export interface AccountFrameProps {
18
+ /** Display name supplied by the host (never fetched by the block). */
19
+ displayName: string;
20
+ /** Optional email; omitted when absent, never rendered as an empty element. */
21
+ email?: string;
22
+ /** Installed modules, in render order. */
23
+ modules: AccountModule[];
24
+ /** The module currently shown in the tabbed shape. */
25
+ activeModule?: string;
26
+ presentation?: AccountFramePresentation;
27
+ labels?: Partial<AccountFrameLabels>;
28
+ /** Report a module selection; the host owns the active module. */
29
+ onSelectModule?: (id: string) => void;
30
+ className?: string;
31
+ }
32
+ /**
33
+ * The account surface header: shopper identity plus module navigation. The block
34
+ * renders exactly what the host supplies — no order counts, rewards, or other
35
+ * invented metrics — and owns no state: the active module is host-controlled.
36
+ */
37
+ export declare function AccountFrame({ displayName, email, modules, activeModule, presentation, labels, onSelectModule, className, }: AccountFrameProps): import("react").JSX.Element;
38
+ //# sourceMappingURL=account-frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-frame.d.ts","sourceRoot":"","sources":["../../../../src/blocks/e-commerce/account/account-frame.tsx"],"names":[],"mappings":"AAMA,8EAA8E;AAC9E,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,MAAM,CAAA;AAEvD,6DAA6D;AAC7D,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,EAAE,EAAE,MAAM,CAAA;IACV,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB;AAOD,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAA;IACnB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0CAA0C;IAC1C,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,wBAAwB,CAAA;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACpC,kEAAkE;IAClE,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAC3B,WAAW,EACX,KAAK,EACL,OAAO,EACP,YAAY,EACZ,YAAsB,EACtB,MAAM,EACN,cAAc,EACd,SAAS,GACV,EAAE,iBAAiB,+BAoFnB"}
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ "use client";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var account_frame_exports = {};
21
+ __export(account_frame_exports, {
22
+ AccountFrame: () => AccountFrame
23
+ });
24
+ module.exports = __toCommonJS(account_frame_exports);
25
+ var import_jsx_runtime = require("react/jsx-runtime");
26
+ var import_react = require("react");
27
+ var import_utils = require("../../../lib/utils.js");
28
+ const defaultLabels = {
29
+ title: "Mi cuenta",
30
+ navLabel: "Secciones de la cuenta"
31
+ };
32
+ function AccountFrame({
33
+ displayName,
34
+ email,
35
+ modules,
36
+ activeModule,
37
+ presentation = "stack",
38
+ labels,
39
+ onSelectModule,
40
+ className
41
+ }) {
42
+ if (presentation !== "stack" && presentation !== "tabs") {
43
+ throw new Error(
44
+ `AccountFrame does not support presentation "${String(presentation)}". Use "stack" or "tabs".`
45
+ );
46
+ }
47
+ const copy = { ...defaultLabels, ...labels };
48
+ const tabRefs = (0, import_react.useRef)([]);
49
+ const moveSelection = (event) => {
50
+ if (!["ArrowRight", "ArrowLeft", "Home", "End"].includes(event.key)) return;
51
+ event.preventDefault();
52
+ const current = Math.max(
53
+ 0,
54
+ modules.findIndex((module2) => module2.id === activeModule)
55
+ );
56
+ const next = event.key === "Home" ? 0 : event.key === "End" ? modules.length - 1 : event.key === "ArrowRight" ? (current + 1) % modules.length : (current - 1 + modules.length) % modules.length;
57
+ onSelectModule?.(modules[next].id);
58
+ tabRefs.current[next]?.focus();
59
+ };
60
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { className: (0, import_utils.cn)("border-b pb-6", className), children: [
61
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-muted-foreground text-sm", children: copy.title }),
62
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "mt-1 text-2xl font-bold tracking-tight sm:text-3xl", children: displayName }),
63
+ email ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-muted-foreground mt-1 text-sm", children: email }) : null,
64
+ modules.length > 0 ? presentation === "stack" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("nav", { "aria-label": copy.navLabel, className: "mt-6", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "flex flex-wrap gap-x-6 gap-y-2", children: modules.map((module2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
65
+ "a",
66
+ {
67
+ href: module2.href ?? `#${module2.id}`,
68
+ "aria-current": module2.id === activeModule ? "true" : void 0,
69
+ className: "hover:text-foreground text-muted-foreground text-sm font-medium underline-offset-4 hover:underline",
70
+ children: module2.label
71
+ }
72
+ ) }, module2.id)) }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { role: "tablist", "aria-label": copy.navLabel, className: "mt-6 flex flex-wrap gap-2", onKeyDown: moveSelection, children: modules.map((module2) => {
73
+ const selected = module2.id === activeModule;
74
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
75
+ "button",
76
+ {
77
+ ref: (node) => {
78
+ tabRefs.current[modules.indexOf(module2)] = node;
79
+ },
80
+ type: "button",
81
+ role: "tab",
82
+ id: `account-tab-${module2.id}`,
83
+ "aria-selected": selected,
84
+ "aria-controls": `account-panel-${module2.id}`,
85
+ tabIndex: selected ? 0 : -1,
86
+ onClick: () => onSelectModule?.(module2.id),
87
+ className: (0, import_utils.cn)(
88
+ "rounded-md border px-3 py-2 text-sm font-medium transition-colors",
89
+ selected ? "bg-foreground text-background border-transparent" : "hover:bg-muted border-border bg-transparent"
90
+ ),
91
+ children: module2.label
92
+ },
93
+ module2.id
94
+ );
95
+ }) }) : null
96
+ ] });
97
+ }
98
+ // Annotate the CommonJS export names for ESM import in node:
99
+ 0 && (module.exports = {
100
+ AccountFrame
101
+ });
102
+ //# sourceMappingURL=account-frame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/blocks/e-commerce/account/account-frame.tsx"],"sourcesContent":["'use client'\n\nimport { useRef } from 'react'\nimport type { KeyboardEvent } from 'react'\nimport { cn } from '../../../lib/utils'\n\n/** The bounded account page shapes. `sidebar` is deliberately not offered. */\nexport type AccountFramePresentation = 'stack' | 'tabs'\n\n/** One account module the host has installed and mounted. */\nexport interface AccountModule {\n /** Stable module id; used as the anchor/tab id and reported on selection. */\n id: string\n /** Visible navigation label. */\n label: string\n /** Optional explicit destination; the stacked shape defaults to `#<id>`. */\n href?: string\n}\n\n/** Every user-facing string the frame renders. */\nexport interface AccountFrameLabels {\n title: string\n navLabel: string\n}\n\nconst defaultLabels: AccountFrameLabels = {\n title: 'Mi cuenta',\n navLabel: 'Secciones de la cuenta',\n}\n\nexport interface AccountFrameProps {\n /** Display name supplied by the host (never fetched by the block). */\n displayName: string\n /** Optional email; omitted when absent, never rendered as an empty element. */\n email?: string\n /** Installed modules, in render order. */\n modules: AccountModule[]\n /** The module currently shown in the tabbed shape. */\n activeModule?: string\n presentation?: AccountFramePresentation\n labels?: Partial<AccountFrameLabels>\n /** Report a module selection; the host owns the active module. */\n onSelectModule?: (id: string) => void\n className?: string\n}\n\n/**\n * The account surface header: shopper identity plus module navigation. The block\n * renders exactly what the host supplies — no order counts, rewards, or other\n * invented metrics — and owns no state: the active module is host-controlled.\n */\nexport function AccountFrame({\n displayName,\n email,\n modules,\n activeModule,\n presentation = 'stack',\n labels,\n onSelectModule,\n className,\n}: AccountFrameProps) {\n if (presentation !== 'stack' && presentation !== 'tabs') {\n throw new Error(\n `AccountFrame does not support presentation \"${String(presentation)}\". Use \"stack\" or \"tabs\".`,\n )\n }\n const copy = { ...defaultLabels, ...labels }\n const tabRefs = useRef<Array<HTMLButtonElement | null>>([])\n\n const moveSelection = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!['ArrowRight', 'ArrowLeft', 'Home', 'End'].includes(event.key)) return\n event.preventDefault()\n const current = Math.max(\n 0,\n modules.findIndex((module) => module.id === activeModule),\n )\n const next =\n event.key === 'Home'\n ? 0\n : event.key === 'End'\n ? modules.length - 1\n : event.key === 'ArrowRight'\n ? (current + 1) % modules.length\n : (current - 1 + modules.length) % modules.length\n onSelectModule?.(modules[next].id)\n tabRefs.current[next]?.focus()\n }\n\n return (\n <header className={cn('border-b pb-6', className)}>\n <p className=\"text-muted-foreground text-sm\">{copy.title}</p>\n <h1 className=\"mt-1 text-2xl font-bold tracking-tight sm:text-3xl\">{displayName}</h1>\n {email ? <p className=\"text-muted-foreground mt-1 text-sm\">{email}</p> : null}\n\n {modules.length > 0 ? (\n presentation === 'stack' ? (\n <nav aria-label={copy.navLabel} className=\"mt-6\">\n <ul className=\"flex flex-wrap gap-x-6 gap-y-2\">\n {modules.map((module) => (\n <li key={module.id}>\n <a\n href={module.href ?? `#${module.id}`}\n aria-current={module.id === activeModule ? 'true' : undefined}\n className=\"hover:text-foreground text-muted-foreground text-sm font-medium underline-offset-4 hover:underline\"\n >\n {module.label}\n </a>\n </li>\n ))}\n </ul>\n </nav>\n ) : (\n <div role=\"tablist\" aria-label={copy.navLabel} className=\"mt-6 flex flex-wrap gap-2\" onKeyDown={moveSelection}>\n {modules.map((module) => {\n const selected = module.id === activeModule\n return (\n <button\n key={module.id}\n ref={(node) => {\n tabRefs.current[modules.indexOf(module)] = node\n }}\n type=\"button\"\n role=\"tab\"\n id={`account-tab-${module.id}`}\n aria-selected={selected}\n aria-controls={`account-panel-${module.id}`}\n tabIndex={selected ? 0 : -1}\n onClick={() => onSelectModule?.(module.id)}\n className={cn(\n 'rounded-md border px-3 py-2 text-sm font-medium transition-colors',\n selected\n ? 'bg-foreground text-background border-transparent'\n : 'hover:bg-muted border-border bg-transparent',\n )}\n >\n {module.label}\n </button>\n )\n })}\n </div>\n )\n ) : null}\n </header>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyFI;AAvFJ,mBAAuB;AAEvB,mBAAmB;AAqBnB,MAAM,gBAAoC;AAAA,EACxC,OAAO;AAAA,EACP,UAAU;AACZ;AAuBO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AACF,GAAsB;AACpB,MAAI,iBAAiB,WAAW,iBAAiB,QAAQ;AACvD,UAAM,IAAI;AAAA,MACR,+CAA+C,OAAO,YAAY,CAAC;AAAA,IACrE;AAAA,EACF;AACA,QAAM,OAAO,EAAE,GAAG,eAAe,GAAG,OAAO;AAC3C,QAAM,cAAU,qBAAwC,CAAC,CAAC;AAE1D,QAAM,gBAAgB,CAAC,UAAyC;AAC9D,QAAI,CAAC,CAAC,cAAc,aAAa,QAAQ,KAAK,EAAE,SAAS,MAAM,GAAG,EAAG;AACrE,UAAM,eAAe;AACrB,UAAM,UAAU,KAAK;AAAA,MACnB;AAAA,MACA,QAAQ,UAAU,CAACA,YAAWA,QAAO,OAAO,YAAY;AAAA,IAC1D;AACA,UAAM,OACJ,MAAM,QAAQ,SACV,IACA,MAAM,QAAQ,QACZ,QAAQ,SAAS,IACjB,MAAM,QAAQ,gBACX,UAAU,KAAK,QAAQ,UACvB,UAAU,IAAI,QAAQ,UAAU,QAAQ;AACnD,qBAAiB,QAAQ,IAAI,EAAE,EAAE;AACjC,YAAQ,QAAQ,IAAI,GAAG,MAAM;AAAA,EAC/B;AAEA,SACE,6CAAC,YAAO,eAAW,iBAAG,iBAAiB,SAAS,GAC9C;AAAA,gDAAC,OAAE,WAAU,iCAAiC,eAAK,OAAM;AAAA,IACzD,4CAAC,QAAG,WAAU,sDAAsD,uBAAY;AAAA,IAC/E,QAAQ,4CAAC,OAAE,WAAU,sCAAsC,iBAAM,IAAO;AAAA,IAExE,QAAQ,SAAS,IAChB,iBAAiB,UACf,4CAAC,SAAI,cAAY,KAAK,UAAU,WAAU,QACxC,sDAAC,QAAG,WAAU,kCACX,kBAAQ,IAAI,CAACA,YACZ,4CAAC,QACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAMA,QAAO,QAAQ,IAAIA,QAAO,EAAE;AAAA,QAClC,gBAAcA,QAAO,OAAO,eAAe,SAAS;AAAA,QACpD,WAAU;AAAA,QAET,UAAAA,QAAO;AAAA;AAAA,IACV,KAPOA,QAAO,EAQhB,CACD,GACH,GACF,IAEA,4CAAC,SAAI,MAAK,WAAU,cAAY,KAAK,UAAU,WAAU,6BAA4B,WAAW,eAC7F,kBAAQ,IAAI,CAACA,YAAW;AACvB,YAAM,WAAWA,QAAO,OAAO;AAC/B,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,KAAK,CAAC,SAAS;AACb,oBAAQ,QAAQ,QAAQ,QAAQA,OAAM,CAAC,IAAI;AAAA,UAC7C;AAAA,UACA,MAAK;AAAA,UACL,MAAK;AAAA,UACL,IAAI,eAAeA,QAAO,EAAE;AAAA,UAC5B,iBAAe;AAAA,UACf,iBAAe,iBAAiBA,QAAO,EAAE;AAAA,UACzC,UAAU,WAAW,IAAI;AAAA,UACzB,SAAS,MAAM,iBAAiBA,QAAO,EAAE;AAAA,UACzC,eAAW;AAAA,YACT;AAAA,YACA,WACI,qDACA;AAAA,UACN;AAAA,UAEC,UAAAA,QAAO;AAAA;AAAA,QAlBHA,QAAO;AAAA,MAmBd;AAAA,IAEJ,CAAC,GACH,IAEA;AAAA,KACN;AAEJ;","names":["module"]}
@@ -0,0 +1,78 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useRef } from "react";
4
+ import { cn } from "../../../lib/utils.mjs";
5
+ const defaultLabels = {
6
+ title: "Mi cuenta",
7
+ navLabel: "Secciones de la cuenta"
8
+ };
9
+ function AccountFrame({
10
+ displayName,
11
+ email,
12
+ modules,
13
+ activeModule,
14
+ presentation = "stack",
15
+ labels,
16
+ onSelectModule,
17
+ className
18
+ }) {
19
+ if (presentation !== "stack" && presentation !== "tabs") {
20
+ throw new Error(
21
+ `AccountFrame does not support presentation "${String(presentation)}". Use "stack" or "tabs".`
22
+ );
23
+ }
24
+ const copy = { ...defaultLabels, ...labels };
25
+ const tabRefs = useRef([]);
26
+ const moveSelection = (event) => {
27
+ if (!["ArrowRight", "ArrowLeft", "Home", "End"].includes(event.key)) return;
28
+ event.preventDefault();
29
+ const current = Math.max(
30
+ 0,
31
+ modules.findIndex((module) => module.id === activeModule)
32
+ );
33
+ const next = event.key === "Home" ? 0 : event.key === "End" ? modules.length - 1 : event.key === "ArrowRight" ? (current + 1) % modules.length : (current - 1 + modules.length) % modules.length;
34
+ onSelectModule?.(modules[next].id);
35
+ tabRefs.current[next]?.focus();
36
+ };
37
+ return /* @__PURE__ */ jsxs("header", { className: cn("border-b pb-6", className), children: [
38
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: copy.title }),
39
+ /* @__PURE__ */ jsx("h1", { className: "mt-1 text-2xl font-bold tracking-tight sm:text-3xl", children: displayName }),
40
+ email ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: email }) : null,
41
+ modules.length > 0 ? presentation === "stack" ? /* @__PURE__ */ jsx("nav", { "aria-label": copy.navLabel, className: "mt-6", children: /* @__PURE__ */ jsx("ul", { className: "flex flex-wrap gap-x-6 gap-y-2", children: modules.map((module) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
42
+ "a",
43
+ {
44
+ href: module.href ?? `#${module.id}`,
45
+ "aria-current": module.id === activeModule ? "true" : void 0,
46
+ className: "hover:text-foreground text-muted-foreground text-sm font-medium underline-offset-4 hover:underline",
47
+ children: module.label
48
+ }
49
+ ) }, module.id)) }) }) : /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": copy.navLabel, className: "mt-6 flex flex-wrap gap-2", onKeyDown: moveSelection, children: modules.map((module) => {
50
+ const selected = module.id === activeModule;
51
+ return /* @__PURE__ */ jsx(
52
+ "button",
53
+ {
54
+ ref: (node) => {
55
+ tabRefs.current[modules.indexOf(module)] = node;
56
+ },
57
+ type: "button",
58
+ role: "tab",
59
+ id: `account-tab-${module.id}`,
60
+ "aria-selected": selected,
61
+ "aria-controls": `account-panel-${module.id}`,
62
+ tabIndex: selected ? 0 : -1,
63
+ onClick: () => onSelectModule?.(module.id),
64
+ className: cn(
65
+ "rounded-md border px-3 py-2 text-sm font-medium transition-colors",
66
+ selected ? "bg-foreground text-background border-transparent" : "hover:bg-muted border-border bg-transparent"
67
+ ),
68
+ children: module.label
69
+ },
70
+ module.id
71
+ );
72
+ }) }) : null
73
+ ] });
74
+ }
75
+ export {
76
+ AccountFrame
77
+ };
78
+ //# sourceMappingURL=account-frame.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/blocks/e-commerce/account/account-frame.tsx"],"sourcesContent":["'use client'\n\nimport { useRef } from 'react'\nimport type { KeyboardEvent } from 'react'\nimport { cn } from '../../../lib/utils'\n\n/** The bounded account page shapes. `sidebar` is deliberately not offered. */\nexport type AccountFramePresentation = 'stack' | 'tabs'\n\n/** One account module the host has installed and mounted. */\nexport interface AccountModule {\n /** Stable module id; used as the anchor/tab id and reported on selection. */\n id: string\n /** Visible navigation label. */\n label: string\n /** Optional explicit destination; the stacked shape defaults to `#<id>`. */\n href?: string\n}\n\n/** Every user-facing string the frame renders. */\nexport interface AccountFrameLabels {\n title: string\n navLabel: string\n}\n\nconst defaultLabels: AccountFrameLabels = {\n title: 'Mi cuenta',\n navLabel: 'Secciones de la cuenta',\n}\n\nexport interface AccountFrameProps {\n /** Display name supplied by the host (never fetched by the block). */\n displayName: string\n /** Optional email; omitted when absent, never rendered as an empty element. */\n email?: string\n /** Installed modules, in render order. */\n modules: AccountModule[]\n /** The module currently shown in the tabbed shape. */\n activeModule?: string\n presentation?: AccountFramePresentation\n labels?: Partial<AccountFrameLabels>\n /** Report a module selection; the host owns the active module. */\n onSelectModule?: (id: string) => void\n className?: string\n}\n\n/**\n * The account surface header: shopper identity plus module navigation. The block\n * renders exactly what the host supplies — no order counts, rewards, or other\n * invented metrics — and owns no state: the active module is host-controlled.\n */\nexport function AccountFrame({\n displayName,\n email,\n modules,\n activeModule,\n presentation = 'stack',\n labels,\n onSelectModule,\n className,\n}: AccountFrameProps) {\n if (presentation !== 'stack' && presentation !== 'tabs') {\n throw new Error(\n `AccountFrame does not support presentation \"${String(presentation)}\". Use \"stack\" or \"tabs\".`,\n )\n }\n const copy = { ...defaultLabels, ...labels }\n const tabRefs = useRef<Array<HTMLButtonElement | null>>([])\n\n const moveSelection = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!['ArrowRight', 'ArrowLeft', 'Home', 'End'].includes(event.key)) return\n event.preventDefault()\n const current = Math.max(\n 0,\n modules.findIndex((module) => module.id === activeModule),\n )\n const next =\n event.key === 'Home'\n ? 0\n : event.key === 'End'\n ? modules.length - 1\n : event.key === 'ArrowRight'\n ? (current + 1) % modules.length\n : (current - 1 + modules.length) % modules.length\n onSelectModule?.(modules[next].id)\n tabRefs.current[next]?.focus()\n }\n\n return (\n <header className={cn('border-b pb-6', className)}>\n <p className=\"text-muted-foreground text-sm\">{copy.title}</p>\n <h1 className=\"mt-1 text-2xl font-bold tracking-tight sm:text-3xl\">{displayName}</h1>\n {email ? <p className=\"text-muted-foreground mt-1 text-sm\">{email}</p> : null}\n\n {modules.length > 0 ? (\n presentation === 'stack' ? (\n <nav aria-label={copy.navLabel} className=\"mt-6\">\n <ul className=\"flex flex-wrap gap-x-6 gap-y-2\">\n {modules.map((module) => (\n <li key={module.id}>\n <a\n href={module.href ?? `#${module.id}`}\n aria-current={module.id === activeModule ? 'true' : undefined}\n className=\"hover:text-foreground text-muted-foreground text-sm font-medium underline-offset-4 hover:underline\"\n >\n {module.label}\n </a>\n </li>\n ))}\n </ul>\n </nav>\n ) : (\n <div role=\"tablist\" aria-label={copy.navLabel} className=\"mt-6 flex flex-wrap gap-2\" onKeyDown={moveSelection}>\n {modules.map((module) => {\n const selected = module.id === activeModule\n return (\n <button\n key={module.id}\n ref={(node) => {\n tabRefs.current[modules.indexOf(module)] = node\n }}\n type=\"button\"\n role=\"tab\"\n id={`account-tab-${module.id}`}\n aria-selected={selected}\n aria-controls={`account-panel-${module.id}`}\n tabIndex={selected ? 0 : -1}\n onClick={() => onSelectModule?.(module.id)}\n className={cn(\n 'rounded-md border px-3 py-2 text-sm font-medium transition-colors',\n selected\n ? 'bg-foreground text-background border-transparent'\n : 'hover:bg-muted border-border bg-transparent',\n )}\n >\n {module.label}\n </button>\n )\n })}\n </div>\n )\n ) : null}\n </header>\n )\n}\n"],"mappings":";AAyFI,SACE,KADF;AAvFJ,SAAS,cAAc;AAEvB,SAAS,UAAU;AAqBnB,MAAM,gBAAoC;AAAA,EACxC,OAAO;AAAA,EACP,UAAU;AACZ;AAuBO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AACF,GAAsB;AACpB,MAAI,iBAAiB,WAAW,iBAAiB,QAAQ;AACvD,UAAM,IAAI;AAAA,MACR,+CAA+C,OAAO,YAAY,CAAC;AAAA,IACrE;AAAA,EACF;AACA,QAAM,OAAO,EAAE,GAAG,eAAe,GAAG,OAAO;AAC3C,QAAM,UAAU,OAAwC,CAAC,CAAC;AAE1D,QAAM,gBAAgB,CAAC,UAAyC;AAC9D,QAAI,CAAC,CAAC,cAAc,aAAa,QAAQ,KAAK,EAAE,SAAS,MAAM,GAAG,EAAG;AACrE,UAAM,eAAe;AACrB,UAAM,UAAU,KAAK;AAAA,MACnB;AAAA,MACA,QAAQ,UAAU,CAAC,WAAW,OAAO,OAAO,YAAY;AAAA,IAC1D;AACA,UAAM,OACJ,MAAM,QAAQ,SACV,IACA,MAAM,QAAQ,QACZ,QAAQ,SAAS,IACjB,MAAM,QAAQ,gBACX,UAAU,KAAK,QAAQ,UACvB,UAAU,IAAI,QAAQ,UAAU,QAAQ;AACnD,qBAAiB,QAAQ,IAAI,EAAE,EAAE;AACjC,YAAQ,QAAQ,IAAI,GAAG,MAAM;AAAA,EAC/B;AAEA,SACE,qBAAC,YAAO,WAAW,GAAG,iBAAiB,SAAS,GAC9C;AAAA,wBAAC,OAAE,WAAU,iCAAiC,eAAK,OAAM;AAAA,IACzD,oBAAC,QAAG,WAAU,sDAAsD,uBAAY;AAAA,IAC/E,QAAQ,oBAAC,OAAE,WAAU,sCAAsC,iBAAM,IAAO;AAAA,IAExE,QAAQ,SAAS,IAChB,iBAAiB,UACf,oBAAC,SAAI,cAAY,KAAK,UAAU,WAAU,QACxC,8BAAC,QAAG,WAAU,kCACX,kBAAQ,IAAI,CAAC,WACZ,oBAAC,QACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAM,OAAO,QAAQ,IAAI,OAAO,EAAE;AAAA,QAClC,gBAAc,OAAO,OAAO,eAAe,SAAS;AAAA,QACpD,WAAU;AAAA,QAET,iBAAO;AAAA;AAAA,IACV,KAPO,OAAO,EAQhB,CACD,GACH,GACF,IAEA,oBAAC,SAAI,MAAK,WAAU,cAAY,KAAK,UAAU,WAAU,6BAA4B,WAAW,eAC7F,kBAAQ,IAAI,CAAC,WAAW;AACvB,YAAM,WAAW,OAAO,OAAO;AAC/B,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,KAAK,CAAC,SAAS;AACb,oBAAQ,QAAQ,QAAQ,QAAQ,MAAM,CAAC,IAAI;AAAA,UAC7C;AAAA,UACA,MAAK;AAAA,UACL,MAAK;AAAA,UACL,IAAI,eAAe,OAAO,EAAE;AAAA,UAC5B,iBAAe;AAAA,UACf,iBAAe,iBAAiB,OAAO,EAAE;AAAA,UACzC,UAAU,WAAW,IAAI;AAAA,UACzB,SAAS,MAAM,iBAAiB,OAAO,EAAE;AAAA,UACzC,WAAW;AAAA,YACT;AAAA,YACA,WACI,qDACA;AAAA,UACN;AAAA,UAEC,iBAAO;AAAA;AAAA,QAlBH,OAAO;AAAA,MAmBd;AAAA,IAEJ,CAAC,GACH,IAEA;AAAA,KACN;AAEJ;","names":[]}
@@ -0,0 +1,79 @@
1
+ /** One address exactly as the host supplies it; the block formats no fields. */
2
+ export interface AccountAddress {
3
+ id: string;
4
+ recipientName: string;
5
+ /** Address lines in display order (street, city, region, postal code, country). */
6
+ lines: string[];
7
+ isDefaultShipping?: boolean;
8
+ isDefaultBilling?: boolean;
9
+ }
10
+ export interface AddressBookLabels {
11
+ title: string;
12
+ description: string;
13
+ emptyLabel: string;
14
+ addLabel: string;
15
+ editLabel: string;
16
+ deleteLabel: string;
17
+ confirmDeleteLabel: string;
18
+ cancelLabel: string;
19
+ defaultShippingLabel: string;
20
+ defaultBillingLabel: string;
21
+ setDefaultShippingLabel: string;
22
+ setDefaultBillingLabel: string;
23
+ }
24
+ export interface AddressBookProps {
25
+ addresses: AccountAddress[];
26
+ labels?: Partial<AddressBookLabels>;
27
+ onCreate?: () => void;
28
+ onEdit?: (id: string) => void;
29
+ onDelete?: (id: string) => void;
30
+ onSetDefaultShipping?: (id: string) => void;
31
+ onSetDefaultBilling?: (id: string) => void;
32
+ className?: string;
33
+ }
34
+ /**
35
+ * The address book: renders the host's addresses verbatim, in the supplied
36
+ * order, and reports every action. Deletion is a two-step inline confirmation
37
+ * and the entry stays until the host supplies a refreshed list — the block never
38
+ * removes it optimistically.
39
+ */
40
+ export declare function AddressBook({ addresses, labels, onCreate, onEdit, onDelete, onSetDefaultShipping, onSetDefaultBilling, className, }: AddressBookProps): import("react").JSX.Element;
41
+ /** One field of the address form, declared by the host. */
42
+ export interface AddressFormField {
43
+ name: string;
44
+ label: string;
45
+ value?: string;
46
+ type?: 'text' | 'tel' | 'email' | 'select';
47
+ required?: boolean;
48
+ autoComplete?: string;
49
+ /** Required for `select`; a select without options is not rendered. */
50
+ options?: {
51
+ value: string;
52
+ label: string;
53
+ }[];
54
+ }
55
+ export interface AddressFormLabels {
56
+ title: string;
57
+ submit: string;
58
+ saving: string;
59
+ cancel: string;
60
+ requiredError: string;
61
+ }
62
+ export interface AddressFormProps {
63
+ fields: AddressFormField[];
64
+ labels?: Partial<AddressFormLabels>;
65
+ pending?: boolean;
66
+ error?: string | null;
67
+ /** Host-supplied field errors, keyed by field name. */
68
+ fieldErrors?: Record<string, string>;
69
+ onSubmit: (values: Record<string, string>) => void;
70
+ onCancel?: () => void;
71
+ className?: string;
72
+ }
73
+ /**
74
+ * The address editor. It validates only the constraints the host declares (a
75
+ * required field), never invents country or postal rules, and omits a select
76
+ * the host supplied without options.
77
+ */
78
+ export declare function AddressForm({ fields, labels, pending, error, fieldErrors, onSubmit, onCancel, className, }: AddressFormProps): import("react").JSX.Element;
79
+ //# sourceMappingURL=address-book.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address-book.d.ts","sourceRoot":"","sources":["../../../../src/blocks/e-commerce/account/address-book.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ "use client";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var address_book_exports = {};
21
+ __export(address_book_exports, {
22
+ AddressBook: () => AddressBook,
23
+ AddressForm: () => AddressForm
24
+ });
25
+ module.exports = __toCommonJS(address_book_exports);
26
+ var import_jsx_runtime = require("react/jsx-runtime");
27
+ var import_react = require("react");
28
+ var import_badge = require("../../../ui/badge.js");
29
+ var import_button = require("../../../ui/button.js");
30
+ var import_card = require("../../../ui/card.js");
31
+ var import_field = require("../../../ui/field.js");
32
+ var import_input = require("../../../ui/input.js");
33
+ var import_utils = require("../../../lib/utils.js");
34
+ const defaultLabels = {
35
+ title: "Direcciones",
36
+ description: "Direcciones guardadas para tus pedidos.",
37
+ emptyLabel: "A\xFAn no tienes direcciones guardadas.",
38
+ addLabel: "A\xF1adir direcci\xF3n",
39
+ editLabel: "Editar",
40
+ deleteLabel: "Eliminar",
41
+ confirmDeleteLabel: "\xBFEliminar esta direcci\xF3n?",
42
+ cancelLabel: "Cancelar",
43
+ defaultShippingLabel: "Env\xEDo predeterminado",
44
+ defaultBillingLabel: "Facturaci\xF3n predeterminada",
45
+ setDefaultShippingLabel: "Usar para env\xEDo",
46
+ setDefaultBillingLabel: "Usar para facturaci\xF3n"
47
+ };
48
+ function AddressEntry({
49
+ address,
50
+ copy,
51
+ onEdit,
52
+ onDelete,
53
+ onSetDefaultShipping,
54
+ onSetDefaultBilling
55
+ }) {
56
+ const [confirming, setConfirming] = (0, import_react.useState)(false);
57
+ const containerRef = (0, import_react.useRef)(null);
58
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
59
+ "li",
60
+ {
61
+ ref: containerRef,
62
+ tabIndex: -1,
63
+ "data-slot": "address-book-entry",
64
+ className: "focus-visible:ring-ring rounded-lg outline-none focus-visible:ring-2",
65
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_card.Card, { children: [
66
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_card.CardHeader, { className: "flex flex-row items-start justify-between gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
67
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_card.CardTitle, { className: "text-base", children: address.recipientName }),
68
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mt-2 flex flex-wrap gap-2", children: [
69
+ address.isDefaultShipping ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_badge.Badge, { variant: "secondary", children: copy.defaultShippingLabel }) : null,
70
+ address.isDefaultBilling ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_badge.Badge, { variant: "outline", children: copy.defaultBillingLabel }) : null
71
+ ] })
72
+ ] }) }),
73
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_card.CardContent, { children: [
74
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("address", { className: "text-muted-foreground text-sm not-italic", children: address.lines.map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "block", children: line }, `${address.id}:${index}`)) }),
75
+ confirming ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mt-4 flex flex-wrap items-center gap-2", role: "group", "aria-label": copy.confirmDeleteLabel, children: [
76
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-sm", children: copy.confirmDeleteLabel }),
77
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
78
+ import_button.Button,
79
+ {
80
+ type: "button",
81
+ variant: "destructive",
82
+ size: "sm",
83
+ onClick: () => {
84
+ onDelete?.(address.id);
85
+ setConfirming(false);
86
+ containerRef.current?.focus();
87
+ },
88
+ children: copy.deleteLabel
89
+ }
90
+ ),
91
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { type: "button", variant: "outline", size: "sm", onClick: () => setConfirming(false), children: copy.cancelLabel })
92
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mt-4 flex flex-wrap gap-2", children: [
93
+ onEdit ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { type: "button", variant: "outline", size: "sm", onClick: () => onEdit(address.id), children: copy.editLabel }) : null,
94
+ onDelete ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { type: "button", variant: "outline", size: "sm", onClick: () => setConfirming(true), children: copy.deleteLabel }) : null,
95
+ onSetDefaultShipping && !address.isDefaultShipping ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
96
+ import_button.Button,
97
+ {
98
+ type: "button",
99
+ variant: "ghost",
100
+ size: "sm",
101
+ onClick: () => onSetDefaultShipping(address.id),
102
+ children: copy.setDefaultShippingLabel
103
+ }
104
+ ) : null,
105
+ onSetDefaultBilling && !address.isDefaultBilling ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
106
+ import_button.Button,
107
+ {
108
+ type: "button",
109
+ variant: "ghost",
110
+ size: "sm",
111
+ onClick: () => onSetDefaultBilling(address.id),
112
+ children: copy.setDefaultBillingLabel
113
+ }
114
+ ) : null
115
+ ] })
116
+ ] })
117
+ ] })
118
+ }
119
+ );
120
+ }
121
+ function AddressBook({
122
+ addresses,
123
+ labels,
124
+ onCreate,
125
+ onEdit,
126
+ onDelete,
127
+ onSetDefaultShipping,
128
+ onSetDefaultBilling,
129
+ className
130
+ }) {
131
+ const copy = { ...defaultLabels, ...labels };
132
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: (0, import_utils.cn)("rounded-lg border p-6", className), children: [
133
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [
134
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
135
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-lg font-semibold", children: copy.title }),
136
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-muted-foreground mt-1 text-sm", children: copy.description })
137
+ ] }),
138
+ onCreate ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { type: "button", onClick: onCreate, children: copy.addLabel }) : null
139
+ ] }),
140
+ addresses.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-muted-foreground mt-6 text-sm", "data-slot": "address-book-empty", children: copy.emptyLabel }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "mt-6 grid list-none grid-cols-1 gap-4 p-0 md:grid-cols-2", children: addresses.map((address) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
141
+ AddressEntry,
142
+ {
143
+ address,
144
+ copy,
145
+ onEdit,
146
+ onDelete,
147
+ onSetDefaultShipping,
148
+ onSetDefaultBilling
149
+ },
150
+ address.id
151
+ )) })
152
+ ] });
153
+ }
154
+ const defaultFormLabels = {
155
+ title: "Direcci\xF3n",
156
+ submit: "Guardar direcci\xF3n",
157
+ saving: "Guardando\u2026",
158
+ cancel: "Cancelar",
159
+ requiredError: "Este campo es obligatorio."
160
+ };
161
+ function AddressForm({
162
+ fields,
163
+ labels,
164
+ pending = false,
165
+ error,
166
+ fieldErrors,
167
+ onSubmit,
168
+ onCancel,
169
+ className
170
+ }) {
171
+ const copy = { ...defaultFormLabels, ...labels };
172
+ const visibleFields = fields.filter(
173
+ (field) => field.type !== "select" || Array.isArray(field.options) && field.options.length > 0
174
+ );
175
+ const signature = visibleFields.map((field) => `${field.name}:${field.value ?? ""}`).join("|");
176
+ const [values, setValues] = (0, import_react.useState)(
177
+ () => Object.fromEntries(visibleFields.map((field) => [field.name, field.value ?? ""]))
178
+ );
179
+ const [localErrors, setLocalErrors] = (0, import_react.useState)({});
180
+ (0, import_react.useEffect)(() => {
181
+ setValues(Object.fromEntries(visibleFields.map((field) => [field.name, field.value ?? ""])));
182
+ setLocalErrors({});
183
+ }, [signature]);
184
+ const submit = (event) => {
185
+ event.preventDefault();
186
+ const nextErrors = {};
187
+ for (const field of visibleFields) {
188
+ if (field.required && (values[field.name] ?? "").trim() === "") {
189
+ nextErrors[field.name] = copy.requiredError;
190
+ }
191
+ }
192
+ setLocalErrors(nextErrors);
193
+ if (Object.keys(nextErrors).length > 0) return;
194
+ onSubmit(Object.fromEntries(visibleFields.map((field) => [field.name, values[field.name] ?? ""])));
195
+ };
196
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: (0, import_utils.cn)("rounded-lg border p-6", className), children: [
197
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-lg font-semibold", children: copy.title }),
198
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: "mt-6", noValidate: true, onSubmit: submit, children: [
199
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("fieldset", { disabled: pending, "aria-busy": pending, className: "contents", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_field.FieldGroup, { className: "grid grid-cols-1 gap-5 sm:grid-cols-2", children: visibleFields.map((field) => {
200
+ const id = `address-${field.name}`;
201
+ const message = localErrors[field.name] ?? fieldErrors?.[field.name];
202
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_field.Field, { children: [
203
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_field.FieldLabel, { htmlFor: id, children: field.label }),
204
+ field.type === "select" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
205
+ "select",
206
+ {
207
+ id,
208
+ name: field.name,
209
+ value: values[field.name] ?? "",
210
+ required: field.required,
211
+ "aria-invalid": message ? true : void 0,
212
+ "aria-describedby": message ? `${id}-error` : void 0,
213
+ className: "border-input bg-background h-9 w-full rounded-md border px-3 text-sm",
214
+ onChange: (event) => setValues((current) => ({ ...current, [field.name]: event.target.value })),
215
+ children: [
216
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u2014" }),
217
+ (field.options ?? []).map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: option.value, children: option.label }, option.value))
218
+ ]
219
+ }
220
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
221
+ import_input.Input,
222
+ {
223
+ id,
224
+ name: field.name,
225
+ type: field.type ?? "text",
226
+ value: values[field.name] ?? "",
227
+ required: field.required,
228
+ autoComplete: field.autoComplete,
229
+ "aria-invalid": message ? true : void 0,
230
+ "aria-describedby": message ? `${id}-error` : void 0,
231
+ onChange: (event) => setValues((current) => ({ ...current, [field.name]: event.target.value }))
232
+ }
233
+ ),
234
+ message ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { id: `${id}-error`, className: "text-destructive text-sm", children: message }) : null
235
+ ] }, field.name);
236
+ }) }) }),
237
+ error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: "text-destructive mt-4 text-sm", children: error }) : null,
238
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mt-6 flex flex-wrap gap-2", children: [
239
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { type: "submit", disabled: pending, children: pending ? copy.saving : copy.submit }),
240
+ onCancel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { type: "button", variant: "outline", disabled: pending, onClick: onCancel, children: copy.cancel }) : null
241
+ ] })
242
+ ] })
243
+ ] });
244
+ }
245
+ // Annotate the CommonJS export names for ESM import in node:
246
+ 0 && (module.exports = {
247
+ AddressBook,
248
+ AddressForm
249
+ });
250
+ //# sourceMappingURL=address-book.js.map