@mosaicoo/form-angular 0.1.0 → 0.3.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":"mosaicoo-form-angular-designer.mjs","sources":["../../../packages/angular/designer/src/designer-node.component.ts","../../../packages/angular/designer/src/inspector.component.ts","../../../packages/angular/designer/src/field-catalog.ts","../../../packages/angular/designer/src/designer.component.ts","../../../packages/angular/designer/src/public-api.ts","../../../packages/angular/designer/src/mosaicoo-form-angular-designer.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n input,\n output,\n signal,\n} from '@angular/core';\nimport type { ContainerField, FieldNode, FormEngine, NodePath } from '@mosaicoo/form-core';\nimport { FormNodeComponent } from '@mosaicoo/form-angular';\n\n/**\n * Canvas node: draws the selection frame and structure chrome, delegating\n * leaf rendering to the RUNTIME `<mform-node>` so what you see is what the\n * renderer will produce. Canvas controls are non-interactive — testing\n * happens in Preview mode.\n */\n@Component({\n selector: 'mform-designer-node',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [FormNodeComponent],\n template: `\n @let n = node();\n <div\n class=\"dz-node\"\n [class.is-selected]=\"isSelected()\"\n [class.is-container]=\"n.kind === 'container'\"\n (click)=\"onSelect($event)\"\n role=\"button\"\n tabindex=\"0\"\n (keydown.enter)=\"onSelect($event)\"\n [attr.aria-label]=\"chip() + (isSelected() ? ' (selected)' : '')\"\n >\n <span class=\"dz-chip\">{{ chip() }}</span>\n\n @if (n.kind === 'container') {\n @if (n.type === 'tabs') {\n <div class=\"dz-tabbar\">\n @for (tab of container().children; track tab.key; let i = $index) {\n <button\n type=\"button\"\n class=\"dz-tab\"\n [class.is-active]=\"activeTab() === i\"\n (click)=\"setTab(i, $event)\"\n >\n {{ tab.label || 'Tab ' + (i + 1) }}\n </button>\n }\n </div>\n @for (tab of container().children; track tab.key; let i = $index) {\n @if (activeTab() === i) {\n <div class=\"dz-children\">\n <mform-designer-node\n [node]=\"tab\"\n [path]=\"childPath(i)\"\n [engine]=\"engine()\"\n [selected]=\"selected()\"\n (selectNode)=\"selectNode.emit($event)\"\n />\n </div>\n }\n }\n } @else if (n.type === 'columns' && container().columns?.length) {\n <div class=\"dz-columns\" [style.grid-template-columns]=\"columnsTemplate()\">\n @for (column of container().columns; track $index) {\n <div class=\"dz-column\">\n @for (childIndex of column.children; track childIndex) {\n <mform-designer-node\n [node]=\"container().children[childIndex]!\"\n [path]=\"childPath(childIndex)\"\n [engine]=\"engine()\"\n [selected]=\"selected()\"\n (selectNode)=\"selectNode.emit($event)\"\n />\n }\n @if (column.children.length === 0) {\n <div class=\"dz-empty\">empty column</div>\n }\n </div>\n }\n </div>\n } @else {\n <div class=\"dz-children\">\n @for (child of container().children; track child.key; let i = $index) {\n <mform-designer-node\n [node]=\"child\"\n [path]=\"childPath(i)\"\n [engine]=\"engine()\"\n [selected]=\"selected()\"\n (selectNode)=\"selectNode.emit($event)\"\n />\n } @empty {\n <div class=\"dz-empty\">empty — select and add fields</div>\n }\n </div>\n }\n } @else {\n <div class=\"dz-leaf\" inert>\n <mform-node [node]=\"n\" [engine]=\"engine()\" [tick]=\"0\" />\n </div>\n }\n </div>\n `,\n})\nexport class DesignerNodeComponent {\n readonly node = input.required<FieldNode>();\n readonly path = input.required<NodePath>();\n readonly engine = input.required<FormEngine>();\n readonly selected = input<NodePath | null>(null);\n readonly selectNode = output<NodePath>();\n\n readonly activeTab = signal(0);\n\n container(): ContainerField {\n return this.node() as ContainerField;\n }\n\n chip(): string {\n const node = this.node();\n const label = node.kind === 'container' || node.kind === 'static'\n ? node.label ?? node.key\n : node.label ?? node.key;\n return `${label} · ${node.type}`;\n }\n\n isSelected(): boolean {\n const selected = this.selected();\n return selected !== null && selected.join('.') === this.path().join('.');\n }\n\n childPath(index: number): NodePath {\n return [...this.path(), index];\n }\n\n columnsTemplate(): string {\n const columns = this.container().columns ?? [];\n const total = columns.reduce((sum, c) => sum + c.width, 0) || 12;\n return columns.map((c) => `${((c.width / total) * 100).toFixed(3)}fr`).join(' ');\n }\n\n onSelect(event: Event): void {\n event.stopPropagation();\n this.selectNode.emit(this.path());\n }\n\n setTab(index: number, event: Event): void {\n event.stopPropagation();\n this.activeTab.set(index);\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n input,\n output,\n} from '@angular/core';\nimport type {\n Condition,\n ContainerField,\n FieldNode,\n FieldOption,\n FormSchema,\n InputField,\n StaticField,\n ValidatorSpec,\n} from '@mosaicoo/form-core';\nimport { collectInputs } from '@mosaicoo/form-core';\n\n/** Patch emitted towards the shell (applied via core `updateNode`). */\nexport interface InspectorPatch {\n patch: Partial<FieldNode>;\n}\n\n/**\n * Property panel of the selected node. Emits immutable patches — the shell\n * owns the document, history and validation.\n */\n@Component({\n selector: 'mform-inspector',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n template: `\n @let n = node();\n <div class=\"dz-inspector\">\n <h3>{{ n.type }} <code>{{ n.key }}</code></h3>\n\n <label class=\"dz-prop\">\n <span>Key</span>\n <input type=\"text\" [value]=\"n.key\" (change)=\"patchText('key', $event)\" />\n </label>\n <label class=\"dz-prop\">\n <span>Label</span>\n <input type=\"text\" [value]=\"n.label ?? ''\" (change)=\"patchText('label', $event)\" />\n </label>\n <label class=\"dz-prop\">\n <span>Description</span>\n <input type=\"text\" [value]=\"n.description ?? ''\" (change)=\"patchText('description', $event)\" />\n </label>\n\n @if (n.kind === 'input') {\n <label class=\"dz-prop\">\n <span>Placeholder</span>\n <input type=\"text\" [value]=\"field().placeholder ?? ''\" (change)=\"patchText('placeholder', $event)\" />\n </label>\n <label class=\"dz-prop\">\n <span>Default value</span>\n <input type=\"text\" [value]=\"defaultValueText()\" (change)=\"patchDefault($event)\" />\n </label>\n <label class=\"dz-check\">\n <input type=\"checkbox\" [checked]=\"isRequired()\" (change)=\"toggleRequired($event)\" />\n <span>Required</span>\n </label>\n\n <details class=\"dz-section\" open>\n <summary>Validation</summary>\n <label class=\"dz-prop\"><span>Min length</span>\n <input type=\"number\" [value]=\"validatorValue('minLength')\" (change)=\"patchValidator('minLength', $event)\" /></label>\n <label class=\"dz-prop\"><span>Max length</span>\n <input type=\"number\" [value]=\"validatorValue('maxLength')\" (change)=\"patchValidator('maxLength', $event)\" /></label>\n <label class=\"dz-prop\"><span>Min</span>\n <input type=\"number\" [value]=\"validatorValue('min')\" (change)=\"patchValidator('min', $event)\" /></label>\n <label class=\"dz-prop\"><span>Max</span>\n <input type=\"number\" [value]=\"validatorValue('max')\" (change)=\"patchValidator('max', $event)\" /></label>\n <label class=\"dz-prop\"><span>Pattern (regex)</span>\n <input type=\"text\" [value]=\"patternValue()\" (change)=\"patchPattern($event)\" /></label>\n </details>\n\n @if (hasOptions()) {\n <details class=\"dz-section\" open>\n <summary>Options</summary>\n @for (option of field().options ?? []; track $index; let i = $index) {\n <div class=\"dz-option-row\">\n <input type=\"text\" placeholder=\"Label\" [value]=\"option.label\"\n (change)=\"patchOption(i, 'label', $event)\" />\n <input type=\"text\" placeholder=\"Value\" [value]=\"option.value\"\n (change)=\"patchOption(i, 'value', $event)\" />\n <button type=\"button\" (click)=\"removeOption(i)\" aria-label=\"Remove option\">✕</button>\n </div>\n }\n <button type=\"button\" class=\"dz-add\" (click)=\"addOption()\">+ Option</button>\n </details>\n }\n }\n\n @if (n.kind === 'static' && n.type === 'content') {\n <label class=\"dz-prop\">\n <span>Content (HTML)</span>\n <textarea rows=\"5\" [value]=\"static_().content ?? ''\" (change)=\"patchText('content', $event)\"></textarea>\n </label>\n }\n\n @if (n.kind === 'container' && n.type === 'columns') {\n <label class=\"dz-prop\">\n <span>Column widths (of 12, comma-separated)</span>\n <input type=\"text\" [value]=\"columnWidths()\" (change)=\"patchColumnWidths($event)\" />\n </label>\n }\n\n <details class=\"dz-section\">\n <summary>Visibility</summary>\n <label class=\"dz-check\">\n <input type=\"checkbox\" [checked]=\"n.hidden === true\" (change)=\"patchFlag('hidden', $event)\" />\n <span>Hidden</span>\n </label>\n <label class=\"dz-check\">\n <input type=\"checkbox\" [checked]=\"n.disabled === true\" (change)=\"patchFlag('disabled', $event)\" />\n <span>Disabled</span>\n </label>\n <label class=\"dz-prop\">\n <span>Show when field…</span>\n <select [value]=\"n.conditional?.field ?? ''\" (change)=\"patchConditionField($event)\">\n <option value=\"\">(always visible)</option>\n @for (path of otherInputPaths(); track path) {\n <option [value]=\"path\" [selected]=\"n.conditional?.field === path\">{{ path }}</option>\n }\n </select>\n </label>\n @if (n.conditional) {\n <label class=\"dz-prop\">\n <span>…equals value</span>\n <input type=\"text\" [value]=\"conditionValueText()\" (change)=\"patchConditionValue($event)\" />\n </label>\n }\n </details>\n </div>\n `,\n})\nexport class InspectorComponent {\n readonly node = input.required<FieldNode>();\n readonly schema = input.required<FormSchema>();\n readonly nodePatch = output<InspectorPatch>();\n\n field(): InputField {\n return this.node() as InputField;\n }\n\n static_(): StaticField {\n return this.node() as StaticField;\n }\n\n hasOptions(): boolean {\n return ['select', 'radio', 'checkbox-group'].includes(this.node().type);\n }\n\n readonly otherInputPaths = computed(() =>\n collectInputs(this.schema())\n .map((entry) => entry.path)\n .filter((path) => !path.includes('*')),\n );\n\n private emitPatch(patch: Partial<FieldNode>): void {\n this.nodePatch.emit({ patch });\n }\n\n private inputValue(event: Event): string {\n return (event.target as HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement).value;\n }\n\n patchText(member: 'key' | 'label' | 'description' | 'placeholder' | 'content', event: Event): void {\n const value = this.inputValue(event).trim();\n if (member === 'key' && value === '') return; // key can never be emptied\n this.emitPatch({ [member]: value === '' ? undefined : value } as Partial<FieldNode>);\n }\n\n patchFlag(member: 'hidden' | 'disabled', event: Event): void {\n const checked = (event.target as HTMLInputElement).checked;\n this.emitPatch({ [member]: checked ? true : undefined } as Partial<FieldNode>);\n }\n\n defaultValueText(): string {\n const value = this.field().defaultValue;\n return value === undefined || value === null ? '' : String(value);\n }\n\n patchDefault(event: Event): void {\n const raw = this.inputValue(event);\n if (raw === '') {\n this.emitPatch({ defaultValue: undefined } as Partial<FieldNode>);\n return;\n }\n const field = this.field();\n let value: unknown = raw;\n if (field.dataType === 'number') value = Number(raw);\n if (field.dataType === 'boolean') value = raw === 'true';\n this.emitPatch({ defaultValue: value } as Partial<FieldNode>);\n }\n\n // -- validators -----------------------------------------------------------\n\n private validators(): ValidatorSpec[] {\n return this.field().validators ?? [];\n }\n\n isRequired(): boolean {\n return this.validators().some((v) => v.type === 'required');\n }\n\n toggleRequired(event: Event): void {\n const checked = (event.target as HTMLInputElement).checked;\n const rest = this.validators().filter((v) => v.type !== 'required');\n this.emitValidators(checked ? [{ type: 'required' }, ...rest] : rest);\n }\n\n validatorValue(type: 'minLength' | 'maxLength' | 'min' | 'max'): string {\n const spec = this.validators().find((v) => v.type === type);\n return spec && 'value' in spec ? String(spec.value) : '';\n }\n\n patchValidator(type: 'minLength' | 'maxLength' | 'min' | 'max', event: Event): void {\n const raw = this.inputValue(event);\n const rest = this.validators().filter((v) => v.type !== type);\n this.emitValidators(raw === '' ? rest : [...rest, { type, value: Number(raw) }]);\n }\n\n patternValue(): string {\n const spec = this.validators().find((v) => v.type === 'pattern');\n return spec && 'value' in spec ? String(spec.value) : '';\n }\n\n patchPattern(event: Event): void {\n const raw = this.inputValue(event);\n const rest = this.validators().filter((v) => v.type !== 'pattern');\n this.emitValidators(raw === '' ? rest : [...rest, { type: 'pattern', value: raw }]);\n }\n\n private emitValidators(validators: ValidatorSpec[]): void {\n this.emitPatch({ validators: validators.length ? validators : undefined } as Partial<FieldNode>);\n }\n\n // -- options --------------------------------------------------------------\n\n patchOption(index: number, member: 'label' | 'value', event: Event): void {\n const options = [...(this.field().options ?? [])];\n options[index] = { ...options[index]!, [member]: this.inputValue(event) };\n this.emitPatch({ options } as Partial<FieldNode>);\n }\n\n addOption(): void {\n const options = [...(this.field().options ?? [])];\n options.push({ label: `Option ${options.length + 1}`, value: `option${options.length + 1}` });\n this.emitPatch({ options } as Partial<FieldNode>);\n }\n\n removeOption(index: number): void {\n const options = (this.field().options ?? []).filter((_, i) => i !== index);\n this.emitPatch({ options: options.length ? options : undefined } as Partial<FieldNode>);\n }\n\n // -- columns --------------------------------------------------------------\n\n columnWidths(): string {\n return ((this.node() as ContainerField).columns ?? []).map((c) => c.width).join(', ');\n }\n\n patchColumnWidths(event: Event): void {\n const container = this.node() as ContainerField;\n const widths = this.inputValue(event)\n .split(',')\n .map((part) => Number(part.trim()))\n .filter((width) => Number.isFinite(width) && width > 0);\n if (widths.length === 0) return;\n const existing = container.columns ?? [];\n const columns = widths.map((width, i) => ({\n width,\n children: existing[i]?.children ?? [],\n }));\n // children in dropped columns are re-attached to the last remaining one\n for (let i = widths.length; i < existing.length; i++) {\n columns[columns.length - 1]!.children.push(...existing[i]!.children);\n }\n this.emitPatch({ columns } as Partial<FieldNode>);\n }\n\n // -- conditional ----------------------------------------------------------\n\n conditionValueText(): string {\n const value = this.node().conditional?.value;\n return value === undefined || value === null ? '' : String(value);\n }\n\n patchConditionField(event: Event): void {\n const field = this.inputValue(event);\n if (field === '') {\n this.emitPatch({ conditional: undefined });\n return;\n }\n const current = this.node().conditional;\n const conditional: Condition = {\n show: current?.show ?? true,\n op: current?.op ?? 'eq',\n field,\n value: current?.value ?? '',\n };\n this.emitPatch({ conditional });\n }\n\n patchConditionValue(event: Event): void {\n const current = this.node().conditional;\n if (!current) return;\n const raw = this.inputValue(event);\n const value: unknown = raw === 'true' ? true : raw === 'false' ? false : raw;\n this.emitPatch({ conditional: { ...current, value } });\n }\n}\n\n/** Re-export so the shell can type option edits without a deep import. */\nexport type { FieldOption };\n","import type { FieldNode, FormSchema } from '@mosaicoo/form-core';\nimport { generateKey } from '@mosaicoo/form-core';\n\n/**\n * Palette catalog: the node factories the Designer offers. Hosts can extend\n * the palette via the `extraCatalog` input of `<mform-designer>` — entries\n * here stay generic (no domain assumptions).\n */\n\nexport interface CatalogEntry {\n /** Field `type` produced (also used to key custom renderers). */\n type: string;\n label: string;\n /** Short glyph shown in the palette. */\n icon: string;\n create(schema: FormSchema): FieldNode;\n}\n\nexport interface CatalogGroup {\n label: string;\n entries: CatalogEntry[];\n}\n\nfunction input(\n type: string,\n dataType: 'string' | 'number' | 'boolean' | 'date' | 'object' | 'array',\n label: string,\n extra?: Partial<Extract<FieldNode, { kind: 'input' }>>,\n): (schema: FormSchema) => FieldNode {\n return (schema) => ({\n kind: 'input',\n key: generateKey(schema, type),\n type,\n label,\n dataType,\n ...extra,\n });\n}\n\nexport const DEFAULT_CATALOG: CatalogGroup[] = [\n {\n label: 'Basic',\n entries: [\n { type: 'text', label: 'Text', icon: 'Aa', create: input('text', 'string', 'Text') },\n { type: 'textarea', label: 'Text area', icon: '¶', create: input('textarea', 'string', 'Text area') },\n { type: 'number', label: 'Number', icon: '#', create: input('number', 'number', 'Number') },\n { type: 'currency', label: 'Currency', icon: '$', create: input('currency', 'number', 'Currency') },\n { type: 'checkbox', label: 'Checkbox', icon: '☑', create: input('checkbox', 'boolean', 'Checkbox') },\n { type: 'email', label: 'Email', icon: '@', create: input('email', 'string', 'Email', { validators: [{ type: 'email' }] }) },\n { type: 'phone', label: 'Phone', icon: '☎', create: input('phone', 'string', 'Phone') },\n { type: 'password', label: 'Password', icon: '••', create: input('password', 'string', 'Password') },\n ],\n },\n {\n label: 'Choices',\n entries: [\n {\n type: 'select', label: 'Select', icon: '▾',\n create: (s) => ({ ...input('select', 'string', 'Select')(s), options: [\n { label: 'Option 1', value: 'option1' }, { label: 'Option 2', value: 'option2' },\n ] } as FieldNode),\n },\n {\n type: 'radio', label: 'Radio', icon: '◉',\n create: (s) => ({ ...input('radio', 'string', 'Radio')(s), options: [\n { label: 'Option 1', value: 'option1' }, { label: 'Option 2', value: 'option2' },\n ] } as FieldNode),\n },\n {\n type: 'checkbox-group', label: 'Checkbox group', icon: '☷',\n create: (s) => ({ ...input('checkbox-group', 'object', 'Checkbox group')(s), options: [\n { label: 'Option 1', value: 'option1' }, { label: 'Option 2', value: 'option2' },\n ] } as FieldNode),\n },\n { type: 'tags', label: 'Tags', icon: '⌗', create: input('tags', 'array', 'Tags') },\n ],\n },\n {\n label: 'Date & files',\n entries: [\n { type: 'datetime', label: 'Date & time', icon: '📅', create: input('datetime', 'date', 'Date & time') },\n { type: 'day', label: 'Date', icon: '▦', create: input('day', 'string', 'Date') },\n { type: 'time', label: 'Time', icon: '◷', create: input('time', 'string', 'Time') },\n { type: 'file', label: 'File', icon: '📎', create: input('file', 'array', 'File') },\n ],\n },\n {\n label: 'Layout',\n entries: [\n {\n type: 'panel', label: 'Panel', icon: '▭',\n create: (s) => ({ kind: 'container', key: generateKey(s, 'panel'), type: 'panel',\n dataScope: 'inherit', label: 'Panel', children: [] }),\n },\n {\n type: 'columns', label: 'Columns', icon: '▥',\n create: (s) => ({ kind: 'container', key: generateKey(s, 'columns'), type: 'columns',\n dataScope: 'inherit', children: [], columns: [\n { width: 6, children: [] }, { width: 6, children: [] },\n ] }),\n },\n {\n type: 'tabs', label: 'Tabs', icon: '⧉',\n create: (s) => {\n const key = generateKey(s, 'tabs');\n return { kind: 'container', key, type: 'tabs', dataScope: 'inherit', children: [\n { kind: 'container', key: `${key}-tab-1`, type: 'panel', dataScope: 'inherit', label: 'Tab 1', children: [] },\n { kind: 'container', key: `${key}-tab-2`, type: 'panel', dataScope: 'inherit', label: 'Tab 2', children: [] },\n ] };\n },\n },\n {\n type: 'group', label: 'Data group', icon: '⧈',\n create: (s) => ({ kind: 'container', key: generateKey(s, 'group'), type: 'group',\n dataScope: 'nested', label: 'Group', children: [] }),\n },\n {\n type: 'datagrid', label: 'Data grid', icon: '☰',\n create: (s) => ({ kind: 'container', key: generateKey(s, 'datagrid'), type: 'datagrid',\n dataScope: 'array', label: 'Data grid', children: [] }),\n },\n ],\n },\n {\n label: 'Static',\n entries: [\n {\n type: 'content', label: 'Content', icon: '¶¶',\n create: (s) => ({ kind: 'static', key: generateKey(s, 'content'), type: 'content',\n content: '<p>Content</p>' }),\n },\n {\n type: 'button', label: 'Submit button', icon: '⏎',\n create: (s) => ({ kind: 'static', key: generateKey(s, 'button'), type: 'button',\n label: 'Submit', props: { action: 'submit' } }),\n },\n ],\n },\n];\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n effect,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { JsonPipe } from '@angular/common';\nimport {\n createFormEngine,\n duplicateNode,\n getNodeAt,\n insertNode,\n moveNode,\n parentOf,\n removeNode,\n updateNode,\n validateSchema,\n type FieldNode,\n type FormEngine,\n type FormSchema,\n type NodePath,\n type SchemaDiagnostic,\n} from '@mosaicoo/form-core';\nimport { createLegacyImporter, importForm } from '@mosaicoo/form-core/interop';\nimport { FormRendererComponent } from '@mosaicoo/form-angular';\nimport { DesignerNodeComponent } from './designer-node.component.js';\nimport { InspectorComponent, type InspectorPatch } from './inspector.component.js';\nimport { DEFAULT_CATALOG, type CatalogEntry, type CatalogGroup } from './field-catalog.js';\n\nconst EMPTY_SCHEMA: FormSchema = { version: 1, fields: [] };\nconst HISTORY_LIMIT = 50;\n\n/**\n * `<mform-designer>` — visual authoring of form schemas.\n *\n * The designer edits a DOCUMENT (the schema): every change goes through the\n * core's immutable edit operations, feeding undo/redo and `schemaChanged`.\n * Persistence, publishing and permissions belong to the host.\n */\n@Component({\n selector: 'mform-designer',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [DesignerNodeComponent, InspectorComponent, FormRendererComponent, JsonPipe],\n styleUrls: ['./designer-theme.css'],\n template: `\n <div class=\"dz-shell\" (keydown)=\"onKeydown($event)\">\n <header class=\"dz-toolbar\">\n <div class=\"dz-tools\">\n <button type=\"button\" (click)=\"undo()\" [disabled]=\"past().length === 0\" title=\"Undo (Ctrl+Z)\">↶</button>\n <button type=\"button\" (click)=\"redo()\" [disabled]=\"future().length === 0\" title=\"Redo (Ctrl+Y)\">↷</button>\n <span class=\"dz-sep\"></span>\n <button type=\"button\" (click)=\"moveSelected(-1)\" [disabled]=\"!selected()\" title=\"Move up\">↑</button>\n <button type=\"button\" (click)=\"moveSelected(1)\" [disabled]=\"!selected()\" title=\"Move down\">↓</button>\n <button type=\"button\" (click)=\"duplicateSelected()\" [disabled]=\"!selected()\" title=\"Duplicate (Ctrl+D)\">⧉</button>\n <button type=\"button\" (click)=\"removeSelected()\" [disabled]=\"!selected()\" title=\"Delete (Del)\">🗑</button>\n </div>\n <div class=\"dz-tools\">\n @if (diagnostics().length > 0) {\n <button type=\"button\" class=\"dz-diag-badge\" (click)=\"showDiagnostics.set(!showDiagnostics())\">\n ⚠ {{ diagnostics().length }}\n </button>\n }\n <button type=\"button\" (click)=\"dialog.set(dialog() === 'import' ? null : 'import')\">Import</button>\n <button type=\"button\" (click)=\"openExport()\">Export</button>\n <button type=\"button\" class=\"dz-primary\" (click)=\"preview.set(!preview())\">\n {{ preview() ? 'Design' : 'Preview' }}\n </button>\n </div>\n </header>\n\n @if (showDiagnostics() && diagnostics().length > 0) {\n <div class=\"dz-diagnostics\" role=\"alert\">\n @for (diag of diagnostics(); track $index) {\n <div class=\"dz-diag\" [class.is-warning]=\"diag.severity === 'warning'\">\n <code>{{ diag.code }}</code> {{ diag.message }} <em>{{ diag.path }}</em>\n </div>\n }\n </div>\n }\n\n @if (dialog() === 'export') {\n <div class=\"dz-dialog\">\n <h4>Schema JSON</h4>\n <textarea readonly rows=\"12\">{{ exportedJson() }}</textarea>\n <div class=\"dz-dialog-actions\">\n <button type=\"button\" (click)=\"dialog.set(null)\">Close</button>\n </div>\n </div>\n }\n @if (dialog() === 'import') {\n <div class=\"dz-dialog\">\n <h4>Import definition (native schema or supported formats)</h4>\n <textarea rows=\"12\" #importArea placeholder='{\"version\":1,\"fields\":[…]} or a legacy definition'></textarea>\n @if (importError()) {\n <p class=\"dz-import-error\" role=\"alert\">{{ importError() }}</p>\n }\n <div class=\"dz-dialog-actions\">\n <button type=\"button\" (click)=\"dialog.set(null)\">Cancel</button>\n <button type=\"button\" class=\"dz-primary\" (click)=\"doImport(importArea.value)\">Import</button>\n </div>\n </div>\n }\n\n @if (preview()) {\n <div class=\"dz-preview\">\n <mform-renderer [schema]=\"draft()\" (valueChanged)=\"previewData.set($event)\" />\n <details class=\"dz-preview-data\">\n <summary>Test data</summary>\n <pre>{{ previewData() | json }}</pre>\n </details>\n </div>\n } @else {\n <div class=\"dz-body\">\n <aside class=\"dz-palette\">\n <h4>Fields</h4>\n @for (group of catalog(); track group.label) {\n <div class=\"dz-group\">\n <span class=\"dz-group-label\">{{ group.label }}</span>\n <div class=\"dz-group-entries\">\n @for (entry of group.entries; track entry.type) {\n <button type=\"button\" class=\"dz-palette-item\" (click)=\"add(entry)\"\n [title]=\"'Add ' + entry.label\">\n <span class=\"dz-icon\">{{ entry.icon }}</span>{{ entry.label }}\n </button>\n }\n </div>\n </div>\n }\n <h4>Structure</h4>\n <div class=\"dz-tree\" role=\"tree\">\n @for (item of tree(); track item.id) {\n <button\n type=\"button\"\n role=\"treeitem\"\n class=\"dz-tree-item\"\n [class.is-selected]=\"isSelectedPath(item.path)\"\n [style.padding-left.px]=\"8 + item.depth * 14\"\n (click)=\"select(item.path)\"\n >\n {{ item.label }}\n </button>\n } @empty {\n <span class=\"dz-empty\">no fields yet</span>\n }\n </div>\n </aside>\n\n <main class=\"dz-canvas\" (click)=\"select(null)\">\n @for (node of draft().fields; track node.key; let i = $index) {\n <mform-designer-node\n [node]=\"node\"\n [path]=\"[i]\"\n [engine]=\"canvasEngine()\"\n [selected]=\"selected()\"\n (selectNode)=\"select($event)\"\n />\n } @empty {\n <div class=\"dz-canvas-empty\">\n Click a field in the palette to start building.\n </div>\n }\n </main>\n\n <aside class=\"dz-props\">\n @if (selectedNode(); as node) {\n <mform-inspector\n [node]=\"node\"\n [schema]=\"draft()\"\n (nodePatch)=\"applyPatch($event)\"\n />\n } @else {\n <div class=\"dz-empty dz-props-empty\">Select a field to edit its properties.</div>\n }\n </aside>\n </div>\n }\n </div>\n `,\n})\nexport class FormDesignerComponent {\n /** Initial native schema to edit. */\n readonly schema = input<FormSchema | null>(null);\n /** Initial foreign definition (converted through importers). */\n readonly source = input<unknown>(null);\n /** Extra palette groups contributed by the host. */\n readonly extraCatalog = input<CatalogGroup[]>([]);\n\n /** Emitted after every committed edit (undo/redo included). */\n readonly schemaChanged = output<FormSchema>();\n\n readonly draft = signal<FormSchema>(EMPTY_SCHEMA);\n readonly past = signal<FormSchema[]>([]);\n readonly future = signal<FormSchema[]>([]);\n readonly selected = signal<NodePath | null>(null);\n readonly preview = signal(false);\n readonly previewData = signal<Record<string, unknown>>({});\n readonly dialog = signal<'import' | 'export' | null>(null);\n readonly importError = signal('');\n readonly showDiagnostics = signal(false);\n\n readonly catalog = computed<CatalogGroup[]>(() => [...DEFAULT_CATALOG, ...this.extraCatalog()]);\n readonly diagnostics = computed<SchemaDiagnostic[]>(() => validateSchema(this.draft()));\n readonly exportedJson = computed(() => JSON.stringify(this.draft(), null, 2));\n\n /** Disposable engine driving the canvas leaves (defaults visible). */\n readonly canvasEngine = computed<FormEngine>(() => createFormEngine(this.draft()));\n\n readonly selectedNode = computed<FieldNode | null>(() => {\n const path = this.selected();\n return path ? (getNodeAt(this.draft(), path) ?? null) : null;\n });\n\n /** Flat structure tree for navigation. */\n readonly tree = computed(() => {\n const items: Array<{ id: string; label: string; depth: number; path: NodePath }> = [];\n const visit = (nodes: FieldNode[], depth: number, prefix: NodePath) => {\n nodes.forEach((node, i) => {\n const path = [...prefix, i];\n items.push({\n id: path.join('.'),\n label: `${node.label ?? node.key} · ${node.type}`,\n depth,\n path,\n });\n if (node.kind === 'container') visit(node.children, depth + 1, path);\n });\n };\n visit(this.draft().fields, 0, []);\n return items;\n });\n\n constructor() {\n // (Re)load the document whenever the host hands a new definition in.\n effect(() => {\n const native = this.schema();\n const source = this.source();\n // Hosts often feed `schemaChanged` back into [schema] (controlled\n // usage) — the echo of our own draft must not reset history/selection.\n if (native && native === this.draft()) return;\n let initial = EMPTY_SCHEMA;\n if (native) {\n initial = native;\n } else if (source !== null && source !== undefined) {\n try {\n initial = importForm(source, [createLegacyImporter()]).schema;\n } catch {\n initial = EMPTY_SCHEMA;\n }\n }\n this.draft.set(initial);\n this.past.set([]);\n this.future.set([]);\n this.selected.set(null);\n });\n }\n\n // -- document mutation ----------------------------------------------------\n\n private commit(next: FormSchema): void {\n this.past.update((stack) => [...stack.slice(-(HISTORY_LIMIT - 1)), this.draft()]);\n this.future.set([]);\n this.draft.set(next);\n this.schemaChanged.emit(next);\n }\n\n undo(): void {\n const past = this.past();\n if (past.length === 0) return;\n this.future.update((stack) => [this.draft(), ...stack]);\n this.past.set(past.slice(0, -1));\n this.draft.set(past[past.length - 1]!);\n this.selected.set(null);\n this.schemaChanged.emit(this.draft());\n }\n\n redo(): void {\n const future = this.future();\n if (future.length === 0) return;\n this.past.update((stack) => [...stack, this.draft()]);\n this.future.set(future.slice(1));\n this.draft.set(future[0]!);\n this.selected.set(null);\n this.schemaChanged.emit(this.draft());\n }\n\n add(entry: CatalogEntry): void {\n const node = entry.create(this.draft());\n const target = this.insertionPath();\n this.commit(insertNode(this.draft(), target, node));\n this.select(target);\n }\n\n /** New nodes land inside a selected container, after a selected leaf, or at the end. */\n private insertionPath(): NodePath {\n const selected = this.selected();\n if (!selected) return [this.draft().fields.length];\n const node = getNodeAt(this.draft(), selected);\n if (node?.kind === 'container' && node.type !== 'columns') {\n return [...selected, node.children.length];\n }\n const { parent, index } = parentOf(selected);\n return [...parent, index + 1];\n }\n\n removeSelected(): void {\n const selected = this.selected();\n if (!selected) return;\n this.commit(removeNode(this.draft(), selected));\n this.selected.set(null);\n }\n\n duplicateSelected(): void {\n const selected = this.selected();\n if (!selected) return;\n this.commit(duplicateNode(this.draft(), selected));\n }\n\n moveSelected(delta: -1 | 1): void {\n const selected = this.selected();\n if (!selected) return;\n const { parent, index } = parentOf(selected);\n const siblings =\n parent.length === 0\n ? this.draft().fields\n : (getNodeAt(this.draft(), parent) as { children?: FieldNode[] })?.children ?? [];\n const target = index + delta;\n if (target < 0 || target >= siblings.length) return;\n this.commit(moveNode(this.draft(), selected, [...parent, target]));\n this.select([...parent, target]);\n }\n\n applyPatch(event: InspectorPatch): void {\n const selected = this.selected();\n if (!selected) return;\n this.commit(updateNode(this.draft(), selected, event.patch));\n }\n\n // -- selection ------------------------------------------------------------\n\n select(path: NodePath | null): void {\n this.selected.set(path);\n }\n\n isSelectedPath(path: NodePath): boolean {\n return this.selected()?.join('.') === path.join('.');\n }\n\n // -- import / export ------------------------------------------------------\n\n openExport(): void {\n this.dialog.set(this.dialog() === 'export' ? null : 'export');\n }\n\n doImport(raw: string): void {\n try {\n const parsed: unknown = JSON.parse(raw);\n const { schema } = importForm(parsed, [createLegacyImporter()]);\n this.commit(schema);\n this.selected.set(null);\n this.dialog.set(null);\n this.importError.set('');\n } catch (error) {\n this.importError.set('Could not import: ' + String(error));\n }\n }\n\n // -- keyboard -------------------------------------------------------------\n\n onKeydown(event: KeyboardEvent): void {\n const target = event.target as HTMLElement;\n if (['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName)) return;\n const key = event.key.toLowerCase();\n if (event.ctrlKey && key === 'z' && !event.shiftKey) {\n event.preventDefault();\n this.undo();\n } else if ((event.ctrlKey && key === 'y') || (event.ctrlKey && event.shiftKey && key === 'z')) {\n event.preventDefault();\n this.redo();\n } else if (event.ctrlKey && key === 'd') {\n event.preventDefault();\n this.duplicateSelected();\n } else if (key === 'delete') {\n event.preventDefault();\n this.removeSelected();\n }\n }\n}\n","/*\n * Designer entry point (`@mosaicoo/form-angular/designer`).\n *\n * Authoring lives behind this secondary entry so applications that only\n * RENDER forms never load designer code — required for federated hosts and\n * lazy loading.\n */\nexport { FormDesignerComponent } from './designer.component.js';\nexport { DesignerNodeComponent } from './designer-node.component.js';\nexport { InspectorComponent, type InspectorPatch } from './inspector.component.js';\nexport { DEFAULT_CATALOG, type CatalogEntry, type CatalogGroup } from './field-catalog.js';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["input"],"mappings":"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"}
@@ -1,7 +1,41 @@
1
+ import { NgComponentOutlet, DOCUMENT } from '@angular/common';
1
2
  import * as i0 from '@angular/core';
2
- import { input, signal, effect, untracked, computed, ViewEncapsulation, ChangeDetectionStrategy, Component, output } from '@angular/core';
3
+ import { InjectionToken, makeEnvironmentProviders, input, signal, inject, effect, untracked, computed, ViewEncapsulation, ChangeDetectionStrategy, Component, output } from '@angular/core';
3
4
  import { importForm, createLegacyImporter, createFormEngine, collectInputs } from '@mosaicoo/form-core';
4
5
 
6
+ /** Multi-provider token: maps merge, later providers win on conflicts. */
7
+ const MFORM_FIELD_COMPONENTS = new InjectionToken('MFORM_FIELD_COMPONENTS');
8
+ /**
9
+ * Transport used for `optionsSource: { type: 'remote' }` fields. Register it
10
+ * to route those requests through the host's HTTP stack (authentication,
11
+ * base URLs, caching). Without it, a plain `fetch` is used.
12
+ */
13
+ const MFORM_REMOTE_FETCHER = new InjectionToken('MFORM_REMOTE_FETCHER');
14
+ /**
15
+ * Registers renderer extensions at any injector level:
16
+ *
17
+ * ```ts
18
+ * bootstrapApplication(App, {
19
+ * providers: [
20
+ * provideMosaicooForm({
21
+ * components: { signature: SignatureFieldComponent },
22
+ * remoteFetcher: (url) => authenticatedGet(url),
23
+ * }),
24
+ * ],
25
+ * });
26
+ * ```
27
+ */
28
+ function provideMosaicooForm(config) {
29
+ const providers = [];
30
+ if (config.components) {
31
+ providers.push({ provide: MFORM_FIELD_COMPONENTS, useValue: config.components, multi: true });
32
+ }
33
+ if (config.remoteFetcher) {
34
+ providers.push({ provide: MFORM_REMOTE_FETCHER, useValue: config.remoteFetcher });
35
+ }
36
+ return makeEnvironmentProviders(providers);
37
+ }
38
+
5
39
  /**
6
40
  * Renders one schema node (input, container or static) and recurses into
7
41
  * children. State lives in the headless engine — this component only projects
@@ -20,10 +54,37 @@ class FormNodeComponent {
20
54
  /** Host-registered providers for `optionsSource: provider` fields. */
21
55
  providers = input({}, ...(ngDevMode ? [{ debugName: "providers" }] : /* istanbul ignore next */ []));
22
56
  activeTab = signal(0, ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
57
+ /** DI-registered custom field components (maps merge; later wins). */
58
+ componentMaps = inject(MFORM_FIELD_COMPONENTS, { optional: true });
59
+ /** Host transport for remote options; plain fetch when absent. */
60
+ remoteFetcher = inject(MFORM_REMOTE_FETCHER, { optional: true });
61
+ /** Custom component registered for this field type, if any. */
62
+ customComponent() {
63
+ const node = this.node();
64
+ if (node.kind !== 'input' || !this.componentMaps)
65
+ return null;
66
+ for (let i = this.componentMaps.length - 1; i >= 0; i--) {
67
+ const match = this.componentMaps[i]?.[node.type];
68
+ if (match)
69
+ return match;
70
+ }
71
+ return null;
72
+ }
73
+ /** Inputs handed to a custom component (MformFieldComponent contract). */
74
+ customInputs() {
75
+ return {
76
+ field: this.field(),
77
+ engine: this.engine(),
78
+ path: this.path(),
79
+ tick: this.tick(),
80
+ };
81
+ }
23
82
  /** Options resolved from a dynamic source (provider or remote URL). */
24
83
  resolvedOptions = signal(null, ...(ngDevMode ? [{ debugName: "resolvedOptions" }] : /* istanbul ignore next */ []));
25
84
  /** Snapshot of the observed refresh source at the last resolution. */
26
85
  lastRefreshKey = null;
86
+ /** Discards resolutions that arrive after a newer request started. */
87
+ optionsRequestSeq = 0;
27
88
  constructor() {
28
89
  effect(() => {
29
90
  const node = this.node();
@@ -47,18 +108,28 @@ class FormNodeComponent {
47
108
  if (refreshKey === this.lastRefreshKey)
48
109
  return;
49
110
  this.lastRefreshKey = refreshKey;
111
+ // Stale-response guard: only the latest request may write options.
112
+ const requestId = ++this.optionsRequestSeq;
113
+ const apply = (options) => {
114
+ if (requestId === this.optionsRequestSeq)
115
+ this.resolvedOptions.set(options);
116
+ };
50
117
  if (source.type === 'provider') {
51
118
  const provider = registry[source.name];
52
119
  if (!provider)
53
120
  return; // no provider: static options/fallback stand
54
121
  Promise.resolve(provider({ field: node, path, data: engine.getData(), args: source.args }))
55
- .then((options) => this.resolvedOptions.set(options))
122
+ .then(apply)
56
123
  .catch(() => { }); // provider failure keeps the static fallback
57
124
  }
58
125
  else {
59
- fetch(source.url)
60
- .then((response) => (response.ok ? response.json() : []))
61
- .then((list) => this.resolvedOptions.set((Array.isArray(list) ? list : []).map((item) => ({
126
+ // The host's transport (auth, base URL, caching) when registered via
127
+ // provideMosaicooForm; plain fetch as the zero-config default.
128
+ const request = this.remoteFetcher
129
+ ? this.remoteFetcher(source.url)
130
+ : fetch(source.url).then((response) => (response.ok ? response.json() : []));
131
+ request
132
+ .then((list) => apply((Array.isArray(list) ? list : []).map((item) => ({
62
133
  label: String(item[source.labelKey ?? 'label'] ?? item[source.valueKey ?? 'value'] ?? ''),
63
134
  value: (item[source.valueKey ?? 'value'] ?? ''),
64
135
  }))))
@@ -227,6 +298,32 @@ class FormNodeComponent {
227
298
  const files = event.target.files;
228
299
  this.setValue(files ? Array.from(files).map((f) => f.name) : []);
229
300
  }
301
+ prefix() {
302
+ const value = this.node().props?.['prefix'];
303
+ return typeof value === 'string' && value ? value : null;
304
+ }
305
+ suffix() {
306
+ const value = this.node().props?.['suffix'];
307
+ return typeof value === 'string' && value ? value : null;
308
+ }
309
+ tagValues() {
310
+ const value = this.value();
311
+ return Array.isArray(value) ? value.map(String) : [];
312
+ }
313
+ addTag(event) {
314
+ event.preventDefault();
315
+ const input = event.target;
316
+ const tag = input.value.trim();
317
+ if (!tag)
318
+ return;
319
+ this.setValue([...this.tagValues(), tag]);
320
+ input.value = '';
321
+ }
322
+ removeTag(index) {
323
+ const next = [...this.tagValues()];
324
+ next.splice(index, 1);
325
+ this.setValue(next);
326
+ }
230
327
  touch() {
231
328
  this.engine().markTouched(this.path());
232
329
  this.engine().validateField(this.path());
@@ -344,7 +441,12 @@ class FormNodeComponent {
344
441
  }
345
442
  }
346
443
  @case ('input') {
347
- @if (field().type !== 'hidden') {
444
+ @if (customComponent(); as custom) {
445
+ <ng-container
446
+ [ngComponentOutlet]="custom"
447
+ [ngComponentOutletInputs]="customInputs()"
448
+ />
449
+ } @else if (field().type !== 'hidden') {
348
450
  <div class="mform-field" [class.has-error]="errors().length > 0">
349
451
  @if (field().type !== 'checkbox') {
350
452
  <label class="mform-label" [attr.for]="controlId()">
@@ -445,6 +547,30 @@ class FormNodeComponent {
445
547
  }
446
548
  </div>
447
549
  }
550
+ @case ('tags') {
551
+ <div class="mform-tags">
552
+ @for (tag of tagValues(); track $index; let i = $index) {
553
+ <span class="mform-tag">
554
+ {{ tag }}
555
+ <button
556
+ type="button"
557
+ (click)="removeTag(i)"
558
+ [attr.aria-label]="'Remove ' + tag"
559
+ >✕</button>
560
+ </span>
561
+ }
562
+ <input
563
+ class="mform-control mform-tag-input"
564
+ type="text"
565
+ [id]="controlId()"
566
+ [placeholder]="field().placeholder || ''"
567
+ [disabled]="field().disabled === true"
568
+ [attr.aria-describedby]="describedBy()"
569
+ (keydown.enter)="addTag($event)"
570
+ (blur)="touch()"
571
+ />
572
+ </div>
573
+ }
448
574
  @case ('file') {
449
575
  <input
450
576
  class="mform-control"
@@ -467,19 +593,29 @@ class FormNodeComponent {
467
593
  />
468
594
  }
469
595
  @default {
470
- <input
471
- class="mform-control"
472
- [type]="inputType()"
473
- [id]="controlId()"
474
- [value]="stringValue()"
475
- [placeholder]="field().placeholder || ''"
476
- [disabled]="field().disabled === true"
477
- [attr.aria-required]="required() || null"
478
- [attr.aria-invalid]="errors().length > 0 || null"
479
- [attr.aria-describedby]="describedBy()"
480
- (input)="setString($event)"
481
- (blur)="touch()"
482
- />
596
+ <div class="mform-affix" [class.has-affix]="prefix() || suffix()">
597
+ @if (prefix(); as p) {
598
+ <span class="mform-prefix" aria-hidden="true">{{ p }}</span>
599
+ }
600
+ <input
601
+ class="mform-control"
602
+ [type]="inputType()"
603
+ [id]="controlId()"
604
+ [value]="stringValue()"
605
+ [placeholder]="field().placeholder || ''"
606
+ [disabled]="field().disabled === true"
607
+ [attr.step]="field().type === 'currency' ? '0.01' : null"
608
+ [attr.inputmode]="field().type === 'currency' ? 'decimal' : null"
609
+ [attr.aria-required]="required() || null"
610
+ [attr.aria-invalid]="errors().length > 0 || null"
611
+ [attr.aria-describedby]="describedBy()"
612
+ (input)="setString($event)"
613
+ (blur)="touch()"
614
+ />
615
+ @if (suffix(); as s) {
616
+ <span class="mform-suffix" aria-hidden="true">{{ s }}</span>
617
+ }
618
+ </div>
483
619
  }
484
620
  }
485
621
  @if (field().description) {
@@ -493,7 +629,7 @@ class FormNodeComponent {
493
629
  }
494
630
  }
495
631
  }
496
- `, isInline: true, dependencies: [{ kind: "component", type: FormNodeComponent, selector: "mform-node", inputs: ["node", "engine", "tick", "scope", "bare", "providers"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
632
+ `, isInline: true, dependencies: [{ kind: "component", type: FormNodeComponent, selector: "mform-node", inputs: ["node", "engine", "tick", "scope", "bare", "providers"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
497
633
  }
498
634
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FormNodeComponent, decorators: [{
499
635
  type: Component,
@@ -502,6 +638,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
502
638
  changeDetection: ChangeDetectionStrategy.OnPush,
503
639
  encapsulation: ViewEncapsulation.None,
504
640
  host: { class: 'mform-node' },
641
+ imports: [NgComponentOutlet],
505
642
  template: `
506
643
  @let n = node();
507
644
  @if (visible()) {
@@ -608,7 +745,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
608
745
  }
609
746
  }
610
747
  @case ('input') {
611
- @if (field().type !== 'hidden') {
748
+ @if (customComponent(); as custom) {
749
+ <ng-container
750
+ [ngComponentOutlet]="custom"
751
+ [ngComponentOutletInputs]="customInputs()"
752
+ />
753
+ } @else if (field().type !== 'hidden') {
612
754
  <div class="mform-field" [class.has-error]="errors().length > 0">
613
755
  @if (field().type !== 'checkbox') {
614
756
  <label class="mform-label" [attr.for]="controlId()">
@@ -709,6 +851,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
709
851
  }
710
852
  </div>
711
853
  }
854
+ @case ('tags') {
855
+ <div class="mform-tags">
856
+ @for (tag of tagValues(); track $index; let i = $index) {
857
+ <span class="mform-tag">
858
+ {{ tag }}
859
+ <button
860
+ type="button"
861
+ (click)="removeTag(i)"
862
+ [attr.aria-label]="'Remove ' + tag"
863
+ >✕</button>
864
+ </span>
865
+ }
866
+ <input
867
+ class="mform-control mform-tag-input"
868
+ type="text"
869
+ [id]="controlId()"
870
+ [placeholder]="field().placeholder || ''"
871
+ [disabled]="field().disabled === true"
872
+ [attr.aria-describedby]="describedBy()"
873
+ (keydown.enter)="addTag($event)"
874
+ (blur)="touch()"
875
+ />
876
+ </div>
877
+ }
712
878
  @case ('file') {
713
879
  <input
714
880
  class="mform-control"
@@ -731,19 +897,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
731
897
  />
732
898
  }
733
899
  @default {
734
- <input
735
- class="mform-control"
736
- [type]="inputType()"
737
- [id]="controlId()"
738
- [value]="stringValue()"
739
- [placeholder]="field().placeholder || ''"
740
- [disabled]="field().disabled === true"
741
- [attr.aria-required]="required() || null"
742
- [attr.aria-invalid]="errors().length > 0 || null"
743
- [attr.aria-describedby]="describedBy()"
744
- (input)="setString($event)"
745
- (blur)="touch()"
746
- />
900
+ <div class="mform-affix" [class.has-affix]="prefix() || suffix()">
901
+ @if (prefix(); as p) {
902
+ <span class="mform-prefix" aria-hidden="true">{{ p }}</span>
903
+ }
904
+ <input
905
+ class="mform-control"
906
+ [type]="inputType()"
907
+ [id]="controlId()"
908
+ [value]="stringValue()"
909
+ [placeholder]="field().placeholder || ''"
910
+ [disabled]="field().disabled === true"
911
+ [attr.step]="field().type === 'currency' ? '0.01' : null"
912
+ [attr.inputmode]="field().type === 'currency' ? 'decimal' : null"
913
+ [attr.aria-required]="required() || null"
914
+ [attr.aria-invalid]="errors().length > 0 || null"
915
+ [attr.aria-describedby]="describedBy()"
916
+ (input)="setString($event)"
917
+ (blur)="touch()"
918
+ />
919
+ @if (suffix(); as s) {
920
+ <span class="mform-suffix" aria-hidden="true">{{ s }}</span>
921
+ }
922
+ </div>
747
923
  }
748
924
  }
749
925
  @if (field().description) {
@@ -909,13 +1085,14 @@ class FormRendererComponent {
909
1085
  .join('.');
910
1086
  return this.steps().findIndex((step) => collectInputs({ version: 1, fields: step.children }).some((entry) => entry.path === pattern));
911
1087
  }
1088
+ documentRef = inject(DOCUMENT);
912
1089
  focusFirstError(errors) {
913
1090
  const first = errors[0];
914
1091
  if (!first)
915
1092
  return;
916
1093
  const id = `mform-${first.path.replace(/\./g, '-')}`;
917
1094
  // Focus after the view updated with the error states.
918
- queueMicrotask(() => document.getElementById(id)?.focus());
1095
+ queueMicrotask(() => this.documentRef.getElementById(id)?.focus());
919
1096
  }
920
1097
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FormRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
921
1098
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FormRendererComponent, isStandalone: true, selector: "mform-renderer", inputs: { schema: { classPropertyName: "schema", publicName: "schema", isSignal: true, isRequired: false, transformFunction: null }, source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: false, transformFunction: null }, initialData: { classPropertyName: "initialData", publicName: "initialData", isSignal: true, isRequired: false, transformFunction: null }, optionsProviders: { classPropertyName: "optionsProviders", publicName: "optionsProviders", isSignal: true, isRequired: false, transformFunction: null }, messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitted: "submitted", valueChanged: "valueChanged" }, ngImport: i0, template: `
@@ -975,7 +1152,7 @@ class FormRendererComponent {
975
1152
  }
976
1153
  </form>
977
1154
  }
978
- `, isInline: true, styles: [".mform-root{display:flex;flex-direction:column;gap:var(--mform-gap, 16px);font-family:var(--mform-font, system-ui, \"Segoe UI\", sans-serif);color:var(--mform-text, #1f1b2e)}.mform-node{display:contents}.mform-field{display:flex;flex-direction:column;gap:6px}.mform-label{font-size:var(--mform-label-size, 13px);font-weight:var(--mform-label-weight, 600)}.mform-req{color:var(--mform-danger, #c62842);margin-left:2px}.mform-control{font:inherit;width:100%;padding:var(--mform-control-padding, 9px 12px);border:1px solid var(--mform-border, #d9d5e6);border-radius:var(--mform-control-radius, 8px);background:var(--mform-control-bg, #fff);color:inherit;box-sizing:border-box}textarea.mform-control{min-height:72px;resize:vertical}.mform-control:focus-visible{outline:2px solid var(--mform-focus, #8e6ff0);outline-offset:1px;border-color:var(--mform-focus, #8e6ff0)}.mform-field.has-error .mform-control{border-color:var(--mform-danger, #c62842)}.mform-desc{font-size:12px;color:var(--mform-muted, #6b6580)}.mform-error{font-size:12px;color:var(--mform-danger, #c62842)}.mform-choices{display:flex;flex-direction:column;gap:6px}.mform-check{display:flex;align-items:center;gap:8px;font-size:14px;cursor:pointer}.mform-check input{width:16px;height:16px;accent-color:var(--mform-primary, #6d4bd0)}.mform-panel{border:1px solid var(--mform-border, #d9d5e6);border-radius:var(--mform-radius, 10px);overflow:hidden}.mform-panel-head{background:var(--mform-panel-head-bg, linear-gradient(90deg, #efeaff, #f8f6ff));color:var(--mform-panel-head-text, inherit);padding:10px 16px;font-weight:600;font-size:14px;border-bottom:1px solid var(--mform-border, #d9d5e6)}.mform-panel-body,.mform-group,.mform-column,.mform-tabpanel{display:flex;flex-direction:column;gap:var(--mform-gap, 16px)}.mform-panel-body{padding:var(--mform-panel-padding, 16px)}.mform-columns{display:grid;gap:var(--mform-gap, 16px)}.mform-tabbar{display:flex;gap:4px;border-bottom:2px solid var(--mform-border, #d9d5e6);margin-bottom:14px}.mform-tab{padding:8px 18px;font:inherit;font-size:14px;border:none;background:none;color:var(--mform-muted, #6b6580);cursor:pointer}.mform-tab.is-active{color:var(--mform-primary, #6d4bd0);font-weight:600;border-bottom:2px solid var(--mform-primary, #6d4bd0);margin-bottom:-2px}.mform-grid-row{display:flex;align-items:flex-start;gap:8px;padding:10px 0;border-bottom:1px dashed var(--mform-border, #d9d5e6)}.mform-grid-fields{flex:1;display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:var(--mform-gap, 16px)}.mform-row-remove{border:none;background:none;color:var(--mform-muted, #6b6580);font:inherit;cursor:pointer;padding:6px 8px}.mform-row-remove:hover{color:var(--mform-danger, #c62842)}.mform-row-add{align-self:flex-start;background:none;border:1px dashed var(--mform-primary, #6d4bd0);color:var(--mform-primary, #6d4bd0);padding:7px 14px;border-radius:var(--mform-control-radius, 8px);font:inherit;font-size:13px;cursor:pointer}.mform-btn{align-self:flex-start;background:var(--mform-primary, #6d4bd0);color:var(--mform-primary-contrast, #fff);border:none;border-radius:var(--mform-control-radius, 8px);padding:11px 26px;font:inherit;font-weight:600;cursor:pointer}.mform-btn:hover{filter:brightness(1.08)}.mform-btn:focus-visible{outline:2px solid var(--mform-focus, #8e6ff0);outline-offset:2px}.mform-content{font-size:14px}.mform-unsupported{font-size:13px;color:var(--mform-muted, #6b6580);border:1px dashed var(--mform-border, #d9d5e6);border-radius:var(--mform-radius, 10px);padding:10px 14px}.mform-steps{display:flex;gap:18px;list-style:none;margin:0 0 4px;padding:0 0 12px;border-bottom:1px solid var(--mform-border, #d9d5e6);flex-wrap:wrap}.mform-step{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--mform-muted, #6b6580)}.mform-step-index{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;border:1.5px solid var(--mform-border, #d9d5e6);font-size:11px;font-weight:600}.mform-step.is-active{color:var(--mform-primary, #6d4bd0);font-weight:600}.mform-step.is-active .mform-step-index{border-color:var(--mform-primary, #6d4bd0);background:var(--mform-primary, #6d4bd0);color:var(--mform-primary-contrast, #fff)}.mform-step.is-done .mform-step-index{border-color:var(--mform-primary, #6d4bd0);color:var(--mform-primary, #6d4bd0)}.mform-wizard-nav{display:flex;gap:10px;padding-top:4px}.mform-btn-secondary{background:none;border:1px solid var(--mform-primary, #6d4bd0);color:var(--mform-primary, #6d4bd0)}.mform-summary{border:1px solid var(--mform-danger, #c62842);background:var(--mform-danger-bg, #fdf0f2);color:var(--mform-danger, #c62842);border-radius:var(--mform-radius, 10px);padding:12px 16px;font-size:13px}.mform-summary ul{margin:6px 0 0;padding-left:18px}\n"], dependencies: [{ kind: "component", type: FormNodeComponent, selector: "mform-node", inputs: ["node", "engine", "tick", "scope", "bare", "providers"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1155
+ `, isInline: true, styles: [".mform-root{display:flex;flex-direction:column;gap:var(--mform-gap, 16px);font-family:var(--mform-font, system-ui, \"Segoe UI\", sans-serif);color:var(--mform-text, #1f1b2e)}.mform-node{display:contents}.mform-field{display:flex;flex-direction:column;gap:6px}.mform-label{font-size:var(--mform-label-size, 13px);font-weight:var(--mform-label-weight, 600)}.mform-req{color:var(--mform-danger, #c62842);margin-left:2px}.mform-control{font:inherit;width:100%;padding:var(--mform-control-padding, 9px 12px);border:1px solid var(--mform-border, #d9d5e6);border-radius:var(--mform-control-radius, 8px);background:var(--mform-control-bg, #fff);color:inherit;box-sizing:border-box}textarea.mform-control{min-height:72px;resize:vertical}.mform-control:focus-visible{outline:2px solid var(--mform-focus, #8e6ff0);outline-offset:1px;border-color:var(--mform-focus, #8e6ff0)}.mform-field.has-error .mform-control{border-color:var(--mform-danger, #c62842)}.mform-desc{font-size:12px;color:var(--mform-muted, #6b6580)}.mform-error{font-size:12px;color:var(--mform-danger, #c62842)}.mform-choices{display:flex;flex-direction:column;gap:6px}.mform-check{display:flex;align-items:center;gap:8px;font-size:14px;cursor:pointer}.mform-check input{width:16px;height:16px;accent-color:var(--mform-primary, #6d4bd0)}.mform-panel{border:1px solid var(--mform-border, #d9d5e6);border-radius:var(--mform-radius, 10px);overflow:hidden}.mform-panel-head{background:var(--mform-panel-head-bg, linear-gradient(90deg, #efeaff, #f8f6ff));color:var(--mform-panel-head-text, inherit);padding:10px 16px;font-weight:600;font-size:14px;border-bottom:1px solid var(--mform-border, #d9d5e6)}.mform-panel-body,.mform-group,.mform-column,.mform-tabpanel{display:flex;flex-direction:column;gap:var(--mform-gap, 16px)}.mform-panel-body{padding:var(--mform-panel-padding, 16px)}.mform-columns{display:grid;gap:var(--mform-gap, 16px)}@media(max-width:640px){.mform-columns{grid-template-columns:1fr!important}}.mform-affix{display:flex;align-items:center}.mform-affix.has-affix{border:1px solid var(--mform-border, #d9d5e6);border-radius:var(--mform-control-radius, 8px);background:var(--mform-control-bg, #fff)}.mform-affix.has-affix .mform-control{border:none;background:none;flex:1}.mform-affix.has-affix:focus-within{outline:2px solid var(--mform-focus, #8e6ff0);outline-offset:1px}.mform-prefix,.mform-suffix{padding:0 10px;color:var(--mform-muted, #6b6580);font-size:13px;white-space:nowrap}.mform-tags{display:flex;flex-wrap:wrap;gap:6px;align-items:center}.mform-tag{background:var(--mform-primary, #6d4bd0);color:var(--mform-primary-contrast, #fff);border-radius:999px;padding:3px 10px;font-size:12px;display:inline-flex;align-items:center;gap:6px}.mform-tag button{border:none;background:none;color:inherit;cursor:pointer;font-size:12px;padding:0;line-height:1}.mform-tag-input{flex:1;min-width:140px;width:auto}.mform-tabbar{display:flex;gap:4px;border-bottom:2px solid var(--mform-border, #d9d5e6);margin-bottom:14px}.mform-tab{padding:8px 18px;font:inherit;font-size:14px;border:none;background:none;color:var(--mform-muted, #6b6580);cursor:pointer}.mform-tab.is-active{color:var(--mform-primary, #6d4bd0);font-weight:600;border-bottom:2px solid var(--mform-primary, #6d4bd0);margin-bottom:-2px}.mform-grid-row{display:flex;align-items:flex-start;gap:8px;padding:10px 0;border-bottom:1px dashed var(--mform-border, #d9d5e6)}.mform-grid-fields{flex:1;display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:var(--mform-gap, 16px)}.mform-row-remove{border:none;background:none;color:var(--mform-muted, #6b6580);font:inherit;cursor:pointer;padding:6px 8px}.mform-row-remove:hover{color:var(--mform-danger, #c62842)}.mform-row-add{align-self:flex-start;background:none;border:1px dashed var(--mform-primary, #6d4bd0);color:var(--mform-primary, #6d4bd0);padding:7px 14px;border-radius:var(--mform-control-radius, 8px);font:inherit;font-size:13px;cursor:pointer}.mform-btn{align-self:flex-start;background:var(--mform-primary, #6d4bd0);color:var(--mform-primary-contrast, #fff);border:none;border-radius:var(--mform-control-radius, 8px);padding:11px 26px;font:inherit;font-weight:600;cursor:pointer}.mform-btn:hover{filter:brightness(1.08)}.mform-btn:focus-visible{outline:2px solid var(--mform-focus, #8e6ff0);outline-offset:2px}.mform-content{font-size:14px}.mform-unsupported{font-size:13px;color:var(--mform-muted, #6b6580);border:1px dashed var(--mform-border, #d9d5e6);border-radius:var(--mform-radius, 10px);padding:10px 14px}.mform-steps{display:flex;gap:18px;list-style:none;margin:0 0 4px;padding:0 0 12px;border-bottom:1px solid var(--mform-border, #d9d5e6);flex-wrap:wrap}.mform-step{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--mform-muted, #6b6580)}.mform-step-index{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;border:1.5px solid var(--mform-border, #d9d5e6);font-size:11px;font-weight:600}.mform-step.is-active{color:var(--mform-primary, #6d4bd0);font-weight:600}.mform-step.is-active .mform-step-index{border-color:var(--mform-primary, #6d4bd0);background:var(--mform-primary, #6d4bd0);color:var(--mform-primary-contrast, #fff)}.mform-step.is-done .mform-step-index{border-color:var(--mform-primary, #6d4bd0);color:var(--mform-primary, #6d4bd0)}.mform-wizard-nav{display:flex;gap:10px;padding-top:4px}.mform-btn-secondary{background:none;border:1px solid var(--mform-primary, #6d4bd0);color:var(--mform-primary, #6d4bd0)}.mform-summary{border:1px solid var(--mform-danger, #c62842);background:var(--mform-danger-bg, #fdf0f2);color:var(--mform-danger, #c62842);border-radius:var(--mform-radius, 10px);padding:12px 16px;font-size:13px}.mform-summary ul{margin:6px 0 0;padding-left:18px}\n"], dependencies: [{ kind: "component", type: FormNodeComponent, selector: "mform-node", inputs: ["node", "engine", "tick", "scope", "bare", "providers"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
979
1156
  }
980
1157
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FormRendererComponent, decorators: [{
981
1158
  type: Component,
@@ -1036,12 +1213,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
1036
1213
  }
1037
1214
  </form>
1038
1215
  }
1039
- `, styles: [".mform-root{display:flex;flex-direction:column;gap:var(--mform-gap, 16px);font-family:var(--mform-font, system-ui, \"Segoe UI\", sans-serif);color:var(--mform-text, #1f1b2e)}.mform-node{display:contents}.mform-field{display:flex;flex-direction:column;gap:6px}.mform-label{font-size:var(--mform-label-size, 13px);font-weight:var(--mform-label-weight, 600)}.mform-req{color:var(--mform-danger, #c62842);margin-left:2px}.mform-control{font:inherit;width:100%;padding:var(--mform-control-padding, 9px 12px);border:1px solid var(--mform-border, #d9d5e6);border-radius:var(--mform-control-radius, 8px);background:var(--mform-control-bg, #fff);color:inherit;box-sizing:border-box}textarea.mform-control{min-height:72px;resize:vertical}.mform-control:focus-visible{outline:2px solid var(--mform-focus, #8e6ff0);outline-offset:1px;border-color:var(--mform-focus, #8e6ff0)}.mform-field.has-error .mform-control{border-color:var(--mform-danger, #c62842)}.mform-desc{font-size:12px;color:var(--mform-muted, #6b6580)}.mform-error{font-size:12px;color:var(--mform-danger, #c62842)}.mform-choices{display:flex;flex-direction:column;gap:6px}.mform-check{display:flex;align-items:center;gap:8px;font-size:14px;cursor:pointer}.mform-check input{width:16px;height:16px;accent-color:var(--mform-primary, #6d4bd0)}.mform-panel{border:1px solid var(--mform-border, #d9d5e6);border-radius:var(--mform-radius, 10px);overflow:hidden}.mform-panel-head{background:var(--mform-panel-head-bg, linear-gradient(90deg, #efeaff, #f8f6ff));color:var(--mform-panel-head-text, inherit);padding:10px 16px;font-weight:600;font-size:14px;border-bottom:1px solid var(--mform-border, #d9d5e6)}.mform-panel-body,.mform-group,.mform-column,.mform-tabpanel{display:flex;flex-direction:column;gap:var(--mform-gap, 16px)}.mform-panel-body{padding:var(--mform-panel-padding, 16px)}.mform-columns{display:grid;gap:var(--mform-gap, 16px)}.mform-tabbar{display:flex;gap:4px;border-bottom:2px solid var(--mform-border, #d9d5e6);margin-bottom:14px}.mform-tab{padding:8px 18px;font:inherit;font-size:14px;border:none;background:none;color:var(--mform-muted, #6b6580);cursor:pointer}.mform-tab.is-active{color:var(--mform-primary, #6d4bd0);font-weight:600;border-bottom:2px solid var(--mform-primary, #6d4bd0);margin-bottom:-2px}.mform-grid-row{display:flex;align-items:flex-start;gap:8px;padding:10px 0;border-bottom:1px dashed var(--mform-border, #d9d5e6)}.mform-grid-fields{flex:1;display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:var(--mform-gap, 16px)}.mform-row-remove{border:none;background:none;color:var(--mform-muted, #6b6580);font:inherit;cursor:pointer;padding:6px 8px}.mform-row-remove:hover{color:var(--mform-danger, #c62842)}.mform-row-add{align-self:flex-start;background:none;border:1px dashed var(--mform-primary, #6d4bd0);color:var(--mform-primary, #6d4bd0);padding:7px 14px;border-radius:var(--mform-control-radius, 8px);font:inherit;font-size:13px;cursor:pointer}.mform-btn{align-self:flex-start;background:var(--mform-primary, #6d4bd0);color:var(--mform-primary-contrast, #fff);border:none;border-radius:var(--mform-control-radius, 8px);padding:11px 26px;font:inherit;font-weight:600;cursor:pointer}.mform-btn:hover{filter:brightness(1.08)}.mform-btn:focus-visible{outline:2px solid var(--mform-focus, #8e6ff0);outline-offset:2px}.mform-content{font-size:14px}.mform-unsupported{font-size:13px;color:var(--mform-muted, #6b6580);border:1px dashed var(--mform-border, #d9d5e6);border-radius:var(--mform-radius, 10px);padding:10px 14px}.mform-steps{display:flex;gap:18px;list-style:none;margin:0 0 4px;padding:0 0 12px;border-bottom:1px solid var(--mform-border, #d9d5e6);flex-wrap:wrap}.mform-step{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--mform-muted, #6b6580)}.mform-step-index{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;border:1.5px solid var(--mform-border, #d9d5e6);font-size:11px;font-weight:600}.mform-step.is-active{color:var(--mform-primary, #6d4bd0);font-weight:600}.mform-step.is-active .mform-step-index{border-color:var(--mform-primary, #6d4bd0);background:var(--mform-primary, #6d4bd0);color:var(--mform-primary-contrast, #fff)}.mform-step.is-done .mform-step-index{border-color:var(--mform-primary, #6d4bd0);color:var(--mform-primary, #6d4bd0)}.mform-wizard-nav{display:flex;gap:10px;padding-top:4px}.mform-btn-secondary{background:none;border:1px solid var(--mform-primary, #6d4bd0);color:var(--mform-primary, #6d4bd0)}.mform-summary{border:1px solid var(--mform-danger, #c62842);background:var(--mform-danger-bg, #fdf0f2);color:var(--mform-danger, #c62842);border-radius:var(--mform-radius, 10px);padding:12px 16px;font-size:13px}.mform-summary ul{margin:6px 0 0;padding-left:18px}\n"] }]
1216
+ `, styles: [".mform-root{display:flex;flex-direction:column;gap:var(--mform-gap, 16px);font-family:var(--mform-font, system-ui, \"Segoe UI\", sans-serif);color:var(--mform-text, #1f1b2e)}.mform-node{display:contents}.mform-field{display:flex;flex-direction:column;gap:6px}.mform-label{font-size:var(--mform-label-size, 13px);font-weight:var(--mform-label-weight, 600)}.mform-req{color:var(--mform-danger, #c62842);margin-left:2px}.mform-control{font:inherit;width:100%;padding:var(--mform-control-padding, 9px 12px);border:1px solid var(--mform-border, #d9d5e6);border-radius:var(--mform-control-radius, 8px);background:var(--mform-control-bg, #fff);color:inherit;box-sizing:border-box}textarea.mform-control{min-height:72px;resize:vertical}.mform-control:focus-visible{outline:2px solid var(--mform-focus, #8e6ff0);outline-offset:1px;border-color:var(--mform-focus, #8e6ff0)}.mform-field.has-error .mform-control{border-color:var(--mform-danger, #c62842)}.mform-desc{font-size:12px;color:var(--mform-muted, #6b6580)}.mform-error{font-size:12px;color:var(--mform-danger, #c62842)}.mform-choices{display:flex;flex-direction:column;gap:6px}.mform-check{display:flex;align-items:center;gap:8px;font-size:14px;cursor:pointer}.mform-check input{width:16px;height:16px;accent-color:var(--mform-primary, #6d4bd0)}.mform-panel{border:1px solid var(--mform-border, #d9d5e6);border-radius:var(--mform-radius, 10px);overflow:hidden}.mform-panel-head{background:var(--mform-panel-head-bg, linear-gradient(90deg, #efeaff, #f8f6ff));color:var(--mform-panel-head-text, inherit);padding:10px 16px;font-weight:600;font-size:14px;border-bottom:1px solid var(--mform-border, #d9d5e6)}.mform-panel-body,.mform-group,.mform-column,.mform-tabpanel{display:flex;flex-direction:column;gap:var(--mform-gap, 16px)}.mform-panel-body{padding:var(--mform-panel-padding, 16px)}.mform-columns{display:grid;gap:var(--mform-gap, 16px)}@media(max-width:640px){.mform-columns{grid-template-columns:1fr!important}}.mform-affix{display:flex;align-items:center}.mform-affix.has-affix{border:1px solid var(--mform-border, #d9d5e6);border-radius:var(--mform-control-radius, 8px);background:var(--mform-control-bg, #fff)}.mform-affix.has-affix .mform-control{border:none;background:none;flex:1}.mform-affix.has-affix:focus-within{outline:2px solid var(--mform-focus, #8e6ff0);outline-offset:1px}.mform-prefix,.mform-suffix{padding:0 10px;color:var(--mform-muted, #6b6580);font-size:13px;white-space:nowrap}.mform-tags{display:flex;flex-wrap:wrap;gap:6px;align-items:center}.mform-tag{background:var(--mform-primary, #6d4bd0);color:var(--mform-primary-contrast, #fff);border-radius:999px;padding:3px 10px;font-size:12px;display:inline-flex;align-items:center;gap:6px}.mform-tag button{border:none;background:none;color:inherit;cursor:pointer;font-size:12px;padding:0;line-height:1}.mform-tag-input{flex:1;min-width:140px;width:auto}.mform-tabbar{display:flex;gap:4px;border-bottom:2px solid var(--mform-border, #d9d5e6);margin-bottom:14px}.mform-tab{padding:8px 18px;font:inherit;font-size:14px;border:none;background:none;color:var(--mform-muted, #6b6580);cursor:pointer}.mform-tab.is-active{color:var(--mform-primary, #6d4bd0);font-weight:600;border-bottom:2px solid var(--mform-primary, #6d4bd0);margin-bottom:-2px}.mform-grid-row{display:flex;align-items:flex-start;gap:8px;padding:10px 0;border-bottom:1px dashed var(--mform-border, #d9d5e6)}.mform-grid-fields{flex:1;display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:var(--mform-gap, 16px)}.mform-row-remove{border:none;background:none;color:var(--mform-muted, #6b6580);font:inherit;cursor:pointer;padding:6px 8px}.mform-row-remove:hover{color:var(--mform-danger, #c62842)}.mform-row-add{align-self:flex-start;background:none;border:1px dashed var(--mform-primary, #6d4bd0);color:var(--mform-primary, #6d4bd0);padding:7px 14px;border-radius:var(--mform-control-radius, 8px);font:inherit;font-size:13px;cursor:pointer}.mform-btn{align-self:flex-start;background:var(--mform-primary, #6d4bd0);color:var(--mform-primary-contrast, #fff);border:none;border-radius:var(--mform-control-radius, 8px);padding:11px 26px;font:inherit;font-weight:600;cursor:pointer}.mform-btn:hover{filter:brightness(1.08)}.mform-btn:focus-visible{outline:2px solid var(--mform-focus, #8e6ff0);outline-offset:2px}.mform-content{font-size:14px}.mform-unsupported{font-size:13px;color:var(--mform-muted, #6b6580);border:1px dashed var(--mform-border, #d9d5e6);border-radius:var(--mform-radius, 10px);padding:10px 14px}.mform-steps{display:flex;gap:18px;list-style:none;margin:0 0 4px;padding:0 0 12px;border-bottom:1px solid var(--mform-border, #d9d5e6);flex-wrap:wrap}.mform-step{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--mform-muted, #6b6580)}.mform-step-index{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;border:1.5px solid var(--mform-border, #d9d5e6);font-size:11px;font-weight:600}.mform-step.is-active{color:var(--mform-primary, #6d4bd0);font-weight:600}.mform-step.is-active .mform-step-index{border-color:var(--mform-primary, #6d4bd0);background:var(--mform-primary, #6d4bd0);color:var(--mform-primary-contrast, #fff)}.mform-step.is-done .mform-step-index{border-color:var(--mform-primary, #6d4bd0);color:var(--mform-primary, #6d4bd0)}.mform-wizard-nav{display:flex;gap:10px;padding-top:4px}.mform-btn-secondary{background:none;border:1px solid var(--mform-primary, #6d4bd0);color:var(--mform-primary, #6d4bd0)}.mform-summary{border:1px solid var(--mform-danger, #c62842);background:var(--mform-danger-bg, #fdf0f2);color:var(--mform-danger, #c62842);border-radius:var(--mform-radius, 10px);padding:12px 16px;font-size:13px}.mform-summary ul{margin:6px 0 0;padding-left:18px}\n"] }]
1040
1217
  }], ctorParameters: () => [], propDecorators: { schema: [{ type: i0.Input, args: [{ isSignal: true, alias: "schema", required: false }] }], source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: false }] }], initialData: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialData", required: false }] }], optionsProviders: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionsProviders", required: false }] }], messages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messages", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], submitted: [{ type: i0.Output, args: ["submitted"] }], valueChanged: [{ type: i0.Output, args: ["valueChanged"] }] } });
1041
1218
 
1219
+ /*
1220
+ * Runtime entry point of @mosaicoo/form-angular.
1221
+ *
1222
+ * Architectural note: this primary entry stays runtime-only. Authoring
1223
+ * tooling (the visual designer) will ship as a SECONDARY entry point
1224
+ * (`@mosaicoo/form-angular/designer`) so applications that only render
1225
+ * forms never load authoring code — a requirement for federated hosts.
1226
+ */
1227
+
1042
1228
  /**
1043
1229
  * Generated bundle index. Do not edit.
1044
1230
  */
1045
1231
 
1046
- export { FormNodeComponent, FormRendererComponent };
1232
+ export { FormNodeComponent, FormRendererComponent, MFORM_FIELD_COMPONENTS, MFORM_REMOTE_FETCHER, provideMosaicooForm };
1047
1233
  //# sourceMappingURL=mosaicoo-form-angular.mjs.map