import { w as writable, d as derived, a as readonly } from './index2-BO_DJNQw.js'; import { p as page, n as navigating, i as invalidateAll, a as applyAction } from './stores-q_3MsRzq.js'; import { U as UNDEFINED, N as NAN, P as POSITIVE_INFINITY, f as NEGATIVE_INFINITY, h as NEGATIVE_ZERO, H as HOLE, B as BROWSER, d as stringify } from './stringify-D5iWhcfN.js'; import { g as get_store_value, o as onDestroy } from './lifecycle-Cykl3Eqn.js'; import { t as tick } from './scheduler-e11T_xkt.js'; /** * Revive a value serialized with `devalue.stringify` * @param {string} serialized * @param {Record any>} [revivers] */ function parse(serialized, revivers) { return unflatten(JSON.parse(serialized), revivers); } /** * Revive a value flattened with `devalue.stringify` * @param {number | any[]} parsed * @param {Record any>} [revivers] */ function unflatten(parsed, revivers) { if (typeof parsed === 'number') return hydrate(parsed, true); if (!Array.isArray(parsed) || parsed.length === 0) { throw new Error('Invalid input'); } const values = /** @type {any[]} */ (parsed); const hydrated = Array(values.length); /** * @param {number} index * @returns {any} */ function hydrate(index, standalone = false) { if (index === UNDEFINED) return undefined; if (index === NAN) return NaN; if (index === POSITIVE_INFINITY) return Infinity; if (index === NEGATIVE_INFINITY) return -Infinity; if (index === NEGATIVE_ZERO) return -0; if (standalone) throw new Error(`Invalid input`); if (index in hydrated) return hydrated[index]; const value = values[index]; if (!value || typeof value !== 'object') { hydrated[index] = value; } else if (Array.isArray(value)) { if (typeof value[0] === 'string') { const type = value[0]; const reviver = revivers?.[type]; if (reviver) { return (hydrated[index] = reviver(hydrate(value[1]))); } switch (type) { case 'Date': hydrated[index] = new Date(value[1]); break; case 'Set': const set = new Set(); hydrated[index] = set; for (let i = 1; i < value.length; i += 1) { set.add(hydrate(value[i])); } break; case 'Map': const map = new Map(); hydrated[index] = map; for (let i = 1; i < value.length; i += 2) { map.set(hydrate(value[i]), hydrate(value[i + 1])); } break; case 'RegExp': hydrated[index] = new RegExp(value[1], value[2]); break; case 'Object': hydrated[index] = Object(value[1]); break; case 'BigInt': hydrated[index] = BigInt(value[1]); break; case 'null': const obj = Object.create(null); hydrated[index] = obj; for (let i = 1; i < value.length; i += 2) { obj[value[i]] = hydrate(value[i + 1]); } break; default: throw new Error(`Unknown type ${type}`); } } else { const array = new Array(value.length); hydrated[index] = array; for (let i = 0; i < value.length; i += 1) { const n = value[i]; if (n === HOLE) continue; array[i] = hydrate(n); } } } else { /** @type {Record} */ const object = {}; hydrated[index] = object; for (const key in value) { const n = value[key]; object[key] = hydrate(n); } } return hydrated[index]; } return hydrate(0); } function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } var collectionClone = clone$2; /* Deep clones all properties except functions var arr = [1, 2, 3]; var subObj = {aa: 1}; var obj = {a: 3, b: 5, c: arr, d: subObj}; var objClone = clone(obj); arr.push(4); subObj.bb = 2; obj; // {a: 3, b: 5, c: [1, 2, 3, 4], d: {aa: 1}} objClone; // {a: 3, b: 5, c: [1, 2, 3], d: {aa: 1, bb: 2}} */ function clone$2(obj) { let result = obj; var type = {}.toString.call(obj).slice(8, -1); if (type == 'Set') { return new Set([...obj].map(value => clone$2(value))); } if (type == 'Map') { return new Map([...obj].map(kv => [clone$2(kv[0]), clone$2(kv[1])])); } if (type == 'Date') { return new Date(obj.getTime()); } if (type == 'RegExp') { return RegExp(obj.source, getRegExpFlags(obj)); } if (type == 'Array' || type == 'Object') { result = Array.isArray(obj) ? [] : {}; for (var key in obj) { // include prototype properties result[key] = clone$2(obj[key]); } } // primitives and non-supported objects (e.g. functions) land here return result; } function getRegExpFlags(regExp) { if (typeof regExp.source.flags == 'string') { return regExp.source.flags; } else { var flags = []; regExp.global && flags.push('g'); regExp.ignoreCase && flags.push('i'); regExp.multiline && flags.push('m'); regExp.sticky && flags.push('y'); regExp.unicode && flags.push('u'); return flags.join(''); } } // istanbul ignore next const isObject = (obj) => { if (typeof obj === "object" && obj !== null) { if (typeof Object.getPrototypeOf === "function") { const prototype = Object.getPrototypeOf(obj); return prototype === Object.prototype || prototype === null; } return Object.prototype.toString.call(obj) === "[object Object]"; } return false; }; const merge = (...objects) => objects.reduce((result, current) => { if (Array.isArray(current)) { throw new TypeError("Arguments provided to ts-deepmerge must be objects, not arrays."); } Object.keys(current).forEach((key) => { if (["__proto__", "constructor", "prototype"].includes(key)) { return; } if (Array.isArray(result[key]) && Array.isArray(current[key])) { result[key] = merge.options.mergeArrays ? merge.options.uniqueArrayItems ? Array.from(new Set(result[key].concat(current[key]))) : [...result[key], ...current[key]] : current[key]; } else if (isObject(result[key]) && isObject(current[key])) { result[key] = merge(result[key], current[key]); } else { result[key] = current[key] === undefined ? merge.options.allowUndefinedOverrides ? current[key] : result[key] : current[key]; } }); return result; }, {}); const defaultOptions = { allowUndefinedOverrides: true, mergeArrays: true, uniqueArrayItems: true, }; merge.options = defaultOptions; merge.withOptions = (options, ...objects) => { merge.options = Object.assign(Object.assign({}, defaultOptions), options); const result = merge(...objects); merge.options = defaultOptions; return result; }; const browser = BROWSER; function deserialize(result) { const parsed = JSON.parse(result); if (parsed.data) { parsed.data = parse(parsed.data); } return parsed; } function clone$1(element) { return ( /** @type {T} */ HTMLElement.prototype.cloneNode.call(element) ); } function enhance(form_element, submit = () => { }) { const fallback_callback = async ({ action, result, reset = true, invalidateAll: shouldInvalidateAll = true }) => { if (result.type === "success") { if (reset) { HTMLFormElement.prototype.reset.call(form_element); } if (shouldInvalidateAll) { await invalidateAll(); } } if (location.origin + location.pathname === action.origin + action.pathname || result.type === "redirect" || result.type === "error") { applyAction(); } }; async function handle_submit(event) { const method = event.submitter?.hasAttribute("formmethod") ? ( /** @type {HTMLButtonElement | HTMLInputElement} */ event.submitter.formMethod ) : clone$1(form_element).method; if (method !== "post") return; event.preventDefault(); const action = new URL( // We can't do submitter.formAction directly because that property is always set event.submitter?.hasAttribute("formaction") ? ( /** @type {HTMLButtonElement | HTMLInputElement} */ event.submitter.formAction ) : clone$1(form_element).action ); const form_data = new FormData(form_element); const submitter_name = event.submitter?.getAttribute("name"); if (submitter_name) { form_data.append(submitter_name, event.submitter?.getAttribute("value") ?? ""); } const controller = new AbortController(); let cancelled = false; const cancel = () => cancelled = true; const callback = await submit({ action, cancel, controller, formData: form_data, formElement: form_element, submitter: event.submitter }) ?? fallback_callback; if (cancelled) return; let result; try { const response = await fetch(action, { method: "POST", headers: { accept: "application/json", "x-sveltekit-action": "true" }, cache: "no-store", body: form_data, signal: controller.signal }); result = deserialize(await response.text()); if (result.type === "error") result.status = response.status; } catch (error) { if ( /** @type {any} */ error?.name === "AbortError" ) return; result = { type: "error", error }; } callback({ action, formData: form_data, formElement: form_element, update: (opts) => fallback_callback({ action, result, reset: opts?.reset, invalidateAll: opts?.invalidateAll }), // @ts-expect-error generic constraints stuff we don't care about result }); } HTMLFormElement.prototype.addEventListener.call(form_element, "submit", handle_submit); return { destroy() { HTMLFormElement.prototype.removeEventListener.call(form_element, "submit", handle_submit); } }; } function setPath(parent, key, value) { parent[key] = value; return "skip"; } function isInvalidPath(originalPath, pathData) { return pathData.value !== void 0 && typeof pathData.value !== "object" && pathData.path.length < originalPath.length; } function pathExists(obj, path, options = {}) { if (!options.modifier) { options.modifier = (pathData) => isInvalidPath(path, pathData) ? void 0 : pathData.value; } const exists = traversePath(obj, path, options.modifier); if (!exists) return void 0; if (options.value === void 0) return exists; return options.value(exists.value) ? exists : void 0; } function traversePath(obj, realPath, modifier) { if (!realPath.length) return void 0; const path = [realPath[0]]; let parent = obj; while (parent && path.length < realPath.length) { const key2 = path[path.length - 1]; const value = modifier ? modifier({ parent, key: String(key2), value: parent[key2], path: path.map((p) => String(p)), isLeaf: false, set: (v) => setPath(parent, key2, v) }) : parent[key2]; if (value === void 0) return void 0; else parent = value; path.push(realPath[path.length]); } if (!parent) return void 0; const key = realPath[realPath.length - 1]; return { parent, key: String(key), value: parent[key], path: realPath.map((p) => String(p)), isLeaf: true, set: (v) => setPath(parent, key, v) }; } function traversePaths(parent, modifier, path = []) { for (const key in parent) { const value = parent[key]; const isLeaf = value === null || typeof value !== "object"; const pathData = { parent, key, value, path: path.concat([key]), // path.map(String).concat([key]) isLeaf, set: (v) => setPath(parent, key, v) }; const status = modifier(pathData); if (status === "abort") return status; else if (status === "skip") continue; else if (!isLeaf) { const status2 = traversePaths(value, modifier, pathData.path); if (status2 === "abort") return status2; } } } function eqSet(xs, ys) { return xs === ys || xs.size === ys.size && [...xs].every((x) => ys.has(x)); } function comparePaths(newObj, oldObj) { const diffPaths = /* @__PURE__ */ new Map(); function builtInDiff(one, other) { if (one instanceof Date && other instanceof Date && one.getTime() !== other.getTime()) return true; if (one instanceof Set && other instanceof Set && !eqSet(one, other)) return true; if (one instanceof File && other instanceof File && one !== other) return true; return false; } function isBuiltin(data) { return data instanceof Date || data instanceof Set || data instanceof File; } function checkPath(data, compareTo) { const otherData = compareTo ? traversePath(compareTo, data.path) : void 0; function addDiff() { diffPaths.set(data.path.join(" "), data.path); return "skip"; } if (isBuiltin(data.value)) { if (!isBuiltin(otherData?.value) || builtInDiff(data.value, otherData.value)) { return addDiff(); } } if (data.isLeaf) { if (!otherData || data.value !== otherData.value) { addDiff(); } } } traversePaths(newObj, (data) => checkPath(data, oldObj)); traversePaths(oldObj, (data) => checkPath(data, newObj)); return Array.from(diffPaths.values()); } function setPaths(obj, paths, value) { const isFunction = typeof value === "function"; for (const path of paths) { const leaf = traversePath(obj, path, ({ parent, key, value: value2 }) => { if (value2 === void 0 || typeof value2 !== "object") { parent[key] = {}; } return parent[key]; }); if (leaf) leaf.parent[leaf.key] = isFunction ? value(path, leaf) : value; } } function splitPath(path) { return path.toString().split(/[[\].]+/).filter((p) => p); } function mergePath(path) { return path.reduce((acc, next) => { const key = String(next); if (typeof next === "number" || /^\d+$/.test(key)) acc += `[${key}]`; else if (!acc) acc += key; else acc += `.${key}`; return acc; }, ""); } function clone(data) { return data && typeof data === "object" ? collectionClone(data) : data; } function assertSchema(schema, path) { if (typeof schema === "boolean") { throw new SchemaError("Schema property cannot be defined as boolean.", path); } } const conversionFormatTypes = ["unix-time", "bigint", "any", "symbol", "set"]; function schemaInfo(schema, isOptional, path) { assertSchema(schema, path); if (schema.allOf && schema.allOf.length) { return { ...merge.withOptions({ allowUndefinedOverrides: false }, ...schema.allOf.map((s) => schemaInfo(s, false, []))), schema }; } const types = schemaTypes(schema, path); const array = schema.items && types.includes("array") ? (Array.isArray(schema.items) ? schema.items : [schema.items]).filter((s) => typeof s !== "boolean") : void 0; const properties = schema.properties && types.includes("object") ? Object.fromEntries(Object.entries(schema.properties).filter(([, value]) => typeof value !== "boolean")) : void 0; const union = unionInfo(schema)?.filter((u) => u.type !== "null" && u.const !== null); return { types: types.filter((s) => s !== "null"), isOptional, isNullable: types.includes("null"), schema, union: union?.length ? union : void 0, array, properties, required: schema.required }; } function schemaTypes(schema, path) { assertSchema(schema, path); let types = schema.const === null ? ["null"] : []; if (schema.type) { types = Array.isArray(schema.type) ? schema.type : [schema.type]; } if (schema.anyOf) { types = schema.anyOf.flatMap((s) => schemaTypes(s, path)); } if (types.includes("array") && schema.uniqueItems) { const i = types.findIndex((t) => t != "array"); types[i] = "set"; } else if (schema.format && conversionFormatTypes.includes(schema.format)) { types.unshift(schema.format); if (schema.format == "unix-time") { const i = types.findIndex((t) => t == "integer"); types.splice(i, 1); } } if (schema.const && schema.const !== null && typeof schema.const !== "function") { types.push(typeof schema.const); } return Array.from(new Set(types)); } function unionInfo(schema) { if (!schema.anyOf || !schema.anyOf.length) return void 0; return schema.anyOf.filter((s) => typeof s !== "boolean"); } function defaultValues(schema, isOptional = false, path = []) { return _defaultValues(schema, isOptional, path); } function _defaultValues(schema, isOptional, path) { if (!schema) { throw new SchemaError("Schema was undefined", path); } const info = schemaInfo(schema, isOptional, path); if (!info) return void 0; let objectDefaults = void 0; if ("default" in schema) { if (info.types.includes("object") && schema.default && typeof schema.default == "object" && !Array.isArray(schema.default)) { objectDefaults = schema.default; } else { if (info.types.length > 1) { if (info.types.includes("unix-time") && (info.types.includes("integer") || info.types.includes("number"))) throw new SchemaError("Cannot resolve a default value with a union that includes a date and a number/integer.", path); } const [type] = info.types; return formatDefaultValue(type, schema.default); } } let _multiType; const isMultiTypeUnion = () => { if (!info.union || info.union.length < 2) return false; if (info.union.some((i) => i.enum)) return true; if (!_multiType) { _multiType = new Set(info.types.map((i) => { return ["integer", "unix-time"].includes(i) ? "number" : i; })); } return _multiType.size > 1; }; let output = {}; if (!objectDefaults && info.union) { const singleDefault = info.union.filter((s) => typeof s !== "boolean" && s.default !== void 0); if (singleDefault.length == 1) { return _defaultValues(singleDefault[0], isOptional, path); } else if (singleDefault.length > 1) { throw new SchemaError("Only one default value can exist in a union, or set a default value for the whole union.", path); } else { if (info.isNullable) return null; if (info.isOptional) return void 0; if (isMultiTypeUnion()) { throw new SchemaError("Multi-type unions must have a default value, or exactly one of the union types must have.", path); } if (info.union.length && info.types[0] == "object") { output = info.union.length > 1 ? merge.withOptions({ allowUndefinedOverrides: true }, ...info.union.map((s) => _defaultValues(s, isOptional, path))) : _defaultValues(info.union[0], isOptional, path); } } } if (!objectDefaults) { if (info.isNullable) return null; if (info.isOptional) return void 0; } if (info.properties) { for (const [key, value] of Object.entries(info.properties)) { assertSchema(value, [...path, key]); const def = objectDefaults && objectDefaults[key] !== void 0 ? objectDefaults[key] : _defaultValues(value, !info.required?.includes(key), [...path, key]); output[key] = def; } return output; } else if (objectDefaults) { return objectDefaults; } if (schema.enum) { return schema.enum[0]; } if (isMultiTypeUnion()) { throw new SchemaError("Default values cannot have more than one type.", path); } else if (info.types.length == 0) { return void 0; } const [formatType] = info.types; return defaultValue(formatType, schema.enum); } function formatDefaultValue(type, value) { switch (type) { case "set": return Array.isArray(value) ? new Set(value) : value; case "Date": case "date": case "unix-time": if (typeof value === "string" || typeof value === "number") return new Date(value); break; case "bigint": if (typeof value === "string" || typeof value === "number") return BigInt(value); break; case "symbol": if (typeof value === "string" || typeof value === "number") return Symbol(value); break; } return value; } function defaultValue(type, enumType) { switch (type) { case "string": return enumType && enumType.length > 0 ? enumType[0] : ""; case "number": case "integer": return enumType && enumType.length > 0 ? enumType[0] : 0; case "boolean": return false; case "array": return []; case "object": return {}; case "null": return null; case "Date": case "date": case "unix-time": return void 0; case "bigint": return BigInt(0); case "set": return /* @__PURE__ */ new Set(); case "symbol": return Symbol(); case "undefined": case "any": return void 0; default: throw new SchemaError("Schema type or format not supported, requires explicit default value: " + type); } } function defaultTypes(schema, path = []) { return _defaultTypes(schema, false, path); } function _defaultTypes(schema, isOptional, path) { if (!schema) { throw new SchemaError("Schema was undefined", path); } const info = schemaInfo(schema, isOptional, path); const output = { __types: info.types }; if (info.schema.items && typeof info.schema.items == "object" && !Array.isArray(info.schema.items)) { output.__items = _defaultTypes(info.schema.items, info.isOptional, path); } if (info.properties) { for (const [key, value] of Object.entries(info.properties)) { assertSchema(value, [...path, key]); output[key] = _defaultTypes(info.properties[key], !info.required?.includes(key), [ ...path, key ]); } } if (info.isNullable && !output.__types.includes("null")) { output.__types.push("null"); } if (info.isOptional && !output.__types.includes("undefined")) { output.__types.push("undefined"); } return output; } class SuperFormError extends Error { constructor(message) { super(message); Object.setPrototypeOf(this, SuperFormError.prototype); } } class SchemaError extends SuperFormError { path; constructor(message, path) { super((path && path.length ? `[${Array.isArray(path) ? path.join(".") : path}] ` : "") + message); this.path = Array.isArray(path) ? path.join(".") : path; Object.setPrototypeOf(this, SchemaError.prototype); } } function mapErrors(errors, shape) { const output = {}; function addFormLevelError(error) { if (!("_errors" in output)) output._errors = []; if (!Array.isArray(output._errors)) { if (typeof output._errors === "string") output._errors = [output._errors]; else throw new SuperFormError("Form-level error was not an array."); } output._errors.push(error.message); } for (const error of errors) { if (!error.path || error.path.length == 1 && !error.path[0]) { addFormLevelError(error); continue; } const isLastIndexNumeric = /^\d$/.test(String(error.path[error.path.length - 1])); const objectError = !isLastIndexNumeric && pathExists(shape, error.path.filter((p) => /\D/.test(String(p))))?.value; const leaf = traversePath(output, error.path, ({ value, parent: parent2, key: key2 }) => { if (value === void 0) parent2[key2] = {}; return parent2[key2]; }); if (!leaf) { addFormLevelError(error); continue; } const { parent, key } = leaf; if (objectError) { if (!(key in parent)) parent[key] = {}; if (!("_errors" in parent[key])) parent[key]._errors = [error.message]; else parent[key]._errors.push(error.message); } else { if (!(key in parent)) parent[key] = [error.message]; else parent[key].push(error.message); } } return output; } function updateErrors(New, Previous, force) { if (force) return New; traversePaths(Previous, (errors) => { if (!Array.isArray(errors.value)) return; errors.set(void 0); }); traversePaths(New, (error) => { if (!Array.isArray(error.value) && error.value !== void 0) return; setPaths(Previous, [error.path], error.value); }); return Previous; } function flattenErrors(errors) { return _flattenErrors(errors, []); } function _flattenErrors(errors, path) { const entries = Object.entries(errors); return entries.filter(([, value]) => value !== void 0).flatMap(([key, messages]) => { if (Array.isArray(messages) && messages.length > 0) { const currPath = path.concat([key]); return { path: mergePath(currPath), messages }; } else { return _flattenErrors(errors[key], path.concat([key])); } }); } function mergeDefaults(parsedData, defaults) { if (!parsedData) return clone(defaults); return merge.withOptions({ mergeArrays: false }, defaults, parsedData); } function replaceInvalidDefaults(Data, Defaults, _schema, Errors, preprocessed) { const defaultType = _schema.additionalProperties && typeof _schema.additionalProperties == "object" ? { __types: schemaInfo(_schema.additionalProperties, false, []).types } : void 0; const Types = defaultTypes(_schema); function Types_correctValue(dataValue, defValue, type) { const types = type.__types; if (!types.length || types.every((t) => t == "undefined" || t == "null" || t == "any")) { return dataValue; } else if (types.length == 1 && types[0] == "array" && !type.__items) { return dataValue; } const dateTypes = ["unix-time", "Date", "date"]; for (const schemaType of types) { const defaultTypeValue = defaultValue(schemaType, void 0); const sameType = typeof dataValue === typeof defaultTypeValue || dateTypes.includes(schemaType) && dataValue instanceof Date; const sameExistance = sameType && dataValue === null === (defaultTypeValue === null); if (sameType && sameExistance) { return dataValue; } else if (type.__items) { return Types_correctValue(dataValue, defValue, type.__items); } } if (defValue === void 0 && types.includes("null")) { return null; } return defValue; } function Data_traverse() { traversePaths(Defaults, Defaults_traverseAndReplace); Errors_traverseAndReplace(); return Data; } function Data_setValue(currentPath, newValue) { setPaths(Data, [currentPath], newValue); } function Errors_traverseAndReplace() { for (const error of Errors) { if (!error.path) continue; Defaults_traverseAndReplace({ path: error.path, value: pathExists(Defaults, error.path)?.value }); } } function Defaults_traverseAndReplace(defaultPath) { const currentPath = defaultPath.path; if (!currentPath || !currentPath[0]) return; if (typeof currentPath[0] === "string" && preprocessed?.includes(currentPath[0])) return; const dataPath = pathExists(Data, currentPath); if (!dataPath && defaultPath.value !== void 0 || dataPath && dataPath.value === void 0) { Data_setValue(currentPath, defaultPath.value); } else if (dataPath) { const defValue = defaultPath.value; const dataValue = dataPath.value; if (defValue !== void 0 && typeof dataValue === typeof defValue && dataValue === null === (defValue === null)) { return; } const typePath = currentPath.filter((p) => /\D/.test(String(p))); const pathTypes = traversePath(Types, typePath, (path) => { return "__items" in path.value ? path.value.__items : path.value; }); if (!pathTypes) { throw new SchemaError("No types found for defaults", currentPath); } const fieldType = pathTypes.value ?? defaultType; if (!fieldType) { throw new SchemaError("No default value specified for field (can be undefined, but must be explicit)", currentPath); } Data_setValue(currentPath, Types_correctValue(dataValue, defValue, fieldType)); } } { return Data_traverse(); } } function cancelFlash(options) { if (!options.flashMessage || !browser) return; if (!shouldSyncFlash(options)) return; document.cookie = `flash=; Max-Age=0; Path=${options.flashMessage.cookiePath ?? "/"};`; } function shouldSyncFlash(options) { if (!options.flashMessage || !browser) return false; return options.syncFlashMessage; } const noCustomValidityDataAttribute = "noCustomValidity"; async function updateCustomValidity(validityEl, errors) { if ("setCustomValidity" in validityEl) { validityEl.setCustomValidity(""); } if (noCustomValidityDataAttribute in validityEl.dataset) return; setCustomValidity(validityEl, errors); } function setCustomValidityForm(formElement, errors) { for (const el of formElement.querySelectorAll("input,select,textarea,button")) { if (noCustomValidityDataAttribute in el.dataset) { continue; } const error = traversePath(errors, splitPath(el.name)); setCustomValidity(el, error?.value); if (error?.value) return; } } function setCustomValidity(el, errors) { const message = errors && errors.length ? errors.join("\n") : ""; el.setCustomValidity(message); if (message) el.reportValidity(); } const isElementInViewport = (el, topOffset = 0) => { const rect = el.getBoundingClientRect(); return rect.top >= topOffset && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth); }; const scrollToAndCenter = (el, offset = 1.125, behavior = "smooth") => { const elementRect = el.getBoundingClientRect(); const absoluteElementTop = elementRect.top + window.pageYOffset; const top = absoluteElementTop - window.innerHeight / (2 * offset); window.scrollTo({ left: 0, top, behavior }); }; const immediateInputTypes = ["checkbox", "radio", "range", "file"]; function inputInfo(el) { const immediate = !!el && (el instanceof HTMLSelectElement || el instanceof HTMLInputElement && immediateInputTypes.includes(el.type)); const multiple = !!el && el instanceof HTMLSelectElement && el.multiple; const file = !!el && el instanceof HTMLInputElement && el.type == "file"; return { immediate, multiple, file }; } var FetchStatus; (function(FetchStatus2) { FetchStatus2[FetchStatus2["Idle"] = 0] = "Idle"; FetchStatus2[FetchStatus2["Submitting"] = 1] = "Submitting"; FetchStatus2[FetchStatus2["Delayed"] = 2] = "Delayed"; FetchStatus2[FetchStatus2["Timeout"] = 3] = "Timeout"; })(FetchStatus || (FetchStatus = {})); const activeTimers = /* @__PURE__ */ new Set(); function Form(formElement, timers, options) { let state = FetchStatus.Idle; let delayedTimeout, timeoutTimeout; const Timers = activeTimers; function Timers_start() { Timers_clear(); Timers_setState(state != FetchStatus.Delayed ? FetchStatus.Submitting : FetchStatus.Delayed); delayedTimeout = window.setTimeout(() => { if (delayedTimeout && state == FetchStatus.Submitting) Timers_setState(FetchStatus.Delayed); }, options.delayMs); timeoutTimeout = window.setTimeout(() => { if (timeoutTimeout && state == FetchStatus.Delayed) Timers_setState(FetchStatus.Timeout); }, options.timeoutMs); Timers.add(Timers_clear); } function Timers_clear() { clearTimeout(delayedTimeout); clearTimeout(timeoutTimeout); delayedTimeout = timeoutTimeout = 0; Timers.delete(Timers_clear); Timers_setState(FetchStatus.Idle); } function Timers_clearAll() { Timers.forEach((t) => t()); Timers.clear(); } function Timers_setState(s) { state = s; timers.submitting.set(state >= FetchStatus.Submitting); timers.delayed.set(state >= FetchStatus.Delayed); timers.timeout.set(state >= FetchStatus.Timeout); } const ErrorTextEvents = formElement; function ErrorTextEvents__selectText(e) { const target = e.target; if (options.selectErrorText) target.select(); } function ErrorTextEvents_addErrorTextListeners() { if (!options.selectErrorText) return; ErrorTextEvents.querySelectorAll("input").forEach((el) => { el.addEventListener("invalid", ErrorTextEvents__selectText); }); } function ErrorTextEvents_removeErrorTextListeners() { if (!options.selectErrorText) return; ErrorTextEvents.querySelectorAll("input").forEach((el) => el.removeEventListener("invalid", ErrorTextEvents__selectText)); } const Form2 = formElement; { ErrorTextEvents_addErrorTextListeners(); const completed = (opts) => { if (!opts.clearAll) Timers_clear(); else Timers_clearAll(); if (!opts.cancelled) setTimeout(() => scrollToFirstError(Form2, options), 1); }; onDestroy(() => { ErrorTextEvents_removeErrorTextListeners(); completed({ cancelled: true }); }); return { submitting() { Timers_start(); }, completed, scrollToFirstError() { setTimeout(() => scrollToFirstError(Form2, options), 1); }, isSubmitting: () => state === FetchStatus.Submitting || state === FetchStatus.Delayed }; } } const scrollToFirstError = async (Form2, options) => { if (options.scrollToError == "off") return; const selector = options.errorSelector; if (!selector) return; await tick(); let el; el = Form2.querySelector(selector); if (!el) return; el = el.querySelector(selector) ?? el; const nav = options.stickyNavbar ? document.querySelector(options.stickyNavbar) : null; if (typeof options.scrollToError != "string") { el.scrollIntoView(options.scrollToError); } else if (!isElementInViewport(el, nav?.offsetHeight ?? 0)) { scrollToAndCenter(el, void 0, options.scrollToError); } function Form_shouldAutoFocus(userAgent) { if (typeof options.autoFocusOnError === "boolean") return options.autoFocusOnError; else return !/iPhone|iPad|iPod|Android/i.test(userAgent); } if (!Form_shouldAutoFocus(navigator.userAgent)) return; let focusEl; focusEl = el; if (!["INPUT", "SELECT", "BUTTON", "TEXTAREA"].includes(focusEl.tagName)) { focusEl = focusEl.querySelector('input:not([type="hidden"]):not(.flatpickr-input), select, textarea'); } if (focusEl) { try { focusEl.focus({ preventScroll: true }); if (options.selectErrorText && focusEl.tagName == "INPUT") { focusEl.select(); } } catch (err) { } } }; function updateProxyField(obj, path, updater) { const output = traversePath(obj, path, ({ parent, key, value }) => { if (value === void 0) parent[key] = /\D/.test(key) ? {} : []; return parent[key]; }); if (output) { const newValue = updater(output.value); output.parent[output.key] = newValue; } return obj; } function superFieldProxy(superForm2, path, baseOptions) { const form = superForm2.form; const path2 = splitPath(path); const proxy = derived(form, ($form) => { const data = traversePath($form, path2); return data?.value; }); return { subscribe(...params) { const unsub = proxy.subscribe(...params); return () => unsub(); }, update(upd, options) { form.update((data) => updateProxyField(data, path2, upd), options ?? baseOptions); }, set(value, options) { form.update((data) => updateProxyField(data, path2, () => value), options ?? baseOptions); } }; } function isSuperForm(form, options) { const isSuperForm2 = "form" in form; if (!isSuperForm2 && options?.taint !== void 0) { throw new SuperFormError("If options.taint is set, the whole superForm object must be used as a proxy."); } return isSuperForm2; } function fieldProxy(form, path, options) { const path2 = splitPath(path); if (isSuperForm(form, options)) { return superFieldProxy(form, path, options); } const proxy = derived(form, ($form) => { const data = traversePath($form, path2); return data?.value; }); return { subscribe(...params) { const unsub = proxy.subscribe(...params); return () => unsub(); }, update(upd) { form.update((data) => updateProxyField(data, path2, upd)); }, set(value) { form.update((data) => updateProxyField(data, path2, () => value)); } }; } function schemaShape(schema, path = []) { const output = _schemaShape(schema, path); if (!output) throw new SchemaError("No shape could be created for schema.", path); return output; } function _schemaShape(schema, path) { assertSchema(schema, path); const info = schemaInfo(schema, false, path); if (info.array || info.union) { const arr = info.array || []; const union = info.union || []; return arr.concat(union).reduce((shape, next) => { const nextShape = _schemaShape(next, path); if (nextShape) shape = { ...shape ?? {}, ...nextShape }; return shape; }, arr.length ? {} : void 0); } if (info.properties) { const output = {}; for (const [key, prop] of Object.entries(info.properties)) { const shape = _schemaShape(prop, [...path, key]); if (shape) output[key] = shape; } return output; } return info.types.includes("array") || info.types.includes("object") ? {} : void 0; } function shapeFromObject(obj) { let output = {}; const isArray = Array.isArray(obj); for (const [key, value] of Object.entries(obj)) { if (!value || typeof value !== "object") continue; if (isArray) output = { ...output, ...shapeFromObject(value) }; else output[key] = shapeFromObject(value); } return output; } const formIds = /* @__PURE__ */ new WeakMap(); const initialForms = /* @__PURE__ */ new WeakMap(); const defaultOnError = (event) => { console.warn("Unhandled error caught by Superforms, use onError event to handle it:", event.result.error); }; const defaultFormOptions = { applyAction: true, invalidateAll: true, resetForm: true, autoFocusOnError: "detect", scrollToError: "smooth", errorSelector: '[aria-invalid="true"],[data-invalid]', selectErrorText: false, stickyNavbar: void 0, taintedMessage: false, onSubmit: void 0, onResult: void 0, onUpdate: void 0, onUpdated: void 0, onError: defaultOnError, dataType: "form", validators: void 0, customValidity: false, clearOnSubmit: "message", delayMs: 500, timeoutMs: 8e3, multipleSubmits: "prevent", SPA: void 0, validationMethod: "auto" }; let LEGACY_MODE = false; try { if (SUPERFORMS_LEGACY) LEGACY_MODE = true; } catch { } let STORYBOOK_MODE = false; try { if (globalThis.STORIES) STORYBOOK_MODE = true; } catch { } function superForm(form, formOptions) { let initialForm; let options = formOptions ?? {}; let initialValidator = void 0; { if (options.legacy ?? LEGACY_MODE) { if (options.resetForm === void 0) options.resetForm = false; if (options.taintedMessage === void 0) options.taintedMessage = true; } if (STORYBOOK_MODE) { if (options.applyAction === void 0) options.applyAction = false; } if (typeof options.SPA === "string") { if (options.invalidateAll === void 0) options.invalidateAll = false; if (options.applyAction === void 0) options.applyAction = false; } initialValidator = options.validators; options = { ...defaultFormOptions, ...options }; if ((options.SPA === true || typeof options.SPA === "object") && options.validators === void 0) { console.warn("No validators set for superForm in SPA mode. Add a validation adapter to the validators option, or set it to false to disable this warning."); } if (!form) { throw new SuperFormError("No form data sent to superForm. Make sure the output from superValidate is used (usually data.form) and that it's not null or undefined. Alternatively, an object with default values for the form can also be used, but then constraints won't be available."); } if (Context_isValidationObject(form) === false) { form = { id: options.id ?? Math.random().toString(36).slice(2, 10), valid: false, posted: false, errors: {}, data: form, shape: shapeFromObject(form) }; } form = form; const _initialFormId = form.id = options.id ?? form.id; const _currentPage = get_store_value(page) ?? (STORYBOOK_MODE ? {} : void 0); if (!initialForms.has(form)) { initialForms.set(form, form); } initialForm = initialForms.get(form); if (_currentPage.form && typeof _currentPage.form === "object") { const postedData = _currentPage.form; for (const postedForm of Context_findValidationForms(postedData).reverse()) { if (postedForm.id == _initialFormId && !initialForms.has(postedForm)) { initialForms.set(postedData, postedData); const pageDataForm = form; form = postedForm; form.constraints = pageDataForm.constraints; form.shape = pageDataForm.shape; if (form.valid && options.resetForm && (options.resetForm === true || options.resetForm())) { form = clone(pageDataForm); form.message = clone(postedForm.message); } break; } } } else { form = clone(initialForm); } onDestroy(() => { Unsubscriptions_unsubscribe(); NextChange_clear(); EnhancedForm_destroy(); for (const events of Object.values(formEvents)) { events.length = 0; } formIds.get(_currentPage)?.delete(_initialFormId); }); if (options.dataType !== "json") { const checkForNestedData = (key, value) => { if (!value || typeof value !== "object") return; if (Array.isArray(value)) { if (value.length > 0) checkForNestedData(key, value[0]); } else if (!(value instanceof Date) && !(value instanceof File) && !browser) { throw new SuperFormError(`Object found in form field "${key}". Set the dataType option to "json" and add use:enhance to use nested data structures. More information: https://superforms.rocks/concepts/nested-data`); } }; for (const [key, value] of Object.entries(form.data)) { checkForNestedData(key, value); } } } const __data = { formId: form.id, form: clone(form.data), constraints: form.constraints ?? {}, posted: form.posted, errors: clone(form.errors), message: clone(form.message), tainted: void 0, valid: form.valid, submitting: false, shape: form.shape }; const Data = __data; const FormId = writable(options.id ?? form.id); function Context_findValidationForms(data) { const forms = Object.values(data).filter((v) => Context_isValidationObject(v) !== false); return forms; } function Context_isValidationObject(object) { if (!object || typeof object !== "object") return false; if (!("valid" in object && "errors" in object && typeof object.valid === "boolean")) { return false; } return "id" in object && typeof object.id === "string" ? object.id : false; } const _formData = writable(form.data); const Form$1 = { subscribe: _formData.subscribe, set: (value, options2 = {}) => { const newData = clone(value); Tainted_update(newData, options2.taint ?? true); return _formData.set(newData); }, update: (updater, options2 = {}) => { return _formData.update((value) => { const newData = updater(value); Tainted_update(newData, options2.taint ?? true); return newData; }); } }; function Form_isSPA() { return options.SPA === true || typeof options.SPA === "object"; } async function Form_validate(opts = {}) { const dataToValidate = opts.formData ?? Data.form; let errors = {}; let status; const validator = opts.adapter ?? options.validators; if (typeof validator == "object") { if (validator != initialValidator && !("jsonSchema" in validator)) { throw new SuperFormError('Client validation adapter found in options.validators. A full adapter must be used when changing validators dynamically, for example "zod" instead of "zodClient".'); } status = await /* @__PURE__ */ validator.validate(dataToValidate); if (!status.success) { errors = mapErrors(status.issues, validator.shape ?? Data.shape ?? {}); } else if (opts.recheckValidData !== false) { return Form_validate({ ...opts, recheckValidData: false }); } } else { status = { success: true, data: {} }; } const data = { ...Data.form, ...dataToValidate, ...status.success ? status.data : {} }; return { valid: status.success, posted: false, errors, data, constraints: Data.constraints, message: void 0, id: Data.formId, shape: Data.shape }; } function Form__changeEvent(event) { if (!options.onChange || !event.paths.length || event.type == "blur") return; let changeEvent; const paths = event.paths.map(mergePath); if (event.type && event.paths.length == 1 && event.formElement && event.target instanceof Element) { changeEvent = { path: paths[0], paths, formElement: event.formElement, target: event.target, set(path, value, options2) { fieldProxy({ form: Form$1 }, path, options2).set(value); }, get(path) { return get_store_value(fieldProxy(Form$1, path)); } }; } else { changeEvent = { paths, target: void 0, set(path, value, options2) { fieldProxy({ form: Form$1 }, path, options2).set(value); }, get(path) { return get_store_value(fieldProxy(Form$1, path)); } }; } options.onChange(changeEvent); } async function Form_clientValidation(event, force = false, adapter) { if (event) { if (options.validators == "clear") { Errors.update(($errors) => { setPaths($errors, event.paths, void 0); return $errors; }); } setTimeout(() => Form__changeEvent(event)); } let skipValidation = false; if (!force) { if (options.validationMethod == "onsubmit" || options.validationMethod == "submit-only") { skipValidation = true; } else if (options.validationMethod == "onblur" && event?.type == "input") skipValidation = true; else if (options.validationMethod == "oninput" && event?.type == "blur") skipValidation = true; } if (skipValidation || !event || !options.validators || options.validators == "clear") { if (event?.paths) { const formElement = event?.formElement ?? EnhancedForm_get(); if (formElement) Form__clearCustomValidity(formElement, event.paths); } return; } const result = await Form_validate({ adapter }); if (result.valid && (event.immediate || event.type != "input")) { Form$1.set(result.data, { taint: "ignore" }); } await tick(); Form__displayNewErrors(result.errors, event, force); return result; } function Form__clearCustomValidity(formElement, paths) { const validity = /* @__PURE__ */ new Map(); if (options.customValidity && formElement) { for (const path of paths) { const name = CSS.escape(mergePath(path)); const el = formElement.querySelector(`[name="${name}"]`); if (el) { const message = "validationMessage" in el ? String(el.validationMessage) : ""; validity.set(path.join("."), { el, message }); updateCustomValidity(el, void 0); } } } return validity; } async function Form__displayNewErrors(errors, event, force) { const { type, immediate, multiple, paths } = event; const previous = Data.errors; const output = {}; let validity = /* @__PURE__ */ new Map(); const formElement = event.formElement ?? EnhancedForm_get(); if (formElement) validity = Form__clearCustomValidity(formElement, event.paths); traversePaths(errors, (error) => { if (!Array.isArray(error.value)) return; const currentPath = [...error.path]; if (currentPath[currentPath.length - 1] == "_errors") { currentPath.pop(); } const joinedPath = currentPath.join("."); function addError() { setPaths(output, [error.path], error.value); if (options.customValidity && isEventError && validity.has(joinedPath)) { const { el, message } = validity.get(joinedPath); if (message != error.value) { updateCustomValidity(el, error.value); validity.clear(); } } } if (force) return addError(); const lastPath = error.path[error.path.length - 1]; const isObjectError = lastPath == "_errors"; const isEventError = error.value && paths.some((path) => { return isObjectError ? currentPath && path && currentPath.length > 0 && currentPath[0] == path[0] : joinedPath == path.join("."); }); if (isEventError && options.validationMethod == "oninput") return addError(); if (immediate && !multiple && isEventError) return addError(); if (multiple) { const errorPath = pathExists(get_store_value(Errors), error.path.slice(0, -1)); if (errorPath?.value && typeof errorPath?.value == "object") { for (const errors2 of Object.values(errorPath.value)) { if (Array.isArray(errors2)) { return addError(); } } } } const previousError = pathExists(previous, error.path); if (previousError && previousError.key in previousError.parent) { return addError(); } if (isObjectError) { if (options.validationMethod == "oninput" || type == "blur" && Tainted_hasBeenTainted(mergePath(error.path.slice(0, -1)))) { return addError(); } } else { if (type == "blur" && isEventError) { return addError(); } } }); Errors.set(output); } function Form_set(data, options2 = {}) { if (options2.keepFiles) { traversePaths(Data.form, (info) => { if (info.value instanceof File || browser) { const dataPath = pathExists(data, info.path); if (!dataPath || !(dataPath.key in dataPath.parent)) { setPaths(data, [info.path], info.value); } } }); } return Form$1.set(data, options2); } function Form_shouldReset(validForm, successActionResult) { return validForm && successActionResult && options.resetForm && (options.resetForm === true || options.resetForm()); } async function Form_updateFromValidation(form2, successResult) { if (form2.valid && successResult && Form_shouldReset(form2.valid, successResult)) { Form_reset({ message: form2.message, posted: true }); } else { rebind({ form: form2, untaint: successResult, keepFiles: true, // Check if the form data should be used for updating, or if the invalidateAll load function should be used: skipFormData: options.invalidateAll == "force" }); } if (formEvents.onUpdated.length) { await tick(); } for (const event of formEvents.onUpdated) { event({ form: form2 }); } } function Form_reset(opts = {}) { if (opts.newState) initialForm.data = { ...initialForm.data, ...opts.newState }; const resetData = clone(initialForm); resetData.data = { ...resetData.data, ...opts.data }; if (opts.id !== void 0) resetData.id = opts.id; rebind({ form: resetData, untaint: true, message: opts.message, keepFiles: false, posted: opts.posted }); } async function Form_updateFromActionResult(result) { if (result.type == "error") { throw new SuperFormError(`ActionResult of type "${result.type}" cannot be passed to update function.`); } if (result.type == "redirect") { if (Form_shouldReset(true, true)) Form_reset({ posted: true }); return; } if (typeof result.data !== "object") { throw new SuperFormError("Non-object validation data returned from ActionResult."); } const forms = Context_findValidationForms(result.data); if (!forms.length) { throw new SuperFormError("No form data returned from ActionResult. Make sure you return { form } in the form actions."); } for (const newForm of forms) { if (newForm.id !== Data.formId) continue; await Form_updateFromValidation(newForm, result.status >= 200 && result.status < 300); } } const Message = writable(__data.message); const Constraints = writable(__data.constraints); const Posted = writable(__data.posted); const Shape = writable(__data.shape); const _errors = writable(form.errors); const Errors = { subscribe: _errors.subscribe, set(value, options2) { return _errors.set(updateErrors(value, Data.errors, options2?.force)); }, update(updater, options2) { return _errors.update((value) => { return updateErrors(updater(value), Data.errors, options2?.force); }); }, /** * To work with client-side validation, errors cannot be deleted but must * be set to undefined, to know where they existed before (tainted+error check in oninput) */ clear: () => Errors.set({}) }; let NextChange = null; function NextChange_setHtmlEvent(event) { if (NextChange && event && Object.keys(event).length == 1 && event.paths?.length && NextChange.target && NextChange.target instanceof HTMLInputElement && NextChange.target.type.toLowerCase() == "file") { NextChange.paths = event.paths; } else { NextChange = event; } setTimeout(() => { Form_clientValidation(NextChange); }, 0); } function NextChange_additionalEventInformation(event, immediate, multiple, formElement, target) { if (NextChange === null) { NextChange = { paths: [] }; } NextChange.type = event; NextChange.immediate = immediate; NextChange.multiple = multiple; NextChange.formElement = formElement; NextChange.target = target; } function NextChange_paths() { return NextChange?.paths ?? []; } function NextChange_clear() { NextChange = null; } const Tainted = { defaultMessage: "Leave page? Changes that you made may not be saved.", state: writable(), message: options.taintedMessage, clean: clone(form.data), // Important to clone form.data, so it's not comparing the same object, forceRedirection: false }; function Tainted_enable() { options.taintedMessage = Tainted.message; } function Tainted_currentState() { return Tainted.state; } function Tainted_hasBeenTainted(path) { if (!Data.tainted) return false; if (!path) return !!Data.tainted; const field = pathExists(Data.tainted, splitPath(path)); return !!field && field.key in field.parent; } function Tainted_isTainted(path) { if (typeof path === "boolean") return path; if (typeof path === "object") return Tainted__isObjectTainted(path); if (!Data.tainted) return false; if (!path) return Tainted__isObjectTainted(Data.tainted); const field = pathExists(Data.tainted, splitPath(path)); return Tainted__isObjectTainted(field?.value); } function Tainted__isObjectTainted(obj) { if (!obj) return false; if (typeof obj === "object") { for (const obj2 of Object.values(obj)) { if (Tainted__isObjectTainted(obj2)) return true; } } return obj === true; } function Tainted_update(newData, taintOptions) { if (taintOptions == "ignore") return; const paths = comparePaths(newData, Data.form); const newTainted = comparePaths(newData, Tainted.clean).map((path) => path.join()); if (paths.length) { if (taintOptions == "untaint-all" || taintOptions == "untaint-form") { Tainted.state.set(void 0); } else { Tainted.state.update((currentlyTainted) => { if (!currentlyTainted) currentlyTainted = {}; setPaths(currentlyTainted, paths, (path, data) => { if (!newTainted.includes(path.join())) return void 0; const currentValue = traversePath(newData, path); const cleanPath = traversePath(Tainted.clean, path); return currentValue && cleanPath && currentValue.value === cleanPath.value ? void 0 : taintOptions === true ? true : taintOptions === "untaint" ? void 0 : data.value; }); return currentlyTainted; }); } } NextChange_setHtmlEvent({ paths }); } function Tainted_set(tainted, newClean) { Tainted.state.set(tainted); if (newClean) Tainted.clean = newClean; } const Submitting = writable(false); const Delayed = writable(false); const Timeout = writable(false); const Unsubscriptions = [ // eslint-disable-next-line dci-lint/private-role-access Tainted.state.subscribe((tainted) => __data.tainted = clone(tainted)), // eslint-disable-next-line dci-lint/private-role-access Form$1.subscribe((form2) => __data.form = clone(form2)), // eslint-disable-next-line dci-lint/private-role-access Errors.subscribe((errors) => __data.errors = clone(errors)), FormId.subscribe((id) => __data.formId = id), Constraints.subscribe((constraints) => __data.constraints = constraints), Posted.subscribe((posted) => __data.posted = posted), Message.subscribe((message) => __data.message = message), Submitting.subscribe((submitting) => __data.submitting = submitting), Shape.subscribe((shape) => __data.shape = shape) ]; function Unsubscriptions_unsubscribe() { Unsubscriptions.forEach((unsub) => unsub()); } let EnhancedForm; function EnhancedForm_get() { return EnhancedForm; } function EnhancedForm_setAction(action) { if (EnhancedForm) EnhancedForm.action = action; } function EnhancedForm_destroy() { if (EnhancedForm?.parentElement) { EnhancedForm.remove(); } EnhancedForm = void 0; } const AllErrors = derived(Errors, ($errors) => $errors ? flattenErrors($errors) : []); options.taintedMessage = void 0; function rebind(opts) { const form2 = opts.form; const message = opts.message ?? form2.message; if (opts.untaint) { Tainted_set(typeof opts.untaint === "boolean" ? void 0 : opts.untaint, form2.data); } if (opts.skipFormData !== true) { Form_set(form2.data, { taint: "ignore", keepFiles: opts.keepFiles }); } Message.set(message); Errors.set(form2.errors); FormId.set(form2.id); Posted.set(opts.posted ?? form2.posted); if (form2.constraints) Constraints.set(form2.constraints); if (form2.shape) Shape.set(form2.shape); __data.valid = form2.valid; if (options.flashMessage && shouldSyncFlash(options)) { const flash = options.flashMessage.module.getFlash(page); if (message && get_store_value(flash) === void 0) { flash.set(message); } } } const formEvents = { onSubmit: options.onSubmit ? [options.onSubmit] : [], onResult: options.onResult ? [options.onResult] : [], onUpdate: options.onUpdate ? [options.onUpdate] : [], onUpdated: options.onUpdated ? [options.onUpdated] : [], onError: options.onError ? [options.onError] : [] }; function superFormEnhance(FormElement, events) { if (options.SPA !== void 0 && FormElement.method == "get") FormElement.method = "post"; if (typeof options.SPA === "string") { if (options.SPA.length && FormElement.action == document.location.href) { FormElement.action = options.SPA; } } else { EnhancedForm = FormElement; } if (events) { if (events.onError) { if (options.onError === "apply") { throw new SuperFormError('options.onError is set to "apply", cannot add any onError events.'); } else if (events.onError === "apply") { throw new SuperFormError('Cannot add "apply" as onError event in use:enhance.'); } formEvents.onError.push(events.onError); } if (events.onResult) formEvents.onResult.push(events.onResult); if (events.onSubmit) formEvents.onSubmit.push(events.onSubmit); if (events.onUpdate) formEvents.onUpdate.push(events.onUpdate); if (events.onUpdated) formEvents.onUpdated.push(events.onUpdated); } Tainted_enable(); let lastInputChange; async function onInput(e) { const info = inputInfo(e.target); if (info.immediate && !info.file) await new Promise((r) => setTimeout(r, 0)); lastInputChange = NextChange_paths(); NextChange_additionalEventInformation("input", info.immediate, info.multiple, FormElement, e.target ?? void 0); } async function onBlur(e) { if (Data.submitting) return; if (!lastInputChange || NextChange_paths() != lastInputChange) { return; } const info = inputInfo(e.target); if (info.immediate && !info.file) await new Promise((r) => setTimeout(r, 0)); Form_clientValidation({ paths: lastInputChange, immediate: info.multiple, multiple: info.multiple, type: "blur", formElement: FormElement, target: e.target ?? void 0 }); lastInputChange = void 0; } FormElement.addEventListener("focusout", onBlur); FormElement.addEventListener("input", onInput); onDestroy(() => { FormElement.removeEventListener("focusout", onBlur); FormElement.removeEventListener("input", onInput); }); const htmlForm = Form(FormElement, { submitting: Submitting, delayed: Delayed, timeout: Timeout }, options); let currentRequest; return enhance(FormElement, async (submitParams) => { let jsonData = void 0; let validationAdapter = options.validators; const submit = { ...submitParams, jsonData(data) { if (options.dataType !== "json") { throw new SuperFormError("options.dataType must be set to 'json' to use jsonData."); } jsonData = data; }, validators(adapter) { validationAdapter = adapter; } }; const _submitCancel = submit.cancel; let cancelled = false; function clientValidationResult(validation) { const validationResult = { ...validation, posted: true }; const status = validationResult.valid ? 200 : (typeof options.SPA === "boolean" || typeof options.SPA === "string" ? void 0 : options.SPA?.failStatus) ?? 400; const data = { form: validationResult }; const result = validationResult.valid ? { type: "success", status, data } : { type: "failure", status, data }; setTimeout(() => validationResponse({ result }), 0); } function clearOnSubmit() { switch (options.clearOnSubmit) { case "errors-and-message": Errors.clear(); Message.set(void 0); break; case "errors": Errors.clear(); break; case "message": Message.set(void 0); break; } } function cancel(opts = { resetTimers: true }) { cancelled = true; if (opts.resetTimers && htmlForm.isSubmitting()) { htmlForm.completed({ cancelled }); } return _submitCancel(); } submit.cancel = cancel; if (htmlForm.isSubmitting() && options.multipleSubmits == "prevent") { cancel({ resetTimers: false }); } else { if (htmlForm.isSubmitting() && options.multipleSubmits == "abort") { if (currentRequest) currentRequest.abort(); } htmlForm.submitting(); currentRequest = submit.controller; for (const event of formEvents.onSubmit) { await event(submit); } } if (cancelled && options.flashMessage) cancelFlash(options); if (!cancelled) { const noValidate = !Form_isSPA() && (FormElement.noValidate || (submit.submitter instanceof HTMLButtonElement || submit.submitter instanceof HTMLInputElement) && submit.submitter.formNoValidate); let validation = void 0; const validateForm = async () => { return await Form_validate({ adapter: validationAdapter }); }; clearOnSubmit(); if (!noValidate) { validation = await validateForm(); if (!validation.valid) { cancel({ resetTimers: false }); clientValidationResult(validation); } } if (!cancelled) { if (options.flashMessage && (options.clearOnSubmit == "errors-and-message" || options.clearOnSubmit == "message") && shouldSyncFlash(options)) { options.flashMessage.module.getFlash(page).set(void 0); } const submitData = "formData" in submit ? submit.formData : submit.data; lastInputChange = void 0; if (Form_isSPA()) { if (!validation) validation = await validateForm(); cancel({ resetTimers: false }); clientValidationResult(validation); } else if (options.dataType === "json") { if (!validation) validation = await validateForm(); const postData = clone(jsonData ?? validation.data); traversePaths(postData, (data) => { if (data.value instanceof File) { const key = "__superform_file_" + mergePath(data.path); submitData.append(key, data.value); return data.set(void 0); } else if (Array.isArray(data.value) && data.value.length && data.value.every((v) => v instanceof File)) { const key = "__superform_files_" + mergePath(data.path); for (const file of data.value) { submitData.append(key, file); } return data.set(void 0); } }); Object.keys(postData).forEach((key) => { if (typeof submitData.get(key) === "string") { submitData.delete(key); } }); const chunks = chunkSubstr(stringify(postData), options.jsonChunkSize ?? 5e5); for (const chunk of chunks) { submitData.append("__superform_json", chunk); } } if (!submitData.has("__superform_id")) { const id = Data.formId; if (id !== void 0) submitData.set("__superform_id", id); } if (typeof options.SPA === "string") { EnhancedForm_setAction(options.SPA); } } } function chunkSubstr(str, size) { const numChunks = Math.ceil(str.length / size); const chunks = new Array(numChunks); for (let i = 0, o = 0; i < numChunks; ++i, o += size) { chunks[i] = str.substring(o, o + size); } return chunks; } async function validationResponse(event) { let cancelled2 = false; currentRequest = null; let result = "type" in event.result && "status" in event.result ? event.result : { type: "error", status: parseInt(String(event.result.status)) || 500, error: event.result.error instanceof Error ? event.result.error : event.result }; const cancel2 = () => cancelled2 = true; const data = { result, formEl: FormElement, formElement: FormElement, cancel: cancel2 }; const unsubCheckforNav = STORYBOOK_MODE || !Form_isSPA() ? () => { } : navigating.subscribe(($nav) => { if (!$nav || $nav.from?.route.id === $nav.to?.route.id) return; cancel2(); }); for (const event2 of formEvents.onResult) { await event2(data); } result = data.result; if (!cancelled2) { if ((result.type === "success" || result.type == "failure") && result.data) { const forms = Context_findValidationForms(result.data); if (!forms.length) { throw new SuperFormError("No form data returned from ActionResult. Make sure you return { form } in the form actions."); } for (const newForm of forms) { if (newForm.id !== Data.formId) continue; const data2 = { form: newForm, formEl: FormElement, formElement: FormElement, cancel: () => cancelled2 = true, result }; for (const event2 of formEvents.onUpdate) { await event2(data2); } result = data2.result; if (!cancelled2) { if (options.customValidity) { setCustomValidityForm(FormElement, data2.form.errors); } if (Form_shouldReset(data2.form.valid, result.type == "success")) { data2.formElement.querySelectorAll('input[type="file"]').forEach((e) => e.value = ""); } } } } if (!cancelled2) { if (result.type !== "error") { if (result.type === "success" && options.invalidateAll) { await invalidateAll(); } if (options.applyAction) { await applyAction(); } else { await Form_updateFromActionResult(result); } } else { if (options.applyAction) { if (options.onError == "apply") { await applyAction(); } else { ({ type: "failure", status: Math.floor(result.status || 500), data: result }); await applyAction(); } } if (options.onError !== "apply") { const data2 = { result, message: Message }; for (const onErrorEvent of formEvents.onError) { if (onErrorEvent !== "apply" && (onErrorEvent != defaultOnError || !options.flashMessage?.onError)) { await onErrorEvent(data2); } } } } if (options.flashMessage) { if (result.type == "error" && options.flashMessage.onError) { await options.flashMessage.onError({ result, flashMessage: options.flashMessage.module.getFlash(page) }); } } } } if (cancelled2 && options.flashMessage) { cancelFlash(options); } if (cancelled2 || result.type != "redirect") { htmlForm.completed({ cancelled: cancelled2 }); } else if (STORYBOOK_MODE) { htmlForm.completed({ cancelled: cancelled2, clearAll: true }); } else { const unsub = navigating.subscribe(($nav) => { if ($nav) return; setTimeout(() => { try { if (unsub) unsub(); } catch { } }); if (htmlForm.isSubmitting()) { htmlForm.completed({ cancelled: cancelled2, clearAll: true }); } }); } unsubCheckforNav(); } return validationResponse; }); } function removeFiles(formData) { const paths = []; traversePaths(formData, (data2) => { if (data2.value instanceof File) { paths.push(data2.path); return "skip"; } else if (Array.isArray(data2.value) && data2.value.length && data2.value.every((d) => d instanceof File)) { paths.push(data2.path); return "skip"; } }); if (!paths.length) return { data: formData, paths }; const data = clone(formData); setPaths(data, paths, (path) => pathExists(initialForm.data, path)?.value); return { data, paths }; } return { form: Form$1, formId: FormId, errors: Errors, message: Message, constraints: Constraints, tainted: Tainted_currentState(), submitting: readonly(Submitting), delayed: readonly(Delayed), timeout: readonly(Timeout), options, capture() { const { data, paths } = removeFiles(Data.form); let tainted = Data.tainted; if (paths.length) { tainted = clone(tainted) ?? {}; setPaths(tainted, paths, false); } return { valid: Data.valid, posted: Data.posted, errors: Data.errors, data, constraints: Data.constraints, message: Data.message, id: Data.formId, tainted, shape: Data.shape }; }, restore: (snapshot) => { rebind({ form: snapshot, untaint: snapshot.tainted ?? true }); }, async validate(path, opts = {}) { if (!options.validators) { throw new SuperFormError("options.validators must be set to use the validate method."); } if (opts.update === void 0) opts.update = true; if (opts.taint === void 0) opts.taint = false; if (typeof opts.errors == "string") opts.errors = [opts.errors]; let data; const splittedPath = splitPath(path); if ("value" in opts) { if (opts.update === true || opts.update === "value") { Form$1.update(($form) => { setPaths($form, [splittedPath], opts.value); return $form; }, { taint: opts.taint }); data = Data.form; } else { data = clone(Data.form); setPaths(data, [splittedPath], opts.value); } } else { data = Data.form; } const result = await Form_validate({ formData: data }); const error = pathExists(result.errors, splittedPath); if (error && error.value && opts.errors) { error.value = opts.errors; } if (opts.update === true || opts.update == "errors") { Errors.update(($errors) => { setPaths($errors, [splittedPath], error?.value); return $errors; }); } return error?.value; }, async validateForm(opts = {}) { if (!options.validators && !opts.schema) { throw new SuperFormError("options.validators or the schema option must be set to use the validateForm method."); } const result = opts.update ? await Form_clientValidation({ paths: [] }, true, opts.schema) : Form_validate({ adapter: opts.schema }); const enhancedForm = EnhancedForm_get(); if (opts.update && enhancedForm) { setTimeout(() => { if (!enhancedForm) return; scrollToFirstError(enhancedForm, { ...options, scrollToError: opts.focusOnError === false ? "off" : options.scrollToError }); }, 1); } return result || Form_validate({ adapter: opts.schema }); }, allErrors: AllErrors, posted: Posted, reset(options2) { return Form_reset({ message: options2?.keepMessage ? Data.message : void 0, data: options2?.data, id: options2?.id, newState: options2?.newState }); }, submit(submitter) { const form2 = EnhancedForm_get() ? EnhancedForm_get() : submitter && submitter instanceof HTMLElement ? submitter.closest("form") : void 0; if (!form2) { throw new SuperFormError("use:enhance must be added to the form to use submit, or pass a HTMLElement inside the form (or the form itself) as an argument."); } if (!form2.requestSubmit) { return form2.submit(); } const isSubmitButton = submitter && (submitter instanceof HTMLButtonElement && submitter.type == "submit" || submitter instanceof HTMLInputElement && ["submit", "image"].includes(submitter.type)); form2.requestSubmit(isSubmitButton ? submitter : void 0); }, isTainted: Tainted_isTainted, enhance: superFormEnhance }; } let legacyMode = false; try { if (SUPERFORMS_LEGACY) legacyMode = true; } catch { } const unionError = 'FormData parsing failed: Unions are only supported when the dataType option for superForm is set to "json".'; async function parseRequest(data, schemaData, options) { let parsed; if (data instanceof FormData) { parsed = parseFormData(data, schemaData, options); } else if (data instanceof URL || data instanceof URLSearchParams) { parsed = parseSearchParams(data, schemaData, options); } else if (data instanceof Request) { parsed = await tryParseFormData(data, schemaData, options); } else if ( // RequestEvent data && typeof data === "object" && "request" in data && data.request instanceof Request ) { parsed = await tryParseFormData(data.request, schemaData, options); } else { parsed = { id: void 0, data, posted: false }; } return parsed; } async function tryParseFormData(request, schemaData, options) { let formData = void 0; try { formData = await request.formData(); } catch (e) { if (e instanceof TypeError && e.message.includes("already been consumed")) { throw e; } return { id: void 0, data: void 0, posted: false }; } return parseFormData(formData, schemaData, options); } function parseSearchParams(data, schemaData, options) { if (data instanceof URL) data = data.searchParams; const convert = new FormData(); for (const [key, value] of data.entries()) { convert.append(key, value); } const output = parseFormData(convert, schemaData, options); output.posted = false; return output; } function parseFormData(formData, schemaData, options) { function tryParseSuperJson() { if (formData.has("__superform_json")) { try { const output = parse(formData.getAll("__superform_json").join("") ?? ""); if (typeof output === "object") { const filePaths = Array.from(formData.keys()); for (const path of filePaths.filter((path2) => path2.startsWith("__superform_file_"))) { const realPath = splitPath(path.substring(17)); setPaths(output, [realPath], formData.get(path)); } for (const path of filePaths.filter((path2) => path2.startsWith("__superform_files_"))) { const realPath = splitPath(path.substring(18)); const allFiles = formData.getAll(path); setPaths(output, [realPath], Array.from(allFiles)); } return output; } } catch { } } return null; } const data = tryParseSuperJson(); const id = formData.get("__superform_id")?.toString(); return data ? { id, data, posted: true } : { id, data: _parseFormData(formData, schemaData, options), posted: true }; } function _parseFormData(formData, schema, options) { const output = {}; const schemaKeys = options?.strict ? new Set([...formData.keys()].filter((key) => !key.startsWith("__superform_"))) : new Set([ ...Object.keys(schema.properties ?? {}), ...schema.additionalProperties ? formData.keys() : [] ].filter((key) => !key.startsWith("__superform_"))); function parseSingleEntry(key, entry, info) { if (options?.preprocessed && options.preprocessed.includes(key)) { return entry; } if (entry && typeof entry !== "string") { const allowFiles = legacyMode ? options?.allowFiles === true : options?.allowFiles !== false; return !allowFiles ? void 0 : entry.size ? entry : info.isNullable ? null : void 0; } if (info.types.length > 1) { throw new SchemaError(unionError, key); } const [type] = info.types; return parseFormDataEntry(key, entry, type ?? "any", info); } const defaultPropertyType = typeof schema.additionalProperties == "object" ? schema.additionalProperties : { type: "string" }; for (const key of schemaKeys) { const property = schema.properties ? schema.properties[key] : defaultPropertyType; assertSchema(property, key); const info = schemaInfo(property ?? defaultPropertyType, !schema.required?.includes(key), [ key ]); if (!info) continue; if (!info.types.includes("boolean") && !schema.additionalProperties && !formData.has(key)) { continue; } const entries = formData.getAll(key); if (info.union && info.union.length > 1) { throw new SchemaError(unionError, key); } if (info.types.includes("array") || info.types.includes("set")) { const items = property.items ?? (info.union?.length == 1 ? info.union[0] : void 0); if (!items || typeof items == "boolean" || Array.isArray(items) && items.length != 1) { throw new SchemaError('Arrays must have a single "items" property that defines its type.', key); } const arrayType = Array.isArray(items) ? items[0] : items; assertSchema(arrayType, key); const arrayInfo = schemaInfo(arrayType, info.isOptional, [key]); if (!arrayInfo) continue; const isFileArray = entries.length && entries.some((e) => e && typeof e !== "string"); const arrayData = entries.map((e) => parseSingleEntry(key, e, arrayInfo)); if (isFileArray && arrayData.every((file) => !file)) arrayData.length = 0; output[key] = info.types.includes("set") ? new Set(arrayData) : arrayData; } else { output[key] = parseSingleEntry(key, entries[entries.length - 1], info); } } return output; } function parseFormDataEntry(key, value, type, info) { if (!value) { if (type == "boolean" && info.isOptional && info.schema.default === true) { return false; } const defaultValue2 = defaultValues(info.schema, info.isOptional, [key]); if (info.schema.enum && defaultValue2 !== null && defaultValue2 !== void 0) { return value; } if (defaultValue2 !== void 0) return defaultValue2; if (info.isNullable) return null; if (info.isOptional) return void 0; } function typeError() { throw new SchemaError(type[0].toUpperCase() + type.slice(1) + ` type found. Set the dataType option to "json" and add use:enhance on the client to use nested data structures. More information: https://superforms.rocks/concepts/nested-data`, key); } switch (type) { case "string": case "any": return value; case "integer": return parseInt(value ?? "", 10); case "number": return parseFloat(value ?? ""); case "boolean": return Boolean(value == "false" ? "" : value).valueOf(); case "unix-time": { const date = new Date(value ?? ""); return !isNaN(date) ? date : void 0; } case "bigint": return BigInt(value ?? "."); case "symbol": return Symbol(String(value)); case "set": case "array": case "object": return typeError(); default: throw new SuperFormError("Unsupported schema type for FormData: " + type); } } var memoize; var hasRequiredMemoize; function requireMemoize () { if (hasRequiredMemoize) return memoize; hasRequiredMemoize = 1; function isPrimitive(value) { return ((typeof value !== 'object') && (typeof value !== 'function')) || (value === null); } function MapTree() { this.childBranches = new WeakMap(); this.primitiveKeys = new Map(); this.hasValue = false; this.value = undefined; } MapTree.prototype.has = function has(key) { var keyObject = (isPrimitive(key) ? this.primitiveKeys.get(key) : key); return (keyObject ? this.childBranches.has(keyObject) : false); }; MapTree.prototype.get = function get(key) { var keyObject = (isPrimitive(key) ? this.primitiveKeys.get(key) : key); return (keyObject ? this.childBranches.get(keyObject) : undefined); }; MapTree.prototype.resolveBranch = function resolveBranch(key) { if (this.has(key)) { return this.get(key); } var newBranch = new MapTree(); var keyObject = this.createKey(key); this.childBranches.set(keyObject, newBranch); return newBranch; }; MapTree.prototype.setValue = function setValue(value) { this.hasValue = true; return (this.value = value); }; MapTree.prototype.createKey = function createKey(key) { if (isPrimitive(key)) { var keyObject = {}; this.primitiveKeys.set(key, keyObject); return keyObject; } return key; }; MapTree.prototype.clear = function clear() { if (arguments.length === 0) { this.childBranches = new WeakMap(); this.primitiveKeys.clear(); this.hasValue = false; this.value = undefined; } else if (arguments.length === 1) { var key = arguments[0]; if (isPrimitive(key)) { var keyObject = this.primitiveKeys.get(key); if (keyObject) { this.childBranches.delete(keyObject); this.primitiveKeys.delete(key); } } else { this.childBranches.delete(key); } } else { var childKey = arguments[0]; if (this.has(childKey)) { var childBranch = this.get(childKey); childBranch.clear.apply(childBranch, Array.prototype.slice.call(arguments, 1)); } } }; memoize = function memoize(fn) { var argsTree = new MapTree(); function memoized() { var args = Array.prototype.slice.call(arguments); var argNode = args.reduce(function getBranch(parentBranch, arg) { return parentBranch.resolveBranch(arg); }, argsTree); if (argNode.hasValue) { return argNode.value; } var value = fn.apply(null, args); return argNode.setValue(value); } memoized.clear = argsTree.clear.bind(argsTree); return memoized; }; return memoize; } var memoizeWeak; var hasRequiredMemoizeWeak; function requireMemoizeWeak () { if (hasRequiredMemoizeWeak) return memoizeWeak; hasRequiredMemoizeWeak = 1; memoizeWeak = requireMemoize(); return memoizeWeak; } var memoizeWeakExports = requireMemoizeWeak(); var baseMemoize = /*@__PURE__*/getDefaultExportFromCjs(memoizeWeakExports); export { SuperFormError as S, mapErrors as a, baseMemoize as b, schemaShape as c, defaultValues as d, schemaInfo as e, merge as f, superForm as g, mergeDefaults as m, parseRequest as p, replaceInvalidDefaults as r, splitPath as s, traversePath as t }; //# sourceMappingURL=index-DFEd82Gl.js.map