@develemit/storefront 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +244 -2
  2. package/dist/cart/cart-provider.d.ts +25 -0
  3. package/dist/cart/cart-provider.d.ts.map +1 -0
  4. package/dist/cart/cart-reducer.d.ts +32 -0
  5. package/dist/cart/cart-reducer.d.ts.map +1 -0
  6. package/dist/cart/cart-storage.d.ts +7 -0
  7. package/dist/cart/cart-storage.d.ts.map +1 -0
  8. package/dist/client/commerce-client.d.ts +14 -0
  9. package/dist/client/commerce-client.d.ts.map +1 -0
  10. package/dist/client/errors.d.ts +13 -0
  11. package/dist/client/errors.d.ts.map +1 -0
  12. package/dist/client/index.d.ts +3 -0
  13. package/dist/client/index.d.ts.map +1 -0
  14. package/dist/client.js +62 -0
  15. package/dist/components/add-to-cart-button/add-to-cart-button.d.ts +15 -0
  16. package/dist/components/add-to-cart-button/add-to-cart-button.d.ts.map +1 -0
  17. package/dist/components/availability-badge/availability-badge.d.ts +16 -0
  18. package/dist/components/availability-badge/availability-badge.d.ts.map +1 -0
  19. package/dist/components/cart-button/cart-button.d.ts +10 -0
  20. package/dist/components/cart-button/cart-button.d.ts.map +1 -0
  21. package/dist/components/cart-drawer/cart-drawer.d.ts +19 -0
  22. package/dist/components/cart-drawer/cart-drawer.d.ts.map +1 -0
  23. package/dist/components/cart-drawer/use-drawer-presence.d.ts +6 -0
  24. package/dist/components/cart-drawer/use-drawer-presence.d.ts.map +1 -0
  25. package/dist/components/cart-line-item/cart-line-item.d.ts +12 -0
  26. package/dist/components/cart-line-item/cart-line-item.d.ts.map +1 -0
  27. package/dist/components/cart-summary/cart-summary.d.ts +11 -0
  28. package/dist/components/cart-summary/cart-summary.d.ts.map +1 -0
  29. package/dist/components/category-filter/category-filter.d.ts +12 -0
  30. package/dist/components/category-filter/category-filter.d.ts.map +1 -0
  31. package/dist/components/fixtures.d.ts +3 -0
  32. package/dist/components/fixtures.d.ts.map +1 -0
  33. package/dist/components/price-tag/price-tag.d.ts +8 -0
  34. package/dist/components/price-tag/price-tag.d.ts.map +1 -0
  35. package/dist/components/product-card/product-card.d.ts +10 -0
  36. package/dist/components/product-card/product-card.d.ts.map +1 -0
  37. package/dist/components/product-gallery/product-gallery.d.ts +7 -0
  38. package/dist/components/product-gallery/product-gallery.d.ts.map +1 -0
  39. package/dist/components/product-grid/product-grid.d.ts +11 -0
  40. package/dist/components/product-grid/product-grid.d.ts.map +1 -0
  41. package/dist/components/render-with-cart.d.ts +4 -0
  42. package/dist/components/render-with-cart.d.ts.map +1 -0
  43. package/dist/format/index.d.ts +3 -0
  44. package/dist/format/index.d.ts.map +1 -0
  45. package/dist/format.js +1 -0
  46. package/dist/index.d.ts +23 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +672 -0
  49. package/dist/lib/format-price.d.ts +2 -0
  50. package/dist/lib/format-price.d.ts.map +1 -0
  51. package/dist/lib/parse-duration.d.ts +2 -0
  52. package/dist/lib/parse-duration.d.ts.map +1 -0
  53. package/dist/lib/provider.d.ts +29 -0
  54. package/dist/lib/provider.d.ts.map +1 -0
  55. package/dist/lib/theme.d.ts +16 -0
  56. package/dist/lib/theme.d.ts.map +1 -0
  57. package/dist/sort-for-display-Cj6GMeCY.js +13 -0
  58. package/dist/styles.css +454 -0
  59. package/dist/views/featured-products.d.ts +9 -0
  60. package/dist/views/featured-products.d.ts.map +1 -0
  61. package/dist/views/product-detail-view.d.ts +14 -0
  62. package/dist/views/product-detail-view.d.ts.map +1 -0
  63. package/dist/views/shop-view.d.ts +20 -0
  64. package/dist/views/shop-view.d.ts.map +1 -0
  65. package/dist/views/sort-for-display.d.ts +3 -0
  66. package/dist/views/sort-for-display.d.ts.map +1 -0
  67. package/package.json +46 -3
package/dist/index.js ADDED
@@ -0,0 +1,672 @@
1
+ "use client";
2
+ import { n as e, t } from "./sort-for-display-Cj6GMeCY.js";
3
+ import { createContext as n, useCallback as r, useContext as i, useEffect as a, useMemo as o, useReducer as s, useRef as c, useState as l } from "react";
4
+ import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
5
+ import { cartLineSchema as p } from "@develemit/commerce-contracts";
6
+ // src/lib/theme.ts
7
+ var m = {
8
+ colorBg: "--sf-color-bg",
9
+ colorSurface: "--sf-color-surface",
10
+ colorFg: "--sf-color-fg",
11
+ colorMuted: "--sf-color-muted",
12
+ colorAccent: "--sf-color-accent",
13
+ colorAccentFg: "--sf-color-accent-fg",
14
+ colorBorder: "--sf-color-border",
15
+ colorSold: "--sf-color-sold",
16
+ radius: "--sf-radius",
17
+ fontDisplay: "--sf-font-display",
18
+ fontBody: "--sf-font-body",
19
+ spaceUnit: "--sf-space-unit"
20
+ };
21
+ function h(e) {
22
+ let t = {};
23
+ for (let n of Object.keys(m)) {
24
+ let r = e[n];
25
+ r !== void 0 && (t[m[n]] = r);
26
+ }
27
+ return t;
28
+ }
29
+ // src/lib/provider.tsx
30
+ var g = {
31
+ renderLink: ({ href: e, children: t, className: n }) => /* @__PURE__ */ d("a", {
32
+ href: e,
33
+ className: n,
34
+ children: t
35
+ }),
36
+ renderImage: ({ src: e, alt: t, sizes: n, className: r }) => /* @__PURE__ */ d("img", {
37
+ src: e,
38
+ alt: t,
39
+ sizes: n,
40
+ className: r
41
+ }),
42
+ locale: "en-US",
43
+ hrefs: {
44
+ product: (e) => `/shop/${e}`,
45
+ category: (e) => `/shop?category=${e}`
46
+ }
47
+ }, _ = n(g);
48
+ function v({ children: e, hrefs: t, ...n }) {
49
+ let r = {
50
+ ...g,
51
+ ...n,
52
+ hrefs: {
53
+ ...g.hrefs,
54
+ ...t
55
+ }
56
+ };
57
+ return /* @__PURE__ */ d(_.Provider, {
58
+ value: r,
59
+ children: e
60
+ });
61
+ }
62
+ function y() {
63
+ return i(_);
64
+ }
65
+ // src/components/price-tag/price-tag.tsx
66
+ function b({ priceCents: t, currency: n, sold: r = !1, className: i }) {
67
+ let { locale: a } = y(), o = [
68
+ "sf-price",
69
+ r && "sf-price--sold",
70
+ i
71
+ ].filter(Boolean).join(" ");
72
+ return /* @__PURE__ */ d("span", {
73
+ className: o,
74
+ children: e(t, n, a)
75
+ });
76
+ }
77
+ // src/components/availability-badge/availability-badge.tsx
78
+ var x = {
79
+ oneOfAKind: "One of a kind",
80
+ sold: "Sold",
81
+ reserved: "On hold",
82
+ available: "Available"
83
+ };
84
+ function S({ availability: e, quantity: t, labels: n, className: r }) {
85
+ let i = {
86
+ ...x,
87
+ ...n
88
+ }, a, o;
89
+ e === "sold" ? (a = "sold", o = i.sold) : e === "reserved" ? (a = "reserved", o = i.reserved) : t === 1 ? (a = "unique", o = i.oneOfAKind) : (a = "available", o = i.available);
90
+ let s = [
91
+ "sf-badge",
92
+ `sf-badge--${a}`,
93
+ r
94
+ ].filter(Boolean).join(" ");
95
+ return /* @__PURE__ */ d("span", {
96
+ role: "status",
97
+ className: s,
98
+ children: o
99
+ });
100
+ }
101
+ // src/components/product-card/product-card.tsx
102
+ function C({ product: e, labels: t, sizes: n, priority: r }) {
103
+ let { renderLink: i, renderImage: a, hrefs: o } = y(), s = e.availability === "sold", c = e.images[0], l = ["sf-card", s && "sf-card--sold"].filter(Boolean).join(" ");
104
+ return /* @__PURE__ */ d("article", {
105
+ className: l,
106
+ children: i({
107
+ href: o.product(e.slug),
108
+ className: "sf-card__link",
109
+ children: /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d("div", {
110
+ className: "sf-card__media",
111
+ children: c ? a({
112
+ src: c.url,
113
+ alt: c.alt,
114
+ sizes: n,
115
+ className: "sf-card__image",
116
+ priority: r
117
+ }) : /* @__PURE__ */ d("div", {
118
+ className: "sf-card__placeholder",
119
+ "aria-hidden": "true"
120
+ })
121
+ }), /* @__PURE__ */ f("div", {
122
+ className: "sf-card__body",
123
+ children: [
124
+ /* @__PURE__ */ d("h3", {
125
+ className: "sf-card__title",
126
+ children: e.name
127
+ }),
128
+ /* @__PURE__ */ d(b, {
129
+ priceCents: e.priceCents,
130
+ currency: e.currency,
131
+ sold: s
132
+ }),
133
+ /* @__PURE__ */ d(S, {
134
+ availability: e.availability,
135
+ quantity: e.quantity,
136
+ labels: t
137
+ })
138
+ ]
139
+ })] })
140
+ })
141
+ });
142
+ }
143
+ // src/components/product-grid/product-grid.tsx
144
+ function w({ products: e, emptyState: t, labels: n, priorityCount: r = 0 }) {
145
+ return e.length === 0 ? /* @__PURE__ */ d("div", {
146
+ className: "sf-grid-empty",
147
+ children: t ?? "No products found."
148
+ }) : /* @__PURE__ */ d("ul", {
149
+ className: "sf-grid",
150
+ children: e.map((e, t) => /* @__PURE__ */ d("li", {
151
+ className: "sf-grid__item",
152
+ children: /* @__PURE__ */ d(C, {
153
+ product: e,
154
+ labels: n,
155
+ priority: t < r
156
+ })
157
+ }, e.id))
158
+ });
159
+ }
160
+ // src/components/category-filter/category-filter.tsx
161
+ function T({ categories: e, selected: t, onSelect: n, allLabel: r = "All", label: i = "Categories", formatLabel: a, sortCategories: o }) {
162
+ let { renderLink: s, hrefs: c } = y(), l = o ? [...e].sort(o) : e, u = n !== void 0, p = (e, r, i) => {
163
+ let a = t === e, o = `sf-filter__item${a ? " sf-filter__item--active" : ""}`;
164
+ return /* @__PURE__ */ d("li", { children: u ? /* @__PURE__ */ d("button", {
165
+ type: "button",
166
+ className: o,
167
+ "aria-pressed": a,
168
+ onClick: () => n(e),
169
+ children: r
170
+ }) : s({
171
+ href: i,
172
+ className: o,
173
+ children: r
174
+ }) }, e ?? "__all");
175
+ };
176
+ return /* @__PURE__ */ d("nav", {
177
+ "aria-label": i,
178
+ className: "sf-filter",
179
+ children: /* @__PURE__ */ f("ul", {
180
+ className: "sf-filter__list",
181
+ children: [p(void 0, r, c.category("")), l.map((e) => p(e.slug, a ? a(e) : e.label, c.category(e.slug)))]
182
+ })
183
+ });
184
+ }
185
+ // src/components/product-gallery/product-gallery.tsx
186
+ function E({ images: e, sizes: t }) {
187
+ let { renderImage: n } = y(), [r, i] = l(0);
188
+ return e.length === 0 ? null : /* @__PURE__ */ f("div", {
189
+ className: "sf-gallery",
190
+ role: "group",
191
+ "aria-roledescription": "carousel",
192
+ "aria-label": "Product images",
193
+ tabIndex: 0,
194
+ onKeyDown: (t) => {
195
+ if (t.key === "ArrowRight") i((t) => (t + 1) % e.length);
196
+ else if (t.key === "ArrowLeft") i((t) => (t - 1 + e.length) % e.length);
197
+ else if (t.key === "Home") i(0);
198
+ else if (t.key === "End") i(e.length - 1);
199
+ else return;
200
+ t.preventDefault();
201
+ },
202
+ children: [/* @__PURE__ */ d("div", {
203
+ className: "sf-gallery__stage",
204
+ children: e.map((e, i) => /* @__PURE__ */ d("div", {
205
+ className: "sf-gallery__slide",
206
+ hidden: i !== r,
207
+ children: n({
208
+ src: e.url,
209
+ alt: e.alt,
210
+ sizes: t,
211
+ priority: i === r,
212
+ className: "sf-gallery__image"
213
+ })
214
+ }, e.url))
215
+ }), e.length > 1 && /* @__PURE__ */ d("div", {
216
+ className: "sf-gallery__thumbs",
217
+ children: e.map((t, a) => /* @__PURE__ */ d("button", {
218
+ type: "button",
219
+ className: `sf-gallery__thumb${a === r ? " sf-gallery__thumb--active" : ""}`,
220
+ "aria-label": `Show image ${a + 1} of ${e.length}`,
221
+ "aria-current": a === r,
222
+ onClick: () => i(a),
223
+ children: n({
224
+ src: t.url,
225
+ alt: "",
226
+ className: "sf-gallery__thumb-image"
227
+ })
228
+ }, t.url))
229
+ })]
230
+ });
231
+ }
232
+ // src/views/shop-view.tsx
233
+ function D({ products: e, categories: n, activeCategory: r, slots: i = {}, labels: a, allLabel: o, formatCategoryLabel: s, sortCategories: c }) {
234
+ return /* @__PURE__ */ f("div", {
235
+ className: "sf-shop",
236
+ children: [
237
+ i.header,
238
+ i.intro,
239
+ /* @__PURE__ */ d(T, {
240
+ categories: n,
241
+ selected: r,
242
+ allLabel: o,
243
+ formatLabel: s,
244
+ sortCategories: c
245
+ }),
246
+ /* @__PURE__ */ d(w, {
247
+ products: t(e),
248
+ emptyState: i.emptyState,
249
+ labels: a,
250
+ priorityCount: 6
251
+ })
252
+ ]
253
+ });
254
+ }
255
+ // src/views/product-detail-view.tsx
256
+ function O({ product: e, slots: t = {}, labels: n }) {
257
+ return /* @__PURE__ */ f("article", {
258
+ className: "sf-detail",
259
+ children: [/* @__PURE__ */ d(E, { images: e.images }), /* @__PURE__ */ f("div", {
260
+ className: "sf-detail__body",
261
+ children: [
262
+ /* @__PURE__ */ d("h1", {
263
+ className: "sf-detail__title",
264
+ children: e.name
265
+ }),
266
+ /* @__PURE__ */ d(b, {
267
+ priceCents: e.priceCents,
268
+ currency: e.currency
269
+ }),
270
+ /* @__PURE__ */ d(S, {
271
+ availability: e.availability,
272
+ quantity: e.quantity,
273
+ labels: n
274
+ }),
275
+ /* @__PURE__ */ d("p", {
276
+ className: "sf-detail__description",
277
+ children: e.description
278
+ }),
279
+ (e.materials || e.dimensions) && /* @__PURE__ */ f("dl", {
280
+ className: "sf-detail__specs",
281
+ children: [e.materials && /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d("dt", { children: "Materials" }), /* @__PURE__ */ d("dd", { children: e.materials })] }), e.dimensions && /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d("dt", { children: "Dimensions" }), /* @__PURE__ */ d("dd", { children: e.dimensions })] })]
282
+ }),
283
+ t.actions && /* @__PURE__ */ d("div", {
284
+ className: "sf-detail__actions",
285
+ children: t.actions
286
+ }),
287
+ t.afterDetails
288
+ ]
289
+ })]
290
+ });
291
+ }
292
+ // src/views/featured-products.tsx
293
+ function k({ products: e, heading: t = "Featured", labels: n }) {
294
+ return e.length === 0 ? null : /* @__PURE__ */ f("section", {
295
+ className: "sf-featured",
296
+ children: [/* @__PURE__ */ d("h2", {
297
+ className: "sf-featured__heading",
298
+ children: t
299
+ }), /* @__PURE__ */ d(w, {
300
+ products: e,
301
+ labels: n,
302
+ priorityCount: 6
303
+ })]
304
+ });
305
+ }
306
+ // src/cart/cart-reducer.ts
307
+ var A = { lines: [] };
308
+ function j(e, t) {
309
+ let n = e.lines[0];
310
+ if (n && n.currency !== t.currency) return {
311
+ state: e,
312
+ added: !1,
313
+ capped: !1,
314
+ reason: "currency-mismatch"
315
+ };
316
+ let r = e.lines.find((e) => e.productId === t.productId);
317
+ if (!r) {
318
+ let n = Math.min(t.quantity, t.maxQuantity);
319
+ return {
320
+ state: { lines: [...e.lines, {
321
+ ...t,
322
+ quantity: n
323
+ }] },
324
+ added: !0,
325
+ capped: n < t.quantity
326
+ };
327
+ }
328
+ if (r.quantity >= r.maxQuantity) return {
329
+ state: e,
330
+ added: !1,
331
+ capped: !0
332
+ };
333
+ let i = Math.min(r.quantity + t.quantity, r.maxQuantity);
334
+ return {
335
+ state: { lines: e.lines.map((e) => e.productId === t.productId ? {
336
+ ...e,
337
+ quantity: i
338
+ } : e) },
339
+ added: !0,
340
+ capped: r.quantity + t.quantity > r.maxQuantity
341
+ };
342
+ }
343
+ function M(e, t) {
344
+ switch (t.type) {
345
+ case "add": return j(e, t.line).state;
346
+ case "remove": return { lines: e.lines.filter((e) => e.productId !== t.productId) };
347
+ case "setQuantity": return t.quantity <= 0 ? M(e, {
348
+ type: "remove",
349
+ productId: t.productId
350
+ }) : { lines: e.lines.map((e) => e.productId === t.productId ? {
351
+ ...e,
352
+ quantity: Math.min(t.quantity, e.maxQuantity)
353
+ } : e) };
354
+ case "clear": return A;
355
+ case "hydrate": return t.state;
356
+ }
357
+ }
358
+ function N(e) {
359
+ return e.lines.reduce((e, t) => e + t.priceCents * t.quantity, 0);
360
+ }
361
+ function P(e) {
362
+ return e.lines.reduce((e, t) => e + t.quantity, 0);
363
+ }
364
+ // src/cart/cart-storage.ts
365
+ function F(e = "sf-cart") {
366
+ return {
367
+ load() {
368
+ if (typeof window > "u") return A;
369
+ try {
370
+ let t = window.localStorage.getItem(e);
371
+ if (!t) return A;
372
+ let n = JSON.parse(t);
373
+ return { lines: (Array.isArray(n?.lines) ? n.lines : []).flatMap((e) => {
374
+ let t = p.safeParse(e);
375
+ return t.success ? [t.data] : [];
376
+ }) };
377
+ } catch {
378
+ return A;
379
+ }
380
+ },
381
+ save(t) {
382
+ if (typeof window < "u") try {
383
+ window.localStorage.setItem(e, JSON.stringify(t));
384
+ } catch {}
385
+ }
386
+ };
387
+ }
388
+ // src/cart/cart-provider.tsx
389
+ var I = n(null), L = F();
390
+ function R({ storage: e = L, children: t }) {
391
+ let [n, i] = s(M, A), [u, f] = l(!1), [p, m] = l(!1), h = c(n);
392
+ a(() => {
393
+ h.current = n;
394
+ }, [n]), a(() => {
395
+ let t = !1;
396
+ return Promise.resolve(e.load()).then((e) => {
397
+ t || (i({
398
+ type: "hydrate",
399
+ state: e
400
+ }), f(!0));
401
+ }), () => {
402
+ t = !0;
403
+ };
404
+ }, [e]), a(() => {
405
+ u && e.save(n);
406
+ }, [
407
+ u,
408
+ n,
409
+ e
410
+ ]);
411
+ let g = r((e) => {
412
+ let t = j(h.current, e);
413
+ return t.added && (h.current = t.state, i({
414
+ type: "add",
415
+ line: e
416
+ })), t;
417
+ }, []), _ = o(() => ({
418
+ lines: n.lines,
419
+ itemCount: P(n),
420
+ subtotalCents: N(n),
421
+ currency: n.lines[0]?.currency ?? null,
422
+ hydrated: u,
423
+ isOpen: p,
424
+ open: () => m(!0),
425
+ close: () => m(!1),
426
+ add: g,
427
+ remove: (e) => i({
428
+ type: "remove",
429
+ productId: e
430
+ }),
431
+ setQuantity: (e, t) => i({
432
+ type: "setQuantity",
433
+ productId: e,
434
+ quantity: t
435
+ }),
436
+ clear: () => i({ type: "clear" })
437
+ }), [
438
+ n,
439
+ u,
440
+ p,
441
+ g
442
+ ]);
443
+ return /* @__PURE__ */ d(I.Provider, {
444
+ value: _,
445
+ children: t
446
+ });
447
+ }
448
+ function z() {
449
+ let e = i(I);
450
+ if (!e) throw Error("useCart must be used inside <CartProvider>");
451
+ return e;
452
+ }
453
+ // src/components/add-to-cart-button/add-to-cart-button.tsx
454
+ var B = {
455
+ add: "Add to cart",
456
+ inCart: "In your cart",
457
+ unavailable: "Unavailable"
458
+ };
459
+ function V({ product: e, labels: t, openOnAdd: n = !0, className: r }) {
460
+ let i = z(), a = {
461
+ ...B,
462
+ ...t
463
+ }, o = i.lines.find((t) => t.productId === e.id)?.quantity ?? 0, s = e.availability !== "available", c = o >= e.quantity, l = !i.hydrated || s || c, u = s ? a.unavailable : c ? a.inCart : a.add;
464
+ function f() {
465
+ i.add({
466
+ productId: e.id,
467
+ slug: e.slug,
468
+ name: e.name,
469
+ priceCents: e.priceCents,
470
+ currency: e.currency,
471
+ imageUrl: e.images[0]?.url,
472
+ quantity: 1,
473
+ maxQuantity: e.quantity
474
+ }).added && n && i.open();
475
+ }
476
+ return /* @__PURE__ */ d("button", {
477
+ type: "button",
478
+ className: ["sf-button", r].filter(Boolean).join(" "),
479
+ disabled: l,
480
+ onClick: f,
481
+ children: u
482
+ });
483
+ }
484
+ // src/components/cart-line-item/cart-line-item.tsx
485
+ var H = {
486
+ remove: "Remove",
487
+ quantity: "Quantity"
488
+ };
489
+ function U({ line: t, labels: n }) {
490
+ let { remove: r, setQuantity: i } = z(), { locale: a, renderLink: o, renderImage: s, hrefs: c } = y(), l = {
491
+ ...H,
492
+ ...n
493
+ }, u = t.maxQuantity > 1;
494
+ return /* @__PURE__ */ f("li", {
495
+ className: "sf-cart-line",
496
+ children: [t.imageUrl && s({
497
+ src: t.imageUrl,
498
+ alt: "",
499
+ sizes: "80px",
500
+ className: "sf-cart-line__image"
501
+ }), /* @__PURE__ */ f("div", {
502
+ className: "sf-cart-line__body",
503
+ children: [
504
+ o({
505
+ href: c.product(t.slug),
506
+ className: "sf-cart-line__name",
507
+ children: t.name
508
+ }),
509
+ /* @__PURE__ */ d("span", {
510
+ className: "sf-cart-line__price",
511
+ children: e(t.priceCents * t.quantity, t.currency, a)
512
+ }),
513
+ u && /* @__PURE__ */ f("label", {
514
+ className: "sf-cart-line__qty",
515
+ children: [l.quantity, /* @__PURE__ */ d("input", {
516
+ type: "number",
517
+ min: 1,
518
+ max: t.maxQuantity,
519
+ value: t.quantity,
520
+ onChange: (e) => i(t.productId, Number(e.target.value))
521
+ })]
522
+ }),
523
+ /* @__PURE__ */ d("button", {
524
+ type: "button",
525
+ className: "sf-link-button sf-cart-line__remove",
526
+ onClick: () => r(t.productId),
527
+ "aria-label": `${l.remove} ${t.name}`,
528
+ children: l.remove
529
+ })
530
+ ]
531
+ })]
532
+ });
533
+ }
534
+ // src/lib/parse-duration.ts
535
+ function W(e) {
536
+ let t = /^\s*(-?\d*\.?\d+)\s*(ms|s)\s*$/.exec(e);
537
+ if (!t) return 0;
538
+ let n = Number(t[1]);
539
+ return Math.max(0, t[2] === "s" ? n * 1e3 : n);
540
+ }
541
+ // src/components/cart-drawer/use-drawer-presence.ts
542
+ function G(e, t) {
543
+ let [n, r] = l(0), [i, o] = l(e), [s, c] = l(!1);
544
+ return i !== e && (o(e), c(!e && n > 0)), a(() => {
545
+ e && t.current && r(W(getComputedStyle(t.current).getPropertyValue("--sf-motion-duration")));
546
+ }, [e, t]), a(() => {
547
+ if (!s) return;
548
+ let e = setTimeout(() => c(!1), n);
549
+ return () => clearTimeout(e);
550
+ }, [s, n]), {
551
+ mounted: e || s,
552
+ state: e ? "open" : "closed"
553
+ };
554
+ }
555
+ // src/components/cart-summary/cart-summary.tsx
556
+ function K({ onCheckout: t, checkoutLabel: n = "Checkout", checkoutDisabled: r = !1, labels: i }) {
557
+ let a = z(), { locale: o } = y(), s = i?.subtotal ?? "Subtotal";
558
+ return /* @__PURE__ */ f("div", {
559
+ className: "sf-cart-summary",
560
+ children: [/* @__PURE__ */ f("p", {
561
+ className: "sf-cart-summary__row",
562
+ children: [/* @__PURE__ */ d("span", { children: s }), /* @__PURE__ */ d("span", {
563
+ className: "sf-price",
564
+ children: e(a.subtotalCents, a.currency ?? "USD", o)
565
+ })]
566
+ }), /* @__PURE__ */ d("button", {
567
+ type: "button",
568
+ className: "sf-button",
569
+ disabled: r || !t || a.lines.length === 0,
570
+ onClick: t,
571
+ children: n
572
+ })]
573
+ });
574
+ }
575
+ // src/components/cart-drawer/cart-drawer.tsx
576
+ var q = {
577
+ title: "Your cart",
578
+ close: "Close",
579
+ empty: "Your cart is empty."
580
+ }, J = "a[href], button:not([disabled]), input:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
581
+ function Y({ labels: e, summary: t, slots: n }) {
582
+ let r = z(), i = {
583
+ ...q,
584
+ ...e
585
+ }, o = c(null), s = c(null), { isOpen: l } = r, p = G(l, s);
586
+ if (a(() => {
587
+ if (!l) return;
588
+ let e = document.activeElement;
589
+ return o.current?.querySelector(J)?.focus(), () => e?.focus();
590
+ }, [l]), !p.mounted) return null;
591
+ function m(e) {
592
+ if (e.key === "Escape") {
593
+ e.stopPropagation(), r.close();
594
+ return;
595
+ }
596
+ if (e.key !== "Tab") return;
597
+ let t = Array.from(o.current?.querySelectorAll(J) ?? []);
598
+ if (t.length === 0) return;
599
+ let n = t[0], i = t[t.length - 1];
600
+ e.shiftKey && document.activeElement === n ? (e.preventDefault(), i.focus()) : !e.shiftKey && document.activeElement === i && (e.preventDefault(), n.focus());
601
+ }
602
+ return /* @__PURE__ */ d("div", {
603
+ ref: s,
604
+ className: "sf-drawer-backdrop",
605
+ "data-state": p.state,
606
+ onClick: r.close,
607
+ children: /* @__PURE__ */ f("div", {
608
+ ref: o,
609
+ className: "sf-drawer",
610
+ "data-state": p.state,
611
+ role: "dialog",
612
+ "aria-modal": "true",
613
+ "aria-labelledby": "sf-drawer-title",
614
+ onKeyDown: m,
615
+ onClick: (e) => e.stopPropagation(),
616
+ children: [/* @__PURE__ */ f("div", {
617
+ className: "sf-drawer__header",
618
+ children: [/* @__PURE__ */ d("h2", {
619
+ id: "sf-drawer-title",
620
+ className: "sf-drawer__title",
621
+ children: i.title
622
+ }), /* @__PURE__ */ d("button", {
623
+ type: "button",
624
+ className: "sf-drawer__close",
625
+ "aria-label": i.close,
626
+ onClick: r.close,
627
+ children: /* @__PURE__ */ d("span", {
628
+ "aria-hidden": "true",
629
+ children: "×"
630
+ })
631
+ })]
632
+ }), r.lines.length === 0 ? /* @__PURE__ */ d("div", {
633
+ className: "sf-drawer__empty",
634
+ children: n?.empty ?? /* @__PURE__ */ d("p", { children: i.empty })
635
+ }) : /* @__PURE__ */ f(u, { children: [
636
+ /* @__PURE__ */ d("ul", {
637
+ className: "sf-drawer__lines",
638
+ children: r.lines.map((e) => /* @__PURE__ */ d(U, { line: e }, e.productId))
639
+ }),
640
+ /* @__PURE__ */ d(K, { ...t }),
641
+ n?.summaryNote && /* @__PURE__ */ d("div", {
642
+ className: "sf-drawer__note",
643
+ children: n.summaryNote
644
+ })
645
+ ] })]
646
+ })
647
+ });
648
+ }
649
+ // src/components/cart-button/cart-button.tsx
650
+ function X({ label: e = "Cart", className: t, icon: n, labelHidden: r = !1, hideZeroCount: i = !1 }) {
651
+ let a = z(), o = a.hydrated ? a.itemCount : 0, s = !(i && o === 0), c = s ? r ? `${e}, ${a.itemCount} items` : void 0 : `${e}, empty`;
652
+ return /* @__PURE__ */ f("button", {
653
+ type: "button",
654
+ className: ["sf-cart-button", t].filter(Boolean).join(" "),
655
+ "aria-haspopup": "dialog",
656
+ "aria-label": c,
657
+ onClick: a.open,
658
+ children: [
659
+ n,
660
+ /* @__PURE__ */ d("span", {
661
+ className: r ? "sf-visually-hidden" : void 0,
662
+ children: e
663
+ }),
664
+ s && /* @__PURE__ */ d("span", {
665
+ className: "sf-cart-button__count",
666
+ "aria-label": `${a.itemCount} items`,
667
+ children: o
668
+ })
669
+ ]
670
+ });
671
+ }
672
+ export { V as AddToCartButton, S as AvailabilityBadge, X as CartButton, Y as CartDrawer, U as CartLineItem, R as CartProvider, K as CartSummary, T as CategoryFilter, k as FeaturedProducts, b as PriceTag, C as ProductCard, O as ProductDetailView, E as ProductGallery, w as ProductGrid, D as ShopView, v as StorefrontProvider, j as addLine, M as cartReducer, B as defaultAddToCartLabels, x as defaultAvailabilityLabels, q as defaultCartDrawerLabels, H as defaultCartLineItemLabels, A as emptyCart, e as formatPrice, P as itemCount, F as localStorageCartStorage, t as sortForDisplay, N as subtotalCents, h as themeToCssVars, z as useCart, y as useStorefront };
@@ -0,0 +1,2 @@
1
+ export declare function formatPrice(cents: number, currency: string, locale?: string): string;
2
+ //# sourceMappingURL=format-price.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-price.d.ts","sourceRoot":"","sources":["../../src/lib/format-price.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,MAAM,SAAU,GACf,MAAM,CAIR"}
@@ -0,0 +1,2 @@
1
+ export declare function parseDurationMs(value: string): number;
2
+ //# sourceMappingURL=parse-duration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-duration.d.ts","sourceRoot":"","sources":["../../src/lib/parse-duration.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKrD"}