@asteby/storefront-react 0.20.0 → 0.21.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.
- package/dist/account.cjs +272 -2
- package/dist/account.cjs.map +1 -1
- package/dist/account.css +159 -0
- package/dist/account.d.cts +35 -3
- package/dist/account.d.ts +35 -3
- package/dist/account.js +70 -1
- package/dist/account.js.map +1 -1
- package/dist/cart.cjs +125 -2
- package/dist/cart.cjs.map +1 -1
- package/dist/cart.css +145 -2
- package/dist/cart.js +4 -2
- package/dist/cart.js.map +1 -1
- package/dist/checkout.cjs +129 -1
- package/dist/checkout.cjs.map +1 -1
- package/dist/checkout.css +142 -0
- package/dist/checkout.d.cts +3 -1
- package/dist/checkout.d.ts +3 -1
- package/dist/checkout.js +8 -1
- package/dist/checkout.js.map +1 -1
- package/dist/chunk-VHEY5AU3.js +152 -0
- package/dist/chunk-VHEY5AU3.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/product-preview-DRtLWGLS.d.cts +85 -0
- package/dist/product-preview-DaICr4f2.d.ts +85 -0
- package/dist/ui.cjs +202 -0
- package/dist/ui.cjs.map +1 -1
- package/dist/ui.css +142 -0
- package/dist/ui.d.cts +3 -0
- package/dist/ui.d.ts +3 -0
- package/dist/ui.js +3 -1
- package/dist/ui.js.map +1 -1
- package/package.json +1 -1
package/dist/cart.cjs
CHANGED
|
@@ -70,6 +70,129 @@ function useResolvedLocale(locale) {
|
|
|
70
70
|
const sf = useOptionalStorefront();
|
|
71
71
|
return locale ?? sf?.locale ?? "es-MX";
|
|
72
72
|
}
|
|
73
|
+
var DEFAULT_IMAGE_WIDTHS = [320, 480, 640, 768, 1024, 1280, 1600];
|
|
74
|
+
var defaultImageLoader = (src, width, height) => {
|
|
75
|
+
try {
|
|
76
|
+
const isAbsolute = /^[a-z][a-z0-9+.-]*:/i.test(src);
|
|
77
|
+
const url = new URL(src, "http://relative.invalid");
|
|
78
|
+
url.searchParams.set("width", String(width));
|
|
79
|
+
if (height) url.searchParams.set("height", String(height));
|
|
80
|
+
return isAbsolute ? url.toString() : url.pathname + url.search + url.hash;
|
|
81
|
+
} catch {
|
|
82
|
+
return src;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
function parseRatio(ratio) {
|
|
86
|
+
if (!ratio) return null;
|
|
87
|
+
const [w, h] = ratio.split(/[/:]/).map((n) => Number.parseFloat(n));
|
|
88
|
+
return w && h ? w / h : null;
|
|
89
|
+
}
|
|
90
|
+
function Image({
|
|
91
|
+
data,
|
|
92
|
+
sizes = "100vw",
|
|
93
|
+
widths = DEFAULT_IMAGE_WIDTHS,
|
|
94
|
+
loader = defaultImageLoader,
|
|
95
|
+
priority = false,
|
|
96
|
+
aspectRatio,
|
|
97
|
+
alt,
|
|
98
|
+
loading,
|
|
99
|
+
decoding,
|
|
100
|
+
...rest
|
|
101
|
+
}) {
|
|
102
|
+
const ratio = parseRatio(aspectRatio) ?? (data.width && data.height ? data.width / data.height : null);
|
|
103
|
+
let candidates = [...widths].sort((a, b) => a - b);
|
|
104
|
+
if (data.width) {
|
|
105
|
+
const capped = candidates.filter((w) => w <= data.width);
|
|
106
|
+
candidates = capped.length ? capped : [data.width];
|
|
107
|
+
}
|
|
108
|
+
const srcSet = loader ? candidates.map((w) => `${loader(data.url, w, ratio ? Math.round(w / ratio) : void 0)} ${w}w`).join(", ") : void 0;
|
|
109
|
+
const width = data.width ?? candidates[candidates.length - 1];
|
|
110
|
+
const height = data.height ?? (ratio && width ? Math.round(width / ratio) : void 0);
|
|
111
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
112
|
+
"img",
|
|
113
|
+
{
|
|
114
|
+
src: data.url,
|
|
115
|
+
alt: alt ?? data.alt ?? "",
|
|
116
|
+
...srcSet ? { srcSet, sizes } : {},
|
|
117
|
+
...width ? { width } : {},
|
|
118
|
+
...height ? { height } : {},
|
|
119
|
+
loading: loading ?? (priority ? "eager" : "lazy"),
|
|
120
|
+
decoding: decoding ?? (priority ? "auto" : "async"),
|
|
121
|
+
...priority ? { fetchPriority: "high" } : {},
|
|
122
|
+
...rest
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
function productInitials(name) {
|
|
127
|
+
const words = (name ?? "").normalize("NFKC").split(/[\s\-_/.,()]+/).map((w) => Array.from(w).find((c) => /\p{L}|\p{N}/u.test(c)) ?? "").filter(Boolean);
|
|
128
|
+
if (words.length === 0) return "";
|
|
129
|
+
return (words.length > 1 ? words[0] + words[1] : words[0]).toLocaleUpperCase();
|
|
130
|
+
}
|
|
131
|
+
function ProductThumb({
|
|
132
|
+
image,
|
|
133
|
+
name,
|
|
134
|
+
size = 56,
|
|
135
|
+
ratio = "1/1",
|
|
136
|
+
fit = "contain",
|
|
137
|
+
quantity,
|
|
138
|
+
decorative = false,
|
|
139
|
+
zoom = true,
|
|
140
|
+
priority = false,
|
|
141
|
+
sizes,
|
|
142
|
+
loader,
|
|
143
|
+
className,
|
|
144
|
+
classNames: cx = {}
|
|
145
|
+
}) {
|
|
146
|
+
const url = image?.url || null;
|
|
147
|
+
const [state, setState] = react.useState(url ? "loading" : "fallback");
|
|
148
|
+
const box = react.useRef(null);
|
|
149
|
+
react.useEffect(() => {
|
|
150
|
+
const img = box.current?.querySelector("img");
|
|
151
|
+
setState(!url ? "fallback" : img?.complete ? img.naturalWidth > 0 ? "loaded" : "fallback" : "loading");
|
|
152
|
+
}, [url]);
|
|
153
|
+
const label = name?.trim() || "";
|
|
154
|
+
const initials = productInitials(label);
|
|
155
|
+
const showBadge = typeof quantity === "number" && quantity > 1;
|
|
156
|
+
const a11y = state === "fallback" && !decorative && label ? { role: "img", "aria-label": label } : { "aria-hidden": decorative || state === "fallback" ? true : void 0 };
|
|
157
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
158
|
+
"span",
|
|
159
|
+
{
|
|
160
|
+
ref: box,
|
|
161
|
+
className: [cx.root, className].filter(Boolean).join(" ") || void 0,
|
|
162
|
+
style: { ["--sf-preview-size"]: `${size}px`, ["--sf-preview-ratio"]: ratio.replace(":", "/") },
|
|
163
|
+
"data-sf-thumb": "",
|
|
164
|
+
"data-state": state,
|
|
165
|
+
"data-fit": fit,
|
|
166
|
+
"data-zoom": zoom || void 0,
|
|
167
|
+
...a11y,
|
|
168
|
+
children: [
|
|
169
|
+
url && state !== "fallback" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
170
|
+
Image,
|
|
171
|
+
{
|
|
172
|
+
data: { url, alt: image?.alt ?? null, ...image?.width ? { width: image.width } : {}, ...image?.height ? { height: image.height } : {} },
|
|
173
|
+
alt: decorative ? "" : image?.alt ?? label,
|
|
174
|
+
aspectRatio: ratio,
|
|
175
|
+
sizes: sizes ?? `${size * 2}px`,
|
|
176
|
+
widths: [Math.round(size), Math.round(size * 2), Math.round(size * 3)],
|
|
177
|
+
...loader !== void 0 ? { loader } : {},
|
|
178
|
+
priority,
|
|
179
|
+
className: cx.img,
|
|
180
|
+
onLoad: () => setState("loaded"),
|
|
181
|
+
onError: () => setState("fallback")
|
|
182
|
+
}
|
|
183
|
+
) : null,
|
|
184
|
+
state === "fallback" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.fallback, "data-sf-thumb-fallback": "", "aria-hidden": "true", children: initials ? /* @__PURE__ */ jsxRuntime.jsx("span", { "data-sf-thumb-initial": "", children: initials }) : /* @__PURE__ */ jsxRuntime.jsx(PackageGlyph, {}) }) : null,
|
|
185
|
+
showBadge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.badge, "data-sf-thumb-qty": "", "aria-hidden": "true", children: quantity }) : null
|
|
186
|
+
]
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
function PackageGlyph() {
|
|
191
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", width: "45%", height: "45%", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", focusable: "false", children: [
|
|
192
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 8 12 3 3 8v8l9 5 9-5V8Z" }),
|
|
193
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "m3 8 9 5 9-5M12 13v8" })
|
|
194
|
+
] });
|
|
195
|
+
}
|
|
73
196
|
var isOpen = false;
|
|
74
197
|
var listeners = /* @__PURE__ */ new Set();
|
|
75
198
|
var quietOpen = false;
|
|
@@ -455,7 +578,7 @@ function DrawerLine({
|
|
|
455
578
|
const title = merch.product.title;
|
|
456
579
|
const href = paths.product?.(merch.product.handle, merch.id);
|
|
457
580
|
const img = merch.image ?? merch.product.featured_image;
|
|
458
|
-
const image = props.renderImage ? props.renderImage(line) :
|
|
581
|
+
const image = props.renderImage ? props.renderImage(line) : /* @__PURE__ */ jsxRuntime.jsx(ProductThumb, { image: img ?? null, name: title, size: 80, decorative: true });
|
|
459
582
|
const imageNode = /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.image, "data-sf-cart-image": "", children: image });
|
|
460
583
|
const price = /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.price, "data-sf-cart-price": "", children: money(line.cost.total) });
|
|
461
584
|
const controls = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx.controls, "data-sf-cart-controls": "", children: [
|
|
@@ -492,7 +615,7 @@ function PendingLine({ row, props, money, label }) {
|
|
|
492
615
|
const { classNames: cx = {} } = props;
|
|
493
616
|
const isDefault = props.isDefaultVariantTitle ?? defaultIsDefaultVariant;
|
|
494
617
|
return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: cx.line, "data-sf-cart-line": "", "data-sf-cart-line-pending": "", "aria-busy": "true", children: [
|
|
495
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.image, "data-sf-cart-image": "", children:
|
|
618
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.image, "data-sf-cart-image": "", children: /* @__PURE__ */ jsxRuntime.jsx(ProductThumb, { image: row.image ?? null, name: row.title, size: 80, decorative: true }) }),
|
|
496
619
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx.lineMain, "data-sf-cart-line-main": "", children: [
|
|
497
620
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx.lineHead, "data-sf-cart-line-head": "", children: [
|
|
498
621
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx.lineText, "data-sf-cart-line-text": "", children: [
|
package/dist/cart.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dialog.tsx","../src/context.tsx","../src/locale.ts","../src/cart-drawer/store.ts","../src/cart-drawer/optimistic.ts","../src/cart-drawer/cart-drawer.tsx"],"names":["useRef","useEffect","useCallback","createContext","useContext","useSyncExternalStore","listeners","subscribe","useId","jsx","formatMoney","jsxs","Fragment","notices"],"mappings":";;;;;;;AAkBO,SAAS,cAAA,CAAe,EAAE,IAAA,EAAM,OAAA,EAAS,cAAa,EAA0B;AACrF,EAAA,MAAM,GAAA,GAAMA,aAAiC,IAAI,CAAA;AACjD,EAAA,MAAM,MAAA,GAASA,aAAuB,IAAI,CAAA;AAC1C,EAAA,MAAM,UAAA,GAAaA,aAAO,OAAO,CAAA;AACjC,EAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AAErB,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,KAAK,GAAA,CAAI,OAAA;AACf,IAAA,IAAI,CAAC,EAAA,IAAM,CAAC,IAAA,EAAM;AAClB,IAAA,MAAA,CAAO,OAAA,GAAU,OAAO,QAAA,KAAa,WAAA,GAAc,SAAS,aAAA,GAAgB,IAAA;AAC5E,IAAA,MAAM,QAAA,GAAW,OAAO,EAAA,CAAG,SAAA,KAAc,UAAA;AACzC,IAAA,IAAI,CAAC,GAAG,IAAA,EAAM;AACZ,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,IAAI;AACF,UAAA,EAAA,CAAG,SAAA,EAAU;AAAA,QACf,CAAA,CAAA,MAAQ;AACN,UAAA,EAAA,CAAG,YAAA,CAAa,QAAQ,EAAE,CAAA;AAAA,QAC5B;AAAA,MACF,CAAA,MAAO,EAAA,CAAG,YAAA,CAAa,MAAA,EAAQ,EAAE,CAAA;AAAA,IACnC;AACA,IAAA,MAAM,SAAS,YAAA,EAAc,OAAA,IAAW,EAAA,CAAG,aAAA,CAA2B,qBAAqB,CAAA,IAAK,EAAA;AAChG,IAAA,IAAI,CAAC,MAAA,CAAO,YAAA,CAAa,UAAU,CAAA,IAAK,WAAW,EAAA,EAAI,EAAA,CAAG,YAAA,CAAa,UAAA,EAAY,IAAI,CAAA;AACvF,IAAA,MAAA,CAAO,KAAA,CAAM,EAAE,aAAA,EAAe,IAAA,EAAM,CAAA;AAEpC,IAAA,MAAM,QAAA,GAAW,CAAC,CAAA,KAAa;AAC7B,MAAA,CAAA,CAAE,cAAA,EAAe;AACjB,MAAA,UAAA,CAAW,QAAQ,KAAK,CAAA;AAAA,IAC1B,CAAA;AACA,IAAA,MAAM,KAAA,GAAQ,CAAC,CAAA,KAAqB;AAClC,MAAA,IAAI,CAAA,CAAE,QAAQ,QAAA,EAAU;AACtB,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,UAAA,CAAW,QAAQ,KAAK,CAAA;AAAA,MAC1B;AAAA,IACF,CAAA;AACA,IAAA,EAAA,CAAG,gBAAA,CAAiB,UAAU,QAAQ,CAAA;AACtC,IAAA,IAAI,CAAC,QAAA,EAAU,EAAA,CAAG,gBAAA,CAAiB,WAAW,KAAK,CAAA;AACnD,IAAA,OAAO,MAAM;AACX,MAAA,EAAA,CAAG,mBAAA,CAAoB,UAAU,QAAQ,CAAA;AACzC,MAAA,EAAA,CAAG,mBAAA,CAAoB,WAAW,KAAK,CAAA;AACvC,MAAA,IAAI,GAAG,IAAA,EAAM;AACX,QAAA,IAAI,OAAO,EAAA,CAAG,KAAA,KAAU,UAAA,EAAY;AAClC,UAAA,IAAI;AACF,YAAA,EAAA,CAAG,KAAA,EAAM;AAAA,UACX,CAAA,CAAA,MAAQ;AACN,YAAA,EAAA,CAAG,gBAAgB,MAAM,CAAA;AAAA,UAC3B;AAAA,QACF,CAAA,MAAO,EAAA,CAAG,eAAA,CAAgB,MAAM,CAAA;AAAA,MAClC;AACA,MAAA,MAAM,OAAO,MAAA,CAAO,OAAA;AACpB,MAAA,IAAI,IAAA,YAAgB,eAAe,IAAA,CAAK,WAAA,OAAkB,KAAA,CAAM,EAAE,aAAA,EAAe,IAAA,EAAM,CAAA;AAAA,IACzF,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAGT,EAAA,MAAM,eAAA,GAAkBC,iBAAA,CAAY,CAAC,CAAA,KAA2D;AAC9F,IAAA,IAAI,EAAE,MAAA,KAAW,CAAA,CAAE,aAAA,EAAe,UAAA,CAAW,QAAQ,UAAU,CAAA;AAAA,EACjE,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,EAAE,KAAK,eAAA,EAAgB;AAChC;AChEA,IAAM,iBAAA,GAAoBC,oBAA6C,IAAI,CAAA;AA4CpE,SAAS,qBAAA,GAAuD;AACrE,EAAA,OAAOC,iBAAW,iBAAiB,CAAA;AACrC;;;ACxDO,SAAS,kBAAkB,MAAA,EAAgC;AAChE,EAAA,MAAM,KAAK,qBAAA,EAAsB;AACjC,EAAA,OAAO,MAAA,IAAU,IAAI,MAAA,IAAU,OAAA;AACjC;ACDA,IAAI,MAAA,GAAS,KAAA;AACb,IAAM,SAAA,uBAAgB,GAAA,EAAgB;AAEtC,IAAI,SAAA,GAAY,KAAA;AAGT,SAAS,aAAa,IAAA,EAAe;AAC1C,EAAA,SAAA,GAAY,IAAA;AACd;AAEO,SAAS,WAAA,GAAc;AAC5B,EAAA,OAAO,SAAA;AACT;AAEA,SAAS,IAAI,IAAA,EAAe;AAC1B,EAAA,IAAI,WAAW,IAAA,EAAM;AACrB,EAAA,MAAA,GAAS,IAAA;AACT,EAAA,IAAI,CAAC,MAAM,SAAA,GAAY,KAAA;AACvB,EAAA,KAAA,MAAW,CAAA,IAAK,CAAC,GAAG,SAAS,GAAG,CAAA,EAAE;AACpC;AAEA,IAAM,SAAA,GAAY,CAAC,CAAA,KAAkB;AACnC,EAAA,SAAA,CAAU,IAAI,CAAC,CAAA;AACf,EAAA,OAAO,MAAM;AACX,IAAA,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,EACpB,CAAA;AACF,CAAA;AAGO,SAAS,cAAA,GAAiB;AAC/B,EAAA,GAAA,CAAI,IAAI,CAAA;AACV;AAGO,SAAS,eAAA,GAAkB;AAChC,EAAA,GAAA,CAAI,KAAK,CAAA;AACX;AAEO,SAAS,gBAAA,GAAmB;AACjC,EAAA,GAAA,CAAI,CAAC,MAAM,CAAA;AACb;AAEO,SAAS,gBAAA,GAAmB;AACjC,EAAA,OAAO,MAAA;AACT;AAGO,SAAS,aAAA,GAAgB;AAC9B,EAAA,MAAM,OAAOC,0BAAA,CAAqB,SAAA,EAAW,MAAM,MAAA,EAAQ,MAAM,KAAK,CAAA;AACtE,EAAA,MAAM,SAASH,iBAAAA,CAAY,MAAM,gBAAA,EAAiB,EAAG,EAAE,CAAA;AACvD,EAAA,OAAO,EAAE,IAAA,EAAM,UAAA,EAAY,cAAA,EAAgB,WAAA,EAAa,iBAAiB,MAAA,EAAO;AAClF;AAOO,SAAS,yBAAA,CAA0B,IAAA,EAAe,OAAA,GAA8B,EAAC,EAAG;AACzF,EAAA,MAAM,GAAA,GAAMF,aAAO,KAAK,CAAA;AACxB,EAAA,MAAM,IAAA,GAAOA,aAAO,KAAK,CAAA;AACzB,EAAA,IAAA,CAAK,OAAA,GAAU,CAAC,CAAC,OAAA,CAAQ,IAAA;AACzB,EAAAC,gBAAU,MAAM;AACd,IAAA,IAAI,IAAI,OAAA,IAAW,CAAC,QAAQ,CAAC,IAAA,CAAK,SAAS,cAAA,EAAe;AAC1D,IAAA,GAAA,CAAI,OAAA,GAAU,IAAA;AAAA,EAChB,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AACX;AAgBO,SAAS,oBAAoB,CAAA,EAAc;AAChD,EAAA,IAAI,CAAA,CAAE,gBAAA,IAAoB,CAAA,CAAE,MAAA,KAAW,CAAA,IAAK,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,QAAA,IAAY,CAAA,CAAE,MAAA,EAAQ;AAC9F,EAAA,CAAA,CAAE,cAAA,EAAe;AACjB,EAAA,cAAA,EAAe;AACjB;ACtCA,IAAM,kBAAA,GAAqB,GAAA;AAE3B,IAAI,UAA8B,EAAC;AACnC,IAAI,UAA8B,EAAC;AACnC,IAAI,YAAA,GAAmD,EAAE,IAAA,EAAM,IAAA,EAAM,GAAG,CAAA,EAAE;AAC1E,IAAI,GAAA,GAAM,CAAA;AACV,IAAM,MAAA,uBAAa,GAAA,EAA2C;AAC9D,IAAMK,UAAAA,uBAAgB,GAAA,EAAgB;AACtC,IAAI,WAA+B,OAAA,EAAQ;AAE3C,SAAS,OAAA,GAA8B;AACrC,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAA2B;AACjD,EAAA,KAAA,MAAW,KAAK,OAAA,EAAS;AACvB,IAAA,MAAM,GAAA,GAAM,SAAA,CAAU,GAAA,CAAI,CAAA,CAAE,SAAS,CAAA;AACrC,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,GAAA,CAAI,YAAY,CAAA,CAAE,QAAA;AAClB,MAAA,GAAA,CAAI,SAAA,CAAU,IAAA,CAAK,CAAA,CAAE,EAAE,CAAA;AAAA,IACzB,CAAA,MAAO;AACL,MAAA,SAAA,CAAU,GAAA,CAAI,EAAE,SAAA,EAAW;AAAA,QACzB,WAAW,CAAA,CAAE,SAAA;AAAA,QAAW,OAAO,CAAA,CAAE,KAAA;AAAA,QAAO,cAAc,CAAA,CAAE,YAAA;AAAA,QAAc,eAAe,CAAA,CAAE,aAAA;AAAA,QACvF,OAAO,CAAA,CAAE,KAAA;AAAA,QAAO,OAAO,CAAA,CAAE,KAAA;AAAA,QAAO,UAAU,CAAA,CAAE,QAAA;AAAA,QAAU,SAAA,EAAW,CAAC,CAAA,CAAE,EAAE;AAAA,OACvE,CAAA;AAAA,IACH;AAAA,EACF;AACA,EAAA,MAAM,IAAA,GAAO,CAAC,GAAG,SAAA,CAAU,QAAQ,CAAA;AACnC,EAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,CAAK,OAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,QAAA,EAAU,CAAC,CAAA,EAAG,SAAS,YAAA,EAAa;AAC3F;AAEA,SAAS,IAAA,GAAO;AACd,EAAA,QAAA,GAAW,OAAA,EAAQ;AACnB,EAAA,KAAA,MAAW,CAAA,IAAK,CAAC,GAAGA,UAAS,GAAG,CAAA,EAAE;AACpC;AAEA,IAAMC,UAAAA,GAAY,CAAC,CAAA,KAAkB;AACnC,EAAAD,UAAAA,CAAU,IAAI,CAAC,CAAA;AACf,EAAA,OAAO,MAAM;AACX,IAAAA,UAAAA,CAAU,OAAO,CAAC,CAAA;AAAA,EACpB,CAAA;AACF,CAAA;AACA,IAAM,QAA4B,EAAE,IAAA,EAAM,EAAC,EAAG,UAAU,CAAA,EAAG,OAAA,EAAS,EAAC,EAAG,cAAc,EAAE,IAAA,EAAM,IAAA,EAAM,CAAA,EAAG,GAAE,EAAE;AAE3G,SAAS,KAAK,EAAA,EAA0C;AACtD,EAAA,MAAM,IAAI,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,EAAE,CAAA;AACzC,EAAA,IAAI,CAAC,GAAG,OAAO,MAAA;AACf,EAAA,OAAA,GAAU,QAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,EAAE,CAAA;AAC3C,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,GAAA,CAAI,EAAE,CAAA;AACvB,EAAA,IAAI,CAAA,eAAgB,CAAC,CAAA;AACrB,EAAA,MAAA,CAAO,OAAO,EAAE,CAAA;AAChB,EAAA,OAAO,CAAA;AACT;AAEA,SAAS,QAAA,GAAW;AAClB,EAAA,YAAA,GAAe,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA,EAAG,YAAA,CAAa,IAAI,CAAA,EAAE;AACxD;AAEO,IAAM,cAAA,GAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,EAK5B,GAAA,CAAI,KAAA,EAA4B,OAAA,GAAkD,EAAC,EAAW;AAC5F,IAAA,IAAI,MAAM,GAAA,EAAK;AACb,MAAA,MAAM,IAAA,GAAO,QAAQ,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,GAAA,KAAQ,MAAM,GAAG,CAAA;AACpD,MAAA,IAAI,IAAA,SAAa,IAAA,CAAK,EAAA;AAAA,IACxB;AACA,IAAA,MAAM,EAAA,GAAK,CAAA,IAAA,EAAO,EAAE,GAAG,CAAA,CAAA;AACvB,IAAA,MAAM,QAAA,GAAW,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,KAAA,CAAM,QAAA,IAAY,CAAC,CAAC,CAAA;AAC5D,IAAA,OAAA,GAAU,CAAC,GAAG,OAAA,EAAS,EAAE,GAAG,KAAA,EAAO,EAAA,EAAI,UAAU,CAAA;AACjD,IAAA,MAAM,EAAA,GAAK,QAAQ,SAAA,IAAa,kBAAA;AAChC,IAAA,IAAI,EAAA,GAAK,CAAA,IAAK,OAAO,UAAA,KAAe,UAAA,EAAY;AAC9C,MAAA,MAAA,CAAO,GAAA,CAAI,EAAA,EAAI,UAAA,CAAW,MAAM,eAAe,QAAA,CAAS,EAAA,EAAI,kBAAA,CAAmB,EAAE,MAAM,SAAA,EAAW,CAAC,CAAA,EAAG,EAAE,CAAC,CAAA;AAAA,IAC3G;AACA,IAAA,QAAA,EAAS;AACT,IAAA,IAAI,OAAA,CAAQ,SAAS,KAAA,EAAO;AAC1B,MAAA,YAAA,CAAa,IAAI,CAAA;AACjB,MAAA,cAAA,EAAe;AAAA,IACjB;AACA,IAAA,IAAA,EAAK;AACL,IAAA,OAAO,EAAA;AAAA,EACT,CAAA;AAAA;AAAA,EAGA,QAAQ,EAAA,EAAY;AAClB,IAAA,IAAI,CAAC,IAAA,CAAK,EAAE,CAAA,EAAG;AACf,IAAA,QAAA,EAAS;AACT,IAAA,IAAA,EAAK;AAAA,EACP,CAAA;AAAA;AAAA,EAGA,QAAA,CAAS,EAAA,EAAY,MAAA,GAAS,SAAA,EAAW;AACvC,IAAA,MAAM,CAAA,GAAI,KAAK,EAAE,CAAA;AACjB,IAAA,IAAI,CAAC,CAAA,EAAG;AACR,IAAA,OAAA,GAAU,CAAC,GAAG,OAAA,EAAS,EAAE,EAAA,EAAI,CAAA,EAAA,EAAK,EAAE,GAAG,CAAA,CAAA,EAAI,KAAA,EAAO,CAAA,CAAE,KAAA,EAAO,QAAQ,CAAA;AACnE,IAAA,IAAA,EAAK;AAAA,EACP,CAAA;AAAA;AAAA,EAGA,QAAQ,EAAA,EAAY;AAClB,IAAA,IAAI,IAAA,CAAK,EAAE,CAAA,EAAG,IAAA,EAAK;AAAA,EACrB,CAAA;AAAA,EAEA,cAAc,EAAA,EAAY;AACxB,IAAA,OAAA,GAAU,QAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,EAAE,CAAA;AAC3C,IAAA,IAAA,EAAK;AAAA,EACP,CAAA;AAAA;AAAA,EAGA,KAAA,GAAQ;AACN,IAAA,KAAA,MAAW,CAAA,IAAK,MAAA,CAAO,MAAA,EAAO,eAAgB,CAAC,CAAA;AAC/C,IAAA,MAAA,CAAO,KAAA,EAAM;AACb,IAAA,OAAA,GAAU,EAAC;AACX,IAAA,OAAA,GAAU,EAAC;AACX,IAAA,YAAA,GAAe,EAAE,IAAA,EAAM,IAAA,EAAM,CAAA,EAAG,CAAA,EAAE;AAClC,IAAA,YAAA,CAAa,KAAK,CAAA;AAClB,IAAA,IAAA,EAAK;AAAA,EACP,CAAA;AAAA,EAEA,aAAa,MAA0B;AACzC;AAGO,SAAS,iBAAA,GAAwC;AACtD,EAAA,OAAOD,0BAAAA,CAAqBE,UAAAA,EAAW,MAAM,QAAA,EAAU,MAAM,KAAK,CAAA;AACpE;AAGO,SAAS,uBAAuB,IAAA,EAAsB;AAC3D,EAAA,OAAO,IAAA,GAAO,mBAAkB,CAAE,QAAA;AACpC;AAGO,SAAS,mBAAmB,KAAA,EAA4H;AAC7J,EAAA,MAAM,OAAO,KAAA,EAAO,IAAA;AACpB,EAAA,MAAM,SAAS,KAAA,EAAO,MAAA;AACtB,EAAA,IAAI,IAAA,KAAS,mBAAmB,OAAO,qCAAA;AACvC,EAAA,IAAI,IAAA,KAAS,WAAW,OAAO,sCAAA;AAC/B,EAAA,IAAI,WAAW,GAAA,IAAO,IAAA,KAAS,cAAA,IAAkB,IAAA,KAAS,sBAAsB,OAAO,6BAAA;AACvF,EAAA,IAAI,MAAA,KAAW,KAAK,IAAA,KAAS,SAAA,IAAc,CAAC,MAAA,IAAU,CAAC,MAAO,OAAO,uBAAA;AACrE,EAAA,IAAI,MAAA,IAAU,MAAA,IAAU,GAAA,EAAK,OAAO,oCAAA;AACpC,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,sCAAA;AAC3B,EAAA,OAAO,KAAA,EAAO,OAAA,EAAS,IAAA,EAAK,IAAK,kBAAA;AACnC;AAKO,SAAS,kBAAkB,IAAA,EAA2B;AAC3D,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA,KAAS,UAAU,OAAO,EAAE,IAAI,IAAA,EAAK;AACzD,EAAA,MAAM,CAAA,GAAI,IAAA;AACV,EAAA,MAAM,SAAS,OAAO,CAAA,CAAE,MAAA,KAAW,QAAA,GAAW,EAAE,MAAA,GAAS,MAAA;AACzD,EAAA,MAAM,GAAA,GAAO,EAAE,KAAA,IAAS,OAAO,EAAE,KAAA,KAAU,QAAA,GAAW,EAAE,KAAA,GAAQ,CAAA;AAChE,EAAA,MAAM,OAAO,OAAO,GAAA,CAAI,IAAA,KAAS,QAAA,GAAW,IAAI,IAAA,GAAO,MAAA;AACvD,EAAA,MAAM,MAAA,GAAS,CAAA,CAAE,KAAA,IAAS,IAAA,IAAQ,CAAA,CAAE,EAAA,KAAO,KAAA,IAAS,CAAA,CAAE,OAAA,KAAY,KAAA,IAAU,MAAA,KAAW,MAAA,IAAa,MAAA,IAAU,GAAA;AAC9G,EAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAE,IAAI,IAAA,EAAK;AAC/B,EAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,MAAA,EAAQ,kBAAA,CAAmB,EAAE,MAAA,EAAQ,MAAA,KAAW,OAAO,GAAA,CAAI,MAAA,KAAW,QAAA,GAAW,IAAI,MAAA,GAAS,MAAA,CAAA,EAAY,IAAA,EAAM,OAAA,EAAS,OAAO,GAAA,CAAI,OAAA,KAAY,QAAA,GAAW,GAAA,CAAI,OAAA,GAAU,MAAA,EAAW,CAAA,EAAE;AAC5M;AAQO,SAAS,gBAAA,CAAiB,OAAA,EAAsB,OAAA,GAAsD,EAAC,EAAG;AAC/G,EAAA,MAAM,OAAA,GAAUP,aAAsB,IAAI,CAAA;AAC1C,EAAA,MAAM,GAAA,GAAMA,aAAO,KAAK,CAAA;AACxB,EAAA,MAAM,SAAA,GAAYA,YAAAA,CAAO,OAAA,CAAQ,MAAM,CAAA;AACvC,EAAA,SAAA,CAAU,UAAU,OAAA,CAAQ,MAAA;AAE5B,EAAAC,gBAAU,MAAM;AACd,IAAA,MAAM,IAAA,GAAO,QAAQ,KAAA,KAAU,MAAA;AAC/B,IAAA,MAAM,KAAK,OAAA,CAAQ,OAAA;AACnB,IAAA,IAAI,GAAA,CAAI,OAAA,IAAW,CAAC,IAAA,IAAQ,EAAA,EAAI;AAC9B,MAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAClB,MAAA,MAAM,GAAA,GAAA,CAAO,SAAA,CAAU,OAAA,IAAW,iBAAA,EAAmB,QAAQ,IAAI,CAAA;AACjE,MAAA,IAAI,GAAA,CAAI,EAAA,EAAI,cAAA,CAAe,OAAA,CAAQ,EAAE,CAAA;AAAA,WAChC,cAAA,CAAe,QAAA,CAAS,EAAA,EAAI,GAAA,CAAI,MAAM,CAAA;AAAA,IAC7C;AACA,IAAA,GAAA,CAAI,OAAA,GAAU,IAAA;AAAA,EAChB,GAAG,CAAC,OAAA,CAAQ,KAAA,EAAO,OAAA,CAAQ,IAAI,CAAC,CAAA;AAEhC,EAAAA,eAAAA;AAAA,IACE,MAAM,MAAM;AACV,MAAA,IAAI,OAAA,CAAQ,OAAA,EAAS,cAAA,CAAe,OAAA,CAAQ,QAAQ,OAAO,CAAA;AAC3D,MAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAAA,IACpB,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,OAAO;AAAA,IACL,GAAA,CAAI,OAA4B,MAAA,EAA4B;AAC1D,MAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,MAAA,MAAM,EAAA,GAAK,cAAA,CAAe,GAAA,CAAI,KAAK,CAAA;AACnC,MAAA,IAAI,IAAA,IAAQ,IAAA,KAAS,EAAA,EAAI,cAAA,CAAe,QAAQ,IAAI,CAAA;AACpD,MAAA,OAAA,CAAQ,OAAA,GAAU,EAAA;AAClB,MAAA,IAAI;AACF,QAAA,MAAA,EAAO;AAAA,MACT,SAAS,CAAA,EAAG;AACV,QAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAClB,QAAA,cAAA,CAAe,QAAA,CAAS,EAAA,EAAI,kBAAA,CAAmB,EAAE,OAAA,EAAS,CAAA,YAAa,KAAA,GAAQ,CAAA,CAAE,OAAA,GAAU,MAAA,EAAW,CAAC,CAAA;AAAA,MACzG;AACA,MAAA,OAAO,EAAA;AAAA,IACT;AAAA,GACF;AACF;AC7OO,IAAM,yBAAA,GAAwD;AAAA,EACnE,MAAA,EAAQ,iBAAA;AAAA,EACR,KAAA,EAAO,qBAAA;AAAA,EACP,WAAA,EAAa,kBAAA;AAAA,EACb,QAAQ,CAAC,KAAA,EAAO,WAAW,CAAA,mBAAA,EAAsB,KAAK,KAAK,MAAM,CAAA,CAAA;AAAA,EACjE,OAAA,EAAS;AACX;AA+FA,IAAM,YAAA,GAAiD;AAAA,EACrD,WAAA,EAAa,QAAA;AAAA,EACb,SAAA,EAAW,SAAA;AAAA,EACX,aAAA,EAAe,UAAA;AAAA,EACf,YAAA,EAAc,QAAA;AAAA,EACd,YAAA,EAAc;AAChB,CAAA;AAEA,IAAM,aAAA,GAAgB,OAA2B,EAAE,IAAA,EAAM,MAAA,EAAO,CAAA;AAEhE,IAAM,0BAA0B,CAAC,CAAA,KAAc,mBAAmB,IAAA,CAAK,CAAA,CAAE,MAAM,CAAA;AAE/E,SAAS,kBAAkB,MAAA,EAAiB;AAC1C,EAAAA,gBAAU,MAAM;AACd,IAAA,IAAI,CAAC,MAAA,IAAU,OAAO,QAAA,KAAa,WAAA,EAAa;AAChD,IAAA,MAAM,KAAK,QAAA,CAAS,eAAA;AACpB,IAAA,MAAM,IAAA,GAAO,GAAG,KAAA,CAAM,QAAA;AACtB,IAAA,EAAA,CAAG,MAAM,QAAA,GAAW,QAAA;AACpB,IAAA,OAAO,MAAM;AACX,MAAA,EAAA,CAAG,MAAM,QAAA,GAAW,IAAA;AAAA,IACtB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AACb;AAUO,SAAS,WAAW,KAAA,EAAwB;AACjD,EAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAO,UAAU,MAAA,EAAQ,MAAA,EAAQ,WAAA,EAAa,KAAA,EAAO,UAAA,EAAY,EAAA,GAAK,EAAC,EAAG,cAAa,GAAI,KAAA;AACjH,EAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,KAAA,CAAM,MAAM,CAAA;AAC7C,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,aAAA,EAAc;AAC/B,EAAA,MAAM,MAAM,iBAAA,EAAkB;AAC9B,EAAA,MAAM,KAAK,EAAE,GAAG,yBAAA,EAA2B,GAAG,MAAM,gBAAA,EAAiB;AACrE,EAAA,MAAM,KAAA,GAAQ,QAAQ,WAAA,EAAY;AAClC,EAAA,MAAM,UAAUO,WAAA,EAAM;AACtB,EAAA,MAAM,WAAWA,WAAA,EAAM;AACvB,EAAA,MAAM,EAAE,GAAA,EAAK,eAAA,EAAgB,GAAI,cAAA,CAAe,EAAE,IAAA,EAAM,OAAA,EAAS,MAAM,eAAA,EAAgB,EAAG,CAAA;AAC1F,EAAA,iBAAA,CAAkB,IAAI,CAAA;AACtB,EAAAP,gBAAU,MAAM;AACd,IAAA,YAAA,GAAe,IAAI,CAAA;AAAA,EACrB,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,EAAA,MAAM,SAAA,GAAY,IAAA,EAAM,KAAA,CAAM,MAAA,IAAU,CAAA;AACxC,EAAA,MAAM,aAAA,GAAgB,IAAA,IAAQ,KAAA,IAAS,SAAA,KAAc,CAAA,IAAK,GAAA,CAAI,IAAA,CAAK,MAAA,KAAW,CAAA,IAAK,GAAA,CAAI,OAAA,CAAQ,MAAA,GAAS,CAAA;AACxG,EAAAA,gBAAU,MAAM;AAEd,IAAA,IAAI,eAAe,eAAA,EAAgB;AAAA,EACrC,CAAA,EAAG,CAAC,aAAa,CAAC,CAAA;AAElB,EAAA,IAAI,CAAC,IAAA,EAAM,OAAO,GAAA,CAAI,OAAA,CAAQ,yBAASQ,cAAAA,CAAC,iBAAA,EAAA,EAAkB,OAAA,EAAS,IAAI,OAAA,EAAS,MAAA,EAAQ,EAAA,EAAI,UAAA,EAAY,IAAI,CAAA,GAAK,IAAA;AAEjH,EAAA,MAAM,QAAQ,KAAA,CAAM,WAAA,KAAgB,CAAC,CAAA,KAAaC,sBAAA,CAAY,GAAG,MAAM,CAAA,CAAA;AACvE,EAAA,MAAM,OAAO,KAAA,CAAM,UAAA,KAAe,CAAC,EAAE,MAAM,SAAA,EAAW,QAAA,EAAU,OAAA,EAAQ,qBACtED,cAAAA,CAAC,GAAA,EAAA,EAAE,IAAA,EAAY,SAAA,EAAsB,SAAmB,QAAA,EAAS,CAAA,CAAA;AAEnE,EAAA,MAAM,gBAAA,GAAmB,IAAI,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,SAAA,EAAW,CAAC,CAAC,CAAC,CAAA;AACtE,EAAA,MAAM,KAAA,GAAA,CAAS,IAAA,EAAM,cAAA,IAAkB,CAAA,IAAK,GAAA,CAAI,QAAA;AAChD,EAAA,MAAM,KAAA,GAAQ,IAAA,EAAM,KAAA,IAAS,EAAC;AAC9B,EAAA,MAAM,YAAY,GAAA,CAAI,IAAA,CAAK,MAAA,CAAO,CAAC,MAAM,CAAC,KAAA,CAAM,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,WAAA,CAAY,EAAA,KAAO,CAAA,CAAE,SAAS,CAAC,CAAA;AAC7F,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,IAAA,CAAK,MAAA,GAAS,CAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,MAAA,KAAW,CAAA,IAAK,UAAU,MAAA,KAAW,CAAA;AACzD,EAAA,MAAM,KAAA,GAAQ,MAAM,eAAA,EAAgB;AAEpC,EAAA,uBACEA,cAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,GAAA;AAAA,MACA,IAAA,EAAK,QAAA;AAAA,MACL,YAAA,EAAW,MAAA;AAAA,MACX,iBAAA,EAAiB,OAAA;AAAA,MACjB,OAAA,EAAS,eAAA;AAAA,MACT,OAAA,EAAS,KAAA;AAAA,MACT,WAAW,EAAA,CAAG,MAAA;AAAA,MACd,qBAAA,EAAoB,EAAA;AAAA,MAEpB,0CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,KAAA,EAAO,sBAAmB,EAAA,EAC3C,QAAA,EAAA;AAAA,wBAAAE,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,MAAA,EAAQ,uBAAoB,EAAA,EAC7C,QAAA,EAAA;AAAA,0BAAAA,eAAA,CAAC,IAAA,EAAA,EAAG,IAAI,OAAA,EAAS,QAAA,EAAU,IAAI,SAAA,EAAW,EAAA,CAAG,KAAA,EAAO,oBAAA,EAAmB,EAAA,EACpE,QAAA,EAAA;AAAA,YAAA,MAAA,CAAO,KAAA;AAAA,YAAO,KAAA,GAAQ,CAAA,GAAI,CAAA,EAAA,EAAK,KAAK,CAAA,CAAA,CAAA,GAAM;AAAA,WAAA,EAC7C,CAAA;AAAA,0BACAF,cAAAA,CAAC,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,OAAA,EAAS,KAAA,EAAO,YAAA,EAAY,MAAA,CAAO,KAAA,EAAO,SAAA,EAAW,EAAA,CAAG,KAAA,EAAO,oBAAA,EAAmB,EAAA,EAAG,mBAAA,EAAmB,KAAA,GAAQ,MAAA,GAAY,EAAA,EAC/I,QAAA,EAAA,KAAA,EAAO,KAAA,oBAASA,cAAAA,CAAC,MAAA,EAAA,EAAK,aAAA,EAAY,MAAA,EAAO,QAAA,EAAA,QAAA,EAAC,CAAA,EAC7C;AAAA,SAAA,EACF,CAAA;AAAA,wBAEAA,eAAC,iBAAA,EAAA,EAAkB,OAAA,EAAS,IAAI,OAAA,EAAS,MAAA,EAAQ,EAAA,EAAI,UAAA,EAAY,EAAA,EAAI,CAAA;AAAA,wBACrEA,cAAAA,CAAC,gBAAA,EAAA,EAAiB,IAAA,EAAM,GAAA,CAAI,YAAA,CAAa,IAAA,EAAM,CAAA,EAAG,GAAA,CAAI,YAAA,CAAa,CAAA,EAAG,IAAA,EAAM,GAAG,KAAA,EAAO,CAAA;AAAA,QAErF,wBACCE,eAAA,CAAC,KAAA,EAAA,EAAI,WAAW,EAAA,CAAG,KAAA,EAAO,sBAAmB,EAAA,EAC3C,QAAA,EAAA;AAAA,0BAAAF,cAAAA,CAAC,OAAE,SAAA,EAAW,EAAA,CAAG,YAAY,0BAAA,EAAyB,EAAA,EAAI,iBAAO,KAAA,EAAM,CAAA;AAAA,UACtE,MAAA,CAAO,SAAA,mBAAYA,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAW,EAAA,CAAG,SAAA,EAAW,yBAAA,EAAwB,EAAA,EAAI,QAAA,EAAA,MAAA,CAAO,SAAA,EAAU,CAAA,GAAO,IAAA;AAAA,UACnG,MAAM,MAAA,IAAU,MAAA,CAAO,SAAS,IAAA,CAAK,EAAE,MAAM,KAAA,CAAM,MAAA,EAAQ,SAAA,EAAW,EAAA,CAAG,QAAQ,QAAA,EAAU,MAAA,CAAO,QAAQ,OAAA,EAAS,KAAA,EAAO,CAAA,GAAI;AAAA,SAAA,EACjI,oBAEAE,eAAA,CAAAC,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,0BAAAD,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,IAAA,EAAM,qBAAkB,EAAA,EACxC,QAAA,EAAA;AAAA,YAAA,QAAA,mBACCA,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,QAAA,EAAU,yBAAsB,EAAA,EAAG,cAAA,EAAc,QAAA,CAAS,OAAA,IAAW,MAAA,EACtF,QAAA,EAAA;AAAA,8BAAAA,eAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAW,EAAA,CAAG,eAAA,EACd,QAAA,EAAA;AAAA,gBAAA,QAAA,CAAS,OAAA,GAAU,KAAA,EAAO,eAAA,GAAkB,KAAA,EAAO,QAAA;AAAA,gBACnD,QAAA,CAAS;AAAA,eAAA,EACZ,CAAA;AAAA,8BACAF,cAAAA;AAAA,gBAAC,KAAA;AAAA,gBAAA;AAAA,kBACC,IAAA,EAAK,aAAA;AAAA,kBACL,eAAA,EAAe,CAAA;AAAA,kBACf,eAAA,EAAe,GAAA;AAAA,kBACf,eAAA,EAAe,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,OAAO,CAAA;AAAA,kBAC1C,cAAY,QAAA,CAAS,aAAA;AAAA,kBACrB,WAAW,EAAA,CAAG,GAAA;AAAA,kBACd,kBAAA,EAAiB,EAAA;AAAA,kBAEjB,QAAA,kBAAAA,eAAC,KAAA,EAAA,EAAI,SAAA,EAAW,GAAG,OAAA,EAAS,uBAAA,EAAsB,EAAA,EAAG,KAAA,EAAO,EAAE,KAAA,EAAO,GAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,SAAS,OAAO,CAAC,CAAC,CAAA,CAAA,CAAA,EAAI,EAAG;AAAA;AAAA;AAC7H,aAAA,EACF,CAAA,GACE,yBACFE,eAAA,CAAC,GAAA,EAAA,EAAE,WAAW,CAAC,EAAA,CAAG,UAAU,EAAA,CAAG,eAAe,EAAE,MAAA,CAAO,OAAO,EAAE,IAAA,CAAK,GAAG,KAAK,MAAA,EAAW,uBAAA,EAAsB,EAAA,EAAG,aAAA,EAAY,EAAA,EAAI,QAAA,EAAA;AAAA,cAAA,KAAA,EAAO,eAAA;AAAA,cAAiB;AAAA,aAAA,EAAO,CAAA,GAC9J,IAAA;AAAA,4CAEH,IAAA,EAAA,EAAG,SAAA,EAAW,EAAA,CAAG,KAAA,EAAO,sBAAmB,EAAA,EACzC,QAAA,EAAA;AAAA,cAAA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,qBACVF,eAAC,UAAA,EAAA,EAAyB,IAAA,EAAY,KAAA,EAAc,KAAA,EAAc,IAAA,EAAY,KAAA,EAAc,SAAS,gBAAA,CAAiB,GAAA,CAAI,IAAA,CAAK,WAAA,CAAY,EAAE,CAAA,EAAG,cAAc,EAAA,CAAG,MAAA,EAAA,EAAhJ,IAAA,CAAK,EAAmJ,CAC1K,CAAA;AAAA,cACA,UAAU,GAAA,CAAI,CAAC,GAAA,qBACdA,eAAC,WAAA,EAAA,EAA6C,GAAA,EAAU,KAAA,EAAc,KAAA,EAAc,OAAO,EAAA,CAAG,MAAA,EAAA,EAA5E,WAAW,GAAA,CAAI,SAAS,EAA4D,CACvG;AAAA,aAAA,EACH,CAAA;AAAA,YAEC,MAAA,mBACCE,eAAA,CAAC,SAAA,EAAA,EAAQ,SAAA,EAAW,EAAA,CAAG,MAAA,EAAQ,qBAAA,EAAoB,EAAA,EAAG,iBAAA,EAAiB,WAAA,GAAc,QAAA,GAAW,MAAA,EAC7F,QAAA,EAAA;AAAA,cAAA,WAAA,mBAAcF,eAAC,IAAA,EAAA,EAAG,EAAA,EAAI,UAAU,SAAA,EAAW,EAAA,CAAG,WAAA,EAAc,QAAA,EAAA,WAAA,EAAY,CAAA,GAAQ,IAAA;AAAA,cAChF;AAAA,aAAA,EACH,CAAA,GACE;AAAA,WAAA,EACN,CAAA;AAAA,0CAEC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,MAAA,EAAQ,uBAAoB,EAAA,EAC7C,QAAA,EAAA;AAAA,4BAAAE,eAAA,CAAC,KAAA,EAAA,EAAI,WAAW,EAAA,CAAG,QAAA,EAAU,yBAAsB,EAAA,EAAG,WAAA,EAAW,WAAW,MAAA,EAC1E,QAAA,EAAA;AAAA,8BAAAF,eAAC,MAAA,EAAA,EAAK,SAAA,EAAW,EAAA,CAAG,aAAA,EAAgB,iBAAO,QAAA,EAAS,CAAA;AAAA,8CACnD,MAAA,EAAA,EAAK,SAAA,EAAW,EAAA,CAAG,aAAA,EAAe,+BAA4B,EAAA,EAAI,QAAA,EAAA;AAAA,gBAAA,IAAA,GAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA,GAAI,IAAA;AAAA,gBAAM,OAAA,mBAAUE,eAAA,CAAC,MAAA,EAAA,EAAK,0BAAA,EAAyB,EAAA,EAAI,QAAA,EAAA;AAAA,kBAAA,IAAA,GAAO,GAAA,GAAM,EAAA;AAAA,kBAAI,EAAA,CAAG;AAAA,iBAAA,EAAY,CAAA,GAAU;AAAA,eAAA,EAAK;AAAA,aAAA,EAC1M,CAAA;AAAA,YACC,MAAA,CAAO,IAAA,mBAAOF,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAW,EAAA,CAAG,IAAA,EAAM,mBAAA,EAAkB,EAAA,EAAI,QAAA,EAAA,MAAA,CAAO,IAAA,EAAK,CAAA,GAAO,IAAA;AAAA,4CAC9E,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,OAAA,EAAS,wBAAqB,EAAA,EAC9C,QAAA,EAAA;AAAA,cAAA,IAAA,CAAK,EAAE,IAAA,EAAM,KAAA,CAAM,QAAA,EAAU,SAAA,EAAW,EAAA,CAAG,QAAA,EAAU,QAAA,EAAU,MAAA,CAAO,QAAA,EAAU,OAAA,EAAS,KAAA,EAAO,CAAA;AAAA,cAChG,IAAA,CAAK,EAAE,IAAA,EAAM,KAAA,CAAM,IAAA,EAAM,SAAA,EAAW,EAAA,CAAG,QAAA,EAAU,QAAA,EAAU,MAAA,CAAO,QAAA,EAAU,OAAA,EAAS,OAAO;AAAA,aAAA,EAC/F;AAAA,WAAA,EACF;AAAA,SAAA,EACF;AAAA,OAAA,EAEJ;AAAA;AAAA,GACF;AAEJ;AAEA,SAAS,UAAA,CAAW;AAAA,EAClB,IAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,EAQG;AACD,EAAA,MAAM,EAAE,QAAQ,KAAA,EAAO,KAAA,EAAO,YAAY,EAAA,GAAK,IAAG,GAAI,KAAA;AACtD,EAAA,MAAM,IAAI,EAAE,GAAG,YAAA,EAAc,GAAG,MAAM,IAAA,EAAK;AAC3C,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAS,GAAA,CAAK,KAAA,CAAM,eAAe,aAAA,GAAe;AAChE,EAAA,MAAM,QAAA,GAAW,QAAA,GAAW,MAAA,CAAO,QAAA,CAAS,GAAA,CAAI,CAAA,CAAE,aAAa,CAAA,IAAK,CAAC,CAAA,GAAI,IAAA,CAAK,QAAA,IAAY,SAAS,QAAA,IAAY,CAAA,CAAA;AAC/G,EAAA,IAAI,QAAA,KAAa,QAAA,CAAS,GAAA,CAAI,CAAA,CAAE,WAAW,MAAM,CAAA,CAAE,YAAA,IAAgB,QAAA,KAAa,CAAA,CAAA,EAAI,OAAO,IAAA;AAE3F,EAAA,MAAM,QAAQ,IAAA,CAAK,WAAA;AACnB,EAAA,MAAM,SAAA,GAAY,MAAM,qBAAA,IAAyB,uBAAA;AACjD,EAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,KAAA;AAC5B,EAAA,MAAM,OAAO,KAAA,CAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,MAAA,EAAQ,MAAM,EAAE,CAAA;AAC3D,EAAA,MAAM,GAAA,GAAM,KAAA,CAAM,KAAA,IAAS,KAAA,CAAM,OAAA,CAAQ,cAAA;AACzC,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,WAAA,GAAc,KAAA,CAAM,WAAA,CAAY,IAAI,CAAA,GAAI,GAAA,mBAC1DA,cAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAK,GAAA,CAAI,KAAK,GAAA,EAAK,GAAA,CAAI,GAAA,IAAO,EAAA,EAAI,KAAA,EAAO,EAAA,EAAI,MAAA,EAAQ,EAAA,EAAI,OAAA,EAAQ,MAAA,EAAO,QAAA,EAAS,OAAA,EAAQ,CAAA,GAC5F,IAAA;AAEJ,EAAA,MAAM,SAAA,mBAAYA,cAAAA,CAAC,MAAA,EAAA,EAAK,WAAW,EAAA,CAAG,KAAA,EAAO,oBAAA,EAAmB,EAAA,EAAI,QAAA,EAAA,KAAA,EAAM,CAAA;AAC1E,EAAA,MAAM,KAAA,mBAAQA,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,EAAA,CAAG,KAAA,EAAO,oBAAA,EAAmB,EAAA,EAAI,QAAA,EAAA,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,KAAK,CAAA,EAAE,CAAA;AACvF,EAAA,MAAM,2BACJE,eAAA,CAAC,KAAA,EAAA,EAAI,WAAW,EAAA,CAAG,QAAA,EAAU,yBAAsB,EAAA,EACjD,QAAA,EAAA;AAAA,oBAAAA,eAAA,CAAC,IAAA,EAAA,EAAK,MAAA,EAAO,MAAA,EAAO,MAAA,EAAQ,KAAA,CAAM,MAAM,SAAA,EAAW,EAAA,CAAG,GAAA,EAAK,kBAAA,EAAiB,EAAA,EAC1E,QAAA,EAAA;AAAA,sBAAAF,cAAAA,CAAC,WAAM,IAAA,EAAK,QAAA,EAAS,MAAM,CAAA,CAAE,WAAA,EAAa,KAAA,EAAO,CAAA,CAAE,YAAA,EAAc,CAAA;AAAA,sBACjEA,cAAAA,CAAC,OAAA,EAAA,EAAM,IAAA,EAAK,QAAA,EAAS,MAAM,CAAA,CAAE,SAAA,EAAW,KAAA,EAAO,IAAA,CAAK,EAAA,EAAI,CAAA;AAAA,sBACxDA,cAAAA,CAAC,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,IAAA,EAAM,CAAA,CAAE,aAAA,EAAe,KAAA,EAAO,QAAA,GAAW,CAAA,EAAG,YAAA,EAAY,MAAA,CAAO,QAAA,EAAU,SAAA,EAAW,EAAA,CAAG,SAAA,EAAW,yBAAA,EAAwB,EAAA,EAC7I,QAAA,EAAA,KAAA,EAAO,QAAA,oBAAYA,cAAAA,CAAC,MAAA,EAAA,EAAK,aAAA,EAAY,MAAA,EAAO,QAAA,EAAA,QAAA,EAAC,CAAA,EAChD,CAAA;AAAA,sBACAA,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,EAAA,CAAG,UAAU,WAAA,EAAU,QAAA,EAAS,wBAAA,EAAuB,EAAA,EAAI,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,sBACrFA,cAAAA,CAAC,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,IAAA,EAAM,CAAA,CAAE,aAAA,EAAe,KAAA,EAAO,QAAA,GAAW,CAAA,EAAG,YAAA,EAAY,MAAA,CAAO,QAAA,EAAU,SAAA,EAAW,EAAA,CAAG,SAAA,EAAW,yBAAA,EAAwB,EAAA,EAC7I,QAAA,EAAA,KAAA,EAAO,QAAA,oBAAYA,cAAAA,CAAC,MAAA,EAAA,EAAK,aAAA,EAAY,MAAA,EAAO,QAAA,EAAA,GAAA,EAAC,CAAA,EAChD;AAAA,KAAA,EACF,CAAA;AAAA,oBACAE,eAAA,CAAC,QAAK,MAAA,EAAO,MAAA,EAAO,QAAQ,KAAA,CAAM,IAAA,EAAM,4BAAyB,EAAA,EAC/D,QAAA,EAAA;AAAA,sBAAAF,cAAAA,CAAC,WAAM,IAAA,EAAK,QAAA,EAAS,MAAM,CAAA,CAAE,WAAA,EAAa,KAAA,EAAO,CAAA,CAAE,YAAA,EAAc,CAAA;AAAA,sBACjEA,cAAAA,CAAC,OAAA,EAAA,EAAM,IAAA,EAAK,QAAA,EAAS,MAAM,CAAA,CAAE,SAAA,EAAW,KAAA,EAAO,IAAA,CAAK,EAAA,EAAI,CAAA;AAAA,sBACxDA,cAAAA,CAAC,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,SAAA,EAAW,EAAA,CAAG,MAAA,EAAQ,qBAAA,EAAoB,EAAA,EAAI,QAAA,EAAA,MAAA,CAAO,MAAA,EAAO;AAAA,KAAA,EACpF;AAAA,GAAA,EACF,CAAA;AAGF,EAAA,IAAI,KAAA,CAAM,YAAY,uBAAOA,eAAC,IAAA,EAAA,EAAiB,SAAA,EAAW,EAAA,CAAG,IAAA,EAAM,mBAAA,EAAkB,EAAA,EAAI,gBAAM,UAAA,CAAW,IAAA,EAAM,EAAE,QAAA,EAAU,KAAA,EAAO,OAAO,SAAA,EAAW,CAAA,EAAA,EAA/G,IAAA,CAAK,EAA4G,CAAA;AAEvJ,EAAA,uCACG,IAAA,EAAA,EAAG,SAAA,EAAW,EAAA,CAAG,IAAA,EAAM,qBAAkB,EAAA,EACvC,QAAA,EAAA;AAAA,IAAA,SAAA;AAAA,oCACA,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,QAAA,EAAU,0BAAuB,EAAA,EAClD,QAAA,EAAA;AAAA,sBAAAE,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,QAAA,EAAU,0BAAuB,EAAA,EAClD,QAAA,EAAA;AAAA,wBAAAA,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,QAAA,EAAU,0BAAuB,EAAA,EACjD,QAAA,EAAA;AAAA,UAAA,IAAA,GAAO,IAAA,CAAK,EAAE,IAAA,EAAM,SAAA,EAAW,GAAG,SAAA,EAAW,QAAA,EAAU,OAAO,OAAA,EAAS,KAAA,EAAO,CAAA,mBAAIF,eAAC,MAAA,EAAA,EAAK,SAAA,EAAW,GAAG,SAAA,EAAW,yBAAA,EAAwB,IAAI,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,UACnJ,CAAC,SAAA,CAAU,KAAA,CAAM,KAAK,oBAAIA,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAW,GAAG,OAAA,EAAS,sBAAA,EAAqB,EAAA,EAAI,QAAA,EAAA,KAAA,CAAM,OAAM,CAAA,GAAO;AAAA,SAAA,EACnG,CAAA;AAAA,QACC;AAAA,OAAA,EACH,CAAA;AAAA,MACC,QAAA;AAAA,MACA,OAAA,mBAAUA,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAW,GAAG,OAAA,EAAS,4BAAA,EAA2B,EAAA,EAAI,QAAA,EAAA,YAAA,EAAa,CAAA,GAAO;AAAA,KAAA,EAC1F;AAAA,GAAA,EACF,CAAA;AAEJ;AAGA,SAAS,YAAY,EAAE,GAAA,EAAK,KAAA,EAAO,KAAA,EAAO,OAAM,EAAkG;AAChJ,EAAA,MAAM,EAAE,UAAA,EAAY,EAAA,GAAK,IAAG,GAAI,KAAA;AAChC,EAAA,MAAM,SAAA,GAAY,MAAM,qBAAA,IAAyB,uBAAA;AACjD,EAAA,uBACEE,eAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAW,EAAA,CAAG,IAAA,EAAM,qBAAkB,EAAA,EAAG,2BAAA,EAA0B,EAAA,EAAG,WAAA,EAAU,MAAA,EAClF,QAAA,EAAA;AAAA,oBAAAF,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,EAAA,CAAG,KAAA,EAAO,oBAAA,EAAmB,EAAA,EAC3C,QAAA,EAAA,GAAA,CAAI,KAAA,mBAAQA,cAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAK,GAAA,CAAI,KAAA,CAAM,GAAA,EAAK,GAAA,EAAK,GAAA,CAAI,KAAA,CAAM,GAAA,IAAO,EAAA,EAAI,KAAA,EAAO,EAAA,EAAI,MAAA,EAAQ,EAAA,EAAI,QAAA,EAAS,OAAA,EAAQ,CAAA,GAAK,IAAA,EAC/G,CAAA;AAAA,oCACC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,QAAA,EAAU,0BAAuB,EAAA,EAClD,QAAA,EAAA;AAAA,sBAAAE,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,QAAA,EAAU,0BAAuB,EAAA,EAClD,QAAA,EAAA;AAAA,wBAAAA,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,QAAA,EAAU,0BAAuB,EAAA,EAClD,QAAA,EAAA;AAAA,0BAAAF,cAAAA,CAAC,UAAK,SAAA,EAAW,EAAA,CAAG,WAAW,yBAAA,EAAwB,EAAA,EAAI,cAAI,KAAA,EAAM,CAAA;AAAA,UACpE,IAAI,YAAA,IAAgB,CAAC,SAAA,CAAU,GAAA,CAAI,YAAY,CAAA,mBAAIA,cAAAA,CAAC,GAAA,EAAA,EAAE,WAAW,EAAA,CAAG,OAAA,EAAS,wBAAqB,EAAA,EAAI,QAAA,EAAA,GAAA,CAAI,cAAa,CAAA,GAAO;AAAA,SAAA,EACjI,CAAA;AAAA,QACC,GAAA,CAAI,KAAA,mBAAQA,cAAAA,CAAC,UAAK,SAAA,EAAW,EAAA,CAAG,KAAA,EAAO,oBAAA,EAAmB,EAAA,EAAI,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,KAAK,GAAE,CAAA,GAAU;AAAA,OAAA,EAC5F,CAAA;AAAA,sCACC,GAAA,EAAA,EAAE,SAAA,EAAW,EAAA,CAAG,OAAA,EAAS,8BAA2B,EAAA,EAAI,QAAA,EAAA;AAAA,QAAA,KAAA;AAAA,QAAM,YAAA;AAAA,QAAK,GAAA,CAAI;AAAA,OAAA,EAAS;AAAA,KAAA,EACnF;AAAA,GAAA,EACF,CAAA;AAEJ;AAGA,SAAS,gBAAA,CAAiB,EAAE,IAAA,EAAM,CAAA,EAAG,MAAK,EAAsD;AAC9F,EAAA,uBACEA,eAAC,KAAA,EAAA,EAAI,IAAA,EAAK,UAAS,WAAA,EAAU,QAAA,EAAS,uBAAoB,EAAA,EAAG,KAAA,EAAO,iBACjE,QAAA,EAAA,IAAA,KAAS,OAAA,GAAU,GAAG,IAAI,CAAA,EAAG,IAAI,CAAA,GAAI,EAAA,GAAK,QAAQ,CAAA,CAAA,GAAK,EAAA,EAC1D,CAAA;AAEJ;AAEA,IAAM,kBAAkB,EAAE,QAAA,EAAU,YAAY,KAAA,EAAO,CAAA,EAAG,QAAQ,CAAA,EAAG,MAAA,EAAQ,IAAI,OAAA,EAAS,CAAA,EAAG,UAAU,QAAA,EAAU,IAAA,EAAM,iBAAiB,UAAA,EAAY,QAAA,EAAU,QAAQ,CAAA,EAAE;AAGxK,SAAS,kBAAkB,EAAE,OAAA,EAAAI,UAAS,MAAA,EAAQ,UAAA,EAAY,IAAG,EAAsI;AACjM,EAAA,uBACEJ,eAAC,KAAA,EAAA,EAAI,IAAA,EAAK,SAAQ,WAAA,EAAU,WAAA,EAAY,wBAAqB,EAAA,EAAG,SAAA,EAAW,GAAG,OAAA,EAC3E,QAAA,EAAAI,SAAQ,GAAA,CAAI,CAAC,sBACZF,eAAA,CAAC,GAAA,EAAA,EAAa,uBAAoB,EAAA,EAChC,QAAA,EAAA;AAAA,oBAAAF,cAAAA,CAAC,UAAM,QAAA,EAAA,MAAA,CAAO,MAAA,CAAO,EAAE,KAAA,EAAO,CAAA,CAAE,MAAM,CAAA,EAAE,CAAA;AAAA,oBACxCA,eAAC,QAAA,EAAA,EAAO,IAAA,EAAK,UAAS,OAAA,EAAS,MAAM,cAAA,CAAe,aAAA,CAAc,CAAA,CAAE,EAAE,GAAG,YAAA,EAAY,MAAA,CAAO,OAAA,EAAS,6BAAA,EAA4B,EAAA,EAC/H,QAAA,kBAAAA,eAAC,MAAA,EAAA,EAAK,aAAA,EAAY,MAAA,EAAO,QAAA,EAAA,QAAA,EAAC,CAAA,EAC5B;AAAA,GAAA,EAAA,EAJM,CAAA,CAAE,EAKV,CACD,CAAA,EACH,CAAA;AAEJ","file":"cart.cjs","sourcesContent":["import { useCallback, useEffect, useRef, type RefObject } from 'react'\n\nexport type DialogCloseReason = 'esc' | 'x' | 'backdrop' | 'action'\n\ntype UseModalDialogOptions = {\n open: boolean\n /** Called for Esc and backdrop clicks. The owner decides whether to close. */\n onClose: (reason: DialogCloseReason) => void\n /** Element focused when the dialog opens. Default: the element marked `data-sf-autofocus`, else the dialog itself. */\n initialFocus?: RefObject<HTMLElement | null>\n}\n\n/**\n * Native `<dialog>` wiring: `showModal()` (focus trap and inert background come from the browser),\n * Esc and backdrop clicks routed to `onClose`, and focus restored to the opener on close.\n * Falls back to the `open` attribute where `showModal` does not exist (old browsers, some test DOMs)\n * with an Esc key handler.\n */\nexport function useModalDialog({ open, onClose, initialFocus }: UseModalDialogOptions) {\n const ref = useRef<HTMLDialogElement | null>(null)\n const opener = useRef<Element | null>(null)\n const onCloseRef = useRef(onClose)\n onCloseRef.current = onClose\n\n useEffect(() => {\n const el = ref.current\n if (!el || !open) return\n opener.current = typeof document !== 'undefined' ? document.activeElement : null\n const hasModal = typeof el.showModal === 'function'\n if (!el.open) {\n if (hasModal) {\n try {\n el.showModal()\n } catch {\n el.setAttribute('open', '')\n }\n } else el.setAttribute('open', '')\n }\n const target = initialFocus?.current ?? el.querySelector<HTMLElement>('[data-sf-autofocus]') ?? el\n if (!target.hasAttribute('tabindex') && target === el) el.setAttribute('tabindex', '-1')\n target.focus({ preventScroll: true })\n\n const onCancel = (e: Event) => {\n e.preventDefault() // we close through state so the owner can navigate/track first\n onCloseRef.current('esc')\n }\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n onCloseRef.current('esc')\n }\n }\n el.addEventListener('cancel', onCancel)\n if (!hasModal) el.addEventListener('keydown', onKey)\n return () => {\n el.removeEventListener('cancel', onCancel)\n el.removeEventListener('keydown', onKey)\n if (el.open) {\n if (typeof el.close === 'function') {\n try {\n el.close()\n } catch {\n el.removeAttribute('open')\n }\n } else el.removeAttribute('open')\n }\n const back = opener.current\n if (back instanceof HTMLElement && back.isConnected) back.focus({ preventScroll: true })\n }\n }, [open])\n\n /** Click on the backdrop (the dialog element itself, outside its content box). */\n const onBackdropClick = useCallback((e: { target: EventTarget; currentTarget: EventTarget }) => {\n if (e.target === e.currentTarget) onCloseRef.current('backdrop')\n }, [])\n\n return { ref, onBackdropClick }\n}\n\n/** `prefers-reduced-motion: reduce`, read after hydration (false on the server). */\nexport function prefersReducedMotion(): boolean {\n try {\n return typeof window !== 'undefined' && !!window.matchMedia?.('(prefers-reduced-motion: reduce)').matches\n } catch {\n return false\n }\n}\n","import { createContext, useContext, useMemo, type ReactNode } from 'react'\nimport { createStorefrontClient, type Shop, type StorefrontClient, type StorefrontClientOptions } from '@asteby/storefront'\n\nexport type StorefrontContextValue = {\n /** Client for browser-side calls (use a public `pk_` token). */\n client: StorefrontClient | null\n shop: Shop | null\n /** BCP 47 locale used for formatting (defaults to `shop.locale`, then `es-MX`). */\n locale: string\n /** ISO 4217 currency (defaults to `shop.currency_code`, then `MXN`). */\n currency: string\n}\n\nconst StorefrontContext = createContext<StorefrontContextValue | null>(null)\n\nexport type StorefrontProviderProps = {\n /** A ready client. Takes precedence over `config`. */\n client?: StorefrontClient\n /** Options to create the browser client (use a `pk_` token). */\n config?: StorefrontClientOptions\n /** Shop info loaded on the server (root loader). */\n shop?: Shop | null\n locale?: string\n currency?: string\n children?: ReactNode\n}\n\n/**\n * Makes the storefront client, shop, locale and currency available to the\n * tree. SSR-safe: creating the client does not touch `window`.\n */\nexport function StorefrontProvider({ client, config, shop = null, locale, currency, children }: StorefrontProviderProps) {\n const configKey = config ? `${config.baseUrl}|${config.token}|${config.locale ?? ''}|${config.customerToken ?? ''}` : ''\n const resolvedClient = useMemo(\n () => client ?? (config ? createStorefrontClient(config) : null),\n [client, configKey],\n )\n const value = useMemo<StorefrontContextValue>(\n () => ({\n client: resolvedClient,\n shop,\n locale: locale ?? config?.locale ?? shop?.locale ?? 'es-MX',\n currency: currency ?? shop?.currency_code ?? 'MXN',\n }),\n [resolvedClient, shop, locale, currency, config?.locale],\n )\n return <StorefrontContext.Provider value={value}>{children}</StorefrontContext.Provider>\n}\n\n/** Storefront context. Throws outside `<StorefrontProvider>`. */\nexport function useStorefront(): StorefrontContextValue {\n const ctx = useContext(StorefrontContext)\n if (!ctx) throw new Error('useStorefront must be used inside <StorefrontProvider>')\n return ctx\n}\n\n/** Storefront context or `null` outside a provider (for components that work standalone). */\nexport function useOptionalStorefront(): StorefrontContextValue | null {\n return useContext(StorefrontContext)\n}\n\n/** The client from context; throws when the provider has none. */\nexport function useStorefrontClient(): StorefrontClient {\n const { client } = useStorefront()\n if (!client) throw new Error('<StorefrontProvider> needs a `client` or `config` for browser-side calls')\n return client\n}\n","import { useOptionalStorefront } from './context.js'\n\n/** Locale of a component: its own prop, else the `StorefrontProvider`'s, else `es-MX`. */\nexport function useResolvedLocale(locale?: string | null): string {\n const sf = useOptionalStorefront()\n return locale ?? sf?.locale ?? 'es-MX'\n}\n","import { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\n\n// Estado mínimo del cajón del carrito, fuera de React: cualquier parte de la tienda (cabecera, tarjeta, ficha)\n// lo abre sin pasar props. Es del navegador; en el servidor siempre está cerrado.\n\nlet isOpen = false\nconst listeners = new Set<() => void>()\n\nlet quietOpen = false\n\n/** Marca que el cajón lo abrió una acción optimista (la apertura no mueve el foco al botón de cierre). */\nexport function setQuietOpen(next: boolean) {\n quietOpen = next\n}\n\nexport function isQuietOpen() {\n return quietOpen\n}\n\nfunction set(next: boolean) {\n if (isOpen === next) return\n isOpen = next\n if (!next) quietOpen = false\n for (const l of [...listeners]) l()\n}\n\nconst subscribe = (l: () => void) => {\n listeners.add(l)\n return () => {\n listeners.delete(l)\n }\n}\n\n/** Abre el cajón del carrito desde cualquier parte. */\nexport function openCartDrawer() {\n set(true)\n}\n\n/** Cierra el cajón del carrito. */\nexport function closeCartDrawer() {\n set(false)\n}\n\nexport function toggleCartDrawer() {\n set(!isOpen)\n}\n\nexport function isCartDrawerOpen() {\n return isOpen\n}\n\n/** Estado y acciones del cajón. `open` es `false` en el servidor y en la primera pintura. */\nexport function useCartDrawer() {\n const open = useSyncExternalStore(subscribe, () => isOpen, () => false)\n const toggle = useCallback(() => toggleCartDrawer(), [])\n return { open, openDrawer: openCartDrawer, closeDrawer: closeCartDrawer, toggle }\n}\n\n/**\n * Abre el cajón cuando termina un \"agregar al carrito\". `busy` es verdadero mientras hay un agregado en vuelo\n * (en React Router: algún fetcher con la acción del carrito e intención de agregar). Con `skip` verdadero al\n * terminar (error, agregado silencioso) no se abre.\n */\nexport function useOpenCartDrawerWhenDone(busy: boolean, options: { skip?: boolean } = {}) {\n const was = useRef(false)\n const skip = useRef(false)\n skip.current = !!options.skip\n useEffect(() => {\n if (was.current && !busy && !skip.current) openCartDrawer()\n was.current = busy\n }, [busy])\n}\n\ntype ClickLike = {\n defaultPrevented: boolean\n button: number\n metaKey: boolean\n ctrlKey: boolean\n shiftKey: boolean\n altKey: boolean\n preventDefault: () => void\n}\n\n/**\n * `onClick` para el enlace \"Mi carrito\" de la cabecera: con un clic normal abre el cajón; con clic con\n * modificador, clic central o sin JavaScript el `href` (la página del carrito) sigue funcionando.\n */\nexport function handleCartLinkClick(e: ClickLike) {\n if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return\n e.preventDefault()\n openCartDrawer()\n}\n","import { useEffect, useRef, useSyncExternalStore } from 'react'\nimport type { Money } from '@asteby/storefront'\nimport { openCartDrawer, setQuietOpen } from './store.js'\n\n// Estado optimista del cajón del carrito. Solo guarda FILAS provisionales (producto, imagen, título, precio mostrado\n// y cantidad) mientras OPS responde. Nunca calcula dinero: precios, totales, impuestos y envío los dicta OPS cuando\n// llega el carrito real. Vive fuera de React, como el estado de apertura del cajón.\n\n/** Lo que la tienda sabe del producto al pulsar «Agregar». `price` es el precio unitario ya mostrado en la ficha. */\nexport type OptimisticLineInput = {\n /** Variante agregada; dos acciones con la misma variante comparten una sola fila. */\n variantId: string\n title: string\n variantTitle?: string | null | undefined\n productHandle?: string | undefined\n image?: { url: string; alt?: string | null | undefined } | null | undefined\n /** Precio unitario mostrado (solo se pinta, no se multiplica ni se suma). */\n price?: Money | null | undefined\n /** Unidades de ESTA acción (por omisión 1). */\n quantity?: number | undefined\n /** Clave de idempotencia: repetir `add` con una clave viva devuelve la misma acción sin sumar otra vez. */\n key?: string | undefined\n}\n\nexport type OptimisticAction = Required<Pick<OptimisticLineInput, 'variantId' | 'title'>> &\n Omit<OptimisticLineInput, 'quantity' | 'key'> & { id: string; quantity: number; key?: string | undefined }\n\n/** Fila provisional: todas las acciones en vuelo de una misma variante. */\nexport type OptimisticRow = {\n variantId: string\n title: string\n variantTitle?: string | null | undefined\n productHandle?: string | undefined\n image?: { url: string; alt?: string | null | undefined } | null | undefined\n price?: Money | null | undefined\n /** Unidades agregadas que OPS aún no confirma. */\n quantity: number\n actionIds: string[]\n}\n\nexport type OptimisticNotice = { id: string; title: string; reason: string }\n\nexport type OptimisticSnapshot = {\n rows: readonly OptimisticRow[]\n /** Unidades provisionales en total (para el contador). */\n quantity: number\n notices: readonly OptimisticNotice[]\n /** Último evento a anunciar en la región `aria-live=\"polite\"`; `n` cambia en cada evento. */\n announcement: { kind: 'added' | null; n: number }\n}\n\nexport type AddOutcome = { ok: true } | { ok: false; reason: string }\n\nconst DEFAULT_TIMEOUT_MS = 30_000\n\nlet actions: OptimisticAction[] = []\nlet notices: OptimisticNotice[] = []\nlet announcement: OptimisticSnapshot['announcement'] = { kind: null, n: 0 }\nlet seq = 0\nconst timers = new Map<string, ReturnType<typeof setTimeout>>()\nconst listeners = new Set<() => void>()\nlet snapshot: OptimisticSnapshot = compute()\n\nfunction compute(): OptimisticSnapshot {\n const byVariant = new Map<string, OptimisticRow>()\n for (const a of actions) {\n const row = byVariant.get(a.variantId)\n if (row) {\n row.quantity += a.quantity\n row.actionIds.push(a.id)\n } else {\n byVariant.set(a.variantId, {\n variantId: a.variantId, title: a.title, variantTitle: a.variantTitle, productHandle: a.productHandle,\n image: a.image, price: a.price, quantity: a.quantity, actionIds: [a.id],\n })\n }\n }\n const rows = [...byVariant.values()]\n return { rows, quantity: rows.reduce((n, r) => n + r.quantity, 0), notices, announcement }\n}\n\nfunction emit() {\n snapshot = compute()\n for (const l of [...listeners]) l()\n}\n\nconst subscribe = (l: () => void) => {\n listeners.add(l)\n return () => {\n listeners.delete(l)\n }\n}\nconst EMPTY: OptimisticSnapshot = { rows: [], quantity: 0, notices: [], announcement: { kind: null, n: 0 } }\n\nfunction drop(id: string): OptimisticAction | undefined {\n const a = actions.find((x) => x.id === id)\n if (!a) return undefined\n actions = actions.filter((x) => x.id !== id)\n const t = timers.get(id)\n if (t) clearTimeout(t)\n timers.delete(id)\n return a\n}\n\nfunction announce() {\n announcement = { kind: 'added', n: announcement.n + 1 }\n}\n\nexport const cartOptimistic = {\n /**\n * Inserta YA la fila provisional, sube el contador y abre el cajón sin robar el foco. Devuelve el id de la acción\n * para `confirm` / `rollback`. Una acción por clic: la misma variante suma cantidad en una sola fila.\n */\n add(input: OptimisticLineInput, options: { open?: boolean; timeoutMs?: number } = {}): string {\n if (input.key) {\n const live = actions.find((a) => a.key === input.key)\n if (live) return live.id\n }\n const id = `opt-${++seq}`\n const quantity = Math.max(1, Math.floor(input.quantity ?? 1))\n actions = [...actions, { ...input, id, quantity }]\n const ms = options.timeoutMs ?? DEFAULT_TIMEOUT_MS\n if (ms > 0 && typeof setTimeout === 'function') {\n timers.set(id, setTimeout(() => cartOptimistic.rollback(id, describeAddFailure({ code: 'timeout' })), ms))\n }\n announce()\n if (options.open !== false) {\n setQuietOpen(true)\n openCartDrawer()\n }\n emit()\n return id\n },\n\n /** OPS confirmó: la fila provisional sale y el carrito real (ya en `cart`) ocupa su lugar. */\n confirm(id: string) {\n if (!drop(id)) return\n announce()\n emit()\n },\n\n /** Falló: se quita la acción (y su cantidad) y se avisa «No pudimos agregar X: motivo». */\n rollback(id: string, reason = 'unknown') {\n const a = drop(id)\n if (!a) return\n notices = [...notices, { id: `n-${++seq}`, title: a.title, reason }]\n emit()\n },\n\n /** Quita la acción sin avisar (el componente que la lanzó se desmontó). */\n discard(id: string) {\n if (drop(id)) emit()\n },\n\n dismissNotice(id: string) {\n notices = notices.filter((n) => n.id !== id)\n emit()\n },\n\n /** Limpia todo (pruebas, cierre de sesión). */\n reset() {\n for (const t of timers.values()) clearTimeout(t)\n timers.clear()\n actions = []\n notices = []\n announcement = { kind: null, n: 0 }\n setQuietOpen(false)\n emit()\n },\n\n getSnapshot: (): OptimisticSnapshot => snapshot,\n}\n\n/** Estado optimista (filas, contador, avisos). En el servidor siempre vacío. */\nexport function useOptimisticCart(): OptimisticSnapshot {\n return useSyncExternalStore(subscribe, () => snapshot, () => EMPTY)\n}\n\n/** Contador para la cabecera: unidades del carrito de OPS más las que están en vuelo. */\nexport function useOptimisticCartCount(base: number): number {\n return base + useOptimisticCart().quantity\n}\n\n/** Motivo corto en es-MX a partir de un error de la acción (HTTP, código de OPS o red). */\nexport function describeAddFailure(error: { status?: number | undefined; code?: string | undefined; message?: string | undefined } | null | undefined): string {\n const code = error?.code\n const status = error?.status\n if (code === 'store_not_ready') return 'la tienda está cerrada por ahora'\n if (code === 'timeout') return 'tardó demasiado, intenta de nuevo'\n if (status === 409 || code === 'out_of_stock' || code === 'insufficient_stock') return 'sin existencias suficientes'\n if (status === 0 || code === 'network' || (!status && !code)) return 'revisa tu conexión'\n if (status && status >= 500) return 'hubo un problema, intenta de nuevo'\n if (status === 404) return 'el producto ya no está disponible'\n return error?.message?.trim() || 'intenta de nuevo'\n}\n\ntype FetcherLike = { state: string; data?: unknown }\n\n/** Interpreta `fetcher.data` de la acción de ruta: `{ error }`, `{ success:false }`, `{ ok:false }` o `status >= 400` fallan. */\nexport function defaultAddOutcome(data: unknown): AddOutcome {\n if (!data || typeof data !== 'object') return { ok: true }\n const d = data as Record<string, unknown>\n const status = typeof d.status === 'number' ? d.status : undefined\n const err = (d.error && typeof d.error === 'object' ? d.error : d) as Record<string, unknown>\n const code = typeof err.code === 'string' ? err.code : undefined\n const failed = d.error != null || d.ok === false || d.success === false || (status !== undefined && status >= 400)\n if (!failed) return { ok: true }\n return { ok: false, reason: describeAddFailure({ status: status ?? (typeof err.status === 'number' ? err.status : undefined), code, message: typeof err.message === 'string' ? err.message : undefined }) }\n}\n\n/**\n * Conecta un `useFetcher()` de React Router con el estado optimista. `add(input, submit)` inserta la fila, abre el\n * cajón y llama a `submit()` (el `fetcher.submit(...)` de la tienda); al terminar el fetcher confirma o revierte.\n * Un nuevo `add` con el mismo fetcher antes de terminar da por entregado el anterior (el router lo reemplaza y el\n * carrito real que llega con la revalidación manda). Si el componente se desmonta, las filas se descartan sin aviso.\n */\nexport function useOptimisticAdd(fetcher: FetcherLike, options: { settle?: (data: unknown) => AddOutcome } = {}) {\n const current = useRef<string | null>(null)\n const was = useRef(false)\n const settleRef = useRef(options.settle)\n settleRef.current = options.settle\n\n useEffect(() => {\n const busy = fetcher.state !== 'idle'\n const id = current.current\n if (was.current && !busy && id) {\n current.current = null\n const out = (settleRef.current ?? defaultAddOutcome)(fetcher.data)\n if (out.ok) cartOptimistic.confirm(id)\n else cartOptimistic.rollback(id, out.reason)\n }\n was.current = busy\n }, [fetcher.state, fetcher.data])\n\n useEffect(\n () => () => {\n if (current.current) cartOptimistic.discard(current.current)\n current.current = null\n },\n [],\n )\n\n return {\n add(input: OptimisticLineInput, submit: () => void): string {\n const prev = current.current\n const id = cartOptimistic.add(input)\n if (prev && prev !== id) cartOptimistic.confirm(prev)\n current.current = id\n try {\n submit()\n } catch (e) {\n current.current = null\n cartOptimistic.rollback(id, describeAddFailure({ message: e instanceof Error ? e.message : undefined }))\n }\n return id\n },\n }\n}\n","import { useEffect, useId, type ElementType, type ReactNode } from 'react'\nimport { formatMoney, type Cart, type CartLine, type Money } from '@asteby/storefront'\nimport { useModalDialog } from '../dialog.js'\nimport { useResolvedLocale } from '../locale.js'\nimport { closeCartDrawer, isQuietOpen, useCartDrawer } from './store.js'\nimport { cartOptimistic, useOptimisticCart, type OptimisticNotice, type OptimisticRow } from './optimistic.js'\n\n/** Textos del estado optimista. Por omisión es-MX; la tienda puede traducirlos o cambiarlos. */\nexport type CartDrawerOptimisticLabels = {\n /** Estado discreto en la fila provisional. */\n adding: string\n /** Anuncio `aria-live=\"polite\"` al mostrar/confirmar la fila. */\n added: string\n /** Junto al subtotal mientras OPS no confirma. */\n calculating: string\n /** Aviso de error: «No pudimos agregar X: motivo». */\n failed: (title: string, reason: string) => string\n dismiss: string\n}\n\nexport const DEFAULT_OPTIMISTIC_LABELS: CartDrawerOptimisticLabels = {\n adding: 'Agregando…',\n added: 'Agregado al carrito',\n calculating: 'calculando…',\n failed: (title, reason) => `No pudimos agregar ${title}: ${reason}`,\n dismiss: 'Descartar aviso',\n}\n\nexport type CartDrawerLabels = {\n /** Título; el cajón agrega \" (N)\" con la cantidad de unidades. */\n title: string\n /** Texto accesible del botón de cierre. */\n close: string\n empty: string\n emptyHint?: string\n /** Texto del enlace \"seguir comprando\" del estado vacío (se muestra con `paths.browse`). */\n browse?: string\n subtotal: string\n /** Nota bajo el subtotal. */\n note?: string\n checkout: string\n viewCart: string\n remove: string\n increase: string\n decrease: string\n}\n\nexport type CartDrawerPaths = {\n /** Página del carrito: acción de las mutaciones y destino de \"ver carrito\". */\n cart: string\n checkout: string\n browse?: string\n /** Enlace de la línea al producto; sin esto el título no es enlace. */\n product?: (handle: string, variantId: string) => string\n}\n\n/** Contrato de la acción de ruta del carrito de la tienda (nombres de campo e intenciones). */\nexport type CartDrawerFormContract = {\n intentField?: string\n lineField?: string\n quantityField?: string\n updateIntent?: string\n removeIntent?: string\n}\n\nexport type CartDrawerShipping = {\n /** Mensaje ya calculado por la tienda con lo que manda OPS. */\n message: ReactNode\n /** 0..100 */\n percent: number\n reached?: boolean\n progressLabel: string\n}\n\nexport type CartDrawerLineForm = {\n /** Componente de formulario (`'form'`, o `fetcher.Form` del router para mejorar sin recargar). */\n Form: ElementType\n /** Datos en vuelo del formulario, para pintar la cantidad de forma optimista. */\n formData?: FormData | null | undefined\n}\n\nexport type CartDrawerLinkProps = { href: string; className?: string | undefined; children: ReactNode; onClick?: () => void }\n\nexport type CartDrawerSlot =\n | 'dialog' | 'panel' | 'header' | 'title' | 'close' | 'empty' | 'body' | 'shipping' | 'bar' | 'barFill' | 'lines' | 'line'\n | 'image' | 'lineTitle' | 'variant' | 'price' | 'qty' | 'qtyButton' | 'qtyValue' | 'remove' | 'upsell' | 'footer' | 'subtotal'\n | 'note' | 'actions' | 'checkout' | 'viewCart' | 'browse' | 'emptyTitle' | 'emptyHint' | 'shippingMessage' | 'lineMain'\n | 'notices' | 'lineHead' | 'lineText' | 'controls' | 'upsellTitle' | 'subtotalLabel' | 'subtotalValue'\n\nexport type CartDrawerIcons = { close?: ReactNode; decrease?: ReactNode; increase?: ReactNode; shipping?: ReactNode; shippingReached?: ReactNode }\n\nexport type CartDrawerProps = {\n /** `cart.cost` y cada línea vienen de OPS; el cajón no calcula nada. */\n cart: Cart | null | undefined\n labels: CartDrawerLabels\n paths: CartDrawerPaths\n form?: CartDrawerFormContract\n /** Hook que da el formulario de cada línea. Por omisión `<form method=\"post\">` (funciona sin JavaScript). */\n useLineForm?: () => CartDrawerLineForm\n shipping?: CartDrawerShipping | null\n /** Aviso fijo cuando no hay barra de envío (p. ej. \"Envío gratis\"). */\n notice?: ReactNode\n /** Sección \"podría interesarte\" (la tienda decide qué mostrar). */\n upsell?: ReactNode\n upsellTitle?: string\n renderLine?: (line: CartLine, defaults: { controls: ReactNode; price: ReactNode; image: ReactNode }) => ReactNode\n renderImage?: (line: CartLine) => ReactNode\n renderMoney?: (money: Money) => ReactNode\n renderLink?: (props: CartDrawerLinkProps) => ReactNode\n /** Omite el variante cuando es el valor por defecto de OPS (\"Default Title\"). */\n isDefaultVariantTitle?: (title: string) => boolean\n icons?: CartDrawerIcons\n /** Clases por pieza (además de los `data-sf-cart-*`), para tiendas con Tailwind. */\n classNames?: Partial<Record<CartDrawerSlot, string>>\n /** Textos de las filas provisionales y de los avisos (por omisión es-MX). */\n optimisticLabels?: Partial<CartDrawerOptimisticLabels>\n locale?: string\n /** Se llama al abrir/cerrar por cualquier vía. */\n onOpenChange?: (open: boolean) => void\n}\n\nconst DEFAULT_FORM: Required<CartDrawerFormContract> = {\n intentField: 'intent',\n lineField: 'line_id',\n quantityField: 'quantity',\n updateIntent: 'update',\n removeIntent: 'remove',\n}\n\nconst useNativeForm = (): CartDrawerLineForm => ({ Form: 'form' })\n\nconst defaultIsDefaultVariant = (t: string) => /^default title$/i.test(t.trim())\n\nfunction useBodyScrollLock(locked: boolean) {\n useEffect(() => {\n if (!locked || typeof document === 'undefined') return\n const el = document.documentElement\n const prev = el.style.overflow\n el.style.overflow = 'hidden'\n return () => {\n el.style.overflow = prev\n }\n }, [locked])\n}\n\n/**\n * Cajón lateral del carrito (\"Tu carrito (N)\"). Sin textos ni marca: todo llega por props.\n * Se monta una vez (en la raíz) y se abre con `openCartDrawer()` / `useCartDrawer()`.\n * `<dialog>` modal: `role=\"dialog\"`, `aria-modal`, foco atrapado y devuelto al abridor, Esc y clic fuera cierran,\n * el fondo no hace scroll. Las mutaciones usan la acción de ruta de la tienda (formularios nativos que\n * funcionan sin JavaScript, o el `Form` de un fetcher con `useLineForm`). Estilos: `@asteby/storefront-react/cart.css`\n * (tokens de la tienda) y/o `classNames`.\n */\nexport function CartDrawer(props: CartDrawerProps) {\n const { cart, labels, paths, shipping, notice, upsell, upsellTitle, icons, classNames: cx = {}, onOpenChange } = props\n const locale = useResolvedLocale(props.locale)\n const { open } = useCartDrawer()\n const opt = useOptimisticCart()\n const ol = { ...DEFAULT_OPTIMISTIC_LABELS, ...props.optimisticLabels }\n const quiet = open && isQuietOpen()\n const titleId = useId()\n const upsellId = useId()\n const { ref, onBackdropClick } = useModalDialog({ open, onClose: () => closeCartDrawer() })\n useBodyScrollLock(open)\n useEffect(() => {\n onOpenChange?.(open)\n }, [open]) // eslint-disable-line react-hooks/exhaustive-deps\n\n const realLines = cart?.lines.length ?? 0\n const rollbackEmpty = open && quiet && realLines === 0 && opt.rows.length === 0 && opt.notices.length > 0\n useEffect(() => {\n // Sin filas y con un aviso de fallo, un cajón vacío abierto por la acción sería engañoso: se cierra.\n if (rollbackEmpty) closeCartDrawer()\n }, [rollbackEmpty])\n\n if (!open) return opt.notices.length ? <OptimisticNotices notices={opt.notices} labels={ol} classNames={cx} /> : null\n\n const money = props.renderMoney ?? ((m: Money) => formatMoney(m, locale))\n const link = props.renderLink ?? (({ href, className, children, onClick }: CartDrawerLinkProps) => (\n <a href={href} className={className} onClick={onClick}>{children}</a>\n ))\n const pendingByVariant = new Map(opt.rows.map((r) => [r.variantId, r]))\n const count = (cart?.total_quantity ?? 0) + opt.quantity\n const lines = cart?.lines ?? []\n const extraRows = opt.rows.filter((r) => !lines.some((l) => l.merchandise.id === r.variantId))\n const pending = opt.rows.length > 0\n const empty = lines.length === 0 && extraRows.length === 0\n const close = () => closeCartDrawer()\n\n return (\n <dialog\n ref={ref}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n onClick={onBackdropClick}\n onClose={close}\n className={cx.dialog}\n data-sf-cart-drawer=\"\"\n >\n <div className={cx.panel} data-sf-cart-panel=\"\">\n <div className={cx.header} data-sf-cart-header=\"\">\n <h2 id={titleId} tabIndex={-1} className={cx.title} data-sf-cart-title=\"\">\n {labels.title}{count > 0 ? ` (${count})` : ''}\n </h2>\n <button type=\"button\" onClick={close} aria-label={labels.close} className={cx.close} data-sf-cart-close=\"\" data-sf-autofocus={quiet ? undefined : ''}>\n {icons?.close ?? <span aria-hidden=\"true\">✕</span>}\n </button>\n </div>\n\n <OptimisticNotices notices={opt.notices} labels={ol} classNames={cx} />\n <OptimisticStatus kind={opt.announcement.kind} n={opt.announcement.n} text={ol.added} />\n\n {empty ? (\n <div className={cx.empty} data-sf-cart-empty=\"\">\n <p className={cx.emptyTitle} data-sf-cart-empty-title=\"\">{labels.empty}</p>\n {labels.emptyHint ? <p className={cx.emptyHint} data-sf-cart-empty-hint=\"\">{labels.emptyHint}</p> : null}\n {paths.browse && labels.browse ? link({ href: paths.browse, className: cx.browse, children: labels.browse, onClick: close }) : null}\n </div>\n ) : (\n <>\n <div className={cx.body} data-sf-cart-body=\"\">\n {shipping ? (\n <div className={cx.shipping} data-sf-cart-shipping=\"\" data-reached={shipping.reached || undefined}>\n <p className={cx.shippingMessage}>\n {shipping.reached ? icons?.shippingReached : icons?.shipping}\n {shipping.message}\n </p>\n <div\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={Math.round(shipping.percent)}\n aria-label={shipping.progressLabel}\n className={cx.bar}\n data-sf-cart-bar=\"\"\n >\n <div className={cx.barFill} data-sf-cart-bar-fill=\"\" style={{ width: `${Math.max(0, Math.min(100, shipping.percent))}%` }} />\n </div>\n </div>\n ) : notice ? (\n <p className={[cx.shipping, cx.shippingMessage].filter(Boolean).join(\" \") || undefined} data-sf-cart-shipping=\"\" data-notice=\"\">{icons?.shippingReached}{notice}</p>\n ) : null}\n\n <ul className={cx.lines} data-sf-cart-lines=\"\">\n {lines.map((line) => (\n <DrawerLine key={line.id} line={line} props={props} money={money} link={link} close={close} pending={pendingByVariant.get(line.merchandise.id)} pendingLabel={ol.adding} />\n ))}\n {extraRows.map((row) => (\n <PendingLine key={`pending-${row.variantId}`} row={row} props={props} money={money} label={ol.adding} />\n ))}\n </ul>\n\n {upsell ? (\n <section className={cx.upsell} data-sf-cart-upsell=\"\" aria-labelledby={upsellTitle ? upsellId : undefined}>\n {upsellTitle ? <h3 id={upsellId} className={cx.upsellTitle}>{upsellTitle}</h3> : null}\n {upsell}\n </section>\n ) : null}\n </div>\n\n <div className={cx.footer} data-sf-cart-footer=\"\">\n <div className={cx.subtotal} data-sf-cart-subtotal=\"\" aria-busy={pending || undefined}>\n <span className={cx.subtotalLabel}>{labels.subtotal}</span>\n <span className={cx.subtotalValue} data-sf-cart-subtotal-value=\"\">{cart ? money(cart.cost.subtotal) : null}{pending ? <span data-sf-cart-calculating=\"\">{cart ? ' ' : ''}{ol.calculating}</span> : null}</span>\n </div>\n {labels.note ? <p className={cx.note} data-sf-cart-note=\"\">{labels.note}</p> : null}\n <div className={cx.actions} data-sf-cart-actions=\"\">\n {link({ href: paths.checkout, className: cx.checkout, children: labels.checkout, onClick: close })}\n {link({ href: paths.cart, className: cx.viewCart, children: labels.viewCart, onClick: close })}\n </div>\n </div>\n </>\n )}\n </div>\n </dialog>\n )\n}\n\nfunction DrawerLine({\n line,\n props,\n money,\n link,\n close,\n pending,\n pendingLabel,\n}: {\n pending?: OptimisticRow | undefined\n pendingLabel: string\n line: CartLine\n props: CartDrawerProps\n money: (m: Money) => ReactNode\n link: (p: CartDrawerLinkProps) => ReactNode\n close: () => void\n}) {\n const { labels, paths, icons, classNames: cx = {} } = props\n const f = { ...DEFAULT_FORM, ...props.form }\n const { Form, formData } = (props.useLineForm ?? useNativeForm)()\n const quantity = formData ? Number(formData.get(f.quantityField) ?? 0) : line.quantity + (pending?.quantity ?? 0)\n if (formData && (formData.get(f.intentField) === f.removeIntent || quantity === 0)) return null\n\n const merch = line.merchandise\n const isDefault = props.isDefaultVariantTitle ?? defaultIsDefaultVariant\n const title = merch.product.title\n const href = paths.product?.(merch.product.handle, merch.id)\n const img = merch.image ?? merch.product.featured_image\n const image = props.renderImage ? props.renderImage(line) : img ? (\n <img src={img.url} alt={img.alt ?? ''} width={80} height={80} loading=\"lazy\" decoding=\"async\" />\n ) : null\n\n const imageNode = <span className={cx.image} data-sf-cart-image=\"\">{image}</span>\n const price = <span className={cx.price} data-sf-cart-price=\"\">{money(line.cost.total)}</span>\n const controls = (\n <div className={cx.controls} data-sf-cart-controls=\"\">\n <Form method=\"post\" action={paths.cart} className={cx.qty} data-sf-cart-qty=\"\">\n <input type=\"hidden\" name={f.intentField} value={f.updateIntent} />\n <input type=\"hidden\" name={f.lineField} value={line.id} />\n <button type=\"submit\" name={f.quantityField} value={quantity - 1} aria-label={labels.decrease} className={cx.qtyButton} data-sf-cart-qty-button=\"\">\n {icons?.decrease ?? <span aria-hidden=\"true\">−</span>}\n </button>\n <span className={cx.qtyValue} aria-live=\"polite\" data-sf-cart-qty-value=\"\">{quantity}</span>\n <button type=\"submit\" name={f.quantityField} value={quantity + 1} aria-label={labels.increase} className={cx.qtyButton} data-sf-cart-qty-button=\"\">\n {icons?.increase ?? <span aria-hidden=\"true\">+</span>}\n </button>\n </Form>\n <Form method=\"post\" action={paths.cart} data-sf-cart-remove-form=\"\">\n <input type=\"hidden\" name={f.intentField} value={f.removeIntent} />\n <input type=\"hidden\" name={f.lineField} value={line.id} />\n <button type=\"submit\" className={cx.remove} data-sf-cart-remove=\"\">{labels.remove}</button>\n </Form>\n </div>\n )\n\n if (props.renderLine) return <li key={line.id} className={cx.line} data-sf-cart-line=\"\">{props.renderLine(line, { controls, price, image: imageNode })}</li>\n\n return (\n <li className={cx.line} data-sf-cart-line=\"\">\n {imageNode}\n <div className={cx.lineMain} data-sf-cart-line-main=\"\">\n <div className={cx.lineHead} data-sf-cart-line-head=\"\">\n <div className={cx.lineText} data-sf-cart-line-text=\"\">\n {href ? link({ href, className: cx.lineTitle, children: title, onClick: close }) : <span className={cx.lineTitle} data-sf-cart-line-title=\"\">{title}</span>}\n {!isDefault(merch.title) ? <p className={cx.variant} data-sf-cart-variant=\"\">{merch.title}</p> : null}\n </div>\n {price}\n </div>\n {controls}\n {pending ? <p className={cx.variant} data-sf-cart-pending-label=\"\">{pendingLabel}</p> : null}\n </div>\n </li>\n )\n}\n\n/** Fila que existe solo en el navegador hasta que OPS la confirma: sin controles, con el precio unitario mostrado. */\nfunction PendingLine({ row, props, money, label }: { row: OptimisticRow; props: CartDrawerProps; money: (m: Money) => ReactNode; label: string }) {\n const { classNames: cx = {} } = props\n const isDefault = props.isDefaultVariantTitle ?? defaultIsDefaultVariant\n return (\n <li className={cx.line} data-sf-cart-line=\"\" data-sf-cart-line-pending=\"\" aria-busy=\"true\">\n <span className={cx.image} data-sf-cart-image=\"\">\n {row.image ? <img src={row.image.url} alt={row.image.alt ?? ''} width={80} height={80} decoding=\"async\" /> : null}\n </span>\n <div className={cx.lineMain} data-sf-cart-line-main=\"\">\n <div className={cx.lineHead} data-sf-cart-line-head=\"\">\n <div className={cx.lineText} data-sf-cart-line-text=\"\">\n <span className={cx.lineTitle} data-sf-cart-line-title=\"\">{row.title}</span>\n {row.variantTitle && !isDefault(row.variantTitle) ? <p className={cx.variant} data-sf-cart-variant=\"\">{row.variantTitle}</p> : null}\n </div>\n {row.price ? <span className={cx.price} data-sf-cart-price=\"\">{money(row.price)}</span> : null}\n </div>\n <p className={cx.variant} data-sf-cart-pending-label=\"\">{label} · ×{row.quantity}</p>\n </div>\n </li>\n )\n}\n\n/** Región `aria-live=\"polite\"`: anuncia «Agregado al carrito». Alterna un espacio fino para repetir el mismo texto. */\nfunction OptimisticStatus({ kind, n, text }: { kind: 'added' | null; n: number; text: string }) {\n return (\n <div role=\"status\" aria-live=\"polite\" data-sf-cart-status=\"\" style={VISUALLY_HIDDEN}>\n {kind === 'added' ? `${text}${n % 2 ? '' : '\\u200B'}` : ''}\n </div>\n )\n}\n\nconst VISUALLY_HIDDEN = { position: 'absolute', width: 1, height: 1, margin: -1, padding: 0, overflow: 'hidden', clip: 'rect(0 0 0 0)', whiteSpace: 'nowrap', border: 0 } as const\n\n/** Avisos de fallo (`role=\"alert\"`, assertive), descartables. Se pintan dentro del cajón abierto o, si está cerrado, sueltos. */\nfunction OptimisticNotices({ notices, labels, classNames: cx }: { notices: readonly OptimisticNotice[]; labels: CartDrawerOptimisticLabels; classNames: Partial<Record<CartDrawerSlot, string>> }) {\n return (\n <div role=\"alert\" aria-live=\"assertive\" data-sf-cart-notices=\"\" className={cx.notices}>\n {notices.map((n) => (\n <p key={n.id} data-sf-cart-notice=\"\">\n <span>{labels.failed(n.title, n.reason)}</span>\n <button type=\"button\" onClick={() => cartOptimistic.dismissNotice(n.id)} aria-label={labels.dismiss} data-sf-cart-notice-dismiss=\"\">\n <span aria-hidden=\"true\">✕</span>\n </button>\n </p>\n ))}\n </div>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/dialog.tsx","../src/context.tsx","../src/locale.ts","../src/components.tsx","../src/ui/product-preview.tsx","../src/cart-drawer/store.ts","../src/cart-drawer/optimistic.ts","../src/cart-drawer/cart-drawer.tsx"],"names":["useRef","useEffect","useCallback","createContext","useContext","jsx","useState","jsxs","useSyncExternalStore","listeners","subscribe","useId","formatMoney","Fragment","notices"],"mappings":"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","file":"cart.cjs","sourcesContent":["import { useCallback, useEffect, useRef, type RefObject } from 'react'\n\nexport type DialogCloseReason = 'esc' | 'x' | 'backdrop' | 'action'\n\ntype UseModalDialogOptions = {\n open: boolean\n /** Called for Esc and backdrop clicks. The owner decides whether to close. */\n onClose: (reason: DialogCloseReason) => void\n /** Element focused when the dialog opens. Default: the element marked `data-sf-autofocus`, else the dialog itself. */\n initialFocus?: RefObject<HTMLElement | null>\n}\n\n/**\n * Native `<dialog>` wiring: `showModal()` (focus trap and inert background come from the browser),\n * Esc and backdrop clicks routed to `onClose`, and focus restored to the opener on close.\n * Falls back to the `open` attribute where `showModal` does not exist (old browsers, some test DOMs)\n * with an Esc key handler.\n */\nexport function useModalDialog({ open, onClose, initialFocus }: UseModalDialogOptions) {\n const ref = useRef<HTMLDialogElement | null>(null)\n const opener = useRef<Element | null>(null)\n const onCloseRef = useRef(onClose)\n onCloseRef.current = onClose\n\n useEffect(() => {\n const el = ref.current\n if (!el || !open) return\n opener.current = typeof document !== 'undefined' ? document.activeElement : null\n const hasModal = typeof el.showModal === 'function'\n if (!el.open) {\n if (hasModal) {\n try {\n el.showModal()\n } catch {\n el.setAttribute('open', '')\n }\n } else el.setAttribute('open', '')\n }\n const target = initialFocus?.current ?? el.querySelector<HTMLElement>('[data-sf-autofocus]') ?? el\n if (!target.hasAttribute('tabindex') && target === el) el.setAttribute('tabindex', '-1')\n target.focus({ preventScroll: true })\n\n const onCancel = (e: Event) => {\n e.preventDefault() // we close through state so the owner can navigate/track first\n onCloseRef.current('esc')\n }\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n onCloseRef.current('esc')\n }\n }\n el.addEventListener('cancel', onCancel)\n if (!hasModal) el.addEventListener('keydown', onKey)\n return () => {\n el.removeEventListener('cancel', onCancel)\n el.removeEventListener('keydown', onKey)\n if (el.open) {\n if (typeof el.close === 'function') {\n try {\n el.close()\n } catch {\n el.removeAttribute('open')\n }\n } else el.removeAttribute('open')\n }\n const back = opener.current\n if (back instanceof HTMLElement && back.isConnected) back.focus({ preventScroll: true })\n }\n }, [open])\n\n /** Click on the backdrop (the dialog element itself, outside its content box). */\n const onBackdropClick = useCallback((e: { target: EventTarget; currentTarget: EventTarget }) => {\n if (e.target === e.currentTarget) onCloseRef.current('backdrop')\n }, [])\n\n return { ref, onBackdropClick }\n}\n\n/** `prefers-reduced-motion: reduce`, read after hydration (false on the server). */\nexport function prefersReducedMotion(): boolean {\n try {\n return typeof window !== 'undefined' && !!window.matchMedia?.('(prefers-reduced-motion: reduce)').matches\n } catch {\n return false\n }\n}\n","import { createContext, useContext, useMemo, type ReactNode } from 'react'\nimport { createStorefrontClient, type Shop, type StorefrontClient, type StorefrontClientOptions } from '@asteby/storefront'\n\nexport type StorefrontContextValue = {\n /** Client for browser-side calls (use a public `pk_` token). */\n client: StorefrontClient | null\n shop: Shop | null\n /** BCP 47 locale used for formatting (defaults to `shop.locale`, then `es-MX`). */\n locale: string\n /** ISO 4217 currency (defaults to `shop.currency_code`, then `MXN`). */\n currency: string\n}\n\nconst StorefrontContext = createContext<StorefrontContextValue | null>(null)\n\nexport type StorefrontProviderProps = {\n /** A ready client. Takes precedence over `config`. */\n client?: StorefrontClient\n /** Options to create the browser client (use a `pk_` token). */\n config?: StorefrontClientOptions\n /** Shop info loaded on the server (root loader). */\n shop?: Shop | null\n locale?: string\n currency?: string\n children?: ReactNode\n}\n\n/**\n * Makes the storefront client, shop, locale and currency available to the\n * tree. SSR-safe: creating the client does not touch `window`.\n */\nexport function StorefrontProvider({ client, config, shop = null, locale, currency, children }: StorefrontProviderProps) {\n const configKey = config ? `${config.baseUrl}|${config.token}|${config.locale ?? ''}|${config.customerToken ?? ''}` : ''\n const resolvedClient = useMemo(\n () => client ?? (config ? createStorefrontClient(config) : null),\n [client, configKey],\n )\n const value = useMemo<StorefrontContextValue>(\n () => ({\n client: resolvedClient,\n shop,\n locale: locale ?? config?.locale ?? shop?.locale ?? 'es-MX',\n currency: currency ?? shop?.currency_code ?? 'MXN',\n }),\n [resolvedClient, shop, locale, currency, config?.locale],\n )\n return <StorefrontContext.Provider value={value}>{children}</StorefrontContext.Provider>\n}\n\n/** Storefront context. Throws outside `<StorefrontProvider>`. */\nexport function useStorefront(): StorefrontContextValue {\n const ctx = useContext(StorefrontContext)\n if (!ctx) throw new Error('useStorefront must be used inside <StorefrontProvider>')\n return ctx\n}\n\n/** Storefront context or `null` outside a provider (for components that work standalone). */\nexport function useOptionalStorefront(): StorefrontContextValue | null {\n return useContext(StorefrontContext)\n}\n\n/** The client from context; throws when the provider has none. */\nexport function useStorefrontClient(): StorefrontClient {\n const { client } = useStorefront()\n if (!client) throw new Error('<StorefrontProvider> needs a `client` or `config` for browser-side calls')\n return client\n}\n","import { useOptionalStorefront } from './context.js'\n\n/** Locale of a component: its own prop, else the `StorefrontProvider`'s, else `es-MX`. */\nexport function useResolvedLocale(locale?: string | null): string {\n const sf = useOptionalStorefront()\n return locale ?? sf?.locale ?? 'es-MX'\n}\n","import { createElement, type ComponentPropsWithoutRef, type ElementType, type ReactNode } from 'react'\nimport { formatMoney, parseMoney, type FormatMoneyOptions, type Image as ImageData, type Money as MoneyData, type Product, type ProductVariant } from '@asteby/storefront'\nimport { useOptionalStorefront } from './context.js'\n\n// ---------------------------------------------------------------------------\n// Money\n// ---------------------------------------------------------------------------\n\nexport type MoneyProps<As extends ElementType = 'span'> = FormatMoneyOptions & {\n data: MoneyData\n /** Element to render (default `span`). */\n as?: As\n /** Overrides the provider locale. */\n locale?: string\n} & Omit<ComponentPropsWithoutRef<As>, 'children' | 'as'>\n\n/** Formats `Money` with the provider locale (or `locale`). */\nexport function Money<As extends ElementType = 'span'>({\n data,\n as,\n locale,\n withoutTrailingZeros,\n withoutCurrency,\n currencyDisplay,\n ...rest\n}: MoneyProps<As>) {\n const sf = useOptionalStorefront()\n const text = formatMoney(data, locale ?? sf?.locale, {\n ...(withoutTrailingZeros !== undefined ? { withoutTrailingZeros } : {}),\n ...(withoutCurrency !== undefined ? { withoutCurrency } : {}),\n ...(currencyDisplay !== undefined ? { currencyDisplay } : {}),\n })\n return createElement(as ?? 'span', rest, text)\n}\n\n// ---------------------------------------------------------------------------\n// Image\n// ---------------------------------------------------------------------------\n\nexport const DEFAULT_IMAGE_WIDTHS = [320, 480, 640, 768, 1024, 1280, 1600] as const\n\n/** Builds the URL for one srcset width. */\nexport type ImageLoader = (src: string, width: number, height?: number) => string\n\n/**\n * Default loader: adds `?width=<w>` (the convention of most image CDNs and of\n * the OPS image proxy). URLs that cannot be parsed are returned unchanged.\n */\nexport const defaultImageLoader: ImageLoader = (src, width, height) => {\n try {\n const isAbsolute = /^[a-z][a-z0-9+.-]*:/i.test(src)\n const url = new URL(src, 'http://relative.invalid')\n url.searchParams.set('width', String(width))\n if (height) url.searchParams.set('height', String(height))\n return isAbsolute ? url.toString() : url.pathname + url.search + url.hash\n } catch {\n return src\n }\n}\n\nexport type ImageProps = Omit<ComponentPropsWithoutRef<'img'>, 'src' | 'srcSet' | 'width' | 'height'> & {\n data: ImageData\n /** `sizes` attribute (default `100vw`). */\n sizes?: string\n /** Candidate widths for `srcset` (capped at the intrinsic width when known). */\n widths?: readonly number[]\n /** URL builder per width (default adds `?width=`). Pass `null` to disable srcset. */\n loader?: ImageLoader | null\n /** Above-the-fold image: eager loading and `fetchpriority=\"high\"`. */\n priority?: boolean\n /** Forces an aspect ratio, e.g. `1/1` or `4/3`, used for width/height and srcset heights. */\n aspectRatio?: string\n}\n\nfunction parseRatio(ratio: string | undefined): number | null {\n if (!ratio) return null\n const [w, h] = ratio.split(/[/:]/).map((n) => Number.parseFloat(n))\n return w && h ? w / h : null\n}\n\n/** Responsive `<img>` with `srcset`, lazy by default, intrinsic size to avoid layout shift. */\nexport function Image({\n data,\n sizes = '100vw',\n widths = DEFAULT_IMAGE_WIDTHS,\n loader = defaultImageLoader,\n priority = false,\n aspectRatio,\n alt,\n loading,\n decoding,\n ...rest\n}: ImageProps) {\n const ratio = parseRatio(aspectRatio) ?? (data.width && data.height ? data.width / data.height : null)\n let candidates = [...widths].sort((a, b) => a - b)\n if (data.width) {\n const capped = candidates.filter((w) => w <= data.width!)\n candidates = capped.length ? capped : [data.width]\n }\n const srcSet = loader\n ? candidates.map((w) => `${loader(data.url, w, ratio ? Math.round(w / ratio) : undefined)} ${w}w`).join(', ')\n : undefined\n const width = data.width ?? candidates[candidates.length - 1]\n const height = data.height ?? (ratio && width ? Math.round(width / ratio) : undefined)\n return (\n <img\n src={data.url}\n alt={alt ?? data.alt ?? ''}\n {...(srcSet ? { srcSet, sizes } : {})}\n {...(width ? { width } : {})}\n {...(height ? { height } : {})}\n loading={loading ?? (priority ? 'eager' : 'lazy')}\n decoding={decoding ?? (priority ? 'auto' : 'async')}\n {...(priority ? { fetchPriority: 'high' as const } : {})}\n {...rest}\n />\n )\n}\n\n// ---------------------------------------------------------------------------\n// ProductPrice\n// ---------------------------------------------------------------------------\n\nconst VISUALLY_HIDDEN = {\n position: 'absolute',\n width: 1,\n height: 1,\n padding: 0,\n margin: -1,\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n border: 0,\n} as const\n\nexport type ProductPriceProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> & {\n product?: Pick<Product, 'price_range' | 'compare_at_price_range'> | null\n variant?: Pick<ProductVariant, 'price' | 'compare_at_price'> | null\n /** Prefix shown when the product has a price range and no variant is selected (default `Desde`). */\n fromLabel?: ReactNode\n /** Accessible label for the compare-at price (default `Precio anterior`). */\n compareAtLabel?: string\n locale?: string\n withoutTrailingZeros?: boolean\n}\n\n/**\n * Price with optional compare-at (strikethrough). With a `variant` it shows\n * that variant; otherwise the product's minimum price (prefixed with\n * `fromLabel` when prices vary).\n */\nexport function ProductPrice({\n product,\n variant,\n fromLabel = 'Desde',\n compareAtLabel = 'Precio anterior',\n locale,\n withoutTrailingZeros,\n ...rest\n}: ProductPriceProps) {\n let price: MoneyData | null = null\n let compareAt: MoneyData | null = null\n let isRange = false\n if (variant) {\n price = variant.price\n compareAt = variant.compare_at_price\n } else if (product) {\n price = product.price_range.min\n compareAt = product.compare_at_price_range?.min ?? null\n isRange = product.price_range.min.amount !== product.price_range.max.amount\n }\n if (!price) return null\n const onSale = compareAt !== null && parseMoney(compareAt) > parseMoney(price)\n const opts = { ...(locale ? { locale } : {}), ...(withoutTrailingZeros !== undefined ? { withoutTrailingZeros } : {}) }\n return (\n <div data-on-sale={onSale || undefined} {...rest}>\n {isRange ? <span data-price-prefix=\"\">{fromLabel} </span> : null}\n <Money data={price} data-price=\"\" {...opts} />\n {onSale && compareAt ? (\n <>\n {' '}\n <s data-compare-at-price=\"\">\n <span style={VISUALLY_HIDDEN}>{compareAtLabel}: </span>\n <Money data={compareAt} {...opts} />\n </s>\n </>\n ) : null}\n </div>\n )\n}\n","/**\n * Product preview of the storefront: ONE picture-plus-text pattern for every place a product is listed (cart drawer,\n * checkout summary, \"Mis pedidos\", order detail). Headless (`data-sf-preview*`, `classNames`), styled by\n * `product-preview.css` (plain CSS on the store tokens, dark mode included), SSR-safe.\n *\n * - `ProductThumb`: the picture alone. Fixed aspect ratio, `object-fit: contain` on a soft surface (parts photographed\n * on white are never cropped), responsive `srcset` through the shared `Image`, lazy by default, a shimmer while it\n * loads and an elegant fallback (initial of the name, or a package glyph) when there is no image, it is broken, or\n * the product no longer exists. Optional quantity badge.\n * - `ProductPreview`: thumb + name (2 lines) + variant + SKU + quantity x unit price, with the line total aligned right.\n * - `ProductThumbStack`: overlapped thumbs with a \"+N\" counter (order cards).\n */\nimport { useEffect, useRef, useState, type ReactNode } from 'react'\nimport type { Image as ImageData } from '@asteby/storefront'\nimport { Image, type ImageLoader } from '../components.js'\n\ntype ThumbState = 'loading' | 'loaded' | 'fallback'\n\n/** First letter(s) of the name for the fallback: two initials from two words, one otherwise. Empty when nothing usable. */\nexport function productInitials(name: string | null | undefined): string {\n const words = (name ?? '')\n .normalize('NFKC')\n .split(/[\\s\\-_/.,()]+/)\n .map((w) => Array.from(w).find((c) => /\\p{L}|\\p{N}/u.test(c)) ?? '')\n .filter(Boolean)\n if (words.length === 0) return ''\n return (words.length > 1 ? words[0]! + words[1]! : words[0]!).toLocaleUpperCase()\n}\n\nexport type ProductThumbClassNames = Partial<Record<'root' | 'img' | 'fallback' | 'badge', string>>\n\nexport type ProductThumbImage = { url: string; alt?: string | null; width?: number; height?: number }\n\nexport type ProductThumbProps = {\n /** Picture of the product or variant. `null`/missing: shows the fallback. */\n image?: ProductThumbImage | null\n /** Name of the product: alt of the picture (unless `decorative`) and source of the fallback initial. */\n name?: string | null\n /** Side in px. Default 56. */\n size?: number\n /** Aspect ratio of the box, `w/h`. Default `1/1`. */\n ratio?: string\n /** `contain` (default) never crops; `cover` fills the box. */\n fit?: 'contain' | 'cover'\n /** Quantity badge, shown when greater than 1. */\n quantity?: number\n /** The name sits next to it as text: the picture has `alt=\"\"` and the fallback is hidden from screen readers. Default false. */\n decorative?: boolean\n /** Slight zoom on hover (honours `prefers-reduced-motion`). Default true. */\n zoom?: boolean\n /** Above the fold: eager load. */\n priority?: boolean\n sizes?: string\n loader?: ImageLoader | null\n className?: string\n classNames?: ProductThumbClassNames\n}\n\n/** The picture of a product with fixed ratio, shimmer, lazy loading and a fallback that always looks designed. */\nexport function ProductThumb({\n image,\n name,\n size = 56,\n ratio = '1/1',\n fit = 'contain',\n quantity,\n decorative = false,\n zoom = true,\n priority = false,\n sizes,\n loader,\n className,\n classNames: cx = {},\n}: ProductThumbProps) {\n const url = image?.url || null\n const [state, setState] = useState<ThumbState>(url ? 'loading' : 'fallback')\n const box = useRef<HTMLSpanElement>(null)\n // A new picture (another variant) starts over; a missing one goes straight to the fallback.\n useEffect(() => {\n const img = box.current?.querySelector('img')\n // The browser may have loaded the picture before hydration: no `load` event will come.\n setState(!url ? 'fallback' : img?.complete ? (img.naturalWidth > 0 ? 'loaded' : 'fallback') : 'loading')\n }, [url])\n\n const label = name?.trim() || ''\n const initials = productInitials(label)\n const showBadge = typeof quantity === 'number' && quantity > 1\n const a11y = state === 'fallback' && !decorative && label ? { role: 'img', 'aria-label': label } : { 'aria-hidden': decorative || state === 'fallback' ? true : undefined }\n return (\n <span\n ref={box}\n className={[cx.root, className].filter(Boolean).join(' ') || undefined}\n style={{ ['--sf-preview-size' as string]: `${size}px`, ['--sf-preview-ratio' as string]: ratio.replace(':', '/') }}\n data-sf-thumb=\"\"\n data-state={state}\n data-fit={fit}\n data-zoom={zoom || undefined}\n {...a11y}\n >\n {url && state !== 'fallback' ? (\n <Image\n data={{ url, alt: image?.alt ?? null, ...(image?.width ? { width: image.width } : {}), ...(image?.height ? { height: image.height } : {}) }}\n alt={decorative ? '' : (image?.alt ?? label)}\n aspectRatio={ratio}\n sizes={sizes ?? `${size * 2}px`}\n widths={[Math.round(size), Math.round(size * 2), Math.round(size * 3)]}\n {...(loader !== undefined ? { loader } : {})}\n priority={priority}\n className={cx.img}\n onLoad={() => setState('loaded')}\n onError={() => setState('fallback')}\n />\n ) : null}\n {state === 'fallback' ? (\n <span className={cx.fallback} data-sf-thumb-fallback=\"\" aria-hidden=\"true\">\n {initials ? <span data-sf-thumb-initial=\"\">{initials}</span> : <PackageGlyph />}\n </span>\n ) : null}\n {showBadge ? (\n <span className={cx.badge} data-sf-thumb-qty=\"\" aria-hidden=\"true\">\n {quantity}\n </span>\n ) : null}\n </span>\n )\n}\n\nfunction PackageGlyph() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"45%\" height=\"45%\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" focusable=\"false\">\n <path d=\"M21 8 12 3 3 8v8l9 5 9-5V8Z\" />\n <path d=\"m3 8 9 5 9-5M12 13v8\" />\n </svg>\n )\n}\n\nexport type ProductPreviewClassNames = Partial<Record<'root' | 'media' | 'body' | 'name' | 'variant' | 'meta' | 'sku' | 'qty' | 'price' | 'total' | 'unit', string>> & { thumb?: ProductThumbClassNames }\n\nexport type ProductPreviewProps = Pick<ProductThumbProps, 'image' | 'size' | 'ratio' | 'fit' | 'zoom' | 'priority' | 'sizes' | 'loader'> & {\n name: string\n /** \"Rojo / L\". Omit for default variants. */\n variant?: string | null\n sku?: string | null\n /** Quantity: a badge on the picture (> 1) and \"Cantidad N\" under the name. */\n quantity?: number\n /** Unit price, already formatted. Shown next to the quantity when it is greater than 1. */\n unitPrice?: ReactNode\n /** Line total, already formatted: aligned right, the strongest number. */\n total?: ReactNode\n /** Link on the name (product page). */\n href?: string | null\n /** Rendered under the text (status, note, actions). */\n children?: ReactNode\n /** Text of the quantity for screen readers and the meta line. Default `Cantidad {n}`. */\n quantityLabel?: string\n /** Name shown when the line has none (product deleted). Default `Producto no disponible`. */\n unavailableLabel?: string\n className?: string\n classNames?: ProductPreviewClassNames\n}\n\n/**\n * A product line: picture, name (2 lines), variant, SKU, quantity and prices with a clear hierarchy. Degrades to a\n * designed placeholder when the product has no image or no longer exists (empty name).\n */\nexport function ProductPreview({\n image,\n name,\n variant,\n sku,\n quantity,\n unitPrice,\n total,\n href,\n children,\n size = 64,\n ratio,\n fit,\n zoom,\n priority,\n sizes,\n loader,\n quantityLabel,\n unavailableLabel = 'Producto no disponible',\n className,\n classNames: cx = {},\n}: ProductPreviewProps) {\n const missing = !name.trim()\n const title = missing ? unavailableLabel : name\n const hasQty = typeof quantity === 'number' && Number.isFinite(quantity)\n return (\n <div className={[cx.root, className].filter(Boolean).join(' ') || undefined} data-sf-preview=\"\" data-missing={missing || undefined}>\n <span className={cx.media} data-sf-preview-media=\"\">\n <ProductThumb\n image={image}\n name={missing ? null : name}\n size={size}\n decorative\n {...(ratio ? { ratio } : {})}\n {...(fit ? { fit } : {})}\n {...(zoom !== undefined ? { zoom } : {})}\n {...(priority ? { priority } : {})}\n {...(sizes ? { sizes } : {})}\n {...(loader !== undefined ? { loader } : {})}\n {...(hasQty ? { quantity: quantity! } : {})}\n {...(cx.thumb ? { classNames: cx.thumb } : {})}\n />\n </span>\n <span className={cx.body} data-sf-preview-body=\"\">\n <span className={cx.name} data-sf-preview-name=\"\">\n {href && !missing ? <a href={href}>{title}</a> : title}\n </span>\n {variant ? (\n <span className={cx.variant} data-sf-preview-variant=\"\">\n {variant}\n </span>\n ) : null}\n {sku ? (\n <span className={cx.sku} data-sf-preview-sku=\"\">\n SKU {sku}\n </span>\n ) : null}\n {hasQty ? (\n <span className={cx.meta} data-sf-preview-meta=\"\">\n <span className={cx.qty} data-sf-preview-qty=\"\">\n {(quantityLabel ?? 'Cantidad {n}').replace('{n}', String(quantity))}\n </span>\n {unitPrice != null && quantity! > 1 ? (\n <span className={cx.unit} data-sf-preview-unit=\"\">\n {' · '}\n {unitPrice}\n </span>\n ) : null}\n </span>\n ) : null}\n {children}\n </span>\n {total != null ? (\n <span className={cx.total} data-sf-preview-total=\"\">\n {total}\n </span>\n ) : unitPrice != null && !(hasQty && quantity! > 1) ? (\n <span className={cx.price} data-sf-preview-total=\"\">\n {unitPrice}\n </span>\n ) : null}\n </div>\n )\n}\n\nexport type ProductThumbStackProps = {\n items: ReadonlyArray<{ image?: ProductThumbImage | null; name?: string | null }>\n /** Thumbs shown before \"+N\". Default 4. */\n max?: number\n size?: number\n /** Screen reader text for the hidden remainder, `{n}` = how many. Default `y {n} más`. */\n moreLabel?: string\n className?: string\n}\n\n/** Overlapped thumbs with a \"+N\" counter: the products of an order at a glance. */\nexport function ProductThumbStack({ items, max = 4, size = 44, moreLabel = 'y {n} más', className }: ProductThumbStackProps) {\n if (items.length === 0) return null\n const shown = items.length > max ? items.slice(0, max - 1) : items\n const rest = items.length - shown.length\n return (\n <span className={className} data-sf-thumb-stack=\"\" style={{ ['--sf-preview-size' as string]: `${size}px` }}>\n {shown.map((it, i) => (\n <ProductThumb key={i} image={it.image ?? null} name={it.name ?? null} size={size} zoom={false} />\n ))}\n {rest > 0 ? (\n <span data-sf-thumb-more=\"\" role=\"img\" aria-label={moreLabel.replace('{n}', String(rest))}>\n +{rest}\n </span>\n ) : null}\n </span>\n )\n}\n","import { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\n\n// Estado mínimo del cajón del carrito, fuera de React: cualquier parte de la tienda (cabecera, tarjeta, ficha)\n// lo abre sin pasar props. Es del navegador; en el servidor siempre está cerrado.\n\nlet isOpen = false\nconst listeners = new Set<() => void>()\n\nlet quietOpen = false\n\n/** Marca que el cajón lo abrió una acción optimista (la apertura no mueve el foco al botón de cierre). */\nexport function setQuietOpen(next: boolean) {\n quietOpen = next\n}\n\nexport function isQuietOpen() {\n return quietOpen\n}\n\nfunction set(next: boolean) {\n if (isOpen === next) return\n isOpen = next\n if (!next) quietOpen = false\n for (const l of [...listeners]) l()\n}\n\nconst subscribe = (l: () => void) => {\n listeners.add(l)\n return () => {\n listeners.delete(l)\n }\n}\n\n/** Abre el cajón del carrito desde cualquier parte. */\nexport function openCartDrawer() {\n set(true)\n}\n\n/** Cierra el cajón del carrito. */\nexport function closeCartDrawer() {\n set(false)\n}\n\nexport function toggleCartDrawer() {\n set(!isOpen)\n}\n\nexport function isCartDrawerOpen() {\n return isOpen\n}\n\n/** Estado y acciones del cajón. `open` es `false` en el servidor y en la primera pintura. */\nexport function useCartDrawer() {\n const open = useSyncExternalStore(subscribe, () => isOpen, () => false)\n const toggle = useCallback(() => toggleCartDrawer(), [])\n return { open, openDrawer: openCartDrawer, closeDrawer: closeCartDrawer, toggle }\n}\n\n/**\n * Abre el cajón cuando termina un \"agregar al carrito\". `busy` es verdadero mientras hay un agregado en vuelo\n * (en React Router: algún fetcher con la acción del carrito e intención de agregar). Con `skip` verdadero al\n * terminar (error, agregado silencioso) no se abre.\n */\nexport function useOpenCartDrawerWhenDone(busy: boolean, options: { skip?: boolean } = {}) {\n const was = useRef(false)\n const skip = useRef(false)\n skip.current = !!options.skip\n useEffect(() => {\n if (was.current && !busy && !skip.current) openCartDrawer()\n was.current = busy\n }, [busy])\n}\n\ntype ClickLike = {\n defaultPrevented: boolean\n button: number\n metaKey: boolean\n ctrlKey: boolean\n shiftKey: boolean\n altKey: boolean\n preventDefault: () => void\n}\n\n/**\n * `onClick` para el enlace \"Mi carrito\" de la cabecera: con un clic normal abre el cajón; con clic con\n * modificador, clic central o sin JavaScript el `href` (la página del carrito) sigue funcionando.\n */\nexport function handleCartLinkClick(e: ClickLike) {\n if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return\n e.preventDefault()\n openCartDrawer()\n}\n","import { useEffect, useRef, useSyncExternalStore } from 'react'\nimport type { Money } from '@asteby/storefront'\nimport { openCartDrawer, setQuietOpen } from './store.js'\n\n// Estado optimista del cajón del carrito. Solo guarda FILAS provisionales (producto, imagen, título, precio mostrado\n// y cantidad) mientras OPS responde. Nunca calcula dinero: precios, totales, impuestos y envío los dicta OPS cuando\n// llega el carrito real. Vive fuera de React, como el estado de apertura del cajón.\n\n/** Lo que la tienda sabe del producto al pulsar «Agregar». `price` es el precio unitario ya mostrado en la ficha. */\nexport type OptimisticLineInput = {\n /** Variante agregada; dos acciones con la misma variante comparten una sola fila. */\n variantId: string\n title: string\n variantTitle?: string | null | undefined\n productHandle?: string | undefined\n image?: { url: string; alt?: string | null | undefined } | null | undefined\n /** Precio unitario mostrado (solo se pinta, no se multiplica ni se suma). */\n price?: Money | null | undefined\n /** Unidades de ESTA acción (por omisión 1). */\n quantity?: number | undefined\n /** Clave de idempotencia: repetir `add` con una clave viva devuelve la misma acción sin sumar otra vez. */\n key?: string | undefined\n}\n\nexport type OptimisticAction = Required<Pick<OptimisticLineInput, 'variantId' | 'title'>> &\n Omit<OptimisticLineInput, 'quantity' | 'key'> & { id: string; quantity: number; key?: string | undefined }\n\n/** Fila provisional: todas las acciones en vuelo de una misma variante. */\nexport type OptimisticRow = {\n variantId: string\n title: string\n variantTitle?: string | null | undefined\n productHandle?: string | undefined\n image?: { url: string; alt?: string | null | undefined } | null | undefined\n price?: Money | null | undefined\n /** Unidades agregadas que OPS aún no confirma. */\n quantity: number\n actionIds: string[]\n}\n\nexport type OptimisticNotice = { id: string; title: string; reason: string }\n\nexport type OptimisticSnapshot = {\n rows: readonly OptimisticRow[]\n /** Unidades provisionales en total (para el contador). */\n quantity: number\n notices: readonly OptimisticNotice[]\n /** Último evento a anunciar en la región `aria-live=\"polite\"`; `n` cambia en cada evento. */\n announcement: { kind: 'added' | null; n: number }\n}\n\nexport type AddOutcome = { ok: true } | { ok: false; reason: string }\n\nconst DEFAULT_TIMEOUT_MS = 30_000\n\nlet actions: OptimisticAction[] = []\nlet notices: OptimisticNotice[] = []\nlet announcement: OptimisticSnapshot['announcement'] = { kind: null, n: 0 }\nlet seq = 0\nconst timers = new Map<string, ReturnType<typeof setTimeout>>()\nconst listeners = new Set<() => void>()\nlet snapshot: OptimisticSnapshot = compute()\n\nfunction compute(): OptimisticSnapshot {\n const byVariant = new Map<string, OptimisticRow>()\n for (const a of actions) {\n const row = byVariant.get(a.variantId)\n if (row) {\n row.quantity += a.quantity\n row.actionIds.push(a.id)\n } else {\n byVariant.set(a.variantId, {\n variantId: a.variantId, title: a.title, variantTitle: a.variantTitle, productHandle: a.productHandle,\n image: a.image, price: a.price, quantity: a.quantity, actionIds: [a.id],\n })\n }\n }\n const rows = [...byVariant.values()]\n return { rows, quantity: rows.reduce((n, r) => n + r.quantity, 0), notices, announcement }\n}\n\nfunction emit() {\n snapshot = compute()\n for (const l of [...listeners]) l()\n}\n\nconst subscribe = (l: () => void) => {\n listeners.add(l)\n return () => {\n listeners.delete(l)\n }\n}\nconst EMPTY: OptimisticSnapshot = { rows: [], quantity: 0, notices: [], announcement: { kind: null, n: 0 } }\n\nfunction drop(id: string): OptimisticAction | undefined {\n const a = actions.find((x) => x.id === id)\n if (!a) return undefined\n actions = actions.filter((x) => x.id !== id)\n const t = timers.get(id)\n if (t) clearTimeout(t)\n timers.delete(id)\n return a\n}\n\nfunction announce() {\n announcement = { kind: 'added', n: announcement.n + 1 }\n}\n\nexport const cartOptimistic = {\n /**\n * Inserta YA la fila provisional, sube el contador y abre el cajón sin robar el foco. Devuelve el id de la acción\n * para `confirm` / `rollback`. Una acción por clic: la misma variante suma cantidad en una sola fila.\n */\n add(input: OptimisticLineInput, options: { open?: boolean; timeoutMs?: number } = {}): string {\n if (input.key) {\n const live = actions.find((a) => a.key === input.key)\n if (live) return live.id\n }\n const id = `opt-${++seq}`\n const quantity = Math.max(1, Math.floor(input.quantity ?? 1))\n actions = [...actions, { ...input, id, quantity }]\n const ms = options.timeoutMs ?? DEFAULT_TIMEOUT_MS\n if (ms > 0 && typeof setTimeout === 'function') {\n timers.set(id, setTimeout(() => cartOptimistic.rollback(id, describeAddFailure({ code: 'timeout' })), ms))\n }\n announce()\n if (options.open !== false) {\n setQuietOpen(true)\n openCartDrawer()\n }\n emit()\n return id\n },\n\n /** OPS confirmó: la fila provisional sale y el carrito real (ya en `cart`) ocupa su lugar. */\n confirm(id: string) {\n if (!drop(id)) return\n announce()\n emit()\n },\n\n /** Falló: se quita la acción (y su cantidad) y se avisa «No pudimos agregar X: motivo». */\n rollback(id: string, reason = 'unknown') {\n const a = drop(id)\n if (!a) return\n notices = [...notices, { id: `n-${++seq}`, title: a.title, reason }]\n emit()\n },\n\n /** Quita la acción sin avisar (el componente que la lanzó se desmontó). */\n discard(id: string) {\n if (drop(id)) emit()\n },\n\n dismissNotice(id: string) {\n notices = notices.filter((n) => n.id !== id)\n emit()\n },\n\n /** Limpia todo (pruebas, cierre de sesión). */\n reset() {\n for (const t of timers.values()) clearTimeout(t)\n timers.clear()\n actions = []\n notices = []\n announcement = { kind: null, n: 0 }\n setQuietOpen(false)\n emit()\n },\n\n getSnapshot: (): OptimisticSnapshot => snapshot,\n}\n\n/** Estado optimista (filas, contador, avisos). En el servidor siempre vacío. */\nexport function useOptimisticCart(): OptimisticSnapshot {\n return useSyncExternalStore(subscribe, () => snapshot, () => EMPTY)\n}\n\n/** Contador para la cabecera: unidades del carrito de OPS más las que están en vuelo. */\nexport function useOptimisticCartCount(base: number): number {\n return base + useOptimisticCart().quantity\n}\n\n/** Motivo corto en es-MX a partir de un error de la acción (HTTP, código de OPS o red). */\nexport function describeAddFailure(error: { status?: number | undefined; code?: string | undefined; message?: string | undefined } | null | undefined): string {\n const code = error?.code\n const status = error?.status\n if (code === 'store_not_ready') return 'la tienda está cerrada por ahora'\n if (code === 'timeout') return 'tardó demasiado, intenta de nuevo'\n if (status === 409 || code === 'out_of_stock' || code === 'insufficient_stock') return 'sin existencias suficientes'\n if (status === 0 || code === 'network' || (!status && !code)) return 'revisa tu conexión'\n if (status && status >= 500) return 'hubo un problema, intenta de nuevo'\n if (status === 404) return 'el producto ya no está disponible'\n return error?.message?.trim() || 'intenta de nuevo'\n}\n\ntype FetcherLike = { state: string; data?: unknown }\n\n/** Interpreta `fetcher.data` de la acción de ruta: `{ error }`, `{ success:false }`, `{ ok:false }` o `status >= 400` fallan. */\nexport function defaultAddOutcome(data: unknown): AddOutcome {\n if (!data || typeof data !== 'object') return { ok: true }\n const d = data as Record<string, unknown>\n const status = typeof d.status === 'number' ? d.status : undefined\n const err = (d.error && typeof d.error === 'object' ? d.error : d) as Record<string, unknown>\n const code = typeof err.code === 'string' ? err.code : undefined\n const failed = d.error != null || d.ok === false || d.success === false || (status !== undefined && status >= 400)\n if (!failed) return { ok: true }\n return { ok: false, reason: describeAddFailure({ status: status ?? (typeof err.status === 'number' ? err.status : undefined), code, message: typeof err.message === 'string' ? err.message : undefined }) }\n}\n\n/**\n * Conecta un `useFetcher()` de React Router con el estado optimista. `add(input, submit)` inserta la fila, abre el\n * cajón y llama a `submit()` (el `fetcher.submit(...)` de la tienda); al terminar el fetcher confirma o revierte.\n * Un nuevo `add` con el mismo fetcher antes de terminar da por entregado el anterior (el router lo reemplaza y el\n * carrito real que llega con la revalidación manda). Si el componente se desmonta, las filas se descartan sin aviso.\n */\nexport function useOptimisticAdd(fetcher: FetcherLike, options: { settle?: (data: unknown) => AddOutcome } = {}) {\n const current = useRef<string | null>(null)\n const was = useRef(false)\n const settleRef = useRef(options.settle)\n settleRef.current = options.settle\n\n useEffect(() => {\n const busy = fetcher.state !== 'idle'\n const id = current.current\n if (was.current && !busy && id) {\n current.current = null\n const out = (settleRef.current ?? defaultAddOutcome)(fetcher.data)\n if (out.ok) cartOptimistic.confirm(id)\n else cartOptimistic.rollback(id, out.reason)\n }\n was.current = busy\n }, [fetcher.state, fetcher.data])\n\n useEffect(\n () => () => {\n if (current.current) cartOptimistic.discard(current.current)\n current.current = null\n },\n [],\n )\n\n return {\n add(input: OptimisticLineInput, submit: () => void): string {\n const prev = current.current\n const id = cartOptimistic.add(input)\n if (prev && prev !== id) cartOptimistic.confirm(prev)\n current.current = id\n try {\n submit()\n } catch (e) {\n current.current = null\n cartOptimistic.rollback(id, describeAddFailure({ message: e instanceof Error ? e.message : undefined }))\n }\n return id\n },\n }\n}\n","import { useEffect, useId, type ElementType, type ReactNode } from 'react'\nimport { formatMoney, type Cart, type CartLine, type Money } from '@asteby/storefront'\nimport { useModalDialog } from '../dialog.js'\nimport { useResolvedLocale } from '../locale.js'\nimport { ProductThumb } from '../ui/product-preview.js'\nimport { closeCartDrawer, isQuietOpen, useCartDrawer } from './store.js'\nimport { cartOptimistic, useOptimisticCart, type OptimisticNotice, type OptimisticRow } from './optimistic.js'\n\n/** Textos del estado optimista. Por omisión es-MX; la tienda puede traducirlos o cambiarlos. */\nexport type CartDrawerOptimisticLabels = {\n /** Estado discreto en la fila provisional. */\n adding: string\n /** Anuncio `aria-live=\"polite\"` al mostrar/confirmar la fila. */\n added: string\n /** Junto al subtotal mientras OPS no confirma. */\n calculating: string\n /** Aviso de error: «No pudimos agregar X: motivo». */\n failed: (title: string, reason: string) => string\n dismiss: string\n}\n\nexport const DEFAULT_OPTIMISTIC_LABELS: CartDrawerOptimisticLabels = {\n adding: 'Agregando…',\n added: 'Agregado al carrito',\n calculating: 'calculando…',\n failed: (title, reason) => `No pudimos agregar ${title}: ${reason}`,\n dismiss: 'Descartar aviso',\n}\n\nexport type CartDrawerLabels = {\n /** Título; el cajón agrega \" (N)\" con la cantidad de unidades. */\n title: string\n /** Texto accesible del botón de cierre. */\n close: string\n empty: string\n emptyHint?: string\n /** Texto del enlace \"seguir comprando\" del estado vacío (se muestra con `paths.browse`). */\n browse?: string\n subtotal: string\n /** Nota bajo el subtotal. */\n note?: string\n checkout: string\n viewCart: string\n remove: string\n increase: string\n decrease: string\n}\n\nexport type CartDrawerPaths = {\n /** Página del carrito: acción de las mutaciones y destino de \"ver carrito\". */\n cart: string\n checkout: string\n browse?: string\n /** Enlace de la línea al producto; sin esto el título no es enlace. */\n product?: (handle: string, variantId: string) => string\n}\n\n/** Contrato de la acción de ruta del carrito de la tienda (nombres de campo e intenciones). */\nexport type CartDrawerFormContract = {\n intentField?: string\n lineField?: string\n quantityField?: string\n updateIntent?: string\n removeIntent?: string\n}\n\nexport type CartDrawerShipping = {\n /** Mensaje ya calculado por la tienda con lo que manda OPS. */\n message: ReactNode\n /** 0..100 */\n percent: number\n reached?: boolean\n progressLabel: string\n}\n\nexport type CartDrawerLineForm = {\n /** Componente de formulario (`'form'`, o `fetcher.Form` del router para mejorar sin recargar). */\n Form: ElementType\n /** Datos en vuelo del formulario, para pintar la cantidad de forma optimista. */\n formData?: FormData | null | undefined\n}\n\nexport type CartDrawerLinkProps = { href: string; className?: string | undefined; children: ReactNode; onClick?: () => void }\n\nexport type CartDrawerSlot =\n | 'dialog' | 'panel' | 'header' | 'title' | 'close' | 'empty' | 'body' | 'shipping' | 'bar' | 'barFill' | 'lines' | 'line'\n | 'image' | 'lineTitle' | 'variant' | 'price' | 'qty' | 'qtyButton' | 'qtyValue' | 'remove' | 'upsell' | 'footer' | 'subtotal'\n | 'note' | 'actions' | 'checkout' | 'viewCart' | 'browse' | 'emptyTitle' | 'emptyHint' | 'shippingMessage' | 'lineMain'\n | 'notices' | 'lineHead' | 'lineText' | 'controls' | 'upsellTitle' | 'subtotalLabel' | 'subtotalValue'\n\nexport type CartDrawerIcons = { close?: ReactNode; decrease?: ReactNode; increase?: ReactNode; shipping?: ReactNode; shippingReached?: ReactNode }\n\nexport type CartDrawerProps = {\n /** `cart.cost` y cada línea vienen de OPS; el cajón no calcula nada. */\n cart: Cart | null | undefined\n labels: CartDrawerLabels\n paths: CartDrawerPaths\n form?: CartDrawerFormContract\n /** Hook que da el formulario de cada línea. Por omisión `<form method=\"post\">` (funciona sin JavaScript). */\n useLineForm?: () => CartDrawerLineForm\n shipping?: CartDrawerShipping | null\n /** Aviso fijo cuando no hay barra de envío (p. ej. \"Envío gratis\"). */\n notice?: ReactNode\n /** Sección \"podría interesarte\" (la tienda decide qué mostrar). */\n upsell?: ReactNode\n upsellTitle?: string\n renderLine?: (line: CartLine, defaults: { controls: ReactNode; price: ReactNode; image: ReactNode }) => ReactNode\n renderImage?: (line: CartLine) => ReactNode\n renderMoney?: (money: Money) => ReactNode\n renderLink?: (props: CartDrawerLinkProps) => ReactNode\n /** Omite el variante cuando es el valor por defecto de OPS (\"Default Title\"). */\n isDefaultVariantTitle?: (title: string) => boolean\n icons?: CartDrawerIcons\n /** Clases por pieza (además de los `data-sf-cart-*`), para tiendas con Tailwind. */\n classNames?: Partial<Record<CartDrawerSlot, string>>\n /** Textos de las filas provisionales y de los avisos (por omisión es-MX). */\n optimisticLabels?: Partial<CartDrawerOptimisticLabels>\n locale?: string\n /** Se llama al abrir/cerrar por cualquier vía. */\n onOpenChange?: (open: boolean) => void\n}\n\nconst DEFAULT_FORM: Required<CartDrawerFormContract> = {\n intentField: 'intent',\n lineField: 'line_id',\n quantityField: 'quantity',\n updateIntent: 'update',\n removeIntent: 'remove',\n}\n\nconst useNativeForm = (): CartDrawerLineForm => ({ Form: 'form' })\n\nconst defaultIsDefaultVariant = (t: string) => /^default title$/i.test(t.trim())\n\nfunction useBodyScrollLock(locked: boolean) {\n useEffect(() => {\n if (!locked || typeof document === 'undefined') return\n const el = document.documentElement\n const prev = el.style.overflow\n el.style.overflow = 'hidden'\n return () => {\n el.style.overflow = prev\n }\n }, [locked])\n}\n\n/**\n * Cajón lateral del carrito (\"Tu carrito (N)\"). Sin textos ni marca: todo llega por props.\n * Se monta una vez (en la raíz) y se abre con `openCartDrawer()` / `useCartDrawer()`.\n * `<dialog>` modal: `role=\"dialog\"`, `aria-modal`, foco atrapado y devuelto al abridor, Esc y clic fuera cierran,\n * el fondo no hace scroll. Las mutaciones usan la acción de ruta de la tienda (formularios nativos que\n * funcionan sin JavaScript, o el `Form` de un fetcher con `useLineForm`). Estilos: `@asteby/storefront-react/cart.css`\n * (tokens de la tienda) y/o `classNames`.\n */\nexport function CartDrawer(props: CartDrawerProps) {\n const { cart, labels, paths, shipping, notice, upsell, upsellTitle, icons, classNames: cx = {}, onOpenChange } = props\n const locale = useResolvedLocale(props.locale)\n const { open } = useCartDrawer()\n const opt = useOptimisticCart()\n const ol = { ...DEFAULT_OPTIMISTIC_LABELS, ...props.optimisticLabels }\n const quiet = open && isQuietOpen()\n const titleId = useId()\n const upsellId = useId()\n const { ref, onBackdropClick } = useModalDialog({ open, onClose: () => closeCartDrawer() })\n useBodyScrollLock(open)\n useEffect(() => {\n onOpenChange?.(open)\n }, [open]) // eslint-disable-line react-hooks/exhaustive-deps\n\n const realLines = cart?.lines.length ?? 0\n const rollbackEmpty = open && quiet && realLines === 0 && opt.rows.length === 0 && opt.notices.length > 0\n useEffect(() => {\n // Sin filas y con un aviso de fallo, un cajón vacío abierto por la acción sería engañoso: se cierra.\n if (rollbackEmpty) closeCartDrawer()\n }, [rollbackEmpty])\n\n if (!open) return opt.notices.length ? <OptimisticNotices notices={opt.notices} labels={ol} classNames={cx} /> : null\n\n const money = props.renderMoney ?? ((m: Money) => formatMoney(m, locale))\n const link = props.renderLink ?? (({ href, className, children, onClick }: CartDrawerLinkProps) => (\n <a href={href} className={className} onClick={onClick}>{children}</a>\n ))\n const pendingByVariant = new Map(opt.rows.map((r) => [r.variantId, r]))\n const count = (cart?.total_quantity ?? 0) + opt.quantity\n const lines = cart?.lines ?? []\n const extraRows = opt.rows.filter((r) => !lines.some((l) => l.merchandise.id === r.variantId))\n const pending = opt.rows.length > 0\n const empty = lines.length === 0 && extraRows.length === 0\n const close = () => closeCartDrawer()\n\n return (\n <dialog\n ref={ref}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n onClick={onBackdropClick}\n onClose={close}\n className={cx.dialog}\n data-sf-cart-drawer=\"\"\n >\n <div className={cx.panel} data-sf-cart-panel=\"\">\n <div className={cx.header} data-sf-cart-header=\"\">\n <h2 id={titleId} tabIndex={-1} className={cx.title} data-sf-cart-title=\"\">\n {labels.title}{count > 0 ? ` (${count})` : ''}\n </h2>\n <button type=\"button\" onClick={close} aria-label={labels.close} className={cx.close} data-sf-cart-close=\"\" data-sf-autofocus={quiet ? undefined : ''}>\n {icons?.close ?? <span aria-hidden=\"true\">✕</span>}\n </button>\n </div>\n\n <OptimisticNotices notices={opt.notices} labels={ol} classNames={cx} />\n <OptimisticStatus kind={opt.announcement.kind} n={opt.announcement.n} text={ol.added} />\n\n {empty ? (\n <div className={cx.empty} data-sf-cart-empty=\"\">\n <p className={cx.emptyTitle} data-sf-cart-empty-title=\"\">{labels.empty}</p>\n {labels.emptyHint ? <p className={cx.emptyHint} data-sf-cart-empty-hint=\"\">{labels.emptyHint}</p> : null}\n {paths.browse && labels.browse ? link({ href: paths.browse, className: cx.browse, children: labels.browse, onClick: close }) : null}\n </div>\n ) : (\n <>\n <div className={cx.body} data-sf-cart-body=\"\">\n {shipping ? (\n <div className={cx.shipping} data-sf-cart-shipping=\"\" data-reached={shipping.reached || undefined}>\n <p className={cx.shippingMessage}>\n {shipping.reached ? icons?.shippingReached : icons?.shipping}\n {shipping.message}\n </p>\n <div\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={Math.round(shipping.percent)}\n aria-label={shipping.progressLabel}\n className={cx.bar}\n data-sf-cart-bar=\"\"\n >\n <div className={cx.barFill} data-sf-cart-bar-fill=\"\" style={{ width: `${Math.max(0, Math.min(100, shipping.percent))}%` }} />\n </div>\n </div>\n ) : notice ? (\n <p className={[cx.shipping, cx.shippingMessage].filter(Boolean).join(\" \") || undefined} data-sf-cart-shipping=\"\" data-notice=\"\">{icons?.shippingReached}{notice}</p>\n ) : null}\n\n <ul className={cx.lines} data-sf-cart-lines=\"\">\n {lines.map((line) => (\n <DrawerLine key={line.id} line={line} props={props} money={money} link={link} close={close} pending={pendingByVariant.get(line.merchandise.id)} pendingLabel={ol.adding} />\n ))}\n {extraRows.map((row) => (\n <PendingLine key={`pending-${row.variantId}`} row={row} props={props} money={money} label={ol.adding} />\n ))}\n </ul>\n\n {upsell ? (\n <section className={cx.upsell} data-sf-cart-upsell=\"\" aria-labelledby={upsellTitle ? upsellId : undefined}>\n {upsellTitle ? <h3 id={upsellId} className={cx.upsellTitle}>{upsellTitle}</h3> : null}\n {upsell}\n </section>\n ) : null}\n </div>\n\n <div className={cx.footer} data-sf-cart-footer=\"\">\n <div className={cx.subtotal} data-sf-cart-subtotal=\"\" aria-busy={pending || undefined}>\n <span className={cx.subtotalLabel}>{labels.subtotal}</span>\n <span className={cx.subtotalValue} data-sf-cart-subtotal-value=\"\">{cart ? money(cart.cost.subtotal) : null}{pending ? <span data-sf-cart-calculating=\"\">{cart ? ' ' : ''}{ol.calculating}</span> : null}</span>\n </div>\n {labels.note ? <p className={cx.note} data-sf-cart-note=\"\">{labels.note}</p> : null}\n <div className={cx.actions} data-sf-cart-actions=\"\">\n {link({ href: paths.checkout, className: cx.checkout, children: labels.checkout, onClick: close })}\n {link({ href: paths.cart, className: cx.viewCart, children: labels.viewCart, onClick: close })}\n </div>\n </div>\n </>\n )}\n </div>\n </dialog>\n )\n}\n\nfunction DrawerLine({\n line,\n props,\n money,\n link,\n close,\n pending,\n pendingLabel,\n}: {\n pending?: OptimisticRow | undefined\n pendingLabel: string\n line: CartLine\n props: CartDrawerProps\n money: (m: Money) => ReactNode\n link: (p: CartDrawerLinkProps) => ReactNode\n close: () => void\n}) {\n const { labels, paths, icons, classNames: cx = {} } = props\n const f = { ...DEFAULT_FORM, ...props.form }\n const { Form, formData } = (props.useLineForm ?? useNativeForm)()\n const quantity = formData ? Number(formData.get(f.quantityField) ?? 0) : line.quantity + (pending?.quantity ?? 0)\n if (formData && (formData.get(f.intentField) === f.removeIntent || quantity === 0)) return null\n\n const merch = line.merchandise\n const isDefault = props.isDefaultVariantTitle ?? defaultIsDefaultVariant\n const title = merch.product.title\n const href = paths.product?.(merch.product.handle, merch.id)\n const img = merch.image ?? merch.product.featured_image\n const image = props.renderImage ? props.renderImage(line) : <ProductThumb image={img ?? null} name={title} size={80} decorative />\n\n const imageNode = <span className={cx.image} data-sf-cart-image=\"\">{image}</span>\n const price = <span className={cx.price} data-sf-cart-price=\"\">{money(line.cost.total)}</span>\n const controls = (\n <div className={cx.controls} data-sf-cart-controls=\"\">\n <Form method=\"post\" action={paths.cart} className={cx.qty} data-sf-cart-qty=\"\">\n <input type=\"hidden\" name={f.intentField} value={f.updateIntent} />\n <input type=\"hidden\" name={f.lineField} value={line.id} />\n <button type=\"submit\" name={f.quantityField} value={quantity - 1} aria-label={labels.decrease} className={cx.qtyButton} data-sf-cart-qty-button=\"\">\n {icons?.decrease ?? <span aria-hidden=\"true\">−</span>}\n </button>\n <span className={cx.qtyValue} aria-live=\"polite\" data-sf-cart-qty-value=\"\">{quantity}</span>\n <button type=\"submit\" name={f.quantityField} value={quantity + 1} aria-label={labels.increase} className={cx.qtyButton} data-sf-cart-qty-button=\"\">\n {icons?.increase ?? <span aria-hidden=\"true\">+</span>}\n </button>\n </Form>\n <Form method=\"post\" action={paths.cart} data-sf-cart-remove-form=\"\">\n <input type=\"hidden\" name={f.intentField} value={f.removeIntent} />\n <input type=\"hidden\" name={f.lineField} value={line.id} />\n <button type=\"submit\" className={cx.remove} data-sf-cart-remove=\"\">{labels.remove}</button>\n </Form>\n </div>\n )\n\n if (props.renderLine) return <li key={line.id} className={cx.line} data-sf-cart-line=\"\">{props.renderLine(line, { controls, price, image: imageNode })}</li>\n\n return (\n <li className={cx.line} data-sf-cart-line=\"\">\n {imageNode}\n <div className={cx.lineMain} data-sf-cart-line-main=\"\">\n <div className={cx.lineHead} data-sf-cart-line-head=\"\">\n <div className={cx.lineText} data-sf-cart-line-text=\"\">\n {href ? link({ href, className: cx.lineTitle, children: title, onClick: close }) : <span className={cx.lineTitle} data-sf-cart-line-title=\"\">{title}</span>}\n {!isDefault(merch.title) ? <p className={cx.variant} data-sf-cart-variant=\"\">{merch.title}</p> : null}\n </div>\n {price}\n </div>\n {controls}\n {pending ? <p className={cx.variant} data-sf-cart-pending-label=\"\">{pendingLabel}</p> : null}\n </div>\n </li>\n )\n}\n\n/** Fila que existe solo en el navegador hasta que OPS la confirma: sin controles, con el precio unitario mostrado. */\nfunction PendingLine({ row, props, money, label }: { row: OptimisticRow; props: CartDrawerProps; money: (m: Money) => ReactNode; label: string }) {\n const { classNames: cx = {} } = props\n const isDefault = props.isDefaultVariantTitle ?? defaultIsDefaultVariant\n return (\n <li className={cx.line} data-sf-cart-line=\"\" data-sf-cart-line-pending=\"\" aria-busy=\"true\">\n <span className={cx.image} data-sf-cart-image=\"\">\n <ProductThumb image={row.image ?? null} name={row.title} size={80} decorative />\n </span>\n <div className={cx.lineMain} data-sf-cart-line-main=\"\">\n <div className={cx.lineHead} data-sf-cart-line-head=\"\">\n <div className={cx.lineText} data-sf-cart-line-text=\"\">\n <span className={cx.lineTitle} data-sf-cart-line-title=\"\">{row.title}</span>\n {row.variantTitle && !isDefault(row.variantTitle) ? <p className={cx.variant} data-sf-cart-variant=\"\">{row.variantTitle}</p> : null}\n </div>\n {row.price ? <span className={cx.price} data-sf-cart-price=\"\">{money(row.price)}</span> : null}\n </div>\n <p className={cx.variant} data-sf-cart-pending-label=\"\">{label} · ×{row.quantity}</p>\n </div>\n </li>\n )\n}\n\n/** Región `aria-live=\"polite\"`: anuncia «Agregado al carrito». Alterna un espacio fino para repetir el mismo texto. */\nfunction OptimisticStatus({ kind, n, text }: { kind: 'added' | null; n: number; text: string }) {\n return (\n <div role=\"status\" aria-live=\"polite\" data-sf-cart-status=\"\" style={VISUALLY_HIDDEN}>\n {kind === 'added' ? `${text}${n % 2 ? '' : '\\u200B'}` : ''}\n </div>\n )\n}\n\nconst VISUALLY_HIDDEN = { position: 'absolute', width: 1, height: 1, margin: -1, padding: 0, overflow: 'hidden', clip: 'rect(0 0 0 0)', whiteSpace: 'nowrap', border: 0 } as const\n\n/** Avisos de fallo (`role=\"alert\"`, assertive), descartables. Se pintan dentro del cajón abierto o, si está cerrado, sueltos. */\nfunction OptimisticNotices({ notices, labels, classNames: cx }: { notices: readonly OptimisticNotice[]; labels: CartDrawerOptimisticLabels; classNames: Partial<Record<CartDrawerSlot, string>> }) {\n return (\n <div role=\"alert\" aria-live=\"assertive\" data-sf-cart-notices=\"\" className={cx.notices}>\n {notices.map((n) => (\n <p key={n.id} data-sf-cart-notice=\"\">\n <span>{labels.failed(n.title, n.reason)}</span>\n <button type=\"button\" onClick={() => cartOptimistic.dismissNotice(n.id)} aria-label={labels.dismiss} data-sf-cart-notice-dismiss=\"\">\n <span aria-hidden=\"true\">✕</span>\n </button>\n </p>\n ))}\n </div>\n )\n}\n"]}
|