@kotao/storefront 0.2.2 → 0.2.4
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/dist/chunk-4OQYNUGM.js +29 -0
- package/dist/chunk-4OQYNUGM.js.map +1 -0
- package/dist/{chunk-7XYWHWT4.js → chunk-4TEFGD42.js} +331 -38
- package/dist/chunk-4TEFGD42.js.map +1 -0
- package/dist/chunk-7MTCGXIG.js +144 -0
- package/dist/chunk-7MTCGXIG.js.map +1 -0
- package/dist/chunk-IIOHENCG.js +239 -0
- package/dist/chunk-IIOHENCG.js.map +1 -0
- package/dist/chunk-VV653S52.js +246 -0
- package/dist/chunk-VV653S52.js.map +1 -0
- package/dist/chunk-WG7HYVHJ.js +38 -0
- package/dist/chunk-WG7HYVHJ.js.map +1 -0
- package/dist/{client-DiPdlvPu.d.ts → client-D51WdvYR.d.ts} +55 -8
- package/dist/client-bsiNPHBi.d.ts +159 -0
- package/dist/createCartHandler-C4RrPwSG.d.ts +58 -0
- package/dist/editor.d.ts +1 -1
- package/dist/events-react.d.ts +68 -0
- package/dist/events-react.js +557 -0
- package/dist/events-react.js.map +1 -0
- package/dist/events.d.ts +18 -0
- package/dist/events.js +5 -0
- package/dist/events.js.map +1 -0
- package/dist/{fetch-B6TIc6lI.d.ts → fetch-M3Y-fQrW.d.ts} +1 -1
- package/dist/forms.d.ts +58 -0
- package/dist/forms.js +3 -0
- package/dist/forms.js.map +1 -0
- package/dist/http-types-CGh8WGHB.d.ts +11 -0
- package/dist/index.d.ts +74 -12
- package/dist/index.js +55 -9
- package/dist/index.js.map +1 -1
- package/dist/offer-token-C-nk_nj8.d.ts +16 -0
- package/dist/{pagination-CPgH3fAa.d.ts → pagination-DCrQk02Q.d.ts} +1 -1
- package/dist/product.d.ts +1 -1
- package/dist/react-router.d.ts +11 -7
- package/dist/react-router.js +4 -3
- package/dist/react-router.js.map +1 -1
- package/dist/react.d.ts +30 -7
- package/dist/react.js +4 -2
- package/dist/react.js.map +1 -1
- package/dist/{routing-BxRlep_-.d.ts → routing-sEonP93J.d.ts} +17 -60
- package/dist/seo.d.ts +2 -1
- package/dist/settings.d.ts +5 -4
- package/dist/{shop-DkQmro-Y.d.ts → shop-BJSvtmnV.d.ts} +2 -2
- package/dist/{store-DQK1nhob.d.ts → store-CtCWHI8H.d.ts} +1 -1
- package/dist/types-CSNXbGFW.d.ts +108 -0
- package/dist/{types-Df3bGbKU.d.ts → types-bcbQzx87.d.ts} +1 -1
- package/package.json +14 -2
- package/dist/chunk-7XYWHWT4.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/http-types.ts","../src/events/client.ts"],"names":[],"mappings":"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","file":"chunk-7MTCGXIG.js","sourcesContent":["/** Structural Headers-compatible value without depending on an ambient `HeadersInit` alias. */\nexport interface StorefrontHeadersLike {\n forEach(callback: (value: string, key: string) => void): void\n}\n\n/**\n * Header input accepted by storefront clients. This preserves the iterable and record shapes\n * accepted by the Web Headers constructor while remaining portable to Node-only declarations.\n */\nexport type StorefrontHeadersInit =\n | StorefrontHeadersLike\n | Iterable<Iterable<string>>\n | Record<string, string>\n\nfunction isHeadersLike(input: StorefrontHeadersInit): input is StorefrontHeadersLike {\n return 'forEach' in input && typeof input.forEach === 'function'\n}\n\nfunction isIterableHeaders(input: StorefrontHeadersInit): input is Iterable<Iterable<string>> {\n return Symbol.iterator in input && typeof input[Symbol.iterator] === 'function'\n}\n\nexport function normalizeStorefrontHeaders(input?: StorefrontHeadersInit): Headers {\n const headers = new Headers()\n if (input === undefined) return headers\n\n if (isIterableHeaders(input)) {\n for (const entry of input) {\n const pair = [...entry]\n if (pair.length !== 2) throw new TypeError('header entry must contain exactly two items')\n headers.append(pair[0]!, pair[1]!)\n }\n return headers\n }\n if (isHeadersLike(input)) {\n input.forEach((value, key) => headers.append(key, value))\n return headers\n }\n for (const [key, value] of Object.entries(input)) headers.append(key, value)\n return headers\n}\n","import type {\n ClaimEventApprovalOffer,\n CreateEventApprovalRequest,\n CreateEventCheckoutSession,\n CreateEventWaitlistEntry,\n EventApprovalOfferResolution,\n EventApprovalRequestReceipt,\n EventCheckoutSession,\n EventRegistrationResult,\n EventRegistrationSubmission,\n EventWaitlistReceipt,\n PublicEvent,\n} from './types'\nimport { normalizeStorefrontHeaders, type StorefrontHeadersInit } from '../http-types'\n\nexport interface EventsClient {\n getEvent(handle: string): Promise<PublicEvent>\n createCheckoutSession(\n handle: string,\n input: CreateEventCheckoutSession,\n idempotencyKey: string,\n ): Promise<EventCheckoutSession>\n submitApplication(\n handle: string,\n input: CreateEventApprovalRequest,\n idempotencyKey: string,\n ): Promise<EventApprovalRequestReceipt>\n joinWaitlist(handle: string, input: CreateEventWaitlistEntry): Promise<EventWaitlistReceipt>\n submitRegistration(input: EventRegistrationSubmission): Promise<EventRegistrationResult>\n resolveOffer(\n offerId: string,\n claimToken: string,\n idempotencyKey?: string,\n ): Promise<EventApprovalOfferResolution>\n claimOffer(\n offerId: string,\n input: ClaimEventApprovalOffer,\n idempotencyKey: string,\n ): Promise<EventCheckoutSession>\n}\n\nexport class StorefrontEventsRequestError extends Error {\n readonly status: number\n\n constructor(status: number) {\n super(`Events request failed with status ${status}`)\n this.name = 'StorefrontEventsRequestError'\n this.status = status\n }\n}\n\ninterface EventApprovalClaimResult {\n readonly checkoutSession: EventCheckoutSession\n}\n\nfunction cleanBaseUrl(baseUrl: string): string {\n const trimmed = baseUrl.trim().replace(/\\/+$/u, '')\n if (trimmed === '' || /[?#]/u.test(trimmed)) {\n throw new Error('Events base URL must not contain a query string or fragment')\n }\n return trimmed\n}\n\nfunction resource(value: string): string {\n return encodeURIComponent(value)\n}\n\nfunction requestHeaders(defaultHeaders: Headers, idempotencyKey?: string): Headers {\n const headers = new Headers(defaultHeaders)\n headers.set('content-type', 'application/json')\n if (idempotencyKey !== undefined) headers.set('idempotency-key', idempotencyKey)\n return headers\n}\n\nfunction resolutionIdempotencyKey(): string {\n return `events-resolve-${Date.now()}-${Math.random().toString(36).slice(2)}`\n}\n\nexport function createEventsClient(input: {\n readonly baseUrl: string\n readonly fetch: typeof globalThis.fetch\n readonly defaultHeaders?: StorefrontHeadersInit\n}): EventsClient {\n const baseUrl = cleanBaseUrl(input.baseUrl)\n const defaultHeaders = normalizeStorefrontHeaders(input.defaultHeaders)\n\n async function get<T>(path: string): Promise<T> {\n const headers = new Headers(defaultHeaders)\n headers.delete('content-type')\n const requestInit = {\n method: 'GET',\n headers,\n credentials: 'include',\n cache: 'no-store',\n referrerPolicy: 'no-referrer',\n } as RequestInit\n const response = await input.fetch(`${baseUrl}${path}`, requestInit)\n if (!response.ok) throw new StorefrontEventsRequestError(response.status)\n return (await response.json()) as T\n }\n\n async function post<T>(path: string, body: unknown, idempotencyKey?: string): Promise<T> {\n const requestInit = {\n method: 'POST',\n headers: requestHeaders(defaultHeaders, idempotencyKey),\n credentials: 'include',\n cache: 'no-store',\n referrerPolicy: 'no-referrer',\n body: JSON.stringify(body),\n } as RequestInit\n const response = await input.fetch(`${baseUrl}${path}`, requestInit)\n if (!response.ok) throw new StorefrontEventsRequestError(response.status)\n return (await response.json()) as T\n }\n\n const client: EventsClient = {\n getEvent: (handle) => get<PublicEvent>(`/events/${resource(handle)}`),\n createCheckoutSession: (handle, body, idempotencyKey) =>\n post<EventCheckoutSession>(\n `/events/${resource(handle)}/checkout-sessions`,\n body,\n idempotencyKey,\n ),\n submitApplication: (handle, body, idempotencyKey) =>\n post<EventApprovalRequestReceipt>(\n `/events/${resource(handle)}/approval-requests`,\n body,\n idempotencyKey,\n ),\n joinWaitlist: (handle, body) =>\n post<EventWaitlistReceipt>(`/events/${resource(handle)}/waitlist`, body),\n async submitRegistration(submission) {\n switch (submission.registrationMode) {\n case 'instant':\n return {\n kind: 'checkout',\n checkoutSession: await client.createCheckoutSession(\n submission.handle,\n submission.input,\n submission.idempotencyKey,\n ),\n }\n case 'approval_then_payment':\n return {\n kind: 'approval',\n receipt: await client.submitApplication(\n submission.handle,\n submission.input,\n submission.idempotencyKey,\n ),\n }\n case 'waitlist_only':\n return {\n kind: 'waitlist',\n receipt: await client.joinWaitlist(submission.handle, submission.input),\n }\n }\n },\n resolveOffer: (offerId, claimToken, idempotencyKey) =>\n post<EventApprovalOfferResolution>(\n `/events/approval-offers/${resource(offerId)}/resolve`,\n { claimToken },\n idempotencyKey ?? resolutionIdempotencyKey(),\n ),\n async claimOffer(offerId, body, idempotencyKey) {\n const claimed = await post<EventApprovalClaimResult>(\n `/events/approval-offers/${resource(offerId)}/claim`,\n body,\n idempotencyKey,\n )\n return claimed.checkoutSession\n },\n }\n return client\n}\n"]}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
// src/forms/shared.ts
|
|
2
|
+
var FORM_ANSWER_PREFIX = "answers";
|
|
3
|
+
var ADDRESS_PROPERTIES = [
|
|
4
|
+
"line1",
|
|
5
|
+
"line2",
|
|
6
|
+
"city",
|
|
7
|
+
"postalCode",
|
|
8
|
+
"countryCode",
|
|
9
|
+
"provinceCode"
|
|
10
|
+
];
|
|
11
|
+
function formAnswerName(fieldKey, property) {
|
|
12
|
+
return property === void 0 ? `${FORM_ANSWER_PREFIX}[${fieldKey}]` : `${FORM_ANSWER_PREFIX}[${fieldKey}][${property}]`;
|
|
13
|
+
}
|
|
14
|
+
function resolveFormText(value, locale, fallbackLocale = "en") {
|
|
15
|
+
if (value === void 0) return "";
|
|
16
|
+
return value[locale] ?? value[locale.split("-")[0]] ?? value[fallbackLocale] ?? Object.values(value)[0] ?? "";
|
|
17
|
+
}
|
|
18
|
+
function isEmpty(value) {
|
|
19
|
+
if (value === void 0 || value === "" || value === false) return true;
|
|
20
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
21
|
+
if (typeof value === "object") return Object.values(value).every((item) => item === "");
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
function evaluateFormRule(rule, answers) {
|
|
25
|
+
const actual = answers[rule.fieldKey];
|
|
26
|
+
switch (rule.operator) {
|
|
27
|
+
case "is_empty":
|
|
28
|
+
return isEmpty(actual);
|
|
29
|
+
case "is_not_empty":
|
|
30
|
+
return !isEmpty(actual);
|
|
31
|
+
case "includes":
|
|
32
|
+
return Array.isArray(actual) && actual.includes(String(rule.value ?? ""));
|
|
33
|
+
case "equals":
|
|
34
|
+
return actual === rule.value;
|
|
35
|
+
case "not_equals":
|
|
36
|
+
return actual !== rule.value;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function isFormFieldVisible(field, answers) {
|
|
40
|
+
return field.visibleWhen?.all.every((rule) => evaluateFormRule(rule, answers)) ?? true;
|
|
41
|
+
}
|
|
42
|
+
function formFields(schema) {
|
|
43
|
+
return schema.pages.flatMap(
|
|
44
|
+
(page) => page.blocks.flatMap((block) => block.type === "field" ? [block.field] : [])
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
function parseFormAnswers(schema, data) {
|
|
48
|
+
const answers = {};
|
|
49
|
+
for (const field of formFields(schema)) {
|
|
50
|
+
const name = formAnswerName(field.key);
|
|
51
|
+
if (field.kind === "address") {
|
|
52
|
+
const address = Object.fromEntries(
|
|
53
|
+
ADDRESS_PROPERTIES.map((property) => [
|
|
54
|
+
property,
|
|
55
|
+
String(data.get(formAnswerName(field.key, property)) ?? "")
|
|
56
|
+
]).filter(([, value]) => value !== "")
|
|
57
|
+
);
|
|
58
|
+
if (Object.keys(address).length > 0) answers[field.key] = address;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (field.kind === "multi_select") {
|
|
62
|
+
const values = data.getAll(name).map(String);
|
|
63
|
+
if (values.length > 0) answers[field.key] = values;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (field.kind === "checkbox" || field.kind === "consent") {
|
|
67
|
+
answers[field.key] = data.has(name);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const raw = data.get(name);
|
|
71
|
+
if (raw === null || raw === "") continue;
|
|
72
|
+
answers[field.key] = field.kind === "number" ? Number(raw) : String(raw);
|
|
73
|
+
}
|
|
74
|
+
return answers;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/forms/html.ts
|
|
78
|
+
function escapeHtml(value) {
|
|
79
|
+
return String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
80
|
+
}
|
|
81
|
+
function attrs(values) {
|
|
82
|
+
return Object.entries(values).filter(([, value]) => value !== void 0 && value !== false).map(([key, value]) => value === true ? key : `${key}="${escapeHtml(value)}"`).join(" ");
|
|
83
|
+
}
|
|
84
|
+
function scalarAnswer(value) {
|
|
85
|
+
return typeof value === "string" || typeof value === "number" ? String(value) : "";
|
|
86
|
+
}
|
|
87
|
+
function renderErrors(field, errors) {
|
|
88
|
+
if (errors.length === 0) return "";
|
|
89
|
+
return `<ul id="form-${escapeHtml(field.key)}-errors" data-kotao-form-errors>${errors.map((error) => `<li>${escapeHtml(error)}</li>`).join("")}</ul>`;
|
|
90
|
+
}
|
|
91
|
+
function renderChoices(field, locale, value) {
|
|
92
|
+
const selected = Array.isArray(value) ? value : [String(value ?? "")];
|
|
93
|
+
if (field.kind === "select" || field.kind === "multi_select") {
|
|
94
|
+
return `<select ${attrs({ id: `form-${field.key}`, name: formAnswerName(field.key), required: field.required, multiple: field.kind === "multi_select" })}>${field.choices?.map((choice) => `<option value="${escapeHtml(choice.value)}"${selected.includes(choice.value) ? " selected" : ""}>${escapeHtml(resolveFormText(choice.label, locale))}</option>`).join("") ?? ""}</select>`;
|
|
95
|
+
}
|
|
96
|
+
return `<div role="radiogroup">${field.choices?.map((choice) => `<label><input ${attrs({ type: "radio", name: formAnswerName(field.key), value: choice.value, required: field.required, checked: selected.includes(choice.value) })}> <span>${escapeHtml(resolveFormText(choice.label, locale))}</span></label>`).join("") ?? ""}</div>`;
|
|
97
|
+
}
|
|
98
|
+
function renderField(field, options) {
|
|
99
|
+
const { locale, answers = {}, errors = {} } = options;
|
|
100
|
+
if (!isFormFieldVisible(field, answers)) return "";
|
|
101
|
+
const value = answers[field.key];
|
|
102
|
+
const fieldErrors = errors[field.key] ?? [];
|
|
103
|
+
const id = `form-${field.key}`;
|
|
104
|
+
const label = resolveFormText(field.label, locale, options.fallbackLocale);
|
|
105
|
+
const describedBy = [field.description ? `${id}-description` : "", fieldErrors.length ? `${id}-errors` : ""].filter(Boolean).join(" ") || void 0;
|
|
106
|
+
let control;
|
|
107
|
+
if (field.kind === "textarea") {
|
|
108
|
+
control = `<textarea ${attrs({ id, name: formAnswerName(field.key), required: field.required, minlength: field.validation?.minLength, maxlength: field.validation?.maxLength, "aria-invalid": fieldErrors.length > 0 ? "true" : void 0, "aria-describedby": describedBy })}>${escapeHtml(scalarAnswer(value))}</textarea>`;
|
|
109
|
+
} else if (field.kind === "address") {
|
|
110
|
+
const address = typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
111
|
+
control = `<fieldset><legend>${escapeHtml(label)}</legend>${ADDRESS_PROPERTIES.map((property) => `<label><span>${escapeHtml(property)}</span><input ${attrs({ name: formAnswerName(field.key, property), value: address[property] ?? "", required: field.required && ["line1", "postalCode", "city", "countryCode"].includes(property) })}></label>`).join("")}</fieldset>`;
|
|
112
|
+
} else if (field.kind === "select" || field.kind === "multi_select" || field.kind === "radio") {
|
|
113
|
+
control = renderChoices(field, locale, value);
|
|
114
|
+
} else if (field.kind === "checkbox" || field.kind === "consent") {
|
|
115
|
+
const text = field.kind === "consent" ? resolveFormText(field.consentText, locale) : label;
|
|
116
|
+
control = `<label><input ${attrs({ id, type: "checkbox", name: formAnswerName(field.key), value: "true", required: field.required, checked: value === true, "aria-invalid": fieldErrors.length > 0 ? "true" : void 0, "aria-describedby": describedBy })}> <span>${escapeHtml(text)}</span></label>`;
|
|
117
|
+
} else {
|
|
118
|
+
const type = field.kind === "phone" ? "tel" : field.kind;
|
|
119
|
+
control = `<input ${attrs({ id, type, name: formAnswerName(field.key), value: scalarAnswer(value), required: field.required, minlength: field.validation?.minLength, maxlength: field.validation?.maxLength, min: field.validation?.min, max: field.validation?.max, "aria-invalid": fieldErrors.length > 0 ? "true" : void 0, "aria-describedby": describedBy })}>`;
|
|
120
|
+
}
|
|
121
|
+
const visibleLabel = field.kind !== "address" && field.kind !== "checkbox" && field.kind !== "consent" ? `<label for="${escapeHtml(id)}">${escapeHtml(label)}${field.required ? ' <span aria-hidden="true">*</span>' : ""}</label>` : "";
|
|
122
|
+
const description = field.description ? `<p id="${escapeHtml(id)}-description">${escapeHtml(resolveFormText(field.description, locale))}</p>` : "";
|
|
123
|
+
return `<div data-kotao-form-field="${escapeHtml(field.key)}">${visibleLabel}${control}${description}${renderErrors(field, fieldErrors)}</div>`;
|
|
124
|
+
}
|
|
125
|
+
function renderFormHtml(form, options) {
|
|
126
|
+
const { schema } = form.version;
|
|
127
|
+
const success = options.submitted ? `<p role="status" data-kotao-form-success>${escapeHtml(resolveFormText(schema.successMessage, options.locale, options.fallbackLocale))}</p>` : "";
|
|
128
|
+
const pages = schema.pages.map(
|
|
129
|
+
(page) => `<section data-kotao-form-page="${escapeHtml(page.key)}">${page.title ? `<h2>${escapeHtml(resolveFormText(page.title, options.locale, options.fallbackLocale))}</h2>` : ""}${page.description ? `<p>${escapeHtml(resolveFormText(page.description, options.locale, options.fallbackLocale))}</p>` : ""}${page.blocks.map((block) => block.type === "field" ? renderField(block.field, options) : block.type === "section" ? `<header><h3>${escapeHtml(resolveFormText(block.title, options.locale, options.fallbackLocale))}</h3>${block.description ? `<p>${escapeHtml(resolveFormText(block.description, options.locale, options.fallbackLocale))}</p>` : ""}</header>` : `<div data-kotao-form-content>${escapeHtml(resolveFormText(block.content, options.locale, options.fallbackLocale))}</div>`).join("")}</section>`
|
|
130
|
+
).join("");
|
|
131
|
+
const idempotencyInput = options.idempotencyKey ? `<input type="hidden" name="idempotencyKey" value="${escapeHtml(options.idempotencyKey)}">` : "";
|
|
132
|
+
const honeypot = options.honeypotName ? `<div hidden aria-hidden="true"><label>Leave this field empty<input type="text" name="${escapeHtml(options.honeypotName)}" tabindex="-1" autocomplete="off"></label></div>` : "";
|
|
133
|
+
return `<form ${attrs({ method: "post", action: options.action ?? "", class: options.formClass, "data-kotao-form": form.definition.handle })}><input type="hidden" name="versionId" value="${escapeHtml(form.version.id)}"><input type="hidden" name="locale" value="${escapeHtml(options.locale)}">${idempotencyInput}${honeypot}${success}${pages}<button type="submit">${escapeHtml(resolveFormText(schema.submitLabel, options.locale, options.fallbackLocale) || "Submit")}</button></form>`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/forms/client.ts
|
|
137
|
+
var StorefrontFormRequestError = class extends Error {
|
|
138
|
+
status;
|
|
139
|
+
fieldErrors;
|
|
140
|
+
constructor(status, message, fieldErrors = {}) {
|
|
141
|
+
super(message);
|
|
142
|
+
this.name = "StorefrontFormRequestError";
|
|
143
|
+
this.status = status;
|
|
144
|
+
this.fieldErrors = fieldErrors;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
function endpoint(baseUrl, handle, suffix = "") {
|
|
148
|
+
const base = (baseUrl ?? "/api/storefront").replace(/\/$/, "");
|
|
149
|
+
return `${base}/forms/${encodeURIComponent(handle)}${suffix}`;
|
|
150
|
+
}
|
|
151
|
+
async function requestError(response) {
|
|
152
|
+
let body = {};
|
|
153
|
+
try {
|
|
154
|
+
body = await response.json();
|
|
155
|
+
} catch {
|
|
156
|
+
}
|
|
157
|
+
return new StorefrontFormRequestError(
|
|
158
|
+
response.status,
|
|
159
|
+
body.error ?? `Form request failed with status ${response.status}`,
|
|
160
|
+
body.fieldErrors
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
async function loadPublishedForm(handle, options = {}) {
|
|
164
|
+
const fetcher = options.fetch ?? fetch;
|
|
165
|
+
const response = await fetcher(endpoint(options.apiBaseUrl, handle), {
|
|
166
|
+
method: "GET",
|
|
167
|
+
...options.headers !== void 0 ? { headers: options.headers } : {},
|
|
168
|
+
...options.signal !== void 0 ? { signal: options.signal } : {}
|
|
169
|
+
});
|
|
170
|
+
if (!response.ok) throw await requestError(response);
|
|
171
|
+
return await response.json();
|
|
172
|
+
}
|
|
173
|
+
async function submitPublishedForm(handle, input) {
|
|
174
|
+
const fetcher = input.fetch ?? fetch;
|
|
175
|
+
const headers = new Headers(input.headers);
|
|
176
|
+
headers.set("content-type", "application/json");
|
|
177
|
+
headers.set("idempotency-key", input.idempotencyKey ?? crypto.randomUUID());
|
|
178
|
+
const response = await fetcher(endpoint(input.apiBaseUrl, handle, "/submissions"), {
|
|
179
|
+
method: "POST",
|
|
180
|
+
headers,
|
|
181
|
+
...input.signal !== void 0 ? { signal: input.signal } : {},
|
|
182
|
+
body: JSON.stringify({
|
|
183
|
+
versionId: input.versionId,
|
|
184
|
+
locale: input.locale,
|
|
185
|
+
answers: input.answers
|
|
186
|
+
})
|
|
187
|
+
});
|
|
188
|
+
if (!response.ok) throw await requestError(response);
|
|
189
|
+
return await response.json();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// src/forms/shopify-contact.ts
|
|
193
|
+
var STANDARD_FIELD_KINDS = {
|
|
194
|
+
name: ["text"],
|
|
195
|
+
email: ["email", "text"],
|
|
196
|
+
body: ["textarea", "text"],
|
|
197
|
+
phone: ["phone", "text"]
|
|
198
|
+
};
|
|
199
|
+
function inputValue(input, key) {
|
|
200
|
+
switch (key) {
|
|
201
|
+
case "name":
|
|
202
|
+
return input.name;
|
|
203
|
+
case "email":
|
|
204
|
+
return input.email;
|
|
205
|
+
case "body":
|
|
206
|
+
return input.body;
|
|
207
|
+
case "phone":
|
|
208
|
+
return input.phone;
|
|
209
|
+
default:
|
|
210
|
+
return void 0;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function adaptShopifyContactForm(form, input) {
|
|
214
|
+
if (form.definition.purpose !== "contact") {
|
|
215
|
+
return { compatible: false, reason: "not-contact-purpose" };
|
|
216
|
+
}
|
|
217
|
+
const fields = formFields(form.version.schema);
|
|
218
|
+
for (const field of fields) {
|
|
219
|
+
const supportedKinds = STANDARD_FIELD_KINDS[field.key];
|
|
220
|
+
if (supportedKinds === void 0) {
|
|
221
|
+
if (field.required) return { compatible: false, reason: "unsupported-required-field" };
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (!supportedKinds.includes(field.kind)) {
|
|
225
|
+
return { compatible: false, reason: "incompatible-standard-field" };
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const answers = {};
|
|
229
|
+
for (const field of fields) {
|
|
230
|
+
if (STANDARD_FIELD_KINDS[field.key] === void 0) continue;
|
|
231
|
+
const value = inputValue(input, field.key);
|
|
232
|
+
if (value !== void 0 && value !== null) answers[field.key] = value;
|
|
233
|
+
}
|
|
234
|
+
return { compatible: true, answers };
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export { ADDRESS_PROPERTIES, FORM_ANSWER_PREFIX, StorefrontFormRequestError, adaptShopifyContactForm, evaluateFormRule, formAnswerName, formFields, isFormFieldVisible, loadPublishedForm, parseFormAnswers, renderFormHtml, resolveFormText, submitPublishedForm };
|
|
238
|
+
//# sourceMappingURL=chunk-IIOHENCG.js.map
|
|
239
|
+
//# sourceMappingURL=chunk-IIOHENCG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/forms/shared.ts","../src/forms/html.ts","../src/forms/client.ts","../src/forms/shopify-contact.ts"],"names":[],"mappings":";AASO,IAAM,kBAAA,GAAqB;AAC3B,IAAM,kBAAA,GAAqB;AAAA,EAChC,OAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF;AAEO,SAAS,cAAA,CAAe,UAAkB,QAAA,EAA2B;AAC1E,EAAA,OAAO,QAAA,KAAa,MAAA,GAChB,CAAA,EAAG,kBAAkB,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,CAAA,GACjC,CAAA,EAAG,kBAAkB,CAAA,CAAA,EAAI,QAAQ,CAAA,EAAA,EAAK,QAAQ,CAAA,CAAA,CAAA;AACpD;AAEO,SAAS,eAAA,CACd,KAAA,EACA,MAAA,EACA,cAAA,GAAiB,IAAA,EACT;AACR,EAAA,IAAI,KAAA,KAAU,QAAW,OAAO,EAAA;AAChC,EAAA,OACE,MAAM,MAAM,CAAA,IACZ,MAAM,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAE,CAAA,IAC3B,KAAA,CAAM,cAAc,CAAA,IACpB,MAAA,CAAO,OAAO,KAAK,CAAA,CAAE,CAAC,CAAA,IACtB,EAAA;AAEJ;AAEA,SAAS,QAAQ,KAAA,EAAwC;AACvD,EAAA,IAAI,UAAU,MAAA,IAAa,KAAA,KAAU,EAAA,IAAM,KAAA,KAAU,OAAO,OAAO,IAAA;AACnE,EAAA,IAAI,MAAM,OAAA,CAAQ,KAAK,CAAA,EAAG,OAAO,MAAM,MAAA,KAAW,CAAA;AAClD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA,CAAE,KAAA,CAAM,CAAC,IAAA,KAAS,IAAA,KAAS,EAAE,CAAA;AACtF,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,gBAAA,CAAiB,MAA0B,OAAA,EAA+B;AACxF,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,IAAA,CAAK,QAAQ,CAAA;AACpC,EAAA,QAAQ,KAAK,QAAA;AAAU,IACrB,KAAK,UAAA;AACH,MAAA,OAAO,QAAQ,MAAM,CAAA;AAAA,IACvB,KAAK,cAAA;AACH,MAAA,OAAO,CAAC,QAAQ,MAAM,CAAA;AAAA,IACxB,KAAK,UAAA;AACH,MAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,IAAK,MAAA,CAAO,SAAS,MAAA,CAAO,IAAA,CAAK,KAAA,IAAS,EAAE,CAAC,CAAA;AAAA,IAC1E,KAAK,QAAA;AACH,MAAA,OAAO,WAAW,IAAA,CAAK,KAAA;AAAA,IACzB,KAAK,YAAA;AACH,MAAA,OAAO,WAAW,IAAA,CAAK,KAAA;AAAA;AAE7B;AAEO,SAAS,kBAAA,CAAmB,OAAkB,OAAA,EAA+B;AAClF,EAAA,OAAO,KAAA,CAAM,WAAA,EAAa,GAAA,CAAI,KAAA,CAAM,CAAC,SAAS,gBAAA,CAAiB,IAAA,EAAM,OAAO,CAAC,CAAA,IAAK,IAAA;AACpF;AAEO,SAAS,WAAW,MAAA,EAAwC;AACjE,EAAA,OAAO,OAAO,KAAA,CAAM,OAAA;AAAA,IAAQ,CAAC,IAAA,KAC3B,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAC,KAAA,KAAW,KAAA,CAAM,IAAA,KAAS,UAAU,CAAC,KAAA,CAAM,KAAK,CAAA,GAAI,EAAG;AAAA,GAC9E;AACF;AAEO,SAAS,gBAAA,CAAiB,QAA2B,IAAA,EAA6B;AACvF,EAAA,MAAM,UAAuB,EAAC;AAC9B,EAAA,KAAA,MAAW,KAAA,IAAS,UAAA,CAAW,MAAM,CAAA,EAAG;AACtC,IAAA,MAAM,IAAA,GAAO,cAAA,CAAe,KAAA,CAAM,GAAG,CAAA;AACrC,IAAA,IAAI,KAAA,CAAM,SAAS,SAAA,EAAW;AAC5B,MAAA,MAAM,UAAU,MAAA,CAAO,WAAA;AAAA,QACrB,kBAAA,CAAmB,GAAA,CAAI,CAAC,QAAA,KAAa;AAAA,UACnC,QAAA;AAAA,UACA,MAAA,CAAO,KAAK,GAAA,CAAI,cAAA,CAAe,MAAM,GAAA,EAAK,QAAQ,CAAC,CAAA,IAAK,EAAE;AAAA,SAC3D,EAAE,MAAA,CAAO,CAAC,GAAG,KAAK,CAAA,KAAM,KAAA,KAAU,EAAE;AAAA,OACvC;AACA,MAAA,IAAI,MAAA,CAAO,KAAK,OAAO,CAAA,CAAE,SAAS,CAAA,EAAG,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA,GAAI,OAAA;AAC1D,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAA,CAAM,SAAS,cAAA,EAAgB;AACjC,MAAA,MAAM,SAAS,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA,CAAE,IAAI,MAAM,CAAA;AAC3C,MAAA,IAAI,OAAO,MAAA,GAAS,CAAA,EAAG,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA,GAAI,MAAA;AAC5C,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAA,CAAM,IAAA,KAAS,UAAA,IAAc,KAAA,CAAM,SAAS,SAAA,EAAW;AACzD,MAAA,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA,GAAI,IAAA,CAAK,IAAI,IAAI,CAAA;AAClC,MAAA;AAAA,IACF;AACA,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA;AACzB,IAAA,IAAI,GAAA,KAAQ,IAAA,IAAQ,GAAA,KAAQ,EAAA,EAAI;AAChC,IAAA,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA,GAAI,KAAA,CAAM,IAAA,KAAS,WAAW,MAAA,CAAO,GAAG,CAAA,GAAI,MAAA,CAAO,GAAG,CAAA;AAAA,EACzE;AACA,EAAA,OAAO,OAAA;AACT;;;ACzFA,SAAS,WAAW,KAAA,EAAwB;AAC1C,EAAA,OAAO,MAAA,CAAO,KAAK,CAAA,CAChB,UAAA,CAAW,KAAK,OAAO,CAAA,CACvB,WAAW,GAAA,EAAK,MAAM,EACtB,UAAA,CAAW,GAAA,EAAK,MAAM,CAAA,CACtB,UAAA,CAAW,KAAK,QAAQ,CAAA,CACxB,UAAA,CAAW,GAAA,EAAK,OAAO,CAAA;AAC5B;AAEA,SAAS,MAAM,MAAA,EAAuE;AACpF,EAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CACzB,OAAO,CAAC,GAAG,KAAK,CAAA,KAAM,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,KAAK,CAAA,CAC5D,GAAA,CAAI,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAO,KAAA,KAAU,OAAO,GAAA,GAAM,CAAA,EAAG,GAAG,CAAA,EAAA,EAAK,WAAW,KAAK,CAAC,CAAA,CAAA,CAAI,CAAA,CAC9E,KAAK,GAAG,CAAA;AACb;AAEA,SAAS,aAAa,KAAA,EAAuC;AAC3D,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,OAAO,UAAU,QAAA,GAAW,MAAA,CAAO,KAAK,CAAA,GAAI,EAAA;AAClF;AAEA,SAAS,YAAA,CAAa,OAAkB,MAAA,EAA0B;AAChE,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,EAAA;AAChC,EAAA,OAAO,gBAAgB,UAAA,CAAW,KAAA,CAAM,GAAG,CAAC,CAAA,gCAAA,EAAmC,OAAO,GAAA,CAAI,CAAC,KAAA,KAAU,CAAA,IAAA,EAAO,WAAW,KAAK,CAAC,OAAO,CAAA,CAAE,IAAA,CAAK,EAAE,CAAC,CAAA,KAAA,CAAA;AAChJ;AAEA,SAAS,aAAA,CAAc,KAAA,EAAkB,MAAA,EAAgB,KAAA,EAAuC;AAC9F,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,QAAQ,CAAC,MAAA,CAAO,KAAA,IAAS,EAAE,CAAC,CAAA;AACpE,EAAA,IAAI,KAAA,CAAM,IAAA,KAAS,QAAA,IAAY,KAAA,CAAM,SAAS,cAAA,EAAgB;AAC5D,IAAA,OAAO,CAAA,QAAA,EAAW,KAAA,CAAM,EAAE,EAAA,EAAI,CAAA,KAAA,EAAQ,MAAM,GAAG,CAAA,CAAA,EAAI,IAAA,EAAM,cAAA,CAAe,KAAA,CAAM,GAAG,GAAG,QAAA,EAAU,KAAA,CAAM,QAAA,EAAU,QAAA,EAAU,KAAA,CAAM,IAAA,KAAS,cAAA,EAAgB,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,OAAA,EAAS,GAAA,CAAI,CAAC,WAAW,CAAA,eAAA,EAAkB,UAAA,CAAW,MAAA,CAAO,KAAK,CAAC,CAAA,CAAA,EAAI,SAAS,QAAA,CAAS,MAAA,CAAO,KAAK,CAAA,GAAI,WAAA,GAAc,EAAE,IAAI,UAAA,CAAW,eAAA,CAAgB,MAAA,CAAO,KAAA,EAAO,MAAM,CAAC,CAAC,CAAA,SAAA,CAAW,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA,IAAK,EAAE,CAAA,SAAA,CAAA;AAAA,EAC7W;AACA,EAAA,OAAO,0BAA0B,KAAA,CAAM,OAAA,EAAS,IAAI,CAAC,MAAA,KAAW,iBAAiB,KAAA,CAAM,EAAE,MAAM,OAAA,EAAS,IAAA,EAAM,eAAe,KAAA,CAAM,GAAG,GAAG,KAAA,EAAO,MAAA,CAAO,OAAO,QAAA,EAAU,KAAA,CAAM,UAAU,OAAA,EAAS,QAAA,CAAS,SAAS,MAAA,CAAO,KAAK,GAAG,CAAC,WAAW,UAAA,CAAW,eAAA,CAAgB,OAAO,KAAA,EAAO,MAAM,CAAC,CAAC,CAAA,eAAA,CAAiB,EAAE,IAAA,CAAK,EAAE,KAAK,EAAE,CAAA,MAAA,CAAA;AAClU;AAEA,SAAS,WAAA,CAAY,OAAkB,OAAA,EAAwC;AAC7E,EAAA,MAAM,EAAE,QAAQ,OAAA,GAAU,IAAI,MAAA,GAAS,IAAG,GAAI,OAAA;AAC9C,EAAA,IAAI,CAAC,kBAAA,CAAmB,KAAA,EAAO,OAAO,GAAG,OAAO,EAAA;AAChD,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA;AAC/B,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,KAAA,CAAM,GAAG,KAAK,EAAC;AAC1C,EAAA,MAAM,EAAA,GAAK,CAAA,KAAA,EAAQ,KAAA,CAAM,GAAG,CAAA,CAAA;AAC5B,EAAA,MAAM,QAAQ,eAAA,CAAgB,KAAA,CAAM,KAAA,EAAO,MAAA,EAAQ,QAAQ,cAAc,CAAA;AACzE,EAAA,MAAM,WAAA,GACJ,CAAC,KAAA,CAAM,WAAA,GAAc,GAAG,EAAE,CAAA,YAAA,CAAA,GAAiB,IAAI,WAAA,CAAY,MAAA,GAAS,GAAG,EAAE,CAAA,OAAA,CAAA,GAAY,EAAE,CAAA,CACpF,MAAA,CAAO,OAAO,CAAA,CACd,IAAA,CAAK,GAAG,CAAA,IAAK,MAAA;AAClB,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,KAAA,CAAM,SAAS,UAAA,EAAY;AAC7B,IAAA,OAAA,GAAU,CAAA,UAAA,EAAa,KAAA,CAAM,EAAE,EAAA,EAAI,MAAM,cAAA,CAAe,KAAA,CAAM,GAAG,CAAA,EAAG,UAAU,KAAA,CAAM,QAAA,EAAU,SAAA,EAAW,KAAA,CAAM,YAAY,SAAA,EAAW,SAAA,EAAW,KAAA,CAAM,UAAA,EAAY,WAAW,cAAA,EAAgB,WAAA,CAAY,MAAA,GAAS,CAAA,GAAI,SAAS,MAAA,EAAW,kBAAA,EAAoB,WAAA,EAAa,CAAC,CAAA,CAAA,EAAI,UAAA,CAAW,YAAA,CAAa,KAAK,CAAC,CAAC,CAAA,WAAA,CAAA;AAAA,EAClT,CAAA,MAAA,IAAW,KAAA,CAAM,IAAA,KAAS,SAAA,EAAW;AACnC,IAAA,MAAM,OAAA,GAAU,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,MAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,KAAA,GAAQ,EAAC;AAC9E,IAAA,OAAA,GAAU,CAAA,kBAAA,EAAqB,WAAW,KAAK,CAAC,YAAY,kBAAA,CAAmB,GAAA,CAAI,CAAC,QAAA,KAAa,CAAA,aAAA,EAAgB,WAAW,QAAQ,CAAC,iBAAiB,KAAA,CAAM,EAAE,MAAM,cAAA,CAAe,KAAA,CAAM,KAAK,QAAQ,CAAA,EAAG,OAAO,OAAA,CAAQ,QAAQ,KAAK,EAAA,EAAI,QAAA,EAAU,MAAM,QAAA,IAAY,CAAC,SAAS,YAAA,EAAc,MAAA,EAAQ,aAAa,CAAA,CAAE,QAAA,CAAS,QAAQ,CAAA,EAAG,CAAC,CAAA,SAAA,CAAW,CAAA,CAAE,IAAA,CAAK,EAAE,CAAC,CAAA,WAAA,CAAA;AAAA,EAChW,CAAA,MAAA,IAAW,MAAM,IAAA,KAAS,QAAA,IAAY,MAAM,IAAA,KAAS,cAAA,IAAkB,KAAA,CAAM,IAAA,KAAS,OAAA,EAAS;AAC7F,IAAA,OAAA,GAAU,aAAA,CAAc,KAAA,EAAO,MAAA,EAAQ,KAAK,CAAA;AAAA,EAC9C,WAAW,KAAA,CAAM,IAAA,KAAS,UAAA,IAAc,KAAA,CAAM,SAAS,SAAA,EAAW;AAChE,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,KAAS,SAAA,GAAY,gBAAgB,KAAA,CAAM,WAAA,EAAa,MAAM,CAAA,GAAI,KAAA;AACrF,IAAA,OAAA,GAAU,CAAA,cAAA,EAAiB,KAAA,CAAM,EAAE,EAAA,EAAI,MAAM,UAAA,EAAY,IAAA,EAAM,cAAA,CAAe,KAAA,CAAM,GAAG,CAAA,EAAG,KAAA,EAAO,MAAA,EAAQ,UAAU,KAAA,CAAM,QAAA,EAAU,OAAA,EAAS,KAAA,KAAU,IAAA,EAAM,cAAA,EAAgB,WAAA,CAAY,MAAA,GAAS,IAAI,MAAA,GAAS,MAAA,EAAW,kBAAA,EAAoB,WAAA,EAAa,CAAC,CAAA,QAAA,EAAW,UAAA,CAAW,IAAI,CAAC,CAAA,eAAA,CAAA;AAAA,EACxR,CAAA,MAAO;AACL,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,IAAA,KAAS,OAAA,GAAU,QAAQ,KAAA,CAAM,IAAA;AACpD,IAAA,OAAA,GAAU,UAAU,KAAA,CAAM,EAAE,IAAI,IAAA,EAAM,IAAA,EAAM,eAAe,KAAA,CAAM,GAAG,GAAG,KAAA,EAAO,YAAA,CAAa,KAAK,CAAA,EAAG,QAAA,EAAU,MAAM,QAAA,EAAU,SAAA,EAAW,MAAM,UAAA,EAAY,SAAA,EAAW,SAAA,EAAW,KAAA,CAAM,YAAY,SAAA,EAAW,GAAA,EAAK,MAAM,UAAA,EAAY,GAAA,EAAK,KAAK,KAAA,CAAM,UAAA,EAAY,KAAK,cAAA,EAAgB,WAAA,CAAY,SAAS,CAAA,GAAI,MAAA,GAAS,QAAW,kBAAA,EAAoB,WAAA,EAAa,CAAC,CAAA,CAAA,CAAA;AAAA,EACtW;AACA,EAAA,MAAM,YAAA,GACJ,MAAM,IAAA,KAAS,SAAA,IAAa,MAAM,IAAA,KAAS,UAAA,IAAc,KAAA,CAAM,IAAA,KAAS,SAAA,GACpE,CAAA,YAAA,EAAe,WAAW,EAAE,CAAC,CAAA,EAAA,EAAK,UAAA,CAAW,KAAK,CAAC,GAAG,KAAA,CAAM,QAAA,GAAW,oCAAA,GAAuC,EAAE,CAAA,QAAA,CAAA,GAChH,EAAA;AACN,EAAA,MAAM,WAAA,GAAc,KAAA,CAAM,WAAA,GACtB,CAAA,OAAA,EAAU,WAAW,EAAE,CAAC,CAAA,cAAA,EAAiB,UAAA,CAAW,gBAAgB,KAAA,CAAM,WAAA,EAAa,MAAM,CAAC,CAAC,CAAA,IAAA,CAAA,GAC/F,EAAA;AACJ,EAAA,OAAO,CAAA,4BAAA,EAA+B,UAAA,CAAW,KAAA,CAAM,GAAG,CAAC,CAAA,EAAA,EAAK,YAAY,CAAA,EAAG,OAAO,GAAG,WAAW,CAAA,EAAG,YAAA,CAAa,KAAA,EAAO,WAAW,CAAC,CAAA,MAAA,CAAA;AACzI;AAEO,SAAS,cAAA,CAAe,MAAkB,OAAA,EAAwC;AACvF,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,IAAA,CAAK,OAAA;AACxB,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,SAAA,GACpB,CAAA,yCAAA,EAA4C,WAAW,eAAA,CAAgB,MAAA,CAAO,cAAA,EAAgB,OAAA,CAAQ,MAAA,EAAQ,OAAA,CAAQ,cAAc,CAAC,CAAC,CAAA,IAAA,CAAA,GACtI,EAAA;AACJ,EAAA,MAAM,KAAA,GAAQ,OAAO,KAAA,CAClB,GAAA;AAAA,IACC,CAAC,SACC,CAAA,+BAAA,EAAkC,UAAA,CAAW,KAAK,GAAG,CAAC,KAAK,IAAA,CAAK,KAAA,GAAQ,OAAO,UAAA,CAAW,eAAA,CAAgB,KAAK,KAAA,EAAO,OAAA,CAAQ,QAAQ,OAAA,CAAQ,cAAc,CAAC,CAAC,CAAA,KAAA,CAAA,GAAU,EAAE,GAAG,IAAA,CAAK,WAAA,GAAc,MAAM,UAAA,CAAW,eAAA,CAAgB,KAAK,WAAA,EAAa,OAAA,CAAQ,MAAA,EAAQ,OAAA,CAAQ,cAAc,CAAC,CAAC,CAAA,IAAA,CAAA,GAAS,EAAE,GAAG,IAAA,CAAK,MAAA,CAAO,IAAI,CAAC,KAAA,KAAW,KAAA,CAAM,IAAA,KAAS,OAAA,GAAU,WAAA,CAAY,MAAM,KAAA,EAAO,OAAO,IAAI,KAAA,CAAM,IAAA,KAAS,YAAY,CAAA,YAAA,EAAe,UAAA,CAAW,eAAA,CAAgB,KAAA,CAAM,KAAA,EAAO,OAAA,CAAQ,QAAQ,OAAA,CAAQ,cAAc,CAAC,CAAC,CAAA,KAAA,EAAQ,MAAM,WAAA,GAAc,CAAA,GAAA,EAAM,UAAA,CAAW,eAAA,CAAgB,KAAA,CAAM,WAAA,EAAa,QAAQ,MAAA,EAAQ,OAAA,CAAQ,cAAc,CAAC,CAAC,SAAS,EAAE,CAAA,SAAA,CAAA,GAAc,CAAA,6BAAA,EAAgC,UAAA,CAAW,eAAA,CAAgB,KAAA,CAAM,SAAS,OAAA,CAAQ,MAAA,EAAQ,QAAQ,cAAc,CAAC,CAAC,CAAA,MAAA,CAAS,CAAA,CAAE,IAAA,CAAK,EAAE,CAAC,CAAA,UAAA;AAAA,GACtxB,CACC,KAAK,EAAE,CAAA;AACV,EAAA,MAAM,gBAAA,GAAmB,QAAQ,cAAA,GAC7B,CAAA,kDAAA,EAAqD,WAAW,OAAA,CAAQ,cAAc,CAAC,CAAA,EAAA,CAAA,GACvF,EAAA;AACJ,EAAA,MAAM,QAAA,GAAW,QAAQ,YAAA,GACrB,CAAA,qFAAA,EAAwF,WAAW,OAAA,CAAQ,YAAY,CAAC,CAAA,iDAAA,CAAA,GACxH,EAAA;AACJ,EAAA,OAAO,CAAA,MAAA,EAAS,MAAM,EAAE,MAAA,EAAQ,QAAQ,MAAA,EAAQ,OAAA,CAAQ,MAAA,IAAU,EAAA,EAAI,KAAA,EAAO,OAAA,CAAQ,WAAW,iBAAA,EAAmB,IAAA,CAAK,WAAW,MAAA,EAAQ,CAAC,CAAA,8CAAA,EAAiD,UAAA,CAAW,IAAA,CAAK,OAAA,CAAQ,EAAE,CAAC,+CAA+C,UAAA,CAAW,OAAA,CAAQ,MAAM,CAAC,CAAA,EAAA,EAAK,gBAAgB,CAAA,EAAG,QAAQ,CAAA,EAAG,OAAO,CAAA,EAAG,KAAK,yBAAyB,UAAA,CAAW,eAAA,CAAgB,OAAO,WAAA,EAAa,OAAA,CAAQ,QAAQ,OAAA,CAAQ,cAAc,CAAA,IAAK,QAAQ,CAAC,CAAA,gBAAA,CAAA;AACjd;;;ACnFO,IAAM,0BAAA,GAAN,cAAyC,KAAA,CAAM;AAAA,EAC3C,MAAA;AAAA,EACA,WAAA;AAAA,EAET,WAAA,CAAY,MAAA,EAAgB,OAAA,EAAiB,WAAA,GAA+B,EAAC,EAAG;AAC9E,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,4BAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,WAAA,GAAc,WAAA;AAAA,EACrB;AACF;AAEA,SAAS,QAAA,CAAS,OAAA,EAA6B,MAAA,EAAgB,MAAA,GAAS,EAAA,EAAY;AAClF,EAAA,MAAM,IAAA,GAAA,CAAQ,OAAA,IAAW,iBAAA,EAAmB,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC7D,EAAA,OAAO,GAAG,IAAI,CAAA,OAAA,EAAU,mBAAmB,MAAM,CAAC,GAAG,MAAM,CAAA,CAAA;AAC7D;AAEA,eAAe,aAAa,QAAA,EAAyD;AACnF,EAAA,IAAI,OAA0D,EAAC;AAC/D,EAAA,IAAI;AACF,IAAA,IAAA,GAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,EAC9B,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,IAAI,0BAAA;AAAA,IACT,QAAA,CAAS,MAAA;AAAA,IACT,IAAA,CAAK,KAAA,IAAS,CAAA,gCAAA,EAAmC,QAAA,CAAS,MAAM,CAAA,CAAA;AAAA,IAChE,IAAA,CAAK;AAAA,GACP;AACF;AAEA,eAAsB,iBAAA,CACpB,MAAA,EACA,OAAA,GAA4B,EAAC,EACR;AACrB,EAAA,MAAM,OAAA,GAAU,QAAQ,KAAA,IAAS,KAAA;AACjC,EAAA,MAAM,WAAW,MAAM,OAAA,CAAQ,SAAS,OAAA,CAAQ,UAAA,EAAY,MAAM,CAAA,EAAG;AAAA,IACnE,MAAA,EAAQ,KAAA;AAAA,IACR,GAAI,QAAQ,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAQ,GAAI,EAAC;AAAA,IACpE,GAAI,QAAQ,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAAO,GAAI;AAAC,GAClE,CAAA;AACD,EAAA,IAAI,CAAC,QAAA,CAAS,EAAA,EAAI,MAAM,MAAM,aAAa,QAAQ,CAAA;AACnD,EAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAC9B;AAEA,eAAsB,mBAAA,CACpB,QACA,KAAA,EACyB;AACzB,EAAA,MAAM,OAAA,GAAU,MAAM,KAAA,IAAS,KAAA;AAC/B,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,KAAA,CAAM,OAAO,CAAA;AACzC,EAAA,OAAA,CAAQ,GAAA,CAAI,gBAAgB,kBAAkB,CAAA;AAC9C,EAAA,OAAA,CAAQ,IAAI,iBAAA,EAAmB,KAAA,CAAM,cAAA,IAAkB,MAAA,CAAO,YAAY,CAAA;AAC1E,EAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,QAAA,CAAS,MAAM,UAAA,EAAY,MAAA,EAAQ,cAAc,CAAA,EAAG;AAAA,IACjF,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA;AAAA,IACA,GAAI,MAAM,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,CAAM,MAAA,EAAO,GAAI,EAAC;AAAA,IAC7D,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,MACnB,WAAW,KAAA,CAAM,SAAA;AAAA,MACjB,QAAQ,KAAA,CAAM,MAAA;AAAA,MACd,SAAS,KAAA,CAAM;AAAA,KAChB;AAAA,GACF,CAAA;AACD,EAAA,IAAI,CAAC,QAAA,CAAS,EAAA,EAAI,MAAM,MAAM,aAAa,QAAQ,CAAA;AACnD,EAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAC9B;;;AC7DA,IAAM,oBAAA,GAA+E;AAAA,EACnF,IAAA,EAAM,CAAC,MAAM,CAAA;AAAA,EACb,KAAA,EAAO,CAAC,OAAA,EAAS,MAAM,CAAA;AAAA,EACvB,IAAA,EAAM,CAAC,UAAA,EAAY,MAAM,CAAA;AAAA,EACzB,KAAA,EAAO,CAAC,OAAA,EAAS,MAAM;AACzB,CAAA;AAEA,SAAS,UAAA,CAAW,OAA4B,GAAA,EAAwC;AACtF,EAAA,QAAQ,GAAA;AAAK,IACX,KAAK,MAAA;AACH,MAAA,OAAO,KAAA,CAAM,IAAA;AAAA,IACf,KAAK,OAAA;AACH,MAAA,OAAO,KAAA,CAAM,KAAA;AAAA,IACf,KAAK,MAAA;AACH,MAAA,OAAO,KAAA,CAAM,IAAA;AAAA,IACf,KAAK,OAAA;AACH,MAAA,OAAO,KAAA,CAAM,KAAA;AAAA,IACf;AACE,MAAA,OAAO,MAAA;AAAA;AAEb;AAEO,SAAS,uBAAA,CACd,MACA,KAAA,EAC6B;AAC7B,EAAA,IAAI,IAAA,CAAK,UAAA,CAAW,OAAA,KAAY,SAAA,EAAW;AACzC,IAAA,OAAO,EAAE,UAAA,EAAY,KAAA,EAAO,MAAA,EAAQ,qBAAA,EAAsB;AAAA,EAC5D;AAEA,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA;AAC7C,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,cAAA,GAAiB,oBAAA,CAAqB,KAAA,CAAM,GAAG,CAAA;AACrD,IAAA,IAAI,mBAAmB,MAAA,EAAW;AAChC,MAAA,IAAI,MAAM,QAAA,EAAU,OAAO,EAAE,UAAA,EAAY,KAAA,EAAO,QAAQ,4BAAA,EAA6B;AACrF,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,cAAA,CAAe,QAAA,CAAS,KAAA,CAAM,IAAI,CAAA,EAAG;AACxC,MAAA,OAAO,EAAE,UAAA,EAAY,KAAA,EAAO,MAAA,EAAQ,6BAAA,EAA8B;AAAA,IACpE;AAAA,EACF;AAEA,EAAA,MAAM,UAAuB,EAAC;AAC9B,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,IAAI,oBAAA,CAAqB,KAAA,CAAM,GAAG,CAAA,KAAM,MAAA,EAAW;AACnD,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,KAAA,EAAO,KAAA,CAAM,GAAG,CAAA;AACzC,IAAA,IAAI,UAAU,MAAA,IAAa,KAAA,KAAU,MAAM,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA,GAAI,KAAA;AAAA,EAClE;AACA,EAAA,OAAO,EAAE,UAAA,EAAY,IAAA,EAAM,OAAA,EAAQ;AACrC","file":"chunk-IIOHENCG.js","sourcesContent":["import type {\n FormAnswer,\n FormAnswers,\n FormField,\n FormLocalizedText,\n FormVersionSchema,\n FormVisibilityRule,\n} from './types'\n\nexport const FORM_ANSWER_PREFIX = 'answers'\nexport const ADDRESS_PROPERTIES = [\n 'line1',\n 'line2',\n 'city',\n 'postalCode',\n 'countryCode',\n 'provinceCode',\n] as const\n\nexport function formAnswerName(fieldKey: string, property?: string): string {\n return property === undefined\n ? `${FORM_ANSWER_PREFIX}[${fieldKey}]`\n : `${FORM_ANSWER_PREFIX}[${fieldKey}][${property}]`\n}\n\nexport function resolveFormText(\n value: FormLocalizedText | undefined,\n locale: string,\n fallbackLocale = 'en',\n): string {\n if (value === undefined) return ''\n return (\n value[locale] ??\n value[locale.split('-')[0]!] ??\n value[fallbackLocale] ??\n Object.values(value)[0] ??\n ''\n )\n}\n\nfunction isEmpty(value: FormAnswer | undefined): boolean {\n if (value === undefined || value === '' || value === false) return true\n if (Array.isArray(value)) return value.length === 0\n if (typeof value === 'object') return Object.values(value).every((item) => item === '')\n return false\n}\n\nexport function evaluateFormRule(rule: FormVisibilityRule, answers: FormAnswers): boolean {\n const actual = answers[rule.fieldKey]\n switch (rule.operator) {\n case 'is_empty':\n return isEmpty(actual)\n case 'is_not_empty':\n return !isEmpty(actual)\n case 'includes':\n return Array.isArray(actual) && actual.includes(String(rule.value ?? ''))\n case 'equals':\n return actual === rule.value\n case 'not_equals':\n return actual !== rule.value\n }\n}\n\nexport function isFormFieldVisible(field: FormField, answers: FormAnswers): boolean {\n return field.visibleWhen?.all.every((rule) => evaluateFormRule(rule, answers)) ?? true\n}\n\nexport function formFields(schema: FormVersionSchema): FormField[] {\n return schema.pages.flatMap((page) =>\n page.blocks.flatMap((block) => (block.type === 'field' ? [block.field] : [])),\n )\n}\n\nexport function parseFormAnswers(schema: FormVersionSchema, data: FormData): FormAnswers {\n const answers: FormAnswers = {}\n for (const field of formFields(schema)) {\n const name = formAnswerName(field.key)\n if (field.kind === 'address') {\n const address = Object.fromEntries(\n ADDRESS_PROPERTIES.map((property) => [\n property,\n String(data.get(formAnswerName(field.key, property)) ?? ''),\n ]).filter(([, value]) => value !== ''),\n )\n if (Object.keys(address).length > 0) answers[field.key] = address\n continue\n }\n if (field.kind === 'multi_select') {\n const values = data.getAll(name).map(String)\n if (values.length > 0) answers[field.key] = values\n continue\n }\n if (field.kind === 'checkbox' || field.kind === 'consent') {\n answers[field.key] = data.has(name)\n continue\n }\n const raw = data.get(name)\n if (raw === null || raw === '') continue\n answers[field.key] = field.kind === 'number' ? Number(raw) : String(raw)\n }\n return answers\n}\n","import { ADDRESS_PROPERTIES, formAnswerName, isFormFieldVisible, resolveFormText } from './shared'\nimport type { FormAnswer, FormField, FormRenderState, PublicForm } from './types'\n\nexport interface RenderFormHtmlOptions extends FormRenderState {\n locale: string\n action?: string\n formClass?: string\n fallbackLocale?: string\n idempotencyKey?: string\n honeypotName?: string\n}\n\nfunction escapeHtml(value: unknown): string {\n return String(value)\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''')\n}\n\nfunction attrs(values: Record<string, string | number | boolean | undefined>): string {\n return Object.entries(values)\n .filter(([, value]) => value !== undefined && value !== false)\n .map(([key, value]) => (value === true ? key : `${key}=\"${escapeHtml(value)}\"`))\n .join(' ')\n}\n\nfunction scalarAnswer(value: FormAnswer | undefined): string {\n return typeof value === 'string' || typeof value === 'number' ? String(value) : ''\n}\n\nfunction renderErrors(field: FormField, errors: string[]): string {\n if (errors.length === 0) return ''\n return `<ul id=\"form-${escapeHtml(field.key)}-errors\" data-kotao-form-errors>${errors.map((error) => `<li>${escapeHtml(error)}</li>`).join('')}</ul>`\n}\n\nfunction renderChoices(field: FormField, locale: string, value: FormAnswer | undefined): string {\n const selected = Array.isArray(value) ? value : [String(value ?? '')]\n if (field.kind === 'select' || field.kind === 'multi_select') {\n return `<select ${attrs({ id: `form-${field.key}`, name: formAnswerName(field.key), required: field.required, multiple: field.kind === 'multi_select' })}>${field.choices?.map((choice) => `<option value=\"${escapeHtml(choice.value)}\"${selected.includes(choice.value) ? ' selected' : ''}>${escapeHtml(resolveFormText(choice.label, locale))}</option>`).join('') ?? ''}</select>`\n }\n return `<div role=\"radiogroup\">${field.choices?.map((choice) => `<label><input ${attrs({ type: 'radio', name: formAnswerName(field.key), value: choice.value, required: field.required, checked: selected.includes(choice.value) })}> <span>${escapeHtml(resolveFormText(choice.label, locale))}</span></label>`).join('') ?? ''}</div>`\n}\n\nfunction renderField(field: FormField, options: RenderFormHtmlOptions): string {\n const { locale, answers = {}, errors = {} } = options\n if (!isFormFieldVisible(field, answers)) return ''\n const value = answers[field.key]\n const fieldErrors = errors[field.key] ?? []\n const id = `form-${field.key}`\n const label = resolveFormText(field.label, locale, options.fallbackLocale)\n const describedBy =\n [field.description ? `${id}-description` : '', fieldErrors.length ? `${id}-errors` : '']\n .filter(Boolean)\n .join(' ') || undefined\n let control: string\n if (field.kind === 'textarea') {\n control = `<textarea ${attrs({ id, name: formAnswerName(field.key), required: field.required, minlength: field.validation?.minLength, maxlength: field.validation?.maxLength, 'aria-invalid': fieldErrors.length > 0 ? 'true' : undefined, 'aria-describedby': describedBy })}>${escapeHtml(scalarAnswer(value))}</textarea>`\n } else if (field.kind === 'address') {\n const address = typeof value === 'object' && !Array.isArray(value) ? value : {}\n control = `<fieldset><legend>${escapeHtml(label)}</legend>${ADDRESS_PROPERTIES.map((property) => `<label><span>${escapeHtml(property)}</span><input ${attrs({ name: formAnswerName(field.key, property), value: address[property] ?? '', required: field.required && ['line1', 'postalCode', 'city', 'countryCode'].includes(property) })}></label>`).join('')}</fieldset>`\n } else if (field.kind === 'select' || field.kind === 'multi_select' || field.kind === 'radio') {\n control = renderChoices(field, locale, value)\n } else if (field.kind === 'checkbox' || field.kind === 'consent') {\n const text = field.kind === 'consent' ? resolveFormText(field.consentText, locale) : label\n control = `<label><input ${attrs({ id, type: 'checkbox', name: formAnswerName(field.key), value: 'true', required: field.required, checked: value === true, 'aria-invalid': fieldErrors.length > 0 ? 'true' : undefined, 'aria-describedby': describedBy })}> <span>${escapeHtml(text)}</span></label>`\n } else {\n const type = field.kind === 'phone' ? 'tel' : field.kind\n control = `<input ${attrs({ id, type, name: formAnswerName(field.key), value: scalarAnswer(value), required: field.required, minlength: field.validation?.minLength, maxlength: field.validation?.maxLength, min: field.validation?.min, max: field.validation?.max, 'aria-invalid': fieldErrors.length > 0 ? 'true' : undefined, 'aria-describedby': describedBy })}>`\n }\n const visibleLabel =\n field.kind !== 'address' && field.kind !== 'checkbox' && field.kind !== 'consent'\n ? `<label for=\"${escapeHtml(id)}\">${escapeHtml(label)}${field.required ? ' <span aria-hidden=\"true\">*</span>' : ''}</label>`\n : ''\n const description = field.description\n ? `<p id=\"${escapeHtml(id)}-description\">${escapeHtml(resolveFormText(field.description, locale))}</p>`\n : ''\n return `<div data-kotao-form-field=\"${escapeHtml(field.key)}\">${visibleLabel}${control}${description}${renderErrors(field, fieldErrors)}</div>`\n}\n\nexport function renderFormHtml(form: PublicForm, options: RenderFormHtmlOptions): string {\n const { schema } = form.version\n const success = options.submitted\n ? `<p role=\"status\" data-kotao-form-success>${escapeHtml(resolveFormText(schema.successMessage, options.locale, options.fallbackLocale))}</p>`\n : ''\n const pages = schema.pages\n .map(\n (page) =>\n `<section data-kotao-form-page=\"${escapeHtml(page.key)}\">${page.title ? `<h2>${escapeHtml(resolveFormText(page.title, options.locale, options.fallbackLocale))}</h2>` : ''}${page.description ? `<p>${escapeHtml(resolveFormText(page.description, options.locale, options.fallbackLocale))}</p>` : ''}${page.blocks.map((block) => (block.type === 'field' ? renderField(block.field, options) : block.type === 'section' ? `<header><h3>${escapeHtml(resolveFormText(block.title, options.locale, options.fallbackLocale))}</h3>${block.description ? `<p>${escapeHtml(resolveFormText(block.description, options.locale, options.fallbackLocale))}</p>` : ''}</header>` : `<div data-kotao-form-content>${escapeHtml(resolveFormText(block.content, options.locale, options.fallbackLocale))}</div>`)).join('')}</section>`,\n )\n .join('')\n const idempotencyInput = options.idempotencyKey\n ? `<input type=\"hidden\" name=\"idempotencyKey\" value=\"${escapeHtml(options.idempotencyKey)}\">`\n : ''\n const honeypot = options.honeypotName\n ? `<div hidden aria-hidden=\"true\"><label>Leave this field empty<input type=\"text\" name=\"${escapeHtml(options.honeypotName)}\" tabindex=\"-1\" autocomplete=\"off\"></label></div>`\n : ''\n return `<form ${attrs({ method: 'post', action: options.action ?? '', class: options.formClass, 'data-kotao-form': form.definition.handle })}><input type=\"hidden\" name=\"versionId\" value=\"${escapeHtml(form.version.id)}\"><input type=\"hidden\" name=\"locale\" value=\"${escapeHtml(options.locale)}\">${idempotencyInput}${honeypot}${success}${pages}<button type=\"submit\">${escapeHtml(resolveFormText(schema.submitLabel, options.locale, options.fallbackLocale) || 'Submit')}</button></form>`\n}\n","import type { FormAnswers, FormFieldErrors, FormSubmission, PublicForm } from './types'\n\nexport interface FormFetchOptions {\n fetch?: typeof fetch\n apiBaseUrl?: string\n headers?: ConstructorParameters<typeof Headers>[0]\n signal?: AbortSignal\n}\n\nexport interface SubmitFormInput extends FormFetchOptions {\n versionId: string\n locale: string\n answers: FormAnswers\n idempotencyKey?: string\n}\n\nexport class StorefrontFormRequestError extends Error {\n readonly status: number\n readonly fieldErrors: FormFieldErrors\n\n constructor(status: number, message: string, fieldErrors: FormFieldErrors = {}) {\n super(message)\n this.name = 'StorefrontFormRequestError'\n this.status = status\n this.fieldErrors = fieldErrors\n }\n}\n\nfunction endpoint(baseUrl: string | undefined, handle: string, suffix = ''): string {\n const base = (baseUrl ?? '/api/storefront').replace(/\\/$/, '')\n return `${base}/forms/${encodeURIComponent(handle)}${suffix}`\n}\n\nasync function requestError(response: Response): Promise<StorefrontFormRequestError> {\n let body: { error?: string; fieldErrors?: FormFieldErrors } = {}\n try {\n body = (await response.json()) as typeof body\n } catch {\n // A non-JSON proxy error still becomes one stable SDK error.\n }\n return new StorefrontFormRequestError(\n response.status,\n body.error ?? `Form request failed with status ${response.status}`,\n body.fieldErrors,\n )\n}\n\nexport async function loadPublishedForm(\n handle: string,\n options: FormFetchOptions = {},\n): Promise<PublicForm> {\n const fetcher = options.fetch ?? fetch\n const response = await fetcher(endpoint(options.apiBaseUrl, handle), {\n method: 'GET',\n ...(options.headers !== undefined ? { headers: options.headers } : {}),\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n })\n if (!response.ok) throw await requestError(response)\n return (await response.json()) as PublicForm\n}\n\nexport async function submitPublishedForm(\n handle: string,\n input: SubmitFormInput,\n): Promise<FormSubmission> {\n const fetcher = input.fetch ?? fetch\n const headers = new Headers(input.headers)\n headers.set('content-type', 'application/json')\n headers.set('idempotency-key', input.idempotencyKey ?? crypto.randomUUID())\n const response = await fetcher(endpoint(input.apiBaseUrl, handle, '/submissions'), {\n method: 'POST',\n headers,\n ...(input.signal !== undefined ? { signal: input.signal } : {}),\n body: JSON.stringify({\n versionId: input.versionId,\n locale: input.locale,\n answers: input.answers,\n }),\n })\n if (!response.ok) throw await requestError(response)\n return (await response.json()) as FormSubmission\n}\n","import { formFields } from './shared'\nimport type { FormAnswers, FormField, PublicForm } from './types'\n\nexport interface ShopifyContactInput {\n readonly name?: string | null\n readonly email: string\n readonly body: string\n readonly phone?: string | null\n}\n\nexport type ShopifyContactCompatibility =\n | { readonly compatible: true; readonly answers: FormAnswers }\n | {\n readonly compatible: false\n readonly reason:\n | 'not-contact-purpose'\n | 'unsupported-required-field'\n | 'incompatible-standard-field'\n }\n\nconst STANDARD_FIELD_KINDS: Readonly<Record<string, readonly FormField['kind'][]>> = {\n name: ['text'],\n email: ['email', 'text'],\n body: ['textarea', 'text'],\n phone: ['phone', 'text'],\n}\n\nfunction inputValue(input: ShopifyContactInput, key: string): string | null | undefined {\n switch (key) {\n case 'name':\n return input.name\n case 'email':\n return input.email\n case 'body':\n return input.body\n case 'phone':\n return input.phone\n default:\n return undefined\n }\n}\n\nexport function adaptShopifyContactForm(\n form: PublicForm,\n input: ShopifyContactInput,\n): ShopifyContactCompatibility {\n if (form.definition.purpose !== 'contact') {\n return { compatible: false, reason: 'not-contact-purpose' }\n }\n\n const fields = formFields(form.version.schema)\n for (const field of fields) {\n const supportedKinds = STANDARD_FIELD_KINDS[field.key]\n if (supportedKinds === undefined) {\n if (field.required) return { compatible: false, reason: 'unsupported-required-field' }\n continue\n }\n if (!supportedKinds.includes(field.kind)) {\n return { compatible: false, reason: 'incompatible-standard-field' }\n }\n }\n\n const answers: FormAnswers = {}\n for (const field of fields) {\n if (STANDARD_FIELD_KINDS[field.key] === undefined) continue\n const value = inputValue(input, field.key)\n if (value !== undefined && value !== null) answers[field.key] = value\n }\n return { compatible: true, answers }\n}\n"]}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { resolveFormText, isFormFieldVisible, formAnswerName, ADDRESS_PROPERTIES, formFields } from './chunk-IIOHENCG.js';
|
|
2
|
+
import { useState, useId } from 'react';
|
|
3
|
+
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
var ADDRESS_LABELS = {
|
|
6
|
+
line1: "Address",
|
|
7
|
+
line2: "Address line 2",
|
|
8
|
+
city: "City",
|
|
9
|
+
postalCode: "Postal code",
|
|
10
|
+
countryCode: "Country code",
|
|
11
|
+
provinceCode: "Province or state code"
|
|
12
|
+
};
|
|
13
|
+
function FieldErrors({ id, errors }) {
|
|
14
|
+
if (errors.length === 0) return null;
|
|
15
|
+
return /* @__PURE__ */ jsx("ul", { id, "data-kotao-form-errors": true, children: errors.map((error, index) => /* @__PURE__ */ jsx("li", { children: error }, `${error}-${index}`)) });
|
|
16
|
+
}
|
|
17
|
+
function StorefrontFormField({
|
|
18
|
+
field,
|
|
19
|
+
locale,
|
|
20
|
+
fallbackLocale,
|
|
21
|
+
value,
|
|
22
|
+
errors,
|
|
23
|
+
onChange,
|
|
24
|
+
idPrefix
|
|
25
|
+
}) {
|
|
26
|
+
const id = `${idPrefix}-form-${field.key}`;
|
|
27
|
+
const label = resolveFormText(field.label, locale, fallbackLocale);
|
|
28
|
+
const description = resolveFormText(field.description, locale, fallbackLocale);
|
|
29
|
+
const errorId = `${id}-errors`;
|
|
30
|
+
const descriptionId = `${id}-description`;
|
|
31
|
+
const describedBy = [description ? descriptionId : "", errors.length ? errorId : ""].filter(Boolean).join(" ");
|
|
32
|
+
const common = {
|
|
33
|
+
id,
|
|
34
|
+
name: formAnswerName(field.key),
|
|
35
|
+
required: field.required,
|
|
36
|
+
"aria-invalid": errors.length > 0 || void 0,
|
|
37
|
+
"aria-describedby": describedBy || void 0
|
|
38
|
+
};
|
|
39
|
+
let control;
|
|
40
|
+
if (field.kind === "textarea") {
|
|
41
|
+
control = /* @__PURE__ */ jsx(
|
|
42
|
+
"textarea",
|
|
43
|
+
{
|
|
44
|
+
...common,
|
|
45
|
+
value: typeof value === "string" ? value : "",
|
|
46
|
+
minLength: field.validation?.minLength,
|
|
47
|
+
maxLength: field.validation?.maxLength,
|
|
48
|
+
onChange: (event) => onChange(event.currentTarget.value)
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
} else if (field.kind === "address") {
|
|
52
|
+
const address = typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
53
|
+
control = /* @__PURE__ */ jsxs("fieldset", { "aria-describedby": describedBy || void 0, children: [
|
|
54
|
+
/* @__PURE__ */ jsxs("legend", { children: [
|
|
55
|
+
label,
|
|
56
|
+
field.required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: " *" })
|
|
57
|
+
] }),
|
|
58
|
+
ADDRESS_PROPERTIES.map((property) => /* @__PURE__ */ jsxs("label", { children: [
|
|
59
|
+
/* @__PURE__ */ jsx("span", { children: ADDRESS_LABELS[property] }),
|
|
60
|
+
/* @__PURE__ */ jsx(
|
|
61
|
+
"input",
|
|
62
|
+
{
|
|
63
|
+
name: formAnswerName(field.key, property),
|
|
64
|
+
value: address[property] ?? "",
|
|
65
|
+
required: field.required && ["line1", "postalCode", "city", "countryCode"].includes(property),
|
|
66
|
+
onChange: (event) => onChange({ ...address, [property]: event.currentTarget.value })
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
] }, property))
|
|
70
|
+
] });
|
|
71
|
+
} else if (field.kind === "select" || field.kind === "multi_select") {
|
|
72
|
+
const selected = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
|
|
73
|
+
control = /* @__PURE__ */ jsxs(
|
|
74
|
+
"select",
|
|
75
|
+
{
|
|
76
|
+
...common,
|
|
77
|
+
multiple: field.kind === "multi_select",
|
|
78
|
+
value: field.kind === "multi_select" ? selected : selected[0] ?? "",
|
|
79
|
+
onChange: (event) => onChange(
|
|
80
|
+
field.kind === "multi_select" ? Array.from(event.currentTarget.selectedOptions, (option) => option.value) : event.currentTarget.value
|
|
81
|
+
),
|
|
82
|
+
children: [
|
|
83
|
+
field.kind === "select" && /* @__PURE__ */ jsx("option", { value: "" }),
|
|
84
|
+
field.choices?.map((choice) => /* @__PURE__ */ jsx("option", { value: choice.value, children: resolveFormText(choice.label, locale, fallbackLocale) }, choice.value))
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
} else if (field.kind === "radio") {
|
|
89
|
+
control = /* @__PURE__ */ jsx("div", { role: "radiogroup", "aria-describedby": describedBy || void 0, children: field.choices?.map((choice) => /* @__PURE__ */ jsxs("label", { children: [
|
|
90
|
+
/* @__PURE__ */ jsx(
|
|
91
|
+
"input",
|
|
92
|
+
{
|
|
93
|
+
type: "radio",
|
|
94
|
+
name: common.name,
|
|
95
|
+
value: choice.value,
|
|
96
|
+
required: field.required,
|
|
97
|
+
checked: value === choice.value,
|
|
98
|
+
onChange: (event) => {
|
|
99
|
+
if (event.currentTarget.checked) onChange(choice.value);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
),
|
|
103
|
+
/* @__PURE__ */ jsx("span", { children: resolveFormText(choice.label, locale, fallbackLocale) })
|
|
104
|
+
] }, choice.value)) });
|
|
105
|
+
} else if (field.kind === "checkbox" || field.kind === "consent") {
|
|
106
|
+
control = /* @__PURE__ */ jsxs("label", { children: [
|
|
107
|
+
/* @__PURE__ */ jsx(
|
|
108
|
+
"input",
|
|
109
|
+
{
|
|
110
|
+
...common,
|
|
111
|
+
type: "checkbox",
|
|
112
|
+
value: "true",
|
|
113
|
+
checked: value === true,
|
|
114
|
+
onChange: (event) => onChange(event.currentTarget.checked)
|
|
115
|
+
}
|
|
116
|
+
),
|
|
117
|
+
/* @__PURE__ */ jsx("span", { children: field.kind === "consent" ? resolveFormText(field.consentText, locale, fallbackLocale) : label })
|
|
118
|
+
] });
|
|
119
|
+
} else {
|
|
120
|
+
control = /* @__PURE__ */ jsx(
|
|
121
|
+
"input",
|
|
122
|
+
{
|
|
123
|
+
...common,
|
|
124
|
+
type: field.kind === "phone" ? "tel" : field.kind,
|
|
125
|
+
value: typeof value === "string" || typeof value === "number" ? value : "",
|
|
126
|
+
minLength: field.validation?.minLength,
|
|
127
|
+
maxLength: field.validation?.maxLength,
|
|
128
|
+
min: field.validation?.min,
|
|
129
|
+
max: field.validation?.max,
|
|
130
|
+
onChange: (event) => onChange(
|
|
131
|
+
field.kind === "number" && event.currentTarget.value !== "" ? event.currentTarget.valueAsNumber : event.currentTarget.value
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
const hasSeparateLabel = !["address", "checkbox", "consent"].includes(field.kind);
|
|
137
|
+
return /* @__PURE__ */ jsxs("div", { "data-kotao-form-field": field.key, children: [
|
|
138
|
+
hasSeparateLabel && /* @__PURE__ */ jsxs("label", { htmlFor: id, children: [
|
|
139
|
+
label,
|
|
140
|
+
field.required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: " *" })
|
|
141
|
+
] }),
|
|
142
|
+
control,
|
|
143
|
+
description && /* @__PURE__ */ jsx("p", { id: descriptionId, children: description }),
|
|
144
|
+
/* @__PURE__ */ jsx(FieldErrors, { id: errorId, errors })
|
|
145
|
+
] });
|
|
146
|
+
}
|
|
147
|
+
function StorefrontFormFields({
|
|
148
|
+
form,
|
|
149
|
+
locale,
|
|
150
|
+
fallbackLocale,
|
|
151
|
+
answers: initialAnswers = {},
|
|
152
|
+
errors = {},
|
|
153
|
+
onAnswersChange,
|
|
154
|
+
idPrefix
|
|
155
|
+
}) {
|
|
156
|
+
const [answers, setAnswers] = useState(initialAnswers);
|
|
157
|
+
const generatedId = useId();
|
|
158
|
+
const instanceId = idPrefix ?? `kotao-${generatedId.replaceAll(":", "")}`;
|
|
159
|
+
const schema = form.version.schema;
|
|
160
|
+
function pruneHiddenAnswers(nextAnswers) {
|
|
161
|
+
let pruned = nextAnswers;
|
|
162
|
+
let removed = true;
|
|
163
|
+
while (removed) {
|
|
164
|
+
removed = false;
|
|
165
|
+
for (const field of formFields(schema)) {
|
|
166
|
+
if (Object.hasOwn(pruned, field.key) && !isFormFieldVisible(field, pruned)) {
|
|
167
|
+
if (pruned === nextAnswers) pruned = { ...nextAnswers };
|
|
168
|
+
delete pruned[field.key];
|
|
169
|
+
removed = true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return pruned;
|
|
174
|
+
}
|
|
175
|
+
function updateAnswer(key, answer) {
|
|
176
|
+
setAnswers((current) => {
|
|
177
|
+
const next = pruneHiddenAnswers({ ...current, [key]: answer });
|
|
178
|
+
onAnswersChange?.(next);
|
|
179
|
+
return next;
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
return /* @__PURE__ */ jsx(Fragment, { children: schema.pages.map((page) => /* @__PURE__ */ jsxs("section", { "data-kotao-form-page": page.key, children: [
|
|
183
|
+
page.title && /* @__PURE__ */ jsx("h2", { children: resolveFormText(page.title, locale, fallbackLocale) }),
|
|
184
|
+
page.description && /* @__PURE__ */ jsx("p", { children: resolveFormText(page.description, locale, fallbackLocale) }),
|
|
185
|
+
page.blocks.map((block) => {
|
|
186
|
+
if (block.type === "section") {
|
|
187
|
+
return /* @__PURE__ */ jsxs("header", { children: [
|
|
188
|
+
/* @__PURE__ */ jsx("h3", { children: resolveFormText(block.title, locale, fallbackLocale) }),
|
|
189
|
+
block.description && /* @__PURE__ */ jsx("p", { children: resolveFormText(block.description, locale, fallbackLocale) })
|
|
190
|
+
] }, block.key);
|
|
191
|
+
}
|
|
192
|
+
if (block.type === "content") {
|
|
193
|
+
return /* @__PURE__ */ jsx("div", { "data-kotao-form-content": true, children: resolveFormText(block.content, locale, fallbackLocale) }, block.key);
|
|
194
|
+
}
|
|
195
|
+
return isFormFieldVisible(block.field, answers) ? /* @__PURE__ */ jsx(
|
|
196
|
+
StorefrontFormField,
|
|
197
|
+
{
|
|
198
|
+
field: block.field,
|
|
199
|
+
locale,
|
|
200
|
+
fallbackLocale,
|
|
201
|
+
value: answers[block.field.key],
|
|
202
|
+
errors: errors[block.field.key] ?? [],
|
|
203
|
+
onChange: (answer) => updateAnswer(block.field.key, answer),
|
|
204
|
+
idPrefix: instanceId
|
|
205
|
+
},
|
|
206
|
+
block.field.key
|
|
207
|
+
) : null;
|
|
208
|
+
})
|
|
209
|
+
] }, page.key)) });
|
|
210
|
+
}
|
|
211
|
+
function StorefrontForm({
|
|
212
|
+
form,
|
|
213
|
+
locale,
|
|
214
|
+
fallbackLocale,
|
|
215
|
+
answers,
|
|
216
|
+
errors,
|
|
217
|
+
submitted = false,
|
|
218
|
+
submitLabel,
|
|
219
|
+
onAnswersChange,
|
|
220
|
+
action = "",
|
|
221
|
+
method = "post",
|
|
222
|
+
...props
|
|
223
|
+
}) {
|
|
224
|
+
const schema = form.version.schema;
|
|
225
|
+
return /* @__PURE__ */ jsxs("form", { ...props, action, method, "data-kotao-form": form.definition.handle, children: [
|
|
226
|
+
/* @__PURE__ */ jsx("input", { type: "hidden", name: "versionId", value: form.version.id }),
|
|
227
|
+
/* @__PURE__ */ jsx("input", { type: "hidden", name: "locale", value: locale }),
|
|
228
|
+
submitted && /* @__PURE__ */ jsx("p", { role: "status", "data-kotao-form-success": true, children: resolveFormText(schema.successMessage, locale, fallbackLocale) }),
|
|
229
|
+
/* @__PURE__ */ jsx(
|
|
230
|
+
StorefrontFormFields,
|
|
231
|
+
{
|
|
232
|
+
form,
|
|
233
|
+
locale,
|
|
234
|
+
...fallbackLocale === void 0 ? {} : { fallbackLocale },
|
|
235
|
+
...answers === void 0 ? {} : { answers },
|
|
236
|
+
...errors === void 0 ? {} : { errors },
|
|
237
|
+
...onAnswersChange === void 0 ? {} : { onAnswersChange }
|
|
238
|
+
}
|
|
239
|
+
),
|
|
240
|
+
/* @__PURE__ */ jsx("button", { type: "submit", children: submitLabel ?? (resolveFormText(schema.submitLabel, locale, fallbackLocale) || "Submit") })
|
|
241
|
+
] });
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export { StorefrontForm, StorefrontFormFields };
|
|
245
|
+
//# sourceMappingURL=chunk-VV653S52.js.map
|
|
246
|
+
//# sourceMappingURL=chunk-VV653S52.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react/form.tsx"],"names":[],"mappings":"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","file":"chunk-VV653S52.js","sourcesContent":["import React, { useId, useState, type ComponentPropsWithoutRef, type ReactNode } from 'react'\nimport {\n ADDRESS_PROPERTIES,\n formAnswerName,\n formFields,\n isFormFieldVisible,\n resolveFormText,\n type FormAnswer,\n type FormAnswers,\n type FormField,\n type FormFieldErrors,\n type PublicForm,\n} from '../forms'\n\nexport interface StorefrontFormProps extends Omit<\n ComponentPropsWithoutRef<'form'>,\n 'children' | 'defaultValue'\n> {\n form: PublicForm\n locale: string\n fallbackLocale?: string\n answers?: FormAnswers\n errors?: FormFieldErrors\n submitted?: boolean\n submitLabel?: ReactNode\n onAnswersChange?: (answers: FormAnswers) => void\n}\n\nexport interface StorefrontFormFieldsProps {\n readonly form: PublicForm\n readonly locale: string\n readonly fallbackLocale?: string\n readonly answers?: FormAnswers\n readonly errors?: FormFieldErrors\n readonly onAnswersChange?: (answers: FormAnswers) => void\n readonly idPrefix?: string\n}\n\ninterface FieldProps {\n field: FormField\n locale: string\n fallbackLocale?: string | undefined\n value?: FormAnswer | undefined\n errors: string[]\n onChange: (value: FormAnswer) => void\n idPrefix: string\n}\n\nconst ADDRESS_LABELS: Record<(typeof ADDRESS_PROPERTIES)[number], string> = {\n line1: 'Address',\n line2: 'Address line 2',\n city: 'City',\n postalCode: 'Postal code',\n countryCode: 'Country code',\n provinceCode: 'Province or state code',\n}\n\nfunction FieldErrors({ id, errors }: { id: string; errors: string[] }) {\n if (errors.length === 0) return null\n return (\n <ul id={id} data-kotao-form-errors>\n {errors.map((error, index) => (\n <li key={`${error}-${index}`}>{error}</li>\n ))}\n </ul>\n )\n}\n\nfunction StorefrontFormField({\n field,\n locale,\n fallbackLocale,\n value,\n errors,\n onChange,\n idPrefix,\n}: FieldProps) {\n const id = `${idPrefix}-form-${field.key}`\n const label = resolveFormText(field.label, locale, fallbackLocale)\n const description = resolveFormText(field.description, locale, fallbackLocale)\n const errorId = `${id}-errors`\n const descriptionId = `${id}-description`\n const describedBy = [description ? descriptionId : '', errors.length ? errorId : '']\n .filter(Boolean)\n .join(' ')\n const common = {\n id,\n name: formAnswerName(field.key),\n required: field.required,\n 'aria-invalid': errors.length > 0 || undefined,\n 'aria-describedby': describedBy || undefined,\n }\n let control: ReactNode\n\n if (field.kind === 'textarea') {\n control = (\n <textarea\n {...common}\n value={typeof value === 'string' ? value : ''}\n minLength={field.validation?.minLength}\n maxLength={field.validation?.maxLength}\n onChange={(event) => onChange(event.currentTarget.value)}\n />\n )\n } else if (field.kind === 'address') {\n const address = typeof value === 'object' && !Array.isArray(value) ? value : {}\n control = (\n <fieldset aria-describedby={describedBy || undefined}>\n <legend>\n {label}\n {field.required && <span aria-hidden=\"true\"> *</span>}\n </legend>\n {ADDRESS_PROPERTIES.map((property) => (\n <label key={property}>\n <span>{ADDRESS_LABELS[property]}</span>\n <input\n name={formAnswerName(field.key, property)}\n value={address[property] ?? ''}\n required={\n field.required && ['line1', 'postalCode', 'city', 'countryCode'].includes(property)\n }\n onChange={(event) => onChange({ ...address, [property]: event.currentTarget.value })}\n />\n </label>\n ))}\n </fieldset>\n )\n } else if (field.kind === 'select' || field.kind === 'multi_select') {\n const selected = Array.isArray(value) ? value : typeof value === 'string' ? [value] : []\n control = (\n <select\n {...common}\n multiple={field.kind === 'multi_select'}\n value={field.kind === 'multi_select' ? selected : (selected[0] ?? '')}\n onChange={(event) =>\n onChange(\n field.kind === 'multi_select'\n ? Array.from(event.currentTarget.selectedOptions, (option) => option.value)\n : event.currentTarget.value,\n )\n }\n >\n {field.kind === 'select' && <option value=\"\" />}\n {field.choices?.map((choice) => (\n <option key={choice.value} value={choice.value}>\n {resolveFormText(choice.label, locale, fallbackLocale)}\n </option>\n ))}\n </select>\n )\n } else if (field.kind === 'radio') {\n control = (\n <div role=\"radiogroup\" aria-describedby={describedBy || undefined}>\n {field.choices?.map((choice) => (\n <label key={choice.value}>\n <input\n type=\"radio\"\n name={common.name}\n value={choice.value}\n required={field.required}\n checked={value === choice.value}\n onChange={(event) => {\n if (event.currentTarget.checked) onChange(choice.value)\n }}\n />\n <span>{resolveFormText(choice.label, locale, fallbackLocale)}</span>\n </label>\n ))}\n </div>\n )\n } else if (field.kind === 'checkbox' || field.kind === 'consent') {\n control = (\n <label>\n <input\n {...common}\n type=\"checkbox\"\n value=\"true\"\n checked={value === true}\n onChange={(event) => onChange(event.currentTarget.checked)}\n />\n <span>\n {field.kind === 'consent'\n ? resolveFormText(field.consentText, locale, fallbackLocale)\n : label}\n </span>\n </label>\n )\n } else {\n control = (\n <input\n {...common}\n type={field.kind === 'phone' ? 'tel' : field.kind}\n value={typeof value === 'string' || typeof value === 'number' ? value : ''}\n minLength={field.validation?.minLength}\n maxLength={field.validation?.maxLength}\n min={field.validation?.min}\n max={field.validation?.max}\n onChange={(event) =>\n onChange(\n field.kind === 'number' && event.currentTarget.value !== ''\n ? event.currentTarget.valueAsNumber\n : event.currentTarget.value,\n )\n }\n />\n )\n }\n\n const hasSeparateLabel = !['address', 'checkbox', 'consent'].includes(field.kind)\n return (\n <div data-kotao-form-field={field.key}>\n {hasSeparateLabel && (\n <label htmlFor={id}>\n {label}\n {field.required && <span aria-hidden=\"true\"> *</span>}\n </label>\n )}\n {control}\n {description && <p id={descriptionId}>{description}</p>}\n <FieldErrors id={errorId} errors={errors} />\n </div>\n )\n}\n\nexport function StorefrontFormFields({\n form,\n locale,\n fallbackLocale,\n answers: initialAnswers = {},\n errors = {},\n onAnswersChange,\n idPrefix,\n}: StorefrontFormFieldsProps) {\n const [answers, setAnswers] = useState<FormAnswers>(initialAnswers)\n const generatedId = useId()\n const instanceId = idPrefix ?? `kotao-${generatedId.replaceAll(':', '')}`\n const schema = form.version.schema\n\n function pruneHiddenAnswers(nextAnswers: FormAnswers): FormAnswers {\n let pruned = nextAnswers\n let removed = true\n while (removed) {\n removed = false\n for (const field of formFields(schema)) {\n if (Object.hasOwn(pruned, field.key) && !isFormFieldVisible(field, pruned)) {\n if (pruned === nextAnswers) pruned = { ...nextAnswers }\n delete pruned[field.key]\n removed = true\n }\n }\n }\n return pruned\n }\n\n function updateAnswer(key: string, answer: FormAnswer) {\n setAnswers((current) => {\n const next = pruneHiddenAnswers({ ...current, [key]: answer })\n onAnswersChange?.(next)\n return next\n })\n }\n\n return (\n <>\n {schema.pages.map((page) => (\n <section key={page.key} data-kotao-form-page={page.key}>\n {page.title && <h2>{resolveFormText(page.title, locale, fallbackLocale)}</h2>}\n {page.description && <p>{resolveFormText(page.description, locale, fallbackLocale)}</p>}\n {page.blocks.map((block) => {\n if (block.type === 'section') {\n return (\n <header key={block.key}>\n <h3>{resolveFormText(block.title, locale, fallbackLocale)}</h3>\n {block.description && (\n <p>{resolveFormText(block.description, locale, fallbackLocale)}</p>\n )}\n </header>\n )\n }\n if (block.type === 'content') {\n return (\n <div key={block.key} data-kotao-form-content>\n {resolveFormText(block.content, locale, fallbackLocale)}\n </div>\n )\n }\n return isFormFieldVisible(block.field, answers) ? (\n <StorefrontFormField\n key={block.field.key}\n field={block.field}\n locale={locale}\n fallbackLocale={fallbackLocale}\n value={answers[block.field.key]}\n errors={errors[block.field.key] ?? []}\n onChange={(answer) => updateAnswer(block.field.key, answer)}\n idPrefix={instanceId}\n />\n ) : null\n })}\n </section>\n ))}\n </>\n )\n}\n\nexport function StorefrontForm({\n form,\n locale,\n fallbackLocale,\n answers,\n errors,\n submitted = false,\n submitLabel,\n onAnswersChange,\n action = '',\n method = 'post',\n ...props\n}: StorefrontFormProps) {\n const schema = form.version.schema\n\n return (\n <form {...props} action={action} method={method} data-kotao-form={form.definition.handle}>\n <input type=\"hidden\" name=\"versionId\" value={form.version.id} />\n <input type=\"hidden\" name=\"locale\" value={locale} />\n {submitted && (\n <p role=\"status\" data-kotao-form-success>\n {resolveFormText(schema.successMessage, locale, fallbackLocale)}\n </p>\n )}\n <StorefrontFormFields\n form={form}\n locale={locale}\n {...(fallbackLocale === undefined ? {} : { fallbackLocale })}\n {...(answers === undefined ? {} : { answers })}\n {...(errors === undefined ? {} : { errors })}\n {...(onAnswersChange === undefined ? {} : { onAnswersChange })}\n />\n <button type=\"submit\">\n {submitLabel ?? (resolveFormText(schema.submitLabel, locale, fallbackLocale) || 'Submit')}\n </button>\n </form>\n )\n}\n"]}
|