@develemit/storefront 0.2.0 → 0.3.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 (72) hide show
  1. package/README.md +27 -6
  2. package/dist/cart/cart-provider.d.ts +0 -1
  3. package/dist/cart/cart-reducer.d.ts +0 -1
  4. package/dist/cart/cart-storage.d.ts +0 -1
  5. package/dist/client/commerce-client.d.ts +2 -3
  6. package/dist/client/errors.d.ts +0 -1
  7. package/dist/client/index.d.ts +0 -1
  8. package/dist/client/index.js +64 -0
  9. package/dist/client/index.js.map +1 -0
  10. package/dist/components/add-to-cart-button/add-to-cart-button.d.ts +0 -1
  11. package/dist/components/availability-badge/availability-badge.d.ts +0 -1
  12. package/dist/components/cart-button/cart-button.d.ts +0 -1
  13. package/dist/components/cart-drawer/cart-drawer.d.ts +0 -1
  14. package/dist/components/cart-drawer/use-drawer-presence.d.ts +0 -1
  15. package/dist/components/cart-line-item/cart-line-item.d.ts +0 -1
  16. package/dist/components/cart-summary/cart-summary.d.ts +0 -1
  17. package/dist/components/category-filter/category-filter.d.ts +0 -1
  18. package/dist/components/fixtures.d.ts +0 -1
  19. package/dist/components/price-tag/price-tag.d.ts +0 -1
  20. package/dist/components/product-card/product-card.d.ts +2 -3
  21. package/dist/components/product-gallery/product-gallery.d.ts +0 -1
  22. package/dist/components/product-grid/product-grid.d.ts +2 -3
  23. package/dist/components/render-with-cart.d.ts +0 -1
  24. package/dist/format/index.d.ts +0 -1
  25. package/dist/format/index.js +1 -0
  26. package/dist/index.d.ts +1 -2
  27. package/dist/index.js +17 -3
  28. package/dist/index.js.map +1 -0
  29. package/dist/lib/format-price.d.ts +0 -1
  30. package/dist/lib/parse-duration.d.ts +0 -1
  31. package/dist/lib/provider.d.ts +0 -1
  32. package/dist/lib/theme.d.ts +0 -1
  33. package/dist/sort-for-display-Cj6GMeCY.js +2 -0
  34. package/dist/sort-for-display-Cj6GMeCY.js.map +1 -0
  35. package/dist/styles.css +22 -0
  36. package/dist/views/featured-products.d.ts +2 -3
  37. package/dist/views/product-detail-view.d.ts +0 -1
  38. package/dist/views/shop-view.d.ts +5 -4
  39. package/dist/views/sort-for-display.d.ts +2 -3
  40. package/package.json +6 -6
  41. package/dist/cart/cart-provider.d.ts.map +0 -1
  42. package/dist/cart/cart-reducer.d.ts.map +0 -1
  43. package/dist/cart/cart-storage.d.ts.map +0 -1
  44. package/dist/client/commerce-client.d.ts.map +0 -1
  45. package/dist/client/errors.d.ts.map +0 -1
  46. package/dist/client/index.d.ts.map +0 -1
  47. package/dist/client.js +0 -62
  48. package/dist/components/add-to-cart-button/add-to-cart-button.d.ts.map +0 -1
  49. package/dist/components/availability-badge/availability-badge.d.ts.map +0 -1
  50. package/dist/components/cart-button/cart-button.d.ts.map +0 -1
  51. package/dist/components/cart-drawer/cart-drawer.d.ts.map +0 -1
  52. package/dist/components/cart-drawer/use-drawer-presence.d.ts.map +0 -1
  53. package/dist/components/cart-line-item/cart-line-item.d.ts.map +0 -1
  54. package/dist/components/cart-summary/cart-summary.d.ts.map +0 -1
  55. package/dist/components/category-filter/category-filter.d.ts.map +0 -1
  56. package/dist/components/fixtures.d.ts.map +0 -1
  57. package/dist/components/price-tag/price-tag.d.ts.map +0 -1
  58. package/dist/components/product-card/product-card.d.ts.map +0 -1
  59. package/dist/components/product-gallery/product-gallery.d.ts.map +0 -1
  60. package/dist/components/product-grid/product-grid.d.ts.map +0 -1
  61. package/dist/components/render-with-cart.d.ts.map +0 -1
  62. package/dist/format/index.d.ts.map +0 -1
  63. package/dist/format.js +0 -1
  64. package/dist/index.d.ts.map +0 -1
  65. package/dist/lib/format-price.d.ts.map +0 -1
  66. package/dist/lib/parse-duration.d.ts.map +0 -1
  67. package/dist/lib/provider.d.ts.map +0 -1
  68. package/dist/lib/theme.d.ts.map +0 -1
  69. package/dist/views/featured-products.d.ts.map +0 -1
  70. package/dist/views/product-detail-view.d.ts.map +0 -1
  71. package/dist/views/shop-view.d.ts.map +0 -1
  72. package/dist/views/sort-for-display.d.ts.map +0 -1
package/README.md CHANGED
@@ -110,7 +110,11 @@ use it without pulling in the UI:
110
110
  import { createCommerceClient } from '@develemit/storefront/client';
111
111
 
112
112
  const client = createCommerceClient({ baseUrl: 'https://example.com/api' });
113
- await client.listProducts({ category: 'rings' });
113
+ const { items, nextCursor } = await client.listProducts({
114
+ category: 'rings',
115
+ limit: 24, // default 48, max 100
116
+ // cursor: nextCursor from the previous page
117
+ });
114
118
  await client.getProduct('sample-piece'); // throws NotFoundError on 404
115
119
  await client.listCategories();
116
120
  await client.createCheckout([{ productId: 'p1', quantity: 1 }]); // { url }
@@ -127,6 +131,18 @@ sold or held by another buyer; its `productIds` lists them so the cart can drop
127
131
  them. Send only ids and quantities: the server prices every line itself.
128
132
  Redirect the shopper to the returned `url`.
129
133
 
134
+ ## Images in production
135
+
136
+ The default image adapter is a plain `<img loading="lazy" decoding="async">`
137
+ (`priority` switches to `loading="eager"` and `fetchpriority="high"`). It does
138
+ not resize. Production hosts **must** supply a resizing `renderImage` (such as
139
+ `next/image`) or serve through a resizing CDN; otherwise every card downloads
140
+ the full-size original, and admin uploads can be up to 8MB.
141
+
142
+ Pass accurate `sizes` so the adapter picks a small variant. For `ProductGrid`,
143
+ the sizes should match your column layout, for example
144
+ `(min-width: 1024px) 25vw, (min-width: 640px) 50vw, 100vw`.
145
+
130
146
  ## Views
131
147
 
132
148
  `ShopView`, `ProductDetailView`, and `FeaturedProducts` take plain data plus
@@ -145,16 +161,21 @@ const client = createCommerceClient({ baseUrl: process.env.COMMERCE_API_URL! });
145
161
  export default async function ShopPage({
146
162
  searchParams,
147
163
  }: {
148
- searchParams: Promise<{ category?: string }>;
164
+ searchParams: Promise<{ category?: string; cursor?: string }>;
149
165
  }) {
150
- const { category } = await searchParams;
151
- const [products, categories] = await Promise.all([
152
- client.listProducts({ category }),
166
+ const { category, cursor } = await searchParams;
167
+ const [page, categories] = await Promise.all([
168
+ client.listProducts({ category, cursor }),
153
169
  client.listCategories(),
154
170
  ]);
155
171
  return (
156
172
  <ShopView
157
- products={products}
173
+ products={page.items}
174
+ nextHref={
175
+ page.nextCursor
176
+ ? `/shop?cursor=${encodeURIComponent(page.nextCursor)}`
177
+ : undefined
178
+ }
158
179
  categories={categories}
159
180
  activeCategory={category}
160
181
  slots={{ header: <h1>Shop</h1> }}
@@ -22,4 +22,3 @@ export interface CartProviderProps {
22
22
  }
23
23
  export declare function CartProvider({ storage, children, }: CartProviderProps): import('react').JSX.Element;
24
24
  export declare function useCart(): CartContextValue;
25
- //# sourceMappingURL=cart-provider.d.ts.map
@@ -29,4 +29,3 @@ export declare function addLine(state: CartState, line: CartLine): AddResult;
29
29
  export declare function cartReducer(state: CartState, action: CartAction): CartState;
30
30
  export declare function subtotalCents(state: CartState): number;
31
31
  export declare function itemCount(state: CartState): number;
32
- //# sourceMappingURL=cart-reducer.d.ts.map
@@ -4,4 +4,3 @@ export interface CartStorage {
4
4
  save: (state: CartState) => void | Promise<void>;
5
5
  }
6
6
  export declare function localStorageCartStorage(key?: string): CartStorage;
7
- //# sourceMappingURL=cart-storage.d.ts.map
@@ -1,14 +1,13 @@
1
- import { Category, CheckoutRequest, CheckoutResponse, OrderSummary, Product, ProductListQuery } from '@develemit/commerce-contracts';
1
+ import { Category, CheckoutRequest, CheckoutResponse, OrderSummary, ProductCardPage, Product, ProductListQuery } from '@develemit/commerce-contracts';
2
2
  export interface CommerceClientOptions {
3
3
  baseUrl: string;
4
4
  fetch?: typeof fetch;
5
5
  }
6
6
  export interface CommerceClient {
7
- listProducts(query?: ProductListQuery): Promise<Product[]>;
7
+ listProducts(query?: ProductListQuery): Promise<ProductCardPage>;
8
8
  getProduct(slug: string): Promise<Product>;
9
9
  listCategories(): Promise<Category[]>;
10
10
  createCheckout(items: CheckoutRequest['items']): Promise<CheckoutResponse>;
11
11
  getOrderBySession(sessionId: string): Promise<OrderSummary>;
12
12
  }
13
13
  export declare function createCommerceClient({ baseUrl, fetch: fetchImpl, }: CommerceClientOptions): CommerceClient;
14
- //# sourceMappingURL=commerce-client.d.ts.map
@@ -10,4 +10,3 @@ export declare class CheckoutConflictError extends CommerceApiError {
10
10
  readonly productIds: string[];
11
11
  constructor(url: string, productIds: string[]);
12
12
  }
13
- //# sourceMappingURL=errors.d.ts.map
@@ -1,3 +1,2 @@
1
1
  export * from './commerce-client';
2
2
  export * from './errors';
3
- //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,64 @@
1
+ import { categorySchema as e, checkoutConflictSchema as t, checkoutResponseSchema as n, orderSummarySchema as r, productCardPageSchema as i, productSchema as a } from "@develemit/commerce-contracts";
2
+ // src/client/errors.ts
3
+ var o = class extends Error {
4
+ status;
5
+ url;
6
+ constructor(e, t, n) {
7
+ super(n ?? `Commerce API request failed (${e}): ${t}`), this.status = e, this.url = t, this.name = "CommerceApiError";
8
+ }
9
+ }, s = class extends o {
10
+ constructor(e) {
11
+ super(404, e, `Not found: ${e}`), this.name = "NotFoundError";
12
+ }
13
+ }, c = class extends o {
14
+ productIds;
15
+ constructor(e, t) {
16
+ super(409, e, `Some items are no longer available: ${t.join(", ")}`), this.productIds = t, this.name = "CheckoutConflictError";
17
+ }
18
+ };
19
+ // src/client/commerce-client.ts
20
+ function l({ baseUrl: l, fetch: u = (...e) => globalThis.fetch(...e) }) {
21
+ let d = l.replace(/\/+$/, "");
22
+ async function f(e, t, n) {
23
+ if (t.status === 404) throw new s(e);
24
+ if (!t.ok) throw new o(t.status, e);
25
+ return n.parse(await t.json());
26
+ }
27
+ async function p(e, t) {
28
+ let n = `${d}${e}`;
29
+ return f(n, await u(n, { headers: { accept: "application/json" } }), t);
30
+ }
31
+ async function m(e) {
32
+ let r = `${d}/checkout`, i = await u(r, {
33
+ method: "POST",
34
+ headers: {
35
+ accept: "application/json",
36
+ "content-type": "application/json"
37
+ },
38
+ body: JSON.stringify({ items: e })
39
+ });
40
+ if (i.status === 409) throw new c(r, t.parse(await i.json()).unavailableProductIds);
41
+ return f(r, i, n);
42
+ }
43
+ return {
44
+ async listProducts(e = {}) {
45
+ let t = new URLSearchParams();
46
+ e.category && t.set("category", e.category), e.featured !== void 0 && t.set("featured", String(e.featured)), e.limit !== void 0 && t.set("limit", String(e.limit)), e.cursor && t.set("cursor", e.cursor);
47
+ let n = t.toString();
48
+ return p(`/catalog/products${n ? `?${n}` : ""}`, i);
49
+ },
50
+ getProduct(e) {
51
+ return p(`/catalog/products/${encodeURIComponent(e)}`, a);
52
+ },
53
+ listCategories() {
54
+ return p("/catalog/categories", e.array());
55
+ },
56
+ createCheckout: m,
57
+ getOrderBySession(e) {
58
+ return p(`/orders/session/${encodeURIComponent(e)}`, r);
59
+ }
60
+ };
61
+ }
62
+ export { c as CheckoutConflictError, o as CommerceApiError, s as NotFoundError, l as createCommerceClient };
63
+
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["CommerceApiError","message","status","url","NotFoundError","CheckoutConflictError","productIds","createCommerceClient","fetchImpl","args","root","baseUrl","readJson","res","schema","get","path","createCheckout","checkoutConflictSchema","checkoutResponseSchema","params","query","qs","productCardPageSchema","slug","productSchema","categorySchema","sessionId","orderSummarySchema"],"sources":["../../src/client/errors.ts","../../src/client/commerce-client.ts"],"sourcesContent":["export class CommerceApiError extends Error {\n constructor(\n readonly status: number,\n readonly url: string,\n message?: string,\n ) {\n super(message ?? `Commerce API request failed (${status}): ${url}`);\n this.name = 'CommerceApiError';\n }\n}\n\nexport class NotFoundError extends CommerceApiError {\n constructor(url: string) {\n super(404, url, `Not found: ${url}`);\n this.name = 'NotFoundError';\n }\n}\n\nexport class CheckoutConflictError extends CommerceApiError {\n constructor(\n url: string,\n readonly productIds: string[],\n ) {\n super(\n 409,\n url,\n `Some items are no longer available: ${productIds.join(', ')}`,\n );\n this.name = 'CheckoutConflictError';\n }\n}\n","import {\n categorySchema,\n checkoutConflictSchema,\n checkoutResponseSchema,\n orderSummarySchema,\n productCardPageSchema,\n productSchema,\n type Category,\n type CheckoutRequest,\n type CheckoutResponse,\n type OrderSummary,\n type ProductCardPage,\n type Product,\n type ProductListQuery,\n} from '@develemit/commerce-contracts';\nimport {\n CheckoutConflictError,\n CommerceApiError,\n NotFoundError,\n} from './errors';\n\nexport interface CommerceClientOptions {\n baseUrl: string;\n fetch?: typeof fetch;\n}\n\nexport interface CommerceClient {\n listProducts(query?: ProductListQuery): Promise<ProductCardPage>;\n getProduct(slug: string): Promise<Product>;\n listCategories(): Promise<Category[]>;\n createCheckout(items: CheckoutRequest['items']): Promise<CheckoutResponse>;\n getOrderBySession(sessionId: string): Promise<OrderSummary>;\n}\n\ntype Schema<T> = { parse(data: unknown): T };\n\nexport function createCommerceClient({\n baseUrl,\n fetch: fetchImpl = (...args) => globalThis.fetch(...args),\n}: CommerceClientOptions): CommerceClient {\n const root = baseUrl.replace(/\\/+$/, '');\n\n async function readJson<T>(\n url: string,\n res: Response,\n schema: Schema<T>,\n ): Promise<T> {\n if (res.status === 404) throw new NotFoundError(url);\n if (!res.ok) throw new CommerceApiError(res.status, url);\n return schema.parse(await res.json());\n }\n\n async function get<T>(path: string, schema: Schema<T>): Promise<T> {\n const url = `${root}${path}`;\n const res = await fetchImpl(url, {\n headers: { accept: 'application/json' },\n });\n return readJson(url, res, schema);\n }\n\n async function createCheckout(\n items: CheckoutRequest['items'],\n ): Promise<CheckoutResponse> {\n const url = `${root}/checkout`;\n const res = await fetchImpl(url, {\n method: 'POST',\n headers: {\n accept: 'application/json',\n 'content-type': 'application/json',\n },\n body: JSON.stringify({ items }),\n });\n if (res.status === 409) {\n const conflict = checkoutConflictSchema.parse(await res.json());\n throw new CheckoutConflictError(url, conflict.unavailableProductIds);\n }\n return readJson(url, res, checkoutResponseSchema);\n }\n\n return {\n async listProducts(query = {}) {\n const params = new URLSearchParams();\n if (query.category) params.set('category', query.category);\n if (query.featured !== undefined) {\n params.set('featured', String(query.featured));\n }\n if (query.limit !== undefined) params.set('limit', String(query.limit));\n if (query.cursor) params.set('cursor', query.cursor);\n const qs = params.toString();\n return get(\n `/catalog/products${qs ? `?${qs}` : ''}`,\n productCardPageSchema,\n );\n },\n getProduct(slug) {\n return get(\n `/catalog/products/${encodeURIComponent(slug)}`,\n productSchema,\n );\n },\n listCategories() {\n return get('/catalog/categories', categorySchema.array());\n },\n createCheckout,\n getOrderBySession(sessionId) {\n return get(\n `/orders/session/${encodeURIComponent(sessionId)}`,\n orderSummarySchema,\n );\n },\n };\n}\n"],"mappings":";;AAAA,IAAaA,IAAb,cAAsC,MAAM;CAE/B;CACA;CAFX,YACE,GACA,GACA,GACA;EAEA,AADA,MAAMC,KAAW,gCAAgCC,EAAO,KAAKC,GAAK,GAJzD,KAAA,SAAAD,GACA,KAAA,MAAAC,GAIT,KAAK,OAAO;CACd;AACF,GAEaC,IAAb,cAAmCJ,EAAiB;CAClD,YAAY,GAAa;EAEvB,AADA,MAAM,KAAKG,GAAK,cAAcA,GAAK,GACnC,KAAK,OAAO;CACd;AACF,GAEaE,IAAb,cAA2CL,EAAiB;CAG/C;CAFX,YACE,GACA,GACA;EAMA,AALA,MACE,KACAG,GACA,uCAAuCG,EAAW,KAAK,IAAI,GAC7D,GANS,KAAA,aAAAA,GAOT,KAAK,OAAO;CACd;AACF;;ACMA,SAAgBC,EAAqB,EACnC,YACA,OAAOC,KAAa,GAAGC,MAAS,WAAW,MAAM,GAAGA,CAAI,KAChB;CACxC,IAAMC,IAAOC,EAAQ,QAAQ,QAAQ,EAAE;CAEvC,eAAeC,EACb,GACA,GACA,GACY;EACZ,IAAIC,EAAI,WAAW,KAAK,MAAM,IAAIT,EAAcD,CAAG;EACnD,IAAI,CAACU,EAAI,IAAI,MAAM,IAAIb,EAAiBa,EAAI,QAAQV,CAAG;EACvD,OAAOW,EAAO,MAAM,MAAMD,EAAI,KAAK,CAAC;CACtC;CAEA,eAAeE,EAAO,GAAc,GAA+B;EACjE,IAAMZ,IAAM,GAAGO,IAAOM;EAItB,OAAOJ,EAAST,GAAK,MAHHK,EAAUL,GAAK,EAC/B,SAAS,EAAE,QAAQ,mBAAmB,EACxC,CAAC,GACyBW,CAAM;CAClC;CAEA,eAAeG,EACb,GAC2B;EAC3B,IAAMd,IAAM,GAAGO,EAAK,YACdG,IAAM,MAAML,EAAUL,GAAK;GAC/B,QAAQ;GACR,SAAS;IACP,QAAQ;IACR,gBAAgB;GAClB;GACA,MAAM,KAAK,UAAU,EAAE,SAAM,CAAC;EAChC,CAAC;EACD,IAAIU,EAAI,WAAW,KAEjB,MAAM,IAAIR,EAAsBF,GADfe,EAAuB,MAAM,MAAML,EAAI,KAAK,CACxB,CAAA,CAAS,qBAAqB;EAErE,OAAOD,EAAST,GAAKU,GAAKM,CAAsB;CAClD;CAEA,OAAO;EACL,MAAM,aAAa,IAAQ,CAAC,GAAG;GAC7B,IAAMC,IAAS,IAAI,gBAAgB;GAMnC,AALIC,EAAM,YAAUD,EAAO,IAAI,YAAYC,EAAM,QAAQ,GACrDA,EAAM,aAAa,KAAA,KACrBD,EAAO,IAAI,YAAY,OAAOC,EAAM,QAAQ,CAAC,GAE3CA,EAAM,UAAU,KAAA,KAAWD,EAAO,IAAI,SAAS,OAAOC,EAAM,KAAK,CAAC,GAClEA,EAAM,UAAQD,EAAO,IAAI,UAAUC,EAAM,MAAM;GACnD,IAAMC,IAAKF,EAAO,SAAS;GAC3B,OAAOL,EACL,oBAAoBO,IAAK,IAAIA,MAAO,MACpCC,CACF;EACF;EACA,WAAW,GAAM;GACf,OAAOR,EACL,qBAAqB,mBAAmBS,CAAI,KAC5CC,CACF;EACF;EACA,iBAAiB;GACf,OAAOV,EAAI,uBAAuBW,EAAe,MAAM,CAAC;EAC1D;EACA;EACA,kBAAkB,GAAW;GAC3B,OAAOX,EACL,mBAAmB,mBAAmBY,CAAS,KAC/CC,CACF;EACF;CACF;AACF"}
@@ -12,4 +12,3 @@ export interface AddToCartButtonProps {
12
12
  className?: string;
13
13
  }
14
14
  export declare function AddToCartButton({ product, labels, openOnAdd, className, }: AddToCartButtonProps): import('react').JSX.Element;
15
- //# sourceMappingURL=add-to-cart-button.d.ts.map
@@ -13,4 +13,3 @@ export interface AvailabilityBadgeProps {
13
13
  className?: string;
14
14
  }
15
15
  export declare function AvailabilityBadge({ availability, quantity, labels, className, }: AvailabilityBadgeProps): import('react').JSX.Element;
16
- //# sourceMappingURL=availability-badge.d.ts.map
@@ -7,4 +7,3 @@ export interface CartButtonProps {
7
7
  hideZeroCount?: boolean;
8
8
  }
9
9
  export declare function CartButton({ label, className, icon, labelHidden, hideZeroCount, }: CartButtonProps): import('react').JSX.Element;
10
- //# sourceMappingURL=cart-button.d.ts.map
@@ -16,4 +16,3 @@ export interface CartDrawerSlots {
16
16
  summaryNote?: ReactNode;
17
17
  }
18
18
  export declare function CartDrawer({ labels, summary, slots }: CartDrawerProps): import('react').JSX.Element | null;
19
- //# sourceMappingURL=cart-drawer.d.ts.map
@@ -3,4 +3,3 @@ export declare function useDrawerPresence(isOpen: boolean, backdropRef: RefObjec
3
3
  mounted: boolean;
4
4
  state: string;
5
5
  };
6
- //# sourceMappingURL=use-drawer-presence.d.ts.map
@@ -9,4 +9,3 @@ export interface CartLineItemProps {
9
9
  labels?: Partial<CartLineItemLabels>;
10
10
  }
11
11
  export declare function CartLineItem({ line, labels }: CartLineItemProps): import('react').JSX.Element;
12
- //# sourceMappingURL=cart-line-item.d.ts.map
@@ -8,4 +8,3 @@ export interface CartSummaryProps {
8
8
  labels?: Partial<CartSummaryLabels>;
9
9
  }
10
10
  export declare function CartSummary({ onCheckout, checkoutLabel, checkoutDisabled, labels, }: CartSummaryProps): import('react').JSX.Element;
11
- //# sourceMappingURL=cart-summary.d.ts.map
@@ -9,4 +9,3 @@ export interface CategoryFilterProps {
9
9
  sortCategories?: (a: Category, b: Category) => number;
10
10
  }
11
11
  export declare function CategoryFilter({ categories, selected, onSelect, allLabel, label, formatLabel, sortCategories, }: CategoryFilterProps): import('react').JSX.Element;
12
- //# sourceMappingURL=category-filter.d.ts.map
@@ -1,3 +1,2 @@
1
1
  import { Product } from '@develemit/commerce-contracts';
2
2
  export declare function makeProduct(overrides?: Partial<Product>): Product;
3
- //# sourceMappingURL=fixtures.d.ts.map
@@ -5,4 +5,3 @@ export interface PriceTagProps {
5
5
  className?: string;
6
6
  }
7
7
  export declare function PriceTag({ priceCents, currency, sold, className, }: PriceTagProps): import('react').JSX.Element;
8
- //# sourceMappingURL=price-tag.d.ts.map
@@ -1,10 +1,9 @@
1
- import { Product } from '@develemit/commerce-contracts';
1
+ import { ProductCard as ProductCardData } from '@develemit/commerce-contracts';
2
2
  import { AvailabilityLabels } from '../availability-badge/availability-badge';
3
3
  export interface ProductCardProps {
4
- product: Product;
4
+ product: ProductCardData;
5
5
  labels?: Partial<AvailabilityLabels>;
6
6
  sizes?: string;
7
7
  priority?: boolean;
8
8
  }
9
9
  export declare function ProductCard({ product, labels, sizes, priority, }: ProductCardProps): import('react').JSX.Element;
10
- //# sourceMappingURL=product-card.d.ts.map
@@ -4,4 +4,3 @@ export interface ProductGalleryProps {
4
4
  sizes?: string;
5
5
  }
6
6
  export declare function ProductGallery({ images, sizes }: ProductGalleryProps): import('react').JSX.Element | null;
7
- //# sourceMappingURL=product-gallery.d.ts.map
@@ -1,11 +1,10 @@
1
1
  import { ReactNode } from 'react';
2
- import { Product } from '@develemit/commerce-contracts';
2
+ import { ProductCard as ProductCardData } from '@develemit/commerce-contracts';
3
3
  import { AvailabilityLabels } from '../availability-badge/availability-badge';
4
4
  export interface ProductGridProps {
5
- products: Product[];
5
+ products: ProductCardData[];
6
6
  emptyState?: ReactNode;
7
7
  labels?: Partial<AvailabilityLabels>;
8
8
  priorityCount?: number;
9
9
  }
10
10
  export declare function ProductGrid({ products, emptyState, labels, priorityCount, }: ProductGridProps): import('react').JSX.Element;
11
- //# sourceMappingURL=product-grid.d.ts.map
@@ -1,4 +1,3 @@
1
1
  import { ReactElement } from 'react';
2
2
  import { CartStorage } from '../cart/cart-storage';
3
3
  export declare function renderWithCart(ui: ReactElement, storage: CartStorage): Promise<void>;
4
- //# sourceMappingURL=render-with-cart.d.ts.map
@@ -1,3 +1,2 @@
1
1
  export * from '../lib/format-price';
2
2
  export * from '../views/sort-for-display';
3
- //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ export { n as formatPrice, t as sortForDisplay } from "../sort-for-display-Cj6GMeCY.js";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type { Product, ProductImage, ProductAvailability, Category, CartLine, CheckoutRequest, CheckoutResponse, OrderSummary, } from '@develemit/commerce-contracts';
1
+ export type { Product, ProductCard as ProductCardData, ProductCardPage, ProductImage, ProductAvailability, Category, CartLine, CheckoutRequest, CheckoutResponse, OrderSummary, } from '@develemit/commerce-contracts';
2
2
  export * from './lib/format-price';
3
3
  export * from './lib/theme';
4
4
  export * from './lib/provider';
@@ -20,4 +20,3 @@ export * from './components/cart-drawer/cart-drawer';
20
20
  export * from './components/cart-line-item/cart-line-item';
21
21
  export * from './components/cart-summary/cart-summary';
22
22
  export * from './components/cart-button/cart-button';
23
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -33,11 +33,14 @@ var g = {
33
33
  className: n,
34
34
  children: t
35
35
  }),
36
- renderImage: ({ src: e, alt: t, sizes: n, className: r }) => /* @__PURE__ */ d("img", {
36
+ renderImage: ({ src: e, alt: t, sizes: n, className: r, priority: i }) => /* @__PURE__ */ d("img", {
37
37
  src: e,
38
38
  alt: t,
39
39
  sizes: n,
40
- className: r
40
+ className: r,
41
+ loading: i ? "eager" : "lazy",
42
+ decoding: "async",
43
+ fetchPriority: i ? "high" : void 0
41
44
  }),
42
45
  locale: "en-US",
43
46
  hrefs: {
@@ -230,7 +233,8 @@ function E({ images: e, sizes: t }) {
230
233
  });
231
234
  }
232
235
  // src/views/shop-view.tsx
233
- function D({ products: e, categories: n, activeCategory: r, slots: i = {}, labels: a, allLabel: o, formatCategoryLabel: s, sortCategories: c }) {
236
+ function D({ products: e, categories: n, activeCategory: r, slots: i = {}, labels: a, allLabel: o, formatCategoryLabel: s, sortCategories: c, nextHref: l, loadMoreLabel: u = "Load more" }) {
237
+ let { renderLink: p } = y();
234
238
  return /* @__PURE__ */ f("div", {
235
239
  className: "sf-shop",
236
240
  children: [
@@ -248,6 +252,14 @@ function D({ products: e, categories: n, activeCategory: r, slots: i = {}, label
248
252
  emptyState: i.emptyState,
249
253
  labels: a,
250
254
  priorityCount: 6
255
+ }),
256
+ l && /* @__PURE__ */ d("div", {
257
+ className: "sf-shop__pager",
258
+ children: p({
259
+ href: l,
260
+ className: "sf-shop__more",
261
+ children: u
262
+ })
251
263
  })
252
264
  ]
253
265
  });
@@ -670,3 +682,5 @@ function X({ label: e = "Cart", className: t, icon: n, labelHidden: r = !1, hide
670
682
  });
671
683
  }
672
684
  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 };
685
+
686
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["_Fragment","_Fragment","_Fragment","formatPrice","VAR_NAMES","themeToCssVars","vars","key","value","theme","defaults","priority","slug","StorefrontContext","createContext","StorefrontProvider","overrides","hrefs","useStorefront","useContext","PriceTag","classes","sold","className","priceCents","currency","locale","defaultAvailabilityLabels","AvailabilityBadge","text","labels","variant","label","availability","quantity","ProductCard","product","image","renderLink","Fragment","renderImage","ProductGrid","products","emptyState","index","priorityCount","CategoryFilter","ordered","sortCategories","categories","controlled","onSelect","item","active","selected","allLabel","c","formatLabel","ProductGallery","setActive","useState","images","event","i","ShopView","slots","activeCategory","formatCategoryLabel","sortForDisplay","nextHref","loadMoreLabel","ProductDetailView","FeaturedProducts","heading","emptyCart","addLine","first","state","line","existing","l","cartReducer","action","subtotalCents","sum","itemCount","localStorageCartStorage","raw","parsed","result","cartLineSchema","CartContext","defaultStorage","CartProvider","dispatch","useReducer","hydrated","setHydrated","isOpen","setOpen","stateRef","useRef","useEffect","cancelled","storage","loaded","add","useCallback","useMemo","useCart","ctx","defaultAddToCartLabels","AddToCartButton","cart","inCart","unavailable","atCap","disabled","handleClick","openOnAdd","defaultCartLineItemLabels","CartLineItem","editable","setQuantity","remove","parseDurationMs","match","amount","useDrawerPresence","durationMs","setDurationMs","wasOpen","setWasOpen","lingering","setLingering","backdropRef","timer","CartSummary","subtotal","checkoutDisabled","onCheckout","checkoutLabel","defaultCartDrawerLabels","FOCUSABLE","CartDrawer","panelRef","presence","trigger","handleKeyDown","items","last","summary","CartButton","count","showCount","hideZeroCount","ariaLabel","labelHidden","icon"],"sources":["../src/lib/theme.ts","../src/lib/provider.tsx","../src/components/price-tag/price-tag.tsx","../src/components/availability-badge/availability-badge.tsx","../src/components/product-card/product-card.tsx","../src/components/product-grid/product-grid.tsx","../src/components/category-filter/category-filter.tsx","../src/components/product-gallery/product-gallery.tsx","../src/views/shop-view.tsx","../src/views/product-detail-view.tsx","../src/views/featured-products.tsx","../src/cart/cart-reducer.ts","../src/cart/cart-storage.ts","../src/cart/cart-provider.tsx","../src/components/add-to-cart-button/add-to-cart-button.tsx","../src/components/cart-line-item/cart-line-item.tsx","../src/lib/parse-duration.ts","../src/components/cart-drawer/use-drawer-presence.ts","../src/components/cart-summary/cart-summary.tsx","../src/components/cart-drawer/cart-drawer.tsx","../src/components/cart-button/cart-button.tsx"],"sourcesContent":["export interface StorefrontTheme {\n colorBg?: string;\n colorSurface?: string;\n colorFg?: string;\n colorMuted?: string;\n colorAccent?: string;\n colorAccentFg?: string;\n colorBorder?: string;\n colorSold?: string;\n radius?: string;\n fontDisplay?: string;\n fontBody?: string;\n spaceUnit?: string;\n}\n\nconst VAR_NAMES: Record<keyof StorefrontTheme, string> = {\n colorBg: '--sf-color-bg',\n colorSurface: '--sf-color-surface',\n colorFg: '--sf-color-fg',\n colorMuted: '--sf-color-muted',\n colorAccent: '--sf-color-accent',\n colorAccentFg: '--sf-color-accent-fg',\n colorBorder: '--sf-color-border',\n colorSold: '--sf-color-sold',\n radius: '--sf-radius',\n fontDisplay: '--sf-font-display',\n fontBody: '--sf-font-body',\n spaceUnit: '--sf-space-unit',\n};\n\nexport function themeToCssVars(theme: StorefrontTheme): Record<string, string> {\n const vars: Record<string, string> = {};\n for (const key of Object.keys(VAR_NAMES) as (keyof StorefrontTheme)[]) {\n const value = theme[key];\n if (value !== undefined) vars[VAR_NAMES[key]] = value;\n }\n return vars;\n}\n","import { createContext, useContext, type ReactNode } from 'react';\n\nexport interface LinkProps {\n href: string;\n children: ReactNode;\n className?: string;\n}\n\nexport interface ImageProps {\n src: string;\n alt: string;\n sizes?: string;\n className?: string;\n priority?: boolean;\n}\n\nexport interface StorefrontConfig {\n renderLink: (props: LinkProps) => ReactNode;\n renderImage: (props: ImageProps) => ReactNode;\n locale: string;\n hrefs: {\n product: (slug: string) => string;\n category: (slug: string) => string;\n };\n}\n\nconst defaults: StorefrontConfig = {\n renderLink: ({ href, children, className }) => (\n <a href={href} className={className}>\n {children}\n </a>\n ),\n renderImage: ({ src, alt, sizes, className, priority }) => (\n <img\n src={src}\n alt={alt}\n sizes={sizes}\n className={className}\n loading={priority ? 'eager' : 'lazy'}\n decoding=\"async\"\n fetchPriority={priority ? 'high' : undefined}\n />\n ),\n locale: 'en-US',\n hrefs: {\n product: (slug) => `/shop/${slug}`,\n category: (slug) => `/shop?category=${slug}`,\n },\n};\n\nconst StorefrontContext = createContext<StorefrontConfig>(defaults);\n\nexport interface StorefrontProviderProps extends Partial<\n Omit<StorefrontConfig, 'hrefs'>\n> {\n hrefs?: Partial<StorefrontConfig['hrefs']>;\n children: ReactNode;\n}\n\nexport function StorefrontProvider({\n children,\n hrefs,\n ...overrides\n}: StorefrontProviderProps) {\n const value: StorefrontConfig = {\n ...defaults,\n ...overrides,\n hrefs: { ...defaults.hrefs, ...hrefs },\n };\n return (\n <StorefrontContext.Provider value={value}>\n {children}\n </StorefrontContext.Provider>\n );\n}\n\nexport function useStorefront(): StorefrontConfig {\n return useContext(StorefrontContext);\n}\n","import { formatPrice } from '../../lib/format-price';\nimport { useStorefront } from '../../lib/provider';\n\nexport interface PriceTagProps {\n priceCents: number;\n currency: string;\n sold?: boolean;\n className?: string;\n}\n\nexport function PriceTag({\n priceCents,\n currency,\n sold = false,\n className,\n}: PriceTagProps) {\n const { locale } = useStorefront();\n const classes = ['sf-price', sold && 'sf-price--sold', className]\n .filter(Boolean)\n .join(' ');\n return (\n <span className={classes}>{formatPrice(priceCents, currency, locale)}</span>\n );\n}\n","import type { ProductAvailability } from '@develemit/commerce-contracts';\n\nexport interface AvailabilityLabels {\n oneOfAKind: string;\n sold: string;\n reserved: string;\n available: string;\n}\n\nexport const defaultAvailabilityLabels: AvailabilityLabels = {\n oneOfAKind: 'One of a kind',\n sold: 'Sold',\n reserved: 'On hold',\n available: 'Available',\n};\n\nexport interface AvailabilityBadgeProps {\n availability: ProductAvailability;\n quantity: number;\n labels?: Partial<AvailabilityLabels>;\n className?: string;\n}\n\nexport function AvailabilityBadge({\n availability,\n quantity,\n labels,\n className,\n}: AvailabilityBadgeProps) {\n const text = { ...defaultAvailabilityLabels, ...labels };\n let variant: string;\n let label: string;\n if (availability === 'sold') {\n variant = 'sold';\n label = text.sold;\n } else if (availability === 'reserved') {\n variant = 'reserved';\n label = text.reserved;\n } else if (quantity === 1) {\n variant = 'unique';\n label = text.oneOfAKind;\n } else {\n variant = 'available';\n label = text.available;\n }\n const classes = ['sf-badge', `sf-badge--${variant}`, className]\n .filter(Boolean)\n .join(' ');\n return (\n <span role=\"status\" className={classes}>\n {label}\n </span>\n );\n}\n","import type { ProductCard as ProductCardData } from '@develemit/commerce-contracts';\nimport { useStorefront } from '../../lib/provider';\nimport {\n AvailabilityBadge,\n type AvailabilityLabels,\n} from '../availability-badge/availability-badge';\nimport { PriceTag } from '../price-tag/price-tag';\n\nexport interface ProductCardProps {\n product: ProductCardData;\n labels?: Partial<AvailabilityLabels>;\n sizes?: string;\n priority?: boolean;\n}\n\nexport function ProductCard({\n product,\n labels,\n sizes,\n priority,\n}: ProductCardProps) {\n const { renderLink, renderImage, hrefs } = useStorefront();\n const sold = product.availability === 'sold';\n const image = product.images[0];\n const classes = ['sf-card', sold && 'sf-card--sold']\n .filter(Boolean)\n .join(' ');\n return (\n <article className={classes}>\n {renderLink({\n href: hrefs.product(product.slug),\n className: 'sf-card__link',\n children: (\n <>\n <div className=\"sf-card__media\">\n {image ? (\n renderImage({\n src: image.url,\n alt: image.alt,\n sizes,\n className: 'sf-card__image',\n priority,\n })\n ) : (\n <div className=\"sf-card__placeholder\" aria-hidden=\"true\" />\n )}\n </div>\n <div className=\"sf-card__body\">\n <h3 className=\"sf-card__title\">{product.name}</h3>\n <PriceTag\n priceCents={product.priceCents}\n currency={product.currency}\n sold={sold}\n />\n <AvailabilityBadge\n availability={product.availability}\n quantity={product.quantity}\n labels={labels}\n />\n </div>\n </>\n ),\n })}\n </article>\n );\n}\n","import type { ReactNode } from 'react';\nimport type { ProductCard as ProductCardData } from '@develemit/commerce-contracts';\nimport type { AvailabilityLabels } from '../availability-badge/availability-badge';\nimport { ProductCard } from '../product-card/product-card';\n\nexport interface ProductGridProps {\n products: ProductCardData[];\n emptyState?: ReactNode;\n labels?: Partial<AvailabilityLabels>;\n priorityCount?: number;\n}\n\nexport function ProductGrid({\n products,\n emptyState,\n labels,\n priorityCount = 0,\n}: ProductGridProps) {\n if (products.length === 0) {\n return (\n <div className=\"sf-grid-empty\">{emptyState ?? 'No products found.'}</div>\n );\n }\n return (\n <ul className=\"sf-grid\">\n {products.map((product, index) => (\n <li key={product.id} className=\"sf-grid__item\">\n <ProductCard\n product={product}\n labels={labels}\n priority={index < priorityCount}\n />\n </li>\n ))}\n </ul>\n );\n}\n","import type { Category } from '@develemit/commerce-contracts';\nimport { useStorefront } from '../../lib/provider';\n\nexport interface CategoryFilterProps {\n categories: Category[];\n selected?: string;\n onSelect?: (slug: string | undefined) => void;\n allLabel?: string;\n label?: string;\n formatLabel?: (category: Category) => string;\n sortCategories?: (a: Category, b: Category) => number;\n}\n\nexport function CategoryFilter({\n categories,\n selected,\n onSelect,\n allLabel = 'All',\n label = 'Categories',\n formatLabel,\n sortCategories,\n}: CategoryFilterProps) {\n const { renderLink, hrefs } = useStorefront();\n const ordered = sortCategories\n ? [...categories].sort(sortCategories)\n : categories;\n const controlled = onSelect !== undefined;\n\n const item = (slug: string | undefined, text: string, href: string) => {\n const active = selected === slug;\n const className = `sf-filter__item${active ? ' sf-filter__item--active' : ''}`;\n return (\n <li key={slug ?? '__all'}>\n {controlled ? (\n <button\n type=\"button\"\n className={className}\n aria-pressed={active}\n onClick={() => onSelect(slug)}\n >\n {text}\n </button>\n ) : (\n renderLink({\n href,\n className,\n children: text,\n })\n )}\n </li>\n );\n };\n\n return (\n <nav aria-label={label} className=\"sf-filter\">\n <ul className=\"sf-filter__list\">\n {item(undefined, allLabel, hrefs.category(''))}\n {ordered.map((c) =>\n item(\n c.slug,\n formatLabel ? formatLabel(c) : c.label,\n hrefs.category(c.slug),\n ),\n )}\n </ul>\n </nav>\n );\n}\n","import { useState, type KeyboardEvent } from 'react';\nimport type { ProductImage } from '@develemit/commerce-contracts';\nimport { useStorefront } from '../../lib/provider';\n\nexport interface ProductGalleryProps {\n images: ProductImage[];\n sizes?: string;\n}\n\nexport function ProductGallery({ images, sizes }: ProductGalleryProps) {\n const { renderImage } = useStorefront();\n const [active, setActive] = useState(0);\n\n if (images.length === 0) return null;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'ArrowRight') {\n setActive((i) => (i + 1) % images.length);\n } else if (event.key === 'ArrowLeft') {\n setActive((i) => (i - 1 + images.length) % images.length);\n } else if (event.key === 'Home') {\n setActive(0);\n } else if (event.key === 'End') {\n setActive(images.length - 1);\n } else {\n return;\n }\n event.preventDefault();\n };\n\n return (\n <div\n className=\"sf-gallery\"\n role=\"group\"\n aria-roledescription=\"carousel\"\n aria-label=\"Product images\"\n tabIndex={0}\n onKeyDown={onKeyDown}\n >\n <div className=\"sf-gallery__stage\">\n {images.map((image, index) => (\n <div\n key={image.url}\n className=\"sf-gallery__slide\"\n hidden={index !== active}\n >\n {renderImage({\n src: image.url,\n alt: image.alt,\n sizes,\n priority: index === active,\n className: 'sf-gallery__image',\n })}\n </div>\n ))}\n </div>\n {images.length > 1 && (\n <div className=\"sf-gallery__thumbs\">\n {images.map((image, index) => (\n <button\n key={image.url}\n type=\"button\"\n className={`sf-gallery__thumb${index === active ? ' sf-gallery__thumb--active' : ''}`}\n aria-label={`Show image ${index + 1} of ${images.length}`}\n aria-current={index === active}\n onClick={() => setActive(index)}\n >\n {renderImage({\n src: image.url,\n alt: '',\n className: 'sf-gallery__thumb-image',\n })}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport type { Category, ProductCard } from '@develemit/commerce-contracts';\nimport { CategoryFilter } from '../components/category-filter/category-filter';\nimport { ProductGrid } from '../components/product-grid/product-grid';\nimport type { AvailabilityLabels } from '../components/availability-badge/availability-badge';\nimport { useStorefront } from '../lib/provider';\nimport { sortForDisplay } from './sort-for-display';\n\nexport interface ShopViewSlots {\n header?: ReactNode;\n intro?: ReactNode;\n emptyState?: ReactNode;\n}\n\nexport interface ShopViewProps {\n products: ProductCard[];\n categories: Category[];\n activeCategory?: string;\n slots?: ShopViewSlots;\n labels?: Partial<AvailabilityLabels>;\n allLabel?: string;\n formatCategoryLabel?: (category: Category) => string;\n sortCategories?: (a: Category, b: Category) => number;\n nextHref?: string;\n loadMoreLabel?: string;\n}\n\nexport function ShopView({\n products,\n categories,\n activeCategory,\n slots = {},\n labels,\n allLabel,\n formatCategoryLabel,\n sortCategories,\n nextHref,\n loadMoreLabel = 'Load more',\n}: ShopViewProps) {\n const { renderLink } = useStorefront();\n return (\n <div className=\"sf-shop\">\n {slots.header}\n {slots.intro}\n <CategoryFilter\n categories={categories}\n selected={activeCategory}\n allLabel={allLabel}\n formatLabel={formatCategoryLabel}\n sortCategories={sortCategories}\n />\n <ProductGrid\n products={sortForDisplay(products)}\n emptyState={slots.emptyState}\n labels={labels}\n priorityCount={6}\n />\n {nextHref && (\n <div className=\"sf-shop__pager\">\n {renderLink({\n href: nextHref,\n className: 'sf-shop__more',\n children: loadMoreLabel,\n })}\n </div>\n )}\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport type { Product } from '@develemit/commerce-contracts';\nimport {\n AvailabilityBadge,\n type AvailabilityLabels,\n} from '../components/availability-badge/availability-badge';\nimport { PriceTag } from '../components/price-tag/price-tag';\nimport { ProductGallery } from '../components/product-gallery/product-gallery';\n\nexport interface ProductDetailViewSlots {\n actions?: ReactNode;\n afterDetails?: ReactNode;\n}\n\nexport interface ProductDetailViewProps {\n product: Product;\n slots?: ProductDetailViewSlots;\n labels?: Partial<AvailabilityLabels>;\n}\n\nexport function ProductDetailView({\n product,\n slots = {},\n labels,\n}: ProductDetailViewProps) {\n return (\n <article className=\"sf-detail\">\n <ProductGallery images={product.images} />\n <div className=\"sf-detail__body\">\n <h1 className=\"sf-detail__title\">{product.name}</h1>\n <PriceTag priceCents={product.priceCents} currency={product.currency} />\n <AvailabilityBadge\n availability={product.availability}\n quantity={product.quantity}\n labels={labels}\n />\n <p className=\"sf-detail__description\">{product.description}</p>\n {(product.materials || product.dimensions) && (\n <dl className=\"sf-detail__specs\">\n {product.materials && (\n <>\n <dt>Materials</dt>\n <dd>{product.materials}</dd>\n </>\n )}\n {product.dimensions && (\n <>\n <dt>Dimensions</dt>\n <dd>{product.dimensions}</dd>\n </>\n )}\n </dl>\n )}\n {slots.actions && (\n <div className=\"sf-detail__actions\">{slots.actions}</div>\n )}\n {slots.afterDetails}\n </div>\n </article>\n );\n}\n","import type { ProductCard } from '@develemit/commerce-contracts';\nimport type { AvailabilityLabels } from '../components/availability-badge/availability-badge';\nimport { ProductGrid } from '../components/product-grid/product-grid';\n\nexport interface FeaturedProductsProps {\n products: ProductCard[];\n heading?: string;\n labels?: Partial<AvailabilityLabels>;\n}\n\nexport function FeaturedProducts({\n products,\n heading = 'Featured',\n labels,\n}: FeaturedProductsProps) {\n if (products.length === 0) return null;\n return (\n <section className=\"sf-featured\">\n <h2 className=\"sf-featured__heading\">{heading}</h2>\n <ProductGrid products={products} labels={labels} priorityCount={6} />\n </section>\n );\n}\n","import type { CartLine } from '@develemit/commerce-contracts';\n\nexport interface CartState {\n lines: CartLine[];\n}\n\nexport type CartAction =\n | { type: 'add'; line: CartLine }\n | { type: 'remove'; productId: string }\n | { type: 'setQuantity'; productId: string; quantity: number }\n | { type: 'clear' }\n | { type: 'hydrate'; state: CartState };\n\nexport interface AddResult {\n state: CartState;\n added: boolean;\n capped: boolean;\n reason?: 'currency-mismatch';\n}\n\nexport const emptyCart: CartState = { lines: [] };\n\nexport function addLine(state: CartState, line: CartLine): AddResult {\n const first = state.lines[0];\n if (first && first.currency !== line.currency) {\n return { state, added: false, capped: false, reason: 'currency-mismatch' };\n }\n const existing = state.lines.find((l) => l.productId === line.productId);\n if (!existing) {\n const quantity = Math.min(line.quantity, line.maxQuantity);\n return {\n state: { lines: [...state.lines, { ...line, quantity }] },\n added: true,\n capped: quantity < line.quantity,\n };\n }\n if (existing.quantity >= existing.maxQuantity) {\n return { state, added: false, capped: true };\n }\n const quantity = Math.min(\n existing.quantity + line.quantity,\n existing.maxQuantity,\n );\n return {\n state: {\n lines: state.lines.map((l) =>\n l.productId === line.productId ? { ...l, quantity } : l,\n ),\n },\n added: true,\n capped: existing.quantity + line.quantity > existing.maxQuantity,\n };\n}\n\nexport function cartReducer(state: CartState, action: CartAction): CartState {\n switch (action.type) {\n case 'add':\n return addLine(state, action.line).state;\n case 'remove':\n return {\n lines: state.lines.filter((l) => l.productId !== action.productId),\n };\n case 'setQuantity': {\n if (action.quantity <= 0) {\n return cartReducer(state, {\n type: 'remove',\n productId: action.productId,\n });\n }\n return {\n lines: state.lines.map((l) =>\n l.productId === action.productId\n ? { ...l, quantity: Math.min(action.quantity, l.maxQuantity) }\n : l,\n ),\n };\n }\n case 'clear':\n return emptyCart;\n case 'hydrate':\n return action.state;\n }\n}\n\nexport function subtotalCents(state: CartState): number {\n return state.lines.reduce((sum, l) => sum + l.priceCents * l.quantity, 0);\n}\n\nexport function itemCount(state: CartState): number {\n return state.lines.reduce((sum, l) => sum + l.quantity, 0);\n}\n","import { cartLineSchema } from '@develemit/commerce-contracts';\nimport { emptyCart, type CartState } from './cart-reducer';\n\nexport interface CartStorage {\n load: () => CartState | Promise<CartState>;\n save: (state: CartState) => void | Promise<void>;\n}\n\nexport function localStorageCartStorage(key = 'sf-cart'): CartStorage {\n return {\n load() {\n if (typeof window === 'undefined') return emptyCart;\n try {\n const raw = window.localStorage.getItem(key);\n if (!raw) return emptyCart;\n const parsed: unknown = JSON.parse(raw);\n const lines = Array.isArray((parsed as CartState)?.lines)\n ? (parsed as CartState).lines\n : [];\n const valid = lines.flatMap((line) => {\n const result = cartLineSchema.safeParse(line);\n return result.success ? [result.data] : [];\n });\n return { lines: valid };\n } catch {\n return emptyCart;\n }\n },\n save(state) {\n if (typeof window === 'undefined') return;\n try {\n window.localStorage.setItem(key, JSON.stringify(state));\n } catch {\n // storage full or blocked: the cart simply stays in memory\n }\n },\n };\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useReducer,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport type { CartLine } from '@develemit/commerce-contracts';\nimport {\n addLine,\n cartReducer,\n emptyCart,\n itemCount,\n subtotalCents,\n type AddResult,\n type CartState,\n} from './cart-reducer';\nimport { localStorageCartStorage, type CartStorage } from './cart-storage';\n\nexport interface CartContextValue {\n lines: CartLine[];\n itemCount: number;\n subtotalCents: number;\n currency: string | null;\n hydrated: boolean;\n isOpen: boolean;\n open: () => void;\n close: () => void;\n add: (line: CartLine) => AddResult;\n remove: (productId: string) => void;\n setQuantity: (productId: string, quantity: number) => void;\n clear: () => void;\n}\n\nconst CartContext = createContext<CartContextValue | null>(null);\n\nexport interface CartProviderProps {\n storage?: CartStorage;\n children: ReactNode;\n}\n\nconst defaultStorage = localStorageCartStorage();\n\nexport function CartProvider({\n storage = defaultStorage,\n children,\n}: CartProviderProps) {\n const [state, dispatch] = useReducer(cartReducer, emptyCart);\n const [hydrated, setHydrated] = useState(false);\n const [isOpen, setOpen] = useState(false);\n const stateRef = useRef<CartState>(state);\n useEffect(() => {\n stateRef.current = state;\n }, [state]);\n\n useEffect(() => {\n let cancelled = false;\n Promise.resolve(storage.load()).then((loaded) => {\n if (cancelled) return;\n dispatch({ type: 'hydrate', state: loaded });\n setHydrated(true);\n });\n return () => {\n cancelled = true;\n };\n }, [storage]);\n\n useEffect(() => {\n if (hydrated) void storage.save(state);\n }, [hydrated, state, storage]);\n\n const add = useCallback((line: CartLine) => {\n const result = addLine(stateRef.current, line);\n if (result.added) {\n stateRef.current = result.state;\n dispatch({ type: 'add', line });\n }\n return result;\n }, []);\n\n const value = useMemo<CartContextValue>(\n () => ({\n lines: state.lines,\n itemCount: itemCount(state),\n subtotalCents: subtotalCents(state),\n currency: state.lines[0]?.currency ?? null,\n hydrated,\n isOpen,\n open: () => setOpen(true),\n close: () => setOpen(false),\n add,\n remove: (productId) => dispatch({ type: 'remove', productId }),\n setQuantity: (productId, quantity) =>\n dispatch({ type: 'setQuantity', productId, quantity }),\n clear: () => dispatch({ type: 'clear' }),\n }),\n [state, hydrated, isOpen, add],\n );\n\n return <CartContext.Provider value={value}>{children}</CartContext.Provider>;\n}\n\nexport function useCart(): CartContextValue {\n const ctx = useContext(CartContext);\n if (!ctx) throw new Error('useCart must be used inside <CartProvider>');\n return ctx;\n}\n","import type { Product } from '@develemit/commerce-contracts';\nimport { useCart } from '../../cart/cart-provider';\n\nexport interface AddToCartLabels {\n add: string;\n inCart: string;\n unavailable: string;\n}\n\nexport const defaultAddToCartLabels: AddToCartLabels = {\n add: 'Add to cart',\n inCart: 'In your cart',\n unavailable: 'Unavailable',\n};\n\nexport interface AddToCartButtonProps {\n product: Product;\n labels?: Partial<AddToCartLabels>;\n openOnAdd?: boolean;\n className?: string;\n}\n\nexport function AddToCartButton({\n product,\n labels,\n openOnAdd = true,\n className,\n}: AddToCartButtonProps) {\n const cart = useCart();\n const text = { ...defaultAddToCartLabels, ...labels };\n const inCart =\n cart.lines.find((l) => l.productId === product.id)?.quantity ?? 0;\n const unavailable = product.availability !== 'available';\n const atCap = inCart >= product.quantity;\n const disabled = !cart.hydrated || unavailable || atCap;\n const label = unavailable ? text.unavailable : atCap ? text.inCart : text.add;\n\n function handleClick() {\n const result = cart.add({\n productId: product.id,\n slug: product.slug,\n name: product.name,\n priceCents: product.priceCents,\n currency: product.currency,\n imageUrl: product.images[0]?.url,\n quantity: 1,\n maxQuantity: product.quantity,\n });\n if (result.added && openOnAdd) cart.open();\n }\n\n return (\n <button\n type=\"button\"\n className={['sf-button', className].filter(Boolean).join(' ')}\n disabled={disabled}\n onClick={handleClick}\n >\n {label}\n </button>\n );\n}\n","import type { CartLine } from '@develemit/commerce-contracts';\nimport { useCart } from '../../cart/cart-provider';\nimport { formatPrice } from '../../lib/format-price';\nimport { useStorefront } from '../../lib/provider';\n\nexport interface CartLineItemLabels {\n remove: string;\n quantity: string;\n}\n\nexport const defaultCartLineItemLabels: CartLineItemLabels = {\n remove: 'Remove',\n quantity: 'Quantity',\n};\n\nexport interface CartLineItemProps {\n line: CartLine;\n labels?: Partial<CartLineItemLabels>;\n}\n\nexport function CartLineItem({ line, labels }: CartLineItemProps) {\n const { remove, setQuantity } = useCart();\n const { locale, renderLink, renderImage, hrefs } = useStorefront();\n const text = { ...defaultCartLineItemLabels, ...labels };\n const editable = line.maxQuantity > 1;\n return (\n <li className=\"sf-cart-line\">\n {line.imageUrl &&\n renderImage({\n src: line.imageUrl,\n alt: '',\n sizes: '80px',\n className: 'sf-cart-line__image',\n })}\n <div className=\"sf-cart-line__body\">\n {renderLink({\n href: hrefs.product(line.slug),\n className: 'sf-cart-line__name',\n children: line.name,\n })}\n <span className=\"sf-cart-line__price\">\n {formatPrice(line.priceCents * line.quantity, line.currency, locale)}\n </span>\n {editable && (\n <label className=\"sf-cart-line__qty\">\n {text.quantity}\n <input\n type=\"number\"\n min={1}\n max={line.maxQuantity}\n value={line.quantity}\n onChange={(e) =>\n setQuantity(line.productId, Number(e.target.value))\n }\n />\n </label>\n )}\n <button\n type=\"button\"\n className=\"sf-link-button sf-cart-line__remove\"\n onClick={() => remove(line.productId)}\n aria-label={`${text.remove} ${line.name}`}\n >\n {text.remove}\n </button>\n </div>\n </li>\n );\n}\n","export function parseDurationMs(value: string): number {\n const match = /^\\s*(-?\\d*\\.?\\d+)\\s*(ms|s)\\s*$/.exec(value);\n if (!match) return 0;\n const amount = Number(match[1]);\n return Math.max(0, match[2] === 's' ? amount * 1000 : amount);\n}\n","import { useEffect, useState, type RefObject } from 'react';\nimport { parseDurationMs } from '../../lib/parse-duration';\n\nexport function useDrawerPresence(\n isOpen: boolean,\n backdropRef: RefObject<HTMLElement | null>,\n) {\n const [durationMs, setDurationMs] = useState(0);\n const [wasOpen, setWasOpen] = useState(isOpen);\n const [lingering, setLingering] = useState(false);\n\n if (wasOpen !== isOpen) {\n setWasOpen(isOpen);\n setLingering(!isOpen && durationMs > 0);\n }\n\n useEffect(() => {\n if (!isOpen || !backdropRef.current) return;\n setDurationMs(\n parseDurationMs(\n getComputedStyle(backdropRef.current).getPropertyValue(\n '--sf-motion-duration',\n ),\n ),\n );\n }, [isOpen, backdropRef]);\n\n useEffect(() => {\n if (!lingering) return;\n const timer = setTimeout(() => setLingering(false), durationMs);\n return () => clearTimeout(timer);\n }, [lingering, durationMs]);\n\n return { mounted: isOpen || lingering, state: isOpen ? 'open' : 'closed' };\n}\n","import { useCart } from '../../cart/cart-provider';\nimport { formatPrice } from '../../lib/format-price';\nimport { useStorefront } from '../../lib/provider';\n\nexport interface CartSummaryLabels {\n subtotal: string;\n}\n\nexport interface CartSummaryProps {\n onCheckout?: () => void;\n checkoutLabel?: string;\n checkoutDisabled?: boolean;\n labels?: Partial<CartSummaryLabels>;\n}\n\nexport function CartSummary({\n onCheckout,\n checkoutLabel = 'Checkout',\n checkoutDisabled = false,\n labels,\n}: CartSummaryProps) {\n const cart = useCart();\n const { locale } = useStorefront();\n const subtotal = labels?.subtotal ?? 'Subtotal';\n return (\n <div className=\"sf-cart-summary\">\n <p className=\"sf-cart-summary__row\">\n <span>{subtotal}</span>\n <span className=\"sf-price\">\n {formatPrice(cart.subtotalCents, cart.currency ?? 'USD', locale)}\n </span>\n </p>\n <button\n type=\"button\"\n className=\"sf-button\"\n disabled={checkoutDisabled || !onCheckout || cart.lines.length === 0}\n onClick={onCheckout}\n >\n {checkoutLabel}\n </button>\n </div>\n );\n}\n","import { useEffect, useRef, type KeyboardEvent, type ReactNode } from 'react';\nimport { useCart } from '../../cart/cart-provider';\nimport { CartLineItem } from '../cart-line-item/cart-line-item';\nimport { useDrawerPresence } from './use-drawer-presence';\nimport {\n CartSummary,\n type CartSummaryProps,\n} from '../cart-summary/cart-summary';\n\nexport interface CartDrawerLabels {\n title: string;\n close: string;\n empty: string;\n}\n\nexport const defaultCartDrawerLabels: CartDrawerLabels = {\n title: 'Your cart',\n close: 'Close',\n empty: 'Your cart is empty.',\n};\n\nexport interface CartDrawerProps {\n labels?: Partial<CartDrawerLabels>;\n summary?: CartSummaryProps;\n slots?: CartDrawerSlots;\n}\n\nexport interface CartDrawerSlots {\n empty?: ReactNode;\n summaryNote?: ReactNode;\n}\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\nexport function CartDrawer({ labels, summary, slots }: CartDrawerProps) {\n const cart = useCart();\n const text = { ...defaultCartDrawerLabels, ...labels };\n const panelRef = useRef<HTMLDivElement>(null);\n const backdropRef = useRef<HTMLDivElement>(null);\n const { isOpen } = cart;\n const presence = useDrawerPresence(isOpen, backdropRef);\n\n useEffect(() => {\n if (!isOpen) return;\n const trigger = document.activeElement as HTMLElement | null;\n panelRef.current?.querySelector<HTMLElement>(FOCUSABLE)?.focus();\n return () => trigger?.focus();\n }, [isOpen]);\n\n if (!presence.mounted) return null;\n\n function handleKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n if (event.key === 'Escape') {\n event.stopPropagation();\n cart.close();\n return;\n }\n if (event.key !== 'Tab') return;\n const items = Array.from(\n panelRef.current?.querySelectorAll<HTMLElement>(FOCUSABLE) ?? [],\n );\n if (items.length === 0) return;\n const first = items[0];\n const last = items[items.length - 1];\n if (event.shiftKey && document.activeElement === first) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n }\n\n return (\n <div\n ref={backdropRef}\n className=\"sf-drawer-backdrop\"\n data-state={presence.state}\n onClick={cart.close}\n >\n <div\n ref={panelRef}\n className=\"sf-drawer\"\n data-state={presence.state}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"sf-drawer-title\"\n onKeyDown={handleKeyDown}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"sf-drawer__header\">\n <h2 id=\"sf-drawer-title\" className=\"sf-drawer__title\">\n {text.title}\n </h2>\n <button\n type=\"button\"\n className=\"sf-drawer__close\"\n aria-label={text.close}\n onClick={cart.close}\n >\n <span aria-hidden=\"true\">×</span>\n </button>\n </div>\n {cart.lines.length === 0 ? (\n <div className=\"sf-drawer__empty\">\n {slots?.empty ?? <p>{text.empty}</p>}\n </div>\n ) : (\n <>\n <ul className=\"sf-drawer__lines\">\n {cart.lines.map((line) => (\n <CartLineItem key={line.productId} line={line} />\n ))}\n </ul>\n <CartSummary {...summary} />\n {slots?.summaryNote && (\n <div className=\"sf-drawer__note\">{slots.summaryNote}</div>\n )}\n </>\n )}\n </div>\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport { useCart } from '../../cart/cart-provider';\n\nexport interface CartButtonProps {\n label?: string;\n className?: string;\n icon?: ReactNode;\n labelHidden?: boolean;\n hideZeroCount?: boolean;\n}\n\nexport function CartButton({\n label = 'Cart',\n className,\n icon,\n labelHidden = false,\n hideZeroCount = false,\n}: CartButtonProps) {\n const cart = useCart();\n const count = cart.hydrated ? cart.itemCount : 0;\n const showCount = !(hideZeroCount && count === 0);\n const ariaLabel = showCount\n ? labelHidden\n ? `${label}, ${cart.itemCount} items`\n : undefined\n : `${label}, empty`;\n return (\n <button\n type=\"button\"\n className={['sf-cart-button', className].filter(Boolean).join(' ')}\n aria-haspopup=\"dialog\"\n aria-label={ariaLabel}\n onClick={cart.open}\n >\n {icon}\n <span className={labelHidden ? 'sf-visually-hidden' : undefined}>\n {label}\n </span>\n {showCount && (\n <span\n className=\"sf-cart-button__count\"\n aria-label={`${cart.itemCount} items`}\n >\n {count}\n </span>\n )}\n </button>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1 @@
1
1
  export declare function formatPrice(cents: number, currency: string, locale?: string): string;
2
- //# sourceMappingURL=format-price.d.ts.map
@@ -1,2 +1 @@
1
1
  export declare function parseDurationMs(value: string): number;
2
- //# sourceMappingURL=parse-duration.d.ts.map
@@ -26,4 +26,3 @@ export interface StorefrontProviderProps extends Partial<Omit<StorefrontConfig,
26
26
  }
27
27
  export declare function StorefrontProvider({ children, hrefs, ...overrides }: StorefrontProviderProps): import('react').JSX.Element;
28
28
  export declare function useStorefront(): StorefrontConfig;
29
- //# sourceMappingURL=provider.d.ts.map
@@ -13,4 +13,3 @@ export interface StorefrontTheme {
13
13
  spaceUnit?: string;
14
14
  }
15
15
  export declare function themeToCssVars(theme: StorefrontTheme): Record<string, string>;
16
- //# sourceMappingURL=theme.d.ts.map
@@ -11,3 +11,5 @@ function t(e) {
11
11
  return [...e].sort((e, n) => t(e) - t(n));
12
12
  }
13
13
  export { e as n, t };
14
+
15
+ //# sourceMappingURL=sort-for-display-Cj6GMeCY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sort-for-display-Cj6GMeCY.js","names":["formatPrice","locale","cents","sortForDisplay","rank","products","a","b"],"sources":["../src/lib/format-price.ts","../src/views/sort-for-display.ts"],"sourcesContent":["export function formatPrice(\n cents: number,\n currency: string,\n locale = 'en-US',\n): string {\n return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(\n cents / 100,\n );\n}\n","import type { ProductCard } from '@develemit/commerce-contracts';\n\nexport function sortForDisplay(products: ProductCard[]): ProductCard[] {\n const rank = (p: ProductCard) => (p.availability === 'sold' ? 1 : 0);\n return [...products].sort((a, b) => rank(a) - rank(b));\n}\n"],"mappings":";AAAA,SAAgBA,EACd,GACA,GACA,IAAS,SACD;CACR,OAAO,IAAI,KAAK,aAAaC,GAAQ;EAAE,OAAO;EAAY;CAAS,CAAC,CAAC,CAAC,OACpEC,IAAQ,GACV;AACF;;ACNA,SAAgBC,EAAe,GAAwC;CACrE,IAAMC,KAAQ,MAAoB,IAAE,iBAAiB;CACrD,OAAO,CAAC,GAAGC,CAAQ,CAAC,CAAC,MAAM,GAAG,MAAMD,EAAKE,CAAC,IAAIF,EAAKG,CAAC,CAAC;AACvD"}
package/dist/styles.css CHANGED
@@ -309,6 +309,28 @@
309
309
  font-size: 0.75rem;
310
310
  text-align: center;
311
311
  }
312
+
313
+ .sf-shop__pager {
314
+ display: flex;
315
+ justify-content: center;
316
+ }
317
+ .sf-shop__more {
318
+ display: inline-flex;
319
+ align-items: center;
320
+ justify-content: center;
321
+ min-height: 44px;
322
+ padding: 0 calc(var(--sf-space-unit) * 6);
323
+ border: 1px solid var(--sf-color-accent);
324
+ border-radius: var(--sf-radius);
325
+ background: var(--sf-color-accent);
326
+ color: var(--sf-color-accent-fg);
327
+ font-family: var(--sf-font-body);
328
+ text-decoration: none;
329
+ }
330
+ .sf-shop__more:focus-visible {
331
+ outline: 2px solid var(--sf-color-accent);
332
+ outline-offset: 2px;
333
+ }
312
334
  .sf-drawer-backdrop {
313
335
  position: fixed;
314
336
  inset: 0;
@@ -1,9 +1,8 @@
1
- import { Product } from '@develemit/commerce-contracts';
1
+ import { ProductCard } from '@develemit/commerce-contracts';
2
2
  import { AvailabilityLabels } from '../components/availability-badge/availability-badge';
3
3
  export interface FeaturedProductsProps {
4
- products: Product[];
4
+ products: ProductCard[];
5
5
  heading?: string;
6
6
  labels?: Partial<AvailabilityLabels>;
7
7
  }
8
8
  export declare function FeaturedProducts({ products, heading, labels, }: FeaturedProductsProps): import('react').JSX.Element | null;
9
- //# sourceMappingURL=featured-products.d.ts.map
@@ -11,4 +11,3 @@ export interface ProductDetailViewProps {
11
11
  labels?: Partial<AvailabilityLabels>;
12
12
  }
13
13
  export declare function ProductDetailView({ product, slots, labels, }: ProductDetailViewProps): import('react').JSX.Element;
14
- //# sourceMappingURL=product-detail-view.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { Category, Product } from '@develemit/commerce-contracts';
2
+ import { Category, ProductCard } from '@develemit/commerce-contracts';
3
3
  import { AvailabilityLabels } from '../components/availability-badge/availability-badge';
4
4
  export interface ShopViewSlots {
5
5
  header?: ReactNode;
@@ -7,7 +7,7 @@ export interface ShopViewSlots {
7
7
  emptyState?: ReactNode;
8
8
  }
9
9
  export interface ShopViewProps {
10
- products: Product[];
10
+ products: ProductCard[];
11
11
  categories: Category[];
12
12
  activeCategory?: string;
13
13
  slots?: ShopViewSlots;
@@ -15,6 +15,7 @@ export interface ShopViewProps {
15
15
  allLabel?: string;
16
16
  formatCategoryLabel?: (category: Category) => string;
17
17
  sortCategories?: (a: Category, b: Category) => number;
18
+ nextHref?: string;
19
+ loadMoreLabel?: string;
18
20
  }
19
- export declare function ShopView({ products, categories, activeCategory, slots, labels, allLabel, formatCategoryLabel, sortCategories, }: ShopViewProps): import('react').JSX.Element;
20
- //# sourceMappingURL=shop-view.d.ts.map
21
+ export declare function ShopView({ products, categories, activeCategory, slots, labels, allLabel, formatCategoryLabel, sortCategories, nextHref, loadMoreLabel, }: ShopViewProps): import('react').JSX.Element;
@@ -1,3 +1,2 @@
1
- import { Product } from '@develemit/commerce-contracts';
2
- export declare function sortForDisplay(products: Product[]): Product[];
3
- //# sourceMappingURL=sort-for-display.d.ts.map
1
+ import { ProductCard } from '@develemit/commerce-contracts';
2
+ export declare function sortForDisplay(products: ProductCard[]): ProductCard[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@develemit/storefront",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -14,13 +14,13 @@
14
14
  },
15
15
  "./client": {
16
16
  "types": "./dist/client/index.d.ts",
17
- "import": "./dist/client.js",
18
- "default": "./dist/client.js"
17
+ "import": "./dist/client/index.js",
18
+ "default": "./dist/client/index.js"
19
19
  },
20
20
  "./format": {
21
21
  "types": "./dist/format/index.d.ts",
22
- "import": "./dist/format.js",
23
- "default": "./dist/format.js"
22
+ "import": "./dist/format/index.js",
23
+ "default": "./dist/format/index.js"
24
24
  },
25
25
  "./styles.css": "./dist/styles.css"
26
26
  },
@@ -44,6 +44,6 @@
44
44
  "access": "public"
45
45
  },
46
46
  "dependencies": {
47
- "@develemit/commerce-contracts": "0.2.0"
47
+ "@develemit/commerce-contracts": "0.3.0"
48
48
  }
49
49
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"cart-provider.d.ts","sourceRoot":"","sources":["../../src/cart/cart-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAML,KAAK,SAAS,EAEf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAA2B,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE3E,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,GAAG,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,SAAS,CAAC;IACnC,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAID,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAID,wBAAgB,YAAY,CAAC,EAC3B,OAAwB,EACxB,QAAQ,GACT,EAAE,iBAAiB,+BAsDnB;AAED,wBAAgB,OAAO,IAAI,gBAAgB,CAI1C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"cart-reducer.d.ts","sourceRoot":"","sources":["../../src/cart/cart-reducer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAE9D,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,CAAC;AAE1C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B;AAED,eAAO,MAAM,SAAS,EAAE,SAAyB,CAAC;AAElD,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,CA8BnE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS,CA4B3E;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAEtD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAElD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"cart-storage.d.ts","sourceRoot":"","sources":["../../src/cart/cart-storage.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC3C,IAAI,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED,wBAAgB,uBAAuB,CAAC,GAAG,SAAY,GAAG,WAAW,CA6BpE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"commerce-client.d.ts","sourceRoot":"","sources":["../../src/client/commerce-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,OAAO,EACZ,KAAK,gBAAgB,EACtB,MAAM,+BAA+B,CAAC;AAOvC,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,KAAK,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3D,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,cAAc,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IACtC,cAAc,CAAC,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC3E,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC7D;AAID,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EACP,KAAK,EAAE,SAAkD,GAC1D,EAAE,qBAAqB,GAAG,cAAc,CAsExC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/client/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,gBAAiB,SAAQ,KAAK;IAEvC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM;gBADX,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM;CAKnB;AAED,qBAAa,aAAc,SAAQ,gBAAgB;gBACrC,GAAG,EAAE,MAAM;CAIxB;AAED,qBAAa,qBAAsB,SAAQ,gBAAgB;IAGvD,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE;gBAD7B,GAAG,EAAE,MAAM,EACF,UAAU,EAAE,MAAM,EAAE;CAShC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC"}
package/dist/client.js DELETED
@@ -1,62 +0,0 @@
1
- import { categorySchema as e, checkoutConflictSchema as t, checkoutResponseSchema as n, orderSummarySchema as r, productSchema as i } from "@develemit/commerce-contracts";
2
- // src/client/errors.ts
3
- var a = class extends Error {
4
- status;
5
- url;
6
- constructor(e, t, n) {
7
- super(n ?? `Commerce API request failed (${e}): ${t}`), this.status = e, this.url = t, this.name = "CommerceApiError";
8
- }
9
- }, o = class extends a {
10
- constructor(e) {
11
- super(404, e, `Not found: ${e}`), this.name = "NotFoundError";
12
- }
13
- }, s = class extends a {
14
- productIds;
15
- constructor(e, t) {
16
- super(409, e, `Some items are no longer available: ${t.join(", ")}`), this.productIds = t, this.name = "CheckoutConflictError";
17
- }
18
- };
19
- // src/client/commerce-client.ts
20
- function c({ baseUrl: c, fetch: l = (...e) => globalThis.fetch(...e) }) {
21
- let u = c.replace(/\/+$/, "");
22
- async function d(e, t, n) {
23
- if (t.status === 404) throw new o(e);
24
- if (!t.ok) throw new a(t.status, e);
25
- return n.parse(await t.json());
26
- }
27
- async function f(e, t) {
28
- let n = `${u}${e}`;
29
- return d(n, await l(n, { headers: { accept: "application/json" } }), t);
30
- }
31
- async function p(e) {
32
- let r = `${u}/checkout`, i = await l(r, {
33
- method: "POST",
34
- headers: {
35
- accept: "application/json",
36
- "content-type": "application/json"
37
- },
38
- body: JSON.stringify({ items: e })
39
- });
40
- if (i.status === 409) throw new s(r, t.parse(await i.json()).unavailableProductIds);
41
- return d(r, i, n);
42
- }
43
- return {
44
- listProducts(e = {}) {
45
- let t = new URLSearchParams();
46
- e.category && t.set("category", e.category), e.featured !== void 0 && t.set("featured", String(e.featured));
47
- let n = t.toString();
48
- return f(`/catalog/products${n ? `?${n}` : ""}`, i.array());
49
- },
50
- getProduct(e) {
51
- return f(`/catalog/products/${encodeURIComponent(e)}`, i);
52
- },
53
- listCategories() {
54
- return f("/catalog/categories", e.array());
55
- },
56
- createCheckout: p,
57
- getOrderBySession(e) {
58
- return f(`/orders/session/${encodeURIComponent(e)}`, r);
59
- }
60
- };
61
- }
62
- export { s as CheckoutConflictError, a as CommerceApiError, o as NotFoundError, c as createCommerceClient };
@@ -1 +0,0 @@
1
- {"version":3,"file":"add-to-cart-button.d.ts","sourceRoot":"","sources":["../../../src/components/add-to-cart-button/add-to-cart-button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAG7D,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,sBAAsB,EAAE,eAIpC,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,EAC9B,OAAO,EACP,MAAM,EACN,SAAgB,EAChB,SAAS,GACV,EAAE,oBAAoB,+BAkCtB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"availability-badge.d.ts","sourceRoot":"","sources":["../../../src/components/availability-badge/availability-badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,yBAAyB,EAAE,kBAKvC,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,mBAAmB,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,SAAS,GACV,EAAE,sBAAsB,+BAyBxB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"cart-button.d.ts","sourceRoot":"","sources":["../../../src/components/cart-button/cart-button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,UAAU,CAAC,EACzB,KAAc,EACd,SAAS,EACT,IAAI,EACJ,WAAmB,EACnB,aAAqB,GACtB,EAAE,eAAe,+BA+BjB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"cart-drawer.d.ts","sourceRoot":"","sources":["../../../src/components/cart-drawer/cart-drawer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI9E,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,8BAA8B,CAAC;AAEtC,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,uBAAuB,EAAE,gBAIrC,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,SAAS,CAAC;CACzB;AAKD,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,eAAe,sCAyFrE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-drawer-presence.d.ts","sourceRoot":"","sources":["../../../src/components/cart-drawer/use-drawer-presence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG5D,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,OAAO,EACf,WAAW,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC;;;EA6B3C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"cart-line-item.d.ts","sourceRoot":"","sources":["../../../src/components/cart-line-item/cart-line-item.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAK9D,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,yBAAyB,EAAE,kBAGvC,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACtC;AAED,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,iBAAiB,+BAgD/D"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"cart-summary.d.ts","sourceRoot":"","sources":["../../../src/components/cart-summary/cart-summary.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACrC;AAED,wBAAgB,WAAW,CAAC,EAC1B,UAAU,EACV,aAA0B,EAC1B,gBAAwB,EACxB,MAAM,GACP,EAAE,gBAAgB,+BAsBlB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"category-filter.d.ts","sourceRoot":"","sources":["../../../src/components/category-filter/category-filter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAG9D,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,QAAQ,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,MAAM,CAAC;IAC7C,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,KAAK,MAAM,CAAC;CACvD;AAED,wBAAgB,cAAc,CAAC,EAC7B,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,QAAgB,EAChB,KAAoB,EACpB,WAAW,EACX,cAAc,GACf,EAAE,mBAAmB,+BA8CrB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/components/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAE7D,wBAAgB,WAAW,CAAC,SAAS,GAAE,OAAO,CAAC,OAAO,CAAM,GAAG,OAAO,CAerE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"price-tag.d.ts","sourceRoot":"","sources":["../../../src/components/price-tag/price-tag.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,QAAQ,CAAC,EACvB,UAAU,EACV,QAAQ,EACR,IAAY,EACZ,SAAS,GACV,EAAE,aAAa,+BAQf"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"product-card.d.ts","sourceRoot":"","sources":["../../../src/components/product-card/product-card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,0CAA0C,CAAC;AAGlD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,MAAM,EACN,KAAK,EACL,QAAQ,GACT,EAAE,gBAAgB,+BA6ClB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"product-gallery.d.ts","sourceRoot":"","sources":["../../../src/components/product-gallery/product-gallery.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGlE,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,cAAc,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,mBAAmB,sCAqEpE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"product-grid.d.ts","sourceRoot":"","sources":["../../../src/components/product-grid/product-grid.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAGnF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,UAAU,EACV,MAAM,EACN,aAAiB,GAClB,EAAE,gBAAgB,+BAmBlB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"render-with-cart.d.ts","sourceRoot":"","sources":["../../src/components/render-with-cart.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,wBAAsB,cAAc,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,iBAI1E"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/format/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC"}
package/dist/format.js DELETED
@@ -1 +0,0 @@
1
- export { n as formatPrice, t as sortForDisplay } from "./sort-for-display-Cj6GMeCY.js";
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EACP,YAAY,EACZ,mBAAmB,EACnB,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,YAAY,GACb,MAAM,+BAA+B,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kCAAkC,CAAC;AACjD,cAAc,oDAAoD,CAAC;AACnE,cAAc,wCAAwC,CAAC;AACvD,cAAc,wCAAwC,CAAC;AACvD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,8CAA8C,CAAC;AAC7D,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oDAAoD,CAAC;AACnE,cAAc,sCAAsC,CAAC;AACrD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,wCAAwC,CAAC;AACvD,cAAc,sCAAsC,CAAC"}
@@ -1 +0,0 @@
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"}
@@ -1 +0,0 @@
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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/lib/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,SAAS,CAAC;IAC5C,WAAW,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,SAAS,CAAC;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE;QACL,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;QAClC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;KACpC,CAAC;CACH;AAoBD,MAAM,WAAW,uBAAwB,SAAQ,OAAO,CACtD,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAChC;IACC,KAAK,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,KAAK,EACL,GAAG,SAAS,EACb,EAAE,uBAAuB,+BAWzB;AAED,wBAAgB,aAAa,IAAI,gBAAgB,CAEhD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/lib/theme.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiBD,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO7E"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"featured-products.d.ts","sourceRoot":"","sources":["../../src/views/featured-products.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AAG9F,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACtC;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,OAAoB,EACpB,MAAM,GACP,EAAE,qBAAqB,sCAQvB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"product-detail-view.d.ts","sourceRoot":"","sources":["../../src/views/product-detail-view.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,qDAAqD,CAAC;AAI7D,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,YAAY,CAAC,EAAE,SAAS,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,sBAAsB,CAAC;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACtC;AAED,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,KAAU,EACV,MAAM,GACP,EAAE,sBAAsB,+BAoCxB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"shop-view.d.ts","sourceRoot":"","sources":["../../src/views/shop-view.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAGvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AAG9F,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,EAAE,QAAQ,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,MAAM,CAAC;IACrD,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,KAAK,MAAM,CAAC;CACvD;AAED,wBAAgB,QAAQ,CAAC,EACvB,QAAQ,EACR,UAAU,EACV,cAAc,EACd,KAAU,EACV,MAAM,EACN,QAAQ,EACR,mBAAmB,EACnB,cAAc,GACf,EAAE,aAAa,+BAoBf"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"sort-for-display.d.ts","sourceRoot":"","sources":["../../src/views/sort-for-display.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAE7D,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAG7D"}