@zappie/theme-base 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +26 -53
  3. package/dist/address.js +99 -2
  4. package/dist/address.js.map +7 -1
  5. package/dist/cart/address-sheet.js +143 -0
  6. package/dist/cart/address-sheet.js.map +7 -0
  7. package/dist/cart/cart-issues.js +72 -0
  8. package/dist/cart/cart-issues.js.map +7 -0
  9. package/dist/cart/cart-line-groups.js +34 -0
  10. package/dist/cart/cart-line-groups.js.map +7 -0
  11. package/dist/{chunk-FB5DRCU7.js → cart/cart-line.js} +9 -70
  12. package/dist/cart/cart-line.js.map +7 -0
  13. package/dist/cart/cart-lines.js +27 -0
  14. package/dist/cart/cart-lines.js.map +7 -0
  15. package/dist/cart/cart-schedule.js +24 -0
  16. package/dist/cart/cart-schedule.js.map +7 -0
  17. package/dist/cart/cart-sheet.js +35 -0
  18. package/dist/cart/cart-sheet.js.map +7 -0
  19. package/dist/cart/checkout-cta.js +81 -0
  20. package/dist/cart/checkout-cta.js.map +7 -0
  21. package/dist/cart/checkout-state.js +74 -0
  22. package/dist/cart/checkout-state.js.map +7 -0
  23. package/dist/cart/clear-cart.js +44 -0
  24. package/dist/cart/clear-cart.js.map +7 -0
  25. package/dist/cart/customer-details.js +70 -0
  26. package/dist/cart/customer-details.js.map +7 -0
  27. package/dist/cart/delivery-distance.js +22 -0
  28. package/dist/cart/delivery-distance.js.map +7 -0
  29. package/dist/cart/empty-cart.js +14 -0
  30. package/dist/cart/empty-cart.js.map +7 -0
  31. package/dist/cart/fulfilment-panel.js +83 -0
  32. package/dist/cart/fulfilment-panel.js.map +7 -0
  33. package/dist/cart/line-editor.js +35 -0
  34. package/dist/cart/line-editor.js.map +7 -0
  35. package/dist/cart/line-options.js +96 -0
  36. package/dist/cart/line-options.js.map +7 -0
  37. package/dist/cart/loading.js +17 -0
  38. package/dist/cart/loading.js.map +7 -0
  39. package/dist/cart/promo-sheet.js +103 -0
  40. package/dist/cart/promo-sheet.js.map +7 -0
  41. package/dist/cart/region-picker.js +40 -0
  42. package/dist/cart/region-picker.js.map +7 -0
  43. package/dist/cart/rewards-sheet.js +86 -0
  44. package/dist/cart/rewards-sheet.js.map +7 -0
  45. package/dist/cart/schedule-sheet.js +87 -0
  46. package/dist/cart/schedule-sheet.js.map +7 -0
  47. package/dist/{chunk-JFEI2OUZ.js → cart/theme-class.js} +7 -5
  48. package/dist/cart/theme-class.js.map +7 -0
  49. package/dist/cart/totals.js +81 -0
  50. package/dist/cart/totals.js.map +7 -0
  51. package/dist/cart/use-address-selection.js +130 -0
  52. package/dist/cart/use-address-selection.js.map +7 -0
  53. package/dist/cart.js +21 -1069
  54. package/dist/cart.js.map +7 -1
  55. package/dist/catalogue/catalogue-cart.js +25 -0
  56. package/dist/catalogue/catalogue-cart.js.map +7 -0
  57. package/dist/catalogue/catalogue-header.js +88 -0
  58. package/dist/catalogue/catalogue-header.js.map +7 -0
  59. package/dist/catalogue/catalogue-pages.js +68 -0
  60. package/dist/catalogue/catalogue-pages.js.map +7 -0
  61. package/dist/catalogue/catalogue-search.js +89 -0
  62. package/dist/catalogue/catalogue-search.js.map +7 -0
  63. package/dist/catalogue/category-navigation.js +98 -0
  64. package/dist/catalogue/category-navigation.js.map +7 -0
  65. package/dist/catalogue/category-section.js +113 -0
  66. package/dist/catalogue/category-section.js.map +7 -0
  67. package/dist/catalogue/info-banners.js +148 -0
  68. package/dist/catalogue/info-banners.js.map +7 -0
  69. package/dist/catalogue/item-tile.js +55 -0
  70. package/dist/catalogue/item-tile.js.map +7 -0
  71. package/dist/catalogue/loader.js +136 -0
  72. package/dist/catalogue/loader.js.map +7 -0
  73. package/dist/{chunk-USSLDBDY.js → catalogue/presentation.js} +12 -9
  74. package/dist/catalogue/presentation.js.map +7 -0
  75. package/dist/catalogue/saved-catalogue-sync.js +115 -0
  76. package/dist/catalogue/saved-catalogue-sync.js.map +7 -0
  77. package/dist/catalogue/types.js +1 -0
  78. package/dist/catalogue/types.js.map +7 -0
  79. package/dist/catalogue/use-catalogue-data.js +88 -0
  80. package/dist/catalogue/use-catalogue-data.js.map +7 -0
  81. package/dist/catalogue/use-category-scroll.js +115 -0
  82. package/dist/catalogue/use-category-scroll.js.map +7 -0
  83. package/dist/catalogue/use-item-opener.js +46 -0
  84. package/dist/catalogue/use-item-opener.js.map +7 -0
  85. package/dist/catalogue/use-search-source.js +132 -0
  86. package/dist/catalogue/use-search-source.js.map +7 -0
  87. package/dist/catalogue.js +26 -1216
  88. package/dist/catalogue.js.map +7 -1
  89. package/dist/checkout.js +149 -2
  90. package/dist/checkout.js.map +7 -1
  91. package/dist/host-bridge.js +22 -2
  92. package/dist/host-bridge.js.map +7 -1
  93. package/dist/index.js +3 -3
  94. package/dist/index.js.map +7 -1
  95. package/dist/item/configurator-commit.js +15 -0
  96. package/dist/item/configurator-commit.js.map +7 -0
  97. package/dist/item/configurator-draft.js +63 -0
  98. package/dist/item/configurator-draft.js.map +7 -0
  99. package/dist/item/configurator.js +135 -0
  100. package/dist/item/configurator.js.map +7 -0
  101. package/dist/item/note.js +65 -0
  102. package/dist/item/note.js.map +7 -0
  103. package/dist/item/variant-status.js +23 -0
  104. package/dist/item/variant-status.js.map +7 -0
  105. package/dist/item-frame.js +60 -3
  106. package/dist/item-frame.js.map +7 -1
  107. package/dist/item.js +11 -11
  108. package/dist/item.js.map +7 -1
  109. package/dist/navigation.js +39 -2
  110. package/dist/navigation.js.map +7 -1
  111. package/dist/url-navigation-state.js +61 -0
  112. package/dist/url-navigation-state.js.map +7 -0
  113. package/dist/{chunk-ILOCSCZL.js → url-navigation.js} +12 -89
  114. package/dist/url-navigation.js.map +7 -0
  115. package/package.json +8 -7
  116. package/dist/chunk-2MV6KU3R.js +0 -352
  117. package/dist/chunk-2MV6KU3R.js.map +0 -1
  118. package/dist/chunk-FB5DRCU7.js.map +0 -1
  119. package/dist/chunk-IG63ONID.js +0 -139
  120. package/dist/chunk-IG63ONID.js.map +0 -1
  121. package/dist/chunk-ILOCSCZL.js.map +0 -1
  122. package/dist/chunk-JFEI2OUZ.js.map +0 -1
  123. package/dist/chunk-NTJONY3N.js +0 -95
  124. package/dist/chunk-NTJONY3N.js.map +0 -1
  125. package/dist/chunk-QWST2TA2.js +0 -22
  126. package/dist/chunk-QWST2TA2.js.map +0 -1
  127. package/dist/chunk-USSLDBDY.js.map +0 -1
  128. package/dist/chunk-VIAJ27YC.js +0 -59
  129. package/dist/chunk-VIAJ27YC.js.map +0 -1
package/dist/catalogue.js CHANGED
@@ -1,1218 +1,28 @@
1
1
  "use client";
2
- import { Description, ItemImage } from './chunk-USSLDBDY.js';
3
- import { ClearCart, CartLine } from './chunk-FB5DRCU7.js';
4
- import './chunk-2MV6KU3R.js';
5
- import { useBaseHostBridge } from './chunk-QWST2TA2.js';
6
- import { ThemeClassProvider } from './chunk-JFEI2OUZ.js';
7
- import { useCatalogueNavigation } from './chunk-ILOCSCZL.js';
8
- import { useOverlay, createSearchIndex, OpenStatus, Search, Overlay, Cart } from '@zappie/foundations';
9
- import { useZappie, useStore, useCart, useCartCatalogue } from '@zappie/sdk/react';
10
- import { useState, useCallback, useMemo, useEffect, useRef, Fragment } from 'react';
11
- import { jsx, jsxs } from 'react/jsx-runtime';
12
- import { countEvent } from '@zappie/sdk/visits';
13
- import { createSanitizeRichText, splitInfoBanner } from '@zappie/foundations/rich-text';
14
- import { parseRichText } from '@zappie/foundations/rich-text/browser';
15
2
 
16
- function CatalogueCart({
17
- action,
18
- count,
19
- subtotal,
20
- client,
21
- onOpen
22
- }) {
23
- if (count === 0) {
24
- return null;
25
- }
26
- return /* @__PURE__ */ jsxs("button", { type: "button", className: "z-base-catalogue-cart", onClick: onOpen, children: [
27
- action,
28
- " Order \xB7 ",
29
- count,
30
- " items \xB7",
31
- " ",
32
- subtotal ? client.format.money(subtotal) : "Calculating\u2026"
33
- ] });
34
- }
35
- function CatalogueHeader({
36
- branch,
37
- storeName,
38
- menus,
39
- selectedMenuId,
40
- cartLines,
41
- cartOpen,
42
- fulfilmentMode,
43
- layout,
44
- slots,
45
- onOpenCart,
46
- onOpenBranchDetails,
47
- onSelectMenu,
48
- onOpenBranchFinder,
49
- onSwitchFulfilment,
50
- onSetLayout
51
- }) {
52
- const [canShare, setCanShare] = useState(false);
53
- useEffect(() => setCanShare(typeof navigator.share === "function"), []);
54
- const ToolbarAction = slots?.ToolbarAction;
55
- return /* @__PURE__ */ jsxs("header", { children: [
56
- /* @__PURE__ */ jsx("h2", { tabIndex: -1, id: "base-catalogue-heading", children: "Menu" }),
57
- /* @__PURE__ */ jsx(
58
- "button",
59
- {
60
- type: "button",
61
- "aria-label": `Open cart${cartLines.length ? `, ${cartLines.length} items` : ""}`,
62
- onClick: onOpenCart,
63
- children: "Cart"
64
- }
65
- ),
66
- branch && /* @__PURE__ */ jsx(
67
- "button",
68
- {
69
- type: "button",
70
- onClick: onOpenBranchDetails,
71
- "aria-label": "View opening hours",
72
- children: /* @__PURE__ */ jsx(OpenStatus, { branch, children: ({ isOpen, label }) => branch.isOpen === isOpen ? label : branch.isOpen ? "Open" : "Temporarily closed" })
73
- }
74
- ),
75
- selectedMenuId && /* @__PURE__ */ jsxs("label", { children: [
76
- "Menu",
77
- /* @__PURE__ */ jsx(
78
- "select",
79
- {
80
- value: selectedMenuId,
81
- onChange: (event) => onSelectMenu(event.target.value),
82
- children: menus?.map((menu) => /* @__PURE__ */ jsxs("option", { value: menu.id, children: [
83
- menu.name,
84
- " (",
85
- cartLines.filter((line) => line.menuId === menu.id).reduce((sum, line) => sum + line.quantity, 0),
86
- " ",
87
- "added)"
88
- ] }, menu.id))
89
- }
90
- )
91
- ] }),
92
- /* @__PURE__ */ jsx("button", { type: "button", onClick: onOpenBranchFinder, children: "Change branch" }),
93
- /* @__PURE__ */ jsx("button", { type: "button", onClick: onSwitchFulfilment, children: fulfilmentMode === "pickup" ? "Delivery" : "Pickup" }),
94
- canShare && /* @__PURE__ */ jsx(
95
- "button",
96
- {
97
- type: "button",
98
- onClick: () => {
99
- if (navigator.share) {
100
- void navigator.share({
101
- url: window.location.href,
102
- ...storeName ? { title: storeName } : {}
103
- }).catch(() => {
104
- });
105
- }
106
- },
107
- children: "Share menu"
108
- }
109
- ),
110
- ToolbarAction && /* @__PURE__ */ jsx(ToolbarAction, { layout, setLayout: onSetLayout }),
111
- cartLines.length > 0 && !cartOpen && /* @__PURE__ */ jsx(ClearCart, {})
112
- ] });
113
- }
114
- function CatalogueSearch({
115
- search,
116
- open,
117
- themeClass,
118
- onOpen,
119
- onSelectItem,
120
- onSelectCategory
121
- }) {
122
- const content = /* @__PURE__ */ jsxs(
123
- Search.Root,
124
- {
125
- source: search.source,
126
- query: search.query,
127
- onQueryChange: search.setQuery,
128
- onSelect: (result) => {
129
- if (result.type === "item") {
130
- onSelectItem(result.item);
131
- } else {
132
- onSelectCategory(result.category.id);
133
- }
134
- },
135
- children: [
136
- /* @__PURE__ */ jsx(
137
- Search.Input,
138
- {
139
- "aria-label": "Search menu",
140
- placeholder: "Search menu",
141
- onFocus: onOpen
142
- }
143
- ),
144
- search.query && /* @__PURE__ */ jsx("button", { type: "button", onClick: () => search.setQuery(""), children: "Clear search" }),
145
- open && search.query && /* @__PURE__ */ jsx(Search.Results, { children: ({ results, error, retry }) => /* @__PURE__ */ jsxs(Fragment, { children: [
146
- search.source.isLoading && /* @__PURE__ */ jsx("p", { role: "status", children: "Searching\u2026" }),
147
- error && /* @__PURE__ */ jsxs("p", { role: "alert", children: [
148
- error,
149
- /* @__PURE__ */ jsx("button", { type: "button", onClick: retry, children: "Retry search" })
150
- ] }),
151
- !search.source.isLoading && !error && !results.length && /* @__PURE__ */ jsx("p", { children: "No results" }),
152
- search.hasMore && /* @__PURE__ */ jsx(
153
- "button",
154
- {
155
- type: "button",
156
- disabled: search.source.isLoading,
157
- onClick: search.loadMore,
158
- children: "More search results"
159
- }
160
- ),
161
- results.map((result, index) => /* @__PURE__ */ jsx(
162
- Search.Result,
163
- {
164
- index,
165
- children: result.type === "item" ? /* @__PURE__ */ jsxs(Fragment, { children: [
166
- result.item.name,
167
- !result.item.isAvailable && /* @__PURE__ */ jsx("span", { children: result.item.stockLabel ?? "Unavailable" })
168
- ] }) : result.category.name
169
- },
170
- result.type === "item" ? result.item.id : result.category.id
171
- ))
172
- ] }) })
173
- ]
174
- }
175
- );
176
- return /* @__PURE__ */ jsxs(Fragment, { children: [
177
- /* @__PURE__ */ jsx("div", { className: "z-base-search-desktop", children: content }),
178
- /* @__PURE__ */ jsxs(Overlay.Root, { param: "catalogue_search", id: "search", presentation: "sheet", children: [
179
- /* @__PURE__ */ jsx(Overlay.Trigger, { className: "z-base-search-mobile", children: "Search menu" }),
180
- /* @__PURE__ */ jsxs(
181
- Overlay.Content,
182
- {
183
- "data-zappie-theme": "base",
184
- className: ["z-base-cart z-base-editor", themeClass].filter(Boolean).join(" "),
185
- children: [
186
- /* @__PURE__ */ jsx(Overlay.Title, { children: "Search menu" }),
187
- /* @__PURE__ */ jsx(Overlay.Close, { children: "Close search" }),
188
- content
189
- ]
190
- }
191
- )
192
- ] })
193
- ] });
194
- }
195
- function CategoryNavigation({
196
- categories,
197
- active,
198
- themeClass,
199
- slots,
200
- onSelect,
201
- onFocusCategory
202
- }) {
203
- const overlay = useOverlay("catalogue_categories", "categories");
204
- const [filter, setFilter] = useState("");
205
- const [pending, setPending] = useState();
206
- const CategoryTab = slots?.CategoryTab;
207
- useEffect(() => {
208
- if (pending && !overlay.isOpen) {
209
- const frame = requestAnimationFrame(() => {
210
- setPending(void 0);
211
- onSelect(pending);
212
- onFocusCategory(pending);
213
- });
214
- return () => cancelAnimationFrame(frame);
215
- }
216
- }, [pending, overlay.isOpen, onSelect, onFocusCategory]);
217
- const filtered = categories.filter(
218
- (category) => category.name.toLowerCase().includes(filter.toLowerCase())
219
- );
220
- return /* @__PURE__ */ jsxs(Fragment, { children: [
221
- /* @__PURE__ */ jsxs(
222
- Overlay.Root,
223
- {
224
- param: "catalogue_categories",
225
- id: "categories",
226
- presentation: { base: "sheet", lg: "dialog" },
227
- children: [
228
- /* @__PURE__ */ jsx(Overlay.Trigger, { children: "Browse categories" }),
229
- /* @__PURE__ */ jsxs(
230
- Overlay.Content,
231
- {
232
- "data-zappie-theme": "base",
233
- className: ["z-base-cart z-base-editor", themeClass].filter(Boolean).join(" "),
234
- children: [
235
- /* @__PURE__ */ jsx(Overlay.Title, { children: "Browse categories" }),
236
- /* @__PURE__ */ jsx(Overlay.Close, { children: "Close categories" }),
237
- /* @__PURE__ */ jsx(
238
- "input",
239
- {
240
- "aria-label": "Filter categories",
241
- value: filter,
242
- onChange: (event) => setFilter(event.target.value)
243
- }
244
- ),
245
- filtered.map((category) => /* @__PURE__ */ jsx(
246
- "button",
247
- {
248
- type: "button",
249
- onClick: () => {
250
- setPending(category.id);
251
- overlay.close();
252
- },
253
- children: category.name
254
- },
255
- category.id
256
- )),
257
- filtered.length === 0 && /* @__PURE__ */ jsx("p", { children: "No matching categories" })
258
- ]
259
- }
260
- )
261
- ]
262
- }
263
- ),
264
- /* @__PURE__ */ jsx("nav", { "aria-label": "Categories", className: "z-base-category-nav", children: categories.map((category) => /* @__PURE__ */ jsx(
265
- "a",
266
- {
267
- href: `#base-category-${category.id}`,
268
- "aria-current": active === category.id ? "true" : void 0,
269
- onClick: (event) => {
270
- event.preventDefault();
271
- onSelect(category.id);
272
- },
273
- children: CategoryTab ? /* @__PURE__ */ jsx(
274
- CategoryTab,
275
- {
276
- category,
277
- active: active === category.id
278
- }
279
- ) : category.name
280
- },
281
- category.id
282
- )) })
283
- ] });
284
- }
285
- function BaseItemTile({
286
- item,
287
- lines,
288
- href,
289
- layout,
290
- priority,
291
- client,
292
- onOpen
293
- }) {
294
- const price = item.price;
295
- return /* @__PURE__ */ jsxs(
296
- "a",
297
- {
298
- href,
299
- className: "z-base-item-tile",
300
- onClick: (event) => {
301
- event.preventDefault();
302
- event.currentTarget.focus({ preventScroll: true });
303
- onOpen();
304
- },
305
- children: [
306
- /* @__PURE__ */ jsx(
307
- ItemImage,
308
- {
309
- src: item.images[0],
310
- sizes: layout === "LIST" ? "100vw" : "(min-width: 768px) 33vw, 50vw",
311
- priority
312
- }
313
- ),
314
- /* @__PURE__ */ jsx("span", { className: "z-base-item-name", children: item.name }),
315
- item.description && /* @__PURE__ */ jsx(Description, { value: item.description }),
316
- item.promo && /* @__PURE__ */ jsx("span", { children: item.promo.name }),
317
- item.compareAtPrice && /* @__PURE__ */ jsx("del", { children: client.format.money(item.compareAtPrice) }),
318
- price && /* @__PURE__ */ jsxs("span", { className: "z-base-amount", children: [
319
- item.variants.some(
320
- (variant) => variant.price.amountMinor !== price.amountMinor
321
- ) ? "From " : "",
322
- client.format.money(price)
323
- ] }),
324
- (item.stockLabel || !item.isAvailable) && /* @__PURE__ */ jsx("span", { children: item.stockLabel ?? "Unavailable" }),
325
- lines.map((line) => /* @__PURE__ */ jsxs("span", { children: [
326
- line.quantity,
327
- " added"
328
- ] }, line.id))
329
- ]
330
- }
331
- );
332
- }
333
- function CategorySection({
334
- category,
335
- categoryIndex,
336
- catalogue,
337
- menuId,
338
- layout,
339
- slots,
340
- sections,
341
- cartOpen,
342
- client,
343
- busy,
344
- hasMore,
345
- itemHref,
346
- onOpen,
347
- onLoadMore
348
- }) {
349
- const CategoryHeader = slots?.CategoryHeader;
350
- const Tile = slots?.Tile;
351
- const columns = slots?.layout?.columns;
352
- const baseColumns = typeof columns === "object" ? columns.base : columns;
353
- const mediumColumns = typeof columns === "object" ? columns.medium : columns;
354
- const largeColumns = typeof columns === "object" ? columns.large : columns;
355
- return /* @__PURE__ */ jsxs(
356
- "section",
357
- {
358
- id: `base-category-${category.id}`,
359
- className: "z-base-category",
360
- "data-unloaded": category.itemIds.length === 0,
361
- ref: (node) => {
362
- if (node) {
363
- sections.current.set(category.id, node);
364
- } else {
365
- sections.current.delete(category.id);
366
- }
367
- },
368
- children: [
369
- /* @__PURE__ */ jsx("h3", { tabIndex: -1, children: CategoryHeader ? /* @__PURE__ */ jsx(CategoryHeader, { category }) : category.name }),
370
- category.description && /* @__PURE__ */ jsx(Description, { value: category.description }),
371
- /* @__PURE__ */ jsx(
372
- Cart.Root,
373
- {
374
- className: "z-base-item-list",
375
- "data-layout": layout,
376
- "data-columns": baseColumns,
377
- "data-columns-medium": mediumColumns,
378
- "data-columns-large": largeColumns,
379
- "data-density": slots?.layout?.density,
380
- children: category.itemIds.map((id, index) => {
381
- const item = catalogue.items[id];
382
- if (!item) {
383
- return null;
384
- }
385
- const lines = client.cart.lines.filter((line) => line.itemId === id);
386
- const href = itemHref(item.id, menuId);
387
- return /* @__PURE__ */ jsxs("div", { children: [
388
- Tile ? /* @__PURE__ */ jsx(
389
- Tile,
390
- {
391
- item,
392
- ...menuId !== void 0 ? { menuId } : {},
393
- href,
394
- quantityInCart: lines.reduce(
395
- (sum, line) => sum + line.quantity,
396
- 0
397
- ),
398
- onAdd: () => {
399
- try {
400
- client.cart.add(item.id, {
401
- ...menuId !== void 0 ? { menuId } : {}
402
- });
403
- countEvent("add");
404
- } catch {
405
- onOpen(item);
406
- }
407
- },
408
- onOpen: () => onOpen(item)
409
- }
410
- ) : /* @__PURE__ */ jsx(
411
- BaseItemTile,
412
- {
413
- item,
414
- lines,
415
- href,
416
- layout,
417
- priority: categoryIndex === 0 && index < 4,
418
- client,
419
- onOpen: () => onOpen(item)
420
- }
421
- ),
422
- !cartOpen && lines.map((line) => /* @__PURE__ */ jsx(CartLine, { line }, line.id))
423
- ] }, id);
424
- })
425
- }
426
- ),
427
- hasMore && /* @__PURE__ */ jsxs("button", { type: "button", disabled: busy, onClick: onLoadMore, children: [
428
- "Load more ",
429
- category.name
430
- ] })
431
- ]
432
- }
433
- );
434
- }
435
- var sanitize = createSanitizeRichText(parseRichText);
436
- function InfoBanners({ value }) {
437
- const [banners, setBanners] = useState([]);
438
- const [index, setIndex] = useState(0);
439
- const [expanded, setExpanded] = useState({});
440
- const [paused, setPaused] = useState(false);
441
- const viewport = useRef(null);
442
- const interacted = useRef(false);
443
- useEffect(() => {
444
- setBanners(
445
- splitInfoBanner(value).map(sanitize).filter((banner) => banner.replace(/<[^>]*>/g, "").trim())
446
- );
447
- setIndex(0);
448
- setExpanded({});
449
- interacted.current = false;
450
- }, [value]);
451
- function select(next, interaction = true) {
452
- interacted.current || (interacted.current = interaction);
453
- setExpanded({});
454
- viewport.current?.children[next]?.scrollIntoView({
455
- block: "nearest",
456
- inline: "start",
457
- behavior: "instant"
458
- });
459
- setIndex(next);
460
- }
461
- const isExpanded = Object.values(expanded).some(Boolean);
462
- useEffect(() => {
463
- if (paused || isExpanded || banners.length < 2) {
464
- return;
465
- }
466
- const interval = setInterval(() => {
467
- const node = viewport.current;
468
- if (!node || interacted.current || window.matchMedia("(prefers-reduced-motion: reduce)").matches || node.scrollWidth <= node.clientWidth) {
469
- return;
470
- }
471
- select((index + 1) % banners.length, false);
472
- }, 5e3);
473
- return () => clearInterval(interval);
474
- }, [index, paused, isExpanded, banners.length]);
475
- if (!banners.length) {
476
- return null;
477
- }
478
- return /* @__PURE__ */ jsxs(
479
- "section",
480
- {
481
- "aria-label": "Menu information",
482
- onMouseEnter: () => setPaused(true),
483
- onMouseLeave: () => setPaused(false),
484
- onFocus: () => setPaused(true),
485
- onBlur: () => setPaused(false),
486
- children: [
487
- /* @__PURE__ */ jsx(
488
- "div",
489
- {
490
- className: "z-base-info-banners",
491
- ref: viewport,
492
- onPointerDown: () => {
493
- interacted.current = true;
494
- },
495
- onScroll: () => {
496
- const node = viewport.current;
497
- if (node?.children[0]) {
498
- setIndex(
499
- Math.round(
500
- node.scrollLeft / node.children[0].getBoundingClientRect().width
501
- )
502
- );
503
- }
504
- },
505
- children: banners.map((banner, position) => /* @__PURE__ */ jsxs("article", { children: [
506
- /* @__PURE__ */ jsx(
507
- "div",
508
- {
509
- className: "z-base-info-copy",
510
- "data-expanded": Boolean(expanded[position]),
511
- dangerouslySetInnerHTML: { __html: banner }
512
- }
513
- ),
514
- /* @__PURE__ */ jsxs(
515
- "button",
516
- {
517
- type: "button",
518
- "aria-expanded": Boolean(expanded[position]),
519
- onClick: () => setExpanded((current) => ({
520
- ...current,
521
- [position]: !current[position]
522
- })),
523
- children: [
524
- "Show ",
525
- expanded[position] ? "less" : "more"
526
- ]
527
- }
528
- )
529
- ] }, banner + position))
530
- }
531
- ),
532
- banners.length > 1 && /* @__PURE__ */ jsxs("div", { children: [
533
- /* @__PURE__ */ jsx(
534
- "button",
535
- {
536
- type: "button",
537
- "aria-label": "Previous information",
538
- disabled: index === 0,
539
- onClick: () => select(index - 1),
540
- children: "Previous"
541
- }
542
- ),
543
- /* @__PURE__ */ jsx(
544
- "button",
545
- {
546
- type: "button",
547
- "aria-label": "Next information",
548
- disabled: index >= banners.length - 1,
549
- onClick: () => select(index + 1),
550
- children: "Next"
551
- }
552
- ),
553
- banners.map((_, position) => /* @__PURE__ */ jsx(
554
- "button",
555
- {
556
- type: "button",
557
- "aria-label": `Go to banner ${position + 1}`,
558
- "aria-current": index === position ? "true" : void 0,
559
- onClick: () => select(position),
560
- children: position + 1
561
- },
562
- position
563
- ))
564
- ] })
565
- ]
566
- }
567
- );
568
- }
569
-
570
- // src/catalogue/catalogue-pages.ts
571
- var pageKey = (menuId, categoryId) => `${menuId}:${categoryId}`;
572
- function pageState(nextCursor) {
573
- return { ...nextCursor ? { next: nextCursor } : {}, done: !nextCursor };
574
- }
575
- function mergePage(menu, page) {
576
- return {
577
- ...menu,
578
- items: { ...menu.items, ...page.menu.items },
579
- categories: menu.categories.map((category) => {
580
- const incoming = page.menu.categories.find(
581
- (value) => value.id === category.id
582
- );
583
- return incoming ? {
584
- ...category,
585
- itemIds: [.../* @__PURE__ */ new Set([...category.itemIds, ...incoming.itemIds])]
586
- } : category;
587
- }),
588
- completeness: "partial"
589
- };
590
- }
591
- function readSavedPages(client, menuId, branchId, saved, signal) {
592
- return Promise.all(
593
- saved.map(async (entry) => ({
594
- ...entry,
595
- page: await client.menu.page(menuId, entry.categoryId, {
596
- branch: branchId,
597
- signal,
598
- ...entry.cursor ? { cursor: entry.cursor } : {}
599
- })
600
- }))
601
- );
602
- }
603
- function replaceRefreshedCategories(menu, refreshed) {
604
- const fresh = /* @__PURE__ */ new Map();
605
- let next = menu;
606
- for (const { categoryId, page } of refreshed) {
607
- const ids = page.menu.categories.find((c) => c.id === categoryId)?.itemIds;
608
- fresh.set(categoryId, [...fresh.get(categoryId) ?? [], ...ids ?? []]);
609
- next = { ...next, items: { ...next.items, ...page.menu.items } };
610
- }
611
- return {
612
- ...next,
613
- categories: next.categories.map((category) => {
614
- const ids = fresh.get(category.id);
615
- return ids ? { ...category, itemIds: ids } : category;
616
- })
617
- };
618
- }
619
- function replaceSavedPages(saved, refreshed) {
620
- for (const page of refreshed) {
621
- const index = saved.findIndex(
622
- (entry) => entry.categoryId === page.categoryId && entry.cursor === page.cursor
623
- );
624
- if (index >= 0) {
625
- saved[index] = page;
626
- }
627
- }
628
- }
629
-
630
- // src/catalogue/saved-catalogue-sync.ts
631
- async function loadResources(client, scope) {
632
- const [persistence, selected] = await Promise.all([
633
- import('@zappie/sdk/persist/catalogue'),
634
- import('@zappie/sdk/transport/selected-menu')
635
- ]);
636
- return {
637
- saved: persistence.createSavedCatalogue(client, scope),
638
- selected: selected.createSelectedMenuReader(client)
639
- };
640
- }
641
- function createSavedCatalogueSync({
642
- client,
643
- state,
644
- scope,
645
- revision,
646
- publish
647
- }) {
648
- let resources;
649
- function snapshot() {
650
- return {
651
- scope,
652
- menu: state.menu,
653
- coverage: { menuIds: [scope.menuId], complete: state.complete },
654
- pages: [...state.savedPages],
655
- etag: state.menu.version,
656
- savedAt: Date.now(),
657
- ...revision ? { revision } : {}
658
- };
659
- }
660
- async function save() {
661
- if (await resources.saved.publish(snapshot()).catch(() => true)) {
662
- state.abort.signal.throwIfAborted();
663
- publish?.(state.menu);
664
- }
665
- }
666
- async function refresh() {
667
- if (state.complete) {
668
- const response = await resources.selected.read(scope, {
669
- signal: state.abort.signal
670
- });
671
- state.abort.signal.throwIfAborted();
672
- if ("notModified" in response) {
673
- return;
674
- }
675
- state.menu = response.menu;
676
- await save();
677
- return;
678
- }
679
- const refreshed = await readSavedPages(
680
- client,
681
- scope.menuId,
682
- scope.branchId,
683
- state.savedPages,
684
- state.abort.signal
685
- );
686
- state.abort.signal.throwIfAborted();
687
- state.menu = replaceRefreshedCategories(state.menu, refreshed);
688
- for (const { categoryId, page } of refreshed) {
689
- state.pages.set(
690
- pageKey(scope.menuId, categoryId),
691
- pageState(page.nextCursor)
692
- );
693
- }
694
- replaceSavedPages(state.savedPages, refreshed);
695
- await save();
696
- }
697
- return {
698
- get resources() {
699
- return resources;
700
- },
701
- /** Shows the current menu now; saving runs behind it and never fails a read. */
702
- emit() {
703
- state.abort.signal.throwIfAborted();
704
- publish?.(state.menu);
705
- void resources?.saved.publish(snapshot()).catch(() => {
706
- });
707
- },
708
- async restore() {
709
- resources = await loadResources(client, scope);
710
- const value = await resources.saved.restore();
711
- state.abort.signal.throwIfAborted();
712
- if (!value) {
713
- return false;
714
- }
715
- state.menu = value.menu;
716
- state.complete = value.coverage.complete;
717
- state.mode = state.complete ? "eager" : "progressive";
718
- state.savedPages.push(...value.pages);
719
- for (const saved of value.pages) {
720
- state.pages.set(
721
- pageKey(scope.menuId, saved.categoryId),
722
- pageState(saved.page.nextCursor)
723
- );
724
- }
725
- publish?.(state.menu);
726
- if (!revision || value.revision !== revision) {
727
- void refresh().catch(() => {
728
- });
729
- }
730
- return true;
731
- }
732
- };
733
- }
734
-
735
- // src/catalogue/loader.ts
736
- function createCatalogueLoader(client, metadata, resolve, publish, orderContext = "delivery", revision) {
737
- const state = {
738
- menu: metadata,
739
- mode: resolve(metadata),
740
- complete: false,
741
- abort: new AbortController(),
742
- pages: /* @__PURE__ */ new Map(),
743
- savedPages: []
744
- };
745
- const scope = {
746
- store: client.config.store,
747
- branchId: metadata.branchId,
748
- orderContext,
749
- menuId: metadata.menus?.[0]?.id ?? metadata.id
750
- };
751
- const saved = createSavedCatalogueSync({
752
- client,
753
- state,
754
- scope,
755
- revision,
756
- publish
757
- });
758
- const pending = /* @__PURE__ */ new Map();
759
- let eager;
760
- let speculative;
761
- function readEager(signal = state.abort.signal) {
762
- eager ?? (eager = saved.resources.selected.read(scope, { signal }).then(async (response) => {
763
- signal.throwIfAborted();
764
- if ("notModified" in response) {
765
- throw new Error("Unexpected conditional selected-menu response");
766
- }
767
- state.complete = true;
768
- state.menu = response.menu;
769
- saved.emit();
770
- return state.menu;
771
- }).catch((failure) => {
772
- eager = void 0;
773
- throw failure;
774
- }));
775
- return eager;
776
- }
777
- function speculate() {
778
- if (eager) {
779
- return;
780
- }
781
- speculative = new AbortController();
782
- const cancel = () => speculative?.abort();
783
- state.abort.signal.addEventListener("abort", cancel, { once: true });
784
- void readEager(speculative.signal).catch(() => {
785
- });
786
- }
787
- async function readPage(menuId, categoryId, key, cursor) {
788
- const page = await client.menu.page(menuId, categoryId, {
789
- branch: metadata.branchId,
790
- signal: state.abort.signal,
791
- ...cursor ? { cursor } : {}
792
- });
793
- state.abort.signal.throwIfAborted();
794
- if (!state.complete) {
795
- state.menu = mergePage(state.menu, page);
796
- }
797
- state.savedPages.push({ categoryId, ...cursor ? { cursor } : {}, page });
798
- saved.emit();
799
- state.pages.set(key, pageState(page.nextCursor));
800
- if (state.mode === null) {
801
- state.mode = resolve(metadata, page.menu) ?? "progressive";
802
- if (state.mode !== "eager") {
803
- speculative?.abort();
804
- eager = void 0;
805
- }
806
- }
807
- return state.menu;
808
- }
809
- const initialized = saved.restore().catch(() => false);
810
- return {
811
- get value() {
812
- return state.menu;
813
- },
814
- get mode() {
815
- return state.mode;
816
- },
817
- hasMore(menuId, categoryId) {
818
- return state.mode !== "eager" && !state.pages.get(pageKey(menuId, categoryId))?.done;
819
- },
820
- /** True when reaching this category would neither read nor change. */
821
- isLoaded(menuId, categoryId) {
822
- return state.complete || state.mode !== "eager" && state.pages.has(pageKey(menuId, categoryId));
823
- },
824
- async reach(menuId, categoryId, more = false) {
825
- const key = pageKey(menuId, categoryId);
826
- const warm = await initialized;
827
- if (state.complete || warm && state.pages.has(key) && !more) {
828
- return state.menu;
829
- }
830
- if (state.mode === "eager") {
831
- return readEager();
832
- }
833
- const existing = pending.get(key);
834
- if (existing) {
835
- return existing;
836
- }
837
- const loaded = state.pages.get(key);
838
- if (loaded && (!more || loaded.done)) {
839
- return state.menu;
840
- }
841
- if (state.mode === null) {
842
- speculate();
843
- }
844
- const request = readPage(menuId, categoryId, key, loaded?.next);
845
- pending.set(key, request);
846
- try {
847
- return await request;
848
- } finally {
849
- pending.delete(key);
850
- }
851
- },
852
- /** Aborts in-flight reads; `resume()` makes the loader usable again. */
853
- dispose() {
854
- state.abort.abort();
855
- },
856
- resume() {
857
- if (state.abort.signal.aborted) {
858
- state.abort = new AbortController();
859
- }
860
- }
861
- };
862
- }
863
-
864
- // src/catalogue/use-catalogue-data.ts
865
- function useCatalogueData({
866
- client,
867
- initialMenu,
868
- selectedMenuId,
869
- fulfilmentMode,
870
- resolveStrategy,
871
- revision
872
- }) {
873
- const [catalogue, setCatalogue] = useState(initialMenu);
874
- const show = useCallback(
875
- (value) => setCatalogue({
876
- ...value,
877
- ...initialMenu.menus ? { menus: initialMenu.menus } : {},
878
- categories: initialMenu.categories.map(
879
- (category) => value.categories.find((loaded) => loaded.id === category.id) ?? category
880
- )
881
- }),
882
- [initialMenu]
883
- );
884
- const loader = useMemo(() => {
885
- const selected = initialMenu.menus?.find(
886
- (source2) => source2.id === selectedMenuId
887
- );
888
- const scoped = {
889
- ...initialMenu,
890
- ...selected ? { menus: [selected] } : {},
891
- categories: initialMenu.categories.filter(
892
- (category) => !selected || selected.categoryIds.includes(category.id)
893
- )
894
- };
895
- return createCatalogueLoader(
896
- client,
897
- scoped,
898
- resolveStrategy,
899
- show,
900
- fulfilmentMode,
901
- revision
902
- );
903
- }, [
904
- client,
905
- initialMenu,
906
- selectedMenuId,
907
- fulfilmentMode,
908
- resolveStrategy,
909
- revision,
910
- show
911
- ]);
912
- useEffect(() => {
913
- loader.resume();
914
- return () => loader.dispose();
915
- }, [loader]);
916
- const source = catalogue.menus?.find((value) => value.id === selectedMenuId) ?? catalogue.menus?.[0];
917
- const categories = useMemo(
918
- () => catalogue.categories.filter(
919
- (category) => source?.categoryIds.includes(category.id)
920
- ),
921
- [catalogue.categories, source]
922
- );
923
- const [error, setError] = useState();
924
- const [busy, setBusy] = useState(false);
925
- const reach = useCallback(
926
- async (categoryId, more = false) => {
927
- if (!source || !more && loader.isLoaded(source.id, categoryId)) {
928
- return;
929
- }
930
- setBusy(true);
931
- setError(void 0);
932
- try {
933
- show(await loader.reach(source.id, categoryId, more));
934
- } catch (failure) {
935
- if (!(failure instanceof Error) || failure.name !== "AbortError") {
936
- setError("Catalogue could not load. Try again.");
937
- }
938
- } finally {
939
- setBusy(false);
940
- }
941
- },
942
- [loader, source, show]
943
- );
944
- return { catalogue, source, categories, loader, error, busy, reach };
945
- }
946
- function useCategoryScroll({
947
- categories,
948
- selectedCategoryId,
949
- itemOpen,
950
- menuId,
951
- menuLayout,
952
- reach,
953
- onSelectCategory
954
- }) {
955
- const [active, setActive] = useState(selectedCategoryId ?? categories[0]?.id);
956
- const activeRef = useRef(active);
957
- activeRef.current = active;
958
- const sections = useRef(/* @__PURE__ */ new Map());
959
- const wanted = useRef(void 0);
960
- const reading = useRef(false);
961
- const reachLatest = useCallback(
962
- (categoryId) => {
963
- wanted.current = categoryId;
964
- if (reading.current) {
965
- return;
966
- }
967
- reading.current = true;
968
- void (async () => {
969
- try {
970
- while (wanted.current) {
971
- const next = wanted.current;
972
- wanted.current = void 0;
973
- await reach(next);
974
- }
975
- } finally {
976
- reading.current = false;
977
- }
978
- })();
979
- },
980
- [reach]
981
- );
982
- useEffect(() => {
983
- if (itemOpen) {
984
- return;
985
- }
986
- const id = selectedCategoryId ?? categories[0]?.id;
987
- if (id) {
988
- setActive(id);
989
- void reach(id);
990
- }
991
- }, [menuId, selectedCategoryId, itemOpen, reach, categories]);
992
- useEffect(() => {
993
- if (itemOpen) {
994
- return;
995
- }
996
- let frame = 0;
997
- const select = () => {
998
- frame = 0;
999
- let id = categories[0]?.id;
1000
- for (const category of categories) {
1001
- const top = sections.current.get(category.id)?.getBoundingClientRect().top;
1002
- if (top === void 0) {
1003
- continue;
1004
- }
1005
- if (top > 200) {
1006
- break;
1007
- }
1008
- id = category.id;
1009
- }
1010
- if (window.scrollY + window.innerHeight >= document.documentElement.scrollHeight - 2) {
1011
- id = categories.at(-1)?.id ?? id;
1012
- }
1013
- if (id && id !== activeRef.current) {
1014
- setActive(id);
1015
- reachLatest(id);
1016
- }
1017
- };
1018
- const onScroll = () => {
1019
- if (!frame) {
1020
- frame = requestAnimationFrame(select);
1021
- }
1022
- };
1023
- window.addEventListener("scroll", onScroll, { passive: true });
1024
- return () => {
1025
- window.removeEventListener("scroll", onScroll);
1026
- cancelAnimationFrame(frame);
1027
- };
1028
- }, [categories, itemOpen, reachLatest]);
1029
- const selectCategory = useCallback(
1030
- (id) => {
1031
- setActive(id);
1032
- onSelectCategory(id);
1033
- sections.current.get(id)?.scrollIntoView({ block: "start" });
1034
- void reach(id);
1035
- },
1036
- [onSelectCategory, reach]
1037
- );
1038
- const previousLayout = useRef(menuLayout);
1039
- useEffect(() => {
1040
- if (previousLayout.current !== menuLayout && active) {
1041
- sections.current.get(active)?.scrollIntoView({ block: "start" });
1042
- }
1043
- previousLayout.current = menuLayout;
1044
- }, [menuLayout, active]);
1045
- const focusCategory = useCallback((id) => {
1046
- sections.current.get(id)?.querySelector("h3")?.focus();
1047
- }, []);
1048
- return {
1049
- active,
1050
- sections,
1051
- selectCategory,
1052
- focusCategory
1053
- };
1054
- }
1055
- function useItemOpener({
1056
- navigation,
1057
- source,
1058
- clearSearch
1059
- }) {
1060
- const searchOverlay = useOverlay("catalogue_search", "search");
1061
- const [pendingItem, setPendingItem] = useState();
1062
- const open = useCallback(
1063
- async (item) => {
1064
- if (searchOverlay.isOpen) {
1065
- setPendingItem(item);
1066
- searchOverlay.close();
1067
- return;
1068
- }
1069
- const placement = item.placements?.find((value) => value.menuId === source?.id) ?? item.placements?.[0];
1070
- const menuId = placement?.menuId ?? source?.id;
1071
- if (menuId) {
1072
- clearSearch();
1073
- await navigation.openItem({
1074
- itemId: item.id,
1075
- item,
1076
- menuId,
1077
- ...placement ? { categoryId: placement.categoryId } : {}
1078
- });
1079
- }
1080
- },
1081
- [clearSearch, navigation, searchOverlay, source]
1082
- );
1083
- useEffect(() => {
1084
- if (pendingItem && !searchOverlay.isOpen) {
1085
- const frame = requestAnimationFrame(() => {
1086
- setPendingItem(void 0);
1087
- void open(pendingItem);
1088
- });
1089
- return () => cancelAnimationFrame(frame);
1090
- }
1091
- }, [pendingItem, searchOverlay.isOpen, open]);
1092
- return open;
1093
- }
1094
- function useSearchSource(menu, enabled) {
1095
- const client = useZappie();
1096
- const [query, setQuery] = useState("");
1097
- const [composing, setComposing] = useState(false);
1098
- const [attempt, setAttempt] = useState(0);
1099
- const [cursor, setCursor] = useState();
1100
- const [remote, setRemote] = useState({ query: "" });
1101
- const index = useMemo(() => createSearchIndex(menu), [menu]);
1102
- const local = useMemo(() => index(query), [index, query]);
1103
- const hasLocalItems = local.some((result) => result.type === "item");
1104
- useEffect(() => {
1105
- if (!enabled || composing || !query.trim() || hasLocalItems) {
1106
- return;
1107
- }
1108
- const abort = new AbortController();
1109
- const timer = setTimeout(() => {
1110
- setRemote((previous) => ({
1111
- ...cursor && previous.query === query ? previous : {},
1112
- query,
1113
- loading: true
1114
- }));
1115
- void client.menu.search(query, {
1116
- branch: menu.branchId,
1117
- signal: abort.signal,
1118
- ...cursor ? { cursor } : {}
1119
- }).then(
1120
- (page) => {
1121
- if (!abort.signal.aborted) {
1122
- setRemote((previous) => {
1123
- if (!cursor || previous.query !== query || !previous.page) {
1124
- return { query, page };
1125
- }
1126
- return {
1127
- query,
1128
- page: {
1129
- ...page,
1130
- menu: {
1131
- ...page.menu,
1132
- items: {
1133
- ...previous.page.menu.items,
1134
- ...page.menu.items
1135
- },
1136
- categories: [
1137
- ...new Map(
1138
- [
1139
- ...previous.page.menu.categories,
1140
- ...page.menu.categories
1141
- ].map((category) => [category.id, category])
1142
- ).values()
1143
- ]
1144
- }
1145
- }
1146
- };
1147
- });
1148
- }
1149
- },
1150
- () => {
1151
- if (!abort.signal.aborted) {
1152
- setRemote((previous) => ({
1153
- ...cursor && previous.query === query ? previous : {},
1154
- query,
1155
- loading: false,
1156
- error: "Search could not load. Try again."
1157
- }));
1158
- }
1159
- }
1160
- );
1161
- }, 500);
1162
- return () => {
1163
- clearTimeout(timer);
1164
- abort.abort();
1165
- };
1166
- }, [
1167
- client,
1168
- menu.branchId,
1169
- query,
1170
- enabled,
1171
- composing,
1172
- hasLocalItems,
1173
- attempt,
1174
- cursor
1175
- ]);
1176
- const current = !composing && remote.query === query && !hasLocalItems ? remote : void 0;
1177
- const results = useMemo(() => {
1178
- const values = [...local];
1179
- for (const item of Object.values(current?.page?.menu.items ?? {})) {
1180
- if (!values.some(
1181
- (result) => result.type === "item" && result.item.id === item.id
1182
- )) {
1183
- values.push({ type: "item", item, score: 0 });
1184
- }
1185
- }
1186
- for (const category of current?.page?.menu.categories ?? []) {
1187
- if (category.name.toLocaleLowerCase().includes(query.trim().toLocaleLowerCase()) && !values.some(
1188
- (result) => result.type === "category" && result.category.id === category.id
1189
- )) {
1190
- values.push({ type: "category", category, score: 0 });
1191
- }
1192
- }
1193
- return values;
1194
- }, [local, current?.page, query]);
1195
- return {
1196
- query,
1197
- setQuery: (value) => {
1198
- setCursor(void 0);
1199
- setQuery(value);
1200
- },
1201
- hasMore: Boolean(current?.page?.nextCursor),
1202
- loadMore: () => {
1203
- if (!current?.loading && current?.page?.nextCursor) {
1204
- setCursor(current.page.nextCursor);
1205
- }
1206
- },
1207
- source: {
1208
- results,
1209
- isLoading: current?.loading ?? false,
1210
- ...current?.error ? { error: current.error } : {},
1211
- retry: () => setAttempt((value) => value + 1),
1212
- onCompositionChange: setComposing
1213
- }
1214
- };
1215
- }
3
+ // src/catalogue/catalogue.tsx
4
+ import { useOverlay } from "@zappie/foundations";
5
+ import {
6
+ useCart,
7
+ useCartCatalogue,
8
+ useStore,
9
+ useZappie
10
+ } from "@zappie/sdk/react";
11
+ import { useCallback, useState } from "react";
12
+ import { ThemeClassProvider } from "./cart/theme-class.js";
13
+ import { useBaseHostBridge } from "./host-bridge.js";
14
+ import { useCatalogueNavigation } from "./navigation.js";
15
+ import { CatalogueCart } from "./catalogue/catalogue-cart.js";
16
+ import { CatalogueHeader } from "./catalogue/catalogue-header.js";
17
+ import { CatalogueSearch } from "./catalogue/catalogue-search.js";
18
+ import { CategoryNavigation } from "./catalogue/category-navigation.js";
19
+ import { CategorySection } from "./catalogue/category-section.js";
20
+ import { InfoBanners } from "./catalogue/info-banners.js";
21
+ import { useCatalogueData } from "./catalogue/use-catalogue-data.js";
22
+ import { useCategoryScroll } from "./catalogue/use-category-scroll.js";
23
+ import { useItemOpener } from "./catalogue/use-item-opener.js";
24
+ import { useSearchSource } from "./catalogue/use-search-source.js";
25
+ import { jsx, jsxs } from "react/jsx-runtime";
1216
26
  function Catalogue({
1217
27
  initialMenu,
1218
28
  resolveStrategy,
@@ -1383,7 +193,7 @@ function Catalogue({
1383
193
  }
1384
194
  ) });
1385
195
  }
1386
-
1387
- export { Catalogue };
196
+ export {
197
+ Catalogue
198
+ };
1388
199
  //# sourceMappingURL=catalogue.js.map
1389
- //# sourceMappingURL=catalogue.js.map