@zappie/theme-base 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +26 -53
  3. package/dist/address.js +99 -2
  4. package/dist/address.js.map +7 -1
  5. package/dist/cart/address-sheet.js +143 -0
  6. package/dist/cart/address-sheet.js.map +7 -0
  7. package/dist/cart/cart-issues.js +72 -0
  8. package/dist/cart/cart-issues.js.map +7 -0
  9. package/dist/cart/cart-line-groups.js +34 -0
  10. package/dist/cart/cart-line-groups.js.map +7 -0
  11. package/dist/{chunk-FB5DRCU7.js → cart/cart-line.js} +9 -70
  12. package/dist/cart/cart-line.js.map +7 -0
  13. package/dist/cart/cart-lines.js +27 -0
  14. package/dist/cart/cart-lines.js.map +7 -0
  15. package/dist/cart/cart-schedule.js +24 -0
  16. package/dist/cart/cart-schedule.js.map +7 -0
  17. package/dist/cart/cart-sheet.js +35 -0
  18. package/dist/cart/cart-sheet.js.map +7 -0
  19. package/dist/cart/checkout-cta.js +81 -0
  20. package/dist/cart/checkout-cta.js.map +7 -0
  21. package/dist/cart/checkout-state.js +74 -0
  22. package/dist/cart/checkout-state.js.map +7 -0
  23. package/dist/cart/clear-cart.js +44 -0
  24. package/dist/cart/clear-cart.js.map +7 -0
  25. package/dist/cart/customer-details.js +70 -0
  26. package/dist/cart/customer-details.js.map +7 -0
  27. package/dist/cart/delivery-distance.js +22 -0
  28. package/dist/cart/delivery-distance.js.map +7 -0
  29. package/dist/cart/empty-cart.js +14 -0
  30. package/dist/cart/empty-cart.js.map +7 -0
  31. package/dist/cart/fulfilment-panel.js +83 -0
  32. package/dist/cart/fulfilment-panel.js.map +7 -0
  33. package/dist/cart/line-editor.js +35 -0
  34. package/dist/cart/line-editor.js.map +7 -0
  35. package/dist/cart/line-options.js +96 -0
  36. package/dist/cart/line-options.js.map +7 -0
  37. package/dist/cart/loading.js +17 -0
  38. package/dist/cart/loading.js.map +7 -0
  39. package/dist/cart/promo-sheet.js +103 -0
  40. package/dist/cart/promo-sheet.js.map +7 -0
  41. package/dist/cart/region-picker.js +40 -0
  42. package/dist/cart/region-picker.js.map +7 -0
  43. package/dist/cart/rewards-sheet.js +86 -0
  44. package/dist/cart/rewards-sheet.js.map +7 -0
  45. package/dist/cart/schedule-sheet.js +87 -0
  46. package/dist/cart/schedule-sheet.js.map +7 -0
  47. package/dist/{chunk-JFEI2OUZ.js → cart/theme-class.js} +7 -5
  48. package/dist/cart/theme-class.js.map +7 -0
  49. package/dist/cart/totals.js +81 -0
  50. package/dist/cart/totals.js.map +7 -0
  51. package/dist/cart/use-address-selection.js +130 -0
  52. package/dist/cart/use-address-selection.js.map +7 -0
  53. package/dist/cart.js +21 -1069
  54. package/dist/cart.js.map +7 -1
  55. package/dist/catalogue/catalogue-cart.js +25 -0
  56. package/dist/catalogue/catalogue-cart.js.map +7 -0
  57. package/dist/catalogue/catalogue-header.js +88 -0
  58. package/dist/catalogue/catalogue-header.js.map +7 -0
  59. package/dist/catalogue/catalogue-pages.js +68 -0
  60. package/dist/catalogue/catalogue-pages.js.map +7 -0
  61. package/dist/catalogue/catalogue-search.js +89 -0
  62. package/dist/catalogue/catalogue-search.js.map +7 -0
  63. package/dist/catalogue/category-navigation.js +98 -0
  64. package/dist/catalogue/category-navigation.js.map +7 -0
  65. package/dist/catalogue/category-section.js +113 -0
  66. package/dist/catalogue/category-section.js.map +7 -0
  67. package/dist/catalogue/info-banners.js +148 -0
  68. package/dist/catalogue/info-banners.js.map +7 -0
  69. package/dist/catalogue/item-tile.js +55 -0
  70. package/dist/catalogue/item-tile.js.map +7 -0
  71. package/dist/catalogue/loader.js +136 -0
  72. package/dist/catalogue/loader.js.map +7 -0
  73. package/dist/{chunk-USSLDBDY.js → catalogue/presentation.js} +12 -9
  74. package/dist/catalogue/presentation.js.map +7 -0
  75. package/dist/catalogue/saved-catalogue-sync.js +115 -0
  76. package/dist/catalogue/saved-catalogue-sync.js.map +7 -0
  77. package/dist/catalogue/types.js +1 -0
  78. package/dist/catalogue/types.js.map +7 -0
  79. package/dist/catalogue/use-catalogue-data.js +88 -0
  80. package/dist/catalogue/use-catalogue-data.js.map +7 -0
  81. package/dist/catalogue/use-category-scroll.js +115 -0
  82. package/dist/catalogue/use-category-scroll.js.map +7 -0
  83. package/dist/catalogue/use-item-opener.js +46 -0
  84. package/dist/catalogue/use-item-opener.js.map +7 -0
  85. package/dist/catalogue/use-search-source.js +132 -0
  86. package/dist/catalogue/use-search-source.js.map +7 -0
  87. package/dist/catalogue.js +26 -1216
  88. package/dist/catalogue.js.map +7 -1
  89. package/dist/checkout.js +149 -2
  90. package/dist/checkout.js.map +7 -1
  91. package/dist/host-bridge.js +22 -2
  92. package/dist/host-bridge.js.map +7 -1
  93. package/dist/index.js +3 -3
  94. package/dist/index.js.map +7 -1
  95. package/dist/item/configurator-commit.js +15 -0
  96. package/dist/item/configurator-commit.js.map +7 -0
  97. package/dist/item/configurator-draft.js +63 -0
  98. package/dist/item/configurator-draft.js.map +7 -0
  99. package/dist/item/configurator.js +135 -0
  100. package/dist/item/configurator.js.map +7 -0
  101. package/dist/item/note.js +65 -0
  102. package/dist/item/note.js.map +7 -0
  103. package/dist/item/variant-status.js +23 -0
  104. package/dist/item/variant-status.js.map +7 -0
  105. package/dist/item-frame.js +60 -3
  106. package/dist/item-frame.js.map +7 -1
  107. package/dist/item.js +11 -11
  108. package/dist/item.js.map +7 -1
  109. package/dist/navigation.js +39 -2
  110. package/dist/navigation.js.map +7 -1
  111. package/dist/url-navigation-state.js +61 -0
  112. package/dist/url-navigation-state.js.map +7 -0
  113. package/dist/{chunk-ILOCSCZL.js → url-navigation.js} +12 -89
  114. package/dist/url-navigation.js.map +7 -0
  115. package/package.json +8 -7
  116. package/dist/chunk-2MV6KU3R.js +0 -352
  117. package/dist/chunk-2MV6KU3R.js.map +0 -1
  118. package/dist/chunk-FB5DRCU7.js.map +0 -1
  119. package/dist/chunk-IG63ONID.js +0 -139
  120. package/dist/chunk-IG63ONID.js.map +0 -1
  121. package/dist/chunk-ILOCSCZL.js.map +0 -1
  122. package/dist/chunk-JFEI2OUZ.js.map +0 -1
  123. package/dist/chunk-NTJONY3N.js +0 -95
  124. package/dist/chunk-NTJONY3N.js.map +0 -1
  125. package/dist/chunk-QWST2TA2.js +0 -22
  126. package/dist/chunk-QWST2TA2.js.map +0 -1
  127. package/dist/chunk-USSLDBDY.js.map +0 -1
  128. package/dist/chunk-VIAJ27YC.js +0 -59
  129. package/dist/chunk-VIAJ27YC.js.map +0 -1
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/cart-line.tsx"],
4
+ "sourcesContent": ["import { Cart, Money, Overlay, Quantity } from \"@zappie/foundations\";\nimport type { CartLine as Line } from \"@zappie/sdk\";\nimport { useCart } from \"@zappie/sdk/react\";\nimport { LineEditor } from \"./line-editor\";\nexport function CartLine({ line }: { line: Line }) {\n const cart = useCart();\n const invalid = cart.issues.some(\n (issue) => issue.lineId === line.id && issue.severity === \"blocking\",\n );\n return (\n <Cart.Line line={line} className=\"z-base-line\">\n {({ item }) => (\n <>\n <div className=\"z-base-line-heading\">\n <h3>{line.name}</h3>\n {item && !invalid ? (\n <Money value={line.lineSubtotal} />\n ) : (\n <span>Price unavailable</span>\n )}\n </div>\n <ul className=\"z-base-line-options\">\n {line.choices.map((selection) => {\n const group = item?.optionGroups.find(\n (group) => group.id === selection.groupId,\n );\n const choice = group?.choices.find(\n (choice) => choice.id === selection.choiceId,\n );\n return (\n <li key={`${selection.groupId}:${selection.choiceId}`}>\n {choice?.name ?? \"Unavailable option\"}\n {selection.quantity > 1 ? ` \u00D7 ${selection.quantity}` : \"\"}\n </li>\n );\n })}\n {Object.entries(line.inputs).map(([id, value]) => (\n <li key={id}>\n {item?.optionGroups.find((group) => group.id === id)?.name ??\n \"Details\"}\n : {value}\n </li>\n ))}\n </ul>\n {line.note && <p className=\"z-base-muted\">{line.note}</p>}\n <div className=\"z-base-line-actions\">\n <Cart.Quantity\n lineId={line.id}\n disabled={invalid}\n className=\"z-base-quantity\"\n >\n <Quantity.Decrement aria-label={`Decrease ${line.name} quantity`}>\n \u2212\n </Quantity.Decrement>\n <Quantity.Value aria-label={`${line.name} quantity`} />\n <Quantity.Increment aria-label={`Increase ${line.name} quantity`}>\n +\n </Quantity.Increment>\n </Cart.Quantity>\n <Overlay.Root\n param=\"cart_edit\"\n id={line.id}\n presentation={{ base: \"sheet\", lg: \"dialog\" }}\n >\n <Overlay.Trigger\n className=\"z-base-button-secondary\"\n disabled={!item}\n aria-label={`Edit ${line.name}`}\n >\n Edit\n </Overlay.Trigger>\n {item && <LineEditor line={line} item={item} />}\n </Overlay.Root>\n <Cart.Remove\n lineId={line.id}\n className=\"z-base-button-secondary\"\n aria-label={`Remove ${line.name}`}\n >\n Remove\n </Cart.Remove>\n </div>\n </>\n )}\n </Cart.Line>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,MAAM,OAAO,SAAS,gBAAgB;AAE/C,SAAS,eAAe;AACxB,SAAS,kBAAkB;AASnB,mBAEI,KADF,YADF;AARD,SAAS,SAAS,EAAE,KAAK,GAAmB;AACjD,QAAM,OAAO,QAAQ;AACrB,QAAM,UAAU,KAAK,OAAO;AAAA,IAC1B,CAAC,UAAU,MAAM,WAAW,KAAK,MAAM,MAAM,aAAa;AAAA,EAC5D;AACA,SACE,oBAAC,KAAK,MAAL,EAAU,MAAY,WAAU,eAC9B,WAAC,EAAE,KAAK,MACP,iCACE;AAAA,yBAAC,SAAI,WAAU,uBACb;AAAA,0BAAC,QAAI,eAAK,MAAK;AAAA,MACd,QAAQ,CAAC,UACR,oBAAC,SAAM,OAAO,KAAK,cAAc,IAEjC,oBAAC,UAAK,+BAAiB;AAAA,OAE3B;AAAA,IACA,qBAAC,QAAG,WAAU,uBACX;AAAA,WAAK,QAAQ,IAAI,CAAC,cAAc;AAC/B,cAAM,QAAQ,MAAM,aAAa;AAAA,UAC/B,CAACA,WAAUA,OAAM,OAAO,UAAU;AAAA,QACpC;AACA,cAAM,SAAS,OAAO,QAAQ;AAAA,UAC5B,CAACC,YAAWA,QAAO,OAAO,UAAU;AAAA,QACtC;AACA,eACE,qBAAC,QACE;AAAA,kBAAQ,QAAQ;AAAA,UAChB,UAAU,WAAW,IAAI,SAAM,UAAU,QAAQ,KAAK;AAAA,aAFhD,GAAG,UAAU,OAAO,IAAI,UAAU,QAAQ,EAGnD;AAAA,MAEJ,CAAC;AAAA,MACA,OAAO,QAAQ,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,MAC1C,qBAAC,QACE;AAAA,cAAM,aAAa,KAAK,CAAC,UAAU,MAAM,OAAO,EAAE,GAAG,QACpD;AAAA,QAAU;AAAA,QACT;AAAA,WAHI,EAIT,CACD;AAAA,OACH;AAAA,IACC,KAAK,QAAQ,oBAAC,OAAE,WAAU,gBAAgB,eAAK,MAAK;AAAA,IACrD,qBAAC,SAAI,WAAU,uBACb;AAAA;AAAA,QAAC,KAAK;AAAA,QAAL;AAAA,UACC,QAAQ,KAAK;AAAA,UACb,UAAU;AAAA,UACV,WAAU;AAAA,UAEV;AAAA,gCAAC,SAAS,WAAT,EAAmB,cAAY,YAAY,KAAK,IAAI,aAAa,oBAElE;AAAA,YACA,oBAAC,SAAS,OAAT,EAAe,cAAY,GAAG,KAAK,IAAI,aAAa;AAAA,YACrD,oBAAC,SAAS,WAAT,EAAmB,cAAY,YAAY,KAAK,IAAI,aAAa,eAElE;AAAA;AAAA;AAAA,MACF;AAAA,MACA;AAAA,QAAC,QAAQ;AAAA,QAAR;AAAA,UACC,OAAM;AAAA,UACN,IAAI,KAAK;AAAA,UACT,cAAc,EAAE,MAAM,SAAS,IAAI,SAAS;AAAA,UAE5C;AAAA;AAAA,cAAC,QAAQ;AAAA,cAAR;AAAA,gBACC,WAAU;AAAA,gBACV,UAAU,CAAC;AAAA,gBACX,cAAY,QAAQ,KAAK,IAAI;AAAA,gBAC9B;AAAA;AAAA,YAED;AAAA,YACC,QAAQ,oBAAC,cAAW,MAAY,MAAY;AAAA;AAAA;AAAA,MAC/C;AAAA,MACA;AAAA,QAAC,KAAK;AAAA,QAAL;AAAA,UACC,QAAQ,KAAK;AAAA,UACb,WAAU;AAAA,UACV,cAAY,UAAU,KAAK,IAAI;AAAA,UAChC;AAAA;AAAA,MAED;AAAA,OACF;AAAA,KACF,GAEJ;AAEJ;",
6
+ "names": ["group", "choice"]
7
+ }
@@ -0,0 +1,27 @@
1
+ // src/cart/cart-lines.tsx
2
+ import { useCart, useCartCatalogue } from "@zappie/sdk/react";
3
+ import { CartLine } from "./cart-line.js";
4
+ import { groupCartLinesByMenu } from "./cart-line-groups.js";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ function CartLines() {
7
+ const { lines } = useCart();
8
+ const catalogue = useCartCatalogue();
9
+ const groups = groupCartLinesByMenu(lines, catalogue);
10
+ const grouped = (catalogue?.menus?.length ?? 0) > 1;
11
+ return /* @__PURE__ */ jsx("section", { "aria-label": "Cart items", className: "z-base-lines", children: groups.map((group) => /* @__PURE__ */ jsxs(
12
+ "section",
13
+ {
14
+ "aria-label": group.menuName ?? "Other items",
15
+ className: "z-base-line-group",
16
+ children: [
17
+ grouped && /* @__PURE__ */ jsx("h2", { children: group.menuName ?? "Other items" }),
18
+ group.lines.map((line) => /* @__PURE__ */ jsx(CartLine, { line }, line.id))
19
+ ]
20
+ },
21
+ group.menuId
22
+ )) });
23
+ }
24
+ export {
25
+ CartLines
26
+ };
27
+ //# sourceMappingURL=cart-lines.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/cart-lines.tsx"],
4
+ "sourcesContent": ["import { useCart, useCartCatalogue } from \"@zappie/sdk/react\";\nimport { CartLine } from \"./cart-line\";\nimport { groupCartLinesByMenu } from \"./cart-line-groups\";\nexport function CartLines() {\n const { lines } = useCart();\n const catalogue = useCartCatalogue();\n const groups = groupCartLinesByMenu(lines, catalogue);\n const grouped = (catalogue?.menus?.length ?? 0) > 1;\n return (\n <section aria-label=\"Cart items\" className=\"z-base-lines\">\n {groups.map((group) => (\n <section\n key={group.menuId}\n aria-label={group.menuName ?? \"Other items\"}\n className=\"z-base-line-group\"\n >\n {grouped && <h2>{group.menuName ?? \"Other items\"}</h2>}\n {group.lines.map((line) => (\n <CartLine key={line.id} line={line} />\n ))}\n </section>\n ))}\n </section>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,SAAS,wBAAwB;AAC1C,SAAS,gBAAgB;AACzB,SAAS,4BAA4B;AAS7B,SAKc,KALd;AARD,SAAS,YAAY;AAC1B,QAAM,EAAE,MAAM,IAAI,QAAQ;AAC1B,QAAM,YAAY,iBAAiB;AACnC,QAAM,SAAS,qBAAqB,OAAO,SAAS;AACpD,QAAM,WAAW,WAAW,OAAO,UAAU,KAAK;AAClD,SACE,oBAAC,aAAQ,cAAW,cAAa,WAAU,gBACxC,iBAAO,IAAI,CAAC,UACX;AAAA,IAAC;AAAA;AAAA,MAEC,cAAY,MAAM,YAAY;AAAA,MAC9B,WAAU;AAAA,MAET;AAAA,mBAAW,oBAAC,QAAI,gBAAM,YAAY,eAAc;AAAA,QAChD,MAAM,MAAM,IAAI,CAAC,SAChB,oBAAC,YAAuB,QAAT,KAAK,EAAgB,CACrC;AAAA;AAAA;AAAA,IAPI,MAAM;AAAA,EAQb,CACD,GACH;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,24 @@
1
+ // src/cart/cart-schedule.ts
2
+ function cartScheduleLimits(menu, lines, maxDays) {
3
+ const sections = (menu?.menus ?? []).filter(
4
+ (section) => section.schedule?.preorder && lines.some(
5
+ (line) => line.menuId ? line.menuId === section.id : section.categoryIds.some(
6
+ (id) => menu?.categories.find((category) => category.id === id)?.itemIds.includes(line.itemId)
7
+ )
8
+ )
9
+ );
10
+ const notice = Math.max(
11
+ 0,
12
+ ...sections.map((section) => section.schedule?.preorderNoticeHours ?? 0)
13
+ );
14
+ const horizons = sections.map((section) => section.schedule?.preorderMaxDays).filter((days) => typeof days === "number" && days > 0);
15
+ const limit = horizons.length > 0 ? Math.min(maxDays ?? Number.POSITIVE_INFINITY, ...horizons) : maxDays;
16
+ return {
17
+ noticeMinutes: notice * 60,
18
+ maxDays: limit === void 0 ? void 0 : Math.max(1, Math.min(90, limit))
19
+ };
20
+ }
21
+ export {
22
+ cartScheduleLimits
23
+ };
24
+ //# sourceMappingURL=cart-schedule.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/cart-schedule.ts"],
4
+ "sourcesContent": ["import type { CartLine, Menu } from \"@zappie/sdk\";\n/**\n * Pre-order limits for the menus the cart's lines come from. Schedule reads a\n * menu's notice only from a single-menu catalogue; with several menus the\n * tightest notice and horizon among the cart's pre-order menus apply.\n */\nexport function cartScheduleLimits(\n menu: Menu | undefined,\n lines: readonly CartLine[],\n maxDays: number | undefined,\n): { noticeMinutes: number; maxDays: number | undefined } {\n const sections = (menu?.menus ?? []).filter(\n (section) =>\n section.schedule?.preorder &&\n lines.some((line) =>\n line.menuId\n ? line.menuId === section.id\n : section.categoryIds.some((id) =>\n menu?.categories\n .find((category) => category.id === id)\n ?.itemIds.includes(line.itemId),\n ),\n ),\n );\n const notice = Math.max(\n 0,\n ...sections.map((section) => section.schedule?.preorderNoticeHours ?? 0),\n );\n const horizons = sections\n .map((section) => section.schedule?.preorderMaxDays)\n .filter((days): days is number => typeof days === \"number\" && days > 0);\n const limit =\n horizons.length > 0\n ? Math.min(maxDays ?? Number.POSITIVE_INFINITY, ...horizons)\n : maxDays;\n return {\n noticeMinutes: notice * 60,\n maxDays: limit === undefined ? undefined : Math.max(1, Math.min(90, limit)),\n };\n}\n"],
5
+ "mappings": ";AAMO,SAAS,mBACd,MACA,OACA,SACwD;AACxD,QAAM,YAAY,MAAM,SAAS,CAAC,GAAG;AAAA,IACnC,CAAC,YACC,QAAQ,UAAU,YAClB,MAAM;AAAA,MAAK,CAAC,SACV,KAAK,SACD,KAAK,WAAW,QAAQ,KACxB,QAAQ,YAAY;AAAA,QAAK,CAAC,OACxB,MAAM,WACH,KAAK,CAAC,aAAa,SAAS,OAAO,EAAE,GACpC,QAAQ,SAAS,KAAK,MAAM;AAAA,MAClC;AAAA,IACN;AAAA,EACJ;AACA,QAAM,SAAS,KAAK;AAAA,IAClB;AAAA,IACA,GAAG,SAAS,IAAI,CAAC,YAAY,QAAQ,UAAU,uBAAuB,CAAC;AAAA,EACzE;AACA,QAAM,WAAW,SACd,IAAI,CAAC,YAAY,QAAQ,UAAU,eAAe,EAClD,OAAO,CAAC,SAAyB,OAAO,SAAS,YAAY,OAAO,CAAC;AACxE,QAAM,QACJ,SAAS,SAAS,IACd,KAAK,IAAI,WAAW,OAAO,mBAAmB,GAAG,QAAQ,IACzD;AACN,SAAO;AAAA,IACL,eAAe,SAAS;AAAA,IACxB,SAAS,UAAU,SAAY,SAAY,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC;AAAA,EAC5E;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,35 @@
1
+ // src/cart/cart-sheet.tsx
2
+ import { Overlay, useOverlay } from "@zappie/foundations";
3
+ import { useThemeClass } from "./theme-class.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ function CartSheet({
6
+ id,
7
+ title,
8
+ trigger,
9
+ children
10
+ }) {
11
+ const rootClass = useThemeClass("z-base-cart z-base-editor");
12
+ const overlay = useOverlay("cart_sheet", id);
13
+ return /* @__PURE__ */ jsxs(
14
+ Overlay.Root,
15
+ {
16
+ param: "cart_sheet",
17
+ id,
18
+ presentation: { base: "sheet", lg: "dialog" },
19
+ children: [
20
+ /* @__PURE__ */ jsx(Overlay.Trigger, { className: "z-base-button-secondary", children: trigger }),
21
+ /* @__PURE__ */ jsxs(Overlay.Content, { "data-zappie-theme": "base", className: rootClass, children: [
22
+ /* @__PURE__ */ jsxs("header", { className: "z-base-cart-header", children: [
23
+ /* @__PURE__ */ jsx(Overlay.Title, { children: title }),
24
+ /* @__PURE__ */ jsx(Overlay.Close, { className: "z-base-button-secondary", children: "Cancel" })
25
+ ] }),
26
+ overlay.isOpen && /* @__PURE__ */ jsx("div", { className: "z-base-cart-body", children })
27
+ ] })
28
+ ]
29
+ }
30
+ );
31
+ }
32
+ export {
33
+ CartSheet
34
+ };
35
+ //# sourceMappingURL=cart-sheet.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/cart-sheet.tsx"],
4
+ "sourcesContent": ["import { Overlay, useOverlay } from \"@zappie/foundations\";\nimport type { ReactNode } from \"react\";\nimport { useThemeClass } from \"./theme-class\";\nexport function CartSheet({\n id,\n title,\n trigger,\n children,\n}: {\n id: string;\n title: string;\n trigger: string;\n children: ReactNode;\n}) {\n const rootClass = useThemeClass(\"z-base-cart z-base-editor\");\n const overlay = useOverlay(\"cart_sheet\", id);\n return (\n <Overlay.Root\n param=\"cart_sheet\"\n id={id}\n presentation={{ base: \"sheet\", lg: \"dialog\" }}\n >\n <Overlay.Trigger className=\"z-base-button-secondary\">\n {trigger}\n </Overlay.Trigger>\n <Overlay.Content data-zappie-theme=\"base\" className={rootClass}>\n <header className=\"z-base-cart-header\">\n <Overlay.Title>{title}</Overlay.Title>\n <Overlay.Close className=\"z-base-button-secondary\">\n Cancel\n </Overlay.Close>\n </header>\n {overlay.isOpen && <div className=\"z-base-cart-body\">{children}</div>}\n </Overlay.Content>\n </Overlay.Root>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,SAAS,kBAAkB;AAEpC,SAAS,qBAAqB;AAoBxB,cAIE,YAJF;AAnBC,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,YAAY,cAAc,2BAA2B;AAC3D,QAAM,UAAU,WAAW,cAAc,EAAE;AAC3C,SACE;AAAA,IAAC,QAAQ;AAAA,IAAR;AAAA,MACC,OAAM;AAAA,MACN;AAAA,MACA,cAAc,EAAE,MAAM,SAAS,IAAI,SAAS;AAAA,MAE5C;AAAA,4BAAC,QAAQ,SAAR,EAAgB,WAAU,2BACxB,mBACH;AAAA,QACA,qBAAC,QAAQ,SAAR,EAAgB,qBAAkB,QAAO,WAAW,WACnD;AAAA,+BAAC,YAAO,WAAU,sBAChB;AAAA,gCAAC,QAAQ,OAAR,EAAe,iBAAM;AAAA,YACtB,oBAAC,QAAQ,OAAR,EAAc,WAAU,2BAA0B,oBAEnD;AAAA,aACF;AAAA,UACC,QAAQ,UAAU,oBAAC,SAAI,WAAU,oBAAoB,UAAS;AAAA,WACjE;AAAA;AAAA;AAAA,EACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,81 @@
1
+ // src/cart/checkout-cta.tsx
2
+ import { isContactPhoneValid } from "@zappie/sdk/checkout";
3
+ import { useCart } from "@zappie/sdk/react";
4
+ import { useState } from "react";
5
+ import { useCheckoutHandoff } from "../checkout.js";
6
+ import { useBaseHostBridge } from "../host-bridge.js";
7
+ import { checkoutButtonState } from "./checkout-state.js";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ function CheckoutCta({
10
+ totalsStatus,
11
+ contactPhone
12
+ }) {
13
+ const cart = useCart();
14
+ const bridge = useBaseHostBridge();
15
+ const handoff = useCheckoutHandoff();
16
+ const [busy, setBusy] = useState(false);
17
+ const [error, setError] = useState(null);
18
+ const showContactPhone = Boolean(
19
+ contactPhone && handoff.contactPhone && handoff.customer
20
+ );
21
+ const buttonInput = {
22
+ busy,
23
+ cartState: cart.state,
24
+ totalsStatus,
25
+ fulfilment: cart.fulfilment,
26
+ customer: handoff.customer,
27
+ contactPhoneValid: !showContactPhone || isContactPhoneValid(contactPhone?.value ?? "")
28
+ };
29
+ if (bridge.deliveryDistance) {
30
+ buttonInput.deliveryDistance = bridge.deliveryDistance;
31
+ }
32
+ const button = checkoutButtonState(buttonInput);
33
+ const checkout = async () => {
34
+ if (!button.enabled) {
35
+ return;
36
+ }
37
+ if (button.status === "phone") {
38
+ contactPhone?.touch();
39
+ return;
40
+ }
41
+ setBusy(true);
42
+ setError(null);
43
+ try {
44
+ if (!handoff.customer) {
45
+ await handoff.signIn();
46
+ } else {
47
+ const payload = cart.actions.toCheckoutPayload();
48
+ if (showContactPhone && contactPhone) {
49
+ await handoff.pay(payload, { contactPhone: contactPhone.value });
50
+ } else {
51
+ await handoff.pay(payload);
52
+ }
53
+ }
54
+ } catch (error2) {
55
+ setError(
56
+ error2 instanceof Error ? error2.message : "Unable to continue to checkout"
57
+ );
58
+ } finally {
59
+ setBusy(false);
60
+ }
61
+ };
62
+ return /* @__PURE__ */ jsxs("div", { className: "z-base-checkout", children: [
63
+ error && /* @__PURE__ */ jsx("p", { role: "alert", children: error }),
64
+ /* @__PURE__ */ jsx(
65
+ "button",
66
+ {
67
+ type: "button",
68
+ className: "z-base-button",
69
+ disabled: !button.enabled,
70
+ onClick: () => {
71
+ void checkout();
72
+ },
73
+ children: button.label
74
+ }
75
+ )
76
+ ] });
77
+ }
78
+ export {
79
+ CheckoutCta
80
+ };
81
+ //# sourceMappingURL=checkout-cta.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/checkout-cta.tsx"],
4
+ "sourcesContent": ["import type { TotalsState } from \"@zappie/foundations\";\nimport { isContactPhoneValid } from \"@zappie/sdk/checkout\";\nimport { useCart } from \"@zappie/sdk/react\";\nimport { useState } from \"react\";\nimport { useCheckoutHandoff } from \"../checkout\";\nimport { useBaseHostBridge } from \"../host-bridge\";\nimport { checkoutButtonState } from \"./checkout-state\";\nimport type { ContactPhoneState } from \"./customer-details\";\nexport function CheckoutCta({\n totalsStatus,\n contactPhone,\n}: {\n totalsStatus: TotalsState[\"status\"];\n contactPhone?: ContactPhoneState;\n}) {\n const cart = useCart();\n const bridge = useBaseHostBridge();\n const handoff = useCheckoutHandoff();\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const showContactPhone = Boolean(\n contactPhone && handoff.contactPhone && handoff.customer,\n );\n const buttonInput: Parameters<typeof checkoutButtonState>[0] = {\n busy,\n cartState: cart.state,\n totalsStatus,\n fulfilment: cart.fulfilment,\n customer: handoff.customer,\n contactPhoneValid:\n !showContactPhone || isContactPhoneValid(contactPhone?.value ?? \"\"),\n };\n if (bridge.deliveryDistance) {\n buttonInput.deliveryDistance = bridge.deliveryDistance;\n }\n const button = checkoutButtonState(buttonInput);\n const checkout = async () => {\n if (!button.enabled) {\n return;\n }\n if (button.status === \"phone\") {\n contactPhone?.touch();\n return;\n }\n setBusy(true);\n setError(null);\n try {\n if (!handoff.customer) {\n await handoff.signIn();\n } else {\n const payload = cart.actions.toCheckoutPayload();\n if (showContactPhone && contactPhone) {\n await handoff.pay(payload, { contactPhone: contactPhone.value });\n } else {\n await handoff.pay(payload);\n }\n }\n } catch (error) {\n setError(\n error instanceof Error\n ? error.message\n : \"Unable to continue to checkout\",\n );\n } finally {\n setBusy(false);\n }\n };\n return (\n <div className=\"z-base-checkout\">\n {error && <p role=\"alert\">{error}</p>}\n <button\n type=\"button\"\n className=\"z-base-button\"\n disabled={!button.enabled}\n onClick={() => {\n void checkout();\n }}\n >\n {button.label}\n </button>\n </div>\n );\n}\n"],
5
+ "mappings": ";AACA,SAAS,2BAA2B;AACpC,SAAS,eAAe;AACxB,SAAS,gBAAgB;AACzB,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AA8DhC,SACY,KADZ;AA5DG,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AACF,GAGG;AACD,QAAM,OAAO,QAAQ;AACrB,QAAM,SAAS,kBAAkB;AACjC,QAAM,UAAU,mBAAmB;AACnC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,mBAAmB;AAAA,IACvB,gBAAgB,QAAQ,gBAAgB,QAAQ;AAAA,EAClD;AACA,QAAM,cAAyD;AAAA,IAC7D;AAAA,IACA,WAAW,KAAK;AAAA,IAChB;AAAA,IACA,YAAY,KAAK;AAAA,IACjB,UAAU,QAAQ;AAAA,IAClB,mBACE,CAAC,oBAAoB,oBAAoB,cAAc,SAAS,EAAE;AAAA,EACtE;AACA,MAAI,OAAO,kBAAkB;AAC3B,gBAAY,mBAAmB,OAAO;AAAA,EACxC;AACA,QAAM,SAAS,oBAAoB,WAAW;AAC9C,QAAM,WAAW,YAAY;AAC3B,QAAI,CAAC,OAAO,SAAS;AACnB;AAAA,IACF;AACA,QAAI,OAAO,WAAW,SAAS;AAC7B,oBAAc,MAAM;AACpB;AAAA,IACF;AACA,YAAQ,IAAI;AACZ,aAAS,IAAI;AACb,QAAI;AACF,UAAI,CAAC,QAAQ,UAAU;AACrB,cAAM,QAAQ,OAAO;AAAA,MACvB,OAAO;AACL,cAAM,UAAU,KAAK,QAAQ,kBAAkB;AAC/C,YAAI,oBAAoB,cAAc;AACpC,gBAAM,QAAQ,IAAI,SAAS,EAAE,cAAc,aAAa,MAAM,CAAC;AAAA,QACjE,OAAO;AACL,gBAAM,QAAQ,IAAI,OAAO;AAAA,QAC3B;AAAA,MACF;AAAA,IACF,SAASA,QAAO;AACd;AAAA,QACEA,kBAAiB,QACbA,OAAM,UACN;AAAA,MACN;AAAA,IACF,UAAE;AACA,cAAQ,KAAK;AAAA,IACf;AAAA,EACF;AACA,SACE,qBAAC,SAAI,WAAU,mBACZ;AAAA,aAAS,oBAAC,OAAE,MAAK,SAAS,iBAAM;AAAA,IACjC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,UAAU,CAAC,OAAO;AAAA,QAClB,SAAS,MAAM;AACb,eAAK,SAAS;AAAA,QAChB;AAAA,QAEC,iBAAO;AAAA;AAAA,IACV;AAAA,KACF;AAEJ;",
6
+ "names": ["error"]
7
+ }
@@ -0,0 +1,74 @@
1
+ // src/cart/checkout-state.ts
2
+ import {
3
+ payReadiness
4
+ } from "@zappie/sdk/checkout";
5
+ var labels = {
6
+ pay: "Continue to payment",
7
+ sign_in: "Sign in to continue",
8
+ busy: "Please wait\u2026",
9
+ quoting: "Updating total\u2026",
10
+ retry: "Update totals to continue",
11
+ address: "Add a delivery address",
12
+ choose_area: "Choose a delivery area",
13
+ fix_issues: "Review your cart",
14
+ too_far: "Too far for delivery",
15
+ phone: "Check your phone number"
16
+ };
17
+ function toPayReadinessQuoteState(cartState, totalsStatus) {
18
+ if (cartState.status === "quoting") {
19
+ return { status: "loading" };
20
+ }
21
+ if (totalsStatus === "stale" || totalsStatus === "offline") {
22
+ return { status: "error" };
23
+ }
24
+ if (cartState.status === "quoted") {
25
+ return { status: "ready", quote: cartState.quote };
26
+ }
27
+ if (cartState.status === "needs_attention") {
28
+ if (cartState.quote) {
29
+ return { status: "ready", quote: cartState.quote };
30
+ }
31
+ return { status: "error" };
32
+ }
33
+ return { status: "idle" };
34
+ }
35
+ function checkoutButtonState({
36
+ busy,
37
+ cartState,
38
+ totalsStatus,
39
+ fulfilment,
40
+ customer,
41
+ contactPhoneValid = true,
42
+ deliveryDistance
43
+ }) {
44
+ let status;
45
+ if (busy) {
46
+ status = "busy";
47
+ } else if (!customer) {
48
+ status = "sign_in";
49
+ } else if (deliveryDistance?.status === "too_far") {
50
+ status = "too_far";
51
+ } else {
52
+ const addressValid = fulfilment?.type !== "delivery" || Boolean(
53
+ fulfilment.address.line1 || fulfilment.address.placeId || fulfilment.address.coordinates
54
+ );
55
+ status = payReadiness(
56
+ toPayReadinessQuoteState(cartState, totalsStatus),
57
+ contactPhoneValid,
58
+ addressValid
59
+ );
60
+ if (status === "pay" && cartState.status === "needs_attention") {
61
+ status = "fix_issues";
62
+ }
63
+ }
64
+ return {
65
+ status,
66
+ label: labels[status],
67
+ enabled: status === "pay" || status === "sign_in" || status === "phone"
68
+ };
69
+ }
70
+ export {
71
+ checkoutButtonState,
72
+ toPayReadinessQuoteState
73
+ };
74
+ //# sourceMappingURL=checkout-state.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/checkout-state.ts"],
4
+ "sourcesContent": ["import type { TotalsState } from \"@zappie/foundations\";\nimport type { CartFulfilment, CartState } from \"@zappie/sdk\";\nimport {\n payReadiness,\n type PayReadiness,\n type PayReadinessQuoteState,\n} from \"@zappie/sdk/checkout\";\n\nexport type CheckoutButtonStatus = PayReadiness | \"busy\" | \"too_far\";\n\nexport type CheckoutButtonState = {\n status: CheckoutButtonStatus;\n label: string;\n enabled: boolean;\n};\n\nconst labels: Record<CheckoutButtonStatus, string> = {\n pay: \"Continue to payment\",\n sign_in: \"Sign in to continue\",\n busy: \"Please wait\u2026\",\n quoting: \"Updating total\u2026\",\n retry: \"Update totals to continue\",\n address: \"Add a delivery address\",\n choose_area: \"Choose a delivery area\",\n fix_issues: \"Review your cart\",\n too_far: \"Too far for delivery\",\n phone: \"Check your phone number\",\n};\n\nexport function toPayReadinessQuoteState(\n cartState: CartState,\n totalsStatus: TotalsState[\"status\"],\n): PayReadinessQuoteState {\n if (cartState.status === \"quoting\") {\n return { status: \"loading\" };\n }\n if (totalsStatus === \"stale\" || totalsStatus === \"offline\") {\n return { status: \"error\" };\n }\n if (cartState.status === \"quoted\") {\n return { status: \"ready\", quote: cartState.quote };\n }\n if (cartState.status === \"needs_attention\") {\n if (cartState.quote) {\n return { status: \"ready\", quote: cartState.quote };\n }\n return { status: \"error\" };\n }\n return { status: \"idle\" };\n}\n\nexport function checkoutButtonState({\n busy,\n cartState,\n totalsStatus,\n fulfilment,\n customer,\n contactPhoneValid = true,\n deliveryDistance,\n}: {\n busy: boolean;\n cartState: CartState;\n totalsStatus: TotalsState[\"status\"];\n fulfilment: CartFulfilment | null;\n customer: { name?: string } | null;\n contactPhoneValid?: boolean;\n deliveryDistance?: { status: \"unknown\" | \"far\" | \"too_far\" };\n}): CheckoutButtonState {\n let status: CheckoutButtonStatus;\n if (busy) {\n status = \"busy\";\n } else if (!customer) {\n status = \"sign_in\";\n } else if (deliveryDistance?.status === \"too_far\") {\n status = \"too_far\";\n } else {\n const addressValid =\n fulfilment?.type !== \"delivery\" ||\n Boolean(\n fulfilment.address.line1 ||\n fulfilment.address.placeId ||\n fulfilment.address.coordinates,\n );\n status = payReadiness(\n toPayReadinessQuoteState(cartState, totalsStatus),\n contactPhoneValid,\n addressValid,\n );\n // Unresolved warnings (a changed price, a refused promo) still hold payment\n // until the shopper deals with them, although the API would accept the order.\n if (status === \"pay\" && cartState.status === \"needs_attention\") {\n status = \"fix_issues\";\n }\n }\n return {\n status,\n label: labels[status],\n enabled: status === \"pay\" || status === \"sign_in\" || status === \"phone\",\n };\n}\n"],
5
+ "mappings": ";AAEA;AAAA,EACE;AAAA,OAGK;AAUP,IAAM,SAA+C;AAAA,EACnD,KAAK;AAAA,EACL,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,OAAO;AACT;AAEO,SAAS,yBACd,WACA,cACwB;AACxB,MAAI,UAAU,WAAW,WAAW;AAClC,WAAO,EAAE,QAAQ,UAAU;AAAA,EAC7B;AACA,MAAI,iBAAiB,WAAW,iBAAiB,WAAW;AAC1D,WAAO,EAAE,QAAQ,QAAQ;AAAA,EAC3B;AACA,MAAI,UAAU,WAAW,UAAU;AACjC,WAAO,EAAE,QAAQ,SAAS,OAAO,UAAU,MAAM;AAAA,EACnD;AACA,MAAI,UAAU,WAAW,mBAAmB;AAC1C,QAAI,UAAU,OAAO;AACnB,aAAO,EAAE,QAAQ,SAAS,OAAO,UAAU,MAAM;AAAA,IACnD;AACA,WAAO,EAAE,QAAQ,QAAQ;AAAA,EAC3B;AACA,SAAO,EAAE,QAAQ,OAAO;AAC1B;AAEO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,oBAAoB;AAAA,EACpB;AACF,GAQwB;AACtB,MAAI;AACJ,MAAI,MAAM;AACR,aAAS;AAAA,EACX,WAAW,CAAC,UAAU;AACpB,aAAS;AAAA,EACX,WAAW,kBAAkB,WAAW,WAAW;AACjD,aAAS;AAAA,EACX,OAAO;AACL,UAAM,eACJ,YAAY,SAAS,cACrB;AAAA,MACE,WAAW,QAAQ,SACnB,WAAW,QAAQ,WACnB,WAAW,QAAQ;AAAA,IACrB;AACF,aAAS;AAAA,MACP,yBAAyB,WAAW,YAAY;AAAA,MAChD;AAAA,MACA;AAAA,IACF;AAGA,QAAI,WAAW,SAAS,UAAU,WAAW,mBAAmB;AAC9D,eAAS;AAAA,IACX;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA,OAAO,OAAO,MAAM;AAAA,IACpB,SAAS,WAAW,SAAS,WAAW,aAAa,WAAW;AAAA,EAClE;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,44 @@
1
+ // src/cart/clear-cart.tsx
2
+ import { Overlay, useOverlay } from "@zappie/foundations";
3
+ import { useCart } from "@zappie/sdk/react";
4
+ import { useThemeClass } from "./theme-class.js";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ function ClearCart() {
7
+ const rootClass = useThemeClass("z-base-cart z-base-confirm");
8
+ const cart = useCart();
9
+ const confirm = useOverlay("cart_clear", "confirm");
10
+ return /* @__PURE__ */ jsxs(Overlay.Root, { param: "cart_clear", id: "confirm", presentation: "dialog", children: [
11
+ /* @__PURE__ */ jsx(Overlay.Trigger, { className: "z-base-button-secondary", children: "Clear cart" }),
12
+ /* @__PURE__ */ jsxs(
13
+ Overlay.Content,
14
+ {
15
+ "data-zappie-theme": "base",
16
+ role: "alertdialog",
17
+ className: rootClass,
18
+ children: [
19
+ /* @__PURE__ */ jsx(Overlay.Title, { children: "Clear your cart?" }),
20
+ /* @__PURE__ */ jsx("p", { children: "This removes every item in your cart." }),
21
+ /* @__PURE__ */ jsxs("div", { className: "z-base-confirm-actions", children: [
22
+ /* @__PURE__ */ jsx(Overlay.Close, { className: "z-base-button-secondary", children: "Keep items" }),
23
+ /* @__PURE__ */ jsx(
24
+ "button",
25
+ {
26
+ type: "button",
27
+ className: "z-base-button",
28
+ onClick: () => {
29
+ cart.actions.clear();
30
+ confirm.close();
31
+ },
32
+ children: "Clear cart"
33
+ }
34
+ )
35
+ ] })
36
+ ]
37
+ }
38
+ )
39
+ ] });
40
+ }
41
+ export {
42
+ ClearCart
43
+ };
44
+ //# sourceMappingURL=clear-cart.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/clear-cart.tsx"],
4
+ "sourcesContent": ["import { Overlay, useOverlay } from \"@zappie/foundations\";\nimport { useCart } from \"@zappie/sdk/react\";\nimport { useThemeClass } from \"./theme-class\";\n/** Clearing removes every line, so it asks first, as the legacy cart does. */\nexport function ClearCart() {\n const rootClass = useThemeClass(\"z-base-cart z-base-confirm\");\n const cart = useCart();\n const confirm = useOverlay(\"cart_clear\", \"confirm\");\n return (\n <Overlay.Root param=\"cart_clear\" id=\"confirm\" presentation=\"dialog\">\n <Overlay.Trigger className=\"z-base-button-secondary\">\n Clear cart\n </Overlay.Trigger>\n <Overlay.Content\n data-zappie-theme=\"base\"\n role=\"alertdialog\"\n className={rootClass}\n >\n <Overlay.Title>Clear your cart?</Overlay.Title>\n <p>This removes every item in your cart.</p>\n <div className=\"z-base-confirm-actions\">\n <Overlay.Close className=\"z-base-button-secondary\">\n Keep items\n </Overlay.Close>\n <button\n type=\"button\"\n className=\"z-base-button\"\n onClick={() => {\n cart.actions.clear();\n confirm.close();\n }}\n >\n Clear cart\n </button>\n </div>\n </Overlay.Content>\n </Overlay.Root>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,SAAS,kBAAkB;AACpC,SAAS,eAAe;AACxB,SAAS,qBAAqB;AAQxB,cAUE,YAVF;AANC,SAAS,YAAY;AAC1B,QAAM,YAAY,cAAc,4BAA4B;AAC5D,QAAM,OAAO,QAAQ;AACrB,QAAM,UAAU,WAAW,cAAc,SAAS;AAClD,SACE,qBAAC,QAAQ,MAAR,EAAa,OAAM,cAAa,IAAG,WAAU,cAAa,UACzD;AAAA,wBAAC,QAAQ,SAAR,EAAgB,WAAU,2BAA0B,wBAErD;AAAA,IACA;AAAA,MAAC,QAAQ;AAAA,MAAR;AAAA,QACC,qBAAkB;AAAA,QAClB,MAAK;AAAA,QACL,WAAW;AAAA,QAEX;AAAA,8BAAC,QAAQ,OAAR,EAAc,8BAAgB;AAAA,UAC/B,oBAAC,OAAE,mDAAqC;AAAA,UACxC,qBAAC,SAAI,WAAU,0BACb;AAAA,gCAAC,QAAQ,OAAR,EAAc,WAAU,2BAA0B,wBAEnD;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,SAAS,MAAM;AACb,uBAAK,QAAQ,MAAM;AACnB,0BAAQ,MAAM;AAAA,gBAChB;AAAA,gBACD;AAAA;AAAA,YAED;AAAA,aACF;AAAA;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,70 @@
1
+ // src/cart/customer-details.tsx
2
+ import { isContactPhoneValid } from "@zappie/sdk/checkout";
3
+ import { useId } from "react";
4
+ import { useCheckoutHandoff } from "../checkout.js";
5
+ import { useBaseHostBridge } from "../host-bridge.js";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ var FIELDS = [
8
+ { field: "firstName", label: "First name", autoComplete: "given-name" },
9
+ { field: "lastName", label: "Last name", autoComplete: "family-name" },
10
+ { field: "email", label: "Email", autoComplete: "email" }
11
+ ];
12
+ function CustomerDetails({
13
+ contactPhone
14
+ } = {}) {
15
+ const { customerDetails } = useBaseHostBridge();
16
+ const handoff = useCheckoutHandoff();
17
+ const showPhone = Boolean(
18
+ contactPhone && handoff.contactPhone && handoff.customer
19
+ );
20
+ const inputId = useId();
21
+ const hintId = useId();
22
+ const errorId = useId();
23
+ const invalid = Boolean(
24
+ contactPhone?.touched && !isContactPhoneValid(contactPhone.value)
25
+ );
26
+ if (!customerDetails && !showPhone) {
27
+ return null;
28
+ }
29
+ return /* @__PURE__ */ jsxs("section", { className: "z-base-fulfilment-panel", "aria-label": "Your details", children: [
30
+ /* @__PURE__ */ jsx("h2", { children: "Your details" }),
31
+ customerDetails && FIELDS.filter(
32
+ ({ field }) => field !== "email" || customerDetails.requiresEmail
33
+ ).map(({ field, label, autoComplete }) => /* @__PURE__ */ jsxs("label", { className: "z-base-field", children: [
34
+ label,
35
+ /* @__PURE__ */ jsx(
36
+ "input",
37
+ {
38
+ type: field === "email" ? "email" : "text",
39
+ autoComplete,
40
+ required: field !== "lastName",
41
+ value: customerDetails.values[field],
42
+ onChange: (event) => customerDetails.update(field, event.target.value)
43
+ }
44
+ )
45
+ ] }, field)),
46
+ showPhone && contactPhone && /* @__PURE__ */ jsxs("div", { className: "z-base-field", children: [
47
+ /* @__PURE__ */ jsx("label", { htmlFor: inputId, children: "Contact phone (optional)" }),
48
+ /* @__PURE__ */ jsx(
49
+ "input",
50
+ {
51
+ id: inputId,
52
+ type: "tel",
53
+ inputMode: "tel",
54
+ autoComplete: "tel",
55
+ value: contactPhone.value,
56
+ "aria-describedby": invalid ? `${hintId} ${errorId}` : hintId,
57
+ "aria-invalid": invalid,
58
+ onBlur: contactPhone.touch,
59
+ onChange: (event) => contactPhone.update(event.target.value)
60
+ }
61
+ ),
62
+ /* @__PURE__ */ jsx("span", { id: hintId, children: handoff.customer?.phoneLast4 ? `Leave blank to use your Zappie number ending ${handoff.customer.phoneLast4}` : "Leave blank to use your Zappie number" }),
63
+ invalid && /* @__PURE__ */ jsx("span", { id: errorId, role: "alert", children: "Enter a phone number with 7 to 15 digits" })
64
+ ] })
65
+ ] });
66
+ }
67
+ export {
68
+ CustomerDetails
69
+ };
70
+ //# sourceMappingURL=customer-details.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/customer-details.tsx"],
4
+ "sourcesContent": ["import { isContactPhoneValid } from \"@zappie/sdk/checkout\";\nimport { useId } from \"react\";\nimport { useCheckoutHandoff } from \"../checkout\";\nimport { useBaseHostBridge } from \"../host-bridge\";\nconst FIELDS = [\n { field: \"firstName\", label: \"First name\", autoComplete: \"given-name\" },\n { field: \"lastName\", label: \"Last name\", autoComplete: \"family-name\" },\n { field: \"email\", label: \"Email\", autoComplete: \"email\" },\n] as const;\n\nexport type ContactPhoneState = {\n value: string;\n touched: boolean;\n update(value: string): void;\n touch(): void;\n};\n\n/** The details a business requires before payment, such as a name for the order. */\nexport function CustomerDetails({\n contactPhone,\n}: {\n contactPhone?: ContactPhoneState;\n} = {}) {\n const { customerDetails } = useBaseHostBridge();\n const handoff = useCheckoutHandoff();\n const showPhone = Boolean(\n contactPhone && handoff.contactPhone && handoff.customer,\n );\n const inputId = useId();\n const hintId = useId();\n const errorId = useId();\n const invalid = Boolean(\n contactPhone?.touched && !isContactPhoneValid(contactPhone.value),\n );\n if (!customerDetails && !showPhone) {\n return null;\n }\n return (\n <section className=\"z-base-fulfilment-panel\" aria-label=\"Your details\">\n <h2>Your details</h2>\n {customerDetails &&\n FIELDS.filter(\n ({ field }) => field !== \"email\" || customerDetails.requiresEmail,\n ).map(({ field, label, autoComplete }) => (\n <label key={field} className=\"z-base-field\">\n {label}\n <input\n type={field === \"email\" ? \"email\" : \"text\"}\n autoComplete={autoComplete}\n required={field !== \"lastName\"}\n value={customerDetails.values[field]}\n onChange={(event) =>\n customerDetails.update(field, event.target.value)\n }\n />\n </label>\n ))}\n {showPhone && contactPhone && (\n <div className=\"z-base-field\">\n <label htmlFor={inputId}>Contact phone (optional)</label>\n <input\n id={inputId}\n type=\"tel\"\n inputMode=\"tel\"\n autoComplete=\"tel\"\n value={contactPhone.value}\n aria-describedby={invalid ? `${hintId} ${errorId}` : hintId}\n aria-invalid={invalid}\n onBlur={contactPhone.touch}\n onChange={(event) => contactPhone.update(event.target.value)}\n />\n <span id={hintId}>\n {handoff.customer?.phoneLast4\n ? `Leave blank to use your Zappie number ending ${handoff.customer.phoneLast4}`\n : \"Leave blank to use your Zappie number\"}\n </span>\n {invalid && (\n <span id={errorId} role=\"alert\">\n Enter a phone number with 7 to 15 digits\n </span>\n )}\n </div>\n )}\n </section>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,2BAA2B;AACpC,SAAS,aAAa;AACtB,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAoC5B,cAKI,YALJ;AAnCN,IAAM,SAAS;AAAA,EACb,EAAE,OAAO,aAAa,OAAO,cAAc,cAAc,aAAa;AAAA,EACtE,EAAE,OAAO,YAAY,OAAO,aAAa,cAAc,cAAc;AAAA,EACrE,EAAE,OAAO,SAAS,OAAO,SAAS,cAAc,QAAQ;AAC1D;AAUO,SAAS,gBAAgB;AAAA,EAC9B;AACF,IAEI,CAAC,GAAG;AACN,QAAM,EAAE,gBAAgB,IAAI,kBAAkB;AAC9C,QAAM,UAAU,mBAAmB;AACnC,QAAM,YAAY;AAAA,IAChB,gBAAgB,QAAQ,gBAAgB,QAAQ;AAAA,EAClD;AACA,QAAM,UAAU,MAAM;AACtB,QAAM,SAAS,MAAM;AACrB,QAAM,UAAU,MAAM;AACtB,QAAM,UAAU;AAAA,IACd,cAAc,WAAW,CAAC,oBAAoB,aAAa,KAAK;AAAA,EAClE;AACA,MAAI,CAAC,mBAAmB,CAAC,WAAW;AAClC,WAAO;AAAA,EACT;AACA,SACE,qBAAC,aAAQ,WAAU,2BAA0B,cAAW,gBACtD;AAAA,wBAAC,QAAG,0BAAY;AAAA,IACf,mBACC,OAAO;AAAA,MACL,CAAC,EAAE,MAAM,MAAM,UAAU,WAAW,gBAAgB;AAAA,IACtD,EAAE,IAAI,CAAC,EAAE,OAAO,OAAO,aAAa,MAClC,qBAAC,WAAkB,WAAU,gBAC1B;AAAA;AAAA,MACD;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,UAAU,UAAU,UAAU;AAAA,UACpC;AAAA,UACA,UAAU,UAAU;AAAA,UACpB,OAAO,gBAAgB,OAAO,KAAK;AAAA,UACnC,UAAU,CAAC,UACT,gBAAgB,OAAO,OAAO,MAAM,OAAO,KAAK;AAAA;AAAA,MAEpD;AAAA,SAVU,KAWZ,CACD;AAAA,IACF,aAAa,gBACZ,qBAAC,SAAI,WAAU,gBACb;AAAA,0BAAC,WAAM,SAAS,SAAS,sCAAwB;AAAA,MACjD;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,MAAK;AAAA,UACL,WAAU;AAAA,UACV,cAAa;AAAA,UACb,OAAO,aAAa;AAAA,UACpB,oBAAkB,UAAU,GAAG,MAAM,IAAI,OAAO,KAAK;AAAA,UACrD,gBAAc;AAAA,UACd,QAAQ,aAAa;AAAA,UACrB,UAAU,CAAC,UAAU,aAAa,OAAO,MAAM,OAAO,KAAK;AAAA;AAAA,MAC7D;AAAA,MACA,oBAAC,UAAK,IAAI,QACP,kBAAQ,UAAU,aACf,gDAAgD,QAAQ,SAAS,UAAU,KAC3E,yCACN;AAAA,MACC,WACC,oBAAC,UAAK,IAAI,SAAS,MAAK,SAAQ,sDAEhC;AAAA,OAEJ;AAAA,KAEJ;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,22 @@
1
+ // src/cart/delivery-distance.tsx
2
+ import { useBaseHostBridge } from "../host-bridge.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+ function DeliveryDistance() {
5
+ const distance = useBaseHostBridge().deliveryDistance;
6
+ if (!distance?.message) {
7
+ return null;
8
+ }
9
+ return /* @__PURE__ */ jsx(
10
+ "p",
11
+ {
12
+ role: distance.status === "too_far" ? "alert" : "status",
13
+ className: "z-base-notice",
14
+ "data-severity": distance.status === "too_far" ? "error" : "warning",
15
+ children: distance.message
16
+ }
17
+ );
18
+ }
19
+ export {
20
+ DeliveryDistance
21
+ };
22
+ //# sourceMappingURL=delivery-distance.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/delivery-distance.tsx"],
4
+ "sourcesContent": ["import { useBaseHostBridge } from \"../host-bridge\";\n\nexport function DeliveryDistance() {\n const distance = useBaseHostBridge().deliveryDistance;\n if (!distance?.message) {\n return null;\n }\n return (\n <p\n role={distance.status === \"too_far\" ? \"alert\" : \"status\"}\n className=\"z-base-notice\"\n data-severity={distance.status === \"too_far\" ? \"error\" : \"warning\"}\n >\n {distance.message}\n </p>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,yBAAyB;AAQ9B;AANG,SAAS,mBAAmB;AACjC,QAAM,WAAW,kBAAkB,EAAE;AACrC,MAAI,CAAC,UAAU,SAAS;AACtB,WAAO;AAAA,EACT;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,SAAS,WAAW,YAAY,UAAU;AAAA,MAChD,WAAU;AAAA,MACV,iBAAe,SAAS,WAAW,YAAY,UAAU;AAAA,MAExD,mBAAS;AAAA;AAAA,EACZ;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,14 @@
1
+ // src/cart/empty-cart.tsx
2
+ import { Cart, Overlay } from "@zappie/foundations";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ function EmptyCart() {
5
+ return /* @__PURE__ */ jsxs(Cart.Empty, { className: "z-base-cart-empty", children: [
6
+ /* @__PURE__ */ jsx("h2", { children: "Your cart is empty" }),
7
+ /* @__PURE__ */ jsx("p", { children: "Add something from the menu to get started." }),
8
+ /* @__PURE__ */ jsx(Overlay.Close, { className: "z-base-button", children: "Browse menu" })
9
+ ] });
10
+ }
11
+ export {
12
+ EmptyCart
13
+ };
14
+ //# sourceMappingURL=empty-cart.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/empty-cart.tsx"],
4
+ "sourcesContent": ["import { Cart, Overlay } from \"@zappie/foundations\";\nexport function EmptyCart() {\n return (\n <Cart.Empty className=\"z-base-cart-empty\">\n <h2>Your cart is empty</h2>\n <p>Add something from the menu to get started.</p>\n <Overlay.Close className=\"z-base-button\">Browse menu</Overlay.Close>\n </Cart.Empty>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,MAAM,eAAe;AAG1B,SACE,KADF;AAFG,SAAS,YAAY;AAC1B,SACE,qBAAC,KAAK,OAAL,EAAW,WAAU,qBACpB;AAAA,wBAAC,QAAG,gCAAkB;AAAA,IACtB,oBAAC,OAAE,yDAA2C;AAAA,IAC9C,oBAAC,QAAQ,OAAR,EAAc,WAAU,iBAAgB,yBAAW;AAAA,KACtD;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,83 @@
1
+ // src/cart/fulfilment-panel.tsx
2
+ import { Branch, Fulfilment } from "@zappie/foundations";
3
+ import { useCart, useStore } from "@zappie/sdk/react";
4
+ import { Fragment, useState } from "react";
5
+ import { useAddressLookup } from "../address.js";
6
+ import { useBaseHostBridge } from "../host-bridge.js";
7
+ import { AddressSheet } from "./address-sheet.js";
8
+ import { RegionPicker } from "./region-picker.js";
9
+ import { ScheduleSheet } from "./schedule-sheet.js";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ function FulfilmentPanel() {
12
+ const cart = useCart();
13
+ const store = useStore();
14
+ const bridge = useBaseHostBridge();
15
+ const lookup = useAddressLookup();
16
+ const [error, setError] = useState(null);
17
+ const branch = store.data?.branches.find(
18
+ (branch2) => branch2.id === cart.branchId
19
+ );
20
+ const mode = bridge.fulfilmentMode ?? cart.fulfilment?.type ?? "delivery";
21
+ if (!branch) {
22
+ return null;
23
+ }
24
+ const scheduledFor = cart.fulfilment && "scheduledFor" in cart.fulfilment ? cart.fulfilment.scheduledFor : void 0;
25
+ return /* @__PURE__ */ jsxs("section", { className: "z-base-fulfilment-panel", "aria-label": "Fulfilment", children: [
26
+ /* @__PURE__ */ jsx("h2", { children: "Fulfilment" }),
27
+ /* @__PURE__ */ jsx(Fulfilment.Switch, { "aria-label": "Order fulfilment", children: ({ options }) => /* @__PURE__ */ jsx("div", { className: "z-base-line-actions", children: options.filter((option) => option !== "dine_in").map((option) => /* @__PURE__ */ jsx(
28
+ "button",
29
+ {
30
+ type: "button",
31
+ "aria-pressed": mode === option,
32
+ className: "z-base-button-secondary",
33
+ onClick: () => {
34
+ setError(null);
35
+ try {
36
+ if (!bridge.setFulfilmentMode(
37
+ option
38
+ )) {
39
+ setError(
40
+ "This menu does not allow that fulfilment option."
41
+ );
42
+ }
43
+ } catch (failure) {
44
+ setError(
45
+ failure instanceof Error ? failure.message : "Unable to change fulfilment"
46
+ );
47
+ }
48
+ },
49
+ children: option === "pickup" ? "Pickup" : "Delivery"
50
+ },
51
+ option
52
+ )) }) }),
53
+ /* @__PURE__ */ jsx(Branch.Picker, { branches: [branch], children: ({ selected }) => /* @__PURE__ */ jsxs("p", { children: [
54
+ mode === "pickup" ? "Collect from" : "Ordering from",
55
+ " ",
56
+ selected?.name,
57
+ selected?.address ? ` \u2014 ${selected.address}` : ""
58
+ ] }) }),
59
+ error && /* @__PURE__ */ jsx("p", { role: "alert", children: error }),
60
+ mode === "delivery" && /* @__PURE__ */ jsxs(Fragment, { children: [
61
+ cart.fulfilment?.type === "delivery" && /* @__PURE__ */ jsxs(Fragment, { children: [
62
+ /* @__PURE__ */ jsx("p", { children: cart.fulfilment.address.line1 }),
63
+ lookup.Map && /* @__PURE__ */ jsx(lookup.Map, { address: cart.fulfilment.address })
64
+ ] }),
65
+ /* @__PURE__ */ jsx(AddressSheet, {}),
66
+ /* @__PURE__ */ jsx(RegionPicker, {})
67
+ ] }),
68
+ scheduledFor && /* @__PURE__ */ jsxs("p", { children: [
69
+ "Scheduled for",
70
+ " ",
71
+ new Intl.DateTimeFormat("en", {
72
+ dateStyle: "medium",
73
+ timeStyle: "short",
74
+ timeZone: branch.timezone ?? store.data?.timezone
75
+ }).format(new Date(scheduledFor))
76
+ ] }),
77
+ branch.fulfilment.scheduling && /* @__PURE__ */ jsx(ScheduleSheet, { branch })
78
+ ] });
79
+ }
80
+ export {
81
+ FulfilmentPanel
82
+ };
83
+ //# sourceMappingURL=fulfilment-panel.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cart/fulfilment-panel.tsx"],
4
+ "sourcesContent": ["import { Branch, Fulfilment } from \"@zappie/foundations\";\nimport { useCart, useStore } from \"@zappie/sdk/react\";\nimport { Fragment, useState } from \"react\";\nimport { useAddressLookup } from \"../address\";\nimport { useBaseHostBridge } from \"../host-bridge\";\nimport { AddressSheet } from \"./address-sheet\";\nimport { RegionPicker } from \"./region-picker\";\nimport { ScheduleSheet } from \"./schedule-sheet\";\nexport function FulfilmentPanel() {\n const cart = useCart();\n const store = useStore();\n const bridge = useBaseHostBridge();\n const lookup = useAddressLookup();\n const [error, setError] = useState<string | null>(null);\n const branch = store.data?.branches.find(\n (branch) => branch.id === cart.branchId,\n );\n const mode = bridge.fulfilmentMode ?? cart.fulfilment?.type ?? \"delivery\";\n if (!branch) {\n return null;\n }\n const scheduledFor =\n cart.fulfilment && \"scheduledFor\" in cart.fulfilment\n ? cart.fulfilment.scheduledFor\n : undefined;\n return (\n <section className=\"z-base-fulfilment-panel\" aria-label=\"Fulfilment\">\n <h2>Fulfilment</h2>\n <Fulfilment.Switch aria-label=\"Order fulfilment\">\n {({ options }) => (\n <div className=\"z-base-line-actions\">\n {options\n .filter((option) => option !== \"dine_in\")\n .map((option) => (\n <button\n type=\"button\"\n key={option}\n aria-pressed={mode === option}\n className=\"z-base-button-secondary\"\n onClick={() => {\n setError(null);\n try {\n if (\n !bridge.setFulfilmentMode(\n option as \"delivery\" | \"pickup\",\n )\n ) {\n setError(\n \"This menu does not allow that fulfilment option.\",\n );\n }\n } catch (failure) {\n setError(\n failure instanceof Error\n ? failure.message\n : \"Unable to change fulfilment\",\n );\n }\n }}\n >\n {option === \"pickup\" ? \"Pickup\" : \"Delivery\"}\n </button>\n ))}\n </div>\n )}\n </Fulfilment.Switch>\n <Branch.Picker branches={[branch]}>\n {({ selected }) => (\n <p>\n {mode === \"pickup\" ? \"Collect from\" : \"Ordering from\"}{\" \"}\n {selected?.name}\n {selected?.address ? ` \u2014 ${selected.address}` : \"\"}\n </p>\n )}\n </Branch.Picker>\n {error && <p role=\"alert\">{error}</p>}\n {mode === \"delivery\" && (\n <Fragment>\n {cart.fulfilment?.type === \"delivery\" && (\n <Fragment>\n <p>{cart.fulfilment.address.line1}</p>\n {lookup.Map && <lookup.Map address={cart.fulfilment.address} />}\n </Fragment>\n )}\n <AddressSheet />\n <RegionPicker />\n </Fragment>\n )}\n {scheduledFor && (\n <p>\n Scheduled for{\" \"}\n {new Intl.DateTimeFormat(\"en\", {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n timeZone: branch.timezone ?? store.data?.timezone,\n }).format(new Date(scheduledFor))}\n </p>\n )}\n {branch.fulfilment.scheduling && <ScheduleSheet branch={branch} />}\n </section>\n );\n}\n"],
5
+ "mappings": ";AAAA,SAAS,QAAQ,kBAAkB;AACnC,SAAS,SAAS,gBAAgB;AAClC,SAAS,UAAU,gBAAgB;AACnC,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAClC,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAoBxB,cAyCI,YAzCJ;AAnBC,SAAS,kBAAkB;AAChC,QAAM,OAAO,QAAQ;AACrB,QAAM,QAAQ,SAAS;AACvB,QAAM,SAAS,kBAAkB;AACjC,QAAM,SAAS,iBAAiB;AAChC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,SAAS,MAAM,MAAM,SAAS;AAAA,IAClC,CAACA,YAAWA,QAAO,OAAO,KAAK;AAAA,EACjC;AACA,QAAM,OAAO,OAAO,kBAAkB,KAAK,YAAY,QAAQ;AAC/D,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,QAAM,eACJ,KAAK,cAAc,kBAAkB,KAAK,aACtC,KAAK,WAAW,eAChB;AACN,SACE,qBAAC,aAAQ,WAAU,2BAA0B,cAAW,cACtD;AAAA,wBAAC,QAAG,wBAAU;AAAA,IACd,oBAAC,WAAW,QAAX,EAAkB,cAAW,oBAC3B,WAAC,EAAE,QAAQ,MACV,oBAAC,SAAI,WAAU,uBACZ,kBACE,OAAO,CAAC,WAAW,WAAW,SAAS,EACvC,IAAI,CAAC,WACJ;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QAEL,gBAAc,SAAS;AAAA,QACvB,WAAU;AAAA,QACV,SAAS,MAAM;AACb,mBAAS,IAAI;AACb,cAAI;AACF,gBACE,CAAC,OAAO;AAAA,cACN;AAAA,YACF,GACA;AACA;AAAA,gBACE;AAAA,cACF;AAAA,YACF;AAAA,UACF,SAAS,SAAS;AAChB;AAAA,cACE,mBAAmB,QACf,QAAQ,UACR;AAAA,YACN;AAAA,UACF;AAAA,QACF;AAAA,QAEC,qBAAW,WAAW,WAAW;AAAA;AAAA,MAxB7B;AAAA,IAyBP,CACD,GACL,GAEJ;AAAA,IACA,oBAAC,OAAO,QAAP,EAAc,UAAU,CAAC,MAAM,GAC7B,WAAC,EAAE,SAAS,MACX,qBAAC,OACE;AAAA,eAAS,WAAW,iBAAiB;AAAA,MAAiB;AAAA,MACtD,UAAU;AAAA,MACV,UAAU,UAAU,WAAM,SAAS,OAAO,KAAK;AAAA,OAClD,GAEJ;AAAA,IACC,SAAS,oBAAC,OAAE,MAAK,SAAS,iBAAM;AAAA,IAChC,SAAS,cACR,qBAAC,YACE;AAAA,WAAK,YAAY,SAAS,cACzB,qBAAC,YACC;AAAA,4BAAC,OAAG,eAAK,WAAW,QAAQ,OAAM;AAAA,QACjC,OAAO,OAAO,oBAAC,OAAO,KAAP,EAAW,SAAS,KAAK,WAAW,SAAS;AAAA,SAC/D;AAAA,MAEF,oBAAC,gBAAa;AAAA,MACd,oBAAC,gBAAa;AAAA,OAChB;AAAA,IAED,gBACC,qBAAC,OAAE;AAAA;AAAA,MACa;AAAA,MACb,IAAI,KAAK,eAAe,MAAM;AAAA,QAC7B,WAAW;AAAA,QACX,WAAW;AAAA,QACX,UAAU,OAAO,YAAY,MAAM,MAAM;AAAA,MAC3C,CAAC,EAAE,OAAO,IAAI,KAAK,YAAY,CAAC;AAAA,OAClC;AAAA,IAED,OAAO,WAAW,cAAc,oBAAC,iBAAc,QAAgB;AAAA,KAClE;AAEJ;",
6
+ "names": ["branch"]
7
+ }