@zappie/theme-base 0.1.0 → 0.1.2

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 (129) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +26 -53
  3. package/dist/address.js +99 -2
  4. package/dist/address.js.map +7 -1
  5. package/dist/cart/address-sheet.js +143 -0
  6. package/dist/cart/address-sheet.js.map +7 -0
  7. package/dist/cart/cart-issues.js +72 -0
  8. package/dist/cart/cart-issues.js.map +7 -0
  9. package/dist/cart/cart-line-groups.js +34 -0
  10. package/dist/cart/cart-line-groups.js.map +7 -0
  11. package/dist/{chunk-FB5DRCU7.js → cart/cart-line.js} +9 -70
  12. package/dist/cart/cart-line.js.map +7 -0
  13. package/dist/cart/cart-lines.js +27 -0
  14. package/dist/cart/cart-lines.js.map +7 -0
  15. package/dist/cart/cart-schedule.js +24 -0
  16. package/dist/cart/cart-schedule.js.map +7 -0
  17. package/dist/cart/cart-sheet.js +35 -0
  18. package/dist/cart/cart-sheet.js.map +7 -0
  19. package/dist/cart/checkout-cta.js +81 -0
  20. package/dist/cart/checkout-cta.js.map +7 -0
  21. package/dist/cart/checkout-state.js +74 -0
  22. package/dist/cart/checkout-state.js.map +7 -0
  23. package/dist/cart/clear-cart.js +44 -0
  24. package/dist/cart/clear-cart.js.map +7 -0
  25. package/dist/cart/customer-details.js +70 -0
  26. package/dist/cart/customer-details.js.map +7 -0
  27. package/dist/cart/delivery-distance.js +22 -0
  28. package/dist/cart/delivery-distance.js.map +7 -0
  29. package/dist/cart/empty-cart.js +14 -0
  30. package/dist/cart/empty-cart.js.map +7 -0
  31. package/dist/cart/fulfilment-panel.js +83 -0
  32. package/dist/cart/fulfilment-panel.js.map +7 -0
  33. package/dist/cart/line-editor.js +35 -0
  34. package/dist/cart/line-editor.js.map +7 -0
  35. package/dist/cart/line-options.js +96 -0
  36. package/dist/cart/line-options.js.map +7 -0
  37. package/dist/cart/loading.js +17 -0
  38. package/dist/cart/loading.js.map +7 -0
  39. package/dist/cart/promo-sheet.js +103 -0
  40. package/dist/cart/promo-sheet.js.map +7 -0
  41. package/dist/cart/region-picker.js +40 -0
  42. package/dist/cart/region-picker.js.map +7 -0
  43. package/dist/cart/rewards-sheet.js +86 -0
  44. package/dist/cart/rewards-sheet.js.map +7 -0
  45. package/dist/cart/schedule-sheet.js +87 -0
  46. package/dist/cart/schedule-sheet.js.map +7 -0
  47. package/dist/{chunk-JFEI2OUZ.js → cart/theme-class.js} +7 -5
  48. package/dist/cart/theme-class.js.map +7 -0
  49. package/dist/cart/totals.js +81 -0
  50. package/dist/cart/totals.js.map +7 -0
  51. package/dist/cart/use-address-selection.js +130 -0
  52. package/dist/cart/use-address-selection.js.map +7 -0
  53. package/dist/cart.js +21 -1069
  54. package/dist/cart.js.map +7 -1
  55. package/dist/catalogue/catalogue-cart.js +25 -0
  56. package/dist/catalogue/catalogue-cart.js.map +7 -0
  57. package/dist/catalogue/catalogue-header.js +88 -0
  58. package/dist/catalogue/catalogue-header.js.map +7 -0
  59. package/dist/catalogue/catalogue-pages.js +68 -0
  60. package/dist/catalogue/catalogue-pages.js.map +7 -0
  61. package/dist/catalogue/catalogue-search.js +89 -0
  62. package/dist/catalogue/catalogue-search.js.map +7 -0
  63. package/dist/catalogue/category-navigation.js +98 -0
  64. package/dist/catalogue/category-navigation.js.map +7 -0
  65. package/dist/catalogue/category-section.js +113 -0
  66. package/dist/catalogue/category-section.js.map +7 -0
  67. package/dist/catalogue/info-banners.js +148 -0
  68. package/dist/catalogue/info-banners.js.map +7 -0
  69. package/dist/catalogue/item-tile.js +55 -0
  70. package/dist/catalogue/item-tile.js.map +7 -0
  71. package/dist/catalogue/loader.js +136 -0
  72. package/dist/catalogue/loader.js.map +7 -0
  73. package/dist/{chunk-USSLDBDY.js → catalogue/presentation.js} +12 -9
  74. package/dist/catalogue/presentation.js.map +7 -0
  75. package/dist/catalogue/saved-catalogue-sync.js +115 -0
  76. package/dist/catalogue/saved-catalogue-sync.js.map +7 -0
  77. package/dist/catalogue/types.js +1 -0
  78. package/dist/catalogue/types.js.map +7 -0
  79. package/dist/catalogue/use-catalogue-data.js +88 -0
  80. package/dist/catalogue/use-catalogue-data.js.map +7 -0
  81. package/dist/catalogue/use-category-scroll.js +115 -0
  82. package/dist/catalogue/use-category-scroll.js.map +7 -0
  83. package/dist/catalogue/use-item-opener.js +46 -0
  84. package/dist/catalogue/use-item-opener.js.map +7 -0
  85. package/dist/catalogue/use-search-source.js +132 -0
  86. package/dist/catalogue/use-search-source.js.map +7 -0
  87. package/dist/catalogue.js +26 -1216
  88. package/dist/catalogue.js.map +7 -1
  89. package/dist/checkout.js +149 -2
  90. package/dist/checkout.js.map +7 -1
  91. package/dist/host-bridge.js +22 -2
  92. package/dist/host-bridge.js.map +7 -1
  93. package/dist/index.js +3 -3
  94. package/dist/index.js.map +7 -1
  95. package/dist/item/configurator-commit.js +15 -0
  96. package/dist/item/configurator-commit.js.map +7 -0
  97. package/dist/item/configurator-draft.js +63 -0
  98. package/dist/item/configurator-draft.js.map +7 -0
  99. package/dist/item/configurator.js +135 -0
  100. package/dist/item/configurator.js.map +7 -0
  101. package/dist/item/note.js +65 -0
  102. package/dist/item/note.js.map +7 -0
  103. package/dist/item/variant-status.js +23 -0
  104. package/dist/item/variant-status.js.map +7 -0
  105. package/dist/item-frame.js +60 -3
  106. package/dist/item-frame.js.map +7 -1
  107. package/dist/item.js +11 -11
  108. package/dist/item.js.map +7 -1
  109. package/dist/navigation.js +39 -2
  110. package/dist/navigation.js.map +7 -1
  111. package/dist/url-navigation-state.js +61 -0
  112. package/dist/url-navigation-state.js.map +7 -0
  113. package/dist/{chunk-ILOCSCZL.js → url-navigation.js} +12 -89
  114. package/dist/url-navigation.js.map +7 -0
  115. package/package.json +8 -7
  116. package/dist/chunk-2MV6KU3R.js +0 -352
  117. package/dist/chunk-2MV6KU3R.js.map +0 -1
  118. package/dist/chunk-FB5DRCU7.js.map +0 -1
  119. package/dist/chunk-IG63ONID.js +0 -139
  120. package/dist/chunk-IG63ONID.js.map +0 -1
  121. package/dist/chunk-ILOCSCZL.js.map +0 -1
  122. package/dist/chunk-JFEI2OUZ.js.map +0 -1
  123. package/dist/chunk-NTJONY3N.js +0 -95
  124. package/dist/chunk-NTJONY3N.js.map +0 -1
  125. package/dist/chunk-QWST2TA2.js +0 -22
  126. package/dist/chunk-QWST2TA2.js.map +0 -1
  127. package/dist/chunk-USSLDBDY.js.map +0 -1
  128. package/dist/chunk-VIAJ27YC.js +0 -59
  129. package/dist/chunk-VIAJ27YC.js.map +0 -1
@@ -1,65 +1,11 @@
1
- import { createContext, useState, useEffect, useContext } from 'react';
2
- import { parseStorefrontUrl, buildStorefrontUrl } from '@zappie/sdk/url';
3
- import { jsx } from 'react/jsx-runtime';
4
-
5
- // src/navigation.tsx
6
-
7
- // src/url-navigation-state.ts
8
- var NAVIGATION_ENTRY = "zappie:storefront-navigation-entry";
9
- var routeBase = (route) => {
10
- if (route.type === "item" || route.type === "order-menu") {
11
- return {
12
- business: route.business,
13
- ...route.branch !== void 0 ? { branch: route.branch } : {}
14
- };
15
- }
16
- return null;
17
- };
18
- var stateWith = (state, values) => {
19
- const query = { ...state.query };
20
- const next = { ...state, query };
21
- const update = (property, key, value) => {
22
- if (!Object.hasOwn(values, property)) {
23
- return;
24
- }
25
- if (value === void 0) {
26
- delete query[key];
27
- delete next[property];
28
- return;
29
- }
30
- query[key] = property === "mode" ? String(value === "pickup") : value;
31
- if (property === "mode") {
32
- next.mode = value === "pickup" ? "pickup" : "delivery";
33
- } else if (property === "menuId") {
34
- next.menuId = value;
35
- } else if (property === "categoryId") {
36
- next.categoryId = value;
37
- } else if (property === "menuLayout") {
38
- next.menuLayout = value;
39
- } else {
40
- next.modalId = value;
41
- }
42
- };
43
- update("menuId", "menu_id", values.menuId);
44
- update("categoryId", "category_id", values.categoryId);
45
- update("menuLayout", "menu_layout", values.menuLayout);
46
- update("modalId", "modal_id", values.modalId);
47
- update("mode", "pickup", values.mode);
48
- return next;
49
- };
50
- var catalogueRoute = (route, state) => {
51
- const base = routeBase(route);
52
- if (!base) {
53
- return route;
54
- }
55
- return {
56
- type: "order-menu",
57
- ...base,
58
- state
59
- };
60
- };
61
-
62
1
  // src/url-navigation.ts
2
+ import { buildStorefrontUrl, parseStorefrontUrl } from "@zappie/sdk/url";
3
+ import {
4
+ catalogueRoute,
5
+ NAVIGATION_ENTRY,
6
+ routeBase,
7
+ stateWith
8
+ } from "./url-navigation-state.js";
63
9
  function createUrlNavigation(options = {}) {
64
10
  const browser = options.window ?? window;
65
11
  const current = () => parseStorefrontUrl(browser.location.href, options);
@@ -154,6 +100,7 @@ function createUrlNavigation(options = {}) {
154
100
  async openItem({ itemId, menuId, categoryId }) {
155
101
  write(
156
102
  hrefFor({
103
+ type: "item",
157
104
  itemId,
158
105
  menuId,
159
106
  ...categoryId !== void 0 ? { categoryId } : {}
@@ -187,31 +134,7 @@ function createUrlNavigation(options = {}) {
187
134
  }
188
135
  };
189
136
  }
190
- var Context = createContext(null);
191
- function CatalogueNavigationProvider({
192
- navigation,
193
- children
194
- }) {
195
- const [, refresh] = useState(0);
196
- useEffect(() => {
197
- const update = () => refresh((value) => value + 1);
198
- window.addEventListener("popstate", update);
199
- return () => {
200
- window.removeEventListener("popstate", update);
201
- };
202
- }, [navigation]);
203
- return /* @__PURE__ */ jsx(Context.Provider, { value: navigation, children });
204
- }
205
- function useCatalogueNavigation() {
206
- const navigation = useContext(Context);
207
- if (!navigation) {
208
- throw new Error(
209
- "useCatalogueNavigation requires CatalogueNavigationProvider"
210
- );
211
- }
212
- return navigation;
213
- }
214
-
215
- export { CatalogueNavigationProvider, createUrlNavigation, useCatalogueNavigation };
216
- //# sourceMappingURL=chunk-ILOCSCZL.js.map
217
- //# sourceMappingURL=chunk-ILOCSCZL.js.map
137
+ export {
138
+ createUrlNavigation
139
+ };
140
+ //# sourceMappingURL=url-navigation.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/url-navigation.ts"],
4
+ "sourcesContent": ["import { buildStorefrontUrl, parseStorefrontUrl } from \"@zappie/sdk/url\";\nimport type {\n CatalogueLocation,\n CatalogueNavigation,\n CatalogueNavigationTarget,\n UrlNavigationOptions,\n} from \"./navigation\";\nimport {\n catalogueRoute,\n NAVIGATION_ENTRY,\n routeBase,\n stateWith,\n} from \"./url-navigation-state\";\n\nexport function createUrlNavigation(\n options: UrlNavigationOptions = {},\n): CatalogueNavigation {\n const browser = options.window ?? window;\n const current = () => parseStorefrontUrl(browser.location.href, options);\n\n const urlFor = (route: Parameters<typeof buildStorefrontUrl>[0]) =>\n buildStorefrontUrl(route, options);\n const notify = () => {\n browser.dispatchEvent(\n new browser.PopStateEvent(\"popstate\", { state: browser.history.state }),\n );\n };\n const write = (url: string, method: \"push\" | \"replace\", entry: string) => {\n const state = {\n ...(typeof browser.history.state === \"object\" && browser.history.state\n ? browser.history.state\n : {}),\n [NAVIGATION_ENTRY]: entry,\n };\n if (method === \"push\") {\n browser.history.pushState(state, \"\", url);\n } else {\n browser.history.replaceState(state, \"\", url);\n }\n notify();\n };\n const hrefFor = (target: CatalogueNavigationTarget) => {\n const route = current();\n const base = routeBase(route);\n if (!base) {\n return browser.location.href;\n }\n const state = stateWith(route.state, {\n ...(target.menuId !== undefined ? { menuId: target.menuId } : {}),\n ...(target.categoryId !== undefined\n ? { categoryId: target.categoryId }\n : {}),\n });\n return urlFor({\n type: \"item\",\n business: base.business,\n ...(base.branch !== undefined ? { branch: base.branch } : {}),\n item: target.itemId,\n state,\n });\n };\n const updateCatalogue = (\n values: Parameters<typeof stateWith>[1],\n method: \"push\" | \"replace\" = \"replace\",\n entry = \"catalogue\",\n ) => {\n const route = current();\n const next = catalogueRoute(route, stateWith(route.state, values));\n write(urlFor(next), method, entry);\n };\n const closeItem = async () => {\n const route = current();\n if (route.type !== \"item\") {\n return;\n }\n if (browser.history.state?.[NAVIGATION_ENTRY] === \"item\") {\n await new Promise<void>((resolve) => {\n browser.addEventListener(\"popstate\", () => resolve(), { once: true });\n browser.history.back();\n });\n return;\n }\n const next = catalogueRoute(\n route,\n stateWith(route.state, { modalId: undefined }),\n );\n write(urlFor(next), \"replace\", \"catalogue\");\n };\n return {\n get location() {\n const route = current();\n const layout = route.state.menuLayout;\n const menuLayout: CatalogueLocation[\"menuLayout\"] =\n layout === \"GRID\" || layout === \"LIST\" || layout === \"CARD\"\n ? layout\n : undefined;\n return {\n pathname: browser.location.pathname,\n ...(route.state.menuId !== undefined\n ? { menuId: route.state.menuId }\n : {}),\n ...(route.state.categoryId !== undefined\n ? { categoryId: route.state.categoryId }\n : {}),\n ...(menuLayout !== undefined ? { menuLayout } : {}),\n ...(route.type === \"item\"\n ? {\n item: {\n id: route.item,\n path: browser.location.pathname,\n presentation: route.state.modalId\n ? (\"query\" as const)\n : (\"path\" as const),\n },\n }\n : {}),\n };\n },\n hrefFor,\n selectMenu(menuId) {\n updateCatalogue({ menuId });\n },\n selectCategory(categoryId) {\n updateCatalogue({ categoryId });\n },\n setLayout(menuLayout) {\n updateCatalogue({ menuLayout });\n },\n async openItem({ itemId, menuId, categoryId }) {\n write(\n hrefFor({\n type: \"item\",\n itemId,\n menuId,\n ...(categoryId !== undefined ? { categoryId } : {}),\n }),\n \"push\",\n \"item\",\n );\n },\n closeItem,\n async openCart() {\n await closeItem();\n updateCatalogue({ modalId: \"review-menu\" }, \"push\", \"cart\");\n },\n async openBranchFinder() {\n await closeItem();\n updateCatalogue({ modalId: \"branch-finder\" }, \"push\", \"branch-finder\");\n },\n async openBranchDetails() {\n await closeItem();\n updateCatalogue({ modalId: \"branch-details\" }, \"push\", \"branch-details\");\n },\n async switchFulfilment(mode) {\n await closeItem();\n updateCatalogue({ mode });\n return true;\n },\n restoreFocus({ itemId }) {\n const item = itemId\n ? browser.document.getElementById(`base-item-${itemId}`)\n : null;\n const target =\n item ?? browser.document.getElementById(\"base-catalogue-heading\");\n target?.focus();\n },\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zappie/theme-base",
3
- "version": "0.1.0",
4
- "description": "The base Zappie storefront theme, built only from public packages (template id base-next).",
3
+ "version": "0.1.2",
4
+ "description": "The base storefront theme Zappie's own storefront app renders, built only from Zappie's public packages.",
5
5
  "type": "module",
6
6
  "sideEffects": [
7
7
  "**/*.css"
@@ -50,12 +50,13 @@
50
50
  "provenance": false
51
51
  },
52
52
  "files": [
53
- "dist"
53
+ "dist",
54
+ "CHANGELOG.md"
54
55
  ],
55
56
  "dependencies": {
56
- "@zappie/foundations": "^0.1.0",
57
- "@zappie/sdk": "^0.1.0",
58
- "@zappie/tokens": "^0.1.0"
57
+ "@zappie/foundations": "^0.1.2",
58
+ "@zappie/sdk": "^0.1.2",
59
+ "@zappie/tokens": "^0.1.1"
59
60
  },
60
61
  "peerDependencies": {
61
62
  "react": "^19.2.0"
@@ -71,6 +72,6 @@
71
72
  "url": "https://github.com/zappie/storefront/issues"
72
73
  },
73
74
  "scripts": {
74
- "build": "tsup"
75
+ "build": "tsup && node ../../scripts/release-packages/build-modules.mjs"
75
76
  }
76
77
  }
@@ -1,352 +0,0 @@
1
- import { useThemeClass } from './chunk-JFEI2OUZ.js';
2
- import { ItemForm, Money, Quantity, useOverlay, Overlay, OptionGroup, Choice } from '@zappie/foundations';
3
- import { useZappie } from '@zappie/sdk/react';
4
- import { countEvent } from '@zappie/sdk/visits';
5
- import { useState, Fragment, useEffect } from 'react';
6
- import { jsx, jsxs } from 'react/jsx-runtime';
7
-
8
- function LineOptions() {
9
- return /* @__PURE__ */ jsx(ItemForm.Options, { children: ({ groups }) => [...groups].sort(
10
- (left, right) => Number(right.isAttribute) - Number(left.isAttribute)
11
- ).map((group) => /* @__PURE__ */ jsx(OptionsSection, { group }, group.id)) });
12
- }
13
- function OptionsSection({ group }) {
14
- const [expanded, setExpanded] = useState(true);
15
- const count = group.selection.max === group.selection.min && group.selection.min > 0 ? `Exactly ${group.selection.min}` : group.selection.max ? `Choose up to ${group.selection.max}` : group.selection.min ? `Choose at least ${group.selection.min}` : "Optional";
16
- return /* @__PURE__ */ jsx(
17
- OptionGroup,
18
- {
19
- group,
20
- className: "z-base-option-group",
21
- "aria-label": group.name,
22
- children: ({ quantities, setQuantity, invalid }) => /* @__PURE__ */ jsxs(Fragment, { children: [
23
- /* @__PURE__ */ jsx("h3", { className: "z-base-option-heading", children: /* @__PURE__ */ jsxs(
24
- "button",
25
- {
26
- type: "button",
27
- "aria-expanded": expanded || invalid,
28
- onClick: () => setExpanded(!expanded),
29
- children: [
30
- /* @__PURE__ */ jsx("span", { children: group.name }),
31
- /* @__PURE__ */ jsxs("span", { className: "z-base-option-rule", children: [
32
- count,
33
- group.required && /* @__PURE__ */ jsx("strong", { children: " Required*" })
34
- ] }),
35
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "z-base-option-chevron", children: expanded || invalid ? "\u2304" : "\u203A" })
36
- ]
37
- }
38
- ) }),
39
- (expanded || invalid) && /* @__PURE__ */ jsxs("div", { className: "z-base-option-choices", children: [
40
- group.helpText && /* @__PURE__ */ jsx("p", { children: group.helpText }),
41
- group.kind === "select" && group.choices.map((choice) => /* @__PURE__ */ jsxs("div", { className: "z-base-choice-row", children: [
42
- /* @__PURE__ */ jsx(Choice, { choice, className: "z-base-choice", children: /* @__PURE__ */ jsxs("span", { className: "z-base-choice-label", children: [
43
- /* @__PURE__ */ jsx("span", { children: choice.name }),
44
- (choice.priceHint ?? choice.price).amountMinor !== 0 && /* @__PURE__ */ jsxs("span", { className: "z-base-choice-price", children: [
45
- (choice.priceHint ?? choice.price).amountMinor > 0 ? "+" : "",
46
- /* @__PURE__ */ jsx(Money, { value: choice.priceHint ?? choice.price })
47
- ] }),
48
- !choice.isAvailable && /* @__PURE__ */ jsx("span", { className: "z-base-choice-price", children: "Unavailable" })
49
- ] }) }),
50
- choice.quantity && (quantities[choice.id] ?? 0) > 0 && /* @__PURE__ */ jsxs(
51
- Quantity.Root,
52
- {
53
- className: "z-base-quantity",
54
- value: quantities[choice.id] ?? 0,
55
- min: 0,
56
- max: choice.quantity.max ?? 99,
57
- disabled: !choice.isAvailable,
58
- onValueChange: (quantity) => setQuantity(choice.id, quantity),
59
- children: [
60
- /* @__PURE__ */ jsx(
61
- Quantity.Decrement,
62
- {
63
- "aria-label": `Decrease ${choice.name}`,
64
- children: "\u2212"
65
- }
66
- ),
67
- /* @__PURE__ */ jsx(
68
- Quantity.Value,
69
- {
70
- "aria-label": `${choice.name} quantity`
71
- }
72
- ),
73
- /* @__PURE__ */ jsx(
74
- Quantity.Increment,
75
- {
76
- "aria-label": `Increase ${choice.name}`,
77
- children: "+"
78
- }
79
- )
80
- ]
81
- }
82
- )
83
- ] }, choice.id)),
84
- (group.kind !== "select" || group.isInformational) && /* @__PURE__ */ jsx(OptionGroup.Input, { className: "z-base-input" })
85
- ] })
86
- ] })
87
- }
88
- );
89
- }
90
-
91
- // src/item/configurator-commit.ts
92
- function createConfiguratorCommit(client, line) {
93
- if (!line) {
94
- return void 0;
95
- }
96
- return (input) => {
97
- const nextInput = { ...input };
98
- delete nextInput.variantId;
99
- return client.cart.update(line.id, nextInput);
100
- };
101
- }
102
- function useConfiguratorDraft({
103
- item,
104
- menuId,
105
- line,
106
- scope
107
- }) {
108
- const key = `zappie:product-draft:${scope}:${item.id}:${menuId ?? ""}:${line?.id ?? "new"}`;
109
- const initial = {
110
- itemId: item.id,
111
- ...menuId !== void 0 ? { menuId } : {},
112
- quantity: line?.quantity ?? item.quantity.min,
113
- choices: line?.choices.map((choice) => ({ ...choice })) ?? [],
114
- inputs: { ...line?.inputs },
115
- note: line?.note ?? ""
116
- };
117
- const [value, setValue] = useState(initial);
118
- const [restored, setRestored] = useState(false);
119
- useEffect(() => {
120
- try {
121
- const saved = JSON.parse(sessionStorage.getItem(key) ?? "null");
122
- if (saved?.itemId === item.id && saved?.menuId === menuId && Number.isFinite(saved.quantity) && Array.isArray(saved.choices) && saved.choices.every((choice) => {
123
- if (!choice || typeof choice !== "object") {
124
- return false;
125
- }
126
- const value2 = choice;
127
- return typeof value2.groupId === "string" && typeof value2.choiceId === "string" && Number.isFinite(value2.quantity);
128
- }) && saved.inputs && typeof saved.inputs === "object" && !Array.isArray(saved.inputs) && Object.values(saved.inputs).every(
129
- (value2) => typeof value2 === "string" || typeof value2 === "boolean" || typeof value2 === "number" && Number.isFinite(value2)
130
- ) && typeof saved.note === "string") {
131
- setValue({
132
- ...initial,
133
- quantity: saved.quantity,
134
- choices: saved.choices,
135
- inputs: saved.inputs,
136
- note: saved.note
137
- });
138
- }
139
- } catch {
140
- }
141
- setRestored(true);
142
- }, [key]);
143
- useEffect(() => {
144
- if (restored) {
145
- try {
146
- sessionStorage.setItem(key, JSON.stringify(value));
147
- } catch {
148
- }
149
- }
150
- }, [key, value, restored]);
151
- const clear = () => {
152
- try {
153
- sessionStorage.removeItem(key);
154
- } catch {
155
- }
156
- };
157
- return { clear, restored, setValue, value };
158
- }
159
- function ItemNote({
160
- id,
161
- value,
162
- onChange
163
- }) {
164
- const overlay = useOverlay("product_note", id);
165
- const themeClass = useThemeClass("z-base-cart z-base-note");
166
- return /* @__PURE__ */ jsxs(
167
- Overlay.Root,
168
- {
169
- param: "product_note",
170
- id,
171
- presentation: { base: "drawer", lg: "dialog" },
172
- children: [
173
- /* @__PURE__ */ jsx(Overlay.Trigger, { className: "z-base-button-secondary", children: value ? "Edit Note" : "Add Note" }),
174
- /* @__PURE__ */ jsxs(Overlay.Content, { "data-zappie-theme": "base", className: themeClass, children: [
175
- /* @__PURE__ */ jsxs("header", { className: "z-base-cart-header", children: [
176
- /* @__PURE__ */ jsx(Overlay.Title, { children: "Add a note" }),
177
- /* @__PURE__ */ jsx(
178
- Overlay.Close,
179
- {
180
- className: "z-base-button-secondary",
181
- "aria-label": "Close note",
182
- children: "\u2715"
183
- }
184
- )
185
- ] }),
186
- /* @__PURE__ */ jsxs("div", { className: "z-base-cart-body", children: [
187
- /* @__PURE__ */ jsxs("label", { className: "z-base-field", children: [
188
- "Note",
189
- /* @__PURE__ */ jsx(
190
- "textarea",
191
- {
192
- className: "z-base-input",
193
- maxLength: Math.max(35, value.length),
194
- value,
195
- onChange: (event) => onChange(event.target.value)
196
- }
197
- )
198
- ] }),
199
- /* @__PURE__ */ jsx(
200
- "button",
201
- {
202
- type: "button",
203
- className: "z-base-button",
204
- onClick: overlay.close,
205
- children: "Add note"
206
- }
207
- )
208
- ] })
209
- ] })
210
- ]
211
- }
212
- );
213
- }
214
- function VariantStatus({
215
- item,
216
- value
217
- }) {
218
- const matches = item.variants.filter(
219
- (variant) => Object.entries(variant.attributeChoices).every(
220
- ([groupId, choiceId]) => value.choices?.some(
221
- (choice) => choice.groupId === groupId && choice.choiceId === choiceId
222
- )
223
- )
224
- );
225
- const selected = matches.length === 1 ? matches[0] : void 0;
226
- if (!item.isAvailable || !selected) {
227
- return null;
228
- }
229
- return !selected.isAvailable ? /* @__PURE__ */ jsx("p", { role: "status", children: "Out of stock" }) : selected.lowStock ? /* @__PURE__ */ jsx("p", { role: "status", children: "Low stock" }) : null;
230
- }
231
- function ItemConfigurator({
232
- item,
233
- menuId,
234
- line,
235
- onComplete,
236
- scope,
237
- showPrice = false,
238
- introduction
239
- }) {
240
- const client = useZappie();
241
- const { clear, restored, setValue, value } = useConfiguratorDraft({
242
- item,
243
- ...menuId !== void 0 ? { menuId } : {},
244
- ...line !== void 0 ? { line } : {},
245
- scope
246
- });
247
- const [error, setError] = useState();
248
- const onCommit = createConfiguratorCommit(client, line);
249
- return /* @__PURE__ */ jsx(
250
- ItemForm.Root,
251
- {
252
- item,
253
- value,
254
- onValueChange: (next) => {
255
- const nextValue = { ...next };
256
- delete nextValue.variantId;
257
- setValue(nextValue);
258
- setError(void 0);
259
- },
260
- ...onCommit ? { onCommit } : {},
261
- onAdded: () => {
262
- if (!line) {
263
- countEvent("add");
264
- }
265
- clear();
266
- onComplete();
267
- },
268
- className: "z-base-configurator",
269
- children: (configuration) => /* @__PURE__ */ jsxs(Fragment, { children: [
270
- /* @__PURE__ */ jsxs("div", { className: "z-base-item-summary", children: [
271
- showPrice && /* @__PURE__ */ jsxs("p", { className: "z-base-item-price", children: [
272
- /* @__PURE__ */ jsx(Money, { value: configuration.unitPrice }),
273
- item.compareAtPrice && /* @__PURE__ */ jsx("del", { children: /* @__PURE__ */ jsx(Money, { value: item.compareAtPrice }) })
274
- ] }),
275
- !line && /* @__PURE__ */ jsx(
276
- ItemNote,
277
- {
278
- id: item.id,
279
- value: value.note ?? "",
280
- onChange: (note) => configuration.setValue({ ...value, note })
281
- }
282
- )
283
- ] }),
284
- line && /* @__PURE__ */ jsxs("label", { className: "z-base-field", children: [
285
- "Note",
286
- /* @__PURE__ */ jsx(
287
- "textarea",
288
- {
289
- className: "z-base-input",
290
- maxLength: line ? 280 : Math.max(35, value.note?.length ?? 0),
291
- value: value.note ?? "",
292
- onChange: (event) => configuration.setValue({ ...value, note: event.target.value })
293
- }
294
- )
295
- ] }),
296
- showPrice && /* @__PURE__ */ jsx(VariantStatus, { item, value: configuration.value }),
297
- introduction,
298
- /* @__PURE__ */ jsx(LineOptions, {}),
299
- configuration.issues.length > 0 && /* @__PURE__ */ jsx("div", { role: "alert", children: configuration.issues.map((issue, index) => /* @__PURE__ */ jsx("p", { children: issue.message }, `${issue.code}:${issue.groupId}:${index}`)) }),
300
- error && /* @__PURE__ */ jsx("p", { role: "alert", children: error }),
301
- line && /* @__PURE__ */ jsxs("p", { "aria-live": "polite", children: [
302
- "Estimated total: ",
303
- /* @__PURE__ */ jsx(Money, { value: configuration.total })
304
- ] }),
305
- /* @__PURE__ */ jsxs("footer", { className: "z-base-item-purchase", children: [
306
- /* @__PURE__ */ jsxs(
307
- Quantity.Root,
308
- {
309
- className: "z-base-quantity",
310
- value: configuration.quantity,
311
- min: item.quantity.min,
312
- max: Math.min(item.quantity.max ?? 99, 99),
313
- step: item.quantity.step,
314
- onValueChange: configuration.setQuantity,
315
- children: [
316
- /* @__PURE__ */ jsx(Quantity.Decrement, { "aria-label": "Decrease quantity", children: "\u2212" }),
317
- /* @__PURE__ */ jsx(Quantity.Value, { "aria-label": "Item quantity" }),
318
- /* @__PURE__ */ jsx(Quantity.Increment, { "aria-label": "Increase quantity", children: "+" })
319
- ]
320
- }
321
- ),
322
- /* @__PURE__ */ jsxs(
323
- "button",
324
- {
325
- type: "button",
326
- className: "z-base-button",
327
- disabled: !restored || !item.isAvailable,
328
- onClick: () => {
329
- try {
330
- configuration.add();
331
- } catch (failure) {
332
- setError(
333
- failure instanceof Error ? failure.message : "Unable to save this item. Please try again."
334
- );
335
- }
336
- },
337
- children: [
338
- item.isAvailable ? line ? "Save changes" : "Add" : item.stockLabel ?? "Unavailable",
339
- " ",
340
- !line && /* @__PURE__ */ jsx(Money, { value: configuration.total })
341
- ]
342
- }
343
- )
344
- ] })
345
- ] })
346
- }
347
- );
348
- }
349
-
350
- export { ItemConfigurator };
351
- //# sourceMappingURL=chunk-2MV6KU3R.js.map
352
- //# sourceMappingURL=chunk-2MV6KU3R.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cart/line-options.tsx","../src/item/configurator-commit.ts","../src/item/configurator-draft.ts","../src/item/note.tsx","../src/item/variant-status.tsx","../src/item/configurator.tsx"],"names":["useState","value","jsxs","jsx","ItemForm","Fragment","Money","Quantity"],"mappings":";;;;;;;AASO,SAAS,WAAA,GAAc;AAC5B,EAAA,uBACE,GAAA,CAAC,QAAA,CAAS,OAAA,EAAT,EACE,QAAA,EAAA,CAAC,EAAE,MAAA,EAAO,KACT,CAAC,GAAG,MAAM,CAAA,CACP,IAAA;AAAA,IACC,CAAC,MAAM,KAAA,KACL,MAAA,CAAO,MAAM,WAAW,CAAA,GAAI,MAAA,CAAO,IAAA,CAAK,WAAW;AAAA,GACvD,CACC,GAAA,CAAI,CAAC,KAAA,qBAAU,GAAA,CAAC,kBAA8B,KAAA,EAAA,EAAV,KAAA,CAAM,EAAkB,CAAE,CAAA,EAErE,CAAA;AAEJ;AACA,SAAS,cAAA,CAAe,EAAE,KAAA,EAAM,EAAqB;AACnD,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAS,IAAI,CAAA;AAC7C,EAAA,MAAM,KAAA,GACJ,KAAA,CAAM,SAAA,CAAU,GAAA,KAAQ,KAAA,CAAM,SAAA,CAAU,GAAA,IAAO,KAAA,CAAM,SAAA,CAAU,GAAA,GAAM,CAAA,GACjE,CAAA,QAAA,EAAW,MAAM,SAAA,CAAU,GAAG,CAAA,CAAA,GAC9B,KAAA,CAAM,SAAA,CAAU,GAAA,GACd,CAAA,aAAA,EAAgB,KAAA,CAAM,UAAU,GAAG,CAAA,CAAA,GACnC,KAAA,CAAM,SAAA,CAAU,GAAA,GACd,CAAA,gBAAA,EAAmB,KAAA,CAAM,SAAA,CAAU,GAAG,CAAA,CAAA,GACtC,UAAA;AACV,EAAA,uBACE,GAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,KAAA;AAAA,MACA,SAAA,EAAU,qBAAA;AAAA,MACV,cAAY,KAAA,CAAM,IAAA;AAAA,MAEjB,WAAC,EAAE,UAAA,EAAY,aAAa,OAAA,EAAQ,0BAClC,QAAA,EAAA,EACC,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,IAAA,EAAA,EAAG,WAAU,uBAAA,EACZ,QAAA,kBAAA,IAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,iBAAe,QAAA,IAAY,OAAA;AAAA,YAC3B,OAAA,EAAS,MAAM,WAAA,CAAY,CAAC,QAAQ,CAAA;AAAA,YAEpC,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAM,gBAAM,IAAA,EAAK,CAAA;AAAA,8BAClB,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,oBAAA,EACb,QAAA,EAAA;AAAA,gBAAA,KAAA;AAAA,gBACA,KAAA,CAAM,QAAA,oBAAY,GAAA,CAAC,QAAA,EAAA,EAAO,QAAA,EAAA,YAAA,EAAU;AAAA,eAAA,EACvC,CAAA;AAAA,8BACA,GAAA,CAAC,UAAK,aAAA,EAAY,MAAA,EAAO,WAAU,uBAAA,EAChC,QAAA,EAAA,QAAA,IAAY,OAAA,GAAU,QAAA,GAAM,QAAA,EAC/B;AAAA;AAAA;AAAA,SACF,EACF,CAAA;AAAA,QAAA,CACE,QAAA,IAAY,OAAA,qBACZ,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,uBAAA,EACZ,QAAA,EAAA;AAAA,UAAA,KAAA,CAAM,QAAA,oBAAY,GAAA,CAAC,GAAA,EAAA,EAAG,QAAA,EAAA,KAAA,CAAM,QAAA,EAAS,CAAA;AAAA,UACrC,KAAA,CAAM,IAAA,KAAS,QAAA,IACd,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,qBACjB,IAAA,CAAC,KAAA,EAAA,EAAoB,SAAA,EAAU,mBAAA,EAC7B,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,UAAO,MAAA,EAAgB,SAAA,EAAU,iBAChC,QAAA,kBAAA,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,qBAAA,EACd,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAM,iBAAO,IAAA,EAAK,CAAA;AAAA,cAAA,CACjB,MAAA,CAAO,aAAa,MAAA,CAAO,KAAA,EAAO,gBAClC,CAAA,oBACA,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EACZ,QAAA,EAAA;AAAA,gBAAA,CAAA,MAAA,CAAO,SAAA,IAAa,MAAA,CAAO,KAAA,EAAO,WAAA,GAAc,IAC9C,GAAA,GACA,EAAA;AAAA,oCACH,KAAA,EAAA,EAAM,KAAA,EAAO,MAAA,CAAO,SAAA,IAAa,OAAO,KAAA,EAAO;AAAA,eAAA,EAClD,CAAA;AAAA,cAED,CAAC,MAAA,CAAO,WAAA,wBACN,MAAA,EAAA,EAAK,SAAA,EAAU,uBAAsB,QAAA,EAAA,aAAA,EAEtC;AAAA,aAAA,EAEJ,CAAA,EACF,CAAA;AAAA,YACC,OAAO,QAAA,IAAA,CAAa,UAAA,CAAW,OAAO,EAAE,CAAA,IAAK,KAAK,CAAA,oBACjD,IAAA;AAAA,cAAC,QAAA,CAAS,IAAA;AAAA,cAAT;AAAA,gBACC,SAAA,EAAU,iBAAA;AAAA,gBACV,KAAA,EAAO,UAAA,CAAW,MAAA,CAAO,EAAE,CAAA,IAAK,CAAA;AAAA,gBAChC,GAAA,EAAK,CAAA;AAAA,gBACL,GAAA,EAAK,MAAA,CAAO,QAAA,CAAS,GAAA,IAAO,EAAA;AAAA,gBAC5B,QAAA,EAAU,CAAC,MAAA,CAAO,WAAA;AAAA,gBAClB,eAAe,CAAC,QAAA,KACd,WAAA,CAAY,MAAA,CAAO,IAAI,QAAQ,CAAA;AAAA,gBAGjC,QAAA,EAAA;AAAA,kCAAA,GAAA;AAAA,oBAAC,QAAA,CAAS,SAAA;AAAA,oBAAT;AAAA,sBACC,YAAA,EAAY,CAAA,SAAA,EAAY,MAAA,CAAO,IAAI,CAAA,CAAA;AAAA,sBACpC,QAAA,EAAA;AAAA;AAAA,mBAED;AAAA,kCACA,GAAA;AAAA,oBAAC,QAAA,CAAS,KAAA;AAAA,oBAAT;AAAA,sBACC,YAAA,EAAY,CAAA,EAAG,MAAA,CAAO,IAAI,CAAA,SAAA;AAAA;AAAA,mBAC5B;AAAA,kCACA,GAAA;AAAA,oBAAC,QAAA,CAAS,SAAA;AAAA,oBAAT;AAAA,sBACC,YAAA,EAAY,CAAA,SAAA,EAAY,MAAA,CAAO,IAAI,CAAA,CAAA;AAAA,sBACpC,QAAA,EAAA;AAAA;AAAA;AAED;AAAA;AAAA;AACF,WAAA,EAAA,EA5CM,MAAA,CAAO,EA8CjB,CACD,CAAA;AAAA,UAAA,CACD,KAAA,CAAM,IAAA,KAAS,QAAA,IAAY,KAAA,CAAM,eAAA,yBAChC,WAAA,CAAY,KAAA,EAAZ,EAAkB,SAAA,EAAU,cAAA,EAAe;AAAA,SAAA,EAEhD;AAAA,OAAA,EAEJ;AAAA;AAAA,GAEJ;AAEJ;;;ACrHO,SAAS,wBAAA,CACd,QACA,IAAA,EACA;AACA,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,CAAC,KAAA,KAAyB;AAC/B,IAAA,MAAM,SAAA,GAAY,EAAE,GAAG,KAAA,EAAM;AAC7B,IAAA,OAAO,SAAA,CAAU,SAAA;AACjB,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,IAAI,SAAS,CAAA;AAAA,EAC9C,CAAA;AACF;ACXO,SAAS,oBAAA,CAAqB;AAAA,EACnC,IAAA;AAAA,EACA,MAAA;AAAA,EACA,IAAA;AAAA,EACA;AACF,CAAA,EAKG;AACD,EAAA,MAAM,GAAA,GAAM,CAAA,qBAAA,EAAwB,KAAK,CAAA,CAAA,EAAI,IAAA,CAAK,EAAE,CAAA,CAAA,EAAI,MAAA,IAAU,EAAE,CAAA,CAAA,EAAI,IAAA,EAAM,EAAA,IAAM,KAAK,CAAA,CAAA;AACzF,EAAA,MAAM,OAAA,GAAyB;AAAA,IAC7B,QAAQ,IAAA,CAAK,EAAA;AAAA,IACb,GAAI,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,KAAW,EAAC;AAAA,IACzC,QAAA,EAAU,IAAA,EAAM,QAAA,IAAY,IAAA,CAAK,QAAA,CAAS,GAAA;AAAA,IAC1C,OAAA,EAAS,IAAA,EAAM,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,MAAY,EAAE,GAAG,MAAA,EAAO,CAAE,CAAA,IAAK,EAAC;AAAA,IAC5D,MAAA,EAAQ,EAAE,GAAG,IAAA,EAAM,MAAA,EAAO;AAAA,IAC1B,IAAA,EAAM,MAAM,IAAA,IAAQ;AAAA,GACtB;AACA,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,SAAS,OAAO,CAAA;AAC1C,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIA,SAAS,KAAK,CAAA;AAE9C,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI;AACF,MAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,CAAM,eAAe,OAAA,CAAQ,GAAG,KAAK,MAAM,CAAA;AAC9D,MAAA,IACE,KAAA,EAAO,WAAW,IAAA,CAAK,EAAA,IACvB,OAAO,MAAA,KAAW,MAAA,IAClB,OAAO,QAAA,CAAS,KAAA,CAAM,QAAQ,CAAA,IAC9B,KAAA,CAAM,QAAQ,KAAA,CAAM,OAAO,KAC3B,KAAA,CAAM,OAAA,CAAQ,KAAA,CAAM,CAAC,MAAA,KAAoB;AACvC,QAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,EAAU;AACzC,UAAA,OAAO,KAAA;AAAA,QACT;AACA,QAAA,MAAMC,MAAAA,GAAQ,MAAA;AACd,QAAA,OACE,OAAOA,MAAAA,CAAM,OAAA,KAAY,QAAA,IACzB,OAAOA,MAAAA,CAAM,QAAA,KAAa,QAAA,IAC1B,MAAA,CAAO,QAAA,CAASA,MAAAA,CAAM,QAAQ,CAAA;AAAA,MAElC,CAAC,CAAA,IACD,KAAA,CAAM,UACN,OAAO,KAAA,CAAM,WAAW,QAAA,IACxB,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAM,MAAM,CAAA,IAC3B,OAAO,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,CAAE,KAAA;AAAA,QAC1B,CAACA,MAAAA,KACC,OAAOA,MAAAA,KAAU,QAAA,IACjB,OAAOA,MAAAA,KAAU,SAAA,IAChB,OAAOA,MAAAA,KAAU,QAAA,IAAY,MAAA,CAAO,SAASA,MAAK;AAAA,OACvD,IACA,OAAO,KAAA,CAAM,IAAA,KAAS,QAAA,EACtB;AACA,QAAA,QAAA,CAAS;AAAA,UACP,GAAG,OAAA;AAAA,UACH,UAAU,KAAA,CAAM,QAAA;AAAA,UAChB,SAAS,KAAA,CAAM,OAAA;AAAA,UACf,QAAQ,KAAA,CAAM,MAAA;AAAA,UACd,MAAM,KAAA,CAAM;AAAA,SACb,CAAA;AAAA,MACH;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,WAAA,CAAY,IAAI,CAAA;AAAA,EAClB,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AAER,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,IAAI;AACF,QAAA,cAAA,CAAe,OAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,MACnD,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,CAAA,EAAG,CAAC,GAAA,EAAK,KAAA,EAAO,QAAQ,CAAC,CAAA;AAEzB,EAAA,MAAM,QAAQ,MAAM;AAClB,IAAA,IAAI;AACF,MAAA,cAAA,CAAe,WAAW,GAAG,CAAA;AAAA,IAC/B,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,EAAE,KAAA,EAAO,QAAA,EAAU,QAAA,EAAU,KAAA,EAAM;AAC5C;ACtFO,SAAS,QAAA,CAAS;AAAA,EACvB,EAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA,EAIG;AACD,EAAA,MAAM,OAAA,GAAU,UAAA,CAAW,cAAA,EAAgB,EAAE,CAAA;AAC7C,EAAA,MAAM,UAAA,GAAa,cAAc,yBAAyB,CAAA;AAC1D,EAAA,uBACEC,IAAAA;AAAA,IAAC,OAAA,CAAQ,IAAA;AAAA,IAAR;AAAA,MACC,KAAA,EAAM,cAAA;AAAA,MACN,EAAA;AAAA,MACA,YAAA,EAAc,EAAE,IAAA,EAAM,QAAA,EAAU,IAAI,QAAA,EAAS;AAAA,MAE7C,QAAA,EAAA;AAAA,wBAAAC,GAAAA,CAAC,QAAQ,OAAA,EAAR,EAAgB,WAAU,yBAAA,EACxB,QAAA,EAAA,KAAA,GAAQ,cAAc,UAAA,EACzB,CAAA;AAAA,wBACAD,KAAC,OAAA,CAAQ,OAAA,EAAR,EAAgB,mBAAA,EAAkB,MAAA,EAAO,WAAW,UAAA,EACnD,QAAA,EAAA;AAAA,0BAAAA,IAAAA,CAAC,QAAA,EAAA,EAAO,SAAA,EAAU,oBAAA,EAChB,QAAA,EAAA;AAAA,4BAAAC,GAAAA,CAAC,OAAA,CAAQ,KAAA,EAAR,EAAc,QAAA,EAAA,YAAA,EAAU,CAAA;AAAA,4BACzBA,GAAAA;AAAA,cAAC,OAAA,CAAQ,KAAA;AAAA,cAAR;AAAA,gBACC,SAAA,EAAU,yBAAA;AAAA,gBACV,YAAA,EAAW,YAAA;AAAA,gBACZ,QAAA,EAAA;AAAA;AAAA;AAED,WAAA,EACF,CAAA;AAAA,0BACAD,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kBAAA,EACb,QAAA,EAAA;AAAA,4BAAAA,IAAAA,CAAC,OAAA,EAAA,EAAM,SAAA,EAAU,cAAA,EAAe,QAAA,EAAA;AAAA,cAAA,MAAA;AAAA,8BAE9BC,GAAAA;AAAA,gBAAC,UAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAU,cAAA;AAAA,kBACV,SAAA,EAAW,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,MAAM,MAAM,CAAA;AAAA,kBACpC,KAAA;AAAA,kBACA,UAAU,CAAC,KAAA,KAAU,QAAA,CAAS,KAAA,CAAM,OAAO,KAAK;AAAA;AAAA;AAClD,aAAA,EACF,CAAA;AAAA,4BACAA,GAAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,SAAA,EAAU,eAAA;AAAA,gBACV,SAAS,OAAA,CAAQ,KAAA;AAAA,gBAClB,QAAA,EAAA;AAAA;AAAA;AAED,WAAA,EACF;AAAA,SAAA,EACF;AAAA;AAAA;AAAA,GACF;AAEJ;ACpDO,SAAS,aAAA,CAAc;AAAA,EAC5B,IAAA;AAAA,EACA;AACF,CAAA,EAGG;AACD,EAAA,MAAM,OAAA,GAAU,KAAK,QAAA,CAAS,MAAA;AAAA,IAAO,CAAC,OAAA,KACpC,MAAA,CAAO,OAAA,CAAQ,OAAA,CAAQ,gBAAgB,CAAA,CAAE,KAAA;AAAA,MAAM,CAAC,CAAC,OAAA,EAAS,QAAQ,CAAA,KAChE,MAAM,OAAA,EAAS,IAAA;AAAA,QACb,CAAC,MAAA,KAAW,MAAA,CAAO,OAAA,KAAY,OAAA,IAAW,OAAO,QAAA,KAAa;AAAA;AAChE;AACF,GACF;AACA,EAAA,MAAM,WAAW,OAAA,CAAQ,MAAA,KAAW,CAAA,GAAI,OAAA,CAAQ,CAAC,CAAA,GAAI,MAAA;AACrD,EAAA,IAAI,CAAC,IAAA,CAAK,WAAA,IAAe,CAAC,QAAA,EAAU;AAClC,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,CAAC,QAAA,CAAS,WAAA,mBACfA,GAAAA,CAAC,GAAA,EAAA,EAAE,MAAK,QAAA,EAAS,QAAA,EAAA,cAAA,EAAY,CAAA,GAC3B,QAAA,CAAS,2BACXA,GAAAA,CAAC,OAAE,IAAA,EAAK,QAAA,EAAS,uBAAS,CAAA,GACxB,IAAA;AACN;ACZO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,IAAA;AAAA,EACA,MAAA;AAAA,EACA,IAAA;AAAA,EACA,UAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA,GAAY,KAAA;AAAA,EACZ;AACF,CAAA,EAQG;AACD,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAU,QAAA,EAAU,KAAA,KAAU,oBAAA,CAAqB;AAAA,IAChE,IAAA;AAAA,IACA,GAAI,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,KAAW,EAAC;AAAA,IACzC,GAAI,IAAA,KAAS,MAAA,GAAY,EAAE,IAAA,KAAS,EAAC;AAAA,IACrC;AAAA,GACD,CAAA;AACD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIH,QAAAA,EAAiB;AAC3C,EAAA,MAAM,QAAA,GAAW,wBAAA,CAAyB,MAAA,EAAQ,IAAI,CAAA;AACtD,EAAA,uBACEG,GAAAA;AAAA,IAACC,QAAAA,CAAS,IAAA;AAAA,IAAT;AAAA,MACC,IAAA;AAAA,MACA,KAAA;AAAA,MACA,aAAA,EAAe,CAAC,IAAA,KAAS;AACvB,QAAA,MAAM,SAAA,GAAY,EAAE,GAAG,IAAA,EAAK;AAC5B,QAAA,OAAO,SAAA,CAAU,SAAA;AACjB,QAAA,QAAA,CAAS,SAAS,CAAA;AAClB,QAAA,QAAA,CAAS,MAAS,CAAA;AAAA,MACpB,CAAA;AAAA,MACC,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa,EAAC;AAAA,MAChC,SAAS,MAAM;AACb,QAAA,IAAI,CAAC,IAAA,EAAM;AACT,UAAA,UAAA,CAAW,KAAK,CAAA;AAAA,QAClB;AACA,QAAA,KAAA,EAAM;AACN,QAAA,UAAA,EAAW;AAAA,MACb,CAAA;AAAA,MACA,SAAA,EAAU,qBAAA;AAAA,MAET,QAAA,EAAA,CAAC,aAAA,qBACAF,IAAAA,CAACG,UAAA,EACC,QAAA,EAAA;AAAA,wBAAAH,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qBAAA,EACZ,QAAA,EAAA;AAAA,UAAA,SAAA,oBACCA,IAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,mBAAA,EACX,QAAA,EAAA;AAAA,4BAAAC,GAAAA,CAACG,KAAAA,EAAA,EAAM,KAAA,EAAO,cAAc,SAAA,EAAW,CAAA;AAAA,YACtC,IAAA,CAAK,cAAA,oBACJH,GAAAA,CAAC,KAAA,EAAA,EACC,QAAA,kBAAAA,GAAAA,CAACG,KAAAA,EAAA,EAAM,KAAA,EAAO,IAAA,CAAK,cAAA,EAAgB,CAAA,EACrC;AAAA,WAAA,EAEJ,CAAA;AAAA,UAED,CAAC,wBACAH,GAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAI,IAAA,CAAK,EAAA;AAAA,cACT,KAAA,EAAO,MAAM,IAAA,IAAQ,EAAA;AAAA,cACrB,QAAA,EAAU,CAAC,IAAA,KAAS,aAAA,CAAc,SAAS,EAAE,GAAG,KAAA,EAAO,IAAA,EAAM;AAAA;AAAA;AAC/D,SAAA,EAEJ,CAAA;AAAA,QACC,IAAA,oBACCD,IAAAA,CAAC,OAAA,EAAA,EAAM,WAAU,cAAA,EAAe,QAAA,EAAA;AAAA,UAAA,MAAA;AAAA,0BAE9BC,GAAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAU,cAAA;AAAA,cACV,SAAA,EAAW,OAAO,GAAA,GAAM,IAAA,CAAK,IAAI,EAAA,EAAI,KAAA,CAAM,IAAA,EAAM,MAAA,IAAU,CAAC,CAAA;AAAA,cAC5D,KAAA,EAAO,MAAM,IAAA,IAAQ,EAAA;AAAA,cACrB,QAAA,EAAU,CAAC,KAAA,KACT,aAAA,CAAc,QAAA,CAAS,EAAE,GAAG,KAAA,EAAO,IAAA,EAAM,KAAA,CAAM,MAAA,CAAO,KAAA,EAAO;AAAA;AAAA;AAEjE,SAAA,EACF,CAAA;AAAA,QAED,6BACCA,GAAAA,CAAC,iBAAc,IAAA,EAAY,KAAA,EAAO,cAAc,KAAA,EAAO,CAAA;AAAA,QAExD,YAAA;AAAA,wBACDA,IAAC,WAAA,EAAA,EAAY,CAAA;AAAA,QACZ,aAAA,CAAc,MAAA,CAAO,MAAA,GAAS,CAAA,oBAC7BA,GAAAA,CAAC,KAAA,EAAA,EAAI,IAAA,EAAK,OAAA,EACP,QAAA,EAAA,aAAA,CAAc,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,EAAO,KAAA,qBAChCA,GAAAA,CAAC,GAAA,EAAA,EACE,QAAA,EAAA,KAAA,CAAM,OAAA,EAAA,EADD,CAAA,EAAG,KAAA,CAAM,IAAI,CAAA,CAAA,EAAI,KAAA,CAAM,OAAO,CAAA,CAAA,EAAI,KAAK,CAAA,CAE/C,CACD,CAAA,EACH,CAAA;AAAA,QAED,yBAASA,GAAAA,CAAC,GAAA,EAAA,EAAE,IAAA,EAAK,SAAS,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,QAChC,IAAA,oBACCD,IAAAA,CAAC,GAAA,EAAA,EAAE,aAAU,QAAA,EAAS,QAAA,EAAA;AAAA,UAAA,mBAAA;AAAA,0BACHC,GAAAA,CAACG,KAAAA,EAAA,EAAM,KAAA,EAAO,cAAc,KAAA,EAAO;AAAA,SAAA,EACtD,CAAA;AAAA,wBAEFJ,IAAAA,CAAC,QAAA,EAAA,EAAO,SAAA,EAAU,sBAAA,EAChB,QAAA,EAAA;AAAA,0BAAAA,IAAAA;AAAA,YAACK,QAAAA,CAAS,IAAA;AAAA,YAAT;AAAA,cACC,SAAA,EAAU,iBAAA;AAAA,cACV,OAAO,aAAA,CAAc,QAAA;AAAA,cACrB,GAAA,EAAK,KAAK,QAAA,CAAS,GAAA;AAAA,cACnB,KAAK,IAAA,CAAK,GAAA,CAAI,KAAK,QAAA,CAAS,GAAA,IAAO,IAAI,EAAE,CAAA;AAAA,cACzC,IAAA,EAAM,KAAK,QAAA,CAAS,IAAA;AAAA,cACpB,eAAe,aAAA,CAAc,WAAA;AAAA,cAE7B,QAAA,EAAA;AAAA,gCAAAJ,IAACI,QAAAA,CAAS,SAAA,EAAT,EAAmB,YAAA,EAAW,qBAAoB,QAAA,EAAA,QAAA,EAEnD,CAAA;AAAA,gCACAJ,GAAAA,CAACI,QAAAA,CAAS,KAAA,EAAT,EAAe,cAAW,eAAA,EAAgB,CAAA;AAAA,gCAC3CJ,GAAAA,CAACI,QAAAA,CAAS,WAAT,EAAmB,YAAA,EAAW,qBAAoB,QAAA,EAAA,GAAA,EAEnD;AAAA;AAAA;AAAA,WACF;AAAA,0BACAL,IAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,SAAA,EAAU,eAAA;AAAA,cACV,QAAA,EAAU,CAAC,QAAA,IAAY,CAAC,IAAA,CAAK,WAAA;AAAA,cAC7B,SAAS,MAAM;AACb,gBAAA,IAAI;AACF,kBAAA,aAAA,CAAc,GAAA,EAAI;AAAA,gBACpB,SAAS,OAAA,EAAS;AAChB,kBAAA,QAAA;AAAA,oBACE,OAAA,YAAmB,KAAA,GACf,OAAA,CAAQ,OAAA,GACR;AAAA,mBACN;AAAA,gBACF;AAAA,cACF,CAAA;AAAA,cAEC,QAAA,EAAA;AAAA,gBAAA,IAAA,CAAK,WAAA,GACF,IAAA,GACE,cAAA,GACA,KAAA,GACD,KAAK,UAAA,IAAc,aAAA;AAAA,gBAAgB,GAAA;AAAA,gBACvC,CAAC,wBAAQC,GAAAA,CAACG,OAAA,EAAM,KAAA,EAAO,cAAc,KAAA,EAAO;AAAA;AAAA;AAAA;AAC/C,SAAA,EACF;AAAA,OAAA,EACF;AAAA;AAAA,GAEJ;AAEJ","file":"chunk-2MV6KU3R.js","sourcesContent":["import {\n Choice,\n ItemForm,\n Money,\n OptionGroup,\n Quantity,\n} from \"@zappie/foundations\";\nimport type { OptionGroup as Group } from \"@zappie/sdk\";\nimport { Fragment, useState } from \"react\";\nexport function LineOptions() {\n return (\n <ItemForm.Options>\n {({ groups }) =>\n [...groups]\n .sort(\n (left, right) =>\n Number(right.isAttribute) - Number(left.isAttribute),\n )\n .map((group) => <OptionsSection key={group.id} group={group} />)\n }\n </ItemForm.Options>\n );\n}\nfunction OptionsSection({ group }: { group: Group }) {\n const [expanded, setExpanded] = useState(true);\n const count =\n group.selection.max === group.selection.min && group.selection.min > 0\n ? `Exactly ${group.selection.min}`\n : group.selection.max\n ? `Choose up to ${group.selection.max}`\n : group.selection.min\n ? `Choose at least ${group.selection.min}`\n : \"Optional\";\n return (\n <OptionGroup\n group={group}\n className=\"z-base-option-group\"\n aria-label={group.name}\n >\n {({ quantities, setQuantity, invalid }) => (\n <Fragment>\n <h3 className=\"z-base-option-heading\">\n <button\n type=\"button\"\n aria-expanded={expanded || invalid}\n onClick={() => setExpanded(!expanded)}\n >\n <span>{group.name}</span>\n <span className=\"z-base-option-rule\">\n {count}\n {group.required && <strong> Required*</strong>}\n </span>\n <span aria-hidden=\"true\" className=\"z-base-option-chevron\">\n {expanded || invalid ? \"⌄\" : \"›\"}\n </span>\n </button>\n </h3>\n {(expanded || invalid) && (\n <div className=\"z-base-option-choices\">\n {group.helpText && <p>{group.helpText}</p>}\n {group.kind === \"select\" &&\n group.choices.map((choice) => (\n <div key={choice.id} className=\"z-base-choice-row\">\n <Choice choice={choice} className=\"z-base-choice\">\n <span className=\"z-base-choice-label\">\n <span>{choice.name}</span>\n {(choice.priceHint ?? choice.price).amountMinor !==\n 0 && (\n <span className=\"z-base-choice-price\">\n {(choice.priceHint ?? choice.price).amountMinor > 0\n ? \"+\"\n : \"\"}\n <Money value={choice.priceHint ?? choice.price} />\n </span>\n )}\n {!choice.isAvailable && (\n <span className=\"z-base-choice-price\">\n Unavailable\n </span>\n )}\n </span>\n </Choice>\n {choice.quantity && (quantities[choice.id] ?? 0) > 0 && (\n <Quantity.Root\n className=\"z-base-quantity\"\n value={quantities[choice.id] ?? 0}\n min={0}\n max={choice.quantity.max ?? 99}\n disabled={!choice.isAvailable}\n onValueChange={(quantity) =>\n setQuantity(choice.id, quantity)\n }\n >\n <Quantity.Decrement\n aria-label={`Decrease ${choice.name}`}\n >\n −\n </Quantity.Decrement>\n <Quantity.Value\n aria-label={`${choice.name} quantity`}\n />\n <Quantity.Increment\n aria-label={`Increase ${choice.name}`}\n >\n +\n </Quantity.Increment>\n </Quantity.Root>\n )}\n </div>\n ))}\n {(group.kind !== \"select\" || group.isInformational) && (\n <OptionGroup.Input className=\"z-base-input\" />\n )}\n </div>\n )}\n </Fragment>\n )}\n </OptionGroup>\n );\n}\n","import type { CartLine, CartLineInput, Zappie } from \"@zappie/sdk\";\n\nexport function createConfiguratorCommit(\n client: Zappie,\n line: CartLine | undefined,\n) {\n if (!line) {\n return undefined;\n }\n return (input: CartLineInput) => {\n const nextInput = { ...input };\n delete nextInput.variantId;\n return client.cart.update(line.id, nextInput);\n };\n}\n","import type { CartLine, CartLineInput, Item } from \"@zappie/sdk\";\nimport { useEffect, useState } from \"react\";\n\nexport function useConfiguratorDraft({\n item,\n menuId,\n line,\n scope,\n}: {\n item: Item;\n menuId?: string;\n line?: CartLine;\n scope: string;\n}) {\n const key = `zappie:product-draft:${scope}:${item.id}:${menuId ?? \"\"}:${line?.id ?? \"new\"}`;\n const initial: CartLineInput = {\n itemId: item.id,\n ...(menuId !== undefined ? { menuId } : {}),\n quantity: line?.quantity ?? item.quantity.min,\n choices: line?.choices.map((choice) => ({ ...choice })) ?? [],\n inputs: { ...line?.inputs },\n note: line?.note ?? \"\",\n };\n const [value, setValue] = useState(initial);\n const [restored, setRestored] = useState(false);\n\n useEffect(() => {\n try {\n const saved = JSON.parse(sessionStorage.getItem(key) ?? \"null\");\n if (\n saved?.itemId === item.id &&\n saved?.menuId === menuId &&\n Number.isFinite(saved.quantity) &&\n Array.isArray(saved.choices) &&\n saved.choices.every((choice: unknown) => {\n if (!choice || typeof choice !== \"object\") {\n return false;\n }\n const value = choice as Record<string, unknown>;\n return (\n typeof value.groupId === \"string\" &&\n typeof value.choiceId === \"string\" &&\n Number.isFinite(value.quantity)\n );\n }) &&\n saved.inputs &&\n typeof saved.inputs === \"object\" &&\n !Array.isArray(saved.inputs) &&\n Object.values(saved.inputs).every(\n (value) =>\n typeof value === \"string\" ||\n typeof value === \"boolean\" ||\n (typeof value === \"number\" && Number.isFinite(value)),\n ) &&\n typeof saved.note === \"string\"\n ) {\n setValue({\n ...initial,\n quantity: saved.quantity,\n choices: saved.choices,\n inputs: saved.inputs,\n note: saved.note,\n });\n }\n } catch {\n // A draft is optional; storage failure never prevents configuring an item.\n }\n setRestored(true);\n }, [key]);\n\n useEffect(() => {\n if (restored) {\n try {\n sessionStorage.setItem(key, JSON.stringify(value));\n } catch {\n // Keep the in-memory draft when storage is unavailable.\n }\n }\n }, [key, value, restored]);\n\n const clear = () => {\n try {\n sessionStorage.removeItem(key);\n } catch {\n // Saving the cart succeeded; a failed optional draft cleanup must not undo it.\n }\n };\n\n return { clear, restored, setValue, value };\n}\n","\"use client\";\nimport { Overlay, useOverlay } from \"@zappie/foundations\";\nimport { useThemeClass } from \"../cart/theme-class\";\nexport function ItemNote({\n id,\n value,\n onChange,\n}: {\n id: string;\n value: string;\n onChange(value: string): void;\n}) {\n const overlay = useOverlay(\"product_note\", id);\n const themeClass = useThemeClass(\"z-base-cart z-base-note\");\n return (\n <Overlay.Root\n param=\"product_note\"\n id={id}\n presentation={{ base: \"drawer\", lg: \"dialog\" }}\n >\n <Overlay.Trigger className=\"z-base-button-secondary\">\n {value ? \"Edit Note\" : \"Add Note\"}\n </Overlay.Trigger>\n <Overlay.Content data-zappie-theme=\"base\" className={themeClass}>\n <header className=\"z-base-cart-header\">\n <Overlay.Title>Add a note</Overlay.Title>\n <Overlay.Close\n className=\"z-base-button-secondary\"\n aria-label=\"Close note\"\n >\n ✕\n </Overlay.Close>\n </header>\n <div className=\"z-base-cart-body\">\n <label className=\"z-base-field\">\n Note\n <textarea\n className=\"z-base-input\"\n maxLength={Math.max(35, value.length)}\n value={value}\n onChange={(event) => onChange(event.target.value)}\n />\n </label>\n <button\n type=\"button\"\n className=\"z-base-button\"\n onClick={overlay.close}\n >\n Add note\n </button>\n </div>\n </Overlay.Content>\n </Overlay.Root>\n );\n}\n","import type { CartLineInput, Item } from \"@zappie/sdk\";\n\nexport function VariantStatus({\n item,\n value,\n}: {\n item: Item;\n value: CartLineInput;\n}) {\n const matches = item.variants.filter((variant) =>\n Object.entries(variant.attributeChoices).every(([groupId, choiceId]) =>\n value.choices?.some(\n (choice) => choice.groupId === groupId && choice.choiceId === choiceId,\n ),\n ),\n );\n const selected = matches.length === 1 ? matches[0] : undefined;\n if (!item.isAvailable || !selected) {\n return null;\n }\n return !selected.isAvailable ? (\n <p role=\"status\">Out of stock</p>\n ) : selected.lowStock ? (\n <p role=\"status\">Low stock</p>\n ) : null;\n}\n","\"use client\";\nimport { ItemForm, Money, Quantity } from \"@zappie/foundations\";\nimport type { CartLine, Item } from \"@zappie/sdk\";\nimport { useZappie } from \"@zappie/sdk/react\";\nimport { countEvent } from \"@zappie/sdk/visits\";\nimport { Fragment, useState, type ReactNode } from \"react\";\nimport { LineOptions } from \"../cart/line-options\";\nimport { createConfiguratorCommit } from \"./configurator-commit\";\nimport { useConfiguratorDraft } from \"./configurator-draft\";\nimport { ItemNote } from \"./note\";\nimport { VariantStatus } from \"./variant-status\";\n\n/** The same draft and validation workflow for an item, an inline row and a cart edit. */\nexport function ItemConfigurator({\n item,\n menuId,\n line,\n onComplete,\n scope,\n showPrice = false,\n introduction,\n}: {\n item: Item;\n menuId?: string;\n line?: CartLine;\n onComplete(): void;\n scope: string;\n showPrice?: boolean;\n introduction?: ReactNode;\n}) {\n const client = useZappie();\n const { clear, restored, setValue, value } = useConfiguratorDraft({\n item,\n ...(menuId !== undefined ? { menuId } : {}),\n ...(line !== undefined ? { line } : {}),\n scope,\n });\n const [error, setError] = useState<string>();\n const onCommit = createConfiguratorCommit(client, line);\n return (\n <ItemForm.Root\n item={item}\n value={value}\n onValueChange={(next) => {\n const nextValue = { ...next };\n delete nextValue.variantId;\n setValue(nextValue);\n setError(undefined);\n }}\n {...(onCommit ? { onCommit } : {})}\n onAdded={() => {\n if (!line) {\n countEvent(\"add\");\n }\n clear();\n onComplete();\n }}\n className=\"z-base-configurator\"\n >\n {(configuration) => (\n <Fragment>\n <div className=\"z-base-item-summary\">\n {showPrice && (\n <p className=\"z-base-item-price\">\n <Money value={configuration.unitPrice} />\n {item.compareAtPrice && (\n <del>\n <Money value={item.compareAtPrice} />\n </del>\n )}\n </p>\n )}\n {!line && (\n <ItemNote\n id={item.id}\n value={value.note ?? \"\"}\n onChange={(note) => configuration.setValue({ ...value, note })}\n />\n )}\n </div>\n {line && (\n <label className=\"z-base-field\">\n Note\n <textarea\n className=\"z-base-input\"\n maxLength={line ? 280 : Math.max(35, value.note?.length ?? 0)}\n value={value.note ?? \"\"}\n onChange={(event) =>\n configuration.setValue({ ...value, note: event.target.value })\n }\n />\n </label>\n )}\n {showPrice && (\n <VariantStatus item={item} value={configuration.value} />\n )}\n {introduction}\n <LineOptions />\n {configuration.issues.length > 0 && (\n <div role=\"alert\">\n {configuration.issues.map((issue, index) => (\n <p key={`${issue.code}:${issue.groupId}:${index}`}>\n {issue.message}\n </p>\n ))}\n </div>\n )}\n {error && <p role=\"alert\">{error}</p>}\n {line && (\n <p aria-live=\"polite\">\n Estimated total: <Money value={configuration.total} />\n </p>\n )}\n <footer className=\"z-base-item-purchase\">\n <Quantity.Root\n className=\"z-base-quantity\"\n value={configuration.quantity}\n min={item.quantity.min}\n max={Math.min(item.quantity.max ?? 99, 99)}\n step={item.quantity.step}\n onValueChange={configuration.setQuantity}\n >\n <Quantity.Decrement aria-label=\"Decrease quantity\">\n −\n </Quantity.Decrement>\n <Quantity.Value aria-label=\"Item quantity\" />\n <Quantity.Increment aria-label=\"Increase quantity\">\n +\n </Quantity.Increment>\n </Quantity.Root>\n <button\n type=\"button\"\n className=\"z-base-button\"\n disabled={!restored || !item.isAvailable}\n onClick={() => {\n try {\n configuration.add();\n } catch (failure) {\n setError(\n failure instanceof Error\n ? failure.message\n : \"Unable to save this item. Please try again.\",\n );\n }\n }}\n >\n {item.isAvailable\n ? line\n ? \"Save changes\"\n : \"Add\"\n : (item.stockLabel ?? \"Unavailable\")}{\" \"}\n {!line && <Money value={configuration.total} />}\n </button>\n </footer>\n </Fragment>\n )}\n </ItemForm.Root>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cart/clear-cart.tsx","../src/cart/line-editor.tsx","../src/cart/cart-line.tsx"],"names":["useOverlay","jsxs","Overlay","jsx","useCart","group","choice"],"mappings":"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","file":"chunk-FB5DRCU7.js","sourcesContent":["import { Overlay, useOverlay } from \"@zappie/foundations\";\nimport { useCart } from \"@zappie/sdk/react\";\nimport { useThemeClass } from \"./theme-class\";\n/** Clearing removes every line, so it asks first, as the legacy cart does. */\nexport function ClearCart() {\n const rootClass = useThemeClass(\"z-base-cart z-base-confirm\");\n const cart = useCart();\n const confirm = useOverlay(\"cart_clear\", \"confirm\");\n return (\n <Overlay.Root param=\"cart_clear\" id=\"confirm\" presentation=\"dialog\">\n <Overlay.Trigger className=\"z-base-button-secondary\">\n Clear cart\n </Overlay.Trigger>\n <Overlay.Content\n data-zappie-theme=\"base\"\n role=\"alertdialog\"\n className={rootClass}\n >\n <Overlay.Title>Clear your cart?</Overlay.Title>\n <p>This removes every item in your cart.</p>\n <div className=\"z-base-confirm-actions\">\n <Overlay.Close className=\"z-base-button-secondary\">\n Keep items\n </Overlay.Close>\n <button\n type=\"button\"\n className=\"z-base-button\"\n onClick={() => {\n cart.actions.clear();\n confirm.close();\n }}\n >\n Clear cart\n </button>\n </div>\n </Overlay.Content>\n </Overlay.Root>\n );\n}\n","import { Overlay, useOverlay } from \"@zappie/foundations\";\nimport type { CartLine, Item } from \"@zappie/sdk\";\nimport { useZappie } from \"@zappie/sdk/react\";\nimport { ItemConfigurator } from \"../item/configurator\";\nimport { useThemeClass } from \"./theme-class\";\nexport function LineEditor({ line, item }: { line: CartLine; item: Item }) {\n const rootClass = useThemeClass(\"z-base-cart z-base-editor\");\n const overlay = useOverlay(\"cart_edit\", line.id);\n const client = useZappie();\n return (\n <Overlay.Content data-zappie-theme=\"base\" className={rootClass}>\n <header className=\"z-base-cart-header\">\n <Overlay.Title>Edit {line.name}</Overlay.Title>\n <Overlay.Close className=\"z-base-button-secondary\">\n Cancel\n </Overlay.Close>\n </header>\n {overlay.isOpen && (\n <div className=\"z-base-cart-body\">\n <ItemConfigurator\n key={line.id}\n item={item}\n {...(line.menuId !== undefined ? { menuId: line.menuId } : {})}\n line={line}\n scope={`${client.config.store}:${client.cart.branchId}:${client.cart.fulfilment?.type}`}\n onComplete={overlay.close}\n />\n </div>\n )}\n </Overlay.Content>\n );\n}\n","import { Cart, Money, Overlay, Quantity } from \"@zappie/foundations\";\nimport type { CartLine as Line } from \"@zappie/sdk\";\nimport { useCart } from \"@zappie/sdk/react\";\nimport { LineEditor } from \"./line-editor\";\nexport function CartLine({ line }: { line: Line }) {\n const cart = useCart();\n const invalid = cart.issues.some(\n (issue) => issue.lineId === line.id && issue.severity === \"blocking\",\n );\n return (\n <Cart.Line line={line} className=\"z-base-line\">\n {({ item }) => (\n <>\n <div className=\"z-base-line-heading\">\n <h3>{line.name}</h3>\n {item && !invalid ? (\n <Money value={line.lineSubtotal} />\n ) : (\n <span>Price unavailable</span>\n )}\n </div>\n <ul className=\"z-base-line-options\">\n {line.choices.map((selection) => {\n const group = item?.optionGroups.find(\n (group) => group.id === selection.groupId,\n );\n const choice = group?.choices.find(\n (choice) => choice.id === selection.choiceId,\n );\n return (\n <li key={`${selection.groupId}:${selection.choiceId}`}>\n {choice?.name ?? \"Unavailable option\"}\n {selection.quantity > 1 ? ` × ${selection.quantity}` : \"\"}\n </li>\n );\n })}\n {Object.entries(line.inputs).map(([id, value]) => (\n <li key={id}>\n {item?.optionGroups.find((group) => group.id === id)?.name ??\n \"Details\"}\n : {value}\n </li>\n ))}\n </ul>\n {line.note && <p className=\"z-base-muted\">{line.note}</p>}\n <div className=\"z-base-line-actions\">\n <Cart.Quantity\n lineId={line.id}\n disabled={invalid}\n className=\"z-base-quantity\"\n >\n <Quantity.Decrement aria-label={`Decrease ${line.name} quantity`}>\n −\n </Quantity.Decrement>\n <Quantity.Value aria-label={`${line.name} quantity`} />\n <Quantity.Increment aria-label={`Increase ${line.name} quantity`}>\n +\n </Quantity.Increment>\n </Cart.Quantity>\n <Overlay.Root\n param=\"cart_edit\"\n id={line.id}\n presentation={{ base: \"sheet\", lg: \"dialog\" }}\n >\n <Overlay.Trigger\n className=\"z-base-button-secondary\"\n disabled={!item}\n aria-label={`Edit ${line.name}`}\n >\n Edit\n </Overlay.Trigger>\n {item && <LineEditor line={line} item={item} />}\n </Overlay.Root>\n <Cart.Remove\n lineId={line.id}\n className=\"z-base-button-secondary\"\n aria-label={`Remove ${line.name}`}\n >\n Remove\n </Cart.Remove>\n </div>\n </>\n )}\n </Cart.Line>\n );\n}\n"]}