@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
@@ -0,0 +1,35 @@
1
+ // src/cart/line-editor.tsx
2
+ import { Overlay, useOverlay } from "@zappie/foundations";
3
+ import { useZappie } from "@zappie/sdk/react";
4
+ import { ItemConfigurator } from "../item/configurator.js";
5
+ import { useThemeClass } from "./theme-class.js";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ function LineEditor({ line, item }) {
8
+ const rootClass = useThemeClass("z-base-cart z-base-editor");
9
+ const overlay = useOverlay("cart_edit", line.id);
10
+ const client = useZappie();
11
+ return /* @__PURE__ */ jsxs(Overlay.Content, { "data-zappie-theme": "base", className: rootClass, children: [
12
+ /* @__PURE__ */ jsxs("header", { className: "z-base-cart-header", children: [
13
+ /* @__PURE__ */ jsxs(Overlay.Title, { children: [
14
+ "Edit ",
15
+ line.name
16
+ ] }),
17
+ /* @__PURE__ */ jsx(Overlay.Close, { className: "z-base-button-secondary", children: "Cancel" })
18
+ ] }),
19
+ overlay.isOpen && /* @__PURE__ */ jsx("div", { className: "z-base-cart-body", children: /* @__PURE__ */ jsx(
20
+ ItemConfigurator,
21
+ {
22
+ item,
23
+ ...line.menuId !== void 0 ? { menuId: line.menuId } : {},
24
+ line,
25
+ scope: `${client.config.store}:${client.cart.branchId}:${client.cart.fulfilment?.type}`,
26
+ onComplete: overlay.close
27
+ },
28
+ line.id
29
+ ) })
30
+ ] });
31
+ }
32
+ export {
33
+ LineEditor
34
+ };
35
+ //# sourceMappingURL=line-editor.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/line-editor.tsx"],
4
+ "sourcesContent": ["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"],
5
+ "mappings": ";AAAA,SAAS,SAAS,kBAAkB;AAEpC,SAAS,iBAAiB;AAC1B,SAAS,wBAAwB;AACjC,SAAS,qBAAqB;AAQtB,SACA,KADA;AAPD,SAAS,WAAW,EAAE,MAAM,KAAK,GAAmC;AACzE,QAAM,YAAY,cAAc,2BAA2B;AAC3D,QAAM,UAAU,WAAW,aAAa,KAAK,EAAE;AAC/C,QAAM,SAAS,UAAU;AACzB,SACE,qBAAC,QAAQ,SAAR,EAAgB,qBAAkB,QAAO,WAAW,WACnD;AAAA,yBAAC,YAAO,WAAU,sBAChB;AAAA,2BAAC,QAAQ,OAAR,EAAc;AAAA;AAAA,QAAM,KAAK;AAAA,SAAK;AAAA,MAC/B,oBAAC,QAAQ,OAAR,EAAc,WAAU,2BAA0B,oBAEnD;AAAA,OACF;AAAA,IACC,QAAQ,UACP,oBAAC,SAAI,WAAU,oBACb;AAAA,MAAC;AAAA;AAAA,QAEC;AAAA,QACC,GAAI,KAAK,WAAW,SAAY,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,QAC5D;AAAA,QACA,OAAO,GAAG,OAAO,OAAO,KAAK,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,YAAY,IAAI;AAAA,QACrF,YAAY,QAAQ;AAAA;AAAA,MALf,KAAK;AAAA,IAMZ,GACF;AAAA,KAEJ;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,96 @@
1
+ // src/cart/line-options.tsx
2
+ import {
3
+ Choice,
4
+ ItemForm,
5
+ Money,
6
+ OptionGroup,
7
+ Quantity
8
+ } from "@zappie/foundations";
9
+ import { Fragment, useState } from "react";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ function LineOptions() {
12
+ return /* @__PURE__ */ jsx(ItemForm.Options, { children: ({ groups }) => [...groups].sort(
13
+ (left, right) => Number(right.isAttribute) - Number(left.isAttribute)
14
+ ).map((group) => /* @__PURE__ */ jsx(OptionsSection, { group }, group.id)) });
15
+ }
16
+ function OptionsSection({ group }) {
17
+ const [expanded, setExpanded] = useState(true);
18
+ 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";
19
+ return /* @__PURE__ */ jsx(
20
+ OptionGroup,
21
+ {
22
+ group,
23
+ className: "z-base-option-group",
24
+ "aria-label": group.name,
25
+ children: ({ quantities, setQuantity, invalid }) => /* @__PURE__ */ jsxs(Fragment, { children: [
26
+ /* @__PURE__ */ jsx("h3", { className: "z-base-option-heading", children: /* @__PURE__ */ jsxs(
27
+ "button",
28
+ {
29
+ type: "button",
30
+ "aria-expanded": expanded || invalid,
31
+ onClick: () => setExpanded(!expanded),
32
+ children: [
33
+ /* @__PURE__ */ jsx("span", { children: group.name }),
34
+ /* @__PURE__ */ jsxs("span", { className: "z-base-option-rule", children: [
35
+ count,
36
+ group.required && /* @__PURE__ */ jsx("strong", { children: " Required*" })
37
+ ] }),
38
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "z-base-option-chevron", children: expanded || invalid ? "\u2304" : "\u203A" })
39
+ ]
40
+ }
41
+ ) }),
42
+ (expanded || invalid) && /* @__PURE__ */ jsxs("div", { className: "z-base-option-choices", children: [
43
+ group.helpText && /* @__PURE__ */ jsx("p", { children: group.helpText }),
44
+ group.kind === "select" && group.choices.map((choice) => /* @__PURE__ */ jsxs("div", { className: "z-base-choice-row", children: [
45
+ /* @__PURE__ */ jsx(Choice, { choice, className: "z-base-choice", children: /* @__PURE__ */ jsxs("span", { className: "z-base-choice-label", children: [
46
+ /* @__PURE__ */ jsx("span", { children: choice.name }),
47
+ (choice.priceHint ?? choice.price).amountMinor !== 0 && /* @__PURE__ */ jsxs("span", { className: "z-base-choice-price", children: [
48
+ (choice.priceHint ?? choice.price).amountMinor > 0 ? "+" : "",
49
+ /* @__PURE__ */ jsx(Money, { value: choice.priceHint ?? choice.price })
50
+ ] }),
51
+ !choice.isAvailable && /* @__PURE__ */ jsx("span", { className: "z-base-choice-price", children: "Unavailable" })
52
+ ] }) }),
53
+ choice.quantity && (quantities[choice.id] ?? 0) > 0 && /* @__PURE__ */ jsxs(
54
+ Quantity.Root,
55
+ {
56
+ className: "z-base-quantity",
57
+ value: quantities[choice.id] ?? 0,
58
+ min: 0,
59
+ max: choice.quantity.max ?? 99,
60
+ disabled: !choice.isAvailable,
61
+ onValueChange: (quantity) => setQuantity(choice.id, quantity),
62
+ children: [
63
+ /* @__PURE__ */ jsx(
64
+ Quantity.Decrement,
65
+ {
66
+ "aria-label": `Decrease ${choice.name}`,
67
+ children: "\u2212"
68
+ }
69
+ ),
70
+ /* @__PURE__ */ jsx(
71
+ Quantity.Value,
72
+ {
73
+ "aria-label": `${choice.name} quantity`
74
+ }
75
+ ),
76
+ /* @__PURE__ */ jsx(
77
+ Quantity.Increment,
78
+ {
79
+ "aria-label": `Increase ${choice.name}`,
80
+ children: "+"
81
+ }
82
+ )
83
+ ]
84
+ }
85
+ )
86
+ ] }, choice.id)),
87
+ (group.kind !== "select" || group.isInformational) && /* @__PURE__ */ jsx(OptionGroup.Input, { className: "z-base-input" })
88
+ ] })
89
+ ] })
90
+ }
91
+ );
92
+ }
93
+ export {
94
+ LineOptions
95
+ };
96
+ //# sourceMappingURL=line-options.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/line-options.tsx"],
4
+ "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 ? \"\u2304\" : \"\u203A\"}\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 \u2212\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"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,17 @@
1
+ // src/cart/loading.tsx
2
+ import { useStore } from "@zappie/sdk/react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ function Loading() {
5
+ const { error } = useStore();
6
+ if (error) {
7
+ return /* @__PURE__ */ jsx("p", { role: "alert", children: "Unable to load the cart. Reload the page to try again." });
8
+ }
9
+ return /* @__PURE__ */ jsxs("div", { className: "z-base-cart-empty", role: "status", "aria-busy": "true", children: [
10
+ /* @__PURE__ */ jsx("p", { children: "Loading cart\u2026" }),
11
+ /* @__PURE__ */ jsx("div", { className: "z-base-cart-placeholder", "aria-hidden": "true" })
12
+ ] });
13
+ }
14
+ export {
15
+ Loading
16
+ };
17
+ //# sourceMappingURL=loading.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/loading.tsx"],
4
+ "sourcesContent": ["import { useStore } from \"@zappie/sdk/react\";\nexport function Loading() {\n const { error } = useStore();\n if (error) {\n return (\n <p role=\"alert\">Unable to load the cart. Reload the page to try again.</p>\n );\n }\n return (\n <div className=\"z-base-cart-empty\" role=\"status\" aria-busy=\"true\">\n <p>Loading cart\u2026</p>\n <div className=\"z-base-cart-placeholder\" aria-hidden=\"true\" />\n </div>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,gBAAgB;AAKnB,cAIF,YAJE;AAJC,SAAS,UAAU;AACxB,QAAM,EAAE,MAAM,IAAI,SAAS;AAC3B,MAAI,OAAO;AACT,WACE,oBAAC,OAAE,MAAK,SAAQ,oEAAsD;AAAA,EAE1E;AACA,SACE,qBAAC,SAAI,WAAU,qBAAoB,MAAK,UAAS,aAAU,QACzD;AAAA,wBAAC,OAAE,gCAAa;AAAA,IAChB,oBAAC,SAAI,WAAU,2BAA0B,eAAY,QAAO;AAAA,KAC9D;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,103 @@
1
+ // src/cart/promo-sheet.tsx
2
+ import { useOverlay } from "@zappie/foundations";
3
+ import { useCart } from "@zappie/sdk/react";
4
+ import { useState } from "react";
5
+ import { useCheckoutHandoff } from "../checkout.js";
6
+ import { useBaseHostBridge } from "../host-bridge.js";
7
+ import { CartSheet } from "./cart-sheet.js";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ function PromoForm() {
10
+ const cart = useCart();
11
+ const bridge = useBaseHostBridge();
12
+ const overlay = useOverlay("cart_sheet", "promo");
13
+ const [code, setCode] = useState(cart.promoCode ?? "");
14
+ const [error, setError] = useState(null);
15
+ const save = (value) => {
16
+ try {
17
+ cart.actions.setPromoCode(value);
18
+ overlay.close();
19
+ } catch (failure) {
20
+ setError(
21
+ failure instanceof Error ? failure.message : "Unable to apply this code"
22
+ );
23
+ }
24
+ };
25
+ return /* @__PURE__ */ jsxs(
26
+ "form",
27
+ {
28
+ className: "z-base-field",
29
+ onSubmit: (event) => {
30
+ event.preventDefault();
31
+ save(code.trim());
32
+ },
33
+ children: [
34
+ /* @__PURE__ */ jsxs("label", { className: "z-base-field", children: [
35
+ "Promo code",
36
+ /* @__PURE__ */ jsx(
37
+ "input",
38
+ {
39
+ className: "z-base-input",
40
+ autoComplete: "off",
41
+ value: code,
42
+ onChange: (event) => setCode(event.target.value)
43
+ }
44
+ )
45
+ ] }),
46
+ /* @__PURE__ */ jsx("p", { children: "Discounts are confirmed when your order totals update." }),
47
+ bridge.availablePromos?.length ? /* @__PURE__ */ jsxs("section", { "aria-label": "Available promos", children: [
48
+ /* @__PURE__ */ jsx("h3", { children: "Available promos" }),
49
+ /* @__PURE__ */ jsx("ul", { className: "z-base-option-list", children: bridge.availablePromos.map((promo) => /* @__PURE__ */ jsxs("li", { children: [
50
+ /* @__PURE__ */ jsxs("div", { children: [
51
+ /* @__PURE__ */ jsx("strong", { children: promo.name }),
52
+ /* @__PURE__ */ jsx("p", { children: promo.description })
53
+ ] }),
54
+ /* @__PURE__ */ jsxs(
55
+ "button",
56
+ {
57
+ className: "z-base-button-secondary",
58
+ type: "button",
59
+ disabled: promo.disabled,
60
+ onClick: () => save(promo.code),
61
+ children: [
62
+ "Apply ",
63
+ promo.code
64
+ ]
65
+ }
66
+ )
67
+ ] }, promo.id)) })
68
+ ] }) : null,
69
+ error && /* @__PURE__ */ jsx("p", { role: "alert", children: error }),
70
+ /* @__PURE__ */ jsx("button", { className: "z-base-button", type: "submit", disabled: !code.trim(), children: "Apply code" }),
71
+ cart.promoCode && /* @__PURE__ */ jsx(
72
+ "button",
73
+ {
74
+ className: "z-base-button-secondary",
75
+ type: "button",
76
+ onClick: () => save(null),
77
+ children: "Remove code"
78
+ }
79
+ )
80
+ ]
81
+ }
82
+ );
83
+ }
84
+ function PromoSheet() {
85
+ const cart = useCart();
86
+ const handoff = useCheckoutHandoff();
87
+ if (!handoff.customer) {
88
+ return null;
89
+ }
90
+ return /* @__PURE__ */ jsx(
91
+ CartSheet,
92
+ {
93
+ id: "promo",
94
+ title: "Promo code",
95
+ trigger: cart.promoCode ? `Promo: ${cart.promoCode}` : "Add promo code",
96
+ children: /* @__PURE__ */ jsx(PromoForm, {})
97
+ }
98
+ );
99
+ }
100
+ export {
101
+ PromoSheet
102
+ };
103
+ //# sourceMappingURL=promo-sheet.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/promo-sheet.tsx"],
4
+ "sourcesContent": ["import { useOverlay } from \"@zappie/foundations\";\nimport { useCart } from \"@zappie/sdk/react\";\nimport { useState } from \"react\";\nimport { useCheckoutHandoff } from \"../checkout\";\nimport { useBaseHostBridge } from \"../host-bridge\";\nimport { CartSheet } from \"./cart-sheet\";\nfunction PromoForm() {\n const cart = useCart();\n const bridge = useBaseHostBridge();\n const overlay = useOverlay(\"cart_sheet\", \"promo\");\n const [code, setCode] = useState(cart.promoCode ?? \"\");\n const [error, setError] = useState<string | null>(null);\n const save = (value: string | null) => {\n try {\n cart.actions.setPromoCode(value);\n overlay.close();\n } catch (failure) {\n setError(\n failure instanceof Error\n ? failure.message\n : \"Unable to apply this code\",\n );\n }\n };\n return (\n <form\n className=\"z-base-field\"\n onSubmit={(event) => {\n event.preventDefault();\n save(code.trim());\n }}\n >\n <label className=\"z-base-field\">\n Promo code\n <input\n className=\"z-base-input\"\n autoComplete=\"off\"\n value={code}\n onChange={(event) => setCode(event.target.value)}\n />\n </label>\n <p>Discounts are confirmed when your order totals update.</p>\n {bridge.availablePromos?.length ? (\n <section aria-label=\"Available promos\">\n <h3>Available promos</h3>\n <ul className=\"z-base-option-list\">\n {bridge.availablePromos.map((promo) => (\n <li key={promo.id}>\n <div>\n <strong>{promo.name}</strong>\n <p>{promo.description}</p>\n </div>\n <button\n className=\"z-base-button-secondary\"\n type=\"button\"\n disabled={promo.disabled}\n onClick={() => save(promo.code)}\n >\n Apply {promo.code}\n </button>\n </li>\n ))}\n </ul>\n </section>\n ) : null}\n {error && <p role=\"alert\">{error}</p>}\n <button className=\"z-base-button\" type=\"submit\" disabled={!code.trim()}>\n Apply code\n </button>\n {cart.promoCode && (\n <button\n className=\"z-base-button-secondary\"\n type=\"button\"\n onClick={() => save(null)}\n >\n Remove code\n </button>\n )}\n </form>\n );\n}\nexport function PromoSheet() {\n const cart = useCart();\n const handoff = useCheckoutHandoff();\n // Promo codes belong to the customer's account, as in the legacy cart.\n if (!handoff.customer) {\n return null;\n }\n return (\n <CartSheet\n id=\"promo\"\n title=\"Promo code\"\n trigger={cart.promoCode ? `Promo: ${cart.promoCode}` : \"Add promo code\"}\n >\n <PromoForm />\n </CartSheet>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,kBAAkB;AAC3B,SAAS,eAAe;AACxB,SAAS,gBAAgB;AACzB,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAClC,SAAS,iBAAiB;AA2BpB,SAEE,KAFF;AA1BN,SAAS,YAAY;AACnB,QAAM,OAAO,QAAQ;AACrB,QAAM,SAAS,kBAAkB;AACjC,QAAM,UAAU,WAAW,cAAc,OAAO;AAChD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK,aAAa,EAAE;AACrD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,OAAO,CAAC,UAAyB;AACrC,QAAI;AACF,WAAK,QAAQ,aAAa,KAAK;AAC/B,cAAQ,MAAM;AAAA,IAChB,SAAS,SAAS;AAChB;AAAA,QACE,mBAAmB,QACf,QAAQ,UACR;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,UAAU,CAAC,UAAU;AACnB,cAAM,eAAe;AACrB,aAAK,KAAK,KAAK,CAAC;AAAA,MAClB;AAAA,MAEA;AAAA,6BAAC,WAAM,WAAU,gBAAe;AAAA;AAAA,UAE9B;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,cAAa;AAAA,cACb,OAAO;AAAA,cACP,UAAU,CAAC,UAAU,QAAQ,MAAM,OAAO,KAAK;AAAA;AAAA,UACjD;AAAA,WACF;AAAA,QACA,oBAAC,OAAE,oEAAsD;AAAA,QACxD,OAAO,iBAAiB,SACvB,qBAAC,aAAQ,cAAW,oBAClB;AAAA,8BAAC,QAAG,8BAAgB;AAAA,UACpB,oBAAC,QAAG,WAAU,sBACX,iBAAO,gBAAgB,IAAI,CAAC,UAC3B,qBAAC,QACC;AAAA,iCAAC,SACC;AAAA,kCAAC,YAAQ,gBAAM,MAAK;AAAA,cACpB,oBAAC,OAAG,gBAAM,aAAY;AAAA,eACxB;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,MAAK;AAAA,gBACL,UAAU,MAAM;AAAA,gBAChB,SAAS,MAAM,KAAK,MAAM,IAAI;AAAA,gBAC/B;AAAA;AAAA,kBACQ,MAAM;AAAA;AAAA;AAAA,YACf;AAAA,eAZO,MAAM,EAaf,CACD,GACH;AAAA,WACF,IACE;AAAA,QACH,SAAS,oBAAC,OAAE,MAAK,SAAS,iBAAM;AAAA,QACjC,oBAAC,YAAO,WAAU,iBAAgB,MAAK,UAAS,UAAU,CAAC,KAAK,KAAK,GAAG,wBAExE;AAAA,QACC,KAAK,aACJ;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAK;AAAA,YACL,SAAS,MAAM,KAAK,IAAI;AAAA,YACzB;AAAA;AAAA,QAED;AAAA;AAAA;AAAA,EAEJ;AAEJ;AACO,SAAS,aAAa;AAC3B,QAAM,OAAO,QAAQ;AACrB,QAAM,UAAU,mBAAmB;AAEnC,MAAI,CAAC,QAAQ,UAAU;AACrB,WAAO;AAAA,EACT;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,IAAG;AAAA,MACH,OAAM;AAAA,MACN,SAAS,KAAK,YAAY,UAAU,KAAK,SAAS,KAAK;AAAA,MAEvD,8BAAC,aAAU;AAAA;AAAA,EACb;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,40 @@
1
+ // src/cart/region-picker.tsx
2
+ import { format } from "@zappie/sdk";
3
+ import { useBaseHostBridge } from "../host-bridge.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ function RegionPicker() {
6
+ const bridge = useBaseHostBridge();
7
+ const regions = bridge.deliveryRegions;
8
+ if (!regions?.length || !bridge.setDeliveryRegion) {
9
+ return null;
10
+ }
11
+ const sorted = [...regions].sort((a, b) => a.name.localeCompare(b.name));
12
+ return /* @__PURE__ */ jsxs("label", { className: "z-base-field", children: [
13
+ "Delivery region",
14
+ /* @__PURE__ */ jsxs(
15
+ "select",
16
+ {
17
+ className: "z-base-input",
18
+ value: bridge.deliveryRegionId ?? "",
19
+ onChange: (event) => {
20
+ if (event.target.value) {
21
+ bridge.setDeliveryRegion?.(event.target.value);
22
+ }
23
+ },
24
+ children: [
25
+ /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Choose a delivery region" }),
26
+ sorted.map((region) => /* @__PURE__ */ jsxs("option", { value: region.id, children: [
27
+ region.name,
28
+ " (",
29
+ format.money(region.fee),
30
+ ")"
31
+ ] }, region.id))
32
+ ]
33
+ }
34
+ )
35
+ ] });
36
+ }
37
+ export {
38
+ RegionPicker
39
+ };
40
+ //# sourceMappingURL=region-picker.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/region-picker.tsx"],
4
+ "sourcesContent": ["import { format } from \"@zappie/sdk\";\nimport { useBaseHostBridge } from \"../host-bridge\";\n/** Shown when the branch prices delivery by region, as the legacy cart does. */\nexport function RegionPicker() {\n const bridge = useBaseHostBridge();\n const regions = bridge.deliveryRegions;\n if (!regions?.length || !bridge.setDeliveryRegion) {\n return null;\n }\n const sorted = [...regions].sort((a, b) => a.name.localeCompare(b.name));\n return (\n <label className=\"z-base-field\">\n Delivery region\n <select\n className=\"z-base-input\"\n value={bridge.deliveryRegionId ?? \"\"}\n onChange={(event) => {\n if (event.target.value) {\n bridge.setDeliveryRegion?.(event.target.value);\n }\n }}\n >\n <option value=\"\" disabled>\n Choose a delivery region\n </option>\n {sorted.map((region) => (\n <option key={region.id} value={region.id}>\n {region.name} ({format.money(region.fee)})\n </option>\n ))}\n </select>\n </label>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,cAAc;AACvB,SAAS,yBAAyB;AAqB1B,cAIE,YAJF;AAnBD,SAAS,eAAe;AAC7B,QAAM,SAAS,kBAAkB;AACjC,QAAM,UAAU,OAAO;AACvB,MAAI,CAAC,SAAS,UAAU,CAAC,OAAO,mBAAmB;AACjD,WAAO;AAAA,EACT;AACA,QAAM,SAAS,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AACvE,SACE,qBAAC,WAAM,WAAU,gBAAe;AAAA;AAAA,IAE9B;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO,OAAO,oBAAoB;AAAA,QAClC,UAAU,CAAC,UAAU;AACnB,cAAI,MAAM,OAAO,OAAO;AACtB,mBAAO,oBAAoB,MAAM,OAAO,KAAK;AAAA,UAC/C;AAAA,QACF;AAAA,QAEA;AAAA,8BAAC,YAAO,OAAM,IAAG,UAAQ,MAAC,sCAE1B;AAAA,UACC,OAAO,IAAI,CAAC,WACX,qBAAC,YAAuB,OAAO,OAAO,IACnC;AAAA,mBAAO;AAAA,YAAK;AAAA,YAAG,OAAO,MAAM,OAAO,GAAG;AAAA,YAAE;AAAA,eAD9B,OAAO,EAEpB,CACD;AAAA;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,86 @@
1
+ // src/cart/rewards-sheet.tsx
2
+ import { useState } from "react";
3
+ import { useCheckoutHandoff } from "../checkout.js";
4
+ import { useBaseHostBridge } from "../host-bridge.js";
5
+ import { CartSheet } from "./cart-sheet.js";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ function RewardsSheet() {
8
+ const bridge = useBaseHostBridge();
9
+ const handoff = useCheckoutHandoff();
10
+ const [error, setError] = useState(null);
11
+ const rewards = bridge.rewards;
12
+ if (!handoff.customer || !rewards) {
13
+ return null;
14
+ }
15
+ const appliedByPerk = new Map(
16
+ rewards.applied.map((reward) => [reward.perkId, reward])
17
+ );
18
+ return /* @__PURE__ */ jsxs(
19
+ CartSheet,
20
+ {
21
+ id: "rewards",
22
+ title: "Rewards",
23
+ trigger: rewards.applied.length ? `Rewards (${rewards.applied.length})` : "Use rewards",
24
+ children: [
25
+ /* @__PURE__ */ jsxs("p", { children: [
26
+ "Your points: ",
27
+ rewards.balance
28
+ ] }),
29
+ error && /* @__PURE__ */ jsx("p", { role: "alert", children: error }),
30
+ rewards.items.length ? /* @__PURE__ */ jsx("ul", { className: "z-base-option-list", children: rewards.items.map((reward) => {
31
+ const applied = appliedByPerk.get(reward.id);
32
+ const busy = rewards.busyPerkId === reward.id;
33
+ const unavailable = reward.disabled || !applied && reward.pointsCost > rewards.balance;
34
+ return /* @__PURE__ */ jsxs("li", { children: [
35
+ /* @__PURE__ */ jsxs("div", { children: [
36
+ /* @__PURE__ */ jsx("strong", { children: reward.name }),
37
+ /* @__PURE__ */ jsx("p", { children: reward.description }),
38
+ /* @__PURE__ */ jsxs("p", { children: [
39
+ reward.pointsCost,
40
+ " points \xB7 ",
41
+ reward.reward
42
+ ] })
43
+ ] }),
44
+ applied ? /* @__PURE__ */ jsx(
45
+ "button",
46
+ {
47
+ className: "z-base-button-secondary",
48
+ type: "button",
49
+ disabled: busy,
50
+ onClick: () => {
51
+ setError(null);
52
+ void rewards.cancel(applied.redemptionId).catch((failure) => {
53
+ setError(
54
+ failure instanceof Error ? failure.message : "Unable to remove this reward"
55
+ );
56
+ });
57
+ },
58
+ children: "Remove"
59
+ }
60
+ ) : /* @__PURE__ */ jsx(
61
+ "button",
62
+ {
63
+ className: "z-base-button-secondary",
64
+ type: "button",
65
+ disabled: busy || unavailable,
66
+ onClick: () => {
67
+ setError(null);
68
+ void rewards.redeem(reward.id).catch((failure) => {
69
+ setError(
70
+ failure instanceof Error ? failure.message : "Unable to redeem this reward"
71
+ );
72
+ });
73
+ },
74
+ children: reward.pointsCost > rewards.balance ? "Not enough points" : "Redeem"
75
+ }
76
+ )
77
+ ] }, reward.id);
78
+ }) }) : /* @__PURE__ */ jsx("p", { children: "No rewards available yet." })
79
+ ]
80
+ }
81
+ );
82
+ }
83
+ export {
84
+ RewardsSheet
85
+ };
86
+ //# sourceMappingURL=rewards-sheet.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/rewards-sheet.tsx"],
4
+ "sourcesContent": ["import { useState } from \"react\";\nimport { useCheckoutHandoff } from \"../checkout\";\nimport { useBaseHostBridge } from \"../host-bridge\";\nimport { CartSheet } from \"./cart-sheet\";\n\nexport function RewardsSheet() {\n const bridge = useBaseHostBridge();\n const handoff = useCheckoutHandoff();\n const [error, setError] = useState<string | null>(null);\n const rewards = bridge.rewards;\n if (!handoff.customer || !rewards) {\n return null;\n }\n const appliedByPerk = new Map(\n rewards.applied.map((reward) => [reward.perkId, reward]),\n );\n return (\n <CartSheet\n id=\"rewards\"\n title=\"Rewards\"\n trigger={\n rewards.applied.length\n ? `Rewards (${rewards.applied.length})`\n : \"Use rewards\"\n }\n >\n <p>Your points: {rewards.balance}</p>\n {error && <p role=\"alert\">{error}</p>}\n {rewards.items.length ? (\n <ul className=\"z-base-option-list\">\n {rewards.items.map((reward) => {\n const applied = appliedByPerk.get(reward.id);\n const busy = rewards.busyPerkId === reward.id;\n const unavailable =\n reward.disabled ||\n (!applied && reward.pointsCost > rewards.balance);\n return (\n <li key={reward.id}>\n <div>\n <strong>{reward.name}</strong>\n <p>{reward.description}</p>\n <p>\n {reward.pointsCost} points \u00B7 {reward.reward}\n </p>\n </div>\n {applied ? (\n <button\n className=\"z-base-button-secondary\"\n type=\"button\"\n disabled={busy}\n onClick={() => {\n setError(null);\n void rewards\n .cancel(applied.redemptionId)\n .catch((failure) => {\n setError(\n failure instanceof Error\n ? failure.message\n : \"Unable to remove this reward\",\n );\n });\n }}\n >\n Remove\n </button>\n ) : (\n <button\n className=\"z-base-button-secondary\"\n type=\"button\"\n disabled={busy || unavailable}\n onClick={() => {\n setError(null);\n void rewards.redeem(reward.id).catch((failure) => {\n setError(\n failure instanceof Error\n ? failure.message\n : \"Unable to redeem this reward\",\n );\n });\n }}\n >\n {reward.pointsCost > rewards.balance\n ? \"Not enough points\"\n : \"Redeem\"}\n </button>\n )}\n </li>\n );\n })}\n </ul>\n ) : (\n <p>No rewards available yet.</p>\n )}\n </CartSheet>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,gBAAgB;AACzB,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAClC,SAAS,iBAAiB;AAuBpB,SACU,KADV;AArBC,SAAS,eAAe;AAC7B,QAAM,SAAS,kBAAkB;AACjC,QAAM,UAAU,mBAAmB;AACnC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,UAAU,OAAO;AACvB,MAAI,CAAC,QAAQ,YAAY,CAAC,SAAS;AACjC,WAAO;AAAA,EACT;AACA,QAAM,gBAAgB,IAAI;AAAA,IACxB,QAAQ,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,QAAQ,MAAM,CAAC;AAAA,EACzD;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,IAAG;AAAA,MACH,OAAM;AAAA,MACN,SACE,QAAQ,QAAQ,SACZ,YAAY,QAAQ,QAAQ,MAAM,MAClC;AAAA,MAGN;AAAA,6BAAC,OAAE;AAAA;AAAA,UAAc,QAAQ;AAAA,WAAQ;AAAA,QAChC,SAAS,oBAAC,OAAE,MAAK,SAAS,iBAAM;AAAA,QAChC,QAAQ,MAAM,SACb,oBAAC,QAAG,WAAU,sBACX,kBAAQ,MAAM,IAAI,CAAC,WAAW;AAC7B,gBAAM,UAAU,cAAc,IAAI,OAAO,EAAE;AAC3C,gBAAM,OAAO,QAAQ,eAAe,OAAO;AAC3C,gBAAM,cACJ,OAAO,YACN,CAAC,WAAW,OAAO,aAAa,QAAQ;AAC3C,iBACE,qBAAC,QACC;AAAA,iCAAC,SACC;AAAA,kCAAC,YAAQ,iBAAO,MAAK;AAAA,cACrB,oBAAC,OAAG,iBAAO,aAAY;AAAA,cACvB,qBAAC,OACE;AAAA,uBAAO;AAAA,gBAAW;AAAA,gBAAW,OAAO;AAAA,iBACvC;AAAA,eACF;AAAA,YACC,UACC;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,MAAK;AAAA,gBACL,UAAU;AAAA,gBACV,SAAS,MAAM;AACb,2BAAS,IAAI;AACb,uBAAK,QACF,OAAO,QAAQ,YAAY,EAC3B,MAAM,CAAC,YAAY;AAClB;AAAA,sBACE,mBAAmB,QACf,QAAQ,UACR;AAAA,oBACN;AAAA,kBACF,CAAC;AAAA,gBACL;AAAA,gBACD;AAAA;AAAA,YAED,IAEA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,MAAK;AAAA,gBACL,UAAU,QAAQ;AAAA,gBAClB,SAAS,MAAM;AACb,2BAAS,IAAI;AACb,uBAAK,QAAQ,OAAO,OAAO,EAAE,EAAE,MAAM,CAAC,YAAY;AAChD;AAAA,sBACE,mBAAmB,QACf,QAAQ,UACR;AAAA,oBACN;AAAA,kBACF,CAAC;AAAA,gBACH;AAAA,gBAEC,iBAAO,aAAa,QAAQ,UACzB,sBACA;AAAA;AAAA,YACN;AAAA,eA/CK,OAAO,EAiDhB;AAAA,QAEJ,CAAC,GACH,IAEA,oBAAC,OAAE,uCAAyB;AAAA;AAAA;AAAA,EAEhC;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,87 @@
1
+ // src/cart/schedule-sheet.tsx
2
+ import { Schedule, useOverlay } from "@zappie/foundations";
3
+ import { useCart, useCartCatalogue } from "@zappie/sdk/react";
4
+ import { useState } from "react";
5
+ import { useBaseHostBridge } from "../host-bridge.js";
6
+ import { cartScheduleLimits } from "./cart-schedule.js";
7
+ import { CartSheet } from "./cart-sheet.js";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ function ScheduleForm({ branch }) {
10
+ const cart = useCart();
11
+ const bridge = useBaseHostBridge();
12
+ const overlay = useOverlay("cart_sheet", "schedule");
13
+ const menu = useCartCatalogue();
14
+ const limits = cartScheduleLimits(menu, cart.lines, bridge.scheduleMaxDays);
15
+ const [error, setError] = useState(null);
16
+ const fulfilment = cart.fulfilment;
17
+ if (!fulfilment || fulfilment.type === "dine_in") {
18
+ return /* @__PURE__ */ jsx("p", { children: "Add a delivery address or select pickup before choosing a time." });
19
+ }
20
+ return /* @__PURE__ */ jsx(
21
+ Schedule,
22
+ {
23
+ branch: bridge.scheduleOpeningTimes ? { ...branch, openingTimes: bridge.scheduleOpeningTimes } : branch,
24
+ maxDays: limits.maxDays,
25
+ noticeMinutes: limits.noticeMinutes,
26
+ defaultValue: fulfilment.scheduledFor ?? null,
27
+ children: ({ days, value, setValue, canAsap, isValid }) => /* @__PURE__ */ jsxs("div", { className: "z-base-field", children: [
28
+ /* @__PURE__ */ jsxs("p", { children: [
29
+ "Times are shown in ",
30
+ branch.timezone ?? "the store\u2019s timezone",
31
+ "."
32
+ ] }),
33
+ /* @__PURE__ */ jsxs("label", { className: "z-base-field", children: [
34
+ "Order time",
35
+ /* @__PURE__ */ jsxs(
36
+ "select",
37
+ {
38
+ className: "z-base-input",
39
+ value: value ?? "",
40
+ onChange: (event) => setValue(event.target.value || null),
41
+ children: [
42
+ /* @__PURE__ */ jsx("option", { value: "", disabled: !canAsap, children: "As soon as possible" }),
43
+ days.map((day) => /* @__PURE__ */ jsx("optgroup", { label: day.date, children: day.slots.map((slot) => /* @__PURE__ */ jsx("option", { value: slot.value, children: slot.label }, slot.value)) }, day.date))
44
+ ]
45
+ }
46
+ )
47
+ ] }),
48
+ !isValid && /* @__PURE__ */ jsx("p", { role: "alert", children: "Choose an available order time." }),
49
+ days.length === 0 && /* @__PURE__ */ jsx("p", { children: "No scheduled times are currently available." }),
50
+ error && /* @__PURE__ */ jsx("p", { role: "alert", children: error }),
51
+ /* @__PURE__ */ jsx(
52
+ "button",
53
+ {
54
+ type: "button",
55
+ className: "z-base-button",
56
+ disabled: !isValid,
57
+ onClick: () => {
58
+ try {
59
+ const next = { ...fulfilment };
60
+ if (value === null) {
61
+ delete next.scheduledFor;
62
+ } else {
63
+ next.scheduledFor = value;
64
+ }
65
+ cart.actions.setFulfilment(next);
66
+ bridge.saveFulfilment?.(next);
67
+ overlay.close();
68
+ } catch (failure) {
69
+ setError(
70
+ failure instanceof Error ? failure.message : "Unable to save this time"
71
+ );
72
+ }
73
+ },
74
+ children: "Save time"
75
+ }
76
+ )
77
+ ] })
78
+ }
79
+ );
80
+ }
81
+ function ScheduleSheet({ branch }) {
82
+ return /* @__PURE__ */ jsx(CartSheet, { id: "schedule", title: "Schedule order", trigger: "Choose order time", children: /* @__PURE__ */ jsx(ScheduleForm, { branch }) });
83
+ }
84
+ export {
85
+ ScheduleSheet
86
+ };
87
+ //# sourceMappingURL=schedule-sheet.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/schedule-sheet.tsx"],
4
+ "sourcesContent": ["import { Schedule, useOverlay } from \"@zappie/foundations\";\nimport type { Branch } from \"@zappie/sdk\";\nimport { useCart, useCartCatalogue } from \"@zappie/sdk/react\";\nimport { useState } from \"react\";\nimport { useBaseHostBridge } from \"../host-bridge\";\nimport { cartScheduleLimits } from \"./cart-schedule\";\nimport { CartSheet } from \"./cart-sheet\";\nfunction ScheduleForm({ branch }: { branch: Branch }) {\n const cart = useCart();\n const bridge = useBaseHostBridge();\n const overlay = useOverlay(\"cart_sheet\", \"schedule\");\n const menu = useCartCatalogue();\n const limits = cartScheduleLimits(menu, cart.lines, bridge.scheduleMaxDays);\n const [error, setError] = useState<string | null>(null);\n const fulfilment = cart.fulfilment;\n if (!fulfilment || fulfilment.type === \"dine_in\") {\n return (\n <p>Add a delivery address or select pickup before choosing a time.</p>\n );\n }\n return (\n <Schedule\n branch={\n bridge.scheduleOpeningTimes\n ? { ...branch, openingTimes: bridge.scheduleOpeningTimes }\n : branch\n }\n maxDays={limits.maxDays}\n noticeMinutes={limits.noticeMinutes}\n defaultValue={fulfilment.scheduledFor ?? null}\n >\n {({ days, value, setValue, canAsap, isValid }) => (\n <div className=\"z-base-field\">\n <p>Times are shown in {branch.timezone ?? \"the store\u2019s timezone\"}.</p>\n <label className=\"z-base-field\">\n Order time\n <select\n className=\"z-base-input\"\n value={value ?? \"\"}\n onChange={(event) => setValue(event.target.value || null)}\n >\n <option value=\"\" disabled={!canAsap}>\n As soon as possible\n </option>\n {days.map((day) => (\n <optgroup key={day.date} label={day.date}>\n {day.slots.map((slot) => (\n <option key={slot.value} value={slot.value}>\n {slot.label}\n </option>\n ))}\n </optgroup>\n ))}\n </select>\n </label>\n {!isValid && <p role=\"alert\">Choose an available order time.</p>}\n {days.length === 0 && (\n <p>No scheduled times are currently available.</p>\n )}\n {error && <p role=\"alert\">{error}</p>}\n <button\n type=\"button\"\n className=\"z-base-button\"\n disabled={!isValid}\n onClick={() => {\n try {\n const next = { ...fulfilment };\n if (value === null) {\n delete next.scheduledFor;\n } else {\n next.scheduledFor = value;\n }\n cart.actions.setFulfilment(next);\n bridge.saveFulfilment?.(next);\n overlay.close();\n } catch (failure) {\n setError(\n failure instanceof Error\n ? failure.message\n : \"Unable to save this time\",\n );\n }\n }}\n >\n Save time\n </button>\n </div>\n )}\n </Schedule>\n );\n}\nexport function ScheduleSheet({ branch }: { branch: Branch }) {\n return (\n <CartSheet id=\"schedule\" title=\"Schedule order\" trigger=\"Choose order time\">\n <ScheduleForm branch={branch} />\n </CartSheet>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,UAAU,kBAAkB;AAErC,SAAS,SAAS,wBAAwB;AAC1C,SAAS,gBAAgB;AACzB,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AACnC,SAAS,iBAAiB;AAWpB,cAgBI,YAhBJ;AAVN,SAAS,aAAa,EAAE,OAAO,GAAuB;AACpD,QAAM,OAAO,QAAQ;AACrB,QAAM,SAAS,kBAAkB;AACjC,QAAM,UAAU,WAAW,cAAc,UAAU;AACnD,QAAM,OAAO,iBAAiB;AAC9B,QAAM,SAAS,mBAAmB,MAAM,KAAK,OAAO,OAAO,eAAe;AAC1E,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,aAAa,KAAK;AACxB,MAAI,CAAC,cAAc,WAAW,SAAS,WAAW;AAChD,WACE,oBAAC,OAAE,6EAA+D;AAAA,EAEtE;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,QACE,OAAO,uBACH,EAAE,GAAG,QAAQ,cAAc,OAAO,qBAAqB,IACvD;AAAA,MAEN,SAAS,OAAO;AAAA,MAChB,eAAe,OAAO;AAAA,MACtB,cAAc,WAAW,gBAAgB;AAAA,MAExC,WAAC,EAAE,MAAM,OAAO,UAAU,SAAS,QAAQ,MAC1C,qBAAC,SAAI,WAAU,gBACb;AAAA,6BAAC,OAAE;AAAA;AAAA,UAAoB,OAAO,YAAY;AAAA,UAAuB;AAAA,WAAC;AAAA,QAClE,qBAAC,WAAM,WAAU,gBAAe;AAAA;AAAA,UAE9B;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO,SAAS;AAAA,cAChB,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,SAAS,IAAI;AAAA,cAExD;AAAA,oCAAC,YAAO,OAAM,IAAG,UAAU,CAAC,SAAS,iCAErC;AAAA,gBACC,KAAK,IAAI,CAAC,QACT,oBAAC,cAAwB,OAAO,IAAI,MACjC,cAAI,MAAM,IAAI,CAAC,SACd,oBAAC,YAAwB,OAAO,KAAK,OAClC,eAAK,SADK,KAAK,KAElB,CACD,KALY,IAAI,IAMnB,CACD;AAAA;AAAA;AAAA,UACH;AAAA,WACF;AAAA,QACC,CAAC,WAAW,oBAAC,OAAE,MAAK,SAAQ,6CAA+B;AAAA,QAC3D,KAAK,WAAW,KACf,oBAAC,OAAE,yDAA2C;AAAA,QAE/C,SAAS,oBAAC,OAAE,MAAK,SAAS,iBAAM;AAAA,QACjC;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,UAAU,CAAC;AAAA,YACX,SAAS,MAAM;AACb,kBAAI;AACF,sBAAM,OAAO,EAAE,GAAG,WAAW;AAC7B,oBAAI,UAAU,MAAM;AAClB,yBAAO,KAAK;AAAA,gBACd,OAAO;AACL,uBAAK,eAAe;AAAA,gBACtB;AACA,qBAAK,QAAQ,cAAc,IAAI;AAC/B,uBAAO,iBAAiB,IAAI;AAC5B,wBAAQ,MAAM;AAAA,cAChB,SAAS,SAAS;AAChB;AAAA,kBACE,mBAAmB,QACf,QAAQ,UACR;AAAA,gBACN;AAAA,cACF;AAAA,YACF;AAAA,YACD;AAAA;AAAA,QAED;AAAA,SACF;AAAA;AAAA,EAEJ;AAEJ;AACO,SAAS,cAAc,EAAE,OAAO,GAAuB;AAC5D,SACE,oBAAC,aAAU,IAAG,YAAW,OAAM,kBAAiB,SAAQ,qBACtD,8BAAC,gBAAa,QAAgB,GAChC;AAEJ;",
6
+ "names": []
7
+ }
@@ -1,13 +1,15 @@
1
- import { createContext, useContext } from 'react';
1
+ "use client";
2
2
 
3
3
  // src/cart/theme-class.tsx
4
+ import { createContext, useContext } from "react";
4
5
  var ThemeClass = createContext(void 0);
5
6
  var ThemeClassProvider = ThemeClass.Provider;
6
7
  function useThemeClass(className) {
7
8
  const themeClass = useContext(ThemeClass);
8
9
  return themeClass ? `${className} ${themeClass}` : className;
9
10
  }
10
-
11
- export { ThemeClassProvider, useThemeClass };
12
- //# sourceMappingURL=chunk-JFEI2OUZ.js.map
13
- //# sourceMappingURL=chunk-JFEI2OUZ.js.map
11
+ export {
12
+ ThemeClassProvider,
13
+ useThemeClass
14
+ };
15
+ //# sourceMappingURL=theme-class.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/theme-class.tsx"],
4
+ "sourcesContent": ["\"use client\";\nimport { createContext, useContext } from \"react\";\nconst ThemeClass = createContext<string | undefined>(undefined);\nexport const ThemeClassProvider = ThemeClass.Provider;\n/**\n * Class names for an overlay root, plus the class a template passed to\n * `CartReview`. Overlays render in a portal, outside any template wrapper, so\n * a template's tokens reach them only through this class.\n */\nexport function useThemeClass(className: string) {\n const themeClass = useContext(ThemeClass);\n return themeClass ? `${className} ${themeClass}` : className;\n}\n"],
5
+ "mappings": ";;;AACA,SAAS,eAAe,kBAAkB;AAC1C,IAAM,aAAa,cAAkC,MAAS;AACvD,IAAM,qBAAqB,WAAW;AAMtC,SAAS,cAAc,WAAmB;AAC/C,QAAM,aAAa,WAAW,UAAU;AACxC,SAAO,aAAa,GAAG,SAAS,IAAI,UAAU,KAAK;AACrD;",
6
+ "names": []
7
+ }