@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.
- package/CHANGELOG.md +39 -0
- package/README.md +26 -53
- package/dist/address.js +99 -2
- package/dist/address.js.map +7 -1
- package/dist/cart/address-sheet.js +143 -0
- package/dist/cart/address-sheet.js.map +7 -0
- package/dist/cart/cart-issues.js +72 -0
- package/dist/cart/cart-issues.js.map +7 -0
- package/dist/cart/cart-line-groups.js +34 -0
- package/dist/cart/cart-line-groups.js.map +7 -0
- package/dist/{chunk-FB5DRCU7.js → cart/cart-line.js} +9 -70
- package/dist/cart/cart-line.js.map +7 -0
- package/dist/cart/cart-lines.js +27 -0
- package/dist/cart/cart-lines.js.map +7 -0
- package/dist/cart/cart-schedule.js +24 -0
- package/dist/cart/cart-schedule.js.map +7 -0
- package/dist/cart/cart-sheet.js +35 -0
- package/dist/cart/cart-sheet.js.map +7 -0
- package/dist/cart/checkout-cta.js +81 -0
- package/dist/cart/checkout-cta.js.map +7 -0
- package/dist/cart/checkout-state.js +74 -0
- package/dist/cart/checkout-state.js.map +7 -0
- package/dist/cart/clear-cart.js +44 -0
- package/dist/cart/clear-cart.js.map +7 -0
- package/dist/cart/customer-details.js +70 -0
- package/dist/cart/customer-details.js.map +7 -0
- package/dist/cart/delivery-distance.js +22 -0
- package/dist/cart/delivery-distance.js.map +7 -0
- package/dist/cart/empty-cart.js +14 -0
- package/dist/cart/empty-cart.js.map +7 -0
- package/dist/cart/fulfilment-panel.js +83 -0
- package/dist/cart/fulfilment-panel.js.map +7 -0
- package/dist/cart/line-editor.js +35 -0
- package/dist/cart/line-editor.js.map +7 -0
- package/dist/cart/line-options.js +96 -0
- package/dist/cart/line-options.js.map +7 -0
- package/dist/cart/loading.js +17 -0
- package/dist/cart/loading.js.map +7 -0
- package/dist/cart/promo-sheet.js +103 -0
- package/dist/cart/promo-sheet.js.map +7 -0
- package/dist/cart/region-picker.js +40 -0
- package/dist/cart/region-picker.js.map +7 -0
- package/dist/cart/rewards-sheet.js +86 -0
- package/dist/cart/rewards-sheet.js.map +7 -0
- package/dist/cart/schedule-sheet.js +87 -0
- package/dist/cart/schedule-sheet.js.map +7 -0
- package/dist/{chunk-JFEI2OUZ.js → cart/theme-class.js} +7 -5
- package/dist/cart/theme-class.js.map +7 -0
- package/dist/cart/totals.js +81 -0
- package/dist/cart/totals.js.map +7 -0
- package/dist/cart/use-address-selection.js +130 -0
- package/dist/cart/use-address-selection.js.map +7 -0
- package/dist/cart.js +21 -1069
- package/dist/cart.js.map +7 -1
- package/dist/catalogue/catalogue-cart.js +25 -0
- package/dist/catalogue/catalogue-cart.js.map +7 -0
- package/dist/catalogue/catalogue-header.js +88 -0
- package/dist/catalogue/catalogue-header.js.map +7 -0
- package/dist/catalogue/catalogue-pages.js +68 -0
- package/dist/catalogue/catalogue-pages.js.map +7 -0
- package/dist/catalogue/catalogue-search.js +89 -0
- package/dist/catalogue/catalogue-search.js.map +7 -0
- package/dist/catalogue/category-navigation.js +98 -0
- package/dist/catalogue/category-navigation.js.map +7 -0
- package/dist/catalogue/category-section.js +113 -0
- package/dist/catalogue/category-section.js.map +7 -0
- package/dist/catalogue/info-banners.js +148 -0
- package/dist/catalogue/info-banners.js.map +7 -0
- package/dist/catalogue/item-tile.js +55 -0
- package/dist/catalogue/item-tile.js.map +7 -0
- package/dist/catalogue/loader.js +136 -0
- package/dist/catalogue/loader.js.map +7 -0
- package/dist/{chunk-USSLDBDY.js → catalogue/presentation.js} +12 -9
- package/dist/catalogue/presentation.js.map +7 -0
- package/dist/catalogue/saved-catalogue-sync.js +115 -0
- package/dist/catalogue/saved-catalogue-sync.js.map +7 -0
- package/dist/catalogue/types.js +1 -0
- package/dist/catalogue/types.js.map +7 -0
- package/dist/catalogue/use-catalogue-data.js +88 -0
- package/dist/catalogue/use-catalogue-data.js.map +7 -0
- package/dist/catalogue/use-category-scroll.js +115 -0
- package/dist/catalogue/use-category-scroll.js.map +7 -0
- package/dist/catalogue/use-item-opener.js +46 -0
- package/dist/catalogue/use-item-opener.js.map +7 -0
- package/dist/catalogue/use-search-source.js +132 -0
- package/dist/catalogue/use-search-source.js.map +7 -0
- package/dist/catalogue.js +26 -1216
- package/dist/catalogue.js.map +7 -1
- package/dist/checkout.js +149 -2
- package/dist/checkout.js.map +7 -1
- package/dist/host-bridge.js +22 -2
- package/dist/host-bridge.js.map +7 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +7 -1
- package/dist/item/configurator-commit.js +15 -0
- package/dist/item/configurator-commit.js.map +7 -0
- package/dist/item/configurator-draft.js +63 -0
- package/dist/item/configurator-draft.js.map +7 -0
- package/dist/item/configurator.js +135 -0
- package/dist/item/configurator.js.map +7 -0
- package/dist/item/note.js +65 -0
- package/dist/item/note.js.map +7 -0
- package/dist/item/variant-status.js +23 -0
- package/dist/item/variant-status.js.map +7 -0
- package/dist/item-frame.js +60 -3
- package/dist/item-frame.js.map +7 -1
- package/dist/item.js +11 -11
- package/dist/item.js.map +7 -1
- package/dist/navigation.js +39 -2
- package/dist/navigation.js.map +7 -1
- package/dist/url-navigation-state.js +61 -0
- package/dist/url-navigation-state.js.map +7 -0
- package/dist/{chunk-ILOCSCZL.js → url-navigation.js} +12 -89
- package/dist/url-navigation.js.map +7 -0
- package/package.json +8 -7
- package/dist/chunk-2MV6KU3R.js +0 -352
- package/dist/chunk-2MV6KU3R.js.map +0 -1
- package/dist/chunk-FB5DRCU7.js.map +0 -1
- package/dist/chunk-IG63ONID.js +0 -139
- package/dist/chunk-IG63ONID.js.map +0 -1
- package/dist/chunk-ILOCSCZL.js.map +0 -1
- package/dist/chunk-JFEI2OUZ.js.map +0 -1
- package/dist/chunk-NTJONY3N.js +0 -95
- package/dist/chunk-NTJONY3N.js.map +0 -1
- package/dist/chunk-QWST2TA2.js +0 -22
- package/dist/chunk-QWST2TA2.js.map +0 -1
- package/dist/chunk-USSLDBDY.js.map +0 -1
- package/dist/chunk-VIAJ27YC.js +0 -59
- package/dist/chunk-VIAJ27YC.js.map +0 -1
package/dist/chunk-IG63ONID.js
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { CheckoutError, checkoutFulfilment as checkoutFulfilment$1 } from '@zappie/sdk/checkout';
|
|
2
|
-
import { currentSource } from '@zappie/sdk/visits';
|
|
3
|
-
import { createContext, useCallback, useSyncExternalStore, useMemo, useContext } from 'react';
|
|
4
|
-
import { jsx } from 'react/jsx-runtime';
|
|
5
|
-
|
|
6
|
-
// src/checkout.tsx
|
|
7
|
-
var subscriptions = /* @__PURE__ */ new WeakMap();
|
|
8
|
-
var Context = createContext(null);
|
|
9
|
-
var idle = () => () => {
|
|
10
|
-
};
|
|
11
|
-
function CheckoutHandoffProvider({
|
|
12
|
-
handoff,
|
|
13
|
-
children
|
|
14
|
-
}) {
|
|
15
|
-
const subscribe = useCallback(
|
|
16
|
-
(listener) => (subscriptions.get(handoff) ?? idle)(listener),
|
|
17
|
-
[handoff]
|
|
18
|
-
);
|
|
19
|
-
const read = useCallback(() => handoff.customer, [handoff]);
|
|
20
|
-
const customer = useSyncExternalStore(subscribe, read, read);
|
|
21
|
-
const value = useMemo(
|
|
22
|
-
() => ({
|
|
23
|
-
...handoff.contactPhone !== void 0 ? { contactPhone: handoff.contactPhone } : {},
|
|
24
|
-
customer,
|
|
25
|
-
signIn: () => handoff.signIn(),
|
|
26
|
-
pay: (payload, details) => details ? handoff.pay(payload, details) : handoff.pay(payload)
|
|
27
|
-
}),
|
|
28
|
-
[customer, handoff]
|
|
29
|
-
);
|
|
30
|
-
return /* @__PURE__ */ jsx(Context.Provider, { value, children });
|
|
31
|
-
}
|
|
32
|
-
function useCheckoutHandoff() {
|
|
33
|
-
const handoff = useContext(Context);
|
|
34
|
-
if (!handoff) {
|
|
35
|
-
throw new Error("useCheckoutHandoff requires CheckoutHandoffProvider");
|
|
36
|
-
}
|
|
37
|
-
return handoff;
|
|
38
|
-
}
|
|
39
|
-
function customerName(customer) {
|
|
40
|
-
if (!customer) {
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
const digits = customer.phone_masked?.replace(/\D/g, "") ?? "";
|
|
44
|
-
return {
|
|
45
|
-
...customer.given_name ? { name: customer.given_name } : {},
|
|
46
|
-
...digits.length >= 4 ? { phoneLast4: digits.slice(-4) } : {}
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
function checkoutFulfilment(payload) {
|
|
50
|
-
const fulfilment = checkoutFulfilment$1(payload.fulfilment);
|
|
51
|
-
if (fulfilment.type === "delivery") {
|
|
52
|
-
return { ...fulfilment, type: "delivery" };
|
|
53
|
-
}
|
|
54
|
-
if (fulfilment.type === "pickup") {
|
|
55
|
-
return { ...fulfilment, type: "pickup" };
|
|
56
|
-
}
|
|
57
|
-
throw new Error("Dine-in checkout is unavailable");
|
|
58
|
-
}
|
|
59
|
-
function createSdkCheckoutHandoff({
|
|
60
|
-
customer,
|
|
61
|
-
checkout,
|
|
62
|
-
branchId,
|
|
63
|
-
returnUrl,
|
|
64
|
-
cancelUrl,
|
|
65
|
-
attribution = currentSource
|
|
66
|
-
}) {
|
|
67
|
-
let source = customer.customer;
|
|
68
|
-
let current = customerName(source);
|
|
69
|
-
let attempt;
|
|
70
|
-
const readCustomer = () => {
|
|
71
|
-
if (source !== customer.customer) {
|
|
72
|
-
source = customer.customer;
|
|
73
|
-
current = customerName(source);
|
|
74
|
-
}
|
|
75
|
-
return current;
|
|
76
|
-
};
|
|
77
|
-
const handoff = {
|
|
78
|
-
contactPhone: true,
|
|
79
|
-
get customer() {
|
|
80
|
-
return readCustomer();
|
|
81
|
-
},
|
|
82
|
-
signIn() {
|
|
83
|
-
customer.signIn();
|
|
84
|
-
},
|
|
85
|
-
async pay(payload, details) {
|
|
86
|
-
const contactPhone = details?.contactPhone?.trim().replace(/\s+/g, "") ?? "";
|
|
87
|
-
const digest = JSON.stringify({ payload, contactPhone });
|
|
88
|
-
if (attempt?.digest !== digest) {
|
|
89
|
-
const visit = attribution();
|
|
90
|
-
attempt = {
|
|
91
|
-
digest,
|
|
92
|
-
key: crypto.randomUUID(),
|
|
93
|
-
returnUrl: returnUrl ?? `${location.origin}/checkout/return`,
|
|
94
|
-
cancelUrl: cancelUrl ?? location.href,
|
|
95
|
-
source: visit.source,
|
|
96
|
-
campaign: visit.campaign
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
const request = {
|
|
100
|
-
branch_id: branchId,
|
|
101
|
-
menu_version: payload.menu_version,
|
|
102
|
-
lines: payload.lines,
|
|
103
|
-
fulfilment: checkoutFulfilment(payload),
|
|
104
|
-
...contactPhone ? { contact_phone: contactPhone } : {},
|
|
105
|
-
...payload.promo_code ? { promo_code: payload.promo_code } : {},
|
|
106
|
-
...attempt.source ? { source: attempt.source } : {},
|
|
107
|
-
...attempt.campaign ? { campaign: attempt.campaign } : {},
|
|
108
|
-
return_url: attempt.returnUrl,
|
|
109
|
-
cancel_url: attempt.cancelUrl
|
|
110
|
-
};
|
|
111
|
-
try {
|
|
112
|
-
const session = await checkout.open(request, attempt.key);
|
|
113
|
-
location.assign(session.url);
|
|
114
|
-
} catch (failure) {
|
|
115
|
-
if (failure instanceof CheckoutError && failure.apiCode === "customer_required") {
|
|
116
|
-
await handoff.signIn();
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
throw failure;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
subscriptions.set(handoff, (listener) => {
|
|
124
|
-
const unsubscribe = customer.onChange((_state, next) => {
|
|
125
|
-
source = next;
|
|
126
|
-
current = customerName(next);
|
|
127
|
-
listener();
|
|
128
|
-
});
|
|
129
|
-
if (customer.state === "unknown") {
|
|
130
|
-
void customer.session().catch(() => void 0);
|
|
131
|
-
}
|
|
132
|
-
return unsubscribe;
|
|
133
|
-
});
|
|
134
|
-
return handoff;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export { CheckoutHandoffProvider, createSdkCheckoutHandoff, useCheckoutHandoff };
|
|
138
|
-
//# sourceMappingURL=chunk-IG63ONID.js.map
|
|
139
|
-
//# sourceMappingURL=chunk-IG63ONID.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/checkout.tsx"],"names":["wireCheckoutFulfilment"],"mappings":"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","file":"chunk-IG63ONID.js","sourcesContent":["\"use client\";\n\nimport type { CartModule } from \"@zappie/sdk\";\nimport {\n CheckoutError,\n checkoutFulfilment as wireCheckoutFulfilment,\n type CheckoutClient,\n type CheckoutRequest,\n} from \"@zappie/sdk/checkout\";\nimport type { CustomerClient, SessionCustomer } from \"@zappie/sdk/customer\";\nimport { currentSource } from \"@zappie/sdk/visits\";\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useSyncExternalStore,\n type ReactNode,\n} from \"react\";\n\nexport type CheckoutPayload = ReturnType<CartModule[\"toCheckoutPayload\"]>;\nexport type CheckoutHandoff = {\n contactPhone?: boolean;\n customer: { name?: string; phoneLast4?: string } | null;\n signIn(): Promise<void> | void;\n pay(\n payload: CheckoutPayload,\n details?: { contactPhone?: string },\n ): Promise<void>;\n};\n\nconst subscriptions = new WeakMap<\n CheckoutHandoff,\n (listener: () => void) => () => void\n>();\nconst Context = createContext<CheckoutHandoff | null>(null);\nconst idle = () => () => {};\n\nexport function CheckoutHandoffProvider({\n handoff,\n children,\n}: {\n handoff: CheckoutHandoff;\n children: ReactNode;\n}) {\n const subscribe = useCallback(\n (listener: () => void) => (subscriptions.get(handoff) ?? idle)(listener),\n [handoff],\n );\n const read = useCallback(() => handoff.customer, [handoff]);\n const customer = useSyncExternalStore(subscribe, read, read);\n const value = useMemo<CheckoutHandoff>(\n () => ({\n ...(handoff.contactPhone !== undefined\n ? { contactPhone: handoff.contactPhone }\n : {}),\n customer,\n signIn: () => handoff.signIn(),\n pay: (payload, details) =>\n details ? handoff.pay(payload, details) : handoff.pay(payload),\n }),\n [customer, handoff],\n );\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport function useCheckoutHandoff() {\n const handoff = useContext(Context);\n if (!handoff) {\n throw new Error(\"useCheckoutHandoff requires CheckoutHandoffProvider\");\n }\n return handoff;\n}\n\nfunction customerName(customer: SessionCustomer | null) {\n if (!customer) {\n return null;\n }\n const digits = customer.phone_masked?.replace(/\\D/g, \"\") ?? \"\";\n return {\n ...(customer.given_name ? { name: customer.given_name } : {}),\n ...(digits.length >= 4 ? { phoneLast4: digits.slice(-4) } : {}),\n };\n}\n\nfunction checkoutFulfilment(payload: CheckoutPayload) {\n const fulfilment = wireCheckoutFulfilment(payload.fulfilment);\n if (fulfilment.type === \"delivery\") {\n return { ...fulfilment, type: \"delivery\" } as const;\n }\n if (fulfilment.type === \"pickup\") {\n return { ...fulfilment, type: \"pickup\" } as const;\n }\n throw new Error(\"Dine-in checkout is unavailable\");\n}\n\nexport function createSdkCheckoutHandoff({\n customer,\n checkout,\n branchId,\n returnUrl,\n cancelUrl,\n attribution = currentSource,\n}: {\n customer: CustomerClient;\n checkout: CheckoutClient;\n branchId: string;\n returnUrl?: string;\n cancelUrl?: string;\n attribution?: () => { source: string; campaign: string };\n}): CheckoutHandoff {\n let source = customer.customer;\n let current = customerName(source);\n // One attempt per cart and phone: a retry reuses the key and the exact body,\n // because the API refuses a reused key whose body changed.\n let attempt:\n | {\n digest: string;\n key: string;\n returnUrl: string;\n cancelUrl: string;\n source: string;\n campaign: string;\n }\n | undefined;\n const readCustomer = () => {\n if (source !== customer.customer) {\n source = customer.customer;\n current = customerName(source);\n }\n return current;\n };\n const handoff: CheckoutHandoff = {\n contactPhone: true,\n get customer() {\n return readCustomer();\n },\n signIn() {\n customer.signIn();\n },\n async pay(payload, details) {\n const contactPhone =\n details?.contactPhone?.trim().replace(/\\s+/g, \"\") ?? \"\";\n const digest = JSON.stringify({ payload, contactPhone });\n if (attempt?.digest !== digest) {\n const visit = attribution();\n attempt = {\n digest,\n key: crypto.randomUUID(),\n returnUrl: returnUrl ?? `${location.origin}/checkout/return`,\n cancelUrl: cancelUrl ?? location.href,\n source: visit.source,\n campaign: visit.campaign,\n };\n }\n const request: CheckoutRequest = {\n branch_id: branchId,\n menu_version: payload.menu_version,\n lines: payload.lines,\n fulfilment: checkoutFulfilment(payload),\n ...(contactPhone ? { contact_phone: contactPhone } : {}),\n ...(payload.promo_code ? { promo_code: payload.promo_code } : {}),\n ...(attempt.source ? { source: attempt.source } : {}),\n ...(attempt.campaign ? { campaign: attempt.campaign } : {}),\n return_url: attempt.returnUrl,\n cancel_url: attempt.cancelUrl,\n };\n try {\n const session = await checkout.open(request, attempt.key);\n location.assign(session.url);\n } catch (failure) {\n if (\n failure instanceof CheckoutError &&\n failure.apiCode === \"customer_required\"\n ) {\n await handoff.signIn();\n return;\n }\n throw failure;\n }\n },\n };\n subscriptions.set(handoff, (listener) => {\n const unsubscribe = customer.onChange((_state, next) => {\n source = next;\n current = customerName(next);\n listener();\n });\n // Without a CustomerProvider nothing else asks who is signed in.\n if (customer.state === \"unknown\") {\n void customer.session().catch(() => undefined);\n }\n return unsubscribe;\n });\n return handoff;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/url-navigation-state.ts","../src/url-navigation.ts","../src/navigation.tsx"],"names":[],"mappings":"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","file":"chunk-ILOCSCZL.js","sourcesContent":["import type { StorefrontPageState, StorefrontRoute } from \"@zappie/sdk/url\";\n\n/** History-state key marking entries this provider pushed, so close can go Back. */\nexport const NAVIGATION_ENTRY = \"zappie:storefront-navigation-entry\";\n\nexport const routeBase = (route: StorefrontRoute) => {\n if (route.type === \"item\" || route.type === \"order-menu\") {\n return {\n business: route.business,\n ...(route.branch !== undefined ? { branch: route.branch } : {}),\n };\n }\n return null;\n};\n\nexport const stateWith = (\n state: StorefrontPageState,\n values: {\n menuId?: string | undefined;\n categoryId?: string | undefined;\n menuLayout?: string | undefined;\n modalId?: string | undefined;\n mode?: \"delivery\" | \"pickup\" | undefined;\n },\n): StorefrontPageState => {\n const query = { ...state.query };\n const next: StorefrontPageState = { ...state, query };\n const update = (\n property: \"menuId\" | \"categoryId\" | \"menuLayout\" | \"modalId\" | \"mode\",\n key: string,\n value: string | undefined,\n ) => {\n if (!Object.hasOwn(values, property)) {\n return;\n }\n if (value === undefined) {\n delete query[key];\n delete next[property];\n return;\n }\n query[key] = property === \"mode\" ? String(value === \"pickup\") : value;\n if (property === \"mode\") {\n next.mode = value === \"pickup\" ? \"pickup\" : \"delivery\";\n } else if (property === \"menuId\") {\n next.menuId = value;\n } else if (property === \"categoryId\") {\n next.categoryId = value;\n } else if (property === \"menuLayout\") {\n next.menuLayout = value;\n } else {\n next.modalId = value;\n }\n };\n update(\"menuId\", \"menu_id\", values.menuId);\n update(\"categoryId\", \"category_id\", values.categoryId);\n update(\"menuLayout\", \"menu_layout\", values.menuLayout);\n update(\"modalId\", \"modal_id\", values.modalId);\n update(\"mode\", \"pickup\", values.mode);\n return next;\n};\n\nexport const catalogueRoute = (\n route: StorefrontRoute,\n state: StorefrontPageState,\n): StorefrontRoute => {\n const base = routeBase(route);\n if (!base) {\n return route;\n }\n return {\n type: \"order-menu\",\n ...base,\n state,\n };\n};\n","import { buildStorefrontUrl, parseStorefrontUrl } from \"@zappie/sdk/url\";\nimport type {\n CatalogueLocation,\n CatalogueNavigation,\n CatalogueNavigationTarget,\n UrlNavigationOptions,\n} from \"./navigation\";\nimport {\n catalogueRoute,\n NAVIGATION_ENTRY,\n routeBase,\n stateWith,\n} from \"./url-navigation-state\";\n\nexport function createUrlNavigation(\n options: UrlNavigationOptions = {},\n): CatalogueNavigation {\n const browser = options.window ?? window;\n const current = () => parseStorefrontUrl(browser.location.href, options);\n\n const urlFor = (route: Parameters<typeof buildStorefrontUrl>[0]) =>\n buildStorefrontUrl(route, options);\n const notify = () => {\n browser.dispatchEvent(\n new browser.PopStateEvent(\"popstate\", { state: browser.history.state }),\n );\n };\n const write = (url: string, method: \"push\" | \"replace\", entry: string) => {\n const state = {\n ...(typeof browser.history.state === \"object\" && browser.history.state\n ? browser.history.state\n : {}),\n [NAVIGATION_ENTRY]: entry,\n };\n if (method === \"push\") {\n browser.history.pushState(state, \"\", url);\n } else {\n browser.history.replaceState(state, \"\", url);\n }\n notify();\n };\n const hrefFor = (target: CatalogueNavigationTarget) => {\n const route = current();\n const base = routeBase(route);\n if (!base) {\n return browser.location.href;\n }\n const state = stateWith(route.state, {\n ...(target.menuId !== undefined ? { menuId: target.menuId } : {}),\n ...(target.categoryId !== undefined\n ? { categoryId: target.categoryId }\n : {}),\n });\n return urlFor({\n type: \"item\",\n business: base.business,\n ...(base.branch !== undefined ? { branch: base.branch } : {}),\n item: target.itemId,\n state,\n });\n };\n const updateCatalogue = (\n values: Parameters<typeof stateWith>[1],\n method: \"push\" | \"replace\" = \"replace\",\n entry = \"catalogue\",\n ) => {\n const route = current();\n const next = catalogueRoute(route, stateWith(route.state, values));\n write(urlFor(next), method, entry);\n };\n const closeItem = async () => {\n const route = current();\n if (route.type !== \"item\") {\n return;\n }\n if (browser.history.state?.[NAVIGATION_ENTRY] === \"item\") {\n await new Promise<void>((resolve) => {\n browser.addEventListener(\"popstate\", () => resolve(), { once: true });\n browser.history.back();\n });\n return;\n }\n const next = catalogueRoute(\n route,\n stateWith(route.state, { modalId: undefined }),\n );\n write(urlFor(next), \"replace\", \"catalogue\");\n };\n return {\n get location() {\n const route = current();\n const layout = route.state.menuLayout;\n const menuLayout: CatalogueLocation[\"menuLayout\"] =\n layout === \"GRID\" || layout === \"LIST\" || layout === \"CARD\"\n ? layout\n : undefined;\n return {\n pathname: browser.location.pathname,\n ...(route.state.menuId !== undefined\n ? { menuId: route.state.menuId }\n : {}),\n ...(route.state.categoryId !== undefined\n ? { categoryId: route.state.categoryId }\n : {}),\n ...(menuLayout !== undefined ? { menuLayout } : {}),\n ...(route.type === \"item\"\n ? {\n item: {\n id: route.item,\n path: browser.location.pathname,\n presentation: route.state.modalId\n ? (\"query\" as const)\n : (\"path\" as const),\n },\n }\n : {}),\n };\n },\n hrefFor,\n selectMenu(menuId) {\n updateCatalogue({ menuId });\n },\n selectCategory(categoryId) {\n updateCatalogue({ categoryId });\n },\n setLayout(menuLayout) {\n updateCatalogue({ menuLayout });\n },\n async openItem({ itemId, menuId, categoryId }) {\n write(\n hrefFor({\n type: \"item\",\n itemId,\n menuId,\n ...(categoryId !== undefined ? { categoryId } : {}),\n }),\n \"push\",\n \"item\",\n );\n },\n closeItem,\n async openCart() {\n await closeItem();\n updateCatalogue({ modalId: \"review-menu\" }, \"push\", \"cart\");\n },\n async openBranchFinder() {\n await closeItem();\n updateCatalogue({ modalId: \"branch-finder\" }, \"push\", \"branch-finder\");\n },\n async openBranchDetails() {\n await closeItem();\n updateCatalogue({ modalId: \"branch-details\" }, \"push\", \"branch-details\");\n },\n async switchFulfilment(mode) {\n await closeItem();\n updateCatalogue({ mode });\n return true;\n },\n restoreFocus({ itemId }) {\n const item = itemId\n ? browser.document.getElementById(`base-item-${itemId}`)\n : null;\n const target =\n item ?? browser.document.getElementById(\"base-catalogue-heading\");\n target?.focus();\n },\n };\n}\n","\"use client\";\n\nimport type { Item } from \"@zappie/sdk\";\nimport type { StorefrontUrlOptions } from \"@zappie/sdk/url\";\nimport {\n createContext,\n useContext,\n useEffect,\n useState,\n type ReactNode,\n} from \"react\";\n\n/** URL-owned selection, shared by template routers and reusable base screens. */\nexport type CatalogueLocation = {\n pathname: string;\n menuId?: string;\n categoryId?: string;\n menuLayout?: \"GRID\" | \"LIST\" | \"CARD\";\n item?: { id: string; path: string; presentation: \"path\" | \"query\" };\n};\n\n/** Stable identities, not host selectors or retained DOM nodes. */\nexport type CatalogueFocusTarget = { itemId?: string; fallback: \"catalogue\" };\n\nexport type CatalogueNavigationTarget = {\n type: \"item\";\n itemId: string;\n menuId?: string;\n categoryId?: string;\n};\n\nexport type CatalogueNavigation = {\n /** Fresh URL snapshot on every read; providers re-render on history changes. */\n readonly location: CatalogueLocation;\n hrefFor(target: CatalogueNavigationTarget): string;\n selectMenu(menuId: string): void;\n selectCategory(categoryId: string): void;\n setLayout(layout: NonNullable<CatalogueLocation[\"menuLayout\"]>): void;\n openItem(input: {\n itemId: string;\n /** Already normalized catalogue/search item; opening it must not fetch it again. */\n item?: Item;\n menuId: string;\n categoryId?: string;\n }): Promise<void>;\n /** Resolves after history changes and the item releases its modal/focus lock. */\n closeItem(): Promise<void>;\n /** Close the active item/base overlay before opening another surface. */\n openCart(): Promise<void>;\n openBranchFinder(): Promise<void>;\n openBranchDetails?(): Promise<void>;\n switchFulfilment(mode: \"delivery\" | \"pickup\"): Promise<boolean>;\n /** Called after close settles; use a registered trigger, or the catalogue heading. */\n restoreFocus(target: CatalogueFocusTarget): void;\n};\n\nexport type UrlNavigationOptions = StorefrontUrlOptions & {\n window?: Window & typeof globalThis;\n};\nconst Context = createContext<CatalogueNavigation | null>(null);\n\nexport function CatalogueNavigationProvider({\n navigation,\n children,\n}: {\n navigation: CatalogueNavigation;\n children: ReactNode;\n}) {\n const [, refresh] = useState(0);\n useEffect(() => {\n const update = () => refresh((value) => value + 1);\n window.addEventListener(\"popstate\", update);\n return () => {\n window.removeEventListener(\"popstate\", update);\n };\n }, [navigation]);\n return <Context.Provider value={navigation}>{children}</Context.Provider>;\n}\n\nexport function useCatalogueNavigation() {\n const navigation = useContext(Context);\n if (!navigation) {\n throw new Error(\n \"useCatalogueNavigation requires CatalogueNavigationProvider\",\n );\n }\n return navigation;\n}\n\nexport { createUrlNavigation } from \"./url-navigation\";\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cart/theme-class.tsx"],"names":[],"mappings":";;;AAEA,IAAM,UAAA,GAAa,cAAkC,MAAS,CAAA;AACvD,IAAM,qBAAqB,UAAA,CAAW;AAMtC,SAAS,cAAc,SAAA,EAAmB;AAC/C,EAAA,MAAM,UAAA,GAAa,WAAW,UAAU,CAAA;AACxC,EAAA,OAAO,UAAA,GAAa,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA,GAAK,SAAA;AACrD","file":"chunk-JFEI2OUZ.js","sourcesContent":["\"use client\";\nimport { createContext, useContext } from \"react\";\nconst ThemeClass = createContext<string | undefined>(undefined);\nexport const ThemeClassProvider = ThemeClass.Provider;\n/**\n * Class names for an overlay root, plus the class a template passed to\n * `CartReview`. Overlays render in a portal, outside any template wrapper, so\n * a template's tokens reach them only through this class.\n */\nexport function useThemeClass(className: string) {\n const themeClass = useContext(ThemeClass);\n return themeClass ? `${className} ${themeClass}` : className;\n}\n"]}
|
package/dist/chunk-NTJONY3N.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext } from 'react';
|
|
2
|
-
import { jsx } from 'react/jsx-runtime';
|
|
3
|
-
|
|
4
|
-
// src/address.tsx
|
|
5
|
-
function deliveryAddress(place, source) {
|
|
6
|
-
const result = {
|
|
7
|
-
line1: place.line1,
|
|
8
|
-
placeId: place.place_id,
|
|
9
|
-
coordinates: { lat: place.lat, lng: place.lng }
|
|
10
|
-
};
|
|
11
|
-
if (place.city !== void 0) {
|
|
12
|
-
result.city = place.city;
|
|
13
|
-
}
|
|
14
|
-
if (source?.line2 !== void 0) {
|
|
15
|
-
result.line2 = source.line2;
|
|
16
|
-
}
|
|
17
|
-
if (source?.instructions !== void 0) {
|
|
18
|
-
result.instructions = source.instructions;
|
|
19
|
-
}
|
|
20
|
-
return result;
|
|
21
|
-
}
|
|
22
|
-
var Context = createContext(null);
|
|
23
|
-
function AddressLookupProvider({
|
|
24
|
-
lookup,
|
|
25
|
-
children
|
|
26
|
-
}) {
|
|
27
|
-
return /* @__PURE__ */ jsx(Context.Provider, { value: lookup, children });
|
|
28
|
-
}
|
|
29
|
-
function useAddressLookup() {
|
|
30
|
-
const lookup = useContext(Context);
|
|
31
|
-
if (!lookup) {
|
|
32
|
-
throw new Error("useAddressLookup requires AddressLookupProvider");
|
|
33
|
-
}
|
|
34
|
-
return lookup;
|
|
35
|
-
}
|
|
36
|
-
function createSdkAddressLookup({
|
|
37
|
-
places,
|
|
38
|
-
branchId
|
|
39
|
-
}) {
|
|
40
|
-
let sessionToken = crypto.randomUUID();
|
|
41
|
-
const Map = ({ address }) => {
|
|
42
|
-
if (!address.coordinates) {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
return (
|
|
46
|
-
// The theme can't use next/image; the map's size is fixed by the API.
|
|
47
|
-
// eslint-disable-next-line @next/next/no-img-element
|
|
48
|
-
/* @__PURE__ */ jsx(
|
|
49
|
-
"img",
|
|
50
|
-
{
|
|
51
|
-
className: "z-base-address-map",
|
|
52
|
-
src: places.staticMapUrl(
|
|
53
|
-
address.coordinates.lat,
|
|
54
|
-
address.coordinates.lng,
|
|
55
|
-
branchId
|
|
56
|
-
),
|
|
57
|
-
alt: `Map of ${address.line1}`,
|
|
58
|
-
width: 640,
|
|
59
|
-
height: 320,
|
|
60
|
-
loading: "lazy"
|
|
61
|
-
}
|
|
62
|
-
)
|
|
63
|
-
);
|
|
64
|
-
};
|
|
65
|
-
return {
|
|
66
|
-
async suggest(query) {
|
|
67
|
-
const suggestions = await places.autocomplete(query, sessionToken);
|
|
68
|
-
return suggestions.map((suggestion) => ({
|
|
69
|
-
placeId: suggestion.place_id,
|
|
70
|
-
address: suggestion.secondary ? `${suggestion.text}, ${suggestion.secondary}` : suggestion.text,
|
|
71
|
-
sessionToken
|
|
72
|
-
}));
|
|
73
|
-
},
|
|
74
|
-
async resolve(address, token) {
|
|
75
|
-
if (!address.placeId) {
|
|
76
|
-
throw new Error("Choose a suggested delivery address");
|
|
77
|
-
}
|
|
78
|
-
const place = await places.place(address.placeId, {
|
|
79
|
-
branchId,
|
|
80
|
-
sessionToken: token ?? sessionToken
|
|
81
|
-
});
|
|
82
|
-
sessionToken = crypto.randomUUID();
|
|
83
|
-
return deliveryAddress(place, address);
|
|
84
|
-
},
|
|
85
|
-
async reverse({ lat, lng }) {
|
|
86
|
-
const place = await places.reverse(lat, lng);
|
|
87
|
-
return deliveryAddress(place);
|
|
88
|
-
},
|
|
89
|
-
Map
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export { AddressLookupProvider, createSdkAddressLookup, useAddressLookup };
|
|
94
|
-
//# sourceMappingURL=chunk-NTJONY3N.js.map
|
|
95
|
-
//# sourceMappingURL=chunk-NTJONY3N.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/address.tsx"],"names":[],"mappings":"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","file":"chunk-NTJONY3N.js","sourcesContent":["\"use client\";\n\nimport type { DeliveryAddress } from \"@zappie/sdk\";\nimport type { Place, PlacesClient } from \"@zappie/sdk/places\";\nimport {\n createContext,\n useContext,\n type ComponentType,\n type ReactNode,\n} from \"react\";\n\nexport type AddressSuggestion = {\n placeId: string;\n address: string;\n sessionToken?: string;\n};\n\nexport type AddressLookup = {\n suggest(query: string): Promise<AddressSuggestion[]>;\n reverse?(coordinates: { lat: number; lng: number }): Promise<DeliveryAddress>;\n resolve?(\n address: DeliveryAddress,\n sessionToken?: string,\n ): Promise<DeliveryAddress>;\n Map?: ComponentType<{ address: DeliveryAddress }>;\n};\n\nfunction deliveryAddress(\n place: Place,\n source?: DeliveryAddress,\n): DeliveryAddress {\n const result: DeliveryAddress = {\n line1: place.line1,\n placeId: place.place_id,\n coordinates: { lat: place.lat, lng: place.lng },\n };\n if (place.city !== undefined) {\n result.city = place.city;\n }\n if (source?.line2 !== undefined) {\n result.line2 = source.line2;\n }\n if (source?.instructions !== undefined) {\n result.instructions = source.instructions;\n }\n return result;\n}\n\nconst Context = createContext<AddressLookup | null>(null);\n\nexport function AddressLookupProvider({\n lookup,\n children,\n}: {\n lookup: AddressLookup;\n children: ReactNode;\n}) {\n return <Context.Provider value={lookup}>{children}</Context.Provider>;\n}\n\nexport function useAddressLookup() {\n const lookup = useContext(Context);\n if (!lookup) {\n throw new Error(\"useAddressLookup requires AddressLookupProvider\");\n }\n return lookup;\n}\n\nexport function createSdkAddressLookup({\n places,\n branchId,\n}: {\n places: PlacesClient;\n branchId: string;\n}): AddressLookup {\n let sessionToken = crypto.randomUUID();\n const Map = ({ address }: { address: DeliveryAddress }) => {\n if (!address.coordinates) {\n return null;\n }\n return (\n // The theme can't use next/image; the map's size is fixed by the API.\n // eslint-disable-next-line @next/next/no-img-element\n <img\n className=\"z-base-address-map\"\n src={places.staticMapUrl(\n address.coordinates.lat,\n address.coordinates.lng,\n branchId,\n )}\n alt={`Map of ${address.line1}`}\n width={640}\n height={320}\n loading=\"lazy\"\n />\n );\n };\n return {\n async suggest(query) {\n const suggestions = await places.autocomplete(query, sessionToken);\n return suggestions.map((suggestion) => ({\n placeId: suggestion.place_id,\n address: suggestion.secondary\n ? `${suggestion.text}, ${suggestion.secondary}`\n : suggestion.text,\n sessionToken,\n }));\n },\n async resolve(address, token) {\n if (!address.placeId) {\n throw new Error(\"Choose a suggested delivery address\");\n }\n const place = await places.place(address.placeId, {\n branchId,\n sessionToken: token ?? sessionToken,\n });\n sessionToken = crypto.randomUUID();\n return deliveryAddress(place, address);\n },\n async reverse({ lat, lng }) {\n const place = await places.reverse(lat, lng);\n return deliveryAddress(place);\n },\n Map,\n };\n}\n"]}
|
package/dist/chunk-QWST2TA2.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext } from 'react';
|
|
2
|
-
import { jsx } from 'react/jsx-runtime';
|
|
3
|
-
|
|
4
|
-
// src/host-bridge.tsx
|
|
5
|
-
var Context = createContext(null);
|
|
6
|
-
function BaseHostBridgeProvider({
|
|
7
|
-
bridge,
|
|
8
|
-
children
|
|
9
|
-
}) {
|
|
10
|
-
return /* @__PURE__ */ jsx(Context.Provider, { value: bridge, children });
|
|
11
|
-
}
|
|
12
|
-
function useBaseHostBridge() {
|
|
13
|
-
const bridge = useContext(Context);
|
|
14
|
-
if (!bridge) {
|
|
15
|
-
throw new Error("useBaseHostBridge requires BaseHostBridgeProvider");
|
|
16
|
-
}
|
|
17
|
-
return bridge;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export { BaseHostBridgeProvider, useBaseHostBridge };
|
|
21
|
-
//# sourceMappingURL=chunk-QWST2TA2.js.map
|
|
22
|
-
//# sourceMappingURL=chunk-QWST2TA2.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/host-bridge.tsx"],"names":[],"mappings":";;;;AAuFA,IAAM,OAAA,GAAU,cAAqC,IAAI,CAAA;AAClD,SAAS,sBAAA,CAAuB;AAAA,EACrC,MAAA;AAAA,EACA;AACF,CAAA,EAGG;AACD,EAAA,2BAAQ,OAAA,CAAQ,QAAA,EAAR,EAAiB,KAAA,EAAO,QAAS,QAAA,EAAS,CAAA;AACpD;AACO,SAAS,iBAAA,GAAoB;AAClC,EAAA,MAAM,MAAA,GAAS,WAAW,OAAO,CAAA;AACjC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,MAAM,mDAAmD,CAAA;AAAA,EACrE;AACA,EAAA,OAAO,MAAA;AACT","file":"chunk-QWST2TA2.js","sourcesContent":["\"use client\";\nimport type { CartFulfilment, Money, OpeningTime } from \"@zappie/sdk\";\nimport { createContext, useContext, type ReactNode } from \"react\";\n\nexport type { AddressSuggestion } from \"./address\";\nexport type HostPromo = {\n id: string;\n name: string;\n description: string;\n code: string;\n disabled: boolean;\n endsAt?: string;\n};\nexport type HostReward = {\n id: string;\n name: string;\n description: string;\n pointsCost: number;\n disabled: boolean;\n reward: string;\n};\nexport type HostAppliedReward = {\n redemptionId: string;\n perkId: string;\n name: string;\n pointsSpent: number;\n};\n/** Temporary Stage A integration. Themes never import host stores or payment implementations. */\nexport type BaseHostBridge = {\n /**\n * Host-optimised, responsive URLs for a merchant image at the given\n * `sizes`. Absent, themes load the original URL.\n */\n imageProps?(\n src: string,\n sizes: string,\n ): { src: string; srcSet?: string; sizes?: string };\n /**\n * Recoverable host synchronization or checkout failure for the cart screen.\n * Host checkout failures are reported here, so callers don't show them again.\n */\n error?: string | null;\n /** Host-owned mode capabilities during Stage A. */\n fulfilmentMode?: \"delivery\" | \"pickup\";\n scheduleMaxDays?: number;\n /** Delivery regions, when the branch prices delivery by region (else absent). */\n deliveryRegions?: { id: string; name: string; fee: Money }[];\n deliveryRegionId?: string;\n setDeliveryRegion?(id: string): void;\n /**\n * Details the business requires before payment (absent when it requires\n * none). Values start from the customer's profile; the host saves them to\n * the profile when the order is confirmed.\n */\n customerDetails?: {\n requiresEmail: boolean;\n values: CustomerDetailsValues;\n update(field: keyof CustomerDetailsValues, value: string): void;\n };\n /** Opening hours the host accepts scheduled orders in (may start later than the branch's). */\n scheduleOpeningTimes?: OpeningTime[];\n saveFulfilment?: (value: CartFulfilment) => void;\n availablePromos?: HostPromo[];\n rewards?: {\n balance: number;\n items: HostReward[];\n applied: HostAppliedReward[];\n busyPerkId?: string;\n redeem(perkId: string): Promise<void>;\n cancel(redemptionId: string): Promise<void>;\n };\n deliveryDistance?: {\n status: \"unknown\" | \"far\" | \"too_far\";\n message?: string;\n };\n /**\n * Switches the host between delivery and pickup. The host keeps a basket per\n * mode, so the cart remounts against the other basket; returns false when the\n * branch or menu does not allow the switch.\n */\n setFulfilmentMode(mode: \"delivery\" | \"pickup\"): boolean;\n};\nexport type CustomerDetailsValues = {\n firstName: string;\n lastName: string;\n email: string;\n};\nconst Context = createContext<BaseHostBridge | null>(null);\nexport function BaseHostBridgeProvider({\n bridge,\n children,\n}: {\n bridge: BaseHostBridge;\n children: ReactNode;\n}) {\n return <Context.Provider value={bridge}>{children}</Context.Provider>;\n}\nexport function useBaseHostBridge() {\n const bridge = useContext(Context);\n if (!bridge) {\n throw new Error(\"useBaseHostBridge requires BaseHostBridgeProvider\");\n }\n return bridge;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/catalogue/presentation.tsx"],"names":[],"mappings":";;;;;;AAKA,IAAM,QAAA,GAAW,uBAAuB,aAAa,CAAA;AAC9C,SAAS,WAAA,CAAY,EAAE,KAAA,EAAM,EAAsB;AACxD,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,EAAE,CAAA;AACnC,EAAA,SAAA,CAAU,MAAM,QAAQ,QAAA,CAAS,KAAK,CAAC,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AACjD,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,oBAAA;AAAA,MACV,uBAAA,EAAyB,EAAE,MAAA,EAAQ,IAAA;AAAK;AAAA,GAC1C;AAEJ;AACO,SAAS,SAAA,CAAU;AAAA,EACxB,GAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA,GAAW;AACb,CAAA,EAMG;AACD,EAAA,MAAM,SAAS,iBAAA,EAAkB;AACjC,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAS,KAAK,CAAA;AAC1C,EAAA,SAAA,CAAU,MAAM,SAAA,CAAU,KAAK,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AACvC,EAAA,MAAM,KAAA,GAAQ,MAAO,MAAA,CAAO,UAAA,GAAa,KAAK,KAAK,CAAA,IAAK,EAAE,GAAA,EAAI,GAAK,MAAA;AACnE,EAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mBAAA,EACZ,mBAAS,CAAC,MAAA;AAAA;AAAA;AAAA;AAAA,oBAIT,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACE,GAAG,KAAA;AAAA,QACJ,OAAA,EAAS,WAAW,OAAA,GAAU,MAAA;AAAA,QAC9B,aAAA,EAAe,WAAW,MAAA,GAAS,MAAA;AAAA,QACnC,QAAA,EAAS,OAAA;AAAA,QACT,GAAA,EAAI,EAAA;AAAA,QACJ,OAAA,EAAS,MAAM,SAAA,CAAU,IAAI;AAAA;AAAA;AAC/B,sBAEA,GAAA,CAAC,MAAA,EAAA,EAAK,aAAA,EAAY,MAAA,EAAO,+BAAiB,CAAA,EAE9C,CAAA;AAEJ","file":"chunk-USSLDBDY.js","sourcesContent":["\"use client\";\nimport { createSanitizeRichText } from \"@zappie/foundations/rich-text\";\nimport { parseRichText } from \"@zappie/foundations/rich-text/browser\";\nimport { useEffect, useState } from \"react\";\nimport { useBaseHostBridge } from \"../host-bridge\";\nconst sanitize = createSanitizeRichText(parseRichText);\nexport function Description({ value }: { value: string }) {\n const [html, setHtml] = useState(\"\");\n useEffect(() => setHtml(sanitize(value)), [value]);\n return (\n <div\n className=\"z-base-description\"\n dangerouslySetInnerHTML={{ __html: html }}\n />\n );\n}\nexport function ItemImage({\n src,\n sizes,\n priority = false,\n}: {\n src?: string | undefined;\n /** Rendered width hint for responsive host images. */\n sizes: string;\n /** Tiles likely to be the largest paint load first instead of lazily. */\n priority?: boolean;\n}) {\n const bridge = useBaseHostBridge();\n const [failed, setFailed] = useState(false);\n useEffect(() => setFailed(false), [src]);\n const image = src ? (bridge.imageProps?.(src, sizes) ?? { src }) : undefined;\n return (\n <div className=\"z-base-item-image\">\n {image && !failed ? (\n // Public themes remain framework independent; the host may optimise\n // image URLs through the bridge.\n // eslint-disable-next-line @next/next/no-img-element\n <img\n {...image}\n loading={priority ? \"eager\" : \"lazy\"}\n fetchPriority={priority ? \"high\" : \"auto\"}\n decoding=\"async\"\n alt=\"\"\n onError={() => setFailed(true)}\n />\n ) : (\n <span aria-hidden=\"true\">Image unavailable</span>\n )}\n </div>\n );\n}\n"]}
|
package/dist/chunk-VIAJ27YC.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { ThemeClassProvider } from './chunk-JFEI2OUZ.js';
|
|
2
|
-
import { Overlay } from '@zappie/foundations';
|
|
3
|
-
import { createContext, useRef } from 'react';
|
|
4
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
|
-
|
|
6
|
-
var ItemEscapeContext = createContext(null);
|
|
7
|
-
function ItemFrame({
|
|
8
|
-
id,
|
|
9
|
-
name,
|
|
10
|
-
hasImages,
|
|
11
|
-
navigation,
|
|
12
|
-
themeClass,
|
|
13
|
-
children
|
|
14
|
-
}) {
|
|
15
|
-
const escape = useRef(void 0);
|
|
16
|
-
const classes = [
|
|
17
|
-
"z-base-cart z-base-item",
|
|
18
|
-
hasImages ? "z-base-item-with-media" : "",
|
|
19
|
-
themeClass
|
|
20
|
-
].filter(Boolean).join(" ");
|
|
21
|
-
return /* @__PURE__ */ jsx(ItemEscapeContext.Provider, { value: escape, children: /* @__PURE__ */ jsx(ThemeClassProvider, { value: themeClass, children: /* @__PURE__ */ jsx(
|
|
22
|
-
Overlay.Root,
|
|
23
|
-
{
|
|
24
|
-
param: "modal_id",
|
|
25
|
-
id: `product_${id}`,
|
|
26
|
-
navigation,
|
|
27
|
-
presentation: { base: "drawer", lg: "dialog" },
|
|
28
|
-
children: /* @__PURE__ */ jsxs(
|
|
29
|
-
Overlay.Content,
|
|
30
|
-
{
|
|
31
|
-
"data-zappie-theme": "base",
|
|
32
|
-
className: classes,
|
|
33
|
-
"aria-label": name,
|
|
34
|
-
onEscape: (event) => {
|
|
35
|
-
if (escape.current) {
|
|
36
|
-
event.preventDefault();
|
|
37
|
-
escape.current();
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
children: [
|
|
41
|
-
/* @__PURE__ */ jsx("header", { className: "z-base-item-header", children: /* @__PURE__ */ jsx(
|
|
42
|
-
Overlay.Close,
|
|
43
|
-
{
|
|
44
|
-
className: "z-base-button-secondary",
|
|
45
|
-
"aria-label": "Close product",
|
|
46
|
-
children: "\u2715"
|
|
47
|
-
}
|
|
48
|
-
) }),
|
|
49
|
-
children
|
|
50
|
-
]
|
|
51
|
-
}
|
|
52
|
-
)
|
|
53
|
-
}
|
|
54
|
-
) }) });
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export { ItemEscapeContext, ItemFrame };
|
|
58
|
-
//# sourceMappingURL=chunk-VIAJ27YC.js.map
|
|
59
|
-
//# sourceMappingURL=chunk-VIAJ27YC.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/item/frame.tsx"],"names":[],"mappings":";;;;;AAIO,IAAM,iBAAA,GAAoB,cAEvB,IAAI;AAEP,SAAS,SAAA,CAAU;AAAA,EACxB,EAAA;AAAA,EACA,IAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,EAOG;AACD,EAAA,MAAM,MAAA,GAAS,OAAiC,MAAS,CAAA;AACzD,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,yBAAA;AAAA,IACA,YAAY,wBAAA,GAA2B,EAAA;AAAA,IACvC;AAAA,GACF,CACG,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AACX,EAAA,uBACE,GAAA,CAAC,kBAAkB,QAAA,EAAlB,EAA2B,OAAO,MAAA,EACjC,QAAA,kBAAA,GAAA,CAAC,kBAAA,EAAA,EAAmB,KAAA,EAAO,UAAA,EACzB,QAAA,kBAAA,GAAA;AAAA,IAAC,OAAA,CAAQ,IAAA;AAAA,IAAR;AAAA,MACC,KAAA,EAAM,UAAA;AAAA,MACN,EAAA,EAAI,WAAW,EAAE,CAAA,CAAA;AAAA,MACjB,UAAA;AAAA,MACA,YAAA,EAAc,EAAE,IAAA,EAAM,QAAA,EAAU,IAAI,QAAA,EAAS;AAAA,MAE7C,QAAA,kBAAA,IAAA;AAAA,QAAC,OAAA,CAAQ,OAAA;AAAA,QAAR;AAAA,UACC,mBAAA,EAAkB,MAAA;AAAA,UAClB,SAAA,EAAW,OAAA;AAAA,UACX,YAAA,EAAY,IAAA;AAAA,UACZ,QAAA,EAAU,CAAC,KAAA,KAAU;AACnB,YAAA,IAAI,OAAO,OAAA,EAAS;AAClB,cAAA,KAAA,CAAM,cAAA,EAAe;AACrB,cAAA,MAAA,CAAO,OAAA,EAAQ;AAAA,YACjB;AAAA,UACF,CAAA;AAAA,UAEA,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,QAAA,EAAA,EAAO,WAAU,oBAAA,EAChB,QAAA,kBAAA,GAAA;AAAA,cAAC,OAAA,CAAQ,KAAA;AAAA,cAAR;AAAA,gBACC,SAAA,EAAU,yBAAA;AAAA,gBACV,YAAA,EAAW,eAAA;AAAA,gBACZ,QAAA,EAAA;AAAA;AAAA,aAED,EACF,CAAA;AAAA,YACC;AAAA;AAAA;AAAA;AACH;AAAA,KAEJ,CAAA,EACF,CAAA;AAEJ","file":"chunk-VIAJ27YC.js","sourcesContent":["\"use client\";\nimport { Overlay } from \"@zappie/foundations\";\nimport { createContext, useRef, type ReactNode, type RefObject } from \"react\";\nimport { ThemeClassProvider } from \"../cart/theme-class\";\nexport const ItemEscapeContext = createContext<RefObject<\n (() => void) | undefined\n> | null>(null);\n/** The eager modal frame stays mounted while the configurator chunk loads. */\nexport function ItemFrame({\n id,\n name,\n hasImages,\n navigation,\n themeClass,\n children,\n}: {\n id: string;\n name: string;\n hasImages?: boolean;\n themeClass?: string | undefined;\n children: ReactNode;\n navigation: { isOpen: boolean; open(): void; close(): void };\n}) {\n const escape = useRef<(() => void) | undefined>(undefined);\n const classes = [\n \"z-base-cart z-base-item\",\n hasImages ? \"z-base-item-with-media\" : \"\",\n themeClass,\n ]\n .filter(Boolean)\n .join(\" \");\n return (\n <ItemEscapeContext.Provider value={escape}>\n <ThemeClassProvider value={themeClass}>\n <Overlay.Root\n param=\"modal_id\"\n id={`product_${id}`}\n navigation={navigation}\n presentation={{ base: \"drawer\", lg: \"dialog\" }}\n >\n <Overlay.Content\n data-zappie-theme=\"base\"\n className={classes}\n aria-label={name}\n onEscape={(event) => {\n if (escape.current) {\n event.preventDefault();\n escape.current();\n }\n }}\n >\n <header className=\"z-base-item-header\">\n <Overlay.Close\n className=\"z-base-button-secondary\"\n aria-label=\"Close product\"\n >\n ✕\n </Overlay.Close>\n </header>\n {children}\n </Overlay.Content>\n </Overlay.Root>\n </ThemeClassProvider>\n </ItemEscapeContext.Provider>\n );\n}\n"]}
|