@archduck/gst-forms 0.1.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/forms.js","../src/mountForm.js","../src/utils/defaults.js","../src/utils/formHelpers.js","../src/utils/defaultButtons.js","../src/utils/defaultActions.js","../src/utils/formatting.js","../src/utils/validator.js","../src/utils/security.js","../src/utils/scopedContext.js"],"sourcesContent":["/**\n * Form TLP declarations and schema-aware loaders\n *\n * Declares the top-level properties that make gst-core into a forms engine:\n * fields, actions, meta, layout, etc. Wraps the generic loader with the\n * form schema so callers don't need to pass it.\n *\n * Previously lived in a separate gst-forms package.\n */\n\nimport { createTLPSchema, loadJsonConfigRaw as coreLoadJsonConfig, createLiveConfigRaw as coreCreateLiveConfig, loadLiveConfigRaw as coreLoadLiveConfig } from '@archduck/gst-core'\n\n// ============================================================================\n// TLP Declarations\n// ============================================================================\n\n/**\n * Form-specific TLP declarations.\n *\n * Each entry describes one top-level config property: its dependencies,\n * whether it's a registry (participates in spread/cross-ref), its default\n * value, and any child registries nested inside it.\n */\nexport const FORM_TLP_DECLARATIONS = {\n functions: { registry: true, dependencies: [] },\n actions: {\n dependencies: ['functions'],\n children: {\n buttons: { registry: true },\n hooks: {}\n }\n },\n optionSets: { registry: true, dependencies: [] },\n fields: { registry: true, dependencies: ['functions', 'optionSets', 'actions'] },\n components: { registry: true, dependencies: ['fields'] },\n meta: { dependencies: [] },\n state: { dependencies: [], default: {} },\n layout: { dependencies: ['fields', 'components', 'actions'], default: [] },\n record: { dependencies: [], default: null },\n styles: { dependencies: [], default: null }\n}\n\n/**\n * Pre-built schema from the form declarations.\n * Contains: resolutionOrder, dependencies, registryMapping, validRegistries, getDefault\n */\nexport const formSchema = createTLPSchema(FORM_TLP_DECLARATIONS)\n\n// ============================================================================\n// Schema-aware loaders\n// ============================================================================\n\n/**\n * Load a form configuration with the form schema pre-applied.\n * Drop-in replacement for the raw loadJsonConfig -- no need to pass schema.\n */\nexport async function loadJsonConfig(path, options = {}) {\n return coreLoadJsonConfig(path, { ...options, schema: formSchema })\n}\n\n/**\n * Create a LiveConfig instance with the form schema pre-applied.\n */\nexport function createLiveConfig(options = {}) {\n return coreCreateLiveConfig({ ...options, schema: formSchema })\n}\n\n/**\n * Load and return a LiveConfig in one call, with the form schema pre-applied.\n */\nexport async function loadLiveConfig(path, options = {}) {\n return coreLoadLiveConfig(path, { ...options, schema: formSchema })\n}\n","/**\n * Form-specific mount wrapper\n *\n * Injects form behaviors (dirty tracking, field errors, action execution,\n * lifecycle hooks, hidden field clearing, window.gst) into gst-core's\n * generic mount(). This is where all form-specific semantics live.\n */\n\nimport { mount } from '@archduck/gst-core'\nimport { effect } from '@archduck/gst-core'\nimport { pauseTracking, enableTracking } from '@archduck/gst-core'\nimport { trace, isDebugActive } from '@archduck/gst-core'\nimport { getFieldValue, setFieldValue, clearFieldValue, getRecordPath } from '@archduck/gst-core'\n\n// ============================================================================\n// Hidden field clearing (batched with cascade support)\n// ============================================================================\n\nfunction collectFieldNames(def) {\n const names = new Set()\n function walk(item) {\n if (!item) return\n if (typeof item === 'string') { names.add(item); return }\n if (item.name && !item.rows && !item.layout) names.add(item.name)\n const rows = item.rows || item.layout\n if (Array.isArray(rows)) {\n for (const row of rows) {\n if (Array.isArray(row)) { for (const cell of row) walk(cell) }\n else walk(row)\n }\n }\n if (Array.isArray(item.children)) {\n for (const child of item.children) walk(child)\n }\n }\n walk(def)\n return names\n}\n\nlet pendingClear = null\n\nfunction clearHiddenFieldData(def, store) {\n pauseTracking()\n try {\n const clearEnabled = store.meta?.clearHiddenFields ?? true\n if (!clearEnabled) return\n\n const fieldNames = collectFieldNames(def)\n if (fieldNames.size === 0) return\n\n const protectedFields = new Set([\n ...(store.meta?.systemFields || []),\n ...(store.meta?.readonly || []),\n ])\n\n for (const name of fieldNames) {\n if (protectedFields.has(name)) continue\n const fieldDef = store.registries?.fields?.[name]\n if (fieldDef?.bind) continue // bind fields don't live in record\n const val = getFieldValue(store, name, fieldDef)\n if (val !== undefined && val !== null && val !== '') {\n if (!pendingClear) {\n pendingClear = { store, fields: new Set() }\n queueMicrotask(flushClear)\n }\n pendingClear.fields.add(name)\n }\n }\n } finally {\n enableTracking()\n }\n}\n\nfunction flushClear() {\n const batch = pendingClear\n pendingClear = null\n if (!batch || batch.fields.size === 0) return\n\n const { store } = batch\n const saved = new Map()\n for (const name of batch.fields) {\n const def = store.registries?.fields?.[name]\n saved.set(name, getFieldValue(store, name, def))\n }\n\n for (const name of batch.fields) {\n const def = store.registries?.fields?.[name]\n clearFieldValue(store, name, def)\n }\n\n while (pendingClear && pendingClear.fields.size > 0) {\n const cascade = pendingClear\n pendingClear = null\n for (const name of cascade.fields) {\n const def = store.registries?.fields?.[name]\n if (!saved.has(name)) saved.set(name, getFieldValue(store, name, def))\n clearFieldValue(store, name, def)\n }\n }\n\n const confirmEnabled = store.meta?.confirmClearFields ?? false\n if (confirmEnabled && saved.size > 0) {\n const labels = Array.from(saved.keys()).map(name => {\n const fieldDef = store.registries?.fields?.[name]\n return fieldDef?.label || name\n })\n const confirmed = window.confirm(\n `The following fields will be cleared because their section is now hidden:\\n\\n${labels.join(', ')}\\n\\nDo you want to proceed?`\n )\n if (!confirmed) {\n for (const [name, value] of saved) {\n const def = store.registries?.fields?.[name]\n setFieldValue(store, name, def, value)\n }\n }\n }\n}\n\n// ============================================================================\n// Form stage (this binding for action handlers and hooks)\n// ============================================================================\n\nfunction createFormStage(contextGetter, store) {\n const getContext = typeof contextGetter === 'function'\n ? contextGetter : () => contextGetter\n\n return Object.freeze({\n get isDirty() { return store?.isDirty || false },\n get isSubmitting() { return store?.isSubmitting || false },\n get isDeleted() { return store?.isDeleted || false },\n get record() { return store?.record },\n get data() { return store?.record?.data },\n get meta() { return store?.meta },\n\n getValue(name) {\n const def = store?.registries?.fields?.[name]\n return getFieldValue(store, name, def)\n },\n setValue(name, value) {\n const def = store?.registries?.fields?.[name]\n setFieldValue(store, name, def, value)\n },\n getField(name) { return store?.registries?.fields?.[name] },\n\n getErrors(name) { return store?.fieldErrors?.[name] || [] },\n setError(name, msg) {\n if (store?.fieldErrors) store.fieldErrors[name] = Array.isArray(msg) ? msg : [msg]\n },\n clearErrors(name) {\n if (store?.fieldErrors) store.fieldErrors[name] = []\n },\n get hasErrors() {\n return Object.values(store?.fieldErrors || {}).some(\n errors => Array.isArray(errors) && errors.length > 0\n )\n },\n\n executeAction(actionName, extra) {\n return store?.executeAction?.(actionName, extra)\n },\n\n reset() { getContext()?.form?.reset?.() },\n loadRecord(record) { getContext()?.form?.loadRecord?.(record) },\n })\n}\n\n// ============================================================================\n// Action setup (resolution, hook wrapping, form stage binding)\n// ============================================================================\n\nfunction setupFormActions(store, options) {\n const { actionHandlers = {}, wrapAction, onAction } = options\n\n const cloneData = (data) => JSON.parse(JSON.stringify(data || {}))\n let baseline = cloneData(store.record)\n\n function reset() {\n const baselineData = cloneData(baseline)\n store.record.key = baselineData.key ?? null\n const currentData = store.record.data\n for (const key of Object.keys(currentData)) delete currentData[key]\n for (const [key, value] of Object.entries(baselineData.data || {})) currentData[key] = value\n store.fieldErrors = {}\n store.isDeleted = false\n }\n\n function loadRecord(newRecord) {\n baseline = cloneData(newRecord)\n store.record.key = newRecord.key ?? null\n const currentData = store.record.data\n for (const key of Object.keys(currentData)) delete currentData[key]\n for (const [key, value] of Object.entries(newRecord.data || {})) currentData[key] = value\n store.fieldErrors = {}\n store.isDeleted = false\n }\n\n function buildActionContext(actionName, extra = {}) {\n return {\n action: actionName,\n record: store.record,\n meta: store.meta,\n registries: store.registries,\n functions: store.registries?.functions || {},\n hooks: store.registries?.hooks || store.actions?.hooks || {},\n form: {\n isDirty: store.isDirty,\n isSubmitting: store.isSubmitting,\n isDeleted: store.isDeleted,\n getValue: (name) => {\n const def = store.registries?.fields?.[name]\n return getFieldValue(store, name, def)\n },\n setValue: (name, value) => {\n const def = store.registries?.fields?.[name]\n setFieldValue(store, name, def, value)\n },\n getFieldErrors: (name) => store.fieldErrors?.[name] || [],\n setFieldErrors: (name, errors) => { if (store.fieldErrors) store.fieldErrors[name] = errors },\n setFieldError: (name, msg) => { if (store.fieldErrors) store.fieldErrors[name] = Array.isArray(msg) ? msg : [msg] },\n clearFieldError: (name) => { if (store.fieldErrors) store.fieldErrors[name] = [] },\n reset,\n loadRecord,\n setDeleted: (val) => { store.isDeleted = val },\n isRequired: (name) => !!store.registries?.fields?.[name]?.required,\n isReadonly: (name) => !!store.meta?.readOnly || store.meta?.readonly?.includes(name) || false,\n },\n props: { onAction },\n ...extra,\n }\n }\n\n const formStage = createFormStage(() => buildActionContext('_stage'), store)\n\n // Hook resolver\n function resolveHook(hookName) {\n const hook = store.actions?.hooks?.[hookName]\n if (!hook) {\n if (isDebugActive()) {\n trace('hook', `resolve-hook \"${hookName}\"`, 'not defined', { hookName })\n }\n return null\n }\n const fn = typeof hook === 'function' ? hook\n : (typeof hook === 'string' && hook.startsWith('{{'))\n ? store.registries?.functions?.[hook.slice(2, -2).trim()]\n : null\n if (isDebugActive()) {\n trace('hook', `resolve-hook \"${hookName}\"`, fn ? 'found' : 'MISSING function', {\n hookName,\n hookType: typeof hook,\n hookValue: typeof hook === 'string' ? hook : '(function)',\n resolved: !!fn\n })\n }\n return fn ? fn.bind(formStage) : null\n }\n\n // Store fireHook on the store for use by effects\n store._fireHook = (hookName) => {\n const fn = resolveHook(hookName)\n if (fn) queueMicrotask(() => fn(buildActionContext(hookName)))\n }\n\n // Action executor\n store.executeAction = async (actionName, extra = {}) => {\n let resolvedName = actionName\n if (typeof actionName === 'string' && actionName.startsWith('{{') && actionName.endsWith('}}')) {\n resolvedName = actionName.slice(2, -2).trim()\n }\n\n const context = buildActionContext(resolvedName, extra)\n store.isSubmitting = true\n try {\n const registryFn = store.registries?.functions?.[resolvedName]\n const rawHandler = (typeof registryFn === 'function' ? registryFn : null) ||\n actionHandlers[resolvedName] ||\n (onAction ? async (ctx) => onAction(ctx) : null)\n\n if (!rawHandler) {\n if (isDebugActive()) {\n trace('action', `execute-action \"${resolvedName}\"`, 'NO HANDLER found', {\n actionName: resolvedName,\n inFunctionRegistry: !!registryFn,\n inActionHandlers: !!actionHandlers[resolvedName],\n hasOnAction: !!onAction\n })\n }\n return\n }\n\n if (isDebugActive()) {\n const source = typeof registryFn === 'function' ? 'functions registry'\n : actionHandlers[resolvedName] ? 'actionHandlers' : 'onAction callback'\n trace('action', `execute-action \"${resolvedName}\"`, `dispatching (via ${source})`, {\n actionName: resolvedName, source, extra\n })\n }\n\n const handler = rawHandler.bind(formStage)\n if (wrapAction) {\n const wrapped = wrapAction(resolvedName, handler)\n await wrapped.call(formStage, context, extra)\n } else {\n await handler(context, extra)\n }\n } finally {\n store.isSubmitting = false\n }\n }\n}\n\n// ============================================================================\n// Form effects (dirty tracking, change tracking, error tracking)\n// ============================================================================\n\nfunction dirtyTrackingEffect(store, options) {\n const { onDirtyChange } = options\n const cloneData = (data) => JSON.parse(JSON.stringify(data || {}))\n const baseline = cloneData(store.record)\n\n return effect(() => {\n const currentData = store.record.data\n const baselineData = baseline.data || {}\n\n let dirty = false\n const allKeys = new Set([...Object.keys(currentData), ...Object.keys(baselineData)])\n for (const key of allKeys) {\n const current = currentData[key]\n const base = baselineData[key]\n if (current !== base) {\n if (typeof current === 'object' && typeof base === 'object' &&\n JSON.stringify(current) === JSON.stringify(base)) continue\n dirty = true\n break\n }\n }\n\n if (store.isDirty !== dirty) {\n store.isDirty = dirty\n if (onDirtyChange) queueMicrotask(() => onDirtyChange(dirty))\n store._fireHook?.(dirty ? 'onDirty' : 'onClean')\n }\n })\n}\n\nfunction changeTrackingEffect(store, options) {\n const { onChange } = options\n let skipFirst = true\n\n return effect(() => {\n const data = { ...store.record.data }\n if (skipFirst) { skipFirst = false; return }\n if (onChange) queueMicrotask(() => onChange(store.record))\n store._fireHook?.('onChange')\n })\n}\n\nfunction errorTrackingEffect(store) {\n let hadErrors = false\n\n return effect(() => {\n const hasErrors = Object.values(store.fieldErrors).some(\n errors => Array.isArray(errors) && errors.length > 0\n )\n if (hasErrors !== hadErrors) {\n hadErrors = hasErrors\n store._fireHook?.(hasErrors ? 'onError' : 'onRecover')\n\n // Focus the first errored field so keyboard/screen reader users land there\n if (hasErrors) {\n queueMicrotask(() => {\n const firstErroredName = Object.entries(store.fieldErrors)\n .find(([, errs]) => Array.isArray(errs) && errs.length > 0)?.[0]\n if (!firstErroredName) return\n const el = document.querySelector(\n `[name=\"${CSS.escape(firstErroredName)}\"]`\n )\n if (el && typeof el.focus === 'function') el.focus()\n })\n }\n }\n })\n}\n\n// ============================================================================\n// window.gst introspection\n// ============================================================================\n\nfunction exposeWindowGst(store) {\n if (typeof window === 'undefined') return\n window.gst = {\n meta: store.meta,\n state: store.state,\n registries: store.registries,\n actions: store.actions,\n record: store.record,\n get data() { return store.record?.data },\n get isDirty() { return store.isDirty },\n get isSubmitting() { return store.isSubmitting },\n get errors() { return store.fieldErrors },\n\n getField: (name) => store.registries?.fields?.[name],\n getButton: (name) => store.registries?.buttons?.[name],\n getFunction: (name) => store.registries?.functions?.[name],\n getOptions: (name) => store.registries?.optionSets?.[name],\n\n executeAction: (name, extra) => store.executeAction(name, extra),\n setValue: (name, value) => {\n const def = store.registries?.fields?.[name]\n setFieldValue(store, name, def, value)\n },\n getValue: (name) => {\n const def = store.registries?.fields?.[name]\n return getFieldValue(store, name, def)\n },\n setState: (key, value) => { if (store.state) store.state[key] = value },\n getState: (key) => store.state?.[key],\n\n inspect: (path) => path.split('.').reduce((obj, key) => obj?.[key], window.gst),\n listFields: () => Object.keys(store.registries?.fields || {}),\n listButtons: () => Object.keys(store.registries?.buttons || {}),\n listFunctions: () => Object.keys(store.registries?.functions || {}),\n\n store,\n }\n}\n\nfunction cleanupWindowGst(store) {\n if (typeof window !== 'undefined' && window.gst?.store === store) {\n delete window.gst\n }\n}\n\n// ============================================================================\n// mountForm — the form-specific entry point\n// ============================================================================\n\nexport function mountForm(container, config, options = {}) {\n // Detect __source in registries -- it only works in the JSON loader pipeline,\n // not at mount time. JS configs should use imports instead.\n const regs = config.registries || {}\n for (const [regName, reg] of Object.entries(regs)) {\n if (reg && typeof reg === 'object' && !Array.isArray(reg) && reg.__source) {\n console.error(\n `[gst] \"__source\" found in ${regName} registry but won't be processed at mount time. ` +\n `__source only works in JSON configs loaded via loadJsonConfig(). ` +\n `For JS configs, use imports instead: ${regName}: { ...base.${regName}, ...my${regName[0].toUpperCase() + regName.slice(1)} }`\n )\n }\n }\n\n // Wrap in a <form> element for browser autofill/credential manager support\n const formEl = document.createElement(\"form\")\n formEl.addEventListener(\"submit\", e => e.preventDefault())\n // Copy theme classes so CSS selectors like .gst[class*=\"theme-\"] match\n for (const cls of container.classList) {\n if (cls.startsWith(\"theme-\")) formEl.classList.add(cls)\n }\n\n // Skip link for keyboard users to jump to form actions\n const skipLink = document.createElement(\"a\")\n skipLink.className = \"skip-link\"\n skipLink.href = \"#\"\n skipLink.textContent = \"Skip to form actions\"\n skipLink.addEventListener(\"click\", (e) => {\n e.preventDefault()\n const target = formEl.querySelector(\".form-actions, .group-buttons\")\n if (target) {\n const focusable = target.querySelector(\"button:not(:disabled)\")\n if (focusable) focusable.focus()\n }\n })\n formEl.appendChild(skipLink)\n\n container.appendChild(formEl)\n\n return mount(formEl, config, {\n ...options,\n initialState: {\n fieldErrors: {},\n isDirty: false,\n isSubmitting: false,\n isDeleted: false,\n ...options.initialState,\n },\n onHide: clearHiddenFieldData,\n setupActions: setupFormActions,\n effects: [\n dirtyTrackingEffect,\n changeTrackingEffect,\n errorTrackingEffect,\n ...(options.effects || []),\n ],\n onMount: (store, controller) => {\n // Register dirty-form navigation guard\n const removeDirtyGuard = store.addGuard(() => {\n if (store.isDirty) return 'You have unsaved changes.'\n return true\n })\n\n // Wire browser beforeunload to guard check\n const onBeforeUnload = (e) => {\n const result = controller.checkGuards()\n if (result !== true) {\n e.preventDefault()\n e.returnValue = typeof result === 'string' ? result : ''\n }\n }\n window.addEventListener('beforeunload', onBeforeUnload)\n\n // Form keyboard shortcuts: Ctrl+Enter to save, Escape to cancel\n const onKeyDown = (e) => {\n if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {\n e.preventDefault()\n if (store.executeAction) store.executeAction('save')\n } else if (e.key === 'Escape') {\n // Only fire cancel if focus is inside the form and form is dirty\n if (store.isDirty && formEl.contains(document.activeElement)) {\n e.preventDefault()\n if (store.executeAction) store.executeAction('cancel')\n }\n }\n }\n formEl.addEventListener('keydown', onKeyDown)\n\n // Stash cleanup refs for onUnmount\n store._formGuardCleanup = { removeDirtyGuard, onBeforeUnload, onKeyDown }\n\n store._fireHook?.('onLoad')\n exposeWindowGst(store)\n if (options.onMount) options.onMount(store, controller)\n },\n onUnmount: (store) => {\n if (store._formGuardCleanup) {\n store._formGuardCleanup.removeDirtyGuard()\n window.removeEventListener('beforeunload', store._formGuardCleanup.onBeforeUnload)\n formEl.removeEventListener('keydown', store._formGuardCleanup.onKeyDown)\n delete store._formGuardCleanup\n }\n\n store._fireHook?.('onUnload')\n cleanupWindowGst(store)\n if (options.onUnmount) options.onUnmount(store)\n },\n })\n}\n","/**\n * @module defaults\n * @description Centralized default values for form configuration\n *\n * All meta property defaults are defined here for consistency across\n * the codebase. When checking a meta property, use these defaults\n * rather than hardcoding values.\n *\n * ## Usage\n *\n * ```javascript\n * import { META_DEFAULTS } from '@/utils/defaults'\n *\n * // Use nullish coalescing with defaults\n * const clearHidden = meta.clearHiddenFields ?? META_DEFAULTS.clearHiddenFields\n * ```\n */\n\n/**\n * Default record structure\n * Records have a key (for identifying existing vs new records) and a data object\n */\nexport const DEFAULT_RECORD = {\n key: null,\n data: {},\n}\n\n/**\n * Default values for meta configuration properties\n *\n * @property {boolean} clearHiddenFields - Auto-clear data when fields become hidden (true)\n * @property {boolean} confirmClearFields - Show confirmation before clearing hidden fields (false)\n * @property {boolean} confirmCancel - Show confirmation when canceling with unsaved changes (true)\n * @property {boolean} confirmDelete - Show confirmation before deleting (true)\n * @property {boolean} confirmDuplicate - Show confirmation when duplicating with unsaved changes (true)\n * @property {boolean} confirmNew - Show confirmation when creating new with unsaved changes (true)\n * @property {boolean} preventNavigationWhenDirty - Prevent browser navigation when dirty (true)\n * @property {boolean} submitOnEnter - Submit form when Enter pressed in field (true)\n * @property {boolean} debug - Enable debug logging (false)\n * @property {string} recordKeyPath - Path to key in record object ('key')\n * @property {string} recordDataPath - Path to data in record object ('data')\n * @property {Array} readonly - Readonly field names ([])\n * @property {Array} systemFields - System fields protected from clearing ([])\n */\nexport const META_DEFAULTS = {\n // Field clearing behavior\n clearHiddenFields: true,\n confirmClearFields: false,\n\n // Action confirmations\n confirmCancel: true,\n confirmDelete: true,\n confirmDuplicate: true,\n confirmNew: true,\n\n // Navigation\n preventNavigationWhenDirty: true,\n\n // Keyboard\n submitOnEnter: true,\n\n // Debug\n debug: false,\n\n // Record structure\n recordKeyPath: 'key',\n recordDataPath: 'data',\n\n // Field arrays (empty by default)\n readonly: [],\n systemFields: [],\n}\n\n/**\n * Apply defaults to a meta object\n * Only fills in missing properties, does not override existing values\n *\n * @param {Object} meta - The meta configuration object\n * @returns {Object} Meta with defaults applied\n */\nexport function applyMetaDefaults(meta = {}) {\n return {\n ...META_DEFAULTS,\n ...meta,\n }\n}\n","// src/components/utils/formHelpers.js\n// Consolidated form helper utilities\n\nimport { bindFunctions, createStage } from \"@archduck/gst-core\"\nimport { META_DEFAULTS } from \"./defaults.js\"\n\n// ============================================================================\n// RECORD DATA ACCESS\n// ============================================================================\n\n/**\n * Get the data object from a record based on meta.recordDataPath\n * @param {Object} record - The record object\n * @param {Object} meta - Form meta configuration\n * @returns {Object} The record data\n */\nexport function getRecordData(record, meta) {\n if (!record) return {}\n const path = meta?.recordDataPath\n // Empty string means use record directly (flat record structure)\n if (path === '') {\n return record\n }\n // Use default if path not specified\n const dataPath = path ?? META_DEFAULTS.recordDataPath\n return record[dataPath] ?? {}\n}\n\n/**\n * Set data on a record based on meta.recordDataPath\n * Returns a new record object with updated data\n * @param {Object} record - The record object\n * @param {Object} meta - Form meta configuration\n * @param {Object} newData - The new data to set\n * @returns {Object} New record with updated data\n */\nexport function setRecordData(record, meta, newData) {\n if (!record) return { [META_DEFAULTS.recordDataPath]: newData }\n const path = meta?.recordDataPath\n // Empty string means use record directly (flat record structure)\n if (path === '') {\n return { ...record, ...newData }\n }\n // Use default if path not specified\n const dataPath = path ?? META_DEFAULTS.recordDataPath\n return { ...record, [dataPath]: newData }\n}\n\n/**\n * Get the key from a record based on meta.recordKeyPath\n * @param {Object} record - The record object\n * @param {Object} meta - Form meta configuration\n * @returns {*} The record key (null/undefined for new records)\n */\nexport function getRecordKey(record, meta) {\n if (!record) return null\n const path = meta?.recordKeyPath\n // Empty string means no key field (always treated as new)\n if (path === '') {\n return null\n }\n // Use default if path not specified\n const keyPath = path ?? META_DEFAULTS.recordKeyPath\n return record[keyPath] ?? null\n}\n\n/**\n * Initialize missing fields in record data with appropriate defaults\n * Walks through layout and ensures all fields exist with sensible default values\n * @param {Object} record - The record object\n * @param {Object} meta - Form meta configuration\n * @param {Array} layout - Form layout (groups with rows)\n * @param {Object} fieldRegistry - Field definitions registry\n * @returns {Object} Record with all fields initialized\n */\nexport function initializeRecordFields(record, meta, layout, fieldRegistry = {}) {\n if (!layout || layout.length === 0) return record\n\n const currentData = getRecordData(record, meta)\n const initializedData = { ...currentData }\n\n // Helper to get default value for a field type\n const getDefaultValue = (fieldDef) => {\n const type = fieldDef?.type || 'text'\n const component = fieldDef?.component\n\n // If field has explicit value property, use it\n if (fieldDef && 'value' in fieldDef) {\n return fieldDef.value\n }\n\n // Checkbox defaults to false\n if (type === 'checkbox' || component === 'Checkbox') {\n return false\n }\n\n // Array fields default to empty array\n if (type === 'array' || component === 'ArrayField') {\n return []\n }\n\n // Number fields default to empty string (controlled input requirement)\n if (type === 'number') {\n return ''\n }\n\n // Everything else defaults to empty string\n return ''\n }\n\n // Walk through layout to find all field names\n const extractFieldNames = (element) => {\n if (!element) return []\n\n const fieldNames = []\n\n // Handle rows array\n if (Array.isArray(element.rows)) {\n element.rows.forEach(row => {\n if (Array.isArray(row)) {\n row.forEach(fieldName => {\n if (typeof fieldName === 'string') {\n fieldNames.push(fieldName)\n }\n })\n }\n })\n }\n\n return fieldNames\n }\n\n // Process each group in layout\n layout.forEach(group => {\n const fieldNames = extractFieldNames(group)\n\n fieldNames.forEach(fieldName => {\n // Only initialize if field doesn't already exist\n if (!(fieldName in initializedData)) {\n const fieldDef = fieldRegistry[fieldName]\n initializedData[fieldName] = getDefaultValue(fieldDef)\n }\n })\n })\n\n return setRecordData(record, meta, initializedData)\n}\n\n// ============================================================================\n// ERROR MESSAGE FORMATTING\n// ============================================================================\n\n/**\n * Format a runtime error with context and suggestion\n */\nexport function runtimeError(message, context = {}) {\n const { path, suggestion, details } = context\n const parts = ['šŸ”“ Runtime Error:', message]\n\n if (path) parts.push(`\\n Path: ${path}`)\n if (details) parts.push(`\\n Details: ${details}`)\n if (suggestion) parts.push(`\\n šŸ’” ${suggestion}`)\n\n return parts.join('')\n}\n\n/**\n * Format a runtime warning with context and suggestion\n */\nexport function runtimeWarning(message, context = {}) {\n const { path, suggestion, details, available } = context\n const parts = ['āš ļø ', message]\n\n if (path) parts.push(`\\n Path: ${path}`)\n if (details) parts.push(`\\n Details: ${details}`)\n if (available?.length > 0) parts.push(`\\n Available: ${available.join(', ')}`)\n if (suggestion) parts.push(`\\n šŸ’” ${suggestion}`)\n\n return parts.join('')\n}\n\n/**\n * Format missing reference warning\n */\nexport function missingReference(type, name, context = {}) {\n const { path, available = [] } = context\n\n return runtimeWarning(`${type} \"${name}\" not found`, {\n path,\n available,\n suggestion: available.length > 0\n ? `Check spelling or add \"${name}\" to your ${type.toLowerCase()} registry`\n : `No ${type.toLowerCase()} are registered. Add ${type.toLowerCase()} to your registries or load from file`\n })\n}\n\n/**\n * Format function evaluation error\n */\nexport function functionError(functionName, property, error, context = {}) {\n return runtimeError(`Error evaluating ${property} function \"${functionName}\"`, {\n ...context,\n details: error.message,\n suggestion: 'Check function implementation for runtime errors'\n })\n}\n\n/**\n * Format missing handler warning\n */\nexport function missingHandler(handlerName, action) {\n return runtimeWarning(`No ${handlerName} handler provided`, {\n path: `props.${handlerName}`,\n suggestion: `Pass ${handlerName} prop to Form component to handle ${action} action`\n })\n}\n\n/**\n * Format parse/format error\n */\nexport function transformError(operation, fieldName, error, context = {}) {\n return runtimeError(`Error ${operation} field \"${fieldName}\"`, {\n ...context,\n details: error.message,\n suggestion: `Check ${operation === 'parsing' ? 'parse' : 'format'} function for field \"${fieldName}\"`\n })\n}\n\n// ============================================================================\n// DATA ATTRIBUTE GENERATION\n// ============================================================================\n\n/**\n * Generate field data attributes for state hooks\n */\nexport function getFieldDataAttributes(state, fieldName, fieldType) {\n const {\n isDirty = false,\n isTouched = false,\n isFocused = false,\n isDisabled = false,\n isReadonly = false,\n isRequired = false,\n isComputed = false,\n hasErrors = false,\n } = state\n\n return {\n 'data-field': fieldName,\n 'data-type': fieldType || 'text',\n 'data-dirty': isDirty.toString(),\n 'data-touched': isTouched.toString(),\n 'data-focused': isFocused.toString(),\n 'data-disabled': isDisabled.toString(),\n 'data-readonly': isReadonly.toString(),\n 'data-required': isRequired.toString(),\n 'data-computed': isComputed.toString(),\n 'data-valid': (!hasErrors).toString(),\n 'data-invalid': hasErrors.toString(),\n 'data-has-error': hasErrors.toString(),\n }\n}\n\n/**\n * Generate button data attributes for state hooks\n */\nexport function getButtonDataAttributes(buttonName, action, variant, isLoading, isDisabled) {\n return {\n 'data-button': buttonName || action || 'button',\n 'data-action': action || '',\n 'data-variant': variant || 'secondary',\n 'data-loading': isLoading.toString(),\n 'data-disabled': isDisabled.toString(),\n }\n}\n\n/**\n * Generate group/container data attributes\n */\nexport function getGroupDataAttributes(groupName, isVisible) {\n return {\n 'data-group': groupName || 'group',\n 'data-visible': isVisible.toString(),\n }\n}\n\n// ============================================================================\n// VISIBILITY EVALUATION\n// ============================================================================\n\n/**\n * Evaluate visibility of an element based on show property\n *\n * @param {Object} element - The element (group, field, etc.) to check\n * @param {Object} context - The context object with record, registries, functions, etc.\n * @param {string} elementName - Name for stage creation (optional)\n * @returns {boolean} - Whether the element is visible\n */\nexport function evaluateVisibility(element, context, elementName = 'element') {\n if (!element) return true\n\n if (element.show !== undefined) {\n const showValue = element.show\n const functions = context.functions || context.registries?.functions || {}\n\n // Handle {{functionName}} string reference\n if (typeof showValue === 'string' && showValue.startsWith('{{') && showValue.endsWith('}}')) {\n const funcName = showValue.slice(2, -2).trim()\n const func = functions[funcName]\n if (func && typeof func === 'function') {\n const stage = createStage(element, () => context, elementName)\n return func.call(stage, context) !== false\n }\n return !!showValue\n }\n // Handle direct function\n if (typeof showValue === 'function') {\n const stage = createStage(element, () => context, elementName)\n return showValue.call(stage, context) !== false\n }\n // Handle boolean or other values\n return !!showValue\n }\n\n return true\n}\n\n// ============================================================================\n// STRING UTILITIES\n// ============================================================================\n\n/**\n * Convert text to URL-safe slug\n * @param {string} text - Text to slugify\n * @returns {string} URL-safe slug\n */\nexport function slugify(text) {\n if (!text) return \"\"\n return text.toString().toLowerCase()\n .trim()\n .replace(/\\s+/g, '-') // Replace spaces with -\n .replace(/[^\\w\\-]+/g, '') // Remove all non-word chars\n .replace(/\\-\\-+/g, '-') // Replace multiple - with single -\n}\n\n// ============================================================================\n// FIELD DEPENDENCY TRACKING\n// ============================================================================\n\n/**\n * Get fields that should be cleared when groups become hidden\n */\nexport function getFieldsToClear(\n layout,\n record,\n registries,\n config,\n context,\n previousVisibility = {}\n) {\n // Guard: return empty set if config is not ready\n if (!config) return new Set()\n\n const fieldsToClear = new Set()\n const protectedFields = new Set([\n ...(config.systemFields || []),\n ...(config.readonly || [])\n ])\n\n const ctx = context || { record, registries, config }\n\n layout.forEach((group, idx) => {\n const boundGroup = bindFunctions(\n group,\n ctx.functions || ctx.registries?.functions || {},\n ctx.registries?.optionSets || {},\n () => ctx\n )\n\n // Use shared evaluateVisibility utility for consistency\n const currentlyVisible = evaluateVisibility(\n boundGroup,\n ctx,\n boundGroup.name || `group[${idx}]`\n )\n\n const wasVisible = previousVisibility[idx] === true\n\n if (wasVisible && !currentlyVisible && group.rows) {\n for (const row of group.rows) {\n for (const fieldRef of row) {\n const fieldName = typeof fieldRef === \"string\" ? fieldRef : fieldRef.name\n if (!protectedFields.has(fieldName)) {\n fieldsToClear.add(fieldName)\n }\n }\n }\n }\n })\n\n return fieldsToClear\n}","/**\n * @module defaultButtons\n * @description Default button definitions for standard form operations.\n *\n * Five states derived from three facts (hasKey, isDirty, isDeleted):\n *\n * Loaded: hasKey, !isDirty, !isDeleted\n * Editing: hasKey, isDirty, !isDeleted\n * New: !hasKey, !isDirty, !isDeleted\n * Creating: !hasKey, isDirty, !isDeleted\n * Deleted: hasKey, !isDirty, isDeleted\n *\n * Button visibility and labels:\n *\n * | Button | Loaded | Editing | New | Creating | Deleted |\n * |----------|----------|-----------|--------|----------|-------------|\n * | New | New | New | - | New | - |\n * | Duplicate| Duplicate| Duplicate | - | - | - |\n * | Delete | Delete | Delete | - | - | - |\n * | Cancel | - | Cancel | - | Cancel | - |\n * | Save | Save | Save | Create | Create | Undo Delete |\n */\n\nimport { getRecordKey } from './formHelpers.js'\n\n// ============================================================================\n// State reader\n// ============================================================================\n\nfunction getState(context) {\n const key = getRecordKey(context.record, context.meta)\n return {\n hasKey: key != null && key !== '',\n isDirty: context.form?.isDirty ?? false,\n isDeleted: context.form?.isDeleted ?? false,\n }\n}\n\n// ============================================================================\n// Show functions\n// ============================================================================\n\nexport function showNew(context) {\n const { hasKey, isDirty, isDeleted } = getState(context)\n if (isDeleted) return false\n return hasKey || isDirty\n}\n\nexport function showDuplicate(context) {\n const { hasKey, isDeleted } = getState(context)\n return hasKey && !isDeleted\n}\n\nexport function showDelete(context) {\n const { hasKey, isDeleted } = getState(context)\n return hasKey && !isDeleted\n}\n\nexport function showCancel(context) {\n const { isDirty, isDeleted } = getState(context)\n if (isDeleted) return false\n return isDirty\n}\n\nexport function showSave() {\n return true\n}\n\n// ============================================================================\n// Label functions\n// ============================================================================\n\nexport function saveLabel(context) {\n const { hasKey, isDirty, isDeleted } = getState(context)\n if (isDeleted) return 'Undo Delete'\n if (!hasKey) return 'Create'\n return 'Save'\n}\n\nexport function cancelLabel() {\n return 'Cancel'\n}\n\n// ============================================================================\n// Core button functions registry\n// ============================================================================\n\nexport const coreButtonFunctions = {\n showNew,\n showDuplicate,\n showDelete,\n showCancel,\n showSave,\n saveLabel,\n cancelLabel,\n}\n\n// ============================================================================\n// Default button definitions\n// ============================================================================\n\nexport const defaultButtons = {\n save: {\n name: 'save',\n label: '{{saveLabel}}',\n action: 'save',\n variant: 'primary',\n show: '{{showSave}}'\n },\n\n cancel: {\n name: 'cancel',\n label: 'Cancel',\n action: 'cancel',\n variant: 'secondary',\n show: '{{showCancel}}'\n },\n\n delete: {\n name: 'delete',\n label: 'Delete',\n action: 'delete',\n variant: 'danger',\n show: '{{showDelete}}',\n confirm: 'Are you sure you want to delete this record?'\n },\n\n new: {\n name: 'new',\n label: 'New',\n action: 'new',\n variant: 'primary',\n show: '{{showNew}}'\n },\n\n duplicate: {\n name: 'duplicate',\n label: 'Duplicate',\n action: 'duplicate',\n variant: 'secondary',\n show: '{{showDuplicate}}'\n },\n}\n","/**\n * @module defaultActions\n * @description Built-in action handlers for standard form operations\n *\n * GST provides default implementations for common form actions (save, delete,\n * cancel, new, duplicate). These handlers provide standard UX patterns\n * like confirmation dialogs and dirty-state checks.\n *\n * ## Hook System\n *\n * Every action automatically gets before/after hooks:\n * - `beforeSave` / `afterSave`\n * - `beforeDelete` / `afterDelete`\n * - `beforeCancel` / `afterCancel`\n * - `beforeNew` / `afterNew`\n * - `beforeDuplicate` / `afterDuplicate`\n *\n * The save action also triggers more specific hooks:\n * - `beforeCreate` / `afterCreate` (when record.key is empty)\n * - `beforeUpdate` / `afterUpdate` (when record.key exists)\n *\n * ## Custom Actions\n *\n * Any custom action automatically gets hooks too:\n * ```javascript\n * // Button with action: \"slapNazi\"\n * // Automatically triggers: beforeSlapNazi, afterSlapNazi\n * ```\n *\n * ## Handler Resolution Priority\n *\n * When an action is triggered, the handler is resolved in this order:\n * 1. Specific prop handler (e.g., `onSave` prop)\n * 2. Generic `onAction` prop\n * 3. Function from functions registry (e.g., `save` function)\n *\n * ## Confirmation Dialogs\n *\n * Confirmations can be customized via meta properties:\n * ```json\n * {\n * \"confirmDelete\": \"Really delete this patient?\",\n * \"confirmCancel\": false, // Disable confirmation\n * \"confirmNew\": true // Use default message\n * }\n * ```\n *\n * @see {@link executeHooks} for hook execution\n * @see {@link wrapWithHooks} for wrapping custom actions\n * @see {@link defaultActions} for built-in action implementations\n */\n\nimport { createStage, logger } from \"@archduck/gst-core\"\nimport { missingReference, runtimeError } from \"./formHelpers.js\"\nimport { META_DEFAULTS } from \"./defaults.js\"\n\n/**\n * Execute hooks by name. Looks up hook references in context.hooks[hookName]\n * and resolves them from the functions registry.\n *\n * @param {string} hookName - Name of the hook (e.g., \"beforeSave\", \"afterDelete\")\n * @param {object} context - Form context with hooks and functions\n * @param {any} data - Data to pass to hook functions\n * @returns {Promise<boolean>} - false if any hook cancelled, true otherwise\n */\nexport async function executeHooks(hookName, context, data) {\n const hooks = context.hooks?.[hookName]\n if (!hooks) return true\n\n const hookArray = Array.isArray(hooks) ? hooks : [hooks]\n\n for (const hookRef of hookArray) {\n // Strip {{ }} and resolve from functions registry\n const funcName = hookRef.replace(/{{|}}/g, \"\").trim()\n const hookFn = context.functions[funcName]\n\n if (!hookFn) {\n logger.warn(missingReference('Hook function', funcName, {\n path: `hooks.${hookName}`,\n available: Object.keys(context.functions)\n }))\n continue\n }\n\n try {\n const result = await hookFn(context, data)\n if (result === false) {\n return false // Cancel action\n }\n } catch (err) {\n logger.error(runtimeError(`Hook \"${funcName}\" failed`, {\n path: `hooks.${hookName}`,\n details: err.message,\n suggestion: 'Check hook function implementation for errors'\n }))\n return false\n }\n }\n\n return true\n}\n\n/**\n * Capitalize first letter of a string (for hook name generation)\n */\nfunction capitalize(str) {\n if (!str) return ''\n return str.charAt(0).toUpperCase() + str.slice(1)\n}\n\n/**\n * Wrap an action handler with automatic before/after hook execution.\n * This allows any action (not just default ones) to have hooks.\n *\n * @param {string} actionName - Name of the action (e.g., \"save\", \"slapNazi\")\n * @param {function} handler - The action handler function\n * @returns {function} - Wrapped handler that executes hooks\n */\n/**\n * Check if a value is empty (undefined, null, empty string, empty array).\n */\nfunction isEmpty(value) {\n return value === undefined || value === null || value === '' ||\n (Array.isArray(value) && value.length === 0)\n}\n\n/**\n * Validate all required fields. Sets errors on empty required fields.\n *\n * Handles two cases:\n * - Leaf fields: required: true means always required\n * - Constructions (fields with a `fields` sub-block):\n * - If the construction has required: true, its required sub-fields are always enforced\n * - If the construction does NOT have required: true, its required sub-fields are\n * contingently required: only enforced when any sub-field has data\n *\n * Returns true if all valid, false if any empty.\n */\nfunction validateRequiredFields(context) {\n const fields = context.registries?.fields || {}\n const data = context.record?.data || {}\n let valid = true\n\n for (const [name, def] of Object.entries(fields)) {\n if (!def || typeof def !== 'object') continue\n\n // Construction: has a nested fields block\n if (def.fields && typeof def.fields === 'object') {\n const subFields = def.fields\n const constructionRequired = !!def.required\n\n // Collect sub-fields that have required: true (set via bulkApply or directly)\n const requiredSubNames = Object.entries(subFields)\n .filter(([, subDef]) => subDef && typeof subDef === 'object' && subDef.required)\n .map(([subName]) => subName)\n\n // Check if any sub-field has data\n const hasAnyData = !constructionRequired && Object.keys(subFields).some(\n subName => !isEmpty(data[subName])\n )\n\n // If construction is required, always validate sub-fields\n // If not required, only validate when any sub-field has data (contingent)\n if (constructionRequired || hasAnyData) {\n for (const subName of requiredSubNames) {\n if (isEmpty(data[subName])) {\n context.form.setFieldErrors(subName, ['Required'])\n valid = false\n }\n }\n }\n continue\n }\n\n // Leaf field: simple required check\n if (!def.required) continue\n if (isEmpty(data[name])) {\n context.form.setFieldErrors(name, ['Required'])\n valid = false\n }\n }\n\n return valid\n}\n\nexport function wrapWithHooks(actionName, handler) {\n return async function wrappedAction(context, data) {\n const record = context.record\n\n // Validate required fields before save-type actions\n if (actionName === 'save' || actionName === 'create' || actionName === 'update') {\n if (!validateRequiredFields(context)) return\n }\n\n // Execute before hook (e.g., beforeSave, beforeSlapNazi)\n const beforeHook = `before${capitalize(actionName)}`\n const canProceed = await executeHooks(beforeHook, context, record)\n if (!canProceed) return\n\n // Execute the actual action\n const result = await handler(context, data)\n\n // Execute after hook (e.g., afterSave, afterSlapNazi)\n const afterHook = `after${capitalize(actionName)}`\n await executeHooks(afterHook, context, record)\n\n return result\n }\n}\n\n/**\n * Resolve the handler for an action.\n * Priority: specific prop (onSave) > generic onAction > functions registry\n */\nfunction resolveHandler(context, actionName) {\n // 1. Check for specific prop handler (onSave, onDelete, etc.)\n const propName = `on${capitalize(actionName)}`\n const specificHandler = context.props?.[propName]\n if (specificHandler) return specificHandler\n\n // 2. Check for generic onAction handler\n if (context.props?.onAction) return context.props.onAction\n\n // 3. Check functions registry\n return context.functions?.[actionName]\n}\n\n/**\n * Built-in action implementations for standard form operations\n *\n * Each action:\n * - Provides standard UX (confirmations, dirty checks)\n * - Delegates to a resolved handler (specific prop → onAction → functions registry)\n * - Gets automatic before/after hooks via wrapWithHooks\n *\n * @type {Object.<string, function>}\n * @property {function} save - Save action with create/update hooks\n * @property {function} cancel - Cancel with dirty confirmation and form reset\n * @property {function} delete - Delete with confirmation\n * @property {function} duplicate - Duplicate with dirty confirmation\n * @property {function} new - New record with dirty confirmation\n *\n * @example\n * // In a form config\n * {\n * \"buttonSet\": [\"save\", \"cancel\", \"delete\"],\n * \"hooks\": {\n * \"beforeSave\": \"{{validateForm}}\",\n * \"afterDelete\": \"{{navigateToList}}\"\n * }\n * }\n *\n * @example\n * // Custom save handler via onAction prop\n * <Form\n * onAction={async (context) => {\n * if (context.action === 'save') {\n * await api.savePatient(context.record.data)\n * }\n * }}\n * />\n */\nexport const defaultActions = {\n async save(context, buttonDef) {\n const { record, meta, form } = context\n const hasKey = !!record.key\n const isUndoDelete = form?.isDeleted\n\n // Clear isDeleted before save (undo delete = re-save)\n if (isUndoDelete && form?.setDeleted) {\n form.setDeleted(false)\n }\n\n // For save, we also want to call the more specific create/update hooks\n // These are called in addition to beforeSave/afterSave (handled by wrapper)\n const specificBeforeHook = hasKey ? \"beforeUpdate\" : \"beforeCreate\"\n const canProceed = await executeHooks(specificBeforeHook, context, record)\n if (!canProceed) return\n\n // Call the handler\n const handler = resolveHandler(context, 'save')\n if (handler) {\n await handler(context)\n }\n\n // Call the specific after hook\n const specificAfterHook = hasKey ? \"afterUpdate\" : \"afterCreate\"\n await executeHooks(specificAfterHook, context, record)\n },\n\n async cancel(context, buttonDef) {\n const { meta, form } = context\n\n // Check if form is dirty and confirmation is enabled (default: true)\n const confirmCancel = meta?.confirmCancel ?? META_DEFAULTS.confirmCancel\n if (form.isDirty && confirmCancel) {\n const message =\n typeof confirmCancel === \"string\"\n ? confirmCancel\n : \"You have unsaved changes. Are you sure you want to cancel?\"\n\n if (!confirm(message)) return\n }\n\n // Always reset the form on cancel\n if (form?.reset) {\n form.reset()\n }\n\n // Then call the handler if provided (e.g., navigate away)\n const handler = resolveHandler(context, 'cancel')\n if (handler) {\n await handler(context)\n }\n },\n\n async delete(context, buttonDef) {\n const { meta, form } = context\n\n // Check if confirmation is enabled (default: true)\n const confirmDelete = meta?.confirmDelete ?? META_DEFAULTS.confirmDelete\n if (confirmDelete) {\n const message =\n typeof confirmDelete === \"string\"\n ? confirmDelete\n : \"Are you sure you want to delete this record?\"\n\n if (!confirm(message)) return\n }\n\n // Call the handler (should call the server API)\n const handler = resolveHandler(context, 'delete')\n if (handler) {\n await handler(context)\n }\n\n // Mark as deleted - form becomes read-only with undo option\n if (form?.setDeleted) {\n form.setDeleted(true)\n }\n },\n\n async duplicate(context, buttonDef) {\n const { meta, form, record } = context\n\n // Check if form is dirty and confirmation is enabled (default: true)\n const confirmDuplicate = meta?.confirmDuplicate ?? META_DEFAULTS.confirmDuplicate\n if (form.isDirty && confirmDuplicate) {\n const message =\n typeof confirmDuplicate === \"string\"\n ? confirmDuplicate\n : \"You have unsaved changes. Duplicating will discard them. Continue?\"\n\n if (!confirm(message)) return\n }\n\n // Load as new record: keep current data but clear the key\n // This becomes the new baseline (cancel reverts to this state)\n form.loadRecord({ key: null, data: { ...record.data } })\n\n // Then call handler for additional logic (e.g. navigation)\n const handler = resolveHandler(context, 'duplicate')\n if (handler) {\n await handler(context)\n }\n },\n\n async new(context, buttonDef) {\n const { meta, form } = context\n\n // Check if form is dirty and confirmation is enabled (default: true)\n const confirmNew = meta?.confirmNew ?? META_DEFAULTS.confirmNew\n if (form.isDirty && confirmNew) {\n const message =\n typeof confirmNew === \"string\"\n ? confirmNew\n : \"You have unsaved changes. Creating new will discard them. Continue?\"\n\n if (!confirm(message)) return\n }\n\n // Load as new blank record with config defaults\n // This becomes the new baseline (cancel reverts to this state)\n const defaults = meta?.defaultRecord?.data || {}\n form.loadRecord({ key: null, data: { ...defaults } })\n\n // Then call handler for additional logic (e.g. navigation)\n const handler = resolveHandler(context, 'new')\n if (handler) {\n await handler(context)\n }\n },\n}\n","/**\n * Pure formatting and masking utilities\n *\n * Extracted from the former useFieldFormatting hook.\n * No framework dependencies.\n */\n\nimport { logger, createStage, isEventKey } from '@archduck/gst-core'\n\n/**\n * Detect mask type from format pattern\n */\nexport function detectMaskType(mask) {\n if (!mask || typeof mask !== 'string') return null\n\n const patterns = {\n phone: /^\\([0-9]{3}\\) [0-9]{3}-[0-9]{4}$/,\n ssn: /^[0-9]{3}-[0-9]{2}-[0-9]{4}$/,\n ein: /^[0-9]{2}-[0-9]{7}$/,\n creditCard: /^[0-9]{4} [0-9]{4} [0-9]{4} [0-9]{4}$/,\n date: /^(0[1-9]|1[0-2])\\/(0[1-9]|[12][0-9]|3[01])\\/[0-9]{4}$/,\n zip: /^[0-9]{5}$/,\n zipPlus4: /^[0-9]{5}-[0-9]{4}$/,\n }\n\n for (const [type, pattern] of Object.entries(patterns)) {\n if (pattern.test(mask.replace(/[#9]/g, '0'))) {\n return type\n }\n }\n\n return 'custom'\n}\n\n/**\n * Apply mask to value -- walks the mask pattern and builds the result.\n * Mask characters: # or 9 = digit slot, A = letter slot\n * Anything else is a literal that gets auto-inserted.\n */\nexport function applyMask(value, mask) {\n if (!value || !mask) return value\n\n const rawChars = []\n for (const ch of value) {\n if (/\\d/.test(ch) || /[a-zA-Z]/.test(ch)) rawChars.push(ch)\n }\n\n let result = ''\n let charIndex = 0\n\n for (let i = 0; i < mask.length && charIndex < rawChars.length; i++) {\n const maskChar = mask[i]\n\n if (maskChar === '#' || maskChar === '9') {\n while (charIndex < rawChars.length && !/\\d/.test(rawChars[charIndex])) charIndex++\n if (charIndex >= rawChars.length) break\n result += rawChars[charIndex++]\n } else if (maskChar === 'A') {\n while (charIndex < rawChars.length && !/[a-zA-Z]/.test(rawChars[charIndex])) charIndex++\n if (charIndex >= rawChars.length) break\n result += rawChars[charIndex++].toUpperCase()\n } else {\n result += maskChar\n }\n }\n\n return result\n}\n\n/**\n * Resolve a dynamic property value (pure function version)\n *\n * If the value is a {{funcName}} string, look up the function and call it.\n * Otherwise return the static value as-is.\n *\n * @param {string} propName - Property name (for error messages, event handler detection)\n * @param {*} propValue - The value to resolve\n * @param {Object} context - Form context with functions, record, etc.\n * @param {Object} def - Element definition (for stage creation)\n * @returns {*} Resolved value\n */\nexport function resolveProp(propName, propValue, context, def) {\n if (propValue === undefined || propValue === null) return propValue\n if (typeof propValue === 'function') return propValue\n if (typeof propValue !== 'string' || !propValue.startsWith('{{')) return propValue\n\n const funcName = propValue.slice(2, -2).trim()\n const func = context?.functions?.[funcName]\n if (!func) {\n logger.warn(`Function \"${funcName}\" not found for property \"${propName}\"`)\n return undefined\n }\n\n const stage = createStage(def, () => context, def?.name)\n\n // Event handlers get wrapped, not called\n if (isEventKey(propName)) {\n return (event) => {\n try {\n return func.call(stage, context, event)\n } catch (error) {\n logger.error(`Error in event handler ${propName} with function ${funcName}:`, error)\n return undefined\n }\n }\n }\n\n try {\n return func.call(stage, context, null)\n } catch (error) {\n logger.error(`Error resolving ${propName} with function ${funcName}:`, error)\n return undefined\n }\n}\n\n/**\n * Check visibility based on show property (pure function version)\n */\nexport function resolveVisibility(def, context) {\n if (!def) return true\n if (def.show !== undefined) {\n return !!resolveProp('show', def.show, context, def)\n }\n return true\n}\n\n/**\n * Format a value for display using a format function\n */\nexport function formatValue(value, def, context) {\n if (!def?.format) return value\n\n let formatter\n if (typeof def.format === 'function') {\n formatter = def.format\n } else if (typeof def.format === 'string') {\n const funcName = def.format.replace(/^\\{\\{|\\}\\}$/g, '')\n formatter = context?.functions?.[funcName]\n }\n\n if (!formatter) return value\n\n try {\n const stage = createStage(def, () => context, def.name)\n const result = formatter.call(stage, context, null)\n return result !== undefined ? result : value\n } catch (error) {\n logger.error(`Format error for field ${def.name}:`, error)\n return value\n }\n}\n\n/**\n * Parse a value for storage using a parse function\n */\nexport function parseValue(value, def, context) {\n if (!def?.parse) return value\n\n const parser = typeof def.parse === 'function'\n ? def.parse\n : context?.functions?.[def.parse]\n\n if (!parser) return value\n\n try {\n const stage = createStage(def, () => context, def.name)\n const tempStage = { ...stage, value }\n const result = parser.call(tempStage, context, null)\n return result !== undefined ? result : value\n } catch (error) {\n logger.error(`Parse error for field ${def.name}:`, error)\n return value\n }\n}\n\n/**\n * Separate props into wrapper and input categories\n *\n * Wrapper props: className, style, data-* attributes\n * Input props: everything else that's DOM-safe\n */\nconst INTERNAL_PROPS = new Set([\n 'def', 'name', 'show', 'options', 'fields', 'layout', 'rows',\n 'validate', 'validator', 'format', 'formatter', 'parse', 'parser', 'mask',\n 'component', 'action', 'handler', '__source', 'transform',\n 'dependencies', 'triggers', 'effects', 'rules', 'meta',\n 'itemlabel', 'itemlayout', 'defaultitem',\n 'buttons', 'items', 'legend', 'innertext',\n 'group', 'title', 'description',\n 'confirm', 'variant', 'label', 'hint', 'clearable',\n '_componentName', '_component', '_adapter'\n])\n\nexport function separateProps(props) {\n const wrapperProps = {}\n const inputProps = {}\n\n for (const [key, value] of Object.entries(props)) {\n if (INTERNAL_PROPS.has(key)) continue\n if (Array.isArray(value)) continue\n if (value !== null && typeof value === 'object' && key !== 'style' && !key.startsWith('data-')) continue\n\n if (key === 'style' && typeof value === 'string') continue\n if (key === 'class' || key === 'style' || key.startsWith('data-')) {\n wrapperProps[key] = value\n } else {\n inputProps[key] = value\n }\n }\n\n return { wrapperProps, inputProps }\n}\n","// src/utils/validator.js\n\n/**\n * Validates form configuration and registries for common issues.\n * Returns array of validation errors with actionable messages.\n *\n * @param {Object} config - Form configuration { meta, layout, registries }\n * @returns {Array} Array of error objects { type, path, message, suggestion, severity }\n */\nexport function validateConfig({ meta = {}, layout = [], registries = {} }) {\n const errors = []\n const { fields = {}, buttons = {}, optionSets = {}, functions = {} } = registries\n\n // Validate function references throughout config\n validateFunctionReferences(errors, meta, layout, fields, buttons, functions)\n\n // Validate spread references\n validateSpreadReferences(errors, fields, buttons)\n\n // Validate layout field references\n validateLayoutReferences(errors, layout, fields)\n\n // Validate options references (only for fields used in the layout)\n const layoutFields = collectLayoutFieldNames(layout)\n validateOptionsReferences(errors, fields, optionSets, layoutFields)\n\n // Detect arrow functions in wrapper format\n detectArrowFunctions(errors, functions)\n\n // Check for component/type mismatches\n validateComponentTypes(errors, fields)\n\n return errors\n}\n\n/**\n * Find all function references ({{functionName}}) in a value\n */\nfunction findFunctionRefs(value, path = '') {\n const refs = []\n\n if (typeof value === 'string' && value.startsWith('{{') && value.endsWith('}}')) {\n const fnName = value.slice(2, -2)\n refs.push({ name: fnName, path })\n } else if (typeof value === 'object' && value !== null) {\n Object.entries(value).forEach(([key, val]) => {\n refs.push(...findFunctionRefs(val, path ? `${path}.${key}` : key))\n })\n } else if (Array.isArray(value)) {\n value.forEach((val, index) => {\n refs.push(...findFunctionRefs(val, `${path}[${index}]`))\n })\n }\n\n return refs\n}\n\n/**\n * Validate all function references exist in functions registry\n */\nfunction validateFunctionReferences(errors, meta, layout, fields, buttons, functions) {\n const allRefs = []\n\n // Find refs in meta\n allRefs.push(...findFunctionRefs(meta, 'meta'))\n\n // Find refs in layout\n allRefs.push(...findFunctionRefs(layout, 'layout'))\n\n // Find refs in fields\n Object.entries(fields).forEach(([name, def]) => {\n allRefs.push(...findFunctionRefs(def, `fields.${name}`))\n })\n\n // Find refs in buttons\n Object.entries(buttons).forEach(([name, def]) => {\n allRefs.push(...findFunctionRefs(def, `buttons.${name}`))\n })\n\n // Check each ref exists\n const availableFunctions = Object.keys(functions)\n allRefs.forEach(({ name, path }) => {\n if (!functions[name]) {\n errors.push({\n type: 'missing_function',\n severity: 'high',\n path,\n message: `Function \"{{${name}}}\" not found in registries.functions`,\n suggestion: availableFunctions.length > 0\n ? `Available functions: ${availableFunctions.join(', ')}`\n : 'No functions are registered. Add functions to registries.functions or load from functions.js'\n })\n }\n })\n}\n\n/**\n * Validate spread references resolve to actual definitions\n */\nfunction validateSpreadReferences(errors, fields, buttons) {\n // Check field spread references\n Object.entries(fields).forEach(([name, def]) => {\n if (typeof def === 'object' && def !== null && def['...']) {\n const baseRef = def['...']\n if (!fields[baseRef]) {\n errors.push({\n type: 'missing_spread_ref',\n severity: 'high',\n path: `fields.${name}`,\n message: `Spread reference \"...\": \"${baseRef}\" not found in fields registry`,\n suggestion: `Available fields: ${Object.keys(fields).join(', ')}`\n })\n }\n }\n })\n\n // Check button spread references\n Object.entries(buttons).forEach(([name, def]) => {\n if (typeof def === 'object' && def !== null && def['...']) {\n const baseRef = def['...']\n if (!buttons[baseRef]) {\n errors.push({\n type: 'missing_spread_ref',\n severity: 'high',\n path: `buttons.${name}`,\n message: `Spread reference \"...\": \"${baseRef}\" not found in buttons registry`,\n suggestion: `Available buttons: ${Object.keys(buttons).join(', ')}`\n })\n }\n }\n })\n}\n\n/**\n * Validate layout references point to real fields\n */\nfunction validateLayoutReferences(errors, layout, fields) {\n const fieldNames = Object.keys(fields)\n\n function checkLayoutItem(item, path) {\n if (typeof item === 'string') {\n // It's a field reference\n if (!fields[item]) {\n errors.push({\n type: 'missing_field_ref',\n severity: 'high',\n path,\n message: `Layout references field \"${item}\" but it doesn't exist in fields registry`,\n suggestion: fieldNames.length > 0\n ? `Available fields: ${fieldNames.join(', ')}`\n : 'No fields are defined. Add fields to registries.fields'\n })\n }\n } else if (Array.isArray(item)) {\n // It's a row\n item.forEach((field, index) => {\n checkLayoutItem(field, `${path}[${index}]`)\n })\n } else if (typeof item === 'object' && item !== null) {\n // It's a group with nested layout\n if (item.layout) {\n item.layout.forEach((row, index) => {\n checkLayoutItem(row, `${path}.layout[${index}]`)\n })\n }\n if (item.rows) {\n item.rows.forEach((row, index) => {\n checkLayoutItem(row, `${path}.rows[${index}]`)\n })\n }\n }\n }\n\n layout.forEach((item, index) => {\n checkLayoutItem(item, `layout[${index}]`)\n })\n}\n\n/**\n * Collect all field names referenced in the layout\n */\nfunction collectLayoutFieldNames(layout) {\n const names = new Set()\n function walk(item) {\n if (typeof item === 'string') {\n names.add(item)\n } else if (Array.isArray(item)) {\n item.forEach(walk)\n } else if (typeof item === 'object' && item !== null) {\n if (item.layout) item.layout.forEach(walk)\n if (item.rows) item.rows.forEach(walk)\n }\n }\n layout.forEach(walk)\n return names\n}\n\n/**\n * Validate options references exist (only for fields used in the layout)\n */\nfunction validateOptionsReferences(errors, fields, optionSets, layoutFields) {\n const optionSetKeys = Object.keys(optionSets)\n\n Object.entries(fields).forEach(([name, def]) => {\n // Skip fields not referenced in the layout\n if (layoutFields && !layoutFields.has(name)) return\n if (typeof def === 'object' && def !== null) {\n const optionsRef = def.options\n\n // If options is a string reference, validate it\n if (typeof optionsRef === 'string') {\n // Skip function references ({{functionName}}) - they're validated elsewhere\n if (optionsRef.startsWith('{{') && optionsRef.endsWith('}}')) {\n return\n }\n\n // Strip @ prefix if present\n const optionKey = optionsRef.startsWith('@') ? optionsRef.slice(1) : optionsRef\n\n if (!Array.isArray(optionSets[optionKey])) {\n errors.push({\n type: 'missing_options_ref',\n severity: 'high',\n path: `fields.${name}.options`,\n message: `Options reference \"${optionsRef}\" not found in registries.optionSets`,\n suggestion: optionSetKeys.length > 0\n ? `Available option sets: ${optionSetKeys.join(', ')}`\n : 'No option sets are defined. Add options to registries.optionSets'\n })\n }\n }\n }\n })\n}\n\n/**\n * Detect arrow functions in wrapper format (known footgun)\n */\nfunction detectArrowFunctions(errors, functions) {\n Object.entries(functions).forEach(([name, def]) => {\n // Check if it's a wrapper with a value property\n if (typeof def === 'object' && def !== null && typeof def.value === 'function') {\n // Try to detect arrow function by checking if it has prototype\n // Arrow functions don't have prototype property\n if (!def.value.prototype) {\n errors.push({\n type: 'arrow_function_in_wrapper',\n severity: 'high',\n path: `functions.${name}`,\n message: `Function \"${name}\" uses arrow function in wrapper format`,\n suggestion: 'Arrow functions cannot access stage via \"this\". Use regular function: function(context, event) { ... }'\n })\n }\n }\n })\n}\n\n/**\n * Validate component/type combinations make sense\n */\nfunction validateComponentTypes(errors, fields) {\n Object.entries(fields).forEach(([name, def]) => {\n if (typeof def === 'object' && def !== null) {\n const component = def.component\n const hasOptions = def.options !== undefined\n\n // Checkbox/Radio components require options\n if ((component === 'Checkbox' || component === 'Radio') && !hasOptions) {\n errors.push({\n type: 'missing_options',\n severity: 'medium',\n path: `fields.${name}`,\n message: `Field \"${name}\" uses component=\"${component}\" but has no options defined`,\n suggestion: 'Add options property: options: [\"option1\", \"option2\"] or options: \"optionSetName\"'\n })\n }\n\n // Select component should have options\n if (component === 'Select' && !hasOptions) {\n errors.push({\n type: 'missing_options',\n severity: 'medium',\n path: `fields.${name}`,\n message: `Field \"${name}\" uses component=\"Select\" but has no options defined`,\n suggestion: 'Add options property: options: [\"option1\", \"option2\"] or options: \"optionSetName\"'\n })\n }\n }\n })\n}\n\n/**\n * Format validation errors for console output\n */\nexport function formatValidationErrors(errors) {\n if (errors.length === 0) {\n return 'āœ… No validation errors found'\n }\n\n const lines = [`\\nāš ļø Found ${errors.length} validation error${errors.length > 1 ? 's' : ''}:\\n`]\n\n errors.forEach((error, index) => {\n const icon = error.severity === 'high' ? 'šŸ”“' : '🟔'\n lines.push(`${icon} ${index + 1}. ${error.message}`)\n lines.push(` Path: ${error.path}`)\n if (error.suggestion) {\n lines.push(` šŸ’” ${error.suggestion}`)\n }\n lines.push('') // blank line\n })\n\n return lines.join('\\n')\n}\n","// src/components/utils/security.js\n// Consolidated security utilities for input sanitization and HTML safety\n\nimport { logger } from '@archduck/gst-core'\n\n// Dangerous protocols that should be blocked\nconst DANGEROUS_PROTOCOLS = ['javascript:', 'data:', 'vbscript:']\n\n// Whitelist of allowed HTML tags (when HTML is absolutely necessary)\nconst ALLOWED_TAGS = new Set([\n 'b', 'i', 'em', 'strong', 'u', 's', 'strike', 'del',\n 'p', 'br', 'hr', 'div', 'span',\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'ul', 'ol', 'li',\n 'a', 'code', 'pre', 'blockquote'\n])\n\n// Whitelist of allowed attributes per tag\nconst ALLOWED_ATTRS = {\n 'a': ['href', 'title'],\n 'span': ['class'],\n 'div': ['class'],\n '*': ['id', 'class'] // Attributes allowed on all tags\n}\n\n/**\n * Escape HTML special characters\n * Safe alternative to innerHTML for displaying user content\n *\n * @param {string} text - Text to escape\n * @returns {string} - Escaped text safe for HTML display\n */\nexport function escapeHTML(text) {\n if (!text || typeof text !== 'string') return ''\n\n const escapeMap = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#x27;',\n '/': '&#x2F;'\n }\n\n return text.replace(/[&<>\"'/]/g, char => escapeMap[char])\n}\n\n/**\n * Sanitize string input by removing potentially dangerous content\n * Sanitize string input by removing potentially dangerous content\n *\n * @param {*} value - Value to sanitize\n * @param {Object} options - Sanitization options\n * @returns {*} Sanitized value\n */\nexport function sanitizeInput(value, options = {}) {\n // Non-string values pass through\n if (typeof value !== 'string') return value\n\n const { allowBasicHTML = false, maxLength = undefined } = options\n\n let sanitized = value\n\n if (!allowBasicHTML) {\n // Remove all HTML and dangerous patterns\n sanitized = sanitized\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\s*on\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/javascript:/gi, '')\n .replace(/data:text\\/html[^,]*,/gi, '')\n .replace(/<[^>]+>/g, '')\n } else {\n // Allow basic HTML but still remove dangerous elements\n sanitized = stripDangerousHTML(sanitized)\n }\n\n // Apply max length if specified\n if (maxLength && sanitized.length > maxLength) {\n sanitized = sanitized.substring(0, maxLength)\n }\n\n return sanitized.trim()\n}\n\n/**\n * Strip dangerous HTML while allowing basic formatting\n *\n * @param {string} html - HTML to clean\n * @returns {string} - Cleaned HTML\n */\nfunction stripDangerousHTML(html) {\n // Create a temporary container\n const temp = document.createElement('div')\n temp.innerHTML = html\n\n // Process all elements\n const elements = temp.querySelectorAll('*')\n elements.forEach(element => {\n const tagName = element.tagName.toLowerCase()\n\n // Remove disallowed tags\n if (!ALLOWED_TAGS.has(tagName)) {\n element.remove()\n return\n }\n\n // Filter attributes\n const attrs = Array.from(element.attributes)\n attrs.forEach(attr => {\n const attrName = attr.name.toLowerCase()\n const allowed = (ALLOWED_ATTRS[tagName] || []).concat(ALLOWED_ATTRS['*'] || [])\n\n // Remove if not allowed or if it's an event handler\n if (!allowed.includes(attrName) || attrName.startsWith('on')) {\n element.removeAttribute(attr.name)\n }\n\n // Check for dangerous protocols in href/src\n if (attrName === 'href' || attrName === 'src') {\n if (DANGEROUS_PROTOCOLS.some(proto => attr.value.toLowerCase().startsWith(proto))) {\n element.removeAttribute(attr.name)\n logger.error(`Blocked dangerous protocol in ${attrName}: ${attr.value}`)\n }\n }\n })\n })\n\n return temp.innerHTML\n}\n\n/**\n * Sanitize HTML string to prevent XSS attacks (comprehensive)\n * For production, consider using DOMPurify instead\n *\n * @param {string} html - Raw HTML string\n * @param {Object} options - Sanitization options\n * @returns {string} - Sanitized HTML string\n */\nexport function sanitizeHTML(html, options = {}) {\n if (!html || typeof html !== 'string') return ''\n\n logger.warn('HTML sanitization in use. Consider using plain text or markdown instead.')\n\n return stripDangerousHTML(html)\n}\n\n/**\n * Strip all HTML tags from a string\n *\n * @param {string} html - HTML string\n * @returns {string} - Plain text without HTML tags\n */\nexport function stripHTML(html) {\n if (!html || typeof html !== 'string') return ''\n\n // Remove script and style tags with content\n let cleaned = html\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '')\n .replace(/<style\\b[^<]*(?:(?!<\\/style>)<[^<]*)*<\\/style>/gi, '')\n\n // Use DOM to extract text\n const temp = document.createElement('div')\n temp.innerHTML = cleaned\n return (temp.textContent || temp.innerText || '').trim()\n}\n\n/**\n * Validate if a URL is safe to use\n *\n * @param {string} url - URL to validate\n * @returns {boolean} - True if URL is safe\n */\nexport function isSafeURL(url) {\n if (!url || typeof url !== 'string') return false\n\n const lowerUrl = url.toLowerCase().trim()\n\n // Check for dangerous protocols\n if (DANGEROUS_PROTOCOLS.some(proto => lowerUrl.startsWith(proto))) {\n logger.error(`Dangerous URL protocol detected: ${url}`)\n return false\n }\n\n // Allow safe protocols and relative URLs\n return lowerUrl.startsWith('/') ||\n lowerUrl.startsWith('#') ||\n lowerUrl.startsWith('http://') ||\n lowerUrl.startsWith('https://') ||\n lowerUrl.startsWith('mailto:')\n}\n\n/**\n * Sanitize an entire object/record by applying sanitization to all string values\n *\n * @param {Object} data - Object to sanitize\n * @param {Object} options - Sanitization options\n * @returns {Object} Sanitized object\n */\nexport function sanitizeRecord(data, options = {}) {\n if (!data || typeof data !== 'object') return data\n\n const { exclude = [], fieldOptions = {} } = options\n const sanitized = {}\n\n for (const [key, value] of Object.entries(data)) {\n // Skip excluded fields\n if (exclude.includes(key)) {\n sanitized[key] = value\n continue\n }\n\n const fieldOpts = fieldOptions[key] || {}\n\n if (typeof value === 'string') {\n sanitized[key] = sanitizeInput(value, fieldOpts)\n } else if (Array.isArray(value)) {\n sanitized[key] = value.map(item =>\n typeof item === 'string' ? sanitizeInput(item, fieldOpts) : item\n )\n } else if (value && typeof value === 'object') {\n sanitized[key] = sanitizeRecord(value, {\n exclude: fieldOpts.exclude,\n fieldOptions: fieldOpts.nestedOptions\n })\n } else {\n sanitized[key] = value\n }\n }\n\n return sanitized\n}\n\n/**\n * Create a sanitization function with preset options\n *\n * @param {Object} defaultOptions - Default sanitization options\n * @returns {Function} Sanitization function\n */\nexport function createSanitizer(defaultOptions = {}) {\n return (value, overrideOptions = {}) => {\n return sanitizeInput(value, { ...defaultOptions, ...overrideOptions })\n }\n}\n\n/**\n * Common preset sanitizers\n */\nexport const sanitizers = {\n text: createSanitizer({ maxLength: 1000 }),\n name: createSanitizer({ maxLength: 100 }),\n email: createSanitizer({ maxLength: 254 }), // RFC 5321\n url: createSanitizer({ maxLength: 2083 }), // IE limit\n phone: createSanitizer({ maxLength: 20 }),\n username: createSanitizer({ maxLength: 50 }),\n password: (value) => value, // Don't sanitize passwords\n richText: createSanitizer({ allowBasicHTML: true, maxLength: 10000 }),\n comment: createSanitizer({ maxLength: 5000 }),\n numeric: (value) => {\n if (typeof value !== 'string') return value\n return value.replace(/[^\\d.-]/g, '')\n }\n}\n\n// Export security warnings for documentation\nexport const SECURITY_WARNINGS = {\n innerHTML: 'NEVER use innerHTML with user-generated content. Use textContent for safe text rendering.',\n userInput: 'Always validate and sanitize user input on both client and server.',\n externalContent: 'Treat all external content as untrusted. Sanitize before rendering.',\n urlValidation: 'Always validate URLs before using them in href or src attributes.'\n}","/**\n * createScopedFormContext - Creates a scoped form context for nested fields\n *\n * Used by Container to create scoped getValue/setValue that operate on\n * nested objects (e.g., billingAddress.street instead of street).\n *\n * @param {Object} options\n * @param {string} options.name - Parent field name (e.g., \"billingAddress\")\n * @param {Object} options.context - Current form context\n * @param {Object} options.actionsContext - Form actions context\n * @param {Function} [options.parentValidate] - Optional validation function for children\n * @returns {Object} Scoped context with nested getValue/setValue\n */\nexport function createScopedFormContext({ name, context, actionsContext, parentValidate }) {\n return {\n ...context,\n // Explicitly include registries\n registries: context.registries,\n functions: context.functions || context.registries?.functions || {},\n form: {\n ...actionsContext,\n getValue: fieldName => {\n const parentValue = actionsContext.getValue(name) || {}\n return parentValue[fieldName]\n },\n setValue: (fieldName, value) => {\n const parentValue = actionsContext.getValue(name) || {}\n actionsContext.setValue(name, {\n ...parentValue,\n [fieldName]: value,\n })\n },\n getFieldErrors: fieldName => {\n const parentErrors = actionsContext.getFieldErrors(name) || {}\n return parentErrors[fieldName] || []\n },\n setFieldErrors: (fieldName, errors) => {\n const parentErrors = actionsContext.getFieldErrors(name) || {}\n actionsContext.setFieldErrors(name, {\n ...parentErrors,\n [fieldName]: errors,\n })\n },\n setFieldError: (fieldName, message) => {\n const parentErrors = actionsContext.getFieldErrors(name) || {}\n actionsContext.setFieldErrors(name, {\n ...parentErrors,\n [fieldName]: Array.isArray(message) ? message : [message]\n })\n },\n clearFieldError: (fieldName) => {\n const parentErrors = actionsContext.getFieldErrors(name) || {}\n const { [fieldName]: _, ...rest } = parentErrors\n actionsContext.setFieldErrors(name, rest)\n },\n },\n fieldPath: context.fieldPath ? `${context.fieldPath}.${name}` : name,\n parentValidate,\n }\n}\n"],"names":["FORM_TLP_DECLARATIONS","formSchema","createTLPSchema","loadJsonConfig","path","options","coreLoadJsonConfig","createLiveConfig","coreCreateLiveConfig","loadLiveConfig","coreLoadLiveConfig","collectFieldNames","def","names","walk","item","rows","row","cell","child","pendingClear","clearHiddenFieldData","store","pauseTracking","_a","fieldNames","protectedFields","_b","_c","name","fieldDef","_e","_d","val","getFieldValue","flushClear","enableTracking","batch","saved","clearFieldValue","cascade","_f","_g","labels","value","_i","_h","setFieldValue","createFormStage","contextGetter","getContext","msg","errors","actionName","extra","record","setupFormActions","actionHandlers","wrapAction","onAction","cloneData","data","baseline","reset","baselineData","currentData","key","loadRecord","newRecord","buildActionContext","formStage","resolveHook","hookName","hook","isDebugActive","trace","fn","resolvedName","context","registryFn","rawHandler","ctx","source","handler","dirtyTrackingEffect","onDirtyChange","effect","dirty","allKeys","current","base","changeTrackingEffect","onChange","skipFirst","errorTrackingEffect","hadErrors","hasErrors","firstErroredName","errs","el","exposeWindowGst","obj","cleanupWindowGst","mountForm","container","config","regs","regName","reg","formEl","e","cls","skipLink","target","focusable","mount","controller","removeDirtyGuard","onBeforeUnload","result","onKeyDown","DEFAULT_RECORD","META_DEFAULTS","applyMetaDefaults","meta","getRecordData","dataPath","setRecordData","newData","getRecordKey","keyPath","initializeRecordFields","layout","fieldRegistry","initializedData","getDefaultValue","type","component","extractFieldNames","element","fieldName","group","runtimeError","message","suggestion","details","parts","runtimeWarning","available","missingReference","functionError","functionName","property","error","missingHandler","handlerName","action","transformError","operation","getFieldDataAttributes","state","fieldType","isDirty","isTouched","isFocused","isDisabled","isReadonly","isRequired","isComputed","getButtonDataAttributes","buttonName","variant","isLoading","getGroupDataAttributes","groupName","isVisible","evaluateVisibility","elementName","showValue","functions","funcName","func","stage","createStage","slugify","text","getFieldsToClear","registries","previousVisibility","fieldsToClear","idx","boundGroup","bindFunctions","currentlyVisible","fieldRef","getState","showNew","hasKey","isDeleted","showDuplicate","showDelete","showCancel","showSave","saveLabel","cancelLabel","coreButtonFunctions","defaultButtons","executeHooks","hooks","hookArray","hookRef","hookFn","logger","err","capitalize","str","isEmpty","validateRequiredFields","fields","valid","subFields","constructionRequired","requiredSubNames","subDef","subName","hasAnyData","wrapWithHooks","beforeHook","afterHook","resolveHandler","propName","specificHandler","defaultActions","buttonDef","form","confirmCancel","confirmDelete","confirmDuplicate","confirmNew","defaults","detectMaskType","mask","patterns","pattern","applyMask","rawChars","ch","charIndex","i","maskChar","resolveProp","propValue","isEventKey","event","resolveVisibility","formatValue","formatter","parseValue","parser","tempStage","INTERNAL_PROPS","separateProps","props","wrapperProps","inputProps","validateConfig","buttons","optionSets","validateFunctionReferences","validateSpreadReferences","validateLayoutReferences","layoutFields","collectLayoutFieldNames","validateOptionsReferences","detectArrowFunctions","validateComponentTypes","findFunctionRefs","refs","fnName","index","allRefs","availableFunctions","baseRef","checkLayoutItem","field","optionSetKeys","optionsRef","optionKey","hasOptions","formatValidationErrors","lines","icon","DANGEROUS_PROTOCOLS","ALLOWED_TAGS","ALLOWED_ATTRS","escapeHTML","escapeMap","char","sanitizeInput","allowBasicHTML","maxLength","sanitized","stripDangerousHTML","html","temp","tagName","attr","attrName","proto","sanitizeHTML","stripHTML","cleaned","isSafeURL","url","lowerUrl","sanitizeRecord","exclude","fieldOptions","fieldOpts","createSanitizer","defaultOptions","overrideOptions","sanitizers","SECURITY_WARNINGS","createScopedFormContext","actionsContext","parentValidate","parentValue","parentErrors","_","rest"],"mappings":"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"}