@zorgo/next 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +19 -0
  2. package/dist/cli.d.mts +5 -0
  3. package/dist/cli.d.ts +5 -0
  4. package/dist/cli.js +2 -0
  5. package/dist/cli.mjs +2 -0
  6. package/dist/components.d.mts +337 -0
  7. package/dist/components.d.ts +337 -0
  8. package/dist/components.js +1996 -0
  9. package/dist/components.js.map +1 -0
  10. package/dist/components.mjs +1962 -0
  11. package/dist/components.mjs.map +1 -0
  12. package/dist/index.d.mts +305 -0
  13. package/dist/index.d.ts +305 -0
  14. package/dist/index.js +2 -0
  15. package/dist/index.mjs +2 -0
  16. package/dist/seo.d.mts +30 -0
  17. package/dist/seo.d.ts +30 -0
  18. package/dist/seo.js +82 -0
  19. package/dist/seo.js.map +1 -0
  20. package/dist/seo.mjs +56 -0
  21. package/dist/seo.mjs.map +1 -0
  22. package/dist/slugs.d.mts +1 -0
  23. package/dist/slugs.d.ts +1 -0
  24. package/dist/slugs.js +47 -0
  25. package/dist/slugs.js.map +1 -0
  26. package/dist/slugs.mjs +19 -0
  27. package/dist/slugs.mjs.map +1 -0
  28. package/dist/tree/.env.gen.ts +27 -0
  29. package/dist/tree/README.md +0 -0
  30. package/dist/tree/app/api/zorgo-token/route.ts +11 -0
  31. package/dist/tree/app/apple-icon.tsx.gen.ts +54 -0
  32. package/dist/tree/app/checkout/page.tsx +10 -0
  33. package/dist/tree/app/components/Footer.tsx +50 -0
  34. package/dist/tree/app/components/Header.tsx +128 -0
  35. package/dist/tree/app/components/ModalHost.tsx +56 -0
  36. package/dist/tree/app/components/ModalRegistry.tsx +113 -0
  37. package/dist/tree/app/components/TestCard.tsx +35 -0
  38. package/dist/tree/app/components/index.ts +3 -0
  39. package/dist/tree/app/error.tsx +10 -0
  40. package/dist/tree/app/global-error.tsx +12 -0
  41. package/dist/tree/app/globals.css.gen.ts +123 -0
  42. package/dist/tree/app/icon.tsx.gen.ts +87 -0
  43. package/dist/tree/app/layout.tsx.gen.ts +55 -0
  44. package/dist/tree/app/locations/page.tsx +30 -0
  45. package/dist/tree/app/manifest.ts.gen.ts +39 -0
  46. package/dist/tree/app/menu/[slug]/ItemCustomizationClient.tsx +18 -0
  47. package/dist/tree/app/menu/[slug]/page.tsx +78 -0
  48. package/dist/tree/app/menu/page.tsx +36 -0
  49. package/dist/tree/app/not-found.tsx +8 -0
  50. package/dist/tree/app/opengraph-image.tsx.gen.ts +82 -0
  51. package/dist/tree/app/page.tsx +19 -0
  52. package/dist/tree/app/privacy/page.tsx.gen.ts +15 -0
  53. package/dist/tree/app/robots.ts +9 -0
  54. package/dist/tree/app/sitemap.ts +26 -0
  55. package/dist/tree/app/terms/page.tsx.gen.ts +16 -0
  56. package/dist/tree/gitignore +44 -0
  57. package/dist/tree/lib/zorgoSiteToken.ts +20 -0
  58. package/dist/tree/next.config.ts +14 -0
  59. package/dist/tree/open-next.config.ts +4 -0
  60. package/dist/tree/package.json.gen.ts +24 -0
  61. package/dist/tree/postcss.config.mjs +7 -0
  62. package/dist/tree/scripts/prebuild.ts +448 -0
  63. package/dist/tree/tsconfig.json +35 -0
  64. package/package.json +72 -0
@@ -0,0 +1,1996 @@
1
+ "use client";
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/components/index.ts
32
+ var components_exports = {};
33
+ __export(components_exports, {
34
+ ACCORDION_MENU_DEFAULT_ITEM_CLASSES: () => ACCORDION_MENU_DEFAULT_ITEM_CLASSES,
35
+ AccordionMenu: () => AccordionMenu,
36
+ BREADCRUMBS_DEFAULT_ITEM_CLASSES: () => BREADCRUMBS_DEFAULT_ITEM_CLASSES,
37
+ Breadcrumbs: () => Breadcrumbs,
38
+ CHECKOUT_FORM_DEFAULT_ITEM_CLASSES: () => CHECKOUT_FORM_DEFAULT_ITEM_CLASSES,
39
+ CheckoutForm: () => CheckoutForm,
40
+ CookieConsent: () => CookieConsent,
41
+ FIND_LOCATION_DEFAULT_ITEM_CLASSES: () => FIND_LOCATION_DEFAULT_ITEM_CLASSES,
42
+ FindLocation: () => FindLocation,
43
+ GRID_MENU_DEFAULT_ITEM_CLASSES: () => GRID_MENU_DEFAULT_ITEM_CLASSES,
44
+ GridMenu: () => GridMenu,
45
+ ITEM_CUSTOMIZATION_FORM_DEFAULT_ITEM_CLASSES: () => ITEM_CUSTOMIZATION_FORM_DEFAULT_ITEM_CLASSES,
46
+ ItemCustomizationForm: () => ItemCustomizationForm,
47
+ mergeAccordionMenuItemClasses: () => mergeAccordionMenuItemClasses,
48
+ mergeBreadcrumbsItemClasses: () => mergeBreadcrumbsItemClasses,
49
+ mergeCheckoutFormItemClasses: () => mergeCheckoutFormItemClasses,
50
+ mergeFindLocationItemClasses: () => mergeFindLocationItemClasses,
51
+ mergeGridMenuItemClasses: () => mergeGridMenuItemClasses,
52
+ mergeItemCustomizationFormItemClasses: () => mergeItemCustomizationFormItemClasses
53
+ });
54
+ module.exports = __toCommonJS(components_exports);
55
+
56
+ // src/components/CookieConsent.tsx
57
+ var import_react12 = require("react");
58
+
59
+ // ../../node_modules/@headlessui/react/dist/utils/env.js
60
+ var i = Object.defineProperty;
61
+ var d = (t6, e, n3) => e in t6 ? i(t6, e, { enumerable: true, configurable: true, writable: true, value: n3 }) : t6[e] = n3;
62
+ var r = (t6, e, n3) => (d(t6, typeof e != "symbol" ? e + "" : e, n3), n3);
63
+ var o = class {
64
+ constructor() {
65
+ r(this, "current", this.detect());
66
+ r(this, "handoffState", "pending");
67
+ r(this, "currentId", 0);
68
+ }
69
+ set(e) {
70
+ this.current !== e && (this.handoffState = "pending", this.currentId = 0, this.current = e);
71
+ }
72
+ reset() {
73
+ this.set(this.detect());
74
+ }
75
+ nextId() {
76
+ return ++this.currentId;
77
+ }
78
+ get isServer() {
79
+ return this.current === "server";
80
+ }
81
+ get isClient() {
82
+ return this.current === "client";
83
+ }
84
+ detect() {
85
+ return typeof window == "undefined" || typeof document == "undefined" ? "server" : "client";
86
+ }
87
+ handoff() {
88
+ this.handoffState === "pending" && (this.handoffState = "complete");
89
+ }
90
+ get isHandoffComplete() {
91
+ return this.handoffState === "complete";
92
+ }
93
+ };
94
+ var s = new o();
95
+
96
+ // ../../node_modules/@headlessui/react/dist/hooks/use-disposables.js
97
+ var import_react = require("react");
98
+
99
+ // ../../node_modules/@headlessui/react/dist/utils/micro-task.js
100
+ function t(e) {
101
+ typeof queueMicrotask == "function" ? queueMicrotask(e) : Promise.resolve().then(e).catch((o5) => setTimeout(() => {
102
+ throw o5;
103
+ }));
104
+ }
105
+
106
+ // ../../node_modules/@headlessui/react/dist/utils/disposables.js
107
+ function o2() {
108
+ let s5 = [], r4 = { addEventListener(e, t6, n3, i4) {
109
+ return e.addEventListener(t6, n3, i4), r4.add(() => e.removeEventListener(t6, n3, i4));
110
+ }, requestAnimationFrame(...e) {
111
+ let t6 = requestAnimationFrame(...e);
112
+ return r4.add(() => cancelAnimationFrame(t6));
113
+ }, nextFrame(...e) {
114
+ return r4.requestAnimationFrame(() => r4.requestAnimationFrame(...e));
115
+ }, setTimeout(...e) {
116
+ let t6 = setTimeout(...e);
117
+ return r4.add(() => clearTimeout(t6));
118
+ }, microTask(...e) {
119
+ let t6 = { current: true };
120
+ return t(() => {
121
+ t6.current && e[0]();
122
+ }), r4.add(() => {
123
+ t6.current = false;
124
+ });
125
+ }, style(e, t6, n3) {
126
+ let i4 = e.style.getPropertyValue(t6);
127
+ return Object.assign(e.style, { [t6]: n3 }), this.add(() => {
128
+ Object.assign(e.style, { [t6]: i4 });
129
+ });
130
+ }, group(e) {
131
+ let t6 = o2();
132
+ return e(t6), this.add(() => t6.dispose());
133
+ }, add(e) {
134
+ return s5.includes(e) || s5.push(e), () => {
135
+ let t6 = s5.indexOf(e);
136
+ if (t6 >= 0) for (let n3 of s5.splice(t6, 1)) n3();
137
+ };
138
+ }, dispose() {
139
+ for (let e of s5.splice(0)) e();
140
+ } };
141
+ return r4;
142
+ }
143
+
144
+ // ../../node_modules/@headlessui/react/dist/hooks/use-disposables.js
145
+ function p() {
146
+ let [e] = (0, import_react.useState)(o2);
147
+ return (0, import_react.useEffect)(() => () => e.dispose(), [e]), e;
148
+ }
149
+
150
+ // ../../node_modules/@headlessui/react/dist/hooks/use-event.js
151
+ var import_react4 = __toESM(require("react"), 1);
152
+
153
+ // ../../node_modules/@headlessui/react/dist/hooks/use-latest-value.js
154
+ var import_react3 = require("react");
155
+
156
+ // ../../node_modules/@headlessui/react/dist/hooks/use-iso-morphic-effect.js
157
+ var import_react2 = require("react");
158
+ var n = (e, t6) => {
159
+ s.isServer ? (0, import_react2.useEffect)(e, t6) : (0, import_react2.useLayoutEffect)(e, t6);
160
+ };
161
+
162
+ // ../../node_modules/@headlessui/react/dist/hooks/use-latest-value.js
163
+ function s3(e) {
164
+ let r4 = (0, import_react3.useRef)(e);
165
+ return n(() => {
166
+ r4.current = e;
167
+ }, [e]), r4;
168
+ }
169
+
170
+ // ../../node_modules/@headlessui/react/dist/hooks/use-event.js
171
+ var o4 = function(t6) {
172
+ let e = s3(t6);
173
+ return import_react4.default.useCallback((...r4) => e.current(...r4), [e]);
174
+ };
175
+
176
+ // ../../node_modules/@headlessui/react/dist/utils/render.js
177
+ var import_react5 = __toESM(require("react"), 1);
178
+
179
+ // ../../node_modules/@headlessui/react/dist/utils/class-names.js
180
+ function t3(...r4) {
181
+ return Array.from(new Set(r4.flatMap((n3) => typeof n3 == "string" ? n3.split(" ") : []))).filter(Boolean).join(" ");
182
+ }
183
+
184
+ // ../../node_modules/@headlessui/react/dist/utils/match.js
185
+ function u(r4, n3, ...a2) {
186
+ if (r4 in n3) {
187
+ let e = n3[r4];
188
+ return typeof e == "function" ? e(...a2) : e;
189
+ }
190
+ let t6 = new Error(`Tried to handle "${r4}" but there is no handler defined. Only defined handlers are: ${Object.keys(n3).map((e) => `"${e}"`).join(", ")}.`);
191
+ throw Error.captureStackTrace && Error.captureStackTrace(t6, u), t6;
192
+ }
193
+
194
+ // ../../node_modules/@headlessui/react/dist/utils/render.js
195
+ var A = ((a2) => (a2[a2.None = 0] = "None", a2[a2.RenderStrategy = 1] = "RenderStrategy", a2[a2.Static = 2] = "Static", a2))(A || {});
196
+ var C = ((e) => (e[e.Unmount = 0] = "Unmount", e[e.Hidden = 1] = "Hidden", e))(C || {});
197
+ function K() {
198
+ let n3 = $();
199
+ return (0, import_react5.useCallback)((r4) => U({ mergeRefs: n3, ...r4 }), [n3]);
200
+ }
201
+ function U({ ourProps: n3, theirProps: r4, slot: e, defaultTag: a2, features: s5, visible: t6 = true, name: l4, mergeRefs: i4 }) {
202
+ i4 = i4 != null ? i4 : I;
203
+ let o5 = P(r4, n3);
204
+ if (t6) return F(o5, e, a2, l4, i4);
205
+ let y2 = s5 != null ? s5 : 0;
206
+ if (y2 & 2) {
207
+ let { static: f3 = false, ...u4 } = o5;
208
+ if (f3) return F(u4, e, a2, l4, i4);
209
+ }
210
+ if (y2 & 1) {
211
+ let { unmount: f3 = true, ...u4 } = o5;
212
+ return u(f3 ? 0 : 1, { [0]() {
213
+ return null;
214
+ }, [1]() {
215
+ return F({ ...u4, hidden: true, style: { display: "none" } }, e, a2, l4, i4);
216
+ } });
217
+ }
218
+ return F(o5, e, a2, l4, i4);
219
+ }
220
+ function F(n3, r4 = {}, e, a2, s5) {
221
+ let { as: t6 = e, children: l4, refName: i4 = "ref", ...o5 } = h(n3, ["unmount", "static"]), y2 = n3.ref !== void 0 ? { [i4]: n3.ref } : {}, f3 = typeof l4 == "function" ? l4(r4) : l4;
222
+ "className" in o5 && o5.className && typeof o5.className == "function" && (o5.className = o5.className(r4)), o5["aria-labelledby"] && o5["aria-labelledby"] === o5.id && (o5["aria-labelledby"] = void 0);
223
+ let u4 = {};
224
+ if (r4) {
225
+ let d3 = false, p2 = [];
226
+ for (let [c6, T2] of Object.entries(r4)) typeof T2 == "boolean" && (d3 = true), T2 === true && p2.push(c6.replace(/([A-Z])/g, (g) => `-${g.toLowerCase()}`));
227
+ if (d3) {
228
+ u4["data-headlessui-state"] = p2.join(" ");
229
+ for (let c6 of p2) u4[`data-${c6}`] = "";
230
+ }
231
+ }
232
+ if (b(t6) && (Object.keys(m(o5)).length > 0 || Object.keys(m(u4)).length > 0)) if (!(0, import_react5.isValidElement)(f3) || Array.isArray(f3) && f3.length > 1 || D(f3)) {
233
+ if (Object.keys(m(o5)).length > 0) throw new Error(['Passing props on "Fragment"!', "", `The current component <${a2} /> is rendering a "Fragment".`, "However we need to passthrough the following props:", Object.keys(m(o5)).concat(Object.keys(m(u4))).map((d3) => ` - ${d3}`).join(`
234
+ `), "", "You can apply a few solutions:", ['Add an `as="..."` prop, to ensure that we render an actual element instead of a "Fragment".', "Render a single element as the child so that we can forward the props onto that element."].map((d3) => ` - ${d3}`).join(`
235
+ `)].join(`
236
+ `));
237
+ } else {
238
+ let d3 = f3.props, p2 = d3 == null ? void 0 : d3.className, c6 = typeof p2 == "function" ? (...R) => t3(p2(...R), o5.className) : t3(p2, o5.className), T2 = c6 ? { className: c6 } : {}, g = P(f3.props, m(h(o5, ["ref"])));
239
+ for (let R in u4) R in g && delete u4[R];
240
+ return (0, import_react5.cloneElement)(f3, Object.assign({}, g, u4, y2, { ref: s5(H(f3), y2.ref) }, T2));
241
+ }
242
+ return (0, import_react5.createElement)(t6, Object.assign({}, h(o5, ["ref"]), !b(t6) && y2, !b(t6) && u4), f3);
243
+ }
244
+ function $() {
245
+ let n3 = (0, import_react5.useRef)([]), r4 = (0, import_react5.useCallback)((e) => {
246
+ for (let a2 of n3.current) a2 != null && (typeof a2 == "function" ? a2(e) : a2.current = e);
247
+ }, []);
248
+ return (...e) => {
249
+ if (!e.every((a2) => a2 == null)) return n3.current = e, r4;
250
+ };
251
+ }
252
+ function I(...n3) {
253
+ return n3.every((r4) => r4 == null) ? void 0 : (r4) => {
254
+ for (let e of n3) e != null && (typeof e == "function" ? e(r4) : e.current = r4);
255
+ };
256
+ }
257
+ function P(...n3) {
258
+ var a2;
259
+ if (n3.length === 0) return {};
260
+ if (n3.length === 1) return n3[0];
261
+ let r4 = {}, e = {};
262
+ for (let s5 of n3) for (let t6 in s5) t6.startsWith("on") && typeof s5[t6] == "function" ? ((a2 = e[t6]) != null || (e[t6] = []), e[t6].push(s5[t6])) : r4[t6] = s5[t6];
263
+ if (r4.disabled || r4["aria-disabled"]) for (let s5 in e) /^(on(?:Click|Pointer|Mouse|Key)(?:Down|Up|Press)?)$/.test(s5) && (e[s5] = [(t6) => {
264
+ var l4;
265
+ return (l4 = t6 == null ? void 0 : t6.preventDefault) == null ? void 0 : l4.call(t6);
266
+ }]);
267
+ for (let s5 in e) Object.assign(r4, { [s5](t6, ...l4) {
268
+ let i4 = e[s5];
269
+ for (let o5 of i4) {
270
+ if ((t6 instanceof Event || (t6 == null ? void 0 : t6.nativeEvent) instanceof Event) && t6.defaultPrevented) return;
271
+ o5(t6, ...l4);
272
+ }
273
+ } });
274
+ return r4;
275
+ }
276
+ function Y(n3) {
277
+ var r4;
278
+ return Object.assign((0, import_react5.forwardRef)(n3), { displayName: (r4 = n3.displayName) != null ? r4 : n3.name });
279
+ }
280
+ function m(n3) {
281
+ let r4 = Object.assign({}, n3);
282
+ for (let e in r4) r4[e] === void 0 && delete r4[e];
283
+ return r4;
284
+ }
285
+ function h(n3, r4 = []) {
286
+ let e = Object.assign({}, n3);
287
+ for (let a2 of r4) a2 in e && delete e[a2];
288
+ return e;
289
+ }
290
+ function H(n3) {
291
+ return import_react5.default.version.split(".")[0] >= "19" ? n3.props.ref : n3.ref;
292
+ }
293
+ function b(n3) {
294
+ return n3 === import_react5.Fragment || n3 === /* @__PURE__ */ Symbol.for("react.fragment");
295
+ }
296
+ function D(n3) {
297
+ return b(n3.type);
298
+ }
299
+
300
+ // ../../node_modules/@headlessui/react/dist/hooks/use-sync-refs.js
301
+ var import_react6 = require("react");
302
+ var u2 = /* @__PURE__ */ Symbol();
303
+ function y(...t6) {
304
+ let n3 = (0, import_react6.useRef)(t6);
305
+ (0, import_react6.useEffect)(() => {
306
+ n3.current = t6;
307
+ }, [t6]);
308
+ let c6 = o4((e) => {
309
+ for (let o5 of n3.current) o5 != null && (typeof o5 == "function" ? o5(e) : o5.current = e);
310
+ });
311
+ return t6.every((e) => e == null || (e == null ? void 0 : e[u2])) ? void 0 : c6;
312
+ }
313
+
314
+ // ../../node_modules/@headlessui/react/dist/hooks/use-transition.js
315
+ var import_react8 = require("react");
316
+
317
+ // ../../node_modules/@headlessui/react/dist/hooks/use-flags.js
318
+ var import_react7 = require("react");
319
+ function c2(u4 = 0) {
320
+ let [r4, a2] = (0, import_react7.useState)(u4), g = (0, import_react7.useCallback)((e) => a2(e), []), s5 = (0, import_react7.useCallback)((e) => a2((l4) => l4 | e), []), m2 = (0, import_react7.useCallback)((e) => (r4 & e) === e, [r4]), n3 = (0, import_react7.useCallback)((e) => a2((l4) => l4 & ~e), []), F2 = (0, import_react7.useCallback)((e) => a2((l4) => l4 ^ e), []);
321
+ return { flags: r4, setFlag: g, addFlag: s5, hasFlag: m2, removeFlag: n3, toggleFlag: F2 };
322
+ }
323
+
324
+ // ../../node_modules/@headlessui/react/dist/hooks/use-transition.js
325
+ var T;
326
+ var S2;
327
+ typeof process != "undefined" && typeof globalThis != "undefined" && typeof Element != "undefined" && ((T = process == null ? void 0 : process.env) == null ? void 0 : T["NODE_ENV"]) === "test" && typeof ((S2 = Element == null ? void 0 : Element.prototype) == null ? void 0 : S2.getAnimations) == "undefined" && (Element.prototype.getAnimations = function() {
328
+ return console.warn(["Headless UI has polyfilled `Element.prototype.getAnimations` for your tests.", "Please install a proper polyfill e.g. `jsdom-testing-mocks`, to silence these warnings.", "", "Example usage:", "```js", "import { mockAnimationsApi } from 'jsdom-testing-mocks'", "mockAnimationsApi()", "```"].join(`
329
+ `)), [];
330
+ });
331
+ var A2 = ((i4) => (i4[i4.None = 0] = "None", i4[i4.Closed = 1] = "Closed", i4[i4.Enter = 2] = "Enter", i4[i4.Leave = 4] = "Leave", i4))(A2 || {});
332
+ function x2(e) {
333
+ let r4 = {};
334
+ for (let t6 in e) e[t6] === true && (r4[`data-${t6}`] = "");
335
+ return r4;
336
+ }
337
+ function N(e, r4, t6, n3) {
338
+ let [i4, a2] = (0, import_react8.useState)(t6), { hasFlag: s5, addFlag: o5, removeFlag: l4 } = c2(e && i4 ? 3 : 0), u4 = (0, import_react8.useRef)(false), f3 = (0, import_react8.useRef)(false), E2 = p();
339
+ return n(() => {
340
+ var d3;
341
+ if (e) {
342
+ if (t6 && a2(true), !r4) {
343
+ t6 && o5(3);
344
+ return;
345
+ }
346
+ return (d3 = n3 == null ? void 0 : n3.start) == null || d3.call(n3, t6), C2(r4, { inFlight: u4, prepare() {
347
+ f3.current ? f3.current = false : f3.current = u4.current, u4.current = true, !f3.current && (t6 ? (o5(3), l4(4)) : (o5(4), l4(2)));
348
+ }, run() {
349
+ f3.current ? t6 ? (l4(3), o5(4)) : (l4(4), o5(3)) : t6 ? l4(1) : o5(1);
350
+ }, done() {
351
+ var p2;
352
+ f3.current && D2(r4) || (u4.current = false, l4(7), t6 || a2(false), (p2 = n3 == null ? void 0 : n3.end) == null || p2.call(n3, t6));
353
+ } });
354
+ }
355
+ }, [e, t6, r4, E2]), e ? [i4, { closed: s5(1), enter: s5(2), leave: s5(4), transition: s5(2) || s5(4) }] : [t6, { closed: void 0, enter: void 0, leave: void 0, transition: void 0 }];
356
+ }
357
+ function C2(e, { prepare: r4, run: t6, done: n3, inFlight: i4 }) {
358
+ let a2 = o2();
359
+ return j2(e, { prepare: r4, inFlight: i4 }), a2.nextFrame(() => {
360
+ t6(), a2.requestAnimationFrame(() => {
361
+ a2.add(M2(e, n3));
362
+ });
363
+ }), a2.dispose;
364
+ }
365
+ function M2(e, r4) {
366
+ var a2, s5;
367
+ let t6 = o2();
368
+ if (!e) return t6.dispose;
369
+ let n3 = false;
370
+ t6.add(() => {
371
+ n3 = true;
372
+ });
373
+ let i4 = (s5 = (a2 = e.getAnimations) == null ? void 0 : a2.call(e).filter((o5) => o5 instanceof CSSTransition)) != null ? s5 : [];
374
+ return i4.length === 0 ? (r4(), t6.dispose) : (Promise.allSettled(i4.map((o5) => o5.finished)).then(() => {
375
+ n3 || r4();
376
+ }), t6.dispose);
377
+ }
378
+ function j2(e, { inFlight: r4, prepare: t6 }) {
379
+ if (r4 != null && r4.current) {
380
+ t6();
381
+ return;
382
+ }
383
+ let n3 = e.style.transition;
384
+ e.style.transition = "none", t6(), e.offsetHeight, e.style.transition = n3;
385
+ }
386
+ function D2(e) {
387
+ var t6, n3;
388
+ return ((n3 = (t6 = e.getAnimations) == null ? void 0 : t6.call(e)) != null ? n3 : []).some((i4) => i4 instanceof CSSTransition && i4.playState !== "finished");
389
+ }
390
+
391
+ // ../../node_modules/@headlessui/react/dist/internal/open-closed.js
392
+ var import_react9 = __toESM(require("react"), 1);
393
+ var n2 = (0, import_react9.createContext)(null);
394
+ n2.displayName = "OpenClosedContext";
395
+ var i3 = ((e) => (e[e.Open = 1] = "Open", e[e.Closed = 2] = "Closed", e[e.Closing = 4] = "Closing", e[e.Opening = 8] = "Opening", e))(i3 || {});
396
+ function u3() {
397
+ return (0, import_react9.useContext)(n2);
398
+ }
399
+ function c4({ value: o5, children: t6 }) {
400
+ return import_react9.default.createElement(n2.Provider, { value: o5 }, t6);
401
+ }
402
+
403
+ // ../../node_modules/@headlessui/react/dist/hooks/use-server-handoff-complete.js
404
+ var t5 = __toESM(require("react"), 1);
405
+ function s4() {
406
+ let r4 = typeof document == "undefined";
407
+ return "useSyncExternalStore" in t5 ? ((o5) => o5.useSyncExternalStore)(t5)(() => () => {
408
+ }, () => false, () => !r4) : false;
409
+ }
410
+ function l3() {
411
+ let r4 = s4(), [e, n3] = t5.useState(s.isHandoffComplete);
412
+ return e && s.isHandoffComplete === false && n3(false), t5.useEffect(() => {
413
+ e !== true && n3(true);
414
+ }, [e]), t5.useEffect(() => s.handoff(), []), r4 ? false : e;
415
+ }
416
+
417
+ // ../../node_modules/@headlessui/react/dist/hooks/use-is-mounted.js
418
+ var import_react10 = require("react");
419
+ function f2() {
420
+ let e = (0, import_react10.useRef)(false);
421
+ return n(() => (e.current = true, () => {
422
+ e.current = false;
423
+ }), []), e;
424
+ }
425
+
426
+ // ../../node_modules/@headlessui/react/dist/components/transition/transition.js
427
+ var import_react11 = __toESM(require("react"), 1);
428
+ function ue(e) {
429
+ var t6;
430
+ return !!(e.enter || e.enterFrom || e.enterTo || e.leave || e.leaveFrom || e.leaveTo) || !b((t6 = e.as) != null ? t6 : de) || import_react11.default.Children.count(e.children) === 1;
431
+ }
432
+ var V = (0, import_react11.createContext)(null);
433
+ V.displayName = "TransitionContext";
434
+ var De = ((n3) => (n3.Visible = "visible", n3.Hidden = "hidden", n3))(De || {});
435
+ function He() {
436
+ let e = (0, import_react11.useContext)(V);
437
+ if (e === null) throw new Error("A <Transition.Child /> is used but it is missing a parent <Transition /> or <Transition.Root />.");
438
+ return e;
439
+ }
440
+ function Ae() {
441
+ let e = (0, import_react11.useContext)(w2);
442
+ if (e === null) throw new Error("A <Transition.Child /> is used but it is missing a parent <Transition /> or <Transition.Root />.");
443
+ return e;
444
+ }
445
+ var w2 = (0, import_react11.createContext)(null);
446
+ w2.displayName = "NestingContext";
447
+ function M3(e) {
448
+ return "children" in e ? M3(e.children) : e.current.filter(({ el: t6 }) => t6.current !== null).filter(({ state: t6 }) => t6 === "visible").length > 0;
449
+ }
450
+ function Te(e, t6) {
451
+ let n3 = s3(e), l4 = (0, import_react11.useRef)([]), S3 = f2(), R = p(), d3 = o4((o5, i4 = C.Hidden) => {
452
+ let a2 = l4.current.findIndex(({ el: s5 }) => s5 === o5);
453
+ a2 !== -1 && (u(i4, { [C.Unmount]() {
454
+ l4.current.splice(a2, 1);
455
+ }, [C.Hidden]() {
456
+ l4.current[a2].state = "hidden";
457
+ } }), R.microTask(() => {
458
+ var s5;
459
+ !M3(l4) && S3.current && ((s5 = n3.current) == null || s5.call(n3));
460
+ }));
461
+ }), y2 = o4((o5) => {
462
+ let i4 = l4.current.find(({ el: a2 }) => a2 === o5);
463
+ return i4 ? i4.state !== "visible" && (i4.state = "visible") : l4.current.push({ el: o5, state: "visible" }), () => d3(o5, C.Unmount);
464
+ }), C3 = (0, import_react11.useRef)([]), p2 = (0, import_react11.useRef)(Promise.resolve()), h2 = (0, import_react11.useRef)({ enter: [], leave: [] }), g = o4((o5, i4, a2) => {
465
+ C3.current.splice(0), t6 && (t6.chains.current[i4] = t6.chains.current[i4].filter(([s5]) => s5 !== o5)), t6 == null || t6.chains.current[i4].push([o5, new Promise((s5) => {
466
+ C3.current.push(s5);
467
+ })]), t6 == null || t6.chains.current[i4].push([o5, new Promise((s5) => {
468
+ Promise.all(h2.current[i4].map(([r4, f3]) => f3)).then(() => s5());
469
+ })]), i4 === "enter" ? p2.current = p2.current.then(() => t6 == null ? void 0 : t6.wait.current).then(() => a2(i4)) : a2(i4);
470
+ }), v2 = o4((o5, i4, a2) => {
471
+ Promise.all(h2.current[i4].splice(0).map(([s5, r4]) => r4)).then(() => {
472
+ var s5;
473
+ (s5 = C3.current.shift()) == null || s5();
474
+ }).then(() => a2(i4));
475
+ });
476
+ return (0, import_react11.useMemo)(() => ({ children: l4, register: y2, unregister: d3, onStart: g, onStop: v2, wait: p2, chains: h2 }), [y2, d3, l4, g, v2, h2, p2]);
477
+ }
478
+ var de = import_react11.Fragment;
479
+ var fe = A.RenderStrategy;
480
+ function Fe(e, t6) {
481
+ var ee, te;
482
+ let { transition: n3 = true, beforeEnter: l4, afterEnter: S3, beforeLeave: R, afterLeave: d3, enter: y2, enterFrom: C3, enterTo: p2, entered: h2, leave: g, leaveFrom: v2, leaveTo: o5, ...i4 } = e, [a2, s5] = (0, import_react11.useState)(null), r4 = (0, import_react11.useRef)(null), f3 = ue(e), U2 = y(...f3 ? [r4, t6, s5] : t6 === null ? [] : [t6]), H2 = (ee = i4.unmount) == null || ee ? C.Unmount : C.Hidden, { show: u4, appear: z, initial: K2 } = He(), [m2, j3] = (0, import_react11.useState)(u4 ? "visible" : "hidden"), Q = Ae(), { register: A3, unregister: F2 } = Q;
483
+ n(() => A3(r4), [A3, r4]), n(() => {
484
+ if (H2 === C.Hidden && r4.current) {
485
+ if (u4 && m2 !== "visible") {
486
+ j3("visible");
487
+ return;
488
+ }
489
+ return u(m2, { ["hidden"]: () => F2(r4), ["visible"]: () => A3(r4) });
490
+ }
491
+ }, [m2, r4, A3, F2, u4, H2]);
492
+ let G = l3();
493
+ n(() => {
494
+ if (f3 && G && m2 === "visible" && r4.current === null) throw new Error("Did you forget to passthrough the `ref` to the actual DOM node?");
495
+ }, [r4, m2, G, f3]);
496
+ let ce = K2 && !z, Y2 = z && u4 && K2, B = (0, import_react11.useRef)(false), I2 = Te(() => {
497
+ B.current || (j3("hidden"), F2(r4));
498
+ }, Q), Z = o4((W) => {
499
+ B.current = true;
500
+ let L = W ? "enter" : "leave";
501
+ I2.onStart(r4, L, (_) => {
502
+ _ === "enter" ? l4 == null || l4() : _ === "leave" && (R == null || R());
503
+ });
504
+ }), $2 = o4((W) => {
505
+ let L = W ? "enter" : "leave";
506
+ B.current = false, I2.onStop(r4, L, (_) => {
507
+ _ === "enter" ? S3 == null || S3() : _ === "leave" && (d3 == null || d3());
508
+ }), L === "leave" && !M3(I2) && (j3("hidden"), F2(r4));
509
+ });
510
+ (0, import_react11.useEffect)(() => {
511
+ f3 && n3 || (Z(u4), $2(u4));
512
+ }, [u4, f3, n3]);
513
+ let pe = /* @__PURE__ */ (() => !(!n3 || !f3 || !G || ce))(), [, T2] = N(pe, a2, u4, { start: Z, end: $2 }), Ce = m({ ref: U2, className: ((te = t3(i4.className, Y2 && y2, Y2 && C3, T2.enter && y2, T2.enter && T2.closed && C3, T2.enter && !T2.closed && p2, T2.leave && g, T2.leave && !T2.closed && v2, T2.leave && T2.closed && o5, !T2.transition && u4 && h2)) == null ? void 0 : te.trim()) || void 0, ...x2(T2) }), N2 = 0;
514
+ m2 === "visible" && (N2 |= i3.Open), m2 === "hidden" && (N2 |= i3.Closed), u4 && m2 === "hidden" && (N2 |= i3.Opening), !u4 && m2 === "visible" && (N2 |= i3.Closing);
515
+ let he = K();
516
+ return import_react11.default.createElement(w2.Provider, { value: I2 }, import_react11.default.createElement(c4, { value: N2 }, he({ ourProps: Ce, theirProps: i4, defaultTag: de, features: fe, visible: m2 === "visible", name: "Transition.Child" })));
517
+ }
518
+ function Ie(e, t6) {
519
+ let { show: n3, appear: l4 = false, unmount: S3 = true, ...R } = e, d3 = (0, import_react11.useRef)(null), y2 = ue(e), C3 = y(...y2 ? [d3, t6] : t6 === null ? [] : [t6]);
520
+ l3();
521
+ let p2 = u3();
522
+ if (n3 === void 0 && p2 !== null && (n3 = (p2 & i3.Open) === i3.Open), n3 === void 0) throw new Error("A <Transition /> is used but it is missing a `show={true | false}` prop.");
523
+ let [h2, g] = (0, import_react11.useState)(n3 ? "visible" : "hidden"), v2 = Te(() => {
524
+ n3 || g("hidden");
525
+ }), [o5, i4] = (0, import_react11.useState)(true), a2 = (0, import_react11.useRef)([n3]);
526
+ n(() => {
527
+ o5 !== false && a2.current[a2.current.length - 1] !== n3 && (a2.current.push(n3), i4(false));
528
+ }, [a2, n3]);
529
+ let s5 = (0, import_react11.useMemo)(() => ({ show: n3, appear: l4, initial: o5 }), [n3, l4, o5]);
530
+ n(() => {
531
+ n3 ? g("visible") : !M3(v2) && d3.current !== null && g("hidden");
532
+ }, [n3, v2]);
533
+ let r4 = { unmount: S3 }, f3 = o4(() => {
534
+ var u4;
535
+ o5 && i4(false), (u4 = e.beforeEnter) == null || u4.call(e);
536
+ }), U2 = o4(() => {
537
+ var u4;
538
+ o5 && i4(false), (u4 = e.beforeLeave) == null || u4.call(e);
539
+ }), H2 = K();
540
+ return import_react11.default.createElement(w2.Provider, { value: v2 }, import_react11.default.createElement(V.Provider, { value: s5 }, H2({ ourProps: { ...r4, as: import_react11.Fragment, children: import_react11.default.createElement(me, { ref: C3, ...r4, ...R, beforeEnter: f3, beforeLeave: U2 }) }, theirProps: {}, defaultTag: import_react11.Fragment, features: fe, visible: h2 === "visible", name: "Transition" })));
541
+ }
542
+ function Le(e, t6) {
543
+ let n3 = (0, import_react11.useContext)(V) !== null, l4 = u3() !== null;
544
+ return import_react11.default.createElement(import_react11.default.Fragment, null, !n3 && l4 ? import_react11.default.createElement(X, { ref: t6, ...e }) : import_react11.default.createElement(me, { ref: t6, ...e }));
545
+ }
546
+ var X = Y(Ie);
547
+ var me = Y(Fe);
548
+ var Oe = Y(Le);
549
+ var Ke = Object.assign(X, { Child: Oe, Root: X });
550
+
551
+ // src/components/CookieConsent.tsx
552
+ var import_hooks = require("@zorgo/next");
553
+ var import_jsx_runtime = require("react/jsx-runtime");
554
+ function CookieConsent() {
555
+ const { consentAnswered, setConsent } = (0, import_hooks.useCustomer)();
556
+ const [mounted, setMounted] = (0, import_react12.useState)(false);
557
+ (0, import_react12.useEffect)(() => {
558
+ setMounted(true);
559
+ }, []);
560
+ if (!mounted) return null;
561
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
562
+ Ke,
563
+ {
564
+ show: !consentAnswered,
565
+ enter: "transition-opacity duration-300",
566
+ enterFrom: "opacity-0",
567
+ enterTo: "opacity-100",
568
+ leave: "transition-opacity duration-200",
569
+ leaveFrom: "opacity-100",
570
+ leaveTo: "opacity-0",
571
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
572
+ "div",
573
+ {
574
+ className: "fixed inset-x-0 bottom-0 z-[9999] flex flex-col items-center justify-center gap-4 bg-black/85 px-6 py-4 text-center text-sm text-white backdrop-blur md:flex-row",
575
+ role: "alert",
576
+ "aria-live": "polite",
577
+ children: [
578
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "m-0", children: "We use cookies to improve your experience and collect anonymous usage data." }),
579
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex shrink-0 flex-wrap items-center justify-center gap-2", children: [
580
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
581
+ "button",
582
+ {
583
+ type: "button",
584
+ className: "whitespace-nowrap rounded-md px-4 py-2 text-sm font-medium text-zinc-500 hover:border-zinc-600 hover:bg-zinc-900 hover:text-zinc-400",
585
+ onClick: () => setConsent(false),
586
+ children: "Reject"
587
+ }
588
+ ),
589
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
590
+ "button",
591
+ {
592
+ type: "button",
593
+ className: "whitespace-nowrap rounded-md bg-white px-5 py-2 text-sm font-semibold text-black transition-colors hover:bg-gray-400",
594
+ onClick: () => setConsent(true),
595
+ children: "Accept"
596
+ }
597
+ )
598
+ ] })
599
+ ]
600
+ }
601
+ )
602
+ }
603
+ );
604
+ }
605
+
606
+ // src/components/Breadcrumbs.tsx
607
+ var import_link = __toESM(require("next/link"));
608
+ var import_lucide_react = require("lucide-react");
609
+ var import_jsx_runtime2 = require("react/jsx-runtime");
610
+ function cn(...parts) {
611
+ return parts.filter(Boolean).join(" ");
612
+ }
613
+ var BREADCRUMBS_DEFAULT_ITEM_CLASSES = {
614
+ baseContainer: "flex flex-row items-center gap-2 text-sm opacity-75",
615
+ crumbLink: "hover:opacity-75 transition-all duration-300 underline-offset-2 hover:underline",
616
+ crumbText: "font-semibold",
617
+ separator: "h-4 w-4 opacity-50"
618
+ };
619
+ function mergeBreadcrumbsItemClasses(overrides) {
620
+ const d3 = BREADCRUMBS_DEFAULT_ITEM_CLASSES;
621
+ return {
622
+ baseContainer: cn(d3.baseContainer, overrides?.baseContainer),
623
+ crumbLink: cn(d3.crumbLink, overrides?.crumbLink),
624
+ crumbText: cn(d3.crumbText, overrides?.crumbText),
625
+ separator: cn(d3.separator, overrides?.separator)
626
+ };
627
+ }
628
+ function Breadcrumbs({
629
+ items,
630
+ itemClasses
631
+ }) {
632
+ const slots = mergeBreadcrumbsItemClasses(itemClasses);
633
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("nav", { "aria-label": "Breadcrumb", className: slots.baseContainer, children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "flex flex-row items-center gap-2", children: [
634
+ index > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.ChevronRight, { className: slots.separator }),
635
+ item.href ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_link.default, { href: item.href, className: slots.crumbLink, children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: slots.crumbText, children: item.label })
636
+ ] }, `${item.label}-${index}`)) });
637
+ }
638
+
639
+ // src/components/GridMenu.tsx
640
+ var import_link2 = __toESM(require("next/link"));
641
+ var import_hooks2 = require("@zorgo/next");
642
+ var import_menuSlugs = require("@zorgo/next/slugs");
643
+ var import_jsx_runtime3 = require("react/jsx-runtime");
644
+ function cn2(...parts) {
645
+ return parts.filter(Boolean).join(" ");
646
+ }
647
+ function money(cents) {
648
+ return `$${(cents / 100).toFixed(2)}`;
649
+ }
650
+ var GRID_MENU_DEFAULT_ITEM_CLASSES = {
651
+ baseContainer: "flex flex-col gap-16",
652
+ categoryContainer: "flex flex-col gap-8",
653
+ categoryTitle: "text-4xl text-center font-extrabold text-primary",
654
+ itemCardContainer: "flex flex-row flex-wrap gap-8 content-center justify-center py-4 max-w-7xl mx-auto",
655
+ itemCard: "flex flex-col gap-4 no-underline w-60 hover:translate-y-[-2px] hover:opacity-75 transition-all duration-300",
656
+ itemCardImage: "w-full aspect-square bg-background-recessed rounded-2xl overflow-hidden",
657
+ itemCardTextContainer: "flex flex-col opacity-75 px-4 w-full",
658
+ itemCardName: "text-xl font-semibold",
659
+ itemCardPrice: "text-lg",
660
+ itemCardOldPrice: "text-lg line-through opacity-60"
661
+ };
662
+ function mergeGridMenuItemClasses(overrides) {
663
+ const d3 = GRID_MENU_DEFAULT_ITEM_CLASSES;
664
+ return {
665
+ baseContainer: cn2(d3.baseContainer, overrides?.baseContainer),
666
+ categoryContainer: cn2(
667
+ d3.categoryContainer,
668
+ overrides?.categoryContainer
669
+ ),
670
+ categoryTitle: cn2(d3.categoryTitle, overrides?.categoryTitle),
671
+ itemCardContainer: cn2(
672
+ d3.itemCardContainer,
673
+ overrides?.itemCardContainer
674
+ ),
675
+ itemCard: cn2(d3.itemCard, overrides?.itemCard),
676
+ itemCardImage: cn2(d3.itemCardImage, overrides?.itemCardImage),
677
+ itemCardTextContainer: cn2(
678
+ d3.itemCardTextContainer,
679
+ overrides?.itemCardTextContainer
680
+ ),
681
+ itemCardName: cn2(d3.itemCardName, overrides?.itemCardName),
682
+ itemCardPrice: cn2(d3.itemCardPrice, overrides?.itemCardPrice),
683
+ itemCardOldPrice: cn2(d3.itemCardOldPrice, overrides?.itemCardOldPrice)
684
+ };
685
+ }
686
+ function GridMenu({
687
+ items,
688
+ categories,
689
+ itemClasses
690
+ }) {
691
+ const { getItemImageUrl } = (0, import_hooks2.useMenu)();
692
+ const slots = mergeGridMenuItemClasses(itemClasses);
693
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: slots.baseContainer, children: categories.map((category) => {
694
+ const itemsInCategory = items.filter(
695
+ (item) => item.category_id === category.category_id
696
+ );
697
+ if (itemsInCategory.length === 0) {
698
+ return null;
699
+ }
700
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
701
+ "div",
702
+ {
703
+ className: slots.categoryContainer,
704
+ children: [
705
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { className: slots.categoryTitle, children: category.name }),
706
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: slots.itemCardContainer, children: itemsInCategory.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
707
+ ItemCard,
708
+ {
709
+ item,
710
+ imageUrl: getItemImageUrl(item.image_path),
711
+ slots
712
+ },
713
+ item.base_item_id
714
+ )) })
715
+ ]
716
+ },
717
+ category.category_id
718
+ );
719
+ }) });
720
+ }
721
+ function ItemCard({
722
+ item,
723
+ imageUrl,
724
+ slots
725
+ }) {
726
+ const variant = item.variants[0];
727
+ const onSale = variant?.display_price != null && variant.display_price < variant.price;
728
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
729
+ import_link2.default,
730
+ {
731
+ href: `/menu/${(0, import_menuSlugs.menuItemSlug)(item.name, item.base_item_id)}`,
732
+ className: slots.itemCard,
733
+ children: [
734
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: slots.itemCardImage, children: imageUrl && // eslint-disable-next-line @next/next/no-img-element
735
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
736
+ "img",
737
+ {
738
+ src: imageUrl,
739
+ alt: item.name,
740
+ className: "w-full h-full object-cover"
741
+ }
742
+ ) }),
743
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: slots.itemCardTextContainer, children: [
744
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: slots.itemCardName, children: item.name }),
745
+ variant && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: onSale ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
746
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: slots.itemCardPrice, children: money(variant.display_price) }),
747
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: slots.itemCardOldPrice, children: money(variant.price) })
748
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: slots.itemCardPrice, children: money(variant.price) }) })
749
+ ] })
750
+ ]
751
+ }
752
+ );
753
+ }
754
+
755
+ // src/components/AccordionMenu.tsx
756
+ var import_link3 = __toESM(require("next/link"));
757
+ var import_react14 = require("react");
758
+ var import_lucide_react2 = require("lucide-react");
759
+ var import_menuSlugs2 = require("@zorgo/next/slugs");
760
+ var import_jsx_runtime4 = require("react/jsx-runtime");
761
+ function cn3(...parts) {
762
+ return parts.filter(Boolean).join(" ");
763
+ }
764
+ function money2(cents) {
765
+ return `$${(cents / 100).toFixed(2)}`;
766
+ }
767
+ var ACCORDION_MENU_DEFAULT_ITEM_CLASSES = {
768
+ baseContainer: "flex flex-col gap-4",
769
+ categoryContainer: "flex flex-col gap-4 p-4 bg-background-elevated border-3 border-foreground/[15%] rounded-xl shadow-sm",
770
+ categoryTrigger: "flex flex-row items-center justify-between p-4",
771
+ categoryTitle: "text-2xl font-bold",
772
+ categoryIndicator: "h-8 w-8",
773
+ itemsContainer: "flex-col gap-4",
774
+ itemCard: "flex items-center justify-between gap-4 p-4 bg-background rounded-xl hover:translate-x-1 transition-all duration-300",
775
+ itemCardTextContainer: "flex flex-col gap-2 opacity-75",
776
+ itemCardName: "text-lg font-semibold",
777
+ itemCardDescription: "text-lg opacity-75",
778
+ itemCardPriceContainer: "flex flex-col gap-2 opacity-75",
779
+ itemCardPrice: "text-lg font-semibold",
780
+ itemCardOldPrice: "text-lg opacity-75 line-through"
781
+ };
782
+ function mergeAccordionMenuItemClasses(overrides) {
783
+ const d3 = ACCORDION_MENU_DEFAULT_ITEM_CLASSES;
784
+ return {
785
+ baseContainer: cn3(d3.baseContainer, overrides?.baseContainer),
786
+ categoryContainer: cn3(
787
+ d3.categoryContainer,
788
+ overrides?.categoryContainer
789
+ ),
790
+ categoryTrigger: cn3(d3.categoryTrigger, overrides?.categoryTrigger),
791
+ categoryTitle: cn3(d3.categoryTitle, overrides?.categoryTitle),
792
+ categoryIndicator: cn3(
793
+ d3.categoryIndicator,
794
+ overrides?.categoryIndicator
795
+ ),
796
+ itemsContainer: cn3(d3.itemsContainer, overrides?.itemsContainer),
797
+ itemCard: cn3(d3.itemCard, overrides?.itemCard),
798
+ itemCardTextContainer: cn3(
799
+ d3.itemCardTextContainer,
800
+ overrides?.itemCardTextContainer
801
+ ),
802
+ itemCardName: cn3(d3.itemCardName, overrides?.itemCardName),
803
+ itemCardDescription: cn3(
804
+ d3.itemCardDescription,
805
+ overrides?.itemCardDescription
806
+ ),
807
+ itemCardPriceContainer: cn3(
808
+ d3.itemCardPriceContainer,
809
+ overrides?.itemCardPriceContainer
810
+ ),
811
+ itemCardPrice: cn3(d3.itemCardPrice, overrides?.itemCardPrice),
812
+ itemCardOldPrice: cn3(d3.itemCardOldPrice, overrides?.itemCardOldPrice)
813
+ };
814
+ }
815
+ function AccordionMenu({
816
+ items,
817
+ categories,
818
+ itemClasses
819
+ }) {
820
+ const slots = mergeAccordionMenuItemClasses(itemClasses);
821
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: slots.baseContainer, children: categories.map((category) => {
822
+ const itemsInCategory = items.filter(
823
+ (item) => item.category_id === category.category_id
824
+ );
825
+ if (itemsInCategory.length === 0) {
826
+ return null;
827
+ }
828
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
829
+ MenuCategory,
830
+ {
831
+ category,
832
+ itemsInCategory,
833
+ slots
834
+ },
835
+ category.category_id
836
+ );
837
+ }) });
838
+ }
839
+ function MenuCategory({
840
+ category,
841
+ itemsInCategory,
842
+ slots
843
+ }) {
844
+ const [isExpanded, setIsExpanded] = (0, import_react14.useState)(false);
845
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: slots.categoryContainer, children: [
846
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
847
+ "button",
848
+ {
849
+ type: "button",
850
+ onClick: () => setIsExpanded(!isExpanded),
851
+ className: slots.categoryTrigger,
852
+ children: [
853
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: slots.categoryTitle, children: category.name }),
854
+ isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.ChevronUp, { className: slots.categoryIndicator }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.ChevronDown, { className: slots.categoryIndicator })
855
+ ]
856
+ }
857
+ ),
858
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
859
+ "div",
860
+ {
861
+ className: cn3(
862
+ isExpanded ? "flex" : "hidden",
863
+ slots.itemsContainer
864
+ ),
865
+ children: itemsInCategory.map((item) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
866
+ ItemCard2,
867
+ {
868
+ item,
869
+ slots
870
+ },
871
+ item.base_item_id
872
+ ))
873
+ }
874
+ )
875
+ ] });
876
+ }
877
+ function ItemCard2({
878
+ item,
879
+ slots
880
+ }) {
881
+ const variant = item.variants[0];
882
+ const onSale = variant?.display_price != null && variant.display_price < variant.price;
883
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
884
+ import_link3.default,
885
+ {
886
+ href: `/menu/${(0, import_menuSlugs2.menuItemSlug)(item.name, item.base_item_id)}`,
887
+ className: slots.itemCard,
888
+ children: [
889
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: slots.itemCardTextContainer, children: [
890
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: slots.itemCardName, children: item.name }),
891
+ item.description && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: slots.itemCardDescription, children: item.description })
892
+ ] }),
893
+ variant && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: slots.itemCardPriceContainer, children: onSale ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
894
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: slots.itemCardPrice, children: money2(variant.display_price) }),
895
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: slots.itemCardOldPrice, children: money2(variant.price) })
896
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: slots.itemCardPrice, children: money2(variant.price) }) })
897
+ ]
898
+ }
899
+ );
900
+ }
901
+
902
+ // src/components/ItemCustomizationForm.tsx
903
+ var import_lucide_react3 = require("lucide-react");
904
+ var import_hooks3 = require("@zorgo/next");
905
+ var import_jsx_runtime5 = require("react/jsx-runtime");
906
+ function cn4(...parts) {
907
+ return parts.filter(Boolean).join(" ");
908
+ }
909
+ function money3(cents) {
910
+ return `$${(cents / 100).toFixed(2)}`;
911
+ }
912
+ var ITEM_CUSTOMIZATION_FORM_DEFAULT_ITEM_CLASSES = {
913
+ baseContainer: "flex flex-col gap-8",
914
+ title: "text-4xl font-extrabold text-primary",
915
+ description: "opacity-70 text-xl",
916
+ section: "flex flex-col gap-2 shadow-sm rounded-xl p-4 bg-background-elevated border-3 border-foreground/[15%]",
917
+ sectionTitle: "font-bold text-2xl py-4",
918
+ optionsRow: "flex flex-row flex-wrap gap-2",
919
+ optionButton: "flex flex-col items-start gap-0.5 p-3 px-4 rounded-xl border-3 text-lg hover:translate-y-[-2px] transition-all duration-300",
920
+ optionButtonSelected: "bg-background-recessed border-transparent",
921
+ optionButtonUnselected: "bg-background-elevated border-foreground/[15%]",
922
+ optionButtonLabel: "font-semibold leading-tight",
923
+ optionButtonUpcharge: "opacity-60",
924
+ servingsRow: "flex flex-row items-center justify-between gap-4 text-xl",
925
+ servingsLabel: "opacity-75",
926
+ servingsControls: "flex flex-row items-center gap-2",
927
+ incrementButton: "bg-background text-foreground w-10 h-10 rounded-xl flex items-center justify-center hover:bg-foreground hover:text-background transition-all duration-300",
928
+ servingsValue: "w-8 md:w-12 font-semibold opacity-75 text-center",
929
+ ruleError: "text-sm text-red-500",
930
+ commentsTextarea: "p-4 rounded-xl border-3 border-foreground/[15%] outline-none resize-none",
931
+ quantityRow: "flex flex-row items-center gap-4 text-xl",
932
+ submitButton: "bg-primary text-primary-foreground p-4 rounded-xl text-lg font-semibold hover:bg-primary/80 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-300",
933
+ notFound: ""
934
+ };
935
+ function mergeItemCustomizationFormItemClasses(overrides) {
936
+ const d3 = ITEM_CUSTOMIZATION_FORM_DEFAULT_ITEM_CLASSES;
937
+ return {
938
+ baseContainer: cn4(d3.baseContainer, overrides?.baseContainer),
939
+ title: cn4(d3.title, overrides?.title),
940
+ description: cn4(d3.description, overrides?.description),
941
+ section: cn4(d3.section, overrides?.section),
942
+ sectionTitle: cn4(d3.sectionTitle, overrides?.sectionTitle),
943
+ optionsRow: cn4(d3.optionsRow, overrides?.optionsRow),
944
+ optionButton: cn4(d3.optionButton, overrides?.optionButton),
945
+ optionButtonSelected: cn4(
946
+ d3.optionButtonSelected,
947
+ overrides?.optionButtonSelected
948
+ ),
949
+ optionButtonUnselected: cn4(
950
+ d3.optionButtonUnselected,
951
+ overrides?.optionButtonUnselected
952
+ ),
953
+ optionButtonLabel: cn4(
954
+ d3.optionButtonLabel,
955
+ overrides?.optionButtonLabel
956
+ ),
957
+ optionButtonUpcharge: cn4(
958
+ d3.optionButtonUpcharge,
959
+ overrides?.optionButtonUpcharge
960
+ ),
961
+ servingsRow: cn4(d3.servingsRow, overrides?.servingsRow),
962
+ servingsLabel: cn4(d3.servingsLabel, overrides?.servingsLabel),
963
+ servingsControls: cn4(d3.servingsControls, overrides?.servingsControls),
964
+ incrementButton: cn4(d3.incrementButton, overrides?.incrementButton),
965
+ servingsValue: cn4(d3.servingsValue, overrides?.servingsValue),
966
+ ruleError: cn4(d3.ruleError, overrides?.ruleError),
967
+ commentsTextarea: cn4(d3.commentsTextarea, overrides?.commentsTextarea),
968
+ quantityRow: cn4(d3.quantityRow, overrides?.quantityRow),
969
+ submitButton: cn4(d3.submitButton, overrides?.submitButton),
970
+ notFound: cn4(d3.notFound, overrides?.notFound)
971
+ };
972
+ }
973
+ function ItemCustomizationForm({
974
+ baseItemId,
975
+ seed,
976
+ editIndex,
977
+ itemClasses,
978
+ onSubmitSuccess
979
+ }) {
980
+ const slots = mergeItemCustomizationFormItemClasses(itemClasses);
981
+ const {
982
+ item,
983
+ variant,
984
+ variants,
985
+ setVariant,
986
+ ruleGroups,
987
+ unmetRule,
988
+ canSubmit,
989
+ submit,
990
+ quantity,
991
+ setQuantity,
992
+ comments,
993
+ setComments,
994
+ setComponentServings,
995
+ price,
996
+ salePrice,
997
+ isEditMode,
998
+ draft
999
+ } = (0, import_hooks3.useItemCustomization)(baseItemId, seed, editIndex);
1000
+ const { categories } = (0, import_hooks3.useMenu)();
1001
+ if (!item) {
1002
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: slots.notFound, children: "Item not found." });
1003
+ }
1004
+ const category = categories.find(
1005
+ (c6) => c6.category_id === item.category_id
1006
+ );
1007
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.baseContainer, children: [
1008
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1009
+ Breadcrumbs,
1010
+ {
1011
+ items: [
1012
+ { label: "Menu", href: "/menu" },
1013
+ ...category ? [{ label: category.name }] : [],
1014
+ { label: item.name }
1015
+ ]
1016
+ }
1017
+ ),
1018
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h1", { className: slots.title, children: item.name }),
1019
+ item.description && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: slots.description, children: item.description }),
1020
+ variants.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.section, children: [
1021
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: slots.sectionTitle, children: "Variants" }),
1022
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: slots.optionsRow, children: variants.map((v2) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1023
+ OptionButton,
1024
+ {
1025
+ label: v2.name,
1026
+ subtext: money3(v2.price),
1027
+ selected: v2.item_id === variant.item_id,
1028
+ onClick: () => setVariant(v2),
1029
+ slots
1030
+ },
1031
+ v2.item_id
1032
+ )) })
1033
+ ] }),
1034
+ (variant.components?.length ?? 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.section, children: [
1035
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: slots.sectionTitle, children: "Includes" }),
1036
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: slots.optionsRow, children: variant.components.map((component) => {
1037
+ const defaultServings = component.servings_per_item ?? 1;
1038
+ const servings = draft?.components?.find(
1039
+ (c6) => c6.id === component.id
1040
+ )?.quantity_servings ?? defaultServings;
1041
+ const selected = servings > 0;
1042
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1043
+ OptionButton,
1044
+ {
1045
+ label: component.name,
1046
+ selected,
1047
+ onClick: () => setComponentServings(
1048
+ component.id,
1049
+ selected ? 0 : defaultServings
1050
+ ),
1051
+ slots
1052
+ },
1053
+ component.id
1054
+ );
1055
+ }) })
1056
+ ] }),
1057
+ ruleGroups.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.section, children: [
1058
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: slots.sectionTitle, children: rule.group_name }),
1059
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: slots.optionsRow, children: rule.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1060
+ OptionButton,
1061
+ {
1062
+ label: option.name,
1063
+ subtext: option.upcharge > 0 ? `+${money3(option.upcharge)}` : void 0,
1064
+ selected: option.selected,
1065
+ onClick: option.toggle,
1066
+ slots
1067
+ },
1068
+ option.key
1069
+ )) }),
1070
+ rule.message() && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: slots.ruleError, children: rule.message() })
1071
+ ] }, rule.rule_id)),
1072
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.section, children: [
1073
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: slots.sectionTitle, children: "Comments" }),
1074
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1075
+ "textarea",
1076
+ {
1077
+ value: comments,
1078
+ onChange: (e) => setComments(e.target.value),
1079
+ placeholder: "Special instructions...",
1080
+ className: slots.commentsTextarea,
1081
+ rows: 2
1082
+ }
1083
+ )
1084
+ ] }),
1085
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.section, children: [
1086
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: slots.sectionTitle, children: "How many?" }),
1087
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.quantityRow, children: [
1088
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1089
+ "button",
1090
+ {
1091
+ type: "button",
1092
+ className: slots.incrementButton,
1093
+ onClick: () => setQuantity((q2) => Math.max(1, q2 - 1)),
1094
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react3.Minus, { className: "h-4 w-4" })
1095
+ }
1096
+ ),
1097
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: slots.servingsValue, children: quantity }),
1098
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1099
+ "button",
1100
+ {
1101
+ type: "button",
1102
+ className: slots.incrementButton,
1103
+ onClick: () => setQuantity((q2) => q2 + 1),
1104
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react3.Plus, { className: "h-4 w-4" })
1105
+ }
1106
+ )
1107
+ ] })
1108
+ ] }),
1109
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1110
+ "button",
1111
+ {
1112
+ type: "button",
1113
+ disabled: !canSubmit,
1114
+ onClick: () => {
1115
+ submit();
1116
+ onSubmitSuccess?.();
1117
+ },
1118
+ className: slots.submitButton,
1119
+ children: unmetRule ? `Choose ${unmetRule.group_name}` : `${isEditMode ? "Save changes" : "Add to cart"} \u2014 ${money3(salePrice ?? price)}`
1120
+ }
1121
+ )
1122
+ ] });
1123
+ }
1124
+ function OptionButton({
1125
+ label,
1126
+ subtext,
1127
+ selected,
1128
+ onClick,
1129
+ slots
1130
+ }) {
1131
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1132
+ "button",
1133
+ {
1134
+ type: "button",
1135
+ onClick,
1136
+ className: cn4(
1137
+ slots.optionButton,
1138
+ selected ? slots.optionButtonSelected : slots.optionButtonUnselected
1139
+ ),
1140
+ children: [
1141
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: slots.optionButtonLabel, children: label }),
1142
+ subtext && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: slots.optionButtonUpcharge, children: subtext })
1143
+ ]
1144
+ }
1145
+ );
1146
+ }
1147
+
1148
+ // src/components/FindLocation.tsx
1149
+ var import_react15 = require("react");
1150
+ var import_lucide_react4 = require("lucide-react");
1151
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1152
+ function cn5(...parts) {
1153
+ return parts.filter(Boolean).join(" ");
1154
+ }
1155
+ function searchableText(location) {
1156
+ return `${location.name} ${location.address ?? ""}`.toLowerCase();
1157
+ }
1158
+ function matchRank(location, query) {
1159
+ const text = searchableText(location);
1160
+ const q2 = query.trim().toLowerCase();
1161
+ if (!q2) return 0;
1162
+ if (text.startsWith(q2) || location.name.toLowerCase().startsWith(q2)) {
1163
+ return 0;
1164
+ }
1165
+ if (text.includes(q2)) return 1;
1166
+ return 2;
1167
+ }
1168
+ function rankLocations(locations, query, pinnedLocationId) {
1169
+ const q2 = query.trim();
1170
+ const ranked = q2 ? [...locations].sort((a2, b5) => {
1171
+ const rankDiff = matchRank(a2, q2) - matchRank(b5, q2);
1172
+ if (rankDiff !== 0) return rankDiff;
1173
+ return a2.name.localeCompare(b5.name);
1174
+ }) : [...locations];
1175
+ if (pinnedLocationId == null) return ranked;
1176
+ const pinnedIndex = ranked.findIndex(
1177
+ (location) => location.location_id === pinnedLocationId
1178
+ );
1179
+ if (pinnedIndex <= 0) return ranked;
1180
+ const [pinned] = ranked.splice(pinnedIndex, 1);
1181
+ if (!pinned) return ranked;
1182
+ return [pinned, ...ranked];
1183
+ }
1184
+ var FIND_LOCATION_DEFAULT_ITEM_CLASSES = {
1185
+ baseContainer: "flex flex-col gap-6",
1186
+ searchContainer: "relative flex items-center",
1187
+ searchIcon: "absolute left-4 h-5 w-5 text-foreground opacity-50 pointer-events-none",
1188
+ searchInput: "w-full rounded-xl bg-background-recessed opacity-75 py-3 pl-12 pr-4 text-lg text-foreground placeholder:opacity-50 outline-none focus:opacity-100 transition-all duration-300",
1189
+ noMatchesMessage: "text-center opacity-75 text-sm",
1190
+ emptyMessage: "text-center opacity-75 py-8",
1191
+ list: "flex flex-col gap-3",
1192
+ locationRow: "flex items-center justify-between gap-4 p-4 rounded-xl border-3 border-foreground/[15%] shadow-sm hover:translate-x-1 transition-all duration-300 w-full",
1193
+ locationRowSelected: "bg-background-elevated",
1194
+ locationRowUnselected: "bg-background-recessed",
1195
+ locationButton: "flex flex-col gap-1 text-left flex-1 min-w-0",
1196
+ locationName: "text-lg font-semibold text-foreground",
1197
+ locationAddress: "text-base opacity-75 whitespace-pre-line",
1198
+ selectButton: "text-lg font-semibold px-4 py-3 rounded-xl bg-primary text-primary-foreground hover:opacity-75 transition-all duration-300 shrink-0"
1199
+ };
1200
+ function mergeFindLocationItemClasses(overrides) {
1201
+ const d3 = FIND_LOCATION_DEFAULT_ITEM_CLASSES;
1202
+ return {
1203
+ baseContainer: cn5(d3.baseContainer, overrides?.baseContainer),
1204
+ searchContainer: cn5(d3.searchContainer, overrides?.searchContainer),
1205
+ searchIcon: cn5(d3.searchIcon, overrides?.searchIcon),
1206
+ searchInput: cn5(d3.searchInput, overrides?.searchInput),
1207
+ noMatchesMessage: cn5(d3.noMatchesMessage, overrides?.noMatchesMessage),
1208
+ emptyMessage: cn5(d3.emptyMessage, overrides?.emptyMessage),
1209
+ list: cn5(d3.list, overrides?.list),
1210
+ locationRow: cn5(d3.locationRow, overrides?.locationRow),
1211
+ locationRowSelected: cn5(
1212
+ d3.locationRowSelected,
1213
+ overrides?.locationRowSelected
1214
+ ),
1215
+ locationRowUnselected: cn5(
1216
+ d3.locationRowUnselected,
1217
+ overrides?.locationRowUnselected
1218
+ ),
1219
+ locationButton: cn5(d3.locationButton, overrides?.locationButton),
1220
+ locationName: cn5(d3.locationName, overrides?.locationName),
1221
+ locationAddress: cn5(d3.locationAddress, overrides?.locationAddress),
1222
+ selectButton: cn5(d3.selectButton, overrides?.selectButton)
1223
+ };
1224
+ }
1225
+ function FindLocation({
1226
+ locations,
1227
+ initialSelected,
1228
+ onSelect,
1229
+ itemClasses
1230
+ }) {
1231
+ const [query, setQuery] = (0, import_react15.useState)("");
1232
+ const [selected, setSelected] = (0, import_react15.useState)(
1233
+ () => initialSelected ?? null
1234
+ );
1235
+ const slots = mergeFindLocationItemClasses(itemClasses);
1236
+ const pinnedLocationId = initialSelected?.location_id;
1237
+ const ranked = (0, import_react15.useMemo)(
1238
+ () => rankLocations(locations, query, pinnedLocationId),
1239
+ [locations, query, pinnedLocationId]
1240
+ );
1241
+ const trimmedQuery = query.trim();
1242
+ const noMatches = trimmedQuery.length > 0 && locations.every((location) => matchRank(location, trimmedQuery) === 2);
1243
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: slots.baseContainer, children: [
1244
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: slots.searchContainer, children: [
1245
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Search, { className: slots.searchIcon, strokeWidth: 2 }),
1246
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1247
+ "input",
1248
+ {
1249
+ type: "search",
1250
+ value: query,
1251
+ onChange: (e) => setQuery(e.target.value),
1252
+ placeholder: "Search by name or address",
1253
+ className: slots.searchInput,
1254
+ "aria-label": "Search locations"
1255
+ }
1256
+ )
1257
+ ] }),
1258
+ noMatches && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: slots.noMatchesMessage, children: [
1259
+ "No locations match \u201C",
1260
+ trimmedQuery,
1261
+ "\u201D. Showing all locations anyway."
1262
+ ] }),
1263
+ ranked.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: slots.emptyMessage, children: "No locations available." }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: slots.list, children: ranked.map((location) => {
1264
+ const isSelected = selected?.location_id === location.location_id;
1265
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1266
+ "li",
1267
+ {
1268
+ className: cn5(
1269
+ slots.locationRow,
1270
+ isSelected ? slots.locationRowSelected : slots.locationRowUnselected
1271
+ ),
1272
+ children: [
1273
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1274
+ "button",
1275
+ {
1276
+ type: "button",
1277
+ onClick: () => setSelected(location),
1278
+ "aria-pressed": isSelected,
1279
+ className: slots.locationButton,
1280
+ children: [
1281
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: slots.locationName, children: location.name }),
1282
+ location.address && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: slots.locationAddress, children: location.address })
1283
+ ]
1284
+ }
1285
+ ),
1286
+ isSelected && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1287
+ "button",
1288
+ {
1289
+ type: "button",
1290
+ onClick: () => onSelect(location),
1291
+ className: slots.selectButton,
1292
+ children: "Select"
1293
+ }
1294
+ )
1295
+ ]
1296
+ },
1297
+ location.location_id
1298
+ );
1299
+ }) })
1300
+ ] });
1301
+ }
1302
+
1303
+ // src/components/CheckoutForm.tsx
1304
+ var import_react16 = require("react");
1305
+ var import_link4 = __toESM(require("next/link"));
1306
+ var import_react_stripe_js = require("@stripe/react-stripe-js");
1307
+ var import_lucide_react5 = require("lucide-react");
1308
+ var import_hooks4 = require("@zorgo/next");
1309
+ var import_Form = require("@zorgo/next");
1310
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1311
+ function money4(cents) {
1312
+ return `$${(cents / 100).toFixed(2)}`;
1313
+ }
1314
+ function cn6(...parts) {
1315
+ return parts.filter(Boolean).join(" ");
1316
+ }
1317
+ var CHECKOUT_FORM_DEFAULT_ITEM_CLASSES = {
1318
+ shell: "",
1319
+ shellInner: "max-w-2xl mx-auto w-full flex flex-col gap-6",
1320
+ pageTitle: "text-4xl font-extrabold text-primary text-center mb-8",
1321
+ primaryButton: "text-lg font-semibold px-4 py-3 rounded-xl bg-primary text-primary-foreground hover:opacity-75 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed",
1322
+ secondaryButton: "text-lg font-semibold px-4 py-3 rounded-xl bg-background-recessed text-foreground border-3 border-foreground/[15%] hover:opacity-75 transition-all duration-300",
1323
+ incrementButton: "bg-background-recessed text-foreground w-10 h-10 rounded-xl flex items-center justify-center hover:bg-foreground hover:text-background transition-all duration-300",
1324
+ surface: "rounded-xl bg-background-elevated border-3 border-foreground/[15%] shadow-sm",
1325
+ fieldInput: "w-full bg-transparent outline-none text-lg font-semibold text-foreground placeholder:opacity-50",
1326
+ fieldContainer: "flex flex-col gap-1 w-full p-4 rounded-xl bg-background-elevated border-3 border-foreground/[15%]",
1327
+ fieldLabel: "text-xl opacity-50 text-foreground",
1328
+ fieldError: "text-xl text-red-500",
1329
+ statusPanel: "flex flex-col gap-6 items-center text-center p-8 w-full",
1330
+ statusTitle: "text-3xl font-semibold",
1331
+ statusMessage: "text-xl max-w-md opacity-60",
1332
+ statusMessageError: "text-xl max-w-md text-red-500",
1333
+ statusActions: "w-full max-w-sm flex flex-col gap-3",
1334
+ stepSection: "flex flex-col gap-6",
1335
+ sectionTitle: "text-3xl font-semibold mt-8",
1336
+ cartList: "flex flex-col gap-3",
1337
+ totals: "flex flex-col gap-2 p-4",
1338
+ totalsRow: "flex flex-row justify-between text-xl opacity-75",
1339
+ totalsDivider: "h-[2px] bg-foreground/20 rounded-xl w-full",
1340
+ totalsTotalRow: "flex flex-row justify-between text-2xl font-semibold pt-2",
1341
+ form: "flex flex-col gap-4 w-full",
1342
+ formActions: "flex flex-row items-center justify-between gap-3",
1343
+ submitError: "text-sm text-red-500",
1344
+ paymentSurface: "p-4",
1345
+ steps: "flex flex-row items-center gap-2 w-full",
1346
+ stepBadge: "w-10 h-10 rounded-full flex items-center justify-center text-xl font-semibold transition-all duration-300",
1347
+ stepBadgeActive: "bg-foreground text-background",
1348
+ stepBadgeInactive: "bg-background-recessed text-foreground opacity-60",
1349
+ stepLabel: "text-xl transition-all duration-300",
1350
+ stepLabelActive: "font-semibold",
1351
+ stepLabelInactive: "opacity-60",
1352
+ stepDivider: "flex-1 h-[2px] transition-all duration-300",
1353
+ stepDividerActive: "bg-foreground",
1354
+ stepDividerInactive: "bg-foreground/15",
1355
+ cartLine: "flex flex-row items-start justify-between gap-4 p-4 w-full",
1356
+ cartLineName: "text-xl font-semibold text-foreground",
1357
+ cartLineSelection: "text-lg opacity-50",
1358
+ cartLinePrice: "text-lg font-semibold opacity-75",
1359
+ cartLineControls: "flex flex-col flex-col-reverse md:flex-row items-center gap-3 shrink-0",
1360
+ cartLineQuantity: "w-8 text-xl font-semibold text-center",
1361
+ promoApplied: "flex flex-row items-center justify-between gap-4 p-4 w-full",
1362
+ promoAppliedLabel: "flex-1 text-lg font-semibold",
1363
+ promoRow: "flex flex-row gap-3",
1364
+ promoInput: "flex-1 rounded-xl bg-background-recessed border-3 border-transparent py-3 px-4 text-lg font-semibold text-foreground placeholder:opacity-50 outline-none focus:border-foreground/15 transition-all duration-300",
1365
+ promoError: "text-xl text-red-500"
1366
+ };
1367
+ function mergeCheckoutFormItemClasses(overrides) {
1368
+ const d3 = CHECKOUT_FORM_DEFAULT_ITEM_CLASSES;
1369
+ return {
1370
+ shell: cn6(d3.shell, overrides?.shell),
1371
+ shellInner: cn6(d3.shellInner, overrides?.shellInner),
1372
+ pageTitle: cn6(d3.pageTitle, overrides?.pageTitle),
1373
+ primaryButton: cn6(d3.primaryButton, overrides?.primaryButton),
1374
+ secondaryButton: cn6(d3.secondaryButton, overrides?.secondaryButton),
1375
+ incrementButton: cn6(d3.incrementButton, overrides?.incrementButton),
1376
+ surface: cn6(d3.surface, overrides?.surface),
1377
+ fieldInput: cn6(d3.fieldInput, overrides?.fieldInput),
1378
+ fieldContainer: cn6(d3.fieldContainer, overrides?.fieldContainer),
1379
+ fieldLabel: cn6(d3.fieldLabel, overrides?.fieldLabel),
1380
+ fieldError: cn6(d3.fieldError, overrides?.fieldError),
1381
+ statusPanel: cn6(d3.statusPanel, overrides?.statusPanel),
1382
+ statusTitle: cn6(d3.statusTitle, overrides?.statusTitle),
1383
+ statusMessage: cn6(d3.statusMessage, overrides?.statusMessage),
1384
+ statusMessageError: cn6(
1385
+ d3.statusMessageError,
1386
+ overrides?.statusMessageError
1387
+ ),
1388
+ statusActions: cn6(d3.statusActions, overrides?.statusActions),
1389
+ stepSection: cn6(d3.stepSection, overrides?.stepSection),
1390
+ sectionTitle: cn6(d3.sectionTitle, overrides?.sectionTitle),
1391
+ cartList: cn6(d3.cartList, overrides?.cartList),
1392
+ totals: cn6(d3.totals, overrides?.totals),
1393
+ totalsRow: cn6(d3.totalsRow, overrides?.totalsRow),
1394
+ totalsDivider: cn6(d3.totalsDivider, overrides?.totalsDivider),
1395
+ totalsTotalRow: cn6(d3.totalsTotalRow, overrides?.totalsTotalRow),
1396
+ form: cn6(d3.form, overrides?.form),
1397
+ formActions: cn6(d3.formActions, overrides?.formActions),
1398
+ submitError: cn6(d3.submitError, overrides?.submitError),
1399
+ paymentSurface: cn6(d3.paymentSurface, overrides?.paymentSurface),
1400
+ steps: cn6(d3.steps, overrides?.steps),
1401
+ stepBadge: cn6(d3.stepBadge, overrides?.stepBadge),
1402
+ stepBadgeActive: cn6(d3.stepBadgeActive, overrides?.stepBadgeActive),
1403
+ stepBadgeInactive: cn6(
1404
+ d3.stepBadgeInactive,
1405
+ overrides?.stepBadgeInactive
1406
+ ),
1407
+ stepLabel: cn6(d3.stepLabel, overrides?.stepLabel),
1408
+ stepLabelActive: cn6(d3.stepLabelActive, overrides?.stepLabelActive),
1409
+ stepLabelInactive: cn6(
1410
+ d3.stepLabelInactive,
1411
+ overrides?.stepLabelInactive
1412
+ ),
1413
+ stepDivider: cn6(d3.stepDivider, overrides?.stepDivider),
1414
+ stepDividerActive: cn6(
1415
+ d3.stepDividerActive,
1416
+ overrides?.stepDividerActive
1417
+ ),
1418
+ stepDividerInactive: cn6(
1419
+ d3.stepDividerInactive,
1420
+ overrides?.stepDividerInactive
1421
+ ),
1422
+ cartLine: cn6(d3.cartLine, overrides?.cartLine),
1423
+ cartLineName: cn6(d3.cartLineName, overrides?.cartLineName),
1424
+ cartLineSelection: cn6(
1425
+ d3.cartLineSelection,
1426
+ overrides?.cartLineSelection
1427
+ ),
1428
+ cartLinePrice: cn6(d3.cartLinePrice, overrides?.cartLinePrice),
1429
+ cartLineControls: cn6(d3.cartLineControls, overrides?.cartLineControls),
1430
+ cartLineQuantity: cn6(d3.cartLineQuantity, overrides?.cartLineQuantity),
1431
+ promoApplied: cn6(d3.promoApplied, overrides?.promoApplied),
1432
+ promoAppliedLabel: cn6(
1433
+ d3.promoAppliedLabel,
1434
+ overrides?.promoAppliedLabel
1435
+ ),
1436
+ promoRow: cn6(d3.promoRow, overrides?.promoRow),
1437
+ promoInput: cn6(d3.promoInput, overrides?.promoInput),
1438
+ promoError: cn6(d3.promoError, overrides?.promoError)
1439
+ };
1440
+ }
1441
+ function CheckoutForm({
1442
+ itemClasses,
1443
+ homeHref = "/",
1444
+ menuHref = "/menu",
1445
+ checkoutHref = "/checkout"
1446
+ }) {
1447
+ const slots = mergeCheckoutFormItemClasses(itemClasses);
1448
+ const {
1449
+ clientSecret,
1450
+ stripe,
1451
+ elementOptions,
1452
+ isReady,
1453
+ isLoading,
1454
+ error,
1455
+ getReturnStatus
1456
+ } = (0, import_hooks4.usePayment)();
1457
+ const { isEmpty, resetCart } = (0, import_hooks4.useCart)();
1458
+ const { currentLocation, needsLocationSelection } = (0, import_hooks4.useLocation)({
1459
+ promptLocationSelection: true
1460
+ });
1461
+ const { open } = (0, import_hooks4.useModal)();
1462
+ const [returnStatus, setReturnStatus] = (0, import_react16.useState)(null);
1463
+ (0, import_react16.useEffect)(() => {
1464
+ if (window.location.search.includes("redirect_status")) {
1465
+ const status = getReturnStatus(window.location.href);
1466
+ setReturnStatus(status);
1467
+ if (status.succeeded) resetCart();
1468
+ }
1469
+ }, []);
1470
+ if (returnStatus) {
1471
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, { slots, children: returnStatus.succeeded ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1472
+ StatusPanel,
1473
+ {
1474
+ slots,
1475
+ title: "You're all set",
1476
+ message: "Payment successful. Thank you!",
1477
+ action: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1478
+ import_link4.default,
1479
+ {
1480
+ href: homeHref,
1481
+ className: cn6(
1482
+ slots.primaryButton,
1483
+ "block w-full text-center"
1484
+ ),
1485
+ children: "Back home"
1486
+ }
1487
+ )
1488
+ }
1489
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1490
+ StatusPanel,
1491
+ {
1492
+ slots,
1493
+ title: "Payment didn't go through",
1494
+ message: returnStatus.error,
1495
+ tone: "error",
1496
+ action: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1497
+ import_link4.default,
1498
+ {
1499
+ href: checkoutHref,
1500
+ className: cn6(
1501
+ slots.primaryButton,
1502
+ "block w-full text-center"
1503
+ ),
1504
+ children: "Try again"
1505
+ }
1506
+ )
1507
+ }
1508
+ ) });
1509
+ }
1510
+ if (isEmpty && !isLoading && !clientSecret) {
1511
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1512
+ StatusPanel,
1513
+ {
1514
+ slots,
1515
+ title: "Your cart is empty",
1516
+ message: "Add something from the menu to get started.",
1517
+ action: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1518
+ import_link4.default,
1519
+ {
1520
+ href: menuHref,
1521
+ className: cn6(
1522
+ slots.primaryButton,
1523
+ "block w-full text-center"
1524
+ ),
1525
+ children: "Browse the menu"
1526
+ }
1527
+ )
1528
+ }
1529
+ ) });
1530
+ }
1531
+ if (error) {
1532
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1533
+ StatusPanel,
1534
+ {
1535
+ slots,
1536
+ title: "Something went wrong",
1537
+ message: error,
1538
+ tone: "error",
1539
+ action: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1540
+ import_link4.default,
1541
+ {
1542
+ href: menuHref,
1543
+ className: cn6(
1544
+ slots.primaryButton,
1545
+ "block w-full text-center"
1546
+ ),
1547
+ children: "Back to menu"
1548
+ }
1549
+ )
1550
+ }
1551
+ ) });
1552
+ }
1553
+ if (needsLocationSelection) {
1554
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1555
+ StatusPanel,
1556
+ {
1557
+ slots,
1558
+ title: "Choose a location",
1559
+ message: "Please choose a location to continue checkout.",
1560
+ action: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1561
+ "button",
1562
+ {
1563
+ type: "button",
1564
+ onClick: () => open("FIND_LOCATION_MODAL"),
1565
+ className: cn6(slots.primaryButton, "w-full"),
1566
+ children: "Select a location"
1567
+ }
1568
+ )
1569
+ }
1570
+ ) });
1571
+ }
1572
+ if (isReady && elementOptions) {
1573
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1574
+ import_react_stripe_js.Elements,
1575
+ {
1576
+ stripe,
1577
+ options: elementOptions,
1578
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PaymentStep, { slots, checkoutHref })
1579
+ },
1580
+ currentLocation?.stripe_account_id
1581
+ ) });
1582
+ }
1583
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DetailsStep, { slots }) });
1584
+ }
1585
+ function StatusPanel({
1586
+ title,
1587
+ message,
1588
+ action,
1589
+ tone = "default",
1590
+ slots
1591
+ }) {
1592
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn6(slots.statusPanel, slots.surface), children: [
1593
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h2", { className: slots.statusTitle, children: title }),
1594
+ message && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1595
+ "p",
1596
+ {
1597
+ className: tone === "error" ? slots.statusMessageError : slots.statusMessage,
1598
+ children: message
1599
+ }
1600
+ ),
1601
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: slots.statusActions, children: action })
1602
+ ] });
1603
+ }
1604
+ function DetailsStep({ slots }) {
1605
+ const {
1606
+ items,
1607
+ subtotal,
1608
+ discount,
1609
+ tax,
1610
+ serviceFee,
1611
+ total,
1612
+ removeItem,
1613
+ resetCart
1614
+ } = (0, import_hooks4.useCart)();
1615
+ const { customer, setCustomer } = (0, import_hooks4.useCustomer)();
1616
+ const { startCheckout } = (0, import_hooks4.usePayment)();
1617
+ const [submitError, setSubmitError] = (0, import_react16.useState)();
1618
+ const fieldContainerClass = slots.fieldContainer;
1619
+ const fieldStyleProps = {
1620
+ fieldClassName: slots.fieldInput,
1621
+ containerClassName: fieldContainerClass,
1622
+ fieldLabelClassName: slots.fieldLabel,
1623
+ fieldErrorClassName: slots.fieldError
1624
+ };
1625
+ const handleSubmit = async (values) => {
1626
+ const filledCustomer = {
1627
+ first_name: values.firstName,
1628
+ last_name: values.lastName,
1629
+ phone: values.phone,
1630
+ email: values.email,
1631
+ allow_marketing: values.marketingConsent
1632
+ };
1633
+ setCustomer(filledCustomer);
1634
+ try {
1635
+ await startCheckout();
1636
+ } catch (err) {
1637
+ setSubmitError(
1638
+ err instanceof Error ? err.message : "Could not start payment."
1639
+ );
1640
+ }
1641
+ };
1642
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.stepSection, children: [
1643
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Steps, { current: 1, slots }),
1644
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h2", { className: slots.sectionTitle, children: "Your order" }),
1645
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: slots.cartList, children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1646
+ CartLine,
1647
+ {
1648
+ item,
1649
+ index,
1650
+ onRemove: () => removeItem(index),
1651
+ slots
1652
+ },
1653
+ `${item.item_id}-${index}`
1654
+ )) }),
1655
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn6(slots.totals, slots.surface), children: [
1656
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.totalsRow, children: [
1657
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Subtotal" }),
1658
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: money4(subtotal) })
1659
+ ] }),
1660
+ discount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.totalsRow, children: [
1661
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Discount" }),
1662
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: money4(-discount) })
1663
+ ] }),
1664
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.totalsRow, children: [
1665
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Tax" }),
1666
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: money4(tax) })
1667
+ ] }),
1668
+ serviceFee > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.totalsRow, children: [
1669
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Service fee" }),
1670
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: serviceFee })
1671
+ ] }),
1672
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: slots.totalsDivider }),
1673
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.totalsTotalRow, children: [
1674
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Total" }),
1675
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: money4(total) })
1676
+ ] })
1677
+ ] }),
1678
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PromoCode, { slots }),
1679
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h2", { className: slots.sectionTitle, children: "Contact information" }),
1680
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_Form.DynamicFormShell, { onSubmit: handleSubmit, className: slots.form, children: [
1681
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1682
+ import_Form.NameFields,
1683
+ {
1684
+ firstNameInitialValue: customer.first_name ?? "",
1685
+ lastNameInitialValue: customer.last_name ?? "",
1686
+ fieldClassName: slots.fieldInput,
1687
+ fieldLabelClassName: slots.fieldLabel,
1688
+ fieldErrorClassName: slots.fieldError,
1689
+ childClassName: cn6(
1690
+ fieldContainerClass,
1691
+ "md:flex-1 md:min-w-0"
1692
+ )
1693
+ }
1694
+ ),
1695
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col w-full gap-1", children: [
1696
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1697
+ import_Form.PhoneField,
1698
+ {
1699
+ initialValue: customer.phone ?? "",
1700
+ showError: false,
1701
+ ...fieldStyleProps
1702
+ }
1703
+ ),
1704
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_Form.FieldError, { name: "phone", className: slots.fieldError })
1705
+ ] }),
1706
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col w-full gap-1", children: [
1707
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1708
+ import_Form.EmailField,
1709
+ {
1710
+ initialValue: customer.email ?? "",
1711
+ showError: false,
1712
+ ...fieldStyleProps
1713
+ }
1714
+ ),
1715
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_Form.FieldError, { name: "email", className: slots.fieldError })
1716
+ ] }),
1717
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1718
+ import_Form.CheckboxField,
1719
+ {
1720
+ fieldId: "termsAccepted",
1721
+ required: true,
1722
+ requiredText: "You must agree to the terms of service to continue.",
1723
+ fieldErrorClassName: slots.fieldError,
1724
+ children: "I have read and agree to the terms of service."
1725
+ }
1726
+ ),
1727
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_Form.CheckboxField, { fieldId: "marketingConsent", required: false, children: "I consent to receive promotions via text and email." }),
1728
+ submitError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: slots.submitError, children: submitError }),
1729
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.formActions, children: [
1730
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1731
+ "button",
1732
+ {
1733
+ type: "button",
1734
+ onClick: resetCart,
1735
+ className: slots.secondaryButton,
1736
+ children: "Clear cart"
1737
+ }
1738
+ ),
1739
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1740
+ import_Form.SubmitButton,
1741
+ {
1742
+ label: "Continue to payment",
1743
+ loadingLabel: "Setting up...",
1744
+ className: cn6("flex-1", slots.primaryButton)
1745
+ }
1746
+ )
1747
+ ] })
1748
+ ] })
1749
+ ] });
1750
+ }
1751
+ function PaymentStep({
1752
+ slots,
1753
+ checkoutHref
1754
+ }) {
1755
+ const stripe = (0, import_react_stripe_js.useStripe)();
1756
+ const elements = (0, import_react_stripe_js.useElements)();
1757
+ const {
1758
+ total,
1759
+ clientSecret,
1760
+ submitPayment,
1761
+ paymentElementOptions,
1762
+ getReturnUrl,
1763
+ resetCheckout
1764
+ } = (0, import_hooks4.usePayment)();
1765
+ const { customer } = (0, import_hooks4.useCustomer)();
1766
+ const [submitError, setSubmitError] = (0, import_react16.useState)();
1767
+ const handleSubmit = async () => {
1768
+ if (!stripe || !elements || !clientSecret) return;
1769
+ const { error } = await elements.submit();
1770
+ if (error) {
1771
+ setSubmitError(error.message ?? "Please check your card details.");
1772
+ throw error;
1773
+ }
1774
+ const returnUrl = `${getReturnUrl()}${checkoutHref.startsWith("/") ? checkoutHref : `/${checkoutHref}`}`;
1775
+ const result = await submitPayment(
1776
+ stripe,
1777
+ elements,
1778
+ clientSecret,
1779
+ returnUrl,
1780
+ customer
1781
+ );
1782
+ if (!result.success) setSubmitError(result.error);
1783
+ };
1784
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.stepSection, children: [
1785
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Steps, { current: 2, slots }),
1786
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_Form.DynamicFormShell, { onSubmit: handleSubmit, className: slots.form, children: [
1787
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cn6(slots.paymentSurface, slots.surface), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.PaymentElement, { options: paymentElementOptions }) }),
1788
+ submitError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: slots.submitError, children: submitError }),
1789
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.formActions, children: [
1790
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1791
+ "button",
1792
+ {
1793
+ type: "button",
1794
+ onClick: resetCheckout,
1795
+ className: slots.secondaryButton,
1796
+ children: "Back to order"
1797
+ }
1798
+ ),
1799
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1800
+ import_Form.SubmitButton,
1801
+ {
1802
+ label: `Pay ${money4(total ?? 0)}`,
1803
+ loadingLabel: "Processing...",
1804
+ className: cn6("flex-1", slots.primaryButton)
1805
+ }
1806
+ )
1807
+ ] })
1808
+ ] })
1809
+ ] });
1810
+ }
1811
+ function Steps({ current, slots }) {
1812
+ const labels = ["Your details", "Payment"];
1813
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: slots.steps, children: labels.map((label, i4) => {
1814
+ const n3 = i4 + 1;
1815
+ const active = n3 <= current;
1816
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "contents", children: [
1817
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
1818
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1819
+ "div",
1820
+ {
1821
+ className: cn6(
1822
+ slots.stepBadge,
1823
+ active ? slots.stepBadgeActive : slots.stepBadgeInactive
1824
+ ),
1825
+ children: n3
1826
+ }
1827
+ ),
1828
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1829
+ "p",
1830
+ {
1831
+ className: cn6(
1832
+ slots.stepLabel,
1833
+ active ? slots.stepLabelActive : slots.stepLabelInactive
1834
+ ),
1835
+ children: label
1836
+ }
1837
+ )
1838
+ ] }),
1839
+ i4 < labels.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1840
+ "div",
1841
+ {
1842
+ className: cn6(
1843
+ slots.stepDivider,
1844
+ current > n3 ? slots.stepDividerActive : slots.stepDividerInactive
1845
+ )
1846
+ }
1847
+ )
1848
+ ] }, label);
1849
+ }) });
1850
+ }
1851
+ function CartLine({
1852
+ item,
1853
+ index,
1854
+ onRemove,
1855
+ slots
1856
+ }) {
1857
+ const { open } = (0, import_hooks4.useModal)();
1858
+ const { updateItem, getItemTotal } = (0, import_hooks4.useCart)();
1859
+ const setQuantity = (next) => next < 1 ? onRemove() : updateItem({ ...item, quantity: next }, index);
1860
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn6(slots.cartLine, slots.surface), children: [
1861
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-1 flex-1 min-w-0", children: [
1862
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: slots.cartLineName, children: item.name }),
1863
+ (() => {
1864
+ const added = (item.selections ?? []).flatMap((rs) => rs.selections.map((s5) => s5.name));
1865
+ const removed = (item.components ?? []).filter((c6) => c6.quantity_servings === 0).map((c6) => c6.name);
1866
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1867
+ added.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: slots.cartLineSelection, children: [
1868
+ "Add ",
1869
+ added.join(", ")
1870
+ ] }),
1871
+ removed.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: slots.cartLineSelection, children: [
1872
+ "Remove ",
1873
+ removed.join(", ")
1874
+ ] }),
1875
+ item.comments && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: slots.cartLineSelection, children: [
1876
+ "Comments: ",
1877
+ item.comments
1878
+ ] })
1879
+ ] });
1880
+ })(),
1881
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: slots.cartLinePrice, children: money4(getItemTotal(item)) })
1882
+ ] }),
1883
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.cartLineControls, children: [
1884
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1885
+ "button",
1886
+ {
1887
+ type: "button",
1888
+ "aria-label": "Edit item",
1889
+ className: slots.incrementButton,
1890
+ onClick: () => open("EDIT_ITEM_MODAL", {
1891
+ baseItemId: item.base_item_id,
1892
+ seed: item,
1893
+ editIndex: index
1894
+ }),
1895
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.Pencil, { className: "w-5 h-5" })
1896
+ }
1897
+ ),
1898
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1899
+ "button",
1900
+ {
1901
+ type: "button",
1902
+ className: slots.incrementButton,
1903
+ onClick: () => setQuantity(item.quantity - 1),
1904
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.Minus, { className: "w-5 h-5" })
1905
+ }
1906
+ ),
1907
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: slots.cartLineQuantity, children: item.quantity }),
1908
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1909
+ "button",
1910
+ {
1911
+ type: "button",
1912
+ className: slots.incrementButton,
1913
+ onClick: () => setQuantity(item.quantity + 1),
1914
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.Plus, { className: "w-5 h-5" })
1915
+ }
1916
+ )
1917
+ ] })
1918
+ ] });
1919
+ }
1920
+ function PromoCode({ slots }) {
1921
+ const { promoCode, appliedPromo, applyPromo, removePromo, error, loading } = (0, import_hooks4.usePromotions)();
1922
+ const [draft, setDraft] = (0, import_react16.useState)("");
1923
+ if (appliedPromo) {
1924
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn6(slots.promoApplied, slots.surface), children: [
1925
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: slots.promoAppliedLabel, children: [
1926
+ appliedPromo.name,
1927
+ " applied"
1928
+ ] }),
1929
+ promoCode && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1930
+ "button",
1931
+ {
1932
+ type: "button",
1933
+ onClick: removePromo,
1934
+ className: slots.secondaryButton,
1935
+ children: "Remove"
1936
+ }
1937
+ )
1938
+ ] });
1939
+ }
1940
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-2 w-full", children: [
1941
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.promoRow, children: [
1942
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1943
+ "input",
1944
+ {
1945
+ value: draft,
1946
+ onChange: (e) => setDraft(e.target.value),
1947
+ placeholder: "Promo code",
1948
+ className: slots.promoInput
1949
+ }
1950
+ ),
1951
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1952
+ "button",
1953
+ {
1954
+ type: "button",
1955
+ disabled: loading || !draft.trim(),
1956
+ onClick: () => applyPromo(draft),
1957
+ className: cn6(slots.primaryButton, "shrink-0"),
1958
+ children: loading ? "Applying\u2026" : "Apply"
1959
+ }
1960
+ )
1961
+ ] }),
1962
+ error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: slots.promoError, children: error })
1963
+ ] });
1964
+ }
1965
+ function Shell({
1966
+ children,
1967
+ slots
1968
+ }) {
1969
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: slots.shell, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.shellInner, children: [
1970
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { className: slots.pageTitle, children: "Checkout" }),
1971
+ children
1972
+ ] }) });
1973
+ }
1974
+ // Annotate the CommonJS export names for ESM import in node:
1975
+ 0 && (module.exports = {
1976
+ ACCORDION_MENU_DEFAULT_ITEM_CLASSES,
1977
+ AccordionMenu,
1978
+ BREADCRUMBS_DEFAULT_ITEM_CLASSES,
1979
+ Breadcrumbs,
1980
+ CHECKOUT_FORM_DEFAULT_ITEM_CLASSES,
1981
+ CheckoutForm,
1982
+ CookieConsent,
1983
+ FIND_LOCATION_DEFAULT_ITEM_CLASSES,
1984
+ FindLocation,
1985
+ GRID_MENU_DEFAULT_ITEM_CLASSES,
1986
+ GridMenu,
1987
+ ITEM_CUSTOMIZATION_FORM_DEFAULT_ITEM_CLASSES,
1988
+ ItemCustomizationForm,
1989
+ mergeAccordionMenuItemClasses,
1990
+ mergeBreadcrumbsItemClasses,
1991
+ mergeCheckoutFormItemClasses,
1992
+ mergeFindLocationItemClasses,
1993
+ mergeGridMenuItemClasses,
1994
+ mergeItemCustomizationFormItemClasses
1995
+ });
1996
+ //# sourceMappingURL=components.js.map