@zappie/theme-base 0.1.1 → 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 (128) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/address.js +99 -2
  3. package/dist/address.js.map +7 -1
  4. package/dist/cart/address-sheet.js +143 -0
  5. package/dist/cart/address-sheet.js.map +7 -0
  6. package/dist/cart/cart-issues.js +72 -0
  7. package/dist/cart/cart-issues.js.map +7 -0
  8. package/dist/cart/cart-line-groups.js +34 -0
  9. package/dist/cart/cart-line-groups.js.map +7 -0
  10. package/dist/{chunk-FB5DRCU7.js → cart/cart-line.js} +9 -70
  11. package/dist/cart/cart-line.js.map +7 -0
  12. package/dist/cart/cart-lines.js +27 -0
  13. package/dist/cart/cart-lines.js.map +7 -0
  14. package/dist/cart/cart-schedule.js +24 -0
  15. package/dist/cart/cart-schedule.js.map +7 -0
  16. package/dist/cart/cart-sheet.js +35 -0
  17. package/dist/cart/cart-sheet.js.map +7 -0
  18. package/dist/cart/checkout-cta.js +81 -0
  19. package/dist/cart/checkout-cta.js.map +7 -0
  20. package/dist/cart/checkout-state.js +74 -0
  21. package/dist/cart/checkout-state.js.map +7 -0
  22. package/dist/cart/clear-cart.js +44 -0
  23. package/dist/cart/clear-cart.js.map +7 -0
  24. package/dist/cart/customer-details.js +70 -0
  25. package/dist/cart/customer-details.js.map +7 -0
  26. package/dist/cart/delivery-distance.js +22 -0
  27. package/dist/cart/delivery-distance.js.map +7 -0
  28. package/dist/cart/empty-cart.js +14 -0
  29. package/dist/cart/empty-cart.js.map +7 -0
  30. package/dist/cart/fulfilment-panel.js +83 -0
  31. package/dist/cart/fulfilment-panel.js.map +7 -0
  32. package/dist/cart/line-editor.js +35 -0
  33. package/dist/cart/line-editor.js.map +7 -0
  34. package/dist/cart/line-options.js +96 -0
  35. package/dist/cart/line-options.js.map +7 -0
  36. package/dist/cart/loading.js +17 -0
  37. package/dist/cart/loading.js.map +7 -0
  38. package/dist/cart/promo-sheet.js +103 -0
  39. package/dist/cart/promo-sheet.js.map +7 -0
  40. package/dist/cart/region-picker.js +40 -0
  41. package/dist/cart/region-picker.js.map +7 -0
  42. package/dist/cart/rewards-sheet.js +86 -0
  43. package/dist/cart/rewards-sheet.js.map +7 -0
  44. package/dist/cart/schedule-sheet.js +87 -0
  45. package/dist/cart/schedule-sheet.js.map +7 -0
  46. package/dist/{chunk-JFEI2OUZ.js → cart/theme-class.js} +7 -5
  47. package/dist/cart/theme-class.js.map +7 -0
  48. package/dist/cart/totals.js +81 -0
  49. package/dist/cart/totals.js.map +7 -0
  50. package/dist/cart/use-address-selection.js +130 -0
  51. package/dist/cart/use-address-selection.js.map +7 -0
  52. package/dist/cart.js +21 -1069
  53. package/dist/cart.js.map +7 -1
  54. package/dist/catalogue/catalogue-cart.js +25 -0
  55. package/dist/catalogue/catalogue-cart.js.map +7 -0
  56. package/dist/catalogue/catalogue-header.js +88 -0
  57. package/dist/catalogue/catalogue-header.js.map +7 -0
  58. package/dist/catalogue/catalogue-pages.js +68 -0
  59. package/dist/catalogue/catalogue-pages.js.map +7 -0
  60. package/dist/catalogue/catalogue-search.js +89 -0
  61. package/dist/catalogue/catalogue-search.js.map +7 -0
  62. package/dist/catalogue/category-navigation.js +98 -0
  63. package/dist/catalogue/category-navigation.js.map +7 -0
  64. package/dist/catalogue/category-section.js +113 -0
  65. package/dist/catalogue/category-section.js.map +7 -0
  66. package/dist/catalogue/info-banners.js +148 -0
  67. package/dist/catalogue/info-banners.js.map +7 -0
  68. package/dist/catalogue/item-tile.js +55 -0
  69. package/dist/catalogue/item-tile.js.map +7 -0
  70. package/dist/catalogue/loader.js +136 -0
  71. package/dist/catalogue/loader.js.map +7 -0
  72. package/dist/{chunk-USSLDBDY.js → catalogue/presentation.js} +12 -9
  73. package/dist/catalogue/presentation.js.map +7 -0
  74. package/dist/catalogue/saved-catalogue-sync.js +115 -0
  75. package/dist/catalogue/saved-catalogue-sync.js.map +7 -0
  76. package/dist/catalogue/types.js +1 -0
  77. package/dist/catalogue/types.js.map +7 -0
  78. package/dist/catalogue/use-catalogue-data.js +88 -0
  79. package/dist/catalogue/use-catalogue-data.js.map +7 -0
  80. package/dist/catalogue/use-category-scroll.js +115 -0
  81. package/dist/catalogue/use-category-scroll.js.map +7 -0
  82. package/dist/catalogue/use-item-opener.js +46 -0
  83. package/dist/catalogue/use-item-opener.js.map +7 -0
  84. package/dist/catalogue/use-search-source.js +132 -0
  85. package/dist/catalogue/use-search-source.js.map +7 -0
  86. package/dist/catalogue.js +26 -1216
  87. package/dist/catalogue.js.map +7 -1
  88. package/dist/checkout.js +149 -2
  89. package/dist/checkout.js.map +7 -1
  90. package/dist/host-bridge.js +22 -2
  91. package/dist/host-bridge.js.map +7 -1
  92. package/dist/index.js +3 -3
  93. package/dist/index.js.map +7 -1
  94. package/dist/item/configurator-commit.js +15 -0
  95. package/dist/item/configurator-commit.js.map +7 -0
  96. package/dist/item/configurator-draft.js +63 -0
  97. package/dist/item/configurator-draft.js.map +7 -0
  98. package/dist/item/configurator.js +135 -0
  99. package/dist/item/configurator.js.map +7 -0
  100. package/dist/item/note.js +65 -0
  101. package/dist/item/note.js.map +7 -0
  102. package/dist/item/variant-status.js +23 -0
  103. package/dist/item/variant-status.js.map +7 -0
  104. package/dist/item-frame.js +60 -3
  105. package/dist/item-frame.js.map +7 -1
  106. package/dist/item.js +11 -11
  107. package/dist/item.js.map +7 -1
  108. package/dist/navigation.js +39 -2
  109. package/dist/navigation.js.map +7 -1
  110. package/dist/url-navigation-state.js +61 -0
  111. package/dist/url-navigation-state.js.map +7 -0
  112. package/dist/{chunk-ILOCSCZL.js → url-navigation.js} +12 -89
  113. package/dist/url-navigation.js.map +7 -0
  114. package/package.json +4 -4
  115. package/dist/chunk-2MV6KU3R.js +0 -352
  116. package/dist/chunk-2MV6KU3R.js.map +0 -1
  117. package/dist/chunk-FB5DRCU7.js.map +0 -1
  118. package/dist/chunk-IG63ONID.js +0 -139
  119. package/dist/chunk-IG63ONID.js.map +0 -1
  120. package/dist/chunk-ILOCSCZL.js.map +0 -1
  121. package/dist/chunk-JFEI2OUZ.js.map +0 -1
  122. package/dist/chunk-NTJONY3N.js +0 -95
  123. package/dist/chunk-NTJONY3N.js.map +0 -1
  124. package/dist/chunk-QWST2TA2.js +0 -22
  125. package/dist/chunk-QWST2TA2.js.map +0 -1
  126. package/dist/chunk-USSLDBDY.js.map +0 -1
  127. package/dist/chunk-VIAJ27YC.js +0 -59
  128. package/dist/chunk-VIAJ27YC.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @zappie/theme-base
2
2
 
3
+ ## 0.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - d3c5f98: Keep each runtime module separate so your app can split package code across routes. Check and verify accept compatible package updates without pinning you to one patch version.
8
+ - Updated dependencies [d3c5f98]
9
+ - @zappie/sdk@0.1.2
10
+ - @zappie/foundations@0.1.2
11
+
3
12
  ## 0.1.1
4
13
 
5
14
  ### Patch Changes
package/dist/address.js CHANGED
@@ -1,4 +1,101 @@
1
1
  "use client";
2
- export { AddressLookupProvider, createSdkAddressLookup, useAddressLookup } from './chunk-NTJONY3N.js';
2
+
3
+ // src/address.tsx
4
+ import {
5
+ createContext,
6
+ useContext
7
+ } from "react";
8
+ import { jsx } from "react/jsx-runtime";
9
+ function deliveryAddress(place, source) {
10
+ const result = {
11
+ line1: place.line1,
12
+ placeId: place.place_id,
13
+ coordinates: { lat: place.lat, lng: place.lng }
14
+ };
15
+ if (place.city !== void 0) {
16
+ result.city = place.city;
17
+ }
18
+ if (source?.line2 !== void 0) {
19
+ result.line2 = source.line2;
20
+ }
21
+ if (source?.instructions !== void 0) {
22
+ result.instructions = source.instructions;
23
+ }
24
+ return result;
25
+ }
26
+ var Context = createContext(null);
27
+ function AddressLookupProvider({
28
+ lookup,
29
+ children
30
+ }) {
31
+ return /* @__PURE__ */ jsx(Context.Provider, { value: lookup, children });
32
+ }
33
+ function useAddressLookup() {
34
+ const lookup = useContext(Context);
35
+ if (!lookup) {
36
+ throw new Error("useAddressLookup requires AddressLookupProvider");
37
+ }
38
+ return lookup;
39
+ }
40
+ function createSdkAddressLookup({
41
+ places,
42
+ branchId
43
+ }) {
44
+ let sessionToken = crypto.randomUUID();
45
+ const Map = ({ address }) => {
46
+ if (!address.coordinates) {
47
+ return null;
48
+ }
49
+ return (
50
+ // The theme can't use next/image; the map's size is fixed by the API.
51
+ // eslint-disable-next-line @next/next/no-img-element
52
+ /* @__PURE__ */ jsx(
53
+ "img",
54
+ {
55
+ className: "z-base-address-map",
56
+ src: places.staticMapUrl(
57
+ address.coordinates.lat,
58
+ address.coordinates.lng,
59
+ branchId
60
+ ),
61
+ alt: `Map of ${address.line1}`,
62
+ width: 640,
63
+ height: 320,
64
+ loading: "lazy"
65
+ }
66
+ )
67
+ );
68
+ };
69
+ return {
70
+ async suggest(query) {
71
+ const suggestions = await places.autocomplete(query, sessionToken);
72
+ return suggestions.map((suggestion) => ({
73
+ placeId: suggestion.place_id,
74
+ address: suggestion.secondary ? `${suggestion.text}, ${suggestion.secondary}` : suggestion.text,
75
+ sessionToken
76
+ }));
77
+ },
78
+ async resolve(address, token) {
79
+ if (!address.placeId) {
80
+ throw new Error("Choose a suggested delivery address");
81
+ }
82
+ const place = await places.place(address.placeId, {
83
+ branchId,
84
+ sessionToken: token ?? sessionToken
85
+ });
86
+ sessionToken = crypto.randomUUID();
87
+ return deliveryAddress(place, address);
88
+ },
89
+ async reverse({ lat, lng }) {
90
+ const place = await places.reverse(lat, lng);
91
+ return deliveryAddress(place);
92
+ },
93
+ Map
94
+ };
95
+ }
96
+ export {
97
+ AddressLookupProvider,
98
+ createSdkAddressLookup,
99
+ useAddressLookup
100
+ };
3
101
  //# sourceMappingURL=address.js.map
4
- //# sourceMappingURL=address.js.map
@@ -1 +1,7 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"address.js"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/address.tsx"],
4
+ "sourcesContent": ["\"use client\";\n\nimport type { DeliveryAddress } from \"@zappie/sdk\";\nimport type { Place, PlacesClient } from \"@zappie/sdk/places\";\nimport {\n createContext,\n useContext,\n type ComponentType,\n type ReactNode,\n} from \"react\";\n\nexport type AddressSuggestion = {\n placeId: string;\n address: string;\n sessionToken?: string;\n};\n\nexport type AddressLookup = {\n suggest(query: string): Promise<AddressSuggestion[]>;\n reverse?(coordinates: { lat: number; lng: number }): Promise<DeliveryAddress>;\n resolve?(\n address: DeliveryAddress,\n sessionToken?: string,\n ): Promise<DeliveryAddress>;\n Map?: ComponentType<{ address: DeliveryAddress }>;\n};\n\nfunction deliveryAddress(\n place: Place,\n source?: DeliveryAddress,\n): DeliveryAddress {\n const result: DeliveryAddress = {\n line1: place.line1,\n placeId: place.place_id,\n coordinates: { lat: place.lat, lng: place.lng },\n };\n if (place.city !== undefined) {\n result.city = place.city;\n }\n if (source?.line2 !== undefined) {\n result.line2 = source.line2;\n }\n if (source?.instructions !== undefined) {\n result.instructions = source.instructions;\n }\n return result;\n}\n\nconst Context = createContext<AddressLookup | null>(null);\n\nexport function AddressLookupProvider({\n lookup,\n children,\n}: {\n lookup: AddressLookup;\n children: ReactNode;\n}) {\n return <Context.Provider value={lookup}>{children}</Context.Provider>;\n}\n\nexport function useAddressLookup() {\n const lookup = useContext(Context);\n if (!lookup) {\n throw new Error(\"useAddressLookup requires AddressLookupProvider\");\n }\n return lookup;\n}\n\nexport function createSdkAddressLookup({\n places,\n branchId,\n}: {\n places: PlacesClient;\n branchId: string;\n}): AddressLookup {\n let sessionToken = crypto.randomUUID();\n const Map = ({ address }: { address: DeliveryAddress }) => {\n if (!address.coordinates) {\n return null;\n }\n return (\n // The theme can't use next/image; the map's size is fixed by the API.\n // eslint-disable-next-line @next/next/no-img-element\n <img\n className=\"z-base-address-map\"\n src={places.staticMapUrl(\n address.coordinates.lat,\n address.coordinates.lng,\n branchId,\n )}\n alt={`Map of ${address.line1}`}\n width={640}\n height={320}\n loading=\"lazy\"\n />\n );\n };\n return {\n async suggest(query) {\n const suggestions = await places.autocomplete(query, sessionToken);\n return suggestions.map((suggestion) => ({\n placeId: suggestion.place_id,\n address: suggestion.secondary\n ? `${suggestion.text}, ${suggestion.secondary}`\n : suggestion.text,\n sessionToken,\n }));\n },\n async resolve(address, token) {\n if (!address.placeId) {\n throw new Error(\"Choose a suggested delivery address\");\n }\n const place = await places.place(address.placeId, {\n branchId,\n sessionToken: token ?? sessionToken,\n });\n sessionToken = crypto.randomUUID();\n return deliveryAddress(place, address);\n },\n async reverse({ lat, lng }) {\n const place = await places.reverse(lat, lng);\n return deliveryAddress(place);\n },\n Map,\n };\n}\n"],
5
+ "mappings": ";;;AAIA;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAgDE;AA9BT,SAAS,gBACP,OACA,QACiB;AACjB,QAAM,SAA0B;AAAA,IAC9B,OAAO,MAAM;AAAA,IACb,SAAS,MAAM;AAAA,IACf,aAAa,EAAE,KAAK,MAAM,KAAK,KAAK,MAAM,IAAI;AAAA,EAChD;AACA,MAAI,MAAM,SAAS,QAAW;AAC5B,WAAO,OAAO,MAAM;AAAA,EACtB;AACA,MAAI,QAAQ,UAAU,QAAW;AAC/B,WAAO,QAAQ,OAAO;AAAA,EACxB;AACA,MAAI,QAAQ,iBAAiB,QAAW;AACtC,WAAO,eAAe,OAAO;AAAA,EAC/B;AACA,SAAO;AACT;AAEA,IAAM,UAAU,cAAoC,IAAI;AAEjD,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AACF,GAGG;AACD,SAAO,oBAAC,QAAQ,UAAR,EAAiB,OAAO,QAAS,UAAS;AACpD;AAEO,SAAS,mBAAmB;AACjC,QAAM,SAAS,WAAW,OAAO;AACjC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACnE;AACA,SAAO;AACT;AAEO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AACF,GAGkB;AAChB,MAAI,eAAe,OAAO,WAAW;AACrC,QAAM,MAAM,CAAC,EAAE,QAAQ,MAAoC;AACzD,QAAI,CAAC,QAAQ,aAAa;AACxB,aAAO;AAAA,IACT;AACA;AAAA;AAAA;AAAA,MAGE;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,KAAK,OAAO;AAAA,YACV,QAAQ,YAAY;AAAA,YACpB,QAAQ,YAAY;AAAA,YACpB;AAAA,UACF;AAAA,UACA,KAAK,UAAU,QAAQ,KAAK;AAAA,UAC5B,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,SAAQ;AAAA;AAAA,MACV;AAAA;AAAA,EAEJ;AACA,SAAO;AAAA,IACL,MAAM,QAAQ,OAAO;AACnB,YAAM,cAAc,MAAM,OAAO,aAAa,OAAO,YAAY;AACjE,aAAO,YAAY,IAAI,CAAC,gBAAgB;AAAA,QACtC,SAAS,WAAW;AAAA,QACpB,SAAS,WAAW,YAChB,GAAG,WAAW,IAAI,KAAK,WAAW,SAAS,KAC3C,WAAW;AAAA,QACf;AAAA,MACF,EAAE;AAAA,IACJ;AAAA,IACA,MAAM,QAAQ,SAAS,OAAO;AAC5B,UAAI,CAAC,QAAQ,SAAS;AACpB,cAAM,IAAI,MAAM,qCAAqC;AAAA,MACvD;AACA,YAAM,QAAQ,MAAM,OAAO,MAAM,QAAQ,SAAS;AAAA,QAChD;AAAA,QACA,cAAc,SAAS;AAAA,MACzB,CAAC;AACD,qBAAe,OAAO,WAAW;AACjC,aAAO,gBAAgB,OAAO,OAAO;AAAA,IACvC;AAAA,IACA,MAAM,QAAQ,EAAE,KAAK,IAAI,GAAG;AAC1B,YAAM,QAAQ,MAAM,OAAO,QAAQ,KAAK,GAAG;AAC3C,aAAO,gBAAgB,KAAK;AAAA,IAC9B;AAAA,IACA;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,143 @@
1
+ // src/cart/address-sheet.tsx
2
+ import { Address, useOverlay } from "@zappie/foundations";
3
+ import { useCart } from "@zappie/sdk/react";
4
+ import { Fragment, useState } from "react";
5
+ import { useAddressLookup } from "../address.js";
6
+ import { useBaseHostBridge } from "../host-bridge.js";
7
+ import { CartSheet } from "./cart-sheet.js";
8
+ import { useAddressSelection } from "./use-address-selection.js";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ function AddressForm() {
11
+ const cart = useCart();
12
+ const lookup = useAddressLookup();
13
+ const bridge = useBaseHostBridge();
14
+ const overlay = useOverlay("cart_sheet", "address");
15
+ const current = cart.fulfilment?.type === "delivery" ? cart.fulfilment.address : void 0;
16
+ const {
17
+ selected,
18
+ query,
19
+ busy,
20
+ error: lookupError,
21
+ suggestions,
22
+ changeQuery,
23
+ select,
24
+ findCurrentLocation,
25
+ locating
26
+ } = useAddressSelection(current);
27
+ const [instructions, setInstructions] = useState(current?.instructions ?? "");
28
+ const [error, setError] = useState(null);
29
+ const save = () => {
30
+ if (!selected || !cart.branchId || busy) {
31
+ return;
32
+ }
33
+ setError(null);
34
+ try {
35
+ const fulfilment = {
36
+ type: "delivery",
37
+ branchId: cart.branchId,
38
+ address: { ...selected, instructions },
39
+ ...cart.fulfilment && "scheduledFor" in cart.fulfilment ? { scheduledFor: cart.fulfilment.scheduledFor } : {}
40
+ };
41
+ cart.actions.setFulfilment(fulfilment);
42
+ bridge.saveFulfilment?.(fulfilment);
43
+ overlay.close();
44
+ } catch (failure) {
45
+ setError(
46
+ failure instanceof Error ? failure.message : "Unable to save this address"
47
+ );
48
+ }
49
+ };
50
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
51
+ lookup.reverse && typeof navigator !== "undefined" && navigator.geolocation && /* @__PURE__ */ jsx(
52
+ "button",
53
+ {
54
+ type: "button",
55
+ className: "z-base-button-secondary",
56
+ disabled: busy,
57
+ onClick: findCurrentLocation,
58
+ children: locating ? "Finding your location\u2026" : "Use my current location"
59
+ }
60
+ ),
61
+ /* @__PURE__ */ jsx(
62
+ Address.Picker,
63
+ {
64
+ query,
65
+ onQueryChange: changeQuery,
66
+ getSuggestions: suggestions,
67
+ onSelect: (value) => {
68
+ if ("address" in value) {
69
+ void select(value.address);
70
+ }
71
+ },
72
+ children: ({ suggestions: suggestions2, status, isOpen }) => /* @__PURE__ */ jsxs(Fragment, { children: [
73
+ /* @__PURE__ */ jsxs("label", { className: "z-base-field", htmlFor: "z-base-delivery-address", children: [
74
+ "Delivery address",
75
+ /* @__PURE__ */ jsx(
76
+ Address.Input,
77
+ {
78
+ className: "z-base-input",
79
+ id: "z-base-delivery-address",
80
+ "aria-label": "Delivery address"
81
+ }
82
+ )
83
+ ] }),
84
+ status === "loading" && /* @__PURE__ */ jsx("p", { role: "status", children: "Finding addresses\u2026" }),
85
+ status === "error" && /* @__PURE__ */ jsx("p", { role: "alert", children: "Unable to find addresses. Try again." }),
86
+ isOpen && /* @__PURE__ */ jsx(Address.Suggestions, { className: "z-base-suggestions", children: suggestions2.map((value, index) => /* @__PURE__ */ jsx(
87
+ Address.Suggestion,
88
+ {
89
+ index,
90
+ className: "z-base-choice",
91
+ children: value.label
92
+ },
93
+ value.id
94
+ )) }),
95
+ isOpen && status === "ready" && query && suggestions2.length === 0 && /* @__PURE__ */ jsx("p", { children: "No matching addresses." })
96
+ ] })
97
+ }
98
+ ),
99
+ /* @__PURE__ */ jsxs("label", { className: "z-base-field", children: [
100
+ "Delivery instructions",
101
+ /* @__PURE__ */ jsx(
102
+ "textarea",
103
+ {
104
+ className: "z-base-input",
105
+ maxLength: 500,
106
+ value: instructions,
107
+ onChange: (event) => setInstructions(event.target.value)
108
+ }
109
+ )
110
+ ] }),
111
+ selected && lookup.Map && /* @__PURE__ */ jsx(lookup.Map, { address: selected }),
112
+ lookupError && /* @__PURE__ */ jsx("p", { role: "alert", children: lookupError }),
113
+ error && /* @__PURE__ */ jsx("p", { role: "alert", children: error }),
114
+ /* @__PURE__ */ jsx(
115
+ "button",
116
+ {
117
+ type: "button",
118
+ className: "z-base-button",
119
+ disabled: !selected || busy,
120
+ onClick: () => {
121
+ void save();
122
+ },
123
+ children: busy ? "Locating address\u2026" : "Save address"
124
+ }
125
+ )
126
+ ] });
127
+ }
128
+ function AddressSheet() {
129
+ const cart = useCart();
130
+ return /* @__PURE__ */ jsx(
131
+ CartSheet,
132
+ {
133
+ id: "address",
134
+ title: "Delivery address",
135
+ trigger: cart.fulfilment?.type === "delivery" ? "Change address" : "Add delivery address",
136
+ children: /* @__PURE__ */ jsx(AddressForm, {})
137
+ }
138
+ );
139
+ }
140
+ export {
141
+ AddressSheet
142
+ };
143
+ //# sourceMappingURL=address-sheet.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/address-sheet.tsx"],
4
+ "sourcesContent": ["import { Address, useOverlay } from \"@zappie/foundations\";\nimport { useCart } from \"@zappie/sdk/react\";\nimport { Fragment, useState } from \"react\";\nimport { useAddressLookup } from \"../address\";\nimport { useBaseHostBridge } from \"../host-bridge\";\nimport { CartSheet } from \"./cart-sheet\";\nimport { useAddressSelection } from \"./use-address-selection\";\nfunction AddressForm() {\n const cart = useCart();\n const lookup = useAddressLookup();\n const bridge = useBaseHostBridge();\n const overlay = useOverlay(\"cart_sheet\", \"address\");\n const current =\n cart.fulfilment?.type === \"delivery\" ? cart.fulfilment.address : undefined;\n const {\n selected,\n query,\n busy,\n error: lookupError,\n suggestions,\n changeQuery,\n select,\n findCurrentLocation,\n locating,\n } = useAddressSelection(current);\n const [instructions, setInstructions] = useState(current?.instructions ?? \"\");\n const [error, setError] = useState<string | null>(null);\n const save = () => {\n if (!selected || !cart.branchId || busy) {\n return;\n }\n setError(null);\n try {\n const fulfilment = {\n type: \"delivery\" as const,\n branchId: cart.branchId,\n address: { ...selected, instructions },\n ...(cart.fulfilment && \"scheduledFor\" in cart.fulfilment\n ? { scheduledFor: cart.fulfilment.scheduledFor }\n : {}),\n };\n cart.actions.setFulfilment(fulfilment);\n bridge.saveFulfilment?.(fulfilment);\n overlay.close();\n } catch (failure) {\n setError(\n failure instanceof Error\n ? failure.message\n : \"Unable to save this address\",\n );\n }\n };\n return (\n <Fragment>\n {lookup.reverse &&\n typeof navigator !== \"undefined\" &&\n navigator.geolocation && (\n <button\n type=\"button\"\n className=\"z-base-button-secondary\"\n disabled={busy}\n onClick={findCurrentLocation}\n >\n {locating ? \"Finding your location\u2026\" : \"Use my current location\"}\n </button>\n )}\n <Address.Picker\n query={query}\n onQueryChange={changeQuery}\n getSuggestions={suggestions}\n onSelect={(value) => {\n if (\"address\" in value) {\n void select(value.address);\n }\n }}\n >\n {({ suggestions, status, isOpen }) => (\n <Fragment>\n <label className=\"z-base-field\" htmlFor=\"z-base-delivery-address\">\n Delivery address\n <Address.Input\n className=\"z-base-input\"\n id=\"z-base-delivery-address\"\n aria-label=\"Delivery address\"\n />\n </label>\n {status === \"loading\" && <p role=\"status\">Finding addresses\u2026</p>}\n {status === \"error\" && (\n <p role=\"alert\">Unable to find addresses. Try again.</p>\n )}\n {isOpen && (\n <Address.Suggestions className=\"z-base-suggestions\">\n {suggestions.map((value, index) => (\n <Address.Suggestion\n key={value.id}\n index={index}\n className=\"z-base-choice\"\n >\n {value.label}\n </Address.Suggestion>\n ))}\n </Address.Suggestions>\n )}\n {isOpen &&\n status === \"ready\" &&\n query &&\n suggestions.length === 0 && <p>No matching addresses.</p>}\n </Fragment>\n )}\n </Address.Picker>\n <label className=\"z-base-field\">\n Delivery instructions\n <textarea\n className=\"z-base-input\"\n maxLength={500}\n value={instructions}\n onChange={(event) => setInstructions(event.target.value)}\n />\n </label>\n {selected && lookup.Map && <lookup.Map address={selected} />}\n {lookupError && <p role=\"alert\">{lookupError}</p>}\n {error && <p role=\"alert\">{error}</p>}\n <button\n type=\"button\"\n className=\"z-base-button\"\n disabled={!selected || busy}\n onClick={() => {\n void save();\n }}\n >\n {busy ? \"Locating address\u2026\" : \"Save address\"}\n </button>\n </Fragment>\n );\n}\nexport function AddressSheet() {\n const cart = useCart();\n return (\n <CartSheet\n id=\"address\"\n title=\"Delivery address\"\n trigger={\n cart.fulfilment?.type === \"delivery\"\n ? \"Change address\"\n : \"Add delivery address\"\n }\n >\n <AddressForm />\n </CartSheet>\n );\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["suggestions"]
7
+ }
@@ -0,0 +1,72 @@
1
+ // src/cart/cart-issues.tsx
2
+ import { Cart, useOverlay } from "@zappie/foundations";
3
+ import { useState } from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ var labels = {
6
+ remove_line: "Remove item",
7
+ accept_price: "Accept new price",
8
+ remove_promo: "Remove promo",
9
+ set_quantity: "Update quantity",
10
+ choose_option: "Choose options",
11
+ choose_other_option: "Change options",
12
+ change_address: "Change delivery address",
13
+ schedule: "Choose order time"
14
+ };
15
+ function Issue({
16
+ issue,
17
+ applyFix
18
+ }) {
19
+ const editor = useOverlay("cart_edit", issue.lineId ?? "");
20
+ const address = useOverlay("cart_sheet", "address");
21
+ const schedule = useOverlay("cart_sheet", "schedule");
22
+ const [error, setError] = useState(null);
23
+ const fix = (value) => {
24
+ setError(null);
25
+ try {
26
+ if (value.action === "choose_option" || value.action === "choose_other_option") {
27
+ editor.open();
28
+ } else if (value.action === "change_address") {
29
+ address.open();
30
+ } else if (value.action === "schedule") {
31
+ schedule.open();
32
+ } else {
33
+ applyFix(issue, value);
34
+ }
35
+ } catch (error2) {
36
+ setError(
37
+ error2 instanceof Error ? error2.message : "Unable to apply this change"
38
+ );
39
+ }
40
+ };
41
+ return /* @__PURE__ */ jsxs("li", { children: [
42
+ /* @__PURE__ */ jsx("p", { children: issue.message }),
43
+ issue.fixes.filter((value) => labels[value.action]).map((value, index) => /* @__PURE__ */ jsx(
44
+ "button",
45
+ {
46
+ type: "button",
47
+ className: "z-base-button-secondary",
48
+ onClick: () => fix(value),
49
+ children: value.action === "set_quantity" ? `Set quantity to ${value.quantity}` : labels[value.action]
50
+ },
51
+ index
52
+ )),
53
+ error && /* @__PURE__ */ jsx("p", { role: "alert", children: error })
54
+ ] });
55
+ }
56
+ function CartIssues() {
57
+ return /* @__PURE__ */ jsx(Cart.Issues, { children: ({ issues, applyFix }) => issues.length > 0 && /* @__PURE__ */ jsxs("section", { className: "z-base-issues", "aria-label": "Cart issues", children: [
58
+ /* @__PURE__ */ jsx("h2", { children: "Review your cart" }),
59
+ /* @__PURE__ */ jsx("ul", { children: issues.map((issue, index) => /* @__PURE__ */ jsx(
60
+ Issue,
61
+ {
62
+ issue,
63
+ applyFix
64
+ },
65
+ `${issue.lineId}:${issue.code}:${index}`
66
+ )) })
67
+ ] }) });
68
+ }
69
+ export {
70
+ CartIssues
71
+ };
72
+ //# sourceMappingURL=cart-issues.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/cart-issues.tsx"],
4
+ "sourcesContent": ["import { Cart, useOverlay } from \"@zappie/foundations\";\nimport type { CartFix, CartIssue } from \"@zappie/sdk\";\nimport { useState } from \"react\";\nconst labels: Partial<Record<CartFix[\"action\"], string>> = {\n remove_line: \"Remove item\",\n accept_price: \"Accept new price\",\n remove_promo: \"Remove promo\",\n set_quantity: \"Update quantity\",\n choose_option: \"Choose options\",\n choose_other_option: \"Change options\",\n change_address: \"Change delivery address\",\n schedule: \"Choose order time\",\n};\nfunction Issue({\n issue,\n applyFix,\n}: {\n issue: CartIssue;\n applyFix: (issue: CartIssue, fix: CartFix) => void;\n}) {\n const editor = useOverlay(\"cart_edit\", issue.lineId ?? \"\");\n const address = useOverlay(\"cart_sheet\", \"address\");\n const schedule = useOverlay(\"cart_sheet\", \"schedule\");\n const [error, setError] = useState<string | null>(null);\n const fix = (value: CartFix) => {\n setError(null);\n try {\n if (\n value.action === \"choose_option\" ||\n value.action === \"choose_other_option\"\n ) {\n editor.open();\n } else if (value.action === \"change_address\") {\n address.open();\n } else if (value.action === \"schedule\") {\n schedule.open();\n } else {\n applyFix(issue, value);\n }\n } catch (error) {\n setError(\n error instanceof Error ? error.message : \"Unable to apply this change\",\n );\n }\n };\n return (\n <li>\n <p>{issue.message}</p>\n {issue.fixes\n .filter((value) => labels[value.action])\n .map((value, index) => (\n <button\n key={index}\n type=\"button\"\n className=\"z-base-button-secondary\"\n onClick={() => fix(value)}\n >\n {value.action === \"set_quantity\"\n ? `Set quantity to ${value.quantity}`\n : labels[value.action]}\n </button>\n ))}\n {error && <p role=\"alert\">{error}</p>}\n </li>\n );\n}\nexport function CartIssues() {\n return (\n <Cart.Issues>\n {({ issues, applyFix }) =>\n issues.length > 0 && (\n <section className=\"z-base-issues\" aria-label=\"Cart issues\">\n <h2>Review your cart</h2>\n <ul>\n {issues.map((issue, index) => (\n <Issue\n key={`${issue.lineId}:${issue.code}:${index}`}\n issue={issue}\n applyFix={applyFix}\n />\n ))}\n </ul>\n </section>\n )\n }\n </Cart.Issues>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,MAAM,kBAAkB;AAEjC,SAAS,gBAAgB;AA4CrB,SACE,KADF;AA3CJ,IAAM,SAAqD;AAAA,EACzD,aAAa;AAAA,EACb,cAAc;AAAA,EACd,cAAc;AAAA,EACd,cAAc;AAAA,EACd,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,gBAAgB;AAAA,EAChB,UAAU;AACZ;AACA,SAAS,MAAM;AAAA,EACb;AAAA,EACA;AACF,GAGG;AACD,QAAM,SAAS,WAAW,aAAa,MAAM,UAAU,EAAE;AACzD,QAAM,UAAU,WAAW,cAAc,SAAS;AAClD,QAAM,WAAW,WAAW,cAAc,UAAU;AACpD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,MAAM,CAAC,UAAmB;AAC9B,aAAS,IAAI;AACb,QAAI;AACF,UACE,MAAM,WAAW,mBACjB,MAAM,WAAW,uBACjB;AACA,eAAO,KAAK;AAAA,MACd,WAAW,MAAM,WAAW,kBAAkB;AAC5C,gBAAQ,KAAK;AAAA,MACf,WAAW,MAAM,WAAW,YAAY;AACtC,iBAAS,KAAK;AAAA,MAChB,OAAO;AACL,iBAAS,OAAO,KAAK;AAAA,MACvB;AAAA,IACF,SAASA,QAAO;AACd;AAAA,QACEA,kBAAiB,QAAQA,OAAM,UAAU;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACA,SACE,qBAAC,QACC;AAAA,wBAAC,OAAG,gBAAM,SAAQ;AAAA,IACjB,MAAM,MACJ,OAAO,CAAC,UAAU,OAAO,MAAM,MAAM,CAAC,EACtC,IAAI,CAAC,OAAO,UACX;AAAA,MAAC;AAAA;AAAA,QAEC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,SAAS,MAAM,IAAI,KAAK;AAAA,QAEvB,gBAAM,WAAW,iBACd,mBAAmB,MAAM,QAAQ,KACjC,OAAO,MAAM,MAAM;AAAA;AAAA,MAPlB;AAAA,IAQP,CACD;AAAA,IACF,SAAS,oBAAC,OAAE,MAAK,SAAS,iBAAM;AAAA,KACnC;AAEJ;AACO,SAAS,aAAa;AAC3B,SACE,oBAAC,KAAK,QAAL,EACE,WAAC,EAAE,QAAQ,SAAS,MACnB,OAAO,SAAS,KACd,qBAAC,aAAQ,WAAU,iBAAgB,cAAW,eAC5C;AAAA,wBAAC,QAAG,8BAAgB;AAAA,IACpB,oBAAC,QACE,iBAAO,IAAI,CAAC,OAAO,UAClB;AAAA,MAAC;AAAA;AAAA,QAEC;AAAA,QACA;AAAA;AAAA,MAFK,GAAG,MAAM,MAAM,IAAI,MAAM,IAAI,IAAI,KAAK;AAAA,IAG7C,CACD,GACH;AAAA,KACF,GAGN;AAEJ;",
6
+ "names": ["error"]
7
+ }
@@ -0,0 +1,34 @@
1
+ // src/cart/cart-line-groups.ts
2
+ function groupCartLinesByMenu(lines, catalogue) {
3
+ const names = new Map(
4
+ (catalogue?.menus ?? []).map((menu) => [menu.id, menu.name])
5
+ );
6
+ const groups = /* @__PURE__ */ new Map();
7
+ for (const line of lines) {
8
+ const menuId = line.menuId ?? "unknown";
9
+ const group = groups.get(menuId);
10
+ if (group) {
11
+ group.lines.push(line);
12
+ continue;
13
+ }
14
+ const menuName = names.get(menuId);
15
+ groups.set(menuId, {
16
+ menuId,
17
+ ...menuName !== void 0 ? { menuName } : {},
18
+ lines: [line]
19
+ });
20
+ }
21
+ const ordered = [];
22
+ for (const menu of catalogue?.menus ?? []) {
23
+ const group = groups.get(menu.id);
24
+ if (group) {
25
+ ordered.push(group);
26
+ groups.delete(menu.id);
27
+ }
28
+ }
29
+ return [...ordered, ...groups.values()];
30
+ }
31
+ export {
32
+ groupCartLinesByMenu
33
+ };
34
+ //# sourceMappingURL=cart-line-groups.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/cart-line-groups.ts"],
4
+ "sourcesContent": ["import type { CartLine, Menu } from \"@zappie/sdk\";\n\nexport type CartLineGroup = {\n menuId: string;\n menuName?: string;\n lines: CartLine[];\n};\n\nexport function groupCartLinesByMenu(\n lines: readonly CartLine[],\n catalogue?: Menu,\n): CartLineGroup[] {\n const names = new Map(\n (catalogue?.menus ?? []).map((menu) => [menu.id, menu.name]),\n );\n const groups = new Map<string, CartLineGroup>();\n for (const line of lines) {\n const menuId = line.menuId ?? \"unknown\";\n const group = groups.get(menuId);\n if (group) {\n group.lines.push(line);\n continue;\n }\n const menuName = names.get(menuId);\n groups.set(menuId, {\n menuId,\n ...(menuName !== undefined ? { menuName } : {}),\n lines: [line],\n });\n }\n const ordered: CartLineGroup[] = [];\n for (const menu of catalogue?.menus ?? []) {\n const group = groups.get(menu.id);\n if (group) {\n ordered.push(group);\n groups.delete(menu.id);\n }\n }\n return [...ordered, ...groups.values()];\n}\n"],
5
+ "mappings": ";AAQO,SAAS,qBACd,OACA,WACiB;AACjB,QAAM,QAAQ,IAAI;AAAA,KACf,WAAW,SAAS,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC;AAAA,EAC7D;AACA,QAAM,SAAS,oBAAI,IAA2B;AAC9C,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,KAAK,UAAU;AAC9B,UAAM,QAAQ,OAAO,IAAI,MAAM;AAC/B,QAAI,OAAO;AACT,YAAM,MAAM,KAAK,IAAI;AACrB;AAAA,IACF;AACA,UAAM,WAAW,MAAM,IAAI,MAAM;AACjC,WAAO,IAAI,QAAQ;AAAA,MACjB;AAAA,MACA,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,MAC7C,OAAO,CAAC,IAAI;AAAA,IACd,CAAC;AAAA,EACH;AACA,QAAM,UAA2B,CAAC;AAClC,aAAW,QAAQ,WAAW,SAAS,CAAC,GAAG;AACzC,UAAM,QAAQ,OAAO,IAAI,KAAK,EAAE;AAChC,QAAI,OAAO;AACT,cAAQ,KAAK,KAAK;AAClB,aAAO,OAAO,KAAK,EAAE;AAAA,IACvB;AAAA,EACF;AACA,SAAO,CAAC,GAAG,SAAS,GAAG,OAAO,OAAO,CAAC;AACxC;",
6
+ "names": []
7
+ }
@@ -1,69 +1,8 @@
1
- import { ItemConfigurator } from './chunk-2MV6KU3R.js';
2
- import { useThemeClass } from './chunk-JFEI2OUZ.js';
3
- import { useOverlay, Overlay, Cart, Money, Quantity } from '@zappie/foundations';
4
- import { useCart, useZappie } from '@zappie/sdk/react';
5
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
-
7
- function ClearCart() {
8
- const rootClass = useThemeClass("z-base-cart z-base-confirm");
9
- const cart = useCart();
10
- const confirm = useOverlay("cart_clear", "confirm");
11
- return /* @__PURE__ */ jsxs(Overlay.Root, { param: "cart_clear", id: "confirm", presentation: "dialog", children: [
12
- /* @__PURE__ */ jsx(Overlay.Trigger, { className: "z-base-button-secondary", children: "Clear cart" }),
13
- /* @__PURE__ */ jsxs(
14
- Overlay.Content,
15
- {
16
- "data-zappie-theme": "base",
17
- role: "alertdialog",
18
- className: rootClass,
19
- children: [
20
- /* @__PURE__ */ jsx(Overlay.Title, { children: "Clear your cart?" }),
21
- /* @__PURE__ */ jsx("p", { children: "This removes every item in your cart." }),
22
- /* @__PURE__ */ jsxs("div", { className: "z-base-confirm-actions", children: [
23
- /* @__PURE__ */ jsx(Overlay.Close, { className: "z-base-button-secondary", children: "Keep items" }),
24
- /* @__PURE__ */ jsx(
25
- "button",
26
- {
27
- type: "button",
28
- className: "z-base-button",
29
- onClick: () => {
30
- cart.actions.clear();
31
- confirm.close();
32
- },
33
- children: "Clear cart"
34
- }
35
- )
36
- ] })
37
- ]
38
- }
39
- )
40
- ] });
41
- }
42
- function LineEditor({ line, item }) {
43
- const rootClass = useThemeClass("z-base-cart z-base-editor");
44
- const overlay = useOverlay("cart_edit", line.id);
45
- const client = useZappie();
46
- return /* @__PURE__ */ jsxs(Overlay.Content, { "data-zappie-theme": "base", className: rootClass, children: [
47
- /* @__PURE__ */ jsxs("header", { className: "z-base-cart-header", children: [
48
- /* @__PURE__ */ jsxs(Overlay.Title, { children: [
49
- "Edit ",
50
- line.name
51
- ] }),
52
- /* @__PURE__ */ jsx(Overlay.Close, { className: "z-base-button-secondary", children: "Cancel" })
53
- ] }),
54
- overlay.isOpen && /* @__PURE__ */ jsx("div", { className: "z-base-cart-body", children: /* @__PURE__ */ jsx(
55
- ItemConfigurator,
56
- {
57
- item,
58
- ...line.menuId !== void 0 ? { menuId: line.menuId } : {},
59
- line,
60
- scope: `${client.config.store}:${client.cart.branchId}:${client.cart.fulfilment?.type}`,
61
- onComplete: overlay.close
62
- },
63
- line.id
64
- ) })
65
- ] });
66
- }
1
+ // src/cart/cart-line.tsx
2
+ import { Cart, Money, Overlay, Quantity } from "@zappie/foundations";
3
+ import { useCart } from "@zappie/sdk/react";
4
+ import { LineEditor } from "./line-editor.js";
5
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
67
6
  function CartLine({ line }) {
68
7
  const cart = useCart();
69
8
  const invalid = cart.issues.some(
@@ -140,7 +79,7 @@ function CartLine({ line }) {
140
79
  ] })
141
80
  ] }) });
142
81
  }
143
-
144
- export { CartLine, ClearCart };
145
- //# sourceMappingURL=chunk-FB5DRCU7.js.map
146
- //# sourceMappingURL=chunk-FB5DRCU7.js.map
82
+ export {
83
+ CartLine
84
+ };
85
+ //# sourceMappingURL=cart-line.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/cart-line.tsx"],
4
+ "sourcesContent": ["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 ? ` \u00D7 ${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 \u2212\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"],
5
+ "mappings": ";AAAA,SAAS,MAAM,OAAO,SAAS,gBAAgB;AAE/C,SAAS,eAAe;AACxB,SAAS,kBAAkB;AASnB,mBAEI,KADF,YADF;AARD,SAAS,SAAS,EAAE,KAAK,GAAmB;AACjD,QAAM,OAAO,QAAQ;AACrB,QAAM,UAAU,KAAK,OAAO;AAAA,IAC1B,CAAC,UAAU,MAAM,WAAW,KAAK,MAAM,MAAM,aAAa;AAAA,EAC5D;AACA,SACE,oBAAC,KAAK,MAAL,EAAU,MAAY,WAAU,eAC9B,WAAC,EAAE,KAAK,MACP,iCACE;AAAA,yBAAC,SAAI,WAAU,uBACb;AAAA,0BAAC,QAAI,eAAK,MAAK;AAAA,MACd,QAAQ,CAAC,UACR,oBAAC,SAAM,OAAO,KAAK,cAAc,IAEjC,oBAAC,UAAK,+BAAiB;AAAA,OAE3B;AAAA,IACA,qBAAC,QAAG,WAAU,uBACX;AAAA,WAAK,QAAQ,IAAI,CAAC,cAAc;AAC/B,cAAM,QAAQ,MAAM,aAAa;AAAA,UAC/B,CAACA,WAAUA,OAAM,OAAO,UAAU;AAAA,QACpC;AACA,cAAM,SAAS,OAAO,QAAQ;AAAA,UAC5B,CAACC,YAAWA,QAAO,OAAO,UAAU;AAAA,QACtC;AACA,eACE,qBAAC,QACE;AAAA,kBAAQ,QAAQ;AAAA,UAChB,UAAU,WAAW,IAAI,SAAM,UAAU,QAAQ,KAAK;AAAA,aAFhD,GAAG,UAAU,OAAO,IAAI,UAAU,QAAQ,EAGnD;AAAA,MAEJ,CAAC;AAAA,MACA,OAAO,QAAQ,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,MAC1C,qBAAC,QACE;AAAA,cAAM,aAAa,KAAK,CAAC,UAAU,MAAM,OAAO,EAAE,GAAG,QACpD;AAAA,QAAU;AAAA,QACT;AAAA,WAHI,EAIT,CACD;AAAA,OACH;AAAA,IACC,KAAK,QAAQ,oBAAC,OAAE,WAAU,gBAAgB,eAAK,MAAK;AAAA,IACrD,qBAAC,SAAI,WAAU,uBACb;AAAA;AAAA,QAAC,KAAK;AAAA,QAAL;AAAA,UACC,QAAQ,KAAK;AAAA,UACb,UAAU;AAAA,UACV,WAAU;AAAA,UAEV;AAAA,gCAAC,SAAS,WAAT,EAAmB,cAAY,YAAY,KAAK,IAAI,aAAa,oBAElE;AAAA,YACA,oBAAC,SAAS,OAAT,EAAe,cAAY,GAAG,KAAK,IAAI,aAAa;AAAA,YACrD,oBAAC,SAAS,WAAT,EAAmB,cAAY,YAAY,KAAK,IAAI,aAAa,eAElE;AAAA;AAAA;AAAA,MACF;AAAA,MACA;AAAA,QAAC,QAAQ;AAAA,QAAR;AAAA,UACC,OAAM;AAAA,UACN,IAAI,KAAK;AAAA,UACT,cAAc,EAAE,MAAM,SAAS,IAAI,SAAS;AAAA,UAE5C;AAAA;AAAA,cAAC,QAAQ;AAAA,cAAR;AAAA,gBACC,WAAU;AAAA,gBACV,UAAU,CAAC;AAAA,gBACX,cAAY,QAAQ,KAAK,IAAI;AAAA,gBAC9B;AAAA;AAAA,YAED;AAAA,YACC,QAAQ,oBAAC,cAAW,MAAY,MAAY;AAAA;AAAA;AAAA,MAC/C;AAAA,MACA;AAAA,QAAC,KAAK;AAAA,QAAL;AAAA,UACC,QAAQ,KAAK;AAAA,UACb,WAAU;AAAA,UACV,cAAY,UAAU,KAAK,IAAI;AAAA,UAChC;AAAA;AAAA,MAED;AAAA,OACF;AAAA,KACF,GAEJ;AAEJ;",
6
+ "names": ["group", "choice"]
7
+ }
@@ -0,0 +1,27 @@
1
+ // src/cart/cart-lines.tsx
2
+ import { useCart, useCartCatalogue } from "@zappie/sdk/react";
3
+ import { CartLine } from "./cart-line.js";
4
+ import { groupCartLinesByMenu } from "./cart-line-groups.js";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ function CartLines() {
7
+ const { lines } = useCart();
8
+ const catalogue = useCartCatalogue();
9
+ const groups = groupCartLinesByMenu(lines, catalogue);
10
+ const grouped = (catalogue?.menus?.length ?? 0) > 1;
11
+ return /* @__PURE__ */ jsx("section", { "aria-label": "Cart items", className: "z-base-lines", children: groups.map((group) => /* @__PURE__ */ jsxs(
12
+ "section",
13
+ {
14
+ "aria-label": group.menuName ?? "Other items",
15
+ className: "z-base-line-group",
16
+ children: [
17
+ grouped && /* @__PURE__ */ jsx("h2", { children: group.menuName ?? "Other items" }),
18
+ group.lines.map((line) => /* @__PURE__ */ jsx(CartLine, { line }, line.id))
19
+ ]
20
+ },
21
+ group.menuId
22
+ )) });
23
+ }
24
+ export {
25
+ CartLines
26
+ };
27
+ //# sourceMappingURL=cart-lines.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/cart-lines.tsx"],
4
+ "sourcesContent": ["import { useCart, useCartCatalogue } from \"@zappie/sdk/react\";\nimport { CartLine } from \"./cart-line\";\nimport { groupCartLinesByMenu } from \"./cart-line-groups\";\nexport function CartLines() {\n const { lines } = useCart();\n const catalogue = useCartCatalogue();\n const groups = groupCartLinesByMenu(lines, catalogue);\n const grouped = (catalogue?.menus?.length ?? 0) > 1;\n return (\n <section aria-label=\"Cart items\" className=\"z-base-lines\">\n {groups.map((group) => (\n <section\n key={group.menuId}\n aria-label={group.menuName ?? \"Other items\"}\n className=\"z-base-line-group\"\n >\n {grouped && <h2>{group.menuName ?? \"Other items\"}</h2>}\n {group.lines.map((line) => (\n <CartLine key={line.id} line={line} />\n ))}\n </section>\n ))}\n </section>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,SAAS,wBAAwB;AAC1C,SAAS,gBAAgB;AACzB,SAAS,4BAA4B;AAS7B,SAKc,KALd;AARD,SAAS,YAAY;AAC1B,QAAM,EAAE,MAAM,IAAI,QAAQ;AAC1B,QAAM,YAAY,iBAAiB;AACnC,QAAM,SAAS,qBAAqB,OAAO,SAAS;AACpD,QAAM,WAAW,WAAW,OAAO,UAAU,KAAK;AAClD,SACE,oBAAC,aAAQ,cAAW,cAAa,WAAU,gBACxC,iBAAO,IAAI,CAAC,UACX;AAAA,IAAC;AAAA;AAAA,MAEC,cAAY,MAAM,YAAY;AAAA,MAC9B,WAAU;AAAA,MAET;AAAA,mBAAW,oBAAC,QAAI,gBAAM,YAAY,eAAc;AAAA,QAChD,MAAM,MAAM,IAAI,CAAC,SAChB,oBAAC,YAAuB,QAAT,KAAK,EAAgB,CACrC;AAAA;AAAA;AAAA,IAPI,MAAM;AAAA,EAQb,CACD,GACH;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,24 @@
1
+ // src/cart/cart-schedule.ts
2
+ function cartScheduleLimits(menu, lines, maxDays) {
3
+ const sections = (menu?.menus ?? []).filter(
4
+ (section) => section.schedule?.preorder && lines.some(
5
+ (line) => line.menuId ? line.menuId === section.id : section.categoryIds.some(
6
+ (id) => menu?.categories.find((category) => category.id === id)?.itemIds.includes(line.itemId)
7
+ )
8
+ )
9
+ );
10
+ const notice = Math.max(
11
+ 0,
12
+ ...sections.map((section) => section.schedule?.preorderNoticeHours ?? 0)
13
+ );
14
+ const horizons = sections.map((section) => section.schedule?.preorderMaxDays).filter((days) => typeof days === "number" && days > 0);
15
+ const limit = horizons.length > 0 ? Math.min(maxDays ?? Number.POSITIVE_INFINITY, ...horizons) : maxDays;
16
+ return {
17
+ noticeMinutes: notice * 60,
18
+ maxDays: limit === void 0 ? void 0 : Math.max(1, Math.min(90, limit))
19
+ };
20
+ }
21
+ export {
22
+ cartScheduleLimits
23
+ };
24
+ //# sourceMappingURL=cart-schedule.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/cart-schedule.ts"],
4
+ "sourcesContent": ["import type { CartLine, Menu } from \"@zappie/sdk\";\n/**\n * Pre-order limits for the menus the cart's lines come from. Schedule reads a\n * menu's notice only from a single-menu catalogue; with several menus the\n * tightest notice and horizon among the cart's pre-order menus apply.\n */\nexport function cartScheduleLimits(\n menu: Menu | undefined,\n lines: readonly CartLine[],\n maxDays: number | undefined,\n): { noticeMinutes: number; maxDays: number | undefined } {\n const sections = (menu?.menus ?? []).filter(\n (section) =>\n section.schedule?.preorder &&\n lines.some((line) =>\n line.menuId\n ? line.menuId === section.id\n : section.categoryIds.some((id) =>\n menu?.categories\n .find((category) => category.id === id)\n ?.itemIds.includes(line.itemId),\n ),\n ),\n );\n const notice = Math.max(\n 0,\n ...sections.map((section) => section.schedule?.preorderNoticeHours ?? 0),\n );\n const horizons = sections\n .map((section) => section.schedule?.preorderMaxDays)\n .filter((days): days is number => typeof days === \"number\" && days > 0);\n const limit =\n horizons.length > 0\n ? Math.min(maxDays ?? Number.POSITIVE_INFINITY, ...horizons)\n : maxDays;\n return {\n noticeMinutes: notice * 60,\n maxDays: limit === undefined ? undefined : Math.max(1, Math.min(90, limit)),\n };\n}\n"],
5
+ "mappings": ";AAMO,SAAS,mBACd,MACA,OACA,SACwD;AACxD,QAAM,YAAY,MAAM,SAAS,CAAC,GAAG;AAAA,IACnC,CAAC,YACC,QAAQ,UAAU,YAClB,MAAM;AAAA,MAAK,CAAC,SACV,KAAK,SACD,KAAK,WAAW,QAAQ,KACxB,QAAQ,YAAY;AAAA,QAAK,CAAC,OACxB,MAAM,WACH,KAAK,CAAC,aAAa,SAAS,OAAO,EAAE,GACpC,QAAQ,SAAS,KAAK,MAAM;AAAA,MAClC;AAAA,IACN;AAAA,EACJ;AACA,QAAM,SAAS,KAAK;AAAA,IAClB;AAAA,IACA,GAAG,SAAS,IAAI,CAAC,YAAY,QAAQ,UAAU,uBAAuB,CAAC;AAAA,EACzE;AACA,QAAM,WAAW,SACd,IAAI,CAAC,YAAY,QAAQ,UAAU,eAAe,EAClD,OAAO,CAAC,SAAyB,OAAO,SAAS,YAAY,OAAO,CAAC;AACxE,QAAM,QACJ,SAAS,SAAS,IACd,KAAK,IAAI,WAAW,OAAO,mBAAmB,GAAG,QAAQ,IACzD;AACN,SAAO;AAAA,IACL,eAAe,SAAS;AAAA,IACxB,SAAS,UAAU,SAAY,SAAY,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC;AAAA,EAC5E;AACF;",
6
+ "names": []
7
+ }