restaurant-kit 0.1.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.
- package/LICENSE +21 -0
- package/README.md +488 -0
- package/dist/RestaurantSiteRoutes.js +23 -0
- package/dist/admin/AdminActionMenu.js +29 -0
- package/dist/admin/AdminAuthPanel.js +53 -0
- package/dist/admin/AdminBackupsDialog.js +54 -0
- package/dist/admin/AdminDraftProvider.js +10 -0
- package/dist/admin/AdminGroupsPanel.js +68 -0
- package/dist/admin/AdminItemDrawer.js +264 -0
- package/dist/admin/AdminMenuCard.js +63 -0
- package/dist/admin/AdminMenuEditor.module.css.js +209 -0
- package/dist/admin/AdminMenuGroupTabs.js +43 -0
- package/dist/admin/AdminMenuIconPicker.js +39 -0
- package/dist/admin/AdminRoutes.js +13 -0
- package/dist/admin/AdminSectionEditor.js +104 -0
- package/dist/admin/AdminTestimonialsPanel.js +214 -0
- package/dist/admin/AdminTestimonialsPanel.module.css.js +29 -0
- package/dist/admin/adminDraftContext.js +5 -0
- package/dist/admin/adminEditorUtils.js +47 -0
- package/dist/admin/adminMenuCommands.js +83 -0
- package/dist/admin/useAdminDraft.js +14 -0
- package/dist/admin/useAdminMenuDraft.js +226 -0
- package/dist/cart/CartDrawer.js +87 -0
- package/dist/cart/CartDrawer.module.css.js +47 -0
- package/dist/cart/CartProvider.js +31 -0
- package/dist/cart/cartContext.js +5 -0
- package/dist/cart/cartOrder.js +34 -0
- package/dist/cart/cartReducer.js +57 -0
- package/dist/cart/useCart.js +10 -0
- package/dist/components/Brand.js +16 -0
- package/dist/components/Brand.module.css.js +15 -0
- package/dist/components/Footer.js +19 -0
- package/dist/components/Footer.module.css.js +11 -0
- package/dist/components/Header.js +34 -0
- package/dist/components/Header.module.css.js +19 -0
- package/dist/components/Hero.js +23 -0
- package/dist/components/Hero.module.css.js +15 -0
- package/dist/components/InstagramIcon.js +27 -0
- package/dist/components/LocationsSection.js +34 -0
- package/dist/components/LocationsSection.module.css.js +17 -0
- package/dist/components/Marquee.js +10 -0
- package/dist/components/Marquee.module.css.js +9 -0
- package/dist/components/OrderIcon.js +11 -0
- package/dist/components/RatingSection.js +32 -0
- package/dist/components/RatingSection.module.css.js +19 -0
- package/dist/components/TestimonialsSection.js +73 -0
- package/dist/components/TestimonialsSection.module.css.js +37 -0
- package/dist/components/WhatsAppIcon.js +13 -0
- package/dist/config/RestaurantKitProvider.js +26 -0
- package/dist/config/siteConfigContext.js +23 -0
- package/dist/config/useOrdering.js +12 -0
- package/dist/index.js +92 -0
- package/dist/menu/localMenuApi.js +43 -0
- package/dist/menu/menuApi.js +121 -0
- package/dist/menu/menuDraftStorage.js +35 -0
- package/dist/menu/menuIcons.js +24 -0
- package/dist/menu/menuMutations.js +99 -0
- package/dist/menu/menuOrdering.js +94 -0
- package/dist/menu/menuSchema.js +4 -0
- package/dist/menu/priceFormat.js +39 -0
- package/dist/menu/useMenuData.js +38 -0
- package/dist/menu/validateMenu.js +63 -0
- package/dist/menu-browser/MenuBrowser.js +54 -0
- package/dist/menu-browser/MenuBrowser.module.css.js +153 -0
- package/dist/menu-browser/MenuCard.js +106 -0
- package/dist/menu-browser/MenuCartDrawer.js +18 -0
- package/dist/menu-browser/MenuCategoryBlock.js +45 -0
- package/dist/menu-browser/MenuItemSheet.js +132 -0
- package/dist/menu-browser/MenuLightbox.js +33 -0
- package/dist/menu-browser/MenuRow.js +43 -0
- package/dist/menu-browser/MenuSection.js +10 -0
- package/dist/menu-browser/menuItemDisplay.js +19 -0
- package/dist/menu-browser/useMediaQuery.js +19 -0
- package/dist/menu-browser/useMenuBrowserState.js +82 -0
- package/dist/menu-browser/useParkedSheet.js +32 -0
- package/dist/pages/AdminMenuEditor.js +291 -0
- package/dist/pages/AdminPreview.js +43 -0
- package/dist/pages/AdminPreview.module.css.js +9 -0
- package/dist/pages/MenuSite.js +40 -0
- package/dist/restaurant-kit.css +1 -0
- package/dist/testimonials/downscaleImage.js +14 -0
- package/dist/testimonials/testimonialMutations.js +52 -0
- package/dist/types/RestaurantSiteRoutes.d.ts +11 -0
- package/dist/types/admin/AdminActionMenu.d.ts +20 -0
- package/dist/types/admin/AdminAuthPanel.d.ts +13 -0
- package/dist/types/admin/AdminBackupsDialog.d.ts +9 -0
- package/dist/types/admin/AdminDraftProvider.d.ts +12 -0
- package/dist/types/admin/AdminGroupsPanel.d.ts +14 -0
- package/dist/types/admin/AdminItemDrawer.d.ts +16 -0
- package/dist/types/admin/AdminMenuCard.d.ts +10 -0
- package/dist/types/admin/AdminMenuGroupTabs.d.ts +11 -0
- package/dist/types/admin/AdminMenuIconPicker.d.ts +8 -0
- package/dist/types/admin/AdminRoutes.d.ts +5 -0
- package/dist/types/admin/AdminSectionEditor.d.ts +20 -0
- package/dist/types/admin/AdminTestimonialsPanel.d.ts +7 -0
- package/dist/types/admin/adminDraftContext.d.ts +2 -0
- package/dist/types/admin/adminEditorUtils.d.ts +22 -0
- package/dist/types/admin/adminMenuCommands.d.ts +73 -0
- package/dist/types/admin/useAdminDraft.d.ts +5 -0
- package/dist/types/admin/useAdminMenuDraft.d.ts +41 -0
- package/dist/types/cart/CartDrawer.d.ts +7 -0
- package/dist/types/cart/CartProvider.d.ts +4 -0
- package/dist/types/cart/cartContext.d.ts +2 -0
- package/dist/types/cart/cartOrder.d.ts +9 -0
- package/dist/types/cart/cartReducer.d.ts +36 -0
- package/dist/types/cart/cartTypes.d.ts +37 -0
- package/dist/types/cart/useCart.d.ts +1 -0
- package/dist/types/components/Brand.d.ts +5 -0
- package/dist/types/components/Footer.d.ts +1 -0
- package/dist/types/components/Header.d.ts +1 -0
- package/dist/types/components/Hero.d.ts +1 -0
- package/dist/types/components/InstagramIcon.d.ts +6 -0
- package/dist/types/components/LocationsSection.d.ts +1 -0
- package/dist/types/components/Marquee.d.ts +1 -0
- package/dist/types/components/OrderIcon.d.ts +4 -0
- package/dist/types/components/RatingSection.d.ts +1 -0
- package/dist/types/components/TestimonialsSection.d.ts +2 -0
- package/dist/types/components/WhatsAppIcon.d.ts +5 -0
- package/dist/types/config/RestaurantKitProvider.d.ts +24 -0
- package/dist/types/config/siteConfigContext.d.ts +28 -0
- package/dist/types/config/siteTypes.d.ts +50 -0
- package/dist/types/config/useOrdering.d.ts +16 -0
- package/dist/types/index.d.ts +38 -0
- package/dist/types/menu/localMenuApi.d.ts +9 -0
- package/dist/types/menu/menuApi.d.ts +68 -0
- package/dist/types/menu/menuDraftStorage.d.ts +5 -0
- package/dist/types/menu/menuIcons.d.ts +7 -0
- package/dist/types/menu/menuMutations.d.ts +13 -0
- package/dist/types/menu/menuOrdering.d.ts +38 -0
- package/dist/types/menu/menuSchema.d.ts +68 -0
- package/dist/types/menu/priceFormat.d.ts +8 -0
- package/dist/types/menu/useMenuData.d.ts +12 -0
- package/dist/types/menu/validateMenu.d.ts +16 -0
- package/dist/types/menu-browser/MenuBrowser.d.ts +6 -0
- package/dist/types/menu-browser/MenuCard.d.ts +7 -0
- package/dist/types/menu-browser/MenuCartDrawer.d.ts +5 -0
- package/dist/types/menu-browser/MenuCategoryBlock.d.ts +11 -0
- package/dist/types/menu-browser/MenuItemSheet.d.ts +10 -0
- package/dist/types/menu-browser/MenuLightbox.d.ts +9 -0
- package/dist/types/menu-browser/MenuRow.d.ts +7 -0
- package/dist/types/menu-browser/MenuSection.d.ts +1 -0
- package/dist/types/menu-browser/menuItemDisplay.d.ts +5 -0
- package/dist/types/menu-browser/useMediaQuery.d.ts +1 -0
- package/dist/types/menu-browser/useMenuBrowserState.d.ts +17 -0
- package/dist/types/menu-browser/useParkedSheet.d.ts +13 -0
- package/dist/types/pages/AdminMenuEditor.d.ts +1 -0
- package/dist/types/pages/AdminPreview.d.ts +1 -0
- package/dist/types/pages/MenuSite.d.ts +6 -0
- package/dist/types/testimonials/downscaleImage.d.ts +6 -0
- package/dist/types/testimonials/testimonialMutations.d.ts +9 -0
- package/dist/types/utils.d.ts +1 -0
- package/dist/types/worker/auth.d.ts +97 -0
- package/dist/types/worker/http.d.ts +17 -0
- package/dist/types/worker/index.d.ts +16 -0
- package/dist/types/worker/menuStorage.d.ts +94 -0
- package/dist/utils.js +6 -0
- package/dist/worker/auth.js +183 -0
- package/dist/worker/http.js +65 -0
- package/dist/worker/menuStorage.js +95 -0
- package/dist/worker.js +131 -0
- package/package.json +105 -0
- package/scripts/bootstrap-site.mjs +125 -0
- package/scripts/hash-admin-password.mjs +11 -0
- package/scripts/lib/password.mjs +72 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsxs as u, Fragment as c, jsx as i } from "react/jsx-runtime";
|
|
2
|
+
import { CartDrawer as p } from "../cart/CartDrawer.js";
|
|
3
|
+
import { useCart as f } from "../cart/useCart.js";
|
|
4
|
+
import { useMenuData as l } from "../menu/useMenuData.js";
|
|
5
|
+
import { MenuItemSheet as I } from "./MenuItemSheet.js";
|
|
6
|
+
import { useParkedSheet as C } from "./useParkedSheet.js";
|
|
7
|
+
function w() {
|
|
8
|
+
const { menu: o } = l(), { openCart: m, closeCart: n } = f(), { value: e, open: s, close: d } = C(m), r = e ? o.items.find((t) => t.id === e.itemId) : void 0;
|
|
9
|
+
return /* @__PURE__ */ u(c, { children: [
|
|
10
|
+
/* @__PURE__ */ i(p, { onEditItem: (t) => {
|
|
11
|
+
o.items.some((a) => a.id === t.itemId) && (n(), s(t));
|
|
12
|
+
} }),
|
|
13
|
+
e && r ? /* @__PURE__ */ i(I, { item: r, editLine: e, onClose: d }) : null
|
|
14
|
+
] });
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
w as MenuCartDrawer
|
|
18
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsxs as n, jsx as o } from "react/jsx-runtime";
|
|
2
|
+
import { ChevronDown as h } from "lucide-react";
|
|
3
|
+
import { cx as g } from "../utils.js";
|
|
4
|
+
import e from "./MenuBrowser.module.css.js";
|
|
5
|
+
import { MenuCard as f } from "./MenuCard.js";
|
|
6
|
+
import { MenuItemSheet as y } from "./MenuItemSheet.js";
|
|
7
|
+
import { MenuRow as C } from "./MenuRow.js";
|
|
8
|
+
import { useMediaQuery as x } from "./useMediaQuery.js";
|
|
9
|
+
import { useParkedSheet as N } from "./useParkedSheet.js";
|
|
10
|
+
function $({ category: t, groupId: m, groupLabel: s, isOpen: i, items: a, onToggle: p }) {
|
|
11
|
+
const l = x("(max-width: 560px)"), { value: c, open: d, close: u } = N();
|
|
12
|
+
return /* @__PURE__ */ n(
|
|
13
|
+
"section",
|
|
14
|
+
{
|
|
15
|
+
className: g(e.categoryBlock, i && e.openCategory),
|
|
16
|
+
"aria-labelledby": `menu-category-${t.id}`,
|
|
17
|
+
"data-menu-category-block": !0,
|
|
18
|
+
"data-menu-category": t.id,
|
|
19
|
+
"data-menu-group": m,
|
|
20
|
+
children: [
|
|
21
|
+
/* @__PURE__ */ n("button", { className: e.categoryHeading, type: "button", "aria-expanded": i, onClick: p, children: [
|
|
22
|
+
/* @__PURE__ */ n("div", { children: [
|
|
23
|
+
/* @__PURE__ */ o("p", { children: s }),
|
|
24
|
+
/* @__PURE__ */ o("h3", { id: `menu-category-${t.id}`, children: t.title })
|
|
25
|
+
] }),
|
|
26
|
+
/* @__PURE__ */ n("span", { className: e.toggleMeta, children: [
|
|
27
|
+
/* @__PURE__ */ n("span", { className: e.itemCount, children: [
|
|
28
|
+
a.length,
|
|
29
|
+
" ",
|
|
30
|
+
a.length === 1 ? "item" : "items"
|
|
31
|
+
] }),
|
|
32
|
+
/* @__PURE__ */ o(h, { "aria-hidden": "true", className: e.chevron })
|
|
33
|
+
] })
|
|
34
|
+
] }),
|
|
35
|
+
/* @__PURE__ */ o("div", { className: e.categoryContent, children: /* @__PURE__ */ o("div", { className: l ? e.rowList : e.grid, children: a.map(
|
|
36
|
+
(r) => l ? /* @__PURE__ */ o(C, { item: r, onOpen: () => d(r) }, r.id) : /* @__PURE__ */ o(f, { item: r, onOpen: () => d(r) }, r.id)
|
|
37
|
+
) }) }),
|
|
38
|
+
c ? /* @__PURE__ */ o(y, { item: c, onClose: u }) : null
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
$ as MenuCategoryBlock
|
|
45
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { jsxs as n, jsx as t, Fragment as j } from "react/jsx-runtime";
|
|
2
|
+
import { X as Q, Expand as K, Minus as U, Plus as X } from "lucide-react";
|
|
3
|
+
import { useState as c, useRef as R, useEffect as _ } from "react";
|
|
4
|
+
import { useCart as G } from "../cart/useCart.js";
|
|
5
|
+
import { OrderIcon as J } from "../components/OrderIcon.js";
|
|
6
|
+
import { useOrdering as W } from "../config/useOrdering.js";
|
|
7
|
+
import { formatPriceTotal as Y, formatPrice as q } from "../menu/priceFormat.js";
|
|
8
|
+
import { cx as N } from "../utils.js";
|
|
9
|
+
import a from "./MenuBrowser.module.css.js";
|
|
10
|
+
import { sortedSizes as Z, imageSrc as M, variationLabel as ee } from "./menuItemDisplay.js";
|
|
11
|
+
import { MenuLightbox as te } from "./MenuLightbox.js";
|
|
12
|
+
function me({ item: l, editLine: r, onClose: o }) {
|
|
13
|
+
const v = !!l.image, i = Z(l), m = l.removableIngredients ?? [], [g, L] = c(r?.variationId ?? i[0]?.id ?? ""), [d, I] = c(r?.quantity ?? 1), [p, P] = c(r?.note ?? ""), [b, T] = c(
|
|
14
|
+
(r?.removedIngredients ?? []).filter((e) => m.includes(e))
|
|
15
|
+
), f = i.find((e) => e.id === g) ?? i[0], k = f?.price ?? l.price, S = i.length > 1, { addItem: $, replaceItem: A, items: B, openCart: F } = G(), h = W(), { cartEnabled: u } = h, x = R(null), C = Y(k, d), O = B.filter((e) => e.itemId === l.id).reduce((e, s) => e + s.quantity, 0), [z, D] = c(!1), w = R(!1), E = (e) => {
|
|
16
|
+
w.current = e, D(e);
|
|
17
|
+
};
|
|
18
|
+
_(() => {
|
|
19
|
+
x.current?.focus();
|
|
20
|
+
const e = (y) => {
|
|
21
|
+
y.key === "Escape" && !w.current && o();
|
|
22
|
+
}, s = document.body.style.overflow;
|
|
23
|
+
return document.body.style.overflow = "hidden", document.addEventListener("keydown", e), () => {
|
|
24
|
+
document.body.style.overflow = s, document.removeEventListener("keydown", e);
|
|
25
|
+
};
|
|
26
|
+
}, [o]);
|
|
27
|
+
const H = (e) => {
|
|
28
|
+
T((s) => s.includes(e) ? s.filter((y) => y !== e) : [...s, e]);
|
|
29
|
+
}, V = () => {
|
|
30
|
+
const e = {
|
|
31
|
+
itemId: l.id,
|
|
32
|
+
itemName: l.title,
|
|
33
|
+
variationId: f?.id,
|
|
34
|
+
variationName: f?.label,
|
|
35
|
+
...b.length ? { removedIngredients: b } : {}
|
|
36
|
+
};
|
|
37
|
+
r ? A(r.key, e, { quantity: d, note: p }) : $(e, { quantity: d, note: p }), o();
|
|
38
|
+
};
|
|
39
|
+
return /* @__PURE__ */ n("div", { className: a.sheetLayer, role: "dialog", "aria-modal": "true", "aria-label": l.title, children: [
|
|
40
|
+
/* @__PURE__ */ t("div", { className: a.sheetVeil, onClick: o }),
|
|
41
|
+
/* @__PURE__ */ n("div", { className: a.sheet, children: [
|
|
42
|
+
/* @__PURE__ */ t("button", { className: a.sheetClose, type: "button", ref: x, onClick: o, "aria-label": "Close", children: /* @__PURE__ */ t(Q, { "aria-hidden": "true" }) }),
|
|
43
|
+
/* @__PURE__ */ n("div", { className: a.sheetScroll, children: [
|
|
44
|
+
v ? /* @__PURE__ */ n("button", { className: a.sheetHero, type: "button", onClick: () => E(!0), "aria-label": `View photo of ${l.title}`, children: [
|
|
45
|
+
/* @__PURE__ */ t("img", { src: M(l.image), alt: l.title }),
|
|
46
|
+
/* @__PURE__ */ t("span", { className: a.zoomHint, "aria-hidden": "true", children: /* @__PURE__ */ t(K, {}) })
|
|
47
|
+
] }) : null,
|
|
48
|
+
/* @__PURE__ */ n("div", { className: N(a.sheetBody, !v && a.plainSheetBody), children: [
|
|
49
|
+
/* @__PURE__ */ n("header", { className: a.sheetHeader, children: [
|
|
50
|
+
/* @__PURE__ */ t("h3", { children: l.title }),
|
|
51
|
+
S ? null : /* @__PURE__ */ t("span", { className: a.price, children: q(k) || "M.P." })
|
|
52
|
+
] }),
|
|
53
|
+
l.description ? /* @__PURE__ */ t("p", { className: a.sheetDesc, children: l.description }) : null,
|
|
54
|
+
u && O && !r ? /* @__PURE__ */ n("p", { className: a.sheetInCart, children: [
|
|
55
|
+
"In your cart: ",
|
|
56
|
+
O,
|
|
57
|
+
" — this adds another.",
|
|
58
|
+
" ",
|
|
59
|
+
/* @__PURE__ */ t(
|
|
60
|
+
"button",
|
|
61
|
+
{
|
|
62
|
+
type: "button",
|
|
63
|
+
onClick: () => {
|
|
64
|
+
o(), F();
|
|
65
|
+
},
|
|
66
|
+
children: "Edit cart"
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
] }) : null,
|
|
70
|
+
S ? /* @__PURE__ */ t("div", { className: a.variationTabs, "aria-label": `${l.title} size`, children: i.map((e) => {
|
|
71
|
+
const s = e.id === g;
|
|
72
|
+
return /* @__PURE__ */ n(
|
|
73
|
+
"button",
|
|
74
|
+
{
|
|
75
|
+
className: N(a.variationTab, s && a.selectedVariationTab),
|
|
76
|
+
type: "button",
|
|
77
|
+
"aria-pressed": s,
|
|
78
|
+
onClick: () => L(e.id),
|
|
79
|
+
children: [
|
|
80
|
+
/* @__PURE__ */ t("span", { children: ee(e) }),
|
|
81
|
+
/* @__PURE__ */ t("strong", { children: q(e.price) })
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
e.id
|
|
85
|
+
);
|
|
86
|
+
}) }) : null,
|
|
87
|
+
u && m.length ? /* @__PURE__ */ n("fieldset", { className: a.sheetRemovables, children: [
|
|
88
|
+
/* @__PURE__ */ t("legend", { className: a.sheetNoteLabel, children: "Remove ingredients" }),
|
|
89
|
+
m.map((e) => /* @__PURE__ */ n("label", { className: a.sheetRemovable, children: [
|
|
90
|
+
/* @__PURE__ */ t("span", { children: e }),
|
|
91
|
+
/* @__PURE__ */ t("input", { type: "checkbox", checked: b.includes(e), onChange: () => H(e) })
|
|
92
|
+
] }, e))
|
|
93
|
+
] }) : null,
|
|
94
|
+
u ? /* @__PURE__ */ n(j, { children: [
|
|
95
|
+
/* @__PURE__ */ t("label", { className: a.sheetNoteLabel, htmlFor: `sheet-note-${l.id}`, children: "Special instructions" }),
|
|
96
|
+
/* @__PURE__ */ t(
|
|
97
|
+
"textarea",
|
|
98
|
+
{
|
|
99
|
+
className: a.sheetNote,
|
|
100
|
+
id: `sheet-note-${l.id}`,
|
|
101
|
+
value: p,
|
|
102
|
+
onChange: (e) => P(e.target.value),
|
|
103
|
+
placeholder: "e.g. no pickles, sauce on the side…"
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
] }) : null
|
|
107
|
+
] })
|
|
108
|
+
] }),
|
|
109
|
+
u ? /* @__PURE__ */ n("footer", { className: a.sheetFooter, children: [
|
|
110
|
+
/* @__PURE__ */ n("div", { className: a.sheetStepper, "aria-label": `${l.title} quantity`, children: [
|
|
111
|
+
/* @__PURE__ */ t("button", { type: "button", onClick: () => I((e) => Math.max(1, e - 1)), "aria-label": "Decrease quantity", children: /* @__PURE__ */ t(U, { "aria-hidden": "true" }) }),
|
|
112
|
+
/* @__PURE__ */ t("span", { children: d }),
|
|
113
|
+
/* @__PURE__ */ t("button", { type: "button", onClick: () => I((e) => e + 1), "aria-label": "Increase quantity", children: /* @__PURE__ */ t(X, { "aria-hidden": "true" }) })
|
|
114
|
+
] }),
|
|
115
|
+
/* @__PURE__ */ n("button", { className: a.sheetAdd, type: "button", onClick: V, children: [
|
|
116
|
+
/* @__PURE__ */ t("span", { children: r ? "Update cart" : "Add to cart" }),
|
|
117
|
+
C ? /* @__PURE__ */ t("span", { className: a.sheetTotal, children: C }) : null
|
|
118
|
+
] })
|
|
119
|
+
] }) : h.href ? (
|
|
120
|
+
// Browse-only menu: the sheet is a detail view and hands off to the ordering app.
|
|
121
|
+
/* @__PURE__ */ t("footer", { className: a.sheetFooter, children: /* @__PURE__ */ n("a", { className: N(a.sheetAdd, a.sheetOrderLink), href: h.href, target: "_blank", rel: "noreferrer", children: [
|
|
122
|
+
/* @__PURE__ */ t("span", { children: h.label }),
|
|
123
|
+
/* @__PURE__ */ t(J, { className: a.sheetOrderIcon })
|
|
124
|
+
] }) })
|
|
125
|
+
) : null
|
|
126
|
+
] }),
|
|
127
|
+
z ? /* @__PURE__ */ t(te, { alt: l.title, imageSrc: M(l.image), onClose: () => E(!1) }) : null
|
|
128
|
+
] });
|
|
129
|
+
}
|
|
130
|
+
export {
|
|
131
|
+
me as MenuItemSheet
|
|
132
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsxs as d, jsx as t } from "react/jsx-runtime";
|
|
2
|
+
import { X as m } from "lucide-react";
|
|
3
|
+
import { useRef as f, useEffect as b } from "react";
|
|
4
|
+
import r from "./MenuBrowser.module.css.js";
|
|
5
|
+
function v({ addLabel: n, alt: l, imageSrc: c, onAdd: i, onClose: e }) {
|
|
6
|
+
const s = f(null);
|
|
7
|
+
return b(() => {
|
|
8
|
+
s.current?.focus();
|
|
9
|
+
const o = (u) => {
|
|
10
|
+
u.key === "Escape" && e();
|
|
11
|
+
}, a = document.body.style.overflow;
|
|
12
|
+
return document.body.style.overflow = "hidden", document.addEventListener("keydown", o), () => {
|
|
13
|
+
document.body.style.overflow = a, document.removeEventListener("keydown", o);
|
|
14
|
+
};
|
|
15
|
+
}, [e]), /* @__PURE__ */ d("div", { className: r.lightbox, role: "dialog", "aria-modal": "true", "aria-label": l, onClick: e, children: [
|
|
16
|
+
/* @__PURE__ */ t("button", { className: r.lightboxClose, type: "button", ref: s, onClick: e, "aria-label": "Close photo", children: /* @__PURE__ */ t(m, { "aria-hidden": "true" }) }),
|
|
17
|
+
/* @__PURE__ */ t("img", { className: r.lightboxImage, src: c, alt: l }),
|
|
18
|
+
n && i ? /* @__PURE__ */ t(
|
|
19
|
+
"button",
|
|
20
|
+
{
|
|
21
|
+
className: r.lightboxAdd,
|
|
22
|
+
type: "button",
|
|
23
|
+
onClick: (o) => {
|
|
24
|
+
o.stopPropagation(), i();
|
|
25
|
+
},
|
|
26
|
+
children: n
|
|
27
|
+
}
|
|
28
|
+
) : null
|
|
29
|
+
] });
|
|
30
|
+
}
|
|
31
|
+
export {
|
|
32
|
+
v as MenuLightbox
|
|
33
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsxs as i, jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import { Plus as w } from "lucide-react";
|
|
3
|
+
import { useCart as b } from "../cart/useCart.js";
|
|
4
|
+
import { useOrdering as N } from "../config/useOrdering.js";
|
|
5
|
+
import { cx as f } from "../utils.js";
|
|
6
|
+
import e from "./MenuBrowser.module.css.js";
|
|
7
|
+
import { sortedSizes as g, variationLabel as y, imageSrc as I } from "./menuItemDisplay.js";
|
|
8
|
+
import { formatPrice as x } from "../menu/priceFormat.js";
|
|
9
|
+
function A({ item: a, onOpen: s }) {
|
|
10
|
+
const l = !!a.image, t = g(a), n = t[0], m = n?.price ?? a.price, { addItem: u, items: p } = b(), { cartEnabled: c } = N(), d = p.filter((o) => o.itemId === a.id).reduce((o, h) => o + h.quantity, 0);
|
|
11
|
+
return /* @__PURE__ */ i("article", { className: e.row, children: [
|
|
12
|
+
/* @__PURE__ */ r("button", { className: e.rowMain, type: "button", onClick: s, children: /* @__PURE__ */ i("span", { className: e.rowText, children: [
|
|
13
|
+
/* @__PURE__ */ r("span", { className: e.rowTitle, children: a.title }),
|
|
14
|
+
a.description ? /* @__PURE__ */ r("span", { className: e.rowDesc, children: a.description }) : null,
|
|
15
|
+
/* @__PURE__ */ i("span", { className: e.rowPrice, children: [
|
|
16
|
+
x(m) || "M.P.",
|
|
17
|
+
t.length > 1 ? /* @__PURE__ */ i("span", { className: e.rowSizeHint, children: [
|
|
18
|
+
" · ",
|
|
19
|
+
t.map(y).join(" / ")
|
|
20
|
+
] }) : null
|
|
21
|
+
] })
|
|
22
|
+
] }) }),
|
|
23
|
+
l || c ? /* @__PURE__ */ i("div", { className: e.rowMediaCell, children: [
|
|
24
|
+
l ? /* @__PURE__ */ r("button", { className: e.rowThumb, type: "button", onClick: s, tabIndex: -1, "aria-label": `View ${a.title}`, children: /* @__PURE__ */ r("img", { src: I(a.image), alt: "", loading: "lazy" }) }) : null,
|
|
25
|
+
c ? /* @__PURE__ */ i(
|
|
26
|
+
"button",
|
|
27
|
+
{
|
|
28
|
+
className: f(e.rowAdd, !l && e.rowAddInline),
|
|
29
|
+
type: "button",
|
|
30
|
+
onClick: () => u({ itemId: a.id, itemName: a.title, variationId: n?.id, variationName: n?.label }),
|
|
31
|
+
"aria-label": `Add ${a.title} to cart`,
|
|
32
|
+
children: [
|
|
33
|
+
/* @__PURE__ */ r(w, { "aria-hidden": "true" }),
|
|
34
|
+
d ? /* @__PURE__ */ r("span", { className: e.rowQty, children: d }) : null
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
) : null
|
|
38
|
+
] }) : null
|
|
39
|
+
] });
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
A as MenuRow
|
|
43
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import { useMenuData as e } from "../menu/useMenuData.js";
|
|
3
|
+
import { MenuBrowser as n } from "./MenuBrowser.js";
|
|
4
|
+
function i() {
|
|
5
|
+
const { menu: o } = e();
|
|
6
|
+
return /* @__PURE__ */ r(n, { menu: o });
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
i as MenuSection
|
|
10
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { sortByOrder as e } from "../menu/menuOrdering.js";
|
|
2
|
+
import { formatPrice as i } from "../menu/priceFormat.js";
|
|
3
|
+
function l(r) {
|
|
4
|
+
const t = r.label.trim().toLowerCase();
|
|
5
|
+
return t === "small" ? "S" : t === "medium" ? "M" : t === "large" ? "L" : r.label.trim() || i(r.price);
|
|
6
|
+
}
|
|
7
|
+
function u(r) {
|
|
8
|
+
return e(r.sizes.filter((t) => t.label.trim() && t.price));
|
|
9
|
+
}
|
|
10
|
+
const n = /^(https?:|data:|blob:)/i;
|
|
11
|
+
function f(r) {
|
|
12
|
+
return r ? r.startsWith("/") || n.test(r) ? r : `/${r}` : "";
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
i as formatPrice,
|
|
16
|
+
f as imageSrc,
|
|
17
|
+
u as sortedSizes,
|
|
18
|
+
l as variationLabel
|
|
19
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useCallback as r, useSyncExternalStore as c } from "react";
|
|
2
|
+
function i() {
|
|
3
|
+
return typeof window < "u" && typeof window.matchMedia == "function";
|
|
4
|
+
}
|
|
5
|
+
function d(e) {
|
|
6
|
+
const a = r(
|
|
7
|
+
(n) => {
|
|
8
|
+
if (!i()) return () => {
|
|
9
|
+
};
|
|
10
|
+
const t = window.matchMedia(e);
|
|
11
|
+
return t.addEventListener("change", n), () => t.removeEventListener("change", n);
|
|
12
|
+
},
|
|
13
|
+
[e]
|
|
14
|
+
);
|
|
15
|
+
return c(a, () => i() ? window.matchMedia(e).matches : !1);
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
d as useMediaQuery
|
|
19
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { useState as R, useRef as s, useMemo as u, useEffect as k, useCallback as g } from "react";
|
|
2
|
+
import { getOrderedMenu as W } from "../menu/menuOrdering.js";
|
|
3
|
+
function P(B) {
|
|
4
|
+
const [b, h] = R("all"), [E, C] = R([]), [x, G] = R(!1), c = s(/* @__PURE__ */ new Set()), v = s(!1), r = s(null), S = s(null), a = s(null), l = s(null), d = u(() => W(B, { includeHidden: !1, includeEmptySections: !1 }), [B]), M = u(() => d.groups.map(({ group: e }) => e), [d]), A = u(() => new Map(M.map((e) => [e.id, e.label])), [M]), T = u(() => d.sections.map(({ section: e, items: t }) => ({ category: e, items: t })), [d.sections]), m = u(() => T.map(({ category: e }) => e.id), [T]), f = m[0] ?? "";
|
|
5
|
+
k(() => {
|
|
6
|
+
C((e) => {
|
|
7
|
+
const t = new Set(m), n = e.filter((o) => t.has(o)), i = m.filter((o) => !n.includes(o) && !c.current.has(o));
|
|
8
|
+
return [...n, ...i];
|
|
9
|
+
});
|
|
10
|
+
}, [m]), k(() => {
|
|
11
|
+
const e = l.current?.querySelector(`[data-group="${b}"]`);
|
|
12
|
+
if (!e || !l.current) return;
|
|
13
|
+
const t = e.offsetLeft - l.current.clientWidth / 2 + e.clientWidth / 2;
|
|
14
|
+
l.current.scrollTo({ left: Math.max(0, t), behavior: "smooth" });
|
|
15
|
+
}, [b]);
|
|
16
|
+
const p = g((e, t = {}) => {
|
|
17
|
+
if (e) {
|
|
18
|
+
if (t.force) c.current.delete(e);
|
|
19
|
+
else if (c.current.has(e)) return;
|
|
20
|
+
C((n) => n.includes(e) ? n : [...n, e]);
|
|
21
|
+
}
|
|
22
|
+
}, []), F = g((e) => {
|
|
23
|
+
C((t) => t.includes(e) ? (c.current.add(e), t.filter((n) => n !== e)) : (c.current.delete(e), [...t, e]));
|
|
24
|
+
}, []), w = g(() => {
|
|
25
|
+
if (v.current) return;
|
|
26
|
+
const e = Array.from(S.current?.querySelectorAll("[data-menu-category-block]") ?? []);
|
|
27
|
+
if (!e.length) return;
|
|
28
|
+
const n = (a.current?.getBoundingClientRect()?.bottom ?? 0) + 56;
|
|
29
|
+
let i = e[0];
|
|
30
|
+
if (e[0].getBoundingClientRect().top > n) {
|
|
31
|
+
h("all");
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
for (const o of e)
|
|
35
|
+
o.getBoundingClientRect().top <= n && (i = o);
|
|
36
|
+
h(i.dataset.menuGroup ?? "all"), p(i.dataset.menuCategory ?? f);
|
|
37
|
+
}, [f, p]);
|
|
38
|
+
k(() => {
|
|
39
|
+
const e = () => {
|
|
40
|
+
const t = window.matchMedia("(max-width: 980px)").matches;
|
|
41
|
+
G(!!(t && a.current && a.current.getBoundingClientRect().top <= 0)), w();
|
|
42
|
+
};
|
|
43
|
+
return e(), window.addEventListener("scroll", e, { passive: !0 }), window.addEventListener("resize", e), () => {
|
|
44
|
+
window.removeEventListener("scroll", e), window.removeEventListener("resize", e), r.current && window.clearTimeout(r.current);
|
|
45
|
+
};
|
|
46
|
+
}, [w]);
|
|
47
|
+
const O = g(
|
|
48
|
+
(e) => {
|
|
49
|
+
const t = e === "all" ? document.querySelector("#menu") : S.current?.querySelector(`[data-menu-group="${e}"]`);
|
|
50
|
+
if (!t) return;
|
|
51
|
+
r.current && window.clearTimeout(r.current), v.current = !0, h(e), p(t instanceof HTMLElement && t.dataset.menuCategory ? t.dataset.menuCategory : f, { force: !0 });
|
|
52
|
+
const n = Number.parseFloat(window.getComputedStyle(t).scrollMarginTop || "0"), i = t.getBoundingClientRect().top + window.scrollY - (Number.isFinite(n) ? n : 0);
|
|
53
|
+
window.scrollTo({ top: Math.max(0, i), behavior: "smooth" });
|
|
54
|
+
const o = window.performance.now(), L = () => {
|
|
55
|
+
const q = t.getBoundingClientRect().top, y = Number.parseFloat(window.getComputedStyle(t).scrollMarginTop || "0"), H = Number.isFinite(y) ? y : 0, N = window.performance.now() - o > 1800;
|
|
56
|
+
if (!(Math.abs(q - H) < 4 || window.scrollY + window.innerHeight >= document.documentElement.scrollHeight - 2 || N)) {
|
|
57
|
+
r.current = window.setTimeout(L, 80);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
v.current = !1, r.current = null, w();
|
|
61
|
+
};
|
|
62
|
+
r.current = window.setTimeout(L, 120);
|
|
63
|
+
},
|
|
64
|
+
[f, p, w]
|
|
65
|
+
);
|
|
66
|
+
return {
|
|
67
|
+
activeGroup: b,
|
|
68
|
+
catalogRef: S,
|
|
69
|
+
controlStripRef: a,
|
|
70
|
+
groupLabels: A,
|
|
71
|
+
handleGroupClick: O,
|
|
72
|
+
isTabsStuck: x,
|
|
73
|
+
openCategories: E,
|
|
74
|
+
tabsRef: l,
|
|
75
|
+
toggleCategory: F,
|
|
76
|
+
visibleCategories: T,
|
|
77
|
+
visibleGroups: M
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
P as useMenuBrowserState
|
|
82
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useState as w, useRef as s, useEffect as c } from "react";
|
|
2
|
+
function i(e) {
|
|
3
|
+
return e !== 0 && window.history.state?.parkedSheet === e;
|
|
4
|
+
}
|
|
5
|
+
function f(e) {
|
|
6
|
+
const [r, o] = w(null), u = s(e);
|
|
7
|
+
u.current = e;
|
|
8
|
+
const t = s(0), a = (n) => {
|
|
9
|
+
t.current = Date.now(), window.history.pushState({ parkedSheet: t.current }, ""), o(n);
|
|
10
|
+
}, d = () => {
|
|
11
|
+
if (i(t.current)) {
|
|
12
|
+
window.history.back();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
o(null), u.current?.();
|
|
16
|
+
};
|
|
17
|
+
return c(
|
|
18
|
+
() => () => {
|
|
19
|
+
i(t.current) && window.history.back();
|
|
20
|
+
},
|
|
21
|
+
[]
|
|
22
|
+
), c(() => {
|
|
23
|
+
if (r === null) return;
|
|
24
|
+
const n = () => {
|
|
25
|
+
o(null), u.current?.();
|
|
26
|
+
};
|
|
27
|
+
return window.addEventListener("popstate", n), () => window.removeEventListener("popstate", n);
|
|
28
|
+
}, [r]), { value: r, open: a, close: d };
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
f as useParkedSheet
|
|
32
|
+
};
|