@kotao/storefront 0.2.9 → 0.2.11
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/README.md +20 -2
- package/dist/{chunk-PHEKJDFW.js → chunk-4OELOXCN.js} +17 -4
- package/dist/chunk-4OELOXCN.js.map +1 -0
- package/dist/{chunk-OGWYTYYS.js → chunk-GR4QJ7EC.js} +14 -22
- package/dist/chunk-GR4QJ7EC.js.map +1 -0
- package/dist/{chunk-S4HW5NH7.js → chunk-NRWS7HJ2.js} +65 -18
- package/dist/chunk-NRWS7HJ2.js.map +1 -0
- package/dist/{chunk-3YQXJNR7.js → chunk-PWVXOMDE.js} +18 -9
- package/dist/chunk-PWVXOMDE.js.map +1 -0
- package/dist/{client-D-M3Y1ul.d.ts → client-Bt8EEr-K.d.ts} +1 -1
- package/dist/editor.d.ts +1 -1
- package/dist/editor.js +1 -1
- package/dist/events-react.d.ts +2 -2
- package/dist/events.d.ts +2 -2
- package/dist/forms.d.ts +2 -2
- package/dist/image.d.ts +1 -1
- package/dist/image.js +1 -1
- package/dist/index.d.ts +19 -31
- package/dist/index.js +29 -86
- package/dist/index.js.map +1 -1
- package/dist/{pagination-DCrQk02Q.d.ts → pagination-CPgH3fAa.d.ts} +1 -1
- package/dist/product.d.ts +1 -1
- package/dist/react-router.d.ts +18 -6
- package/dist/react-router.js +43 -4
- package/dist/react-router.js.map +1 -1
- package/dist/react.d.ts +17 -7
- package/dist/react.js +50 -21
- package/dist/react.js.map +1 -1
- package/dist/{routing-BYc6JReb.d.ts → routing-hrvYWYEV.d.ts} +3 -1
- package/dist/{shop-keSWbFKV.d.ts → shop-wJdcWcVz.d.ts} +19 -9
- package/dist/{types-CSNXbGFW.d.ts → types-BTUTZXxJ.d.ts} +4 -3
- package/package.json +2 -2
- package/dist/chunk-3YQXJNR7.js.map +0 -1
- package/dist/chunk-OGWYTYYS.js.map +0 -1
- package/dist/chunk-PHEKJDFW.js.map +0 -1
- package/dist/chunk-S4HW5NH7.js.map +0 -1
|
@@ -30,30 +30,18 @@ var GRANTED_CONSENT = Object.freeze({
|
|
|
30
30
|
var CONSENT_COOKIE = "kotao_consent";
|
|
31
31
|
var CONSENT_MAX_AGE = 60 * 60 * 24 * 180;
|
|
32
32
|
function isGranted(state, bucket) {
|
|
33
|
-
return true;
|
|
33
|
+
return state[bucket] === true;
|
|
34
34
|
}
|
|
35
35
|
function mergeConsent(state, patch) {
|
|
36
36
|
return { ...state, ...patch };
|
|
37
37
|
}
|
|
38
38
|
function serializeConsent(state) {
|
|
39
|
-
return
|
|
40
|
-
analytics: state.analytics,
|
|
41
|
-
marketing: state.marketing,
|
|
42
|
-
preferences: state.preferences
|
|
43
|
-
});
|
|
39
|
+
return `v1.${state.analytics ? "1" : "0"}.${state.marketing ? "1" : "0"}.${state.preferences ? "1" : "0"}`;
|
|
44
40
|
}
|
|
45
41
|
function parseConsent(value) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
analytics: parsed.analytics === true,
|
|
51
|
-
marketing: parsed.marketing === true,
|
|
52
|
-
preferences: parsed.preferences === true
|
|
53
|
-
};
|
|
54
|
-
} catch {
|
|
55
|
-
return GRANTED_CONSENT;
|
|
56
|
-
}
|
|
42
|
+
const match = /^v1\.([01])\.([01])\.([01])$/.exec(value ?? "");
|
|
43
|
+
if (match === null) return DENIED_CONSENT;
|
|
44
|
+
return { analytics: match[1] === "1", marketing: match[2] === "1", preferences: match[3] === "1" };
|
|
57
45
|
}
|
|
58
46
|
function buildConsentCookie(state) {
|
|
59
47
|
const value = encodeURIComponent(serializeConsent(state));
|
|
@@ -61,12 +49,16 @@ function buildConsentCookie(state) {
|
|
|
61
49
|
}
|
|
62
50
|
function readConsentCookie(cookieHeader) {
|
|
63
51
|
if (cookieHeader === null || cookieHeader === void 0 || cookieHeader === "")
|
|
64
|
-
return
|
|
52
|
+
return DENIED_CONSENT;
|
|
65
53
|
const match = cookieHeader.split(";").map((part) => part.trim()).find((part) => part.startsWith(`${CONSENT_COOKIE}=`));
|
|
66
|
-
if (match === void 0) return
|
|
67
|
-
|
|
54
|
+
if (match === void 0) return DENIED_CONSENT;
|
|
55
|
+
try {
|
|
56
|
+
return parseConsent(decodeURIComponent(match.slice(CONSENT_COOKIE.length + 1)));
|
|
57
|
+
} catch {
|
|
58
|
+
return DENIED_CONSENT;
|
|
59
|
+
}
|
|
68
60
|
}
|
|
69
61
|
|
|
70
62
|
export { CART_FORM_ACTIONS, CONSENT_BUCKETS, CONSENT_COOKIE, DENIED_CONSENT, GRANTED_CONSENT, buildConsentCookie, isGranted, mergeConsent, parseConsent, readConsentCookie, serializeConsent };
|
|
71
|
-
//# sourceMappingURL=chunk-
|
|
72
|
-
//# sourceMappingURL=chunk-
|
|
63
|
+
//# sourceMappingURL=chunk-GR4QJ7EC.js.map
|
|
64
|
+
//# sourceMappingURL=chunk-GR4QJ7EC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cart/actions.ts","../src/analytics/consent.ts"],"names":[],"mappings":"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","file":"chunk-GR4QJ7EC.js","sourcesContent":["export const CART_FORM_ACTIONS = Object.freeze({\n LinesAdd: 'LinesAdd',\n LinesUpdate: 'LinesUpdate',\n LinesRemove: 'LinesRemove',\n DiscountCodesUpdate: 'DiscountCodesUpdate',\n GiftCardCodesAdd: 'GiftCardCodesAdd',\n GiftCardCodesRemove: 'GiftCardCodesRemove',\n BuyerIdentityUpdate: 'BuyerIdentityUpdate',\n NoteUpdate: 'NoteUpdate',\n AttributesUpdate: 'AttributesUpdate',\n MetafieldsSet: 'MetafieldsSet',\n MetafieldsDelete: 'MetafieldsDelete',\n DeliveryAddressesReplace: 'DeliveryAddressesReplace',\n SelectedDeliveryOptionsUpdate: 'SelectedDeliveryOptionsUpdate',\n} as const)\n\nexport type CartFormAction = (typeof CART_FORM_ACTIONS)[keyof typeof CART_FORM_ACTIONS]\n","/**\n * Shared native-CMP consent state. Unknown choices deny optional categories; the versioned cookie\n * is the same contract used by dispatch and checkout.\n */\nexport type ConsentBucket = 'analytics' | 'marketing' | 'preferences'\nexport type ConsentState = Readonly<Record<ConsentBucket, boolean>>\n\nexport const CONSENT_BUCKETS: readonly ConsentBucket[] = ['analytics', 'marketing', 'preferences']\nexport const DENIED_CONSENT: ConsentState = Object.freeze({\n analytics: false,\n marketing: false,\n preferences: false,\n})\nexport const GRANTED_CONSENT: ConsentState = Object.freeze({\n analytics: true,\n marketing: true,\n preferences: true,\n})\n\nexport const CONSENT_COOKIE = 'kotao_consent'\nconst CONSENT_MAX_AGE = 60 * 60 * 24 * 180 // ~180 days\n\nexport function isGranted(state: ConsentState, bucket: ConsentBucket): boolean {\n return state[bucket] === true\n}\n\nexport function mergeConsent(state: ConsentState, patch: Partial<ConsentState>): ConsentState {\n return { ...state, ...patch }\n}\n\nexport function serializeConsent(state: ConsentState): string {\n return `v1.${state.analytics ? '1' : '0'}.${state.marketing ? '1' : '0'}.${state.preferences ? '1' : '0'}`\n}\n\nexport function parseConsent(value: string | null | undefined): ConsentState {\n const match = /^v1\\.([01])\\.([01])\\.([01])$/.exec(value ?? '')\n if (match === null) return DENIED_CONSENT\n return { analytics: match[1] === '1', marketing: match[2] === '1', preferences: match[3] === '1' }\n}\n\n/** The `document.cookie` string to persist consent (Secure, SameSite=Lax, Path=/, ~180d). */\nexport function buildConsentCookie(state: ConsentState): string {\n const value = encodeURIComponent(serializeConsent(state))\n return `${CONSENT_COOKIE}=${value}; Path=/; Max-Age=${CONSENT_MAX_AGE}; SameSite=Lax; Secure`\n}\n\n/** Read the consent cookie out of a `document.cookie`-style string. */\nexport function readConsentCookie(cookieHeader: string | null | undefined): ConsentState {\n if (cookieHeader === null || cookieHeader === undefined || cookieHeader === '')\n return DENIED_CONSENT\n const match = cookieHeader\n .split(';')\n .map((part) => part.trim())\n .find((part) => part.startsWith(`${CONSENT_COOKIE}=`))\n if (match === undefined) return DENIED_CONSENT\n try {\n return parseConsent(decodeURIComponent(match.slice(CONSENT_COOKIE.length + 1)))\n } catch {\n return DENIED_CONSENT\n }\n}\n"]}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { CART_FORM_ACTIONS } from './chunk-
|
|
2
|
-
import * as ReactRuntime from 'react';
|
|
3
|
-
import { createContext, createElement, useContext } from 'react';
|
|
1
|
+
import { CART_FORM_ACTIONS } from './chunk-GR4QJ7EC.js';
|
|
4
2
|
|
|
5
3
|
// src/cart/CartForm.ts
|
|
6
4
|
function parseFormValue(value) {
|
|
@@ -34,21 +32,70 @@ var CartForm = Object.assign(
|
|
|
34
32
|
},
|
|
35
33
|
{ ACTIONS: CART_FORM_ACTIONS, getFormInput: getCartFormInput }
|
|
36
34
|
);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
|
|
36
|
+
// src/content-security-policy.ts
|
|
37
|
+
var QUOTED_TOKENS = /* @__PURE__ */ new Set([
|
|
38
|
+
"self",
|
|
39
|
+
"none",
|
|
40
|
+
"unsafe-eval",
|
|
41
|
+
"unsafe-hashes",
|
|
42
|
+
"unsafe-inline",
|
|
43
|
+
"strict-dynamic",
|
|
44
|
+
"wasm-unsafe-eval"
|
|
45
|
+
]);
|
|
46
|
+
function createContentSecurityPolicy(options = {}) {
|
|
47
|
+
const nonce = createNonce();
|
|
48
|
+
const shopDomains = shopSources(options.shop);
|
|
49
|
+
const scriptSrc = uniqueSources([
|
|
50
|
+
...normalizeSources(options.scriptSrc ?? ["self"]),
|
|
51
|
+
`'nonce-${nonce}'`
|
|
52
|
+
]);
|
|
53
|
+
const connectSrc = uniqueSources([
|
|
54
|
+
"'self'",
|
|
55
|
+
...shopDomains,
|
|
56
|
+
...normalizeSources(options.connectSrc)
|
|
57
|
+
]);
|
|
58
|
+
const imgSrc = uniqueSources([
|
|
59
|
+
"'self'",
|
|
60
|
+
"data:",
|
|
61
|
+
"https:",
|
|
62
|
+
...shopDomains,
|
|
63
|
+
...normalizeSources(options.imgSrc)
|
|
64
|
+
]);
|
|
65
|
+
const styleSrc = uniqueSources(["'self'", "'unsafe-inline'", ...normalizeSources(options.styleSrc)]);
|
|
66
|
+
const directives = [
|
|
67
|
+
["base-uri", ["'self'"]],
|
|
68
|
+
["default-src", ["'self'"]],
|
|
69
|
+
["connect-src", connectSrc],
|
|
70
|
+
["img-src", imgSrc],
|
|
71
|
+
["script-src", scriptSrc],
|
|
72
|
+
["style-src", styleSrc]
|
|
73
|
+
];
|
|
74
|
+
return {
|
|
75
|
+
nonce,
|
|
76
|
+
header: directives.map(([name, values]) => `${name} ${values.join(" ")}`).join("; ")
|
|
41
77
|
};
|
|
42
78
|
}
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
|
|
79
|
+
function createNonce() {
|
|
80
|
+
const bytes = new Uint8Array(18);
|
|
81
|
+
crypto.getRandomValues(bytes);
|
|
82
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
83
|
+
}
|
|
84
|
+
function shopSources(shop) {
|
|
85
|
+
if (shop === void 0) return [];
|
|
86
|
+
return [shop.storeDomain, shop.checkoutDomain].filter((domain) => domain !== void 0 && domain.trim() !== "").map((domain) => {
|
|
87
|
+
const trimmed = domain.trim();
|
|
88
|
+
return /^https?:\/\//i.test(trimmed) ? new URL(trimmed).origin : `https://${trimmed}`;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function normalizeSources(sources) {
|
|
92
|
+
return (sources ?? []).map((source) => {
|
|
93
|
+
const trimmed = source.trim();
|
|
94
|
+
return QUOTED_TOKENS.has(trimmed) ? `'${trimmed}'` : trimmed;
|
|
95
|
+
});
|
|
46
96
|
}
|
|
47
|
-
function
|
|
48
|
-
|
|
49
|
-
return Boolean(
|
|
50
|
-
runtime.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE?.H ?? runtime.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED?.ReactCurrentDispatcher?.current
|
|
51
|
-
);
|
|
97
|
+
function uniqueSources(sources) {
|
|
98
|
+
return Array.from(new Set(sources.filter((source) => source.length > 0)));
|
|
52
99
|
}
|
|
53
100
|
|
|
54
101
|
// src/analytics/attribution.ts
|
|
@@ -161,6 +208,6 @@ function createPixelTransport(options) {
|
|
|
161
208
|
};
|
|
162
209
|
}
|
|
163
210
|
|
|
164
|
-
export { CartForm, collectAnalyticsAttribution, createAnalyticsBus, createAnalyticsEmitter,
|
|
165
|
-
//# sourceMappingURL=chunk-
|
|
166
|
-
//# sourceMappingURL=chunk-
|
|
211
|
+
export { CartForm, collectAnalyticsAttribution, createAnalyticsBus, createAnalyticsEmitter, createContentSecurityPolicy, createPixelTransport, getCartFormInput };
|
|
212
|
+
//# sourceMappingURL=chunk-NRWS7HJ2.js.map
|
|
213
|
+
//# sourceMappingURL=chunk-NRWS7HJ2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cart/CartForm.ts","../src/content-security-policy.ts","../src/analytics/attribution.ts","../src/analytics/emitter.ts","../src/analytics/analytics-bus.ts","../src/analytics/pixel-transport.ts"],"names":["CartForm"],"mappings":"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","file":"chunk-NRWS7HJ2.js","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { CART_FORM_ACTIONS, type CartFormAction } from './actions'\n\nexport interface CartFormProps {\n readonly action: CartFormAction\n}\n\nexport interface CartFormInputResult {\n readonly action: CartFormAction | null\n readonly inputs: Record<string, any>\n}\n\nfunction parseFormValue(value: unknown): unknown {\n if (typeof value !== 'string') return value\n const trimmed = value.trim()\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n try {\n return JSON.parse(trimmed) as unknown\n } catch {\n return value\n }\n }\n return value\n}\n\nexport function getCartFormInput(formData: FormData): CartFormInputResult {\n const action = formData.get('cartAction')\n const inputs: Record<string, any> = {}\n for (const key of new Set(formData.keys())) {\n if (key === 'cartAction') continue\n const values = formData.getAll(key).map(parseFormValue)\n inputs[key] = values.length === 1 ? values[0] : values\n }\n return {\n action: typeof action === 'string' ? (action as CartFormAction) : null,\n inputs,\n }\n}\n\n/**\n * Lightweight CartForm surface marker for Hydrogen-style imports. React render integration can wrap\n * this constant surface; the load-bearing API today is the stable ACTIONS contract used by handlers.\n */\nexport const CartForm = Object.assign(\n function CartForm(_props: CartFormProps): null {\n return null\n },\n { ACTIONS: CART_FORM_ACTIONS, getFormInput: getCartFormInput },\n)\n","export interface ContentSecurityPolicyShop {\n readonly checkoutDomain?: string\n readonly storeDomain?: string\n}\n\nexport interface CreateContentSecurityPolicyOptions {\n readonly shop?: ContentSecurityPolicyShop\n readonly scriptSrc?: readonly string[]\n readonly connectSrc?: readonly string[]\n readonly imgSrc?: readonly string[]\n readonly styleSrc?: readonly string[]\n}\n\nexport interface ContentSecurityPolicyResult {\n readonly nonce: string\n readonly header: string\n}\n\nconst QUOTED_TOKENS = new Set([\n 'self',\n 'none',\n 'unsafe-eval',\n 'unsafe-hashes',\n 'unsafe-inline',\n 'strict-dynamic',\n 'wasm-unsafe-eval',\n])\n\nexport function createContentSecurityPolicy(\n options: CreateContentSecurityPolicyOptions = {},\n): ContentSecurityPolicyResult {\n const nonce = createNonce()\n const shopDomains = shopSources(options.shop)\n const scriptSrc = uniqueSources([\n ...normalizeSources(options.scriptSrc ?? ['self']),\n `'nonce-${nonce}'`,\n ])\n const connectSrc = uniqueSources([\n \"'self'\",\n ...shopDomains,\n ...normalizeSources(options.connectSrc),\n ])\n const imgSrc = uniqueSources([\n \"'self'\",\n 'data:',\n 'https:',\n ...shopDomains,\n ...normalizeSources(options.imgSrc),\n ])\n const styleSrc = uniqueSources([\"'self'\", \"'unsafe-inline'\", ...normalizeSources(options.styleSrc)])\n const directives = [\n ['base-uri', [\"'self'\"]],\n ['default-src', [\"'self'\"]],\n ['connect-src', connectSrc],\n ['img-src', imgSrc],\n ['script-src', scriptSrc],\n ['style-src', styleSrc],\n ]\n return {\n nonce,\n header: directives\n .map(([name, values]) => `${name} ${(values as readonly string[]).join(' ')}`)\n .join('; '),\n }\n}\n\nfunction createNonce(): string {\n const bytes = new Uint8Array(18)\n crypto.getRandomValues(bytes)\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')\n}\n\nfunction shopSources(shop: ContentSecurityPolicyShop | undefined): readonly string[] {\n if (shop === undefined) return []\n return [shop.storeDomain, shop.checkoutDomain]\n .filter((domain): domain is string => domain !== undefined && domain.trim() !== '')\n .map((domain) => {\n const trimmed = domain.trim()\n return /^https?:\\/\\//i.test(trimmed) ? new URL(trimmed).origin : `https://${trimmed}`\n })\n}\n\nfunction normalizeSources(sources: readonly string[] | undefined): readonly string[] {\n return (sources ?? []).map((source) => {\n const trimmed = source.trim()\n return QUOTED_TOKENS.has(trimmed) ? `'${trimmed}'` : trimmed\n })\n}\n\nfunction uniqueSources(sources: readonly string[]): readonly string[] {\n return Array.from(new Set(sources.filter((source) => source.length > 0)))\n}\n","import type { AnalyticsContext, AnalyticsDeviceClass } from './events'\n\nexport interface AnalyticsAttributionEnvironment {\n readonly referrer?: string\n readonly search?: string\n readonly matchMedia?: (query: string) => { readonly matches: boolean }\n}\n\ntype AttributionContext = Pick<\n AnalyticsContext,\n 'referrer' | 'utmSource' | 'utmMedium' | 'utmCampaign' | 'deviceClass'\n>\n\nfunction deviceClass(\n matchMedia: AnalyticsAttributionEnvironment['matchMedia'],\n): AnalyticsDeviceClass | undefined {\n if (matchMedia === undefined) return undefined\n if (matchMedia('(max-width: 767px)').matches) return 'mobile'\n if (matchMedia('(max-width: 1023px)').matches) return 'tablet'\n return 'desktop'\n}\n\n/** Read static landing attribution plus the current responsive device class without retaining state\n * or identifiers. All values stay optional so non-DOM/SSR emitters keep their existing payload. */\nexport function collectAnalyticsAttribution(\n environment: AnalyticsAttributionEnvironment | null,\n): AttributionContext {\n if (environment === null) return {}\n const params = new URLSearchParams(environment.search ?? '')\n const referrer = environment.referrer || undefined\n const utmSource = params.get('utm_source') || undefined\n const utmMedium = params.get('utm_medium') || undefined\n const utmCampaign = params.get('utm_campaign') || undefined\n const classifiedDevice = deviceClass(environment.matchMedia)\n\n return {\n ...(referrer !== undefined ? { referrer } : {}),\n ...(utmSource !== undefined ? { utmSource } : {}),\n ...(utmMedium !== undefined ? { utmMedium } : {}),\n ...(utmCampaign !== undefined ? { utmCampaign } : {}),\n ...(classifiedDevice !== undefined ? { deviceClass: classifiedDevice } : {}),\n }\n}\n","import type { AnalyticsEventMap, AnalyticsEventName } from './events'\n\nexport type EventHandler<E extends AnalyticsEventName> = (payload: AnalyticsEventMap[E]) => void\n\n/** A framework-agnostic typed pub/sub bus (Hydrogen `useAnalytics` shape, minus React). */\nexport interface AnalyticsEmitter {\n subscribe<E extends AnalyticsEventName>(event: E, handler: EventHandler<E>): () => void\n publish<E extends AnalyticsEventName>(event: E, payload: AnalyticsEventMap[E]): void\n}\n\nexport function createAnalyticsEmitter(): AnalyticsEmitter {\n const handlers = new Map<AnalyticsEventName, Set<(payload: unknown) => void>>()\n return {\n subscribe(event, handler) {\n const set = handlers.get(event) ?? new Set<(payload: unknown) => void>()\n const erased = handler as (payload: unknown) => void\n set.add(erased)\n handlers.set(event, set)\n return () => {\n set.delete(erased)\n }\n },\n publish(event, payload) {\n const set = handlers.get(event)\n if (set === undefined) return\n // Snapshot so a handler unsubscribing mid-dispatch doesn't skip a sibling.\n for (const handler of [...set]) {\n try {\n handler(payload)\n } catch {\n // Isolate: a throwing subscriber must not break sibling handlers or the downstream pixel send.\n }\n }\n },\n }\n}\n","import type { AnonymousAnalyticsContext } from './anonymous-context'\nimport type { ConsentState } from './consent'\nimport { createAnalyticsEmitter, type AnalyticsEmitter } from './emitter'\nimport type { AnalyticsContext, AnalyticsEventMap, AnalyticsEventName } from './events'\nimport type { PixelTransport } from './pixel-transport'\n\nexport interface AnalyticsBusOptions {\n readonly transport: PixelTransport\n /** Legacy consent seam retained for API compatibility while Storefront consent UI is disabled. */\n readonly getConsent: () => ConsentState\n /** Ambient context (including attribution and device class) attached to consented events. */\n readonly getContext?: () => AnalyticsContext\n /** Sanitized same-origin page URL used only for the anonymous page-view fallback. */\n readonly getAnonymousContext?: () => AnonymousAnalyticsContext\n /** Clock seam for deterministic timestamps in tests. */\n readonly now?: () => string\n}\n\nexport interface AnalyticsBus {\n readonly emitter: AnalyticsEmitter\n publish<E extends AnalyticsEventName>(event: E, payload: AnalyticsEventMap[E]): void\n flush(): void\n}\n\n/**\n * Wire the emitter to the pixel. Every published event reaches theme subscribers (via the emitter).\n * First-party recording is consent-strict: denied visits get only an anonymous page_viewed row and\n * never evaluate ambient context, which may read attribution or device-class signals.\n */\nexport function createAnalyticsBus(options: AnalyticsBusOptions): AnalyticsBus {\n const emitter = createAnalyticsEmitter()\n const now = options.now ?? ((): string => new Date().toISOString())\n return {\n emitter,\n publish(event, payload) {\n emitter.publish(event, payload)\n const consented = options.getConsent().analytics === true\n if (consented) {\n const context = options.getContext?.() ?? {}\n options.transport.record({ event, payload, context, timestamp: now(), consent: true })\n return\n }\n if (event === 'page_viewed') {\n options.transport.record({\n event,\n payload: {} as AnalyticsEventMap[typeof event],\n context: options.getAnonymousContext?.() ?? {},\n timestamp: now(),\n consent: false,\n })\n }\n },\n flush() {\n options.transport.flush()\n },\n }\n}\n","import type { PixelEvent } from './events'\n\n/** The actual network send. Injectable so tests don't touch the network. */\nexport type PixelSend = (endpoint: string, body: string) => void\n\nexport interface PixelTransportOptions {\n /** Same-origin carve-out endpoint (default '/api/storefront/pixel') — never cross-origin. */\n readonly endpoint?: string\n readonly batchSize?: number\n readonly flushAfterMs?: number\n /**\n * The actual network send. Required + injected: the browser sender (`sendBeacon`/keepalive `fetch`)\n * is DOM-specific and lives in the React layer, keeping this batching core framework-agnostic and\n * unit-testable with a spy. The provider wires the real sender.\n */\n readonly send: PixelSend\n}\n\nexport interface PixelTransport {\n record(event: PixelEvent): void\n flush(): void\n}\n\nconst DEFAULT_ENDPOINT = '/api/storefront/pixel'\nconst DEFAULT_BATCH_SIZE = 10\n\n/**\n * Batches pixel events and POSTs them to the same-origin carve-out. Flushes on `batchSize` or an\n * explicit `flush()` (the provider flushes on page-hide), or after one second. The endpoint is same-origin so themes need\n * no CORS and no token is exposed in the browser.\n */\nexport function createPixelTransport(options: PixelTransportOptions): PixelTransport {\n const endpoint = options.endpoint ?? DEFAULT_ENDPOINT\n // SECURITY: the pixel must stay same-origin (no CORS, no token leak). Reject a non-relative or\n // protocol-relative endpoint so a misconfigured theme can't exfiltrate visitor data (e.g. clientIp).\n if (!/^\\/(?!\\/)/.test(endpoint)) {\n throw new Error(`pixel endpoint must be a same-origin path starting with '/'; got: ${endpoint}`)\n }\n const batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE\n const send = options.send\n let queue: PixelEvent[] = []\n let timer: ReturnType<typeof setTimeout> | undefined\n\n const flush = (): void => {\n if (timer !== undefined) clearTimeout(timer)\n timer = undefined\n if (queue.length === 0) return\n const batch = queue\n queue = []\n send(endpoint, JSON.stringify({ events: batch }))\n }\n\n return {\n record(event) {\n queue.push(event)\n if (queue.length >= batchSize) flush()\n else timer ??= setTimeout(flush, options.flushAfterMs ?? 1000)\n },\n flush,\n }\n}\n"]}
|
|
@@ -13,7 +13,7 @@ function splitCdnCgi(url) {
|
|
|
13
13
|
const [k, v] = pair.split("=");
|
|
14
14
|
if (k && v) opts.set(k, v);
|
|
15
15
|
}
|
|
16
|
-
return { bare: `${u.origin}${path}`, opts };
|
|
16
|
+
return { bare: `${u.origin}${path}${u.search}`, opts };
|
|
17
17
|
}
|
|
18
18
|
var OPT_ORDER = ["width", "height", "fit", "format", "quality"];
|
|
19
19
|
function imageUrl(url, options = {}) {
|
|
@@ -23,11 +23,12 @@ function imageUrl(url, options = {}) {
|
|
|
23
23
|
if (options.height != null) opts.set("height", String(options.height));
|
|
24
24
|
if (options.fit != null) opts.set("fit", options.fit);
|
|
25
25
|
if (options.format != null) opts.set("format", options.format);
|
|
26
|
+
else if (!opts.has("format")) opts.set("format", "auto");
|
|
26
27
|
if (options.quality != null) opts.set("quality", String(options.quality));
|
|
27
28
|
const ordered = OPT_ORDER.filter((k) => opts.has(k)).map((k) => `${k}=${opts.get(k)}`);
|
|
28
29
|
if (ordered.length === 0) return bare;
|
|
29
30
|
const u = new URL(bare);
|
|
30
|
-
return `${u.origin}${CDN_CGI}${ordered.join(",")}${u.pathname}`;
|
|
31
|
+
return `${u.origin}${CDN_CGI}${ordered.join(",")}${u.pathname}${u.search}`;
|
|
31
32
|
}
|
|
32
33
|
function imageSrcSet(url, options) {
|
|
33
34
|
const { widths, ...rest } = options;
|
|
@@ -39,24 +40,32 @@ var DEFAULT_WIDTHS = [320, 640, 768, 1024, 1280, 1536];
|
|
|
39
40
|
var FALLBACK_WIDTH = 1280;
|
|
40
41
|
function buildImageAttrs(options) {
|
|
41
42
|
const url = options.src ?? options.data.url;
|
|
42
|
-
const
|
|
43
|
+
const requestedWidths = options.srcSetWidths ?? (options.width ? [options.width, options.width * 2, options.width * 3] : DEFAULT_WIDTHS);
|
|
44
|
+
const urlTransform = /^https?:\/\/cdn\.kotao\.[^/]+\/cdn-cgi\/image\/([^/]+)/.exec(url)?.[1];
|
|
45
|
+
const urlOptions = new URLSearchParams(urlTransform?.replaceAll(",", "&"));
|
|
46
|
+
const urlWidth = Number(urlOptions.get("width")) || null;
|
|
47
|
+
const urlHeight = Number(urlOptions.get("height")) || null;
|
|
48
|
+
const sourceWidths = [options.data.width, urlWidth].filter((width) => width != null && width > 0);
|
|
49
|
+
const sourceWidth = sourceWidths.length ? Math.min(...sourceWidths) : null;
|
|
50
|
+
const widths = [...new Set(requestedWidths.map((width) => sourceWidth === null ? width : Math.min(width, sourceWidth)))];
|
|
43
51
|
const aspectRatio = options.aspectRatio ?? (options.data.width != null && options.data.height != null ? `${options.data.width}/${options.data.height}` : void 0);
|
|
44
52
|
const transform = {};
|
|
45
53
|
if (options.crop) transform.fit = "cover";
|
|
46
54
|
if (options.format != null) transform.format = options.format;
|
|
47
55
|
if (options.quality != null) transform.quality = options.quality;
|
|
48
|
-
const heightPerWidth = options.width != null && options.height != null ? options.height / options.width : null;
|
|
56
|
+
const heightPerWidth = options.width != null && options.height != null ? options.height / options.width : urlWidth !== null && urlHeight !== null ? urlHeight / urlWidth : null;
|
|
49
57
|
const candidate = (w) => {
|
|
50
58
|
const opts = { ...transform, width: w };
|
|
51
59
|
if (heightPerWidth != null) opts.height = Math.round(w * heightPerWidth);
|
|
52
60
|
return opts;
|
|
53
61
|
};
|
|
54
|
-
const
|
|
55
|
-
|
|
62
|
+
const fallbackWidth = Math.min(options.width ?? FALLBACK_WIDTH, sourceWidth ?? Infinity);
|
|
63
|
+
const srcOptions = candidate(fallbackWidth);
|
|
64
|
+
if (heightPerWidth === null && options.height != null) srcOptions.height = options.height;
|
|
56
65
|
return {
|
|
57
66
|
src: imageUrl(url, srcOptions),
|
|
58
67
|
srcSet: widths.map((w) => `${imageUrl(url, candidate(w))} ${w}w`).join(", "),
|
|
59
|
-
...options.sizes != null ? { sizes: options.sizes } : {},
|
|
68
|
+
...options.sizes != null ? { sizes: options.sizes } : options.width != null ? { sizes: `${options.width}px` } : {},
|
|
60
69
|
...options.width != null ? { width: options.width } : {},
|
|
61
70
|
...options.height != null ? { height: options.height } : {},
|
|
62
71
|
alt: options.data.altText ?? "",
|
|
@@ -66,5 +75,5 @@ function buildImageAttrs(options) {
|
|
|
66
75
|
}
|
|
67
76
|
|
|
68
77
|
export { buildImageAttrs, imageSrcSet, imageUrl };
|
|
69
|
-
//# sourceMappingURL=chunk-
|
|
70
|
-
//# sourceMappingURL=chunk-
|
|
78
|
+
//# sourceMappingURL=chunk-PWVXOMDE.js.map
|
|
79
|
+
//# sourceMappingURL=chunk-PWVXOMDE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/image/image-url.ts","../src/image/image-attrs.ts"],"names":[],"mappings":";AAwBA,IAAM,OAAA,GAAU,iBAAA;AAChB,IAAM,QAAA,GAAW,CAAC,GAAA,KAAyB,0BAAA,CAA2B,KAAK,GAAG,CAAA;AAG9E,SAAS,YAAY,GAAA,EAAsD;AACzE,EAAA,MAAM,CAAA,GAAI,IAAI,GAAA,CAAI,GAAG,CAAA;AACrB,EAAA,IAAI,CAAC,CAAA,CAAE,QAAA,CAAS,UAAA,CAAW,OAAO,CAAA,EAAG,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,IAAA,EAAM,IAAI,iBAAgB,EAAE;AACrF,EAAA,MAAM,IAAA,GAAO,CAAA,CAAE,QAAA,CAAS,KAAA,CAAM,QAAQ,MAAM,CAAA;AAC5C,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AAC9B,EAAA,MAAM,SAAS,KAAA,KAAU,EAAA,GAAK,OAAO,IAAA,CAAK,KAAA,CAAM,GAAG,KAAK,CAAA;AACxD,EAAA,MAAM,OAAO,KAAA,KAAU,EAAA,GAAK,EAAA,GAAK,IAAA,CAAK,MAAM,KAAK,CAAA;AACjD,EAAA,MAAM,IAAA,GAAO,IAAI,eAAA,EAAgB;AACjC,EAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,EAAG;AACpC,IAAA,MAAM,CAAC,CAAA,EAAG,CAAC,CAAA,GAAI,IAAA,CAAK,MAAM,GAAG,CAAA;AAC7B,IAAA,IAAI,CAAA,IAAK,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,GAAG,CAAC,CAAA;AAAA,EAC3B;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,CAAA,EAAG,CAAA,CAAE,MAAM,CAAA,EAAG,IAAI,CAAA,EAAG,CAAA,CAAE,MAAM,CAAA,CAAA,EAAI,IAAA,EAAK;AACvD;AAEA,IAAM,YAAY,CAAC,OAAA,EAAS,QAAA,EAAU,KAAA,EAAO,UAAU,SAAS,CAAA;AASzD,SAAS,QAAA,CAAS,GAAA,EAAa,OAAA,GAA2B,EAAC,EAAW;AAC3E,EAAA,IAAI,CAAC,QAAA,CAAS,GAAG,CAAA,EAAG,OAAO,GAAA;AAC3B,EAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAK,GAAI,YAAY,GAAG,CAAA;AACtC,EAAA,IAAI,OAAA,CAAQ,SAAS,IAAA,EAAM,IAAA,CAAK,IAAI,OAAA,EAAS,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAC,CAAA;AAClE,EAAA,IAAI,OAAA,CAAQ,UAAU,IAAA,EAAM,IAAA,CAAK,IAAI,QAAA,EAAU,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAC,CAAA;AACrE,EAAA,IAAI,QAAQ,GAAA,IAAO,IAAA,OAAW,GAAA,CAAI,KAAA,EAAO,QAAQ,GAAG,CAAA;AACpD,EAAA,IAAI,QAAQ,MAAA,IAAU,IAAA,OAAW,GAAA,CAAI,QAAA,EAAU,QAAQ,MAAM,CAAA;AAAA,OAAA,IACpD,CAAC,KAAK,GAAA,CAAI,QAAQ,GAAG,IAAA,CAAK,GAAA,CAAI,UAAU,MAAM,CAAA;AACvD,EAAA,IAAI,OAAA,CAAQ,WAAW,IAAA,EAAM,IAAA,CAAK,IAAI,SAAA,EAAW,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAC,CAAA;AACxE,EAAA,MAAM,OAAA,GAAU,UAAU,MAAA,CAAO,CAAC,MAAM,IAAA,CAAK,GAAA,CAAI,CAAC,CAAC,CAAA,CAAE,IAAI,CAAC,CAAA,KAAM,GAAG,CAAC,CAAA,CAAA,EAAI,KAAK,GAAA,CAAI,CAAC,CAAC,CAAA,CAAE,CAAA;AACrF,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AACjC,EAAA,MAAM,CAAA,GAAI,IAAI,GAAA,CAAI,IAAI,CAAA;AACtB,EAAA,OAAO,CAAA,EAAG,CAAA,CAAE,MAAM,CAAA,EAAG,OAAO,CAAA,EAAG,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAC,CAAA,EAAG,CAAA,CAAE,QAAQ,CAAA,EAAG,EAAE,MAAM,CAAA,CAAA;AAC1E;AAWO,SAAS,WAAA,CAAY,KAAa,OAAA,EAAqC;AAC5E,EAAA,MAAM,EAAE,MAAA,EAAQ,GAAG,IAAA,EAAK,GAAI,OAAA;AAC5B,EAAA,OAAO,OAAO,GAAA,CAAI,CAAC,UAAU,CAAA,EAAG,QAAA,CAAS,KAAK,EAAE,GAAG,IAAA,EAAM,KAAA,EAAO,CAAC,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,CAAG,CAAA,CAAE,KAAK,IAAI,CAAA;AAC1F;;;AC1BA,IAAM,iBAAiB,CAAC,GAAA,EAAK,KAAK,GAAA,EAAK,IAAA,EAAM,MAAM,IAAI,CAAA;AAEvD,IAAM,cAAA,GAAiB,IAAA;AAEhB,SAAS,gBAAgB,OAAA,EAAwC;AACtE,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,IAAO,OAAA,CAAQ,IAAA,CAAK,GAAA;AAExC,EAAA,MAAM,eAAA,GACJ,OAAA,CAAQ,YAAA,KACP,OAAA,CAAQ,QAAQ,CAAC,OAAA,CAAQ,KAAA,EAAO,OAAA,CAAQ,KAAA,GAAQ,CAAA,EAAG,OAAA,CAAQ,KAAA,GAAQ,CAAC,CAAA,GAAI,cAAA,CAAA;AAG3E,EAAA,MAAM,YAAA,GAAe,wDAAA,CAAyD,IAAA,CAAK,GAAG,IAAI,CAAC,CAAA;AAC3F,EAAA,MAAM,aAAa,IAAI,eAAA,CAAgB,cAAc,UAAA,CAAW,GAAA,EAAK,GAAG,CAAC,CAAA;AACzE,EAAA,MAAM,WAAW,MAAA,CAAO,UAAA,CAAW,GAAA,CAAI,OAAO,CAAC,CAAA,IAAK,IAAA;AACpD,EAAA,MAAM,YAAY,MAAA,CAAO,UAAA,CAAW,GAAA,CAAI,QAAQ,CAAC,CAAA,IAAK,IAAA;AACtD,EAAA,MAAM,YAAA,GAAe,CAAC,OAAA,CAAQ,IAAA,CAAK,KAAA,EAAO,QAAQ,CAAA,CAC/C,MAAA,CAAO,CAAC,KAAA,KAA2B,KAAA,IAAS,IAAA,IAAQ,QAAQ,CAAC,CAAA;AAChE,EAAA,MAAM,cAAc,YAAA,CAAa,MAAA,GAAS,KAAK,GAAA,CAAI,GAAG,YAAY,CAAA,GAAI,IAAA;AACtE,EAAA,MAAM,SAAS,CAAC,GAAG,IAAI,GAAA,CAAI,gBAAgB,GAAA,CAAI,CAAA,KAAA,KAC7C,WAAA,KAAgB,IAAA,GAAO,QAAQ,IAAA,CAAK,GAAA,CAAI,OAAO,WAAW,CAAC,CAAC,CAAC,CAAA;AAE/D,EAAA,MAAM,cACJ,OAAA,CAAQ,WAAA,KACP,QAAQ,IAAA,CAAK,KAAA,IAAS,QAAQ,OAAA,CAAQ,IAAA,CAAK,UAAU,IAAA,GAClD,CAAA,EAAG,QAAQ,IAAA,CAAK,KAAK,IAAI,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAA,CAAA,GAC5C,MAAA,CAAA;AAIN,EAAA,MAAM,YAA6B,EAAC;AACpC,EAAA,IAAI,OAAA,CAAQ,IAAA,EAAM,SAAA,CAAU,GAAA,GAAM,OAAA;AAClC,EAAA,IAAI,OAAA,CAAQ,MAAA,IAAU,IAAA,EAAM,SAAA,CAAU,SAAS,OAAA,CAAQ,MAAA;AACvD,EAAA,IAAI,OAAA,CAAQ,OAAA,IAAW,IAAA,EAAM,SAAA,CAAU,UAAU,OAAA,CAAQ,OAAA;AAIzD,EAAA,MAAM,iBACJ,OAAA,CAAQ,KAAA,IAAS,IAAA,IAAQ,OAAA,CAAQ,UAAU,IAAA,GAAO,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,QACvE,QAAA,KAAa,IAAA,IAAQ,SAAA,KAAc,IAAA,GAAO,YAAY,QAAA,GAAW,IAAA;AACvE,EAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAA+B;AAChD,IAAA,MAAM,IAAA,GAAwB,EAAE,GAAG,SAAA,EAAW,OAAO,CAAA,EAAE;AACvD,IAAA,IAAI,kBAAkB,IAAA,EAAM,IAAA,CAAK,SAAS,IAAA,CAAK,KAAA,CAAM,IAAI,cAAc,CAAA;AACvE,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,gBAAgB,IAAA,CAAK,GAAA,CAAI,QAAQ,KAAA,IAAS,cAAA,EAAgB,eAAe,QAAQ,CAAA;AACvF,EAAA,MAAM,UAAA,GAAa,UAAU,aAAa,CAAA;AAC1C,EAAA,IAAI,mBAAmB,IAAA,IAAQ,OAAA,CAAQ,UAAU,IAAA,EAAM,UAAA,CAAW,SAAS,OAAA,CAAQ,MAAA;AAEnF,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,QAAA,CAAS,GAAA,EAAK,UAAU,CAAA;AAAA,IAC7B,QAAQ,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,GAAG,QAAA,CAAS,GAAA,EAAK,SAAA,CAAU,CAAC,CAAC,CAAC,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA,CAAG,CAAA,CAAE,KAAK,IAAI,CAAA;AAAA,IAC3E,GAAI,OAAA,CAAQ,KAAA,IAAS,OAAO,EAAE,KAAA,EAAO,QAAQ,KAAA,EAAM,GAC/C,QAAQ,KAAA,IAAS,IAAA,GAAO,EAAE,KAAA,EAAO,CAAA,EAAG,QAAQ,KAAK,CAAA,EAAA,CAAA,KAAS,EAAC;AAAA,IAC/D,GAAI,QAAQ,KAAA,IAAS,IAAA,GAAO,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAM,GAAI,EAAC;AAAA,IACxD,GAAI,QAAQ,MAAA,IAAU,IAAA,GAAO,EAAE,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAAO,GAAI,EAAC;AAAA,IAC3D,GAAA,EAAK,OAAA,CAAQ,IAAA,CAAK,OAAA,IAAW,EAAA;AAAA,IAC7B,OAAA,EAAS,QAAQ,OAAA,IAAW,MAAA;AAAA,IAC5B,GAAI,eAAe,IAAA,GAAO,EAAE,OAAO,EAAE,WAAA,EAAY,EAAE,GAAI;AAAC,GAC1D;AACF","file":"chunk-PWVXOMDE.js","sourcesContent":["/**\n * Framework-agnostic image-URL builders for the storefront SDK (ADR-0003 §SDK image-URL contract).\n * They build Cloudflare `/cdn-cgi/image/<opts>/<path>` path-form transform URLs for `https://cdn.kotao.*`\n * bases, allowing the CDN to serve optimized renderings. Non-CDN URLs (external, data:, theme `/assets/...`)\n * pass through unchanged. Wire-native params — `width`/`height`/`fit`/`format`/`quality` — matching\n * Cloudflare's native image resizing; a Hydrogen-shaped React `<Image>` (with `crop`, `srcSet`/`sizes`\n * props) layers on top in the framework presets (#92). Pure string building, no framework imports, so it\n * stays in the SDK core.\n */\n\n/** Cloudflare-native resize mode (the Gateway's `fit` param). */\nexport type ImageFit = 'scale-down' | 'contain' | 'pad' | 'squeeze' | 'cover' | 'crop'\n/** Output format query value (the Gateway maps it to a content-type). */\nexport type ImageFormat = 'auto' | 'webp' | 'avif' | 'jpeg' | 'png'\n\nexport interface ImageUrlOptions {\n width?: number\n height?: number\n fit?: ImageFit\n format?: ImageFormat\n /** 1–100. */\n quality?: number\n}\n\nconst CDN_CGI = '/cdn-cgi/image/'\nconst isCdnUrl = (url: string): boolean => /^https?:\\/\\/cdn\\.kotao\\./.test(url)\n\n/** Strip a `/cdn-cgi/image/<opts>/` segment back to `{origin}{path}`, returning [bareUrl, existingOpts]. */\nfunction splitCdnCgi(url: string): { bare: string; opts: URLSearchParams } {\n const u = new URL(url)\n if (!u.pathname.startsWith(CDN_CGI)) return { bare: url, opts: new URLSearchParams() }\n const rest = u.pathname.slice(CDN_CGI.length)\n const slash = rest.indexOf('/')\n const optStr = slash === -1 ? rest : rest.slice(0, slash)\n const path = slash === -1 ? '' : rest.slice(slash) // includes leading '/'\n const opts = new URLSearchParams()\n for (const pair of optStr.split(',')) {\n const [k, v] = pair.split('=')\n if (k && v) opts.set(k, v)\n }\n return { bare: `${u.origin}${path}${u.search}`, opts }\n}\n\nconst OPT_ORDER = ['width', 'height', 'fit', 'format', 'quality'] as const\n\n/**\n * Build a Cloudflare `/cdn-cgi/image/` path-form transform URL for a CDN image. For transformable\n * URLs (absolute `https://cdn.kotao.*`), emits `/cdn-cgi/image/{opts}/{path}` where `{opts}` is\n * the comma-joined key=value list (in stable order: width,height,fit,format,quality) and `{path}`\n * is the original pathname. Chaining replaces any existing `/cdn-cgi/image/` segment.\n * Non-CDN URLs pass through unchanged.\n */\nexport function imageUrl(url: string, options: ImageUrlOptions = {}): string {\n if (!isCdnUrl(url)) return url\n const { bare, opts } = splitCdnCgi(url)\n if (options.width != null) opts.set('width', String(options.width))\n if (options.height != null) opts.set('height', String(options.height))\n if (options.fit != null) opts.set('fit', options.fit)\n if (options.format != null) opts.set('format', options.format)\n else if (!opts.has('format')) opts.set('format', 'auto')\n if (options.quality != null) opts.set('quality', String(options.quality))\n const ordered = OPT_ORDER.filter((k) => opts.has(k)).map((k) => `${k}=${opts.get(k)}`)\n if (ordered.length === 0) return bare\n const u = new URL(bare)\n return `${u.origin}${CDN_CGI}${ordered.join(',')}${u.pathname}${u.search}`\n}\n\nexport interface ImageSrcSetOptions extends Omit<ImageUrlOptions, 'width'> {\n /** Candidate widths (px) for the `srcset` descriptors. */\n widths: number[]\n}\n\n/**\n * Build a `srcset` string — one `url width` candidate per width — for responsive `<img srcset>` /\n * `<source srcset>`. Pair with a `sizes` attribute the theme controls.\n */\nexport function imageSrcSet(url: string, options: ImageSrcSetOptions): string {\n const { widths, ...rest } = options\n return widths.map((width) => `${imageUrl(url, { ...rest, width })} ${width}w`).join(', ')\n}\n","/**\n * Framework-agnostic `<img>` attribute builder (ADR-0003 §SDK image-URL contract). Turns the\n * Hydrogen-shaped `<Image>` surface (data/aspectRatio/crop/sizes/width/height) into concrete img\n * attributes (src, srcSet, sizes, width, height, style) over the `cdn.kotao.*` R2-native transform\n * contract, via the pure `imageUrl`/`imageSrcSet` builders. The React `<Image>` is a thin wrapper\n * that spreads these — so all logic lives here, in the core, unit-tested without a DOM.\n */\nimport { imageUrl, type ImageFormat, type ImageUrlOptions } from './image-url'\n\nexport interface ImageData {\n url: string\n altText?: string | null\n width?: number | null\n height?: number | null\n}\n\n/** Hydrogen crop region. v1 maps any crop to a fill+crop (Cloudflare `fit=cover`); positional gravity\n * (top/bottom/left/right) is not on the wire yet, so all values currently centre-crop. */\nexport type ImageCrop = 'center' | 'top' | 'bottom' | 'left' | 'right'\n\n// Optionals are `| undefined` on purpose: the React <Image> feeds them straight from optional props,\n// so explicit `undefined` must be assignable under exactOptionalPropertyTypes.\nexport interface ImageAttrsOptions {\n data: ImageData\n /** Override `data.url`. */\n src?: string | undefined\n /** \"width/height\" (e.g. \"4/5\") — sets the intrinsic box for CLS-free layout. */\n aspectRatio?: string | undefined\n crop?: ImageCrop | undefined\n /** The responsive `sizes` attribute; the theme owns it. */\n sizes?: string | undefined\n /** Fixed render width (px). With it, the srcSet becomes 1x/2x/3x instead of the responsive set. */\n width?: number | undefined\n height?: number | undefined\n loading?: ('eager' | 'lazy') | undefined\n /** srcSet candidate widths; defaults to a responsive set (or 1x/2x/3x when `width` is fixed). */\n srcSetWidths?: number[] | undefined\n format?: ImageFormat | undefined\n quality?: number | undefined\n}\n\nexport interface ImageAttrs {\n src: string\n srcSet: string\n sizes?: string\n width?: number\n height?: number\n alt: string\n loading: 'eager' | 'lazy'\n style?: { aspectRatio: string }\n}\n\n/** Responsive widths when no fixed `width` is given (mirrors Hydrogen's default interval set). */\nconst DEFAULT_WIDTHS = [320, 640, 768, 1024, 1280, 1536]\n/** The `src` fallback width for browsers that ignore srcSet. */\nconst FALLBACK_WIDTH = 1280\n\nexport function buildImageAttrs(options: ImageAttrsOptions): ImageAttrs {\n const url = options.src ?? options.data.url\n\n const requestedWidths =\n options.srcSetWidths ??\n (options.width ? [options.width, options.width * 2, options.width * 3] : DEFAULT_WIDTHS)\n // A preceding Liquid image_url transform can make this a small thumbnail. Never undo that\n // bound by advertising full-page candidates (or upscale beyond an original image's pixels).\n const urlTransform = /^https?:\\/\\/cdn\\.kotao\\.[^/]+\\/cdn-cgi\\/image\\/([^/]+)/.exec(url)?.[1]\n const urlOptions = new URLSearchParams(urlTransform?.replaceAll(',', '&'))\n const urlWidth = Number(urlOptions.get('width')) || null\n const urlHeight = Number(urlOptions.get('height')) || null\n const sourceWidths = [options.data.width, urlWidth]\n .filter((width): width is number => width != null && width > 0)\n const sourceWidth = sourceWidths.length ? Math.min(...sourceWidths) : null\n const widths = [...new Set(requestedWidths.map(width =>\n sourceWidth === null ? width : Math.min(width, sourceWidth)))]\n\n const aspectRatio =\n options.aspectRatio ??\n (options.data.width != null && options.data.height != null\n ? `${options.data.width}/${options.data.height}`\n : undefined)\n\n // Shared transform params — set only when present (exactOptionalPropertyTypes forbids explicit\n // `undefined`). A crop maps to Cloudflare `fit=cover` (fill+crop).\n const transform: ImageUrlOptions = {}\n if (options.crop) transform.fit = 'cover'\n if (options.format != null) transform.format = options.format\n if (options.quality != null) transform.quality = options.quality\n\n // For a fixed box (width+height), the srcSet candidates must scale BOTH dimensions so every DPR\n // variant keeps the same crop aspect (a uniform height would distort the 2x/3x candidates).\n const heightPerWidth =\n options.width != null && options.height != null ? options.height / options.width\n : urlWidth !== null && urlHeight !== null ? urlHeight / urlWidth : null\n const candidate = (w: number): ImageUrlOptions => {\n const opts: ImageUrlOptions = { ...transform, width: w }\n if (heightPerWidth != null) opts.height = Math.round(w * heightPerWidth)\n return opts\n }\n\n const fallbackWidth = Math.min(options.width ?? FALLBACK_WIDTH, sourceWidth ?? Infinity)\n const srcOptions = candidate(fallbackWidth)\n if (heightPerWidth === null && options.height != null) srcOptions.height = options.height\n\n return {\n src: imageUrl(url, srcOptions),\n srcSet: widths.map((w) => `${imageUrl(url, candidate(w))} ${w}w`).join(', '),\n ...(options.sizes != null ? { sizes: options.sizes }\n : options.width != null ? { sizes: `${options.width}px` } : {}),\n ...(options.width != null ? { width: options.width } : {}),\n ...(options.height != null ? { height: options.height } : {}),\n alt: options.data.altText ?? '',\n loading: options.loading ?? 'lazy',\n ...(aspectRatio != null ? { style: { aspectRatio } } : {}),\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as FormVersionSchema } from './types-
|
|
1
|
+
import { F as FormVersionSchema } from './types-BTUTZXxJ.js';
|
|
2
2
|
import { S as StorefrontHeadersInit } from './http-types-CGh8WGHB.js';
|
|
3
3
|
|
|
4
4
|
type EventRegistrationMode = 'instant' | 'approval_then_payment' | 'waitlist_only';
|
package/dist/editor.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { C as CreateStorefrontEditorBridgeArgs, b as CreateStorefrontEditorHostBridgeArgs, c as StorefrontEditorAppExtensionPreview, d as StorefrontEditorBlockSchema, e as StorefrontEditorBridge, f as StorefrontEditorCanvasAction, g as StorefrontEditorCanvasBlockAction, h as StorefrontEditorCanvasPosition, i as StorefrontEditorCanvasSectionAction, j as StorefrontEditorDocument, k as StorefrontEditorHostBridge, l as StorefrontEditorMessageEvent, S as StorefrontEditorMessageSource, a as StorefrontEditorMessageTarget, m as StorefrontEditorNavigationRequest, n as StorefrontEditorReady, o as StorefrontEditorRect, p as StorefrontEditorSectionPreset, q as StorefrontEditorSectionPresetBlock, r as StorefrontEditorSectionSchema, s as StorefrontEditorSelection, t as StorefrontEditorSelectionScope, u as StorefrontEditorSettingInput, v as StorefrontEditorSettingOption, w as StorefrontEditorThemeStyle, x as StorefrontEditorValuesDocument, y as createStorefrontEditorBridge, z as createStorefrontEditorHostBridge, A as positionStorefrontEditorCanvasToolbar } from './bridge-CfNBWu0H.js';
|
|
2
2
|
export { S as STOREFRONT_SECTION_CUSTOM_CSS_SETTING, s as scopeStorefrontSectionCss } from './custom-css-Bl7Ur3-H.js';
|
|
3
|
-
export { HOSTED_SURFACE_DESIGN_INPUTS, HydrogenEditorManifest, HydrogenEditorManifestSchema } from '@kotao/storefront-contracts';
|
|
3
|
+
export { HOSTED_SURFACE_DESIGN_INPUTS, HydrogenEditorManifest, HydrogenEditorManifestSchema, STOREFRONT_EDITOR_ACCESS_MESSAGE, STOREFRONT_EDITOR_ACCESS_PATH } from '@kotao/storefront-contracts';
|
|
4
4
|
import { H as HydrogenEditorSecurityContext, C as CreateHydrogenEditorPreviewRuntimeArgs, a as HydrogenEditorPreviewRuntime } from './hydrogen-CqDMW3YC.js';
|
|
5
5
|
export { b as CreateHydrogenEditorHostBridgeArgs, c as CreateHydrogenEditorSourceProjectionArgs, d as HYDROGEN_EDITOR_BRIDGE_LIMITS, e as HYDROGEN_EDITOR_PROTOCOL_VERSION, f as HydrogenEditorApplyResult, g as HydrogenEditorCanvasDispatchResult, h as HydrogenEditorCanvasIntent, i as HydrogenEditorCapabilityReason, j as HydrogenEditorConfigurationError, k as HydrogenEditorHostBridge, l as HydrogenEditorInstanceSnapshot, m as HydrogenEditorOperationBase, n as HydrogenEditorOperationFailure, o as HydrogenEditorOperationFailureCode, p as HydrogenEditorPreviewOperation, q as HydrogenEditorPreviewSnapshot, r as HydrogenEditorPreviewStore, s as HydrogenEditorProtocolFailure, t as HydrogenEditorProtocolFailureCode, u as HydrogenEditorReadyDocument, v as HydrogenEditorReadyInstance, w as HydrogenEditorReconciliation, x as HydrogenEditorReconciliationReason, y as createHydrogenEditorHostBridge, z as createHydrogenEditorPreviewRuntime, A as createHydrogenEditorSourceProjection, B as parseHydrogenEditorCanvasIntent, D as resolveHydrogenEditorStyles } from './hydrogen-CqDMW3YC.js';
|
|
6
6
|
import './store-ZzoBbWir.js';
|
package/dist/editor.js
CHANGED
|
@@ -2,7 +2,7 @@ import { HydrogenEditorConfigurationError, createHydrogenEditorPreviewRuntime }
|
|
|
2
2
|
export { HYDROGEN_EDITOR_BRIDGE_LIMITS, HYDROGEN_EDITOR_PROTOCOL_VERSION, HydrogenEditorConfigurationError, createHydrogenEditorHostBridge, createHydrogenEditorPreviewRuntime, createHydrogenEditorSourceProjection, parseHydrogenEditorCanvasIntent, resolveHydrogenEditorStyles } from './chunk-XXNCFWXT.js';
|
|
3
3
|
export { STOREFRONT_SECTION_CUSTOM_CSS_SETTING, createStorefrontEditorBridge, createStorefrontEditorHostBridge, positionStorefrontEditorCanvasToolbar, scopeStorefrontSectionCss } from './chunk-RFKLO6TD.js';
|
|
4
4
|
import { toBase64Url, fromBase64Url } from './chunk-CKGI3Y7L.js';
|
|
5
|
-
export { HOSTED_SURFACE_DESIGN_INPUTS, HydrogenEditorManifestSchema } from '@kotao/storefront-contracts';
|
|
5
|
+
export { HOSTED_SURFACE_DESIGN_INPUTS, HydrogenEditorManifestSchema, STOREFRONT_EDITOR_ACCESS_MESSAGE, STOREFRONT_EDITOR_ACCESS_PATH } from '@kotao/storefront-contracts';
|
|
6
6
|
|
|
7
7
|
// src/editor/preview-grant.ts
|
|
8
8
|
var GRANT_VERSION = 1;
|
package/dist/events-react.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { O as OfferTokenLocation, a as OfferTokenHistory } from './offer-token-C-nk_nj8.js';
|
|
4
|
-
import { E as EventsClient, a as EventCheckoutSession, b as EventApprovalOfferResolution, P as PublicEvent, c as EventRegistrationSubmission } from './client-
|
|
5
|
-
import './types-
|
|
4
|
+
import { E as EventsClient, a as EventCheckoutSession, b as EventApprovalOfferResolution, P as PublicEvent, c as EventRegistrationSubmission } from './client-Bt8EEr-K.js';
|
|
5
|
+
import './types-BTUTZXxJ.js';
|
|
6
6
|
import './http-types-CGh8WGHB.js';
|
|
7
7
|
|
|
8
8
|
type EventRegistrationState = 'idle' | 'submitting' | 'awaiting_approval' | 'waitlisted' | 'checkout_ready' | 'request_error';
|
package/dist/events.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { C as CartHandler } from './createCartHandler-DJEZW4o2.js';
|
|
2
|
-
export { C as ClaimEventApprovalOffer, d as CreateEventApprovalRequest, e as CreateEventCheckoutSession, f as CreateEventWaitlistEntry, b as EventApprovalOfferResolution, g as EventApprovalRequestReceipt, a as EventCheckoutSession, h as EventFormAnswer, i as EventFormSubmissionInput, j as EventRegistrationMode, k as EventRegistrationResult, c as EventRegistrationSubmission, l as EventWaitlistReceipt, E as EventsClient, P as PublicEvent, m as PublicEventForm, n as PublicEventOccurrence, o as PublicEventSummary, p as PublicEventTicketType, q as PublicEventVenue, S as StorefrontEventsRequestError, r as createEventsClient } from './client-
|
|
2
|
+
export { C as ClaimEventApprovalOffer, d as CreateEventApprovalRequest, e as CreateEventCheckoutSession, f as CreateEventWaitlistEntry, b as EventApprovalOfferResolution, g as EventApprovalRequestReceipt, a as EventCheckoutSession, h as EventFormAnswer, i as EventFormSubmissionInput, j as EventRegistrationMode, k as EventRegistrationResult, c as EventRegistrationSubmission, l as EventWaitlistReceipt, E as EventsClient, P as PublicEvent, m as PublicEventForm, n as PublicEventOccurrence, o as PublicEventSummary, p as PublicEventTicketType, q as PublicEventVenue, S as StorefrontEventsRequestError, r as createEventsClient } from './client-Bt8EEr-K.js';
|
|
3
3
|
export { a as OfferTokenHistory, O as OfferTokenLocation, c as consumeOfferTokenFragment, o as offerTokenHrefMarker } from './offer-token-C-nk_nj8.js';
|
|
4
4
|
import './client-D51WdvYR.js';
|
|
5
5
|
import './http-types-CGh8WGHB.js';
|
|
6
6
|
import './types-C4yXcret.js';
|
|
7
|
-
import './types-
|
|
7
|
+
import './types-BTUTZXxJ.js';
|
|
8
8
|
|
|
9
9
|
declare class EventCartPreparationError extends Error {
|
|
10
10
|
constructor();
|
package/dist/forms.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as FormVisibilityRule,
|
|
2
|
-
export {
|
|
1
|
+
import { i as FormVisibilityRule, b as FormAnswers, F as FormVersionSchema, d as FormField, f as FormLocalizedText, g as FormRenderState, P as PublicForm, e as FormFieldErrors, h as FormSubmission } from './types-BTUTZXxJ.js';
|
|
2
|
+
export { a as FormAnswer, c as FormBlock, j as PublicFormDefinition, k as PublicFormVersion } from './types-BTUTZXxJ.js';
|
|
3
3
|
|
|
4
4
|
declare const FORM_ANSWER_PREFIX = "answers";
|
|
5
5
|
declare const ADDRESS_PROPERTIES: readonly ["line1", "line2", "city", "postalCode", "countryCode", "provinceCode"];
|
package/dist/image.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
/** Cloudflare-native resize mode (the Gateway's `fit` param). */
|
|
11
11
|
type ImageFit = 'scale-down' | 'contain' | 'pad' | 'squeeze' | 'cover' | 'crop';
|
|
12
12
|
/** Output format query value (the Gateway maps it to a content-type). */
|
|
13
|
-
type ImageFormat = 'webp' | 'avif' | 'jpeg' | 'png';
|
|
13
|
+
type ImageFormat = 'auto' | 'webp' | 'avif' | 'jpeg' | 'png';
|
|
14
14
|
interface ImageUrlOptions {
|
|
15
15
|
width?: number;
|
|
16
16
|
height?: number;
|
package/dist/image.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,31 +1,30 @@
|
|
|
1
1
|
export { c as CacheCustom, d as CacheLong, e as CacheNone, f as CacheShort, C as CacheStrategy, H as HydrogenStorefrontClientOptions, K as KotaoCache, g as StaleIfErrorFallback, h as Storefront, a as StorefrontAuthHeader, i as StorefrontCache, b as StorefrontCacheInput, j as StorefrontCacheQueryOptions, k as StorefrontCacheRequest, S as StorefrontClient, l as StorefrontClientOptions, m as StorefrontClientResult, n as StorefrontDefaultCache, o as StorefrontQueryOptions, p as StorefrontQueryTimeoutError, q as StorefrontUpstreamError, r as createCache, s as createStorefrontClient, t as generateCacheControlHeader } from './client-D51WdvYR.js';
|
|
2
2
|
import { C as Cart } from './types-C4yXcret.js';
|
|
3
3
|
export { k as CART_FORM_ACTIONS, b as CartAttribute, l as CartBuyerIdentity, c as CartBuyerIdentityInput, h as CartDeliveryAddress, j as CartFormAction, m as CartLine, a as CartLineInput, e as CartLineUpdateInput, f as CartMetafield, g as CartMetafieldIdentifier, d as CartMutationResult, i as CartSelectedDeliveryOption, n as CartUserError, o as HydrogenCart, p as HydrogenCartCreateInput, q as HydrogenCartMutationResult, H as HydrogenSession, r as HydrogenSessionData } from './types-C4yXcret.js';
|
|
4
|
-
import {
|
|
5
|
-
export {
|
|
6
|
-
import { a as CartDispatchAction } from './createCartHandler-DJEZW4o2.js';
|
|
7
|
-
export { b as CartGetId,
|
|
4
|
+
import { C as ConsentBucket, a as ConsentState, A as AnalyticsContext } from './shop-wJdcWcVz.js';
|
|
5
|
+
export { b as ANALYTICS_EVENTS, c as AnalyticsBus, d as AnalyticsBusOptions, e as AnalyticsDeviceClass, f as AnalyticsEmitter, g as AnalyticsEventMap, h as AnalyticsEventName, i as AnalyticsGeo, j as CONSENT_BUCKETS, k as CONSENT_COOKIE, l as CartForm, m as CartFormProps, n as CartViewedPayload, o as CollectionViewedPayload, p as ContentSecurityPolicyResult, q as ContentSecurityPolicyShop, r as CreateContentSecurityPolicyOptions, D as DENIED_CONSENT, E as EventHandler, G as GRANTED_CONSENT, s as GetShopAnalyticsOptions, P as PageViewedPayload, t as PixelEvent, u as PixelSend, v as PixelTransport, w as PixelTransportOptions, x as ProductAddedToCartPayload, y as ProductViewedPayload, S as SearchViewedPayload, z as ShopAnalytics, B as buildConsentCookie, F as createAnalyticsBus, H as createAnalyticsEmitter, I as createContentSecurityPolicy, J as createPixelTransport, K as getShopAnalytics, L as isGranted, M as mergeConsent, N as parseConsent, O as readConsentCookie, Q as serializeConsent } from './shop-wJdcWcVz.js';
|
|
6
|
+
import { a as CartDispatchAction, C as CartHandler } from './createCartHandler-DJEZW4o2.js';
|
|
7
|
+
export { b as CartGetId, c as CartSetId, d as CreateCartHandlerOptions, H as HydrogenCartHandlerOptions, R as RequestCartHandlerOptions, e as cartGetIdDefault, f as cartSetIdDefault, g as createCartHandler } from './createCartHandler-DJEZW4o2.js';
|
|
8
8
|
import { c as ThemeSettingsSnapshot, R as ResolvedSettings } from './store-ZzoBbWir.js';
|
|
9
9
|
export { b as ResolvedBlock, a as ResolvedSection, d as ResolvedValuesDocument, T as ThemeSettingsStore, e as createThemeSettingsStore } from './store-ZzoBbWir.js';
|
|
10
|
-
import { C as CustomerAccountClient } from './routing-
|
|
11
|
-
export { A as Address, c as AddressConnection, d as CustomerAccount, e as CustomerAccountError, f as CustomerAccountErrorCode, G as GEO_HEADER, g as GEO_SIGNATURE_HEADER, h as Geo, K as KotaoContext, a as KotaoEnv, b as KotaoSession, L as LocalizePathOptions, M as Money, O as Order, i as OrderConnection, j as OrderPageInfo, k as OrdersOptions, R as ROUTING_LOCALE_HEADER, l as ROUTING_ORIGINAL_PATHNAME_HEADER, m as RequestLoginCodeInput, n as RequestLoginCodeResult, S as StorefrontExecutionContext, o as StorefrontMarketContext, p as StrippedLocalePath, V as VerifyLoginCodeInput, W as WithCache, q as createKotaoContext, r as createWithCache, t as isLocalePathSegment, u as localeFromAcceptLanguage, v as localeFromPathname, w as localeFromRequest, x as localizePath, y as marketContextFromHeaders, z as originalPathnameFromRequest, B as signGeo, D as stripLocalePrefixFromPathname, s as stripLocalePrefixFromRequest, E as trustedShopOriginFromHeaders, F as verifyGeo } from './routing-
|
|
12
|
-
export { AUTO_REDIRECT_LANGUAGE_HEADER, MARKET_ALTERNATE_LOCALES_HEADER, MARKET_CANONICAL_URL_HEADER, MARKET_DEFAULT_LOCALE_HEADER, MARKET_ID_HEADER, MARKET_PATH_PREFIX_HEADER, MARKET_ROOT_URLS_HEADER, MARKET_SETTINGS_ENVIRONMENT_HEADER, MARKET_THEME_ID_HEADER, autoRedirectEnabled } from '@kotao/storefront-contracts';
|
|
10
|
+
import { C as CustomerAccountClient } from './routing-hrvYWYEV.js';
|
|
11
|
+
export { A as Address, c as AddressConnection, d as CustomerAccount, e as CustomerAccountError, f as CustomerAccountErrorCode, G as GEO_HEADER, g as GEO_SIGNATURE_HEADER, h as Geo, K as KotaoContext, a as KotaoEnv, b as KotaoSession, L as LocalizePathOptions, M as Money, O as Order, i as OrderConnection, j as OrderPageInfo, k as OrdersOptions, R as ROUTING_LOCALE_HEADER, l as ROUTING_ORIGINAL_PATHNAME_HEADER, m as RequestLoginCodeInput, n as RequestLoginCodeResult, S as StorefrontExecutionContext, o as StorefrontMarketContext, p as StrippedLocalePath, V as VerifyLoginCodeInput, W as WithCache, q as createKotaoContext, r as createWithCache, t as isLocalePathSegment, u as localeFromAcceptLanguage, v as localeFromPathname, w as localeFromRequest, x as localizePath, y as marketContextFromHeaders, z as originalPathnameFromRequest, B as signGeo, D as stripLocalePrefixFromPathname, s as stripLocalePrefixFromRequest, E as trustedShopOriginFromHeaders, F as verifyGeo } from './routing-hrvYWYEV.js';
|
|
12
|
+
export { AUTO_REDIRECT_LANGUAGE_HEADER, CHECKOUT_BLOCK_POSITIONS, CHECKOUT_BLOCK_TYPES, CHECKOUT_EDITOR_PAGES, CHECKOUT_FIELDS_ATTRIBUTE, CHECKOUT_FIELDS_LIMIT, CHECKOUT_FIELD_TYPES, CHECKOUT_GIFT_NOTE_MAX_LENGTH, CHECKOUT_PAYMENT_METHODS, CHECKOUT_PAYMENT_RULES_ATTRIBUTE, CONSENT_BANNER_DEFAULT_COPY, CONSENT_BANNER_LOCALES, CheckoutBlockPosition, CheckoutBlockType, CheckoutCartEditing, CheckoutCartEditingSchema, CheckoutContentBlock, CheckoutContentPosition, CheckoutCustomFieldSettings, CheckoutCustomFieldSettingsSchema, CheckoutCustomization, CheckoutEditorPage, CheckoutFieldSnapshot, CheckoutFieldValue, CheckoutGiftNote, CheckoutGiftNoteSettingsSchema, CheckoutLayout, CheckoutLayoutSchema, CheckoutPaymentMethod, CheckoutProductOffer, CheckoutReviewSettingsSchema, CheckoutRule, CheckoutRuleConditions, CheckoutRuleConditionsSchema, CheckoutRuleContext, CheckoutRuleSchema, CheckoutRulesSchema, CheckoutShippingNotice, CheckoutShippingNoticeSettingsSchema, ConsentBannerCopy, ConsentBannerLocale, MARKET_ALTERNATE_LOCALES_HEADER, MARKET_CANONICAL_URL_HEADER, MARKET_DEFAULT_LOCALE_HEADER, MARKET_ID_HEADER, MARKET_PATH_PREFIX_HEADER, MARKET_ROOT_URLS_HEADER, MARKET_SETTINGS_ENVIRONMENT_HEADER, MARKET_THEME_ID_HEADER, POST_PURCHASE_BLOCK_POSITIONS, applyCheckoutFieldRules, applyCheckoutShippingRules, autoRedirectEnabled, checkoutBlockAllowedAt, checkoutBlockSettingsSchema, checkoutPageBlockAllowedAt, checkoutPagePositions, checkoutRuleMatches, checkoutShippingNoticeVisible, evaluateCheckoutRules, isCheckoutBlockPosition, isCheckoutBlockType, localizeCheckoutField, readCheckoutCustomization, readCheckoutFieldSnapshots, readCheckoutPaymentExclusions, validateCheckoutFields } from '@kotao/storefront-contracts';
|
|
13
13
|
export { ImageAttrs, ImageAttrsOptions, ImageCrop, ImageData, ImageFit, ImageFormat, ImageSrcSetOptions, ImageUrlOptions, buildImageAttrs, imageSrcSet, imageUrl } from './image.js';
|
|
14
|
-
export { C as Connection, a as ConnectionEdge, F as FlattenableConnection,
|
|
14
|
+
export { C as Connection, a as ConnectionEdge, F as FlattenableConnection, P as PageInfo, b as PaginationInfo, c as PaginationOptions, d as PaginationVariables, f as flattenConnection, g as getPaginationInfo, e as getPaginationVariables } from './pagination-CPgH3fAa.js';
|
|
15
15
|
export { MappedProductOptions, ProductLike, ProductOptionDef, ProductOptionState, ProductOptionValueState, SelectedOption, SelectedOptionsMap, VariantLike, VariantSelectionLike, getAdjacentAndFirstAvailableVariants, getProductOptions, getSelectedProductOptions, getSelectedVariant, mapSelectedProductOptionToObject, useOptimisticVariant, useSelectedOptionInUrlParam } from './product.js';
|
|
16
16
|
export { ResolveThemeSettingsArgs, mergeSection, mergeSettings, reconcileSyntheticSectionGroup, resolveThemeSettings } from './settings.js';
|
|
17
17
|
export { F as FetchThemeSettingsOptions, S as StoredThemeSettings, f as fetchThemeSettings } from './fetch-Bq_cc8_G.js';
|
|
18
18
|
export { AddressInput, BreadcrumbItem, ChangeFreq, GeoInput, LocalBusinessInput, OfferInput, OrganizationInput, ProductJsonLdInput, RedirectLookup, RedirectOptions, RobotsOptions, SitemapEntry, SitemapIndexEntry, StorefrontRedirectOptions, URL_REDIRECT_QUERY, WebSiteInput, breadcrumbListJsonLd, buildRobotsTxt, buildSitemapIndexXml, buildSitemapXml, getSeoMeta, localBusinessJsonLd, organizationJsonLd, productJsonLd, resolveRedirect, resolveStorefrontRedirect, restaurantJsonLd, robotsResponse, serializeJsonLd, sitemapIndexResponse, sitemapResponse, storefrontRedirect, websiteJsonLd } from './seo.js';
|
|
19
19
|
export { A as Alternate, J as JsonLd, O as OpenGraph, a as OpenGraphImage, S as SeoConfig, b as SeoDescriptor, T as TwitterCard } from './types-BkY0yET-.js';
|
|
20
|
-
export {
|
|
20
|
+
export { a as FormAnswer, b as FormAnswers, c as FormBlock, d as FormField, e as FormFieldErrors, f as FormLocalizedText, g as FormRenderState, h as FormSubmission, F as FormVersionSchema, i as FormVisibilityRule, P as PublicForm, j as PublicFormDefinition, k as PublicFormVersion } from './types-BTUTZXxJ.js';
|
|
21
21
|
export { ADDRESS_PROPERTIES, FORM_ANSWER_PREFIX, FormFetchOptions, RenderFormHtmlOptions, ShopifyContactCompatibility, ShopifyContactInput, StorefrontFormRequestError, SubmitFormInput, adaptShopifyContactForm, evaluateFormRule, formAnswerName, formFields, isFormFieldVisible, loadPublishedForm, parseFormAnswers, renderFormHtml, resolveFormText, submitPublishedForm } from './forms.js';
|
|
22
22
|
export { EventCartPreparationError, eventCartToken, prepareEventCart } from './events.js';
|
|
23
|
-
export { C as ClaimEventApprovalOffer, d as CreateEventApprovalRequest, e as CreateEventCheckoutSession, f as CreateEventWaitlistEntry, b as EventApprovalOfferResolution, g as EventApprovalRequestReceipt, a as EventCheckoutSession, h as EventFormAnswer, i as EventFormSubmissionInput, j as EventRegistrationMode, k as EventRegistrationResult, c as EventRegistrationSubmission, l as EventWaitlistReceipt, E as EventsClient, P as PublicEvent, m as PublicEventForm, n as PublicEventOccurrence, o as PublicEventSummary, p as PublicEventTicketType, q as PublicEventVenue, S as StorefrontEventsRequestError, r as createEventsClient } from './client-
|
|
23
|
+
export { C as ClaimEventApprovalOffer, d as CreateEventApprovalRequest, e as CreateEventCheckoutSession, f as CreateEventWaitlistEntry, b as EventApprovalOfferResolution, g as EventApprovalRequestReceipt, a as EventCheckoutSession, h as EventFormAnswer, i as EventFormSubmissionInput, j as EventRegistrationMode, k as EventRegistrationResult, c as EventRegistrationSubmission, l as EventWaitlistReceipt, E as EventsClient, P as PublicEvent, m as PublicEventForm, n as PublicEventOccurrence, o as PublicEventSummary, p as PublicEventTicketType, q as PublicEventVenue, S as StorefrontEventsRequestError, r as createEventsClient } from './client-Bt8EEr-K.js';
|
|
24
24
|
export { a as OfferTokenHistory, O as OfferTokenLocation, c as consumeOfferTokenFragment, o as offerTokenHrefMarker } from './offer-token-C-nk_nj8.js';
|
|
25
25
|
export { C as CreateStorefrontEditorBridgeArgs, b as CreateStorefrontEditorHostBridgeArgs, c as StorefrontEditorAppExtensionPreview, d as StorefrontEditorBlockSchema, e as StorefrontEditorBridge, f as StorefrontEditorCanvasAction, g as StorefrontEditorCanvasBlockAction, h as StorefrontEditorCanvasPosition, i as StorefrontEditorCanvasSectionAction, j as StorefrontEditorDocument, k as StorefrontEditorHostBridge, l as StorefrontEditorMessageEvent, S as StorefrontEditorMessageSource, a as StorefrontEditorMessageTarget, m as StorefrontEditorNavigationRequest, n as StorefrontEditorReady, o as StorefrontEditorRect, p as StorefrontEditorSectionPreset, q as StorefrontEditorSectionPresetBlock, r as StorefrontEditorSectionSchema, s as StorefrontEditorSelection, t as StorefrontEditorSelectionScope, u as StorefrontEditorSettingInput, v as StorefrontEditorSettingOption, w as StorefrontEditorThemeStyle, y as createStorefrontEditorBridge, z as createStorefrontEditorHostBridge, A as positionStorefrontEditorCanvasToolbar } from './bridge-CfNBWu0H.js';
|
|
26
26
|
export { S as STOREFRONT_SECTION_CUSTOM_CSS_SETTING, s as scopeStorefrontSectionCss } from './custom-css-Bl7Ur3-H.js';
|
|
27
27
|
import './http-types-CGh8WGHB.js';
|
|
28
|
-
import 'react';
|
|
29
28
|
import './storefront-api-types.js';
|
|
30
29
|
import '@kotao/storefront-contracts/theme';
|
|
31
30
|
|
|
@@ -48,6 +47,10 @@ declare function decodeCheckoutConsent(input: URLSearchParams | string | URL): C
|
|
|
48
47
|
|
|
49
48
|
interface ResolveCheckoutUrlOptions {
|
|
50
49
|
readonly checkoutUrl: string;
|
|
50
|
+
/** Active storefront language, carried through the platform checkout handoff. */
|
|
51
|
+
readonly locale?: string;
|
|
52
|
+
/** Active market/locale path prefix from the storefront routing context. */
|
|
53
|
+
readonly pathPrefix?: string;
|
|
51
54
|
readonly consent: ConsentState;
|
|
52
55
|
readonly shopDomain?: string;
|
|
53
56
|
readonly requestUrl?: string | URL | Request;
|
|
@@ -55,6 +58,7 @@ interface ResolveCheckoutUrlOptions {
|
|
|
55
58
|
declare function resolveCheckoutUrl(options: ResolveCheckoutUrlOptions): string;
|
|
56
59
|
|
|
57
60
|
interface CheckoutDesignTokens {
|
|
61
|
+
readonly cornerRadius?: number;
|
|
58
62
|
readonly logo: {
|
|
59
63
|
readonly src: string;
|
|
60
64
|
readonly altText: string | null;
|
|
@@ -115,24 +119,6 @@ declare const CHECKOUT_DESIGN_TOKEN_INPUTS: ({
|
|
|
115
119
|
})[];
|
|
116
120
|
declare function extractCheckoutDesignTokens(snapshot: Pick<ThemeSettingsSnapshot, 'global'>): CheckoutDesignTokens;
|
|
117
121
|
|
|
118
|
-
interface ContentSecurityPolicyShop {
|
|
119
|
-
readonly checkoutDomain?: string;
|
|
120
|
-
readonly storeDomain?: string;
|
|
121
|
-
}
|
|
122
|
-
interface CreateContentSecurityPolicyOptions {
|
|
123
|
-
readonly shop?: ContentSecurityPolicyShop;
|
|
124
|
-
readonly scriptSrc?: readonly string[];
|
|
125
|
-
readonly connectSrc?: readonly string[];
|
|
126
|
-
readonly imgSrc?: readonly string[];
|
|
127
|
-
readonly styleSrc?: readonly string[];
|
|
128
|
-
}
|
|
129
|
-
interface ContentSecurityPolicyResult {
|
|
130
|
-
readonly nonce: string;
|
|
131
|
-
readonly header: string;
|
|
132
|
-
readonly NonceProvider: BoundNonceProvider;
|
|
133
|
-
}
|
|
134
|
-
declare function createContentSecurityPolicy(options?: CreateContentSecurityPolicyOptions): ContentSecurityPolicyResult;
|
|
135
|
-
|
|
136
122
|
declare const LOCALIZATION_COOKIE = "kotao_localization";
|
|
137
123
|
declare function readLocalizationCookie(cookieHeader: string | null | undefined): {
|
|
138
124
|
country: string | null;
|
|
@@ -143,7 +129,9 @@ declare function buildLocalizationCookie(sel: {
|
|
|
143
129
|
locale?: string | null;
|
|
144
130
|
}): string;
|
|
145
131
|
|
|
146
|
-
declare function handleLocalizationPost(request: Request
|
|
132
|
+
declare function handleLocalizationPost(request: Request, context?: {
|
|
133
|
+
readonly cart?: Pick<CartHandler, 'get' | 'updateBuyerIdentity'>;
|
|
134
|
+
}): Promise<Response>;
|
|
147
135
|
|
|
148
136
|
interface AnalyticsAttributionEnvironment {
|
|
149
137
|
readonly referrer?: string;
|
|
@@ -267,4 +255,4 @@ interface HostedLocaleInput {
|
|
|
267
255
|
*/
|
|
268
256
|
declare function resolveHostedLocale(input: HostedLocaleInput): string;
|
|
269
257
|
|
|
270
|
-
export { type AnalyticsAttributionEnvironment, AnalyticsContext, CART_ID_COOKIE, CHECKOUT_CONSENT_CATEGORIES, CHECKOUT_CONSENT_PARAM_PREFIX, CHECKOUT_DESIGN_TOKEN_INPUTS, CUSTOMER_SESSION_COOKIE, Cart, CartDispatchAction, type CheckoutDesignTokens, ConsentBucket, ConsentState,
|
|
258
|
+
export { type AnalyticsAttributionEnvironment, AnalyticsContext, CART_ID_COOKIE, CHECKOUT_CONSENT_CATEGORIES, CHECKOUT_CONSENT_PARAM_PREFIX, CHECKOUT_DESIGN_TOKEN_INPUTS, CUSTOMER_SESSION_COOKIE, Cart, CartDispatchAction, CartHandler, type CheckoutDesignTokens, ConsentBucket, ConsentState, CustomerAccountClient, type CustomerAccountClientOptions, DEFAULT_HOSTED_SESSION_MAX_AGE, DEFAULT_SESSION_MAX_AGE, HOSTED_CUSTOMER_CSRF_COOKIE, HOSTED_CUSTOMER_CSRF_HEADER, HOSTED_CUSTOMER_SESSION_COOKIE, type HostedLocaleInput, type HostedSessionCookieAttrs, LOCALIZATION_COOKIE, type LegacySessionReadOptions, MAX_HOSTED_SESSION_MAX_AGE, MAX_LEGACY_CUSTOMER_SESSION_TOKEN_LENGTH, type ResolveCheckoutUrlOptions, ResolvedSettings, type SessionCookieAttrs, ThemeSettingsSnapshot, appendConsentToCheckoutUrl, applyOptimisticCartAction, buildCartIdCookie, buildCustomerSessionCookie, buildHostedCustomerSessionCookie, buildLocalizationCookie, clearCartIdCookie, clearCustomerSessionCookie, clearHostedCustomerSessionCookie, clearLegacyCustomerSessionCookie, collectAnalyticsAttribution, createCustomerAccountClient, decodeCheckoutConsent, decodeConsent, encodeCheckoutConsent, encodeConsent, escapeHostedHtml, extractCheckoutDesignTokens, handleLocalizationPost, readCartIdCookie, readCustomerSessionToken, readHostedCustomerCsrfToken, readHostedCustomerSessionToken, readLegacyCustomerSessionToken, readLocalizationCookie, resolveCheckoutUrl, resolveHostedBranding, resolveHostedLocale, sanitizeHostedCssValue, shopHostname, useOptimisticCart };
|