@ng-forge/dynamic-forms 1.3.0-next.3 → 1.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.
- package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-bnrwNw7Y.mjs +156 -0
- package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-bnrwNw7Y.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-EuYCbquo.mjs → ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-DJinfAnV.mjs} +2 -2
- package/fesm2022/{ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-EuYCbquo.mjs.map → ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-DJinfAnV.mjs.map} +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-bootstrap-web-mcp-2wQK_wPp.mjs → ng-forge-dynamic-forms-bootstrap-web-mcp-Ce93FPLR.mjs} +2 -2
- package/fesm2022/{ng-forge-dynamic-forms-bootstrap-web-mcp-2wQK_wPp.mjs.map → ng-forge-dynamic-forms-bootstrap-web-mcp-Ce93FPLR.mjs.map} +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-form-state-manager-DcOXRFRL.mjs → ng-forge-dynamic-forms-form-state-manager-3Ng7d_U2.mjs} +9 -3
- package/fesm2022/ng-forge-dynamic-forms-form-state-manager-3Ng7d_U2.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-internal.mjs +145 -14
- package/fesm2022/ng-forge-dynamic-forms-internal.mjs.map +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-page-field.component-BRjQmWC9.mjs → ng-forge-dynamic-forms-page-field.component-Bsd8YpzL.mjs} +37 -5
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-Bsd8YpzL.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms.mjs +85 -26
- package/fesm2022/ng-forge-dynamic-forms.mjs.map +1 -1
- package/internal/src/lib/core/expressions/parser/evaluator.d.ts +26 -0
- package/internal/src/lib/core/expressions/parser/evaluator.d.ts.map +1 -0
- package/internal/src/lib/core/expressions/parser/expression-parser.d.ts +20 -0
- package/internal/src/lib/core/expressions/parser/expression-parser.d.ts.map +1 -0
- package/internal/src/lib/core/expressions/parser/parser.d.ts +51 -0
- package/internal/src/lib/core/expressions/parser/parser.d.ts.map +1 -0
- package/internal/src/lib/core/expressions/parser/static-check.d.ts +25 -0
- package/internal/src/lib/core/expressions/parser/static-check.d.ts.map +1 -0
- package/internal/src/lib/core/expressions/parser/tokenizer.d.ts +19 -0
- package/internal/src/lib/core/expressions/parser/tokenizer.d.ts.map +1 -0
- package/internal/src/lib/core/expressions/parser/types.d.ts +117 -0
- package/internal/src/lib/core/expressions/parser/types.d.ts.map +1 -0
- package/internal/src/lib/errors/dynamic-form-error.d.ts +6 -0
- package/internal/src/lib/errors/dynamic-form-error.d.ts.map +1 -0
- package/package.json +1 -1
- package/types/ng-forge-dynamic-forms-integration.d.ts +10 -2
- package/types/ng-forge-dynamic-forms-internal.d.ts +71 -3
- package/types/ng-forge-dynamic-forms.d.ts +63 -2
- package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-CiKN-mcc.mjs +0 -12
- package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-CiKN-mcc.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-form-state-manager-DcOXRFRL.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-BRjQmWC9.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ng-forge-dynamic-forms.mjs","names":["isPageField","isRowField","DynamicFormLogger","DynamicFormLogger","DynamicFormLogger","DynamicFormLogger","isContainerField","DF_FIELD_TEMPLATES","DynamicFormError","isWrapperTypeDefinition","DynamicFormLogger","DF_FIELD_TEMPLATES","DynamicFormLogger","DynamicFormLogger"],"sources":["../../../../packages/dynamic-forms/src/lib/utils/submission-handler/submission-handler.ts","../../../../packages/dynamic-forms/src/lib/utils/preload-form-components/preload-form-components.ts","../../../../packages/dynamic-forms/src/lib/events/constants/page-change.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/pager-state.event.ts","../../../../packages/dynamic-forms/src/lib/providers/features/page-preload/page-preload.token.ts","../../../../packages/dynamic-forms/src/lib/utils/page-utils/collect-leaf-field-keys.ts","../../../../packages/dynamic-forms/src/lib/core/page-orchestrator/page-orchestrator.component.ts","../../../../packages/dynamic-forms/src/lib/core/derivation/config-has-derivations.ts","../../../../packages/dynamic-forms/src/lib/core/derivation/derivation-render-gate.ts","../../../../packages/dynamic-forms/src/lib/providers/features/web-mcp/web-mcp.token.ts","../../../../packages/dynamic-forms/src/lib/core/web-mcp/web-mcp-gate.ts","../../../../packages/dynamic-forms/src/lib/providers/form-initializer.token.ts","../../../../packages/dynamic-forms/src/lib/core/registry/dynamic-form-instance-registry.service.ts","../../../../packages/dynamic-forms/src/lib/core/registry/form-id-prefix.service.ts","../../../../packages/dynamic-forms/src/lib/providers/dynamic-form-di.ts","../../../../packages/dynamic-forms/src/lib/events/event-dispatcher.ts","../../../../packages/dynamic-forms/src/lib/directives/df-template.directive.ts","../../../../packages/dynamic-forms/src/lib/dynamic-form.component.ts","../../../../packages/dynamic-forms/src/lib/providers/built-in-addons.ts","../../../../packages/dynamic-forms/src/lib/providers/built-in-fields.ts","../../../../packages/dynamic-forms/src/lib/wrappers/create-wrappers.ts","../../../../packages/dynamic-forms/src/lib/providers/dynamic-form-providers.ts","../../../../packages/dynamic-forms/src/lib/providers/features/event-form-value/with-event-form-value.ts","../../../../packages/dynamic-forms/src/lib/providers/features/value-exclusion/with-value-exclusion-defaults.ts","../../../../packages/dynamic-forms/src/lib/providers/features/page-preload/with-page-preload.ts","../../../../packages/dynamic-forms/src/lib/providers/features/field-windowing/with-field-windowing.ts","../../../../packages/dynamic-forms/src/lib/providers/features/web-mcp/with-web-mcp.ts","../../../../packages/dynamic-forms/src/lib/providers/features/validation-execution/with-validation-execution-defaults.ts","../../../../packages/dynamic-forms/src/lib/providers/features/legacy-status-classes/with-legacy-status-classes.ts","../../../../packages/dynamic-forms/src/lib/wrappers/wrapper-props.ts","../../../../packages/dynamic-forms/src/lib/addons/text-addon.component.ts","../../../../packages/dynamic-forms/src/lib/addons/template-addon.component.ts","../../../../packages/dynamic-forms/src/lib/addons/component-addon.component.ts","../../../../packages/dynamic-forms/src/lib/providers/features/addons/with-custom-addon.ts","../../../../packages/dynamic-forms/src/lib/providers/features/addons/with-addon-actions.ts","../../../../packages/dynamic-forms/src/lib/utils/validate-form-config/validate-form-config.ts","../../../../packages/dynamic-forms/src/lib/events/constants/go-to-page.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/next-page.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/previous-page.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/form-reset.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/form-clear.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/append-array-item.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/prepend-array-item.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/insert-array-item.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/pop-array-item.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/shift-array-item.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/move-array-item.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/remove-at-index.event.ts","../../../../packages/dynamic-forms/src/lib/events/array-event.ts"],"sourcesContent":["import { Signal } from '@angular/core';\nimport { FieldTree, submit, TreeValidationResult } from '@angular/forms/signals';\nimport { catchError, defer, EMPTY, exhaustMap, firstValueFrom, from, isObservable, Observable, tap } from 'rxjs';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { FormSubmitEvent } from '../../events/constants/submit.event';\nimport { FormConfig } from '@ng-forge/dynamic-forms/internal';\nimport { RegisteredFieldTypes } from '@ng-forge/dynamic-forms/internal';\nimport type { InferFormModel } from '@ng-forge/dynamic-forms/internal';\nimport type { Logger } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Options for creating a submission handler.\n *\n * @typeParam TFields - Array of registered field types available for this form\n * @typeParam TModel - The form value model type (inferred from TFields by default)\n */\nexport interface SubmissionHandlerOptions<\n TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[],\n TModel extends Record<string, unknown> = InferFormModel<TFields>,\n> {\n /** Event bus instance for listening to submit events */\n eventBus: EventBus;\n /** Signal containing the form configuration */\n configSignal: Signal<FormConfig<TFields>>;\n /** Signal containing the form instance */\n formSignal: Signal<FieldTree<TModel>>;\n /** Signal indicating whether the form is currently valid */\n validSignal: Signal<boolean>;\n /** Logger instance for consistent error reporting */\n logger: Logger;\n}\n\n/**\n * Reads whether async validators are still resolving, so a skipped submission\n * can say *why* it was skipped rather than reporting a validation failure that\n * has not actually happened yet.\n */\nfunction isPending<TModel extends Record<string, unknown>>(formSignal: Signal<FieldTree<TModel>>): boolean {\n return formSignal()().pending();\n}\n\n/**\n * Whether a resolved action result is a `TreeValidationResult` carrying server errors.\n *\n * `SubmissionConfig.action` also permits arbitrary success payloads (an Observable\n * action is typically an HTTP call resolving to a response body), so anything that\n * is not shaped like one-or-many `ValidationError` is reported to `submit()` as\n * success rather than being misread as a validation failure.\n */\nfunction isTreeValidationErrors(result: unknown): result is TreeValidationResult {\n const isError = (v: unknown): boolean => typeof v === 'object' && v !== null && 'kind' in v;\n return Array.isArray(result) ? result.every(isError) && result.length > 0 : isError(result);\n}\n\n/**\n * Wraps a submission action to handle both Promise and Observable returns.\n * Converts Observables to Promises for compatibility with Angular Signal Forms' submit().\n *\n * The resolved value is handed back to `submit()` so that an action returning\n * `TreeValidationResult` has its server errors applied to the form.\n *\n * @param action - The submission action function\n * @returns A wrapped function that returns a Promise\n */\nfunction wrapSubmissionAction<TModel extends Record<string, unknown>>(\n action: (formTree: FieldTree<TModel>) => unknown,\n): (formTree: FieldTree<TModel>) => Promise<TreeValidationResult> {\n return async (formTree: FieldTree<TModel>): Promise<TreeValidationResult> => {\n const result = action(formTree);\n // If the action returns an Observable, take its first emission\n const resolved = isObservable(result) ? await firstValueFrom(result) : await Promise.resolve(result);\n\n return isTreeValidationErrors(resolved) ? resolved : undefined;\n };\n}\n\n/**\n * Creates an Observable that handles form submission with optional submission action.\n *\n * @param options - Configuration options for the submission handler\n * @returns Observable that processes submissions (emits when submission completes)\n */\nexport function createSubmissionHandler<\n TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[],\n TModel extends Record<string, unknown> = InferFormModel<TFields>,\n>(options: SubmissionHandlerOptions<TFields, TModel>): Observable<unknown> {\n const { eventBus, configSignal, formSignal, validSignal, logger } = options;\n\n // exhaustMap ensures first-submit-wins: a second submit event while the first\n // is in-flight is silently dropped rather than cancelling the running Promise.\n // switchMap would unsubscribe the Observable wrapper but cannot cancel the\n // underlying Promise, causing both side effects to execute.\n return eventBus.on<FormSubmitEvent>('submit').pipe(\n exhaustMap((event) => {\n // Taking the event is reported before anything else: a caller waiting on a\n // reply distinguishes \"dropped by exhaustMap\" from \"running\" by whether\n // this ran during its synchronous dispatch.\n const reply = event.reply;\n reply?.accept();\n\n const submissionConfig = configSignal().submission;\n\n // If no submission action is configured, let the submitted output handle it\n // This maintains backward compatibility for users handling submission manually\n if (!submissionConfig?.action) {\n reply?.settle(validSignal() ? { status: 'dispatched' } : { status: 'validation-failed' });\n return EMPTY;\n }\n\n // Guard: match the (submitted) output's safety contract — reject submission\n // when the form is invalid or has pending async validators.\n if (!validSignal()) {\n logger.debug('Submission action skipped: form is not valid (invalid or pending async validators)');\n reply?.settle(isPending(formSignal) ? { status: 'pending-validation' } : { status: 'validation-failed' });\n return EMPTY;\n }\n\n // Type assertion needed: submission.action accepts the form tree but its signature\n // is defined broadly in FormConfig. The actual runtime type is FieldTree<TModel>.\n const wrappedAction = wrapSubmissionAction<TModel>(submissionConfig.action as (formTree: FieldTree<TModel>) => unknown);\n\n // Use Angular Signal Forms' native submit() function\n // This automatically:\n // - Sets form.submitting() to true during execution\n // - Applies server errors to form fields on completion\n // - Sets form.submitting() to false when done\n // catchError keeps the exhaustMap stream alive after action failure —\n // without it, an unhandled error would terminate all future submissions.\n // `defer` so the form tree is read when the inner observable is subscribed,\n // keeping the post-submit error read on the same tree the action ran against.\n return defer(() => {\n const formTree = formSignal();\n\n return from(submit(formTree, wrappedAction)).pipe(\n // `submit()` resolves the same way whether the action succeeded or came\n // back with server errors — it applies them to the form rather than\n // rejecting — so the form's own errors are what separate the two.\n tap(() => {\n // Server errors land on the fields they belong to, so the whole-tree\n // summary is what distinguishes a rejected submission from a clean one.\n reply?.settle(formTree().errorSummary().length ? { status: 'server-errors' } : { status: 'success' });\n }),\n catchError((error: unknown) => {\n logger.error('Submission action failed:', error);\n reply?.settle({ status: 'action-failed', error });\n return EMPTY;\n }),\n );\n });\n }),\n );\n}\n","import { inject, Type } from '@angular/core';\nimport {\n DEFAULT_WRAPPERS,\n FieldDef,\n FormConfig,\n isPageField,\n WRAPPER_AUTO_ASSOCIATIONS,\n WRAPPER_COMPONENT_LOAD_CACHE,\n WRAPPER_REGISTRY,\n} from '@ng-forge/dynamic-forms/internal';\nimport { WRAPPER_COMPONENT_CACHE } from '@ng-forge/dynamic-forms/internal';\nimport { injectFieldRegistry } from '../inject-field-registry/inject-field-registry';\nimport { loadWrapperComponent } from '../wrapper-chain/wrapper-chain';\nimport { resolveWrappers } from '../resolve-wrappers/resolve-wrappers';\nimport { normalizeSimplifiedArrays } from '../array-field/normalize-simplified-arrays';\nimport { getNormalizedArrayMetadata } from '../array-field/normalized-array-metadata';\n\n/**\n * Collects every field type named anywhere in a config, including inside\n * containers. Containers hold their children under `fields`, and array item\n * templates under `fields` too, so one recursive walk covers both.\n */\nfunction collectFieldDefs(fields: readonly FieldDef<unknown>[] | undefined, out: FieldDef<unknown>[] = []): FieldDef<unknown>[] {\n for (const field of fields ?? []) {\n out.push(field);\n const children = (field as { fields?: unknown }).fields;\n if (Array.isArray(children)) {\n // Array item templates nest one level deeper: `fields: [[...template]]`.\n for (const child of children) {\n if (Array.isArray(child)) collectFieldDefs(child as FieldDef<unknown>[], out);\n else collectFieldDefs([child as FieldDef<unknown>], out);\n }\n }\n\n const metadata = getNormalizedArrayMetadata(field);\n const template = metadata?.template;\n if (Array.isArray(template)) collectFieldDefs(template as readonly FieldDef<unknown>[], out);\n else if (template) collectFieldDefs([template as FieldDef<unknown>], out);\n if (metadata?.autoRemoveButton) collectFieldDefs([metadata.autoRemoveButton], out);\n }\n return out;\n}\n\nexport interface FormComponentPreloader {\n /** Preload a complete non-paged form config. Paged configs are orchestrator-owned. */\n readonly preloadConfig: (config: FormConfig) => void;\n /** Preload the exact field subtree selected for rendering. */\n readonly preloadFields: (fields: readonly FieldDef<unknown>[]) => void;\n}\n\n/**\n * Warms the field- and wrapper-component caches for everything a config will\n * actually render, in parallel, as soon as the config is known.\n *\n * Without this the two sets load in sequence: a field's wrapper chain is\n * resolved inside `DfFieldOutlet`, which does not exist until that field's own\n * component has loaded. Measured on the 240-field fixture, that dependent\n * waterfall put the last wrapper chunk 30ms before first paint on localhost,\n * where a round trip costs ~1ms — on a real network each wave costs a full RTT.\n *\n * Only the current render scope is fetched: a flat form, or the active page\n * window selected by PageOrchestrator. Both loaders dedupe (field loads through\n * `COMPONENT_LOAD_CACHE`, wrapper loads through the module system's own\n * `import()` dedup), so racing the normal resolution path is safe.\n *\n * Warming the caches also lets the sync fast paths take over: `resolveFieldSync`\n * and the wrapper chain controller's \"every wrapper cached\" branch both skip\n * their async hop entirely once the cache is populated.\n *\n * Failures are swallowed on purpose. This is a head start, not a load-bearing\n * step — every one of these types is loaded again through the normal path,\n * which owns the real error reporting.\n */\nexport function injectFormComponentPreloader(): FormComponentPreloader {\n const fieldRegistry = injectFieldRegistry();\n const wrapperRegistry = inject(WRAPPER_REGISTRY);\n const wrapperCache = inject(WRAPPER_COMPONENT_CACHE);\n const wrapperLoadCache = inject(WRAPPER_COMPONENT_LOAD_CACHE);\n const autoAssociations = inject(WRAPPER_AUTO_ASSOCIATIONS);\n const defaultWrappers = inject(DEFAULT_WRAPPERS, { optional: true });\n const preloadedConfigs = new WeakSet<FormConfig>();\n const preloadedFieldRoots = new WeakSet<FieldDef<unknown>>();\n\n const preloadFields = (fields: readonly FieldDef<unknown>[]): void => {\n const unseenFields = fields.filter((field) => {\n if (preloadedFieldRoots.has(field)) return false;\n preloadedFieldRoots.add(field);\n return true;\n });\n if (unseenFields.length === 0) return;\n\n const normalizedFields = normalizeSimplifiedArrays(unseenFields);\n const defs = collectFieldDefs(normalizedFields);\n if (defs.length === 0) return;\n\n const fieldTypes = new Set<string>();\n const wrapperTypes = new Set<string>();\n\n for (const def of defs) {\n if (def.type) fieldTypes.add(def.type);\n // Pure function of the field def plus registry state, all of it known\n // here — which is what makes the wrapper set computable before any field\n // has rendered.\n for (const wrapper of resolveWrappers(def, defaultWrappers?.(), autoAssociations, wrapperRegistry)) {\n wrapperTypes.add(wrapper.type);\n }\n }\n\n const started: Promise<unknown>[] = [];\n for (const type of fieldTypes) {\n if (fieldRegistry.getLoadedComponent(type)) continue;\n started.push(Promise.resolve(fieldRegistry.loadTypeComponent(type)).catch(() => undefined));\n }\n for (const type of wrapperTypes) {\n if (wrapperCache.has(type)) continue;\n started.push(\n loadWrapperComponent(type, wrapperRegistry, wrapperCache, wrapperLoadCache).catch((): Type<unknown> | undefined => undefined),\n );\n }\n // Deliberately not awaited: rendering must not be gated on the head start.\n void Promise.allSettled(started);\n };\n\n return {\n preloadConfig: (config: FormConfig): void => {\n if (preloadedConfigs.has(config)) return;\n preloadedConfigs.add(config);\n\n const fields = config.fields as readonly FieldDef<unknown>[];\n // PageOrchestrator owns paged rendering and calls preloadFields for the\n // active page plus its configured neighbours. Walking the raw config here\n // would eagerly fetch chunks for every distant page.\n if (fields.length > 0 && fields.every(isPageField)) return;\n preloadFields(fields);\n },\n preloadFields,\n };\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event emitted when the active page of a paged form changes. */\nexport class PageChangeEvent implements FormEvent {\n readonly type = 'page-change' as const;\n\n constructor(\n /** The current page index (0-based) */\n public readonly currentPageIndex: number,\n /** Total number of pages */\n public readonly totalPages: number,\n /** Previous page index (0-based), undefined if first navigation */\n public readonly previousPageIndex?: number,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\nimport { PagerState } from '../../core/page-orchestrator/page-orchestrator.interfaces';\n\n/**\n * Event emitted whenever the pager state of a paged form changes.\n *\n * Unlike `PageChangeEvent`, which fires only when the active page changed, this\n * fires on any change to the derived state — including when `isFirstPage` /\n * `isLastPage` flip because a page's `hidden` logic toggled and the set of\n * visible pages shifted, with the active page never moving.\n */\nexport class PagerStateEvent implements FormEvent {\n readonly type = 'pager-state' as const;\n\n constructor(public state: PagerState) {}\n}\n","import { InjectionToken } from '@angular/core';\n\n/**\n * Global default for how many pages on each side of the current page a paged\n * form mounts during idle time (the \"preload window\").\n *\n * A window of `1` (the default) renders the current page directly and mounts its\n * immediate neighbours (±1) on idle, so sequential navigation is flicker-free while\n * distant pages stay unmounted. Larger windows pre-warm more pages (useful for\n * jump navigation) at the cost of more initial DOM + change detection; `0`\n * mounts only the current page.\n *\n * @internal\n */\nexport const PAGE_PRELOAD_WINDOW = new InjectionToken<number>('PAGE_PRELOAD_WINDOW', {\n providedIn: 'root',\n factory: () => 1,\n});\n","import { isGenericContainerField, isRowField } from '@ng-forge/dynamic-forms/internal';\nimport type { FieldDef } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Form-node keys owned by a page's fields.\n *\n * Layout containers (`row`, `container`) are flattened by `mapFieldToForm`, so no form node\n * exists under their own key — traverse their children instead. `group` and `array` own a node\n * whose `valid()` already aggregates descendants, so their key is used as-is.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any field shape for recursive traversal\nexport function collectLeafFieldKeys(fields: readonly FieldDef<any>[]): string[] {\n const keys: string[] = [];\n\n for (const field of fields) {\n if (isRowField(field) || isGenericContainerField(field)) {\n keys.push(...collectLeafFieldKeys(field.fields as readonly FieldDef<unknown>[]));\n } else if (field.key) {\n keys.push(field.key);\n }\n }\n\n return keys;\n}\n","import { ChangeDetectionStrategy, Component, computed, inject, input, linkedSignal, untracked } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { PageNavigationOptions } from '../../events/constants/go-to-page.event';\nimport { NextPageEvent } from '../../events/constants/next-page.event';\nimport { PageChangeEvent } from '../../events/constants/page-change.event';\nimport { PreviousPageEvent } from '../../events/constants/previous-page.event';\nimport { NavigationResult, PagerState } from './page-orchestrator.interfaces';\nimport { PageField } from '@ng-forge/dynamic-forms/internal';\nimport { ContainerLogicConfig } from '@ng-forge/dynamic-forms/internal';\nimport { FieldSignalContext } from '@ng-forge/dynamic-forms/internal';\nimport PageFieldComponent from '../../fields/page/page-field.component';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { PagerStateEvent } from '../../events/constants/pager-state.event';\nimport { FieldTree } from '@angular/forms/signals';\nimport { FIELD_SIGNAL_CONTEXT, FORM_OPTIONS } from '@ng-forge/dynamic-forms/internal';\nimport { ConditionalExpression } from '@ng-forge/dynamic-forms/internal';\nimport { evaluateCondition } from '@ng-forge/dynamic-forms/internal';\nimport { FunctionRegistryService } from '@ng-forge/dynamic-forms/internal';\nimport { FieldContextRegistryService } from '@ng-forge/dynamic-forms/internal';\nimport { PAGE_PRELOAD_WINDOW } from '../../providers/features/page-preload/page-preload.token';\nimport { clampWindowSize } from '../../providers/features/clamp-window';\nimport { collectLeafFieldKeys } from '../../utils/page-utils/collect-leaf-field-keys';\nimport { FormStateManager } from '../../state/form-state-manager';\nimport { injectFormComponentPreloader } from '../../utils/preload-form-components/preload-form-components';\n\n/**\n * PageOrchestrator manages page navigation and visibility for paged forms.\n * It acts as an intermediary between the DynamicForm component and PageField components,\n * handling page state management and navigation events without interfering with form data.\n */\n@Component({\n selector: 'div[page-orchestrator]',\n imports: [PageFieldComponent],\n template: `\n @for (page of pageRenderStates(); track page.field.key) {\n <!--\n Skip pages hidden by 'hidden' logic conditions entirely. FormStateManager\n derives schema/value/validators from config (not from mounted components),\n so unmounting a hidden page has no effect on form state — only on render +\n CD cost. This is the page-level equivalent of the existing field-level\n \\`@if (!field.hidden())\\` gate in page-field.component.ts.\n -->\n @if (!page.hidden) {\n @if (page.active || page.preload) {\n @defer (when page.active; on idle) {\n <section page-field [field]=\"page.field\" [key]=\"page.field.key\" [pageIndex]=\"page.index\" [isVisible]=\"page.active\"></section>\n } @placeholder {\n <div class=\"df-page-placeholder\" [attr.data-page-index]=\"page.index\" [attr.data-page-key]=\"page.field.key\"></div>\n }\n } @else {\n <!--\n Pages outside the preload window remain lightweight placeholders.\n Form state derives from config, so leaving their components unmounted\n does not affect validity, derivations, or navigation. The active page\n renders directly; configured neighbours preload declaratively on idle.\n -->\n <div class=\"df-page-placeholder\" [attr.data-page-index]=\"page.index\" [attr.data-page-key]=\"page.field.key\"></div>\n }\n }\n }\n `,\n styleUrl: './page-orchestrator.component.scss',\n host: {\n class: 'df-page-orchestrator',\n '[attr.data-current-page]': 'state().currentPageIndex',\n '[attr.data-total-pages]': 'state().totalPages',\n },\n providers: [\n {\n provide: FIELD_SIGNAL_CONTEXT,\n useFactory: (orchestrator: PageOrchestratorComponent) => orchestrator.extendedFieldSignalContext(),\n deps: [PageOrchestratorComponent],\n },\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class PageOrchestratorComponent {\n private readonly eventBus = inject(EventBus);\n private readonly fieldContextRegistry = inject(FieldContextRegistryService);\n private readonly functionRegistry = inject(FunctionRegistryService);\n private readonly formOptions = inject(FORM_OPTIONS, { optional: true });\n private readonly globalPreloadWindow = inject(PAGE_PRELOAD_WINDOW);\n private readonly stateManager = inject(FormStateManager, { optional: true });\n\n /** Pending programmatic page request, owned by FormStateManager. */\n private readonly pendingPageRequest = computed(() => this.stateManager?.pendingPageRequest() ?? null);\n\n /** Whether validation belongs to the page definitions currently being rendered. */\n private readonly schemaCurrent = computed(() => this.stateManager?.isSchemaCurrent() ?? true);\n\n /** Stable ownership scope; page arrays can be recreated during one config transition. */\n private readonly configScope = computed(() => this.stateManager?.activeConfig());\n\n /** Array of page field definitions to render */\n pageFields = input.required<PageField[]>();\n\n /**\n * Root form instance from parent DynamicForm.\n * Uses FieldTree<unknown> to accept any form type.\n */\n form = input.required<FieldTree<unknown>>();\n\n /** Field signal context for child fields */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- FieldSignalContext is contravariant in TModel, using any allows accepting any form type\n fieldSignalContext = input.required<FieldSignalContext<any>>();\n\n /**\n * Computed signal that tracks which pages are hidden.\n * Returns an array of booleans where true means the page is hidden.\n * This signal is reactive and will re-evaluate when form values change.\n */\n readonly pageHiddenStates = computed(() => {\n const pages = this.pageFields();\n\n return pages.map((page) => this.evaluatePageHidden(page));\n });\n\n /**\n * Computed signal that returns indices of visible (non-hidden) pages.\n * This is used for navigation to skip hidden pages.\n */\n readonly visiblePageIndices = computed(() => {\n const hiddenStates = this.pageHiddenStates();\n return hiddenStates\n .map((hidden, index) => ({ index, hidden }))\n .filter((item) => !item.hidden)\n .map((item) => item.index);\n });\n\n /** Current page ownership, reset atomically when the active config changes. */\n private readonly activePageOwnership = linkedSignal<\n object | undefined,\n {\n config: object | undefined;\n initialized: boolean;\n index: number;\n }\n >({\n source: this.configScope,\n computation: (config, previous) => {\n const totalPages = this.pageFields().length;\n\n if (totalPages === 0) return { config, initialized: true, index: 0 };\n\n // Untracked: re-land on a config swap, but never on a later validity or visibility change.\n return untracked(() => {\n // A newly mounted pager may restore ownership for the same config. An existing pager must\n // ignore ownership when the config changes because its outgoing effect can still publish\n // the previous index during that transition.\n const owned = this.stateManager?.activePageState();\n const mayRestore = previous === undefined || previous.source === config;\n if (\n mayRestore &&\n owned !== undefined &&\n owned.config === config &&\n owned.initialized &&\n owned.index >= 0 &&\n owned.index < totalPages\n ) {\n return { config, initialized: true, index: owned.index };\n }\n\n if (this.initialPage().validate && !this.schemaCurrent()) {\n return { config, initialized: false, index: 0 };\n }\n\n return { config, initialized: true, index: this.resolveInitialLanding() };\n });\n },\n });\n\n /** Actual page index, excluding hidden pages from its numbering. */\n private readonly currentPageIndex = computed(() => this.activePageOwnership().index);\n\n private setCurrentPageIndex(index: number): void {\n this.activePageOwnership.update((ownership) => ({ ...ownership, initialized: true, index }));\n }\n\n /** Where `initialPage` actually lands: hidden targets resolve forward, gated ones stop on the first invalid page. */\n private resolveInitialLanding(): number {\n const { index, validate } = this.initialPage();\n const visible = this.visiblePageIndices();\n if (index === 0 || visible.length === 0) return 0;\n\n const target = visible.includes(index) ? index : this.findNearestVisiblePage(index, visible);\n if (target <= 0) return Math.max(target, 0);\n if (!validate) return target;\n\n const firstInvalid = visible.filter((i) => i < target).find((i) => !this.isPageValid(i));\n return firstInvalid ?? target;\n }\n\n /** Resolved `FormOptions.initialPage`: out-of-range clamps to the last page, invalid values fall back to 0. */\n private readonly initialPage = computed<{ index: number; validate: boolean }>(() => {\n const raw = this.formOptions?.()?.initialPage;\n const totalPages = this.pageFields().length;\n const requested = typeof raw === 'number' ? raw : raw?.index;\n const validate = typeof raw === 'number' ? false : (raw?.validate ?? false);\n\n if (typeof requested !== 'number' || !Number.isFinite(requested) || requested < 0 || totalPages === 0) {\n return { index: 0, validate: false };\n }\n\n return { index: Math.min(Math.trunc(requested), totalPages - 1), validate };\n });\n\n /** Computed state for the orchestrator */\n readonly state = computed<PagerState>(() => {\n const currentIndex = this.currentPageIndex();\n const totalPages = this.pageFields().length;\n const visibleIndices = this.visiblePageIndices();\n\n // Find where the current index is in the visible pages list\n const currentVisiblePosition = visibleIndices.indexOf(currentIndex);\n const isFirstVisiblePage = currentVisiblePosition === 0 || currentVisiblePosition === -1;\n const isLastVisiblePage = currentVisiblePosition >= visibleIndices.length - 1;\n\n return {\n currentPageIndex: currentIndex,\n totalPages,\n isFirstPage: isFirstVisiblePage,\n isLastPage: isLastVisiblePage,\n };\n });\n\n /**\n * Signal indicating whether all fields on the current page are valid.\n *\n * @returns `true` if current page is valid, `false` otherwise\n */\n // Reports invalid while the schema is stale: the incoming page's fields are mounted but not\n // yet validated, so trusting them would let a second click skip a page.\n readonly currentPageValid = computed(() => (this.stateManager?.isSchemaCurrent() ?? true) && this.isPageValid(this.currentPageIndex()));\n\n /**\n * Whether all fields on the given page are currently valid.\n *\n * Form state derives from config, not from mounted components, so any page can\n * be checked without having been visited.\n *\n * @param pageIndex The page index (0-based)\n * @returns `true` if the page is valid or the index is out of range\n */\n private isPageValid(pageIndex: number): boolean {\n const pages = this.pageFields();\n const form = this.form();\n\n if (pageIndex < 0 || pageIndex >= pages.length) {\n return true;\n }\n\n // Collect all leaf field keys, recursively traversing group/row containers\n const leafKeys = collectLeafFieldKeys(pages[pageIndex].fields || []);\n\n // Check validity of each leaf field on the page\n // Fields are stored at root level in the form (pages don't add nesting)\n for (const fieldKey of leafKeys) {\n const field = (form as Record<string, unknown>)[fieldKey];\n if (field && typeof field === 'function') {\n const fieldState = (field as () => { valid: () => boolean })();\n if (fieldState && typeof fieldState.valid === 'function' && !fieldState.valid()) {\n return false;\n }\n }\n }\n\n return true;\n }\n\n /** Extended field signal context that includes currentPageValid. */\n readonly extendedFieldSignalContext = computed(() => ({\n ...this.fieldSignalContext(),\n currentPageValid: this.currentPageValid,\n }));\n\n /**\n * Effective preload window (pages preloaded on idle on each side of the current page).\n * Per-form `FormOptions.pagePreloadWindow` wins over the global\n * `withPagePreload(n)` default; both fall back to `1`. Clamped to `>= 0`.\n */\n readonly preloadWindow = computed(() => {\n const perForm = this.formOptions?.()?.pagePreloadWindow;\n // The global is already normalized; a non-finite per-form value falls back to it.\n return clampWindowSize(perForm, this.globalPreloadWindow);\n });\n\n /** Declarative render mode for every configured page. */\n readonly pageRenderStates = computed(() => {\n const activeIndex = this.currentPageIndex();\n const hiddenStates = this.pageHiddenStates();\n const preloadWindow = this.preloadWindow();\n\n return this.pageFields().map((field, index) => ({\n field,\n index,\n hidden: hiddenStates[index],\n active: index === activeIndex,\n preload: index !== activeIndex && Math.abs(index - activeIndex) <= preloadWindow,\n }));\n });\n\n constructor() {\n // Setup event listeners for navigation\n this.setupEventListeners();\n\n // Warm only the pages that can currently render. When navigation moves the\n // window this effect preloads the newly selected subtree before its deferred\n // page component discovers those chunks field by field.\n const preloader = injectFormComponentPreloader();\n explicitEffect([this.pageRenderStates], ([states]) => {\n preloader.preloadFields(states.filter((page) => !page.hidden && (page.active || page.preload)).map((page) => page.field));\n });\n\n // A config swap exposes its page definitions before their schema is current. Defer a gated\n // landing until those fields can be validated, then resolve it exactly once for this page set.\n explicitEffect([this.schemaCurrent, this.pageFields], ([schemaCurrent]) => {\n const ownership = this.activePageOwnership();\n if (!schemaCurrent || ownership.initialized) return;\n this.activePageOwnership.set({ ...ownership, initialized: true, index: this.resolveInitialLanding() });\n });\n\n // B15: Auto-navigate away when current page becomes hidden\n explicitEffect([this.state, this.visiblePageIndices], ([state, visibleIndices]) => {\n const currentVisiblePosition = visibleIndices.indexOf(state.currentPageIndex);\n if (currentVisiblePosition === -1 && visibleIndices.length > 0) {\n // Current page is hidden — navigate to the nearest visible page\n const nearest = this.findNearestVisiblePage(state.currentPageIndex, visibleIndices);\n if (nearest !== -1) {\n this.executePageChange(nearest);\n }\n }\n });\n }\n\n /**\n * Navigate to the next visible page, skipping hidden pages.\n *\n * @returns Navigation result\n */\n navigateToNextPage(): NavigationResult {\n // Guard: do not advance if current page has invalid fields.\n // Respects disableWhenPageInvalid option (defaults to true).\n const disableWhenPageInvalid = this.formOptions?.()?.nextButton?.disableWhenPageInvalid ?? true;\n if (disableWhenPageInvalid && !this.currentPageValid()) {\n return {\n success: false,\n newPageIndex: this.state().currentPageIndex,\n error: 'Current page has invalid fields',\n };\n }\n\n const currentState = this.state();\n const visibleIndices = this.visiblePageIndices();\n\n if (currentState.isLastPage) {\n return {\n success: false,\n newPageIndex: currentState.currentPageIndex,\n error: 'Already on the last visible page',\n };\n }\n\n // Find the next visible page after the current index\n const currentVisiblePosition = visibleIndices.indexOf(currentState.currentPageIndex);\n if (currentVisiblePosition === -1 || currentVisiblePosition >= visibleIndices.length - 1) {\n return {\n success: false,\n newPageIndex: currentState.currentPageIndex,\n error: 'No next visible page available',\n };\n }\n\n const nextVisiblePageIndex = visibleIndices[currentVisiblePosition + 1];\n return this.executePageChange(nextVisiblePageIndex);\n }\n\n /**\n * Navigate to the previous visible page, skipping hidden pages.\n *\n * @returns Navigation result\n */\n navigateToPreviousPage(): NavigationResult {\n const currentState = this.state();\n const visibleIndices = this.visiblePageIndices();\n\n if (currentState.isFirstPage) {\n return {\n success: false,\n newPageIndex: currentState.currentPageIndex,\n error: 'Already on the first visible page',\n };\n }\n\n // Find the previous visible page before the current index\n const currentVisiblePosition = visibleIndices.indexOf(currentState.currentPageIndex);\n if (currentVisiblePosition <= 0) {\n return {\n success: false,\n newPageIndex: currentState.currentPageIndex,\n error: 'No previous visible page available',\n };\n }\n\n const prevVisiblePageIndex = visibleIndices[currentVisiblePosition - 1];\n return this.executePageChange(prevVisiblePageIndex);\n }\n\n /**\n * Navigate to an arbitrary page, applying the jump validation semantics.\n *\n * Backward jumps are unconditional, matching `previous` having no validity gate.\n * Forward jumps validate every visible page crossed by the jump — from the\n * current page up to, but excluding, the target — because conditions may have\n * changed since those pages were last visited. On failure, navigation lands on\n * the first invalid page rather than staying put, so the user ends up where\n * work is required. Hidden pages are never validated.\n *\n * Respects `nextButton.disableWhenPageInvalid`, the same option that gates\n * next-page navigation.\n *\n * @param pageIndex The target page index (0-based)\n * @returns Navigation result\n */\n navigateToPage(pageIndex: number, options?: PageNavigationOptions): NavigationResult {\n const currentIndex = this.state().currentPageIndex;\n const visibleIndices = this.visiblePageIndices();\n\n // Backward jumps and no-ops need no gate. Out-of-bounds and hidden targets\n // fall through too — executePageChange reports those without navigating.\n if (pageIndex <= currentIndex || !visibleIndices.includes(pageIndex)) {\n return this.executePageChange(pageIndex);\n }\n\n // Per-dispatch opt-out, for restoring a saved session onto its exact page.\n if (options?.validate === false) {\n return this.executePageChange(pageIndex);\n }\n\n const disableWhenPageInvalid = this.formOptions?.()?.nextButton?.disableWhenPageInvalid ?? true;\n if (!disableWhenPageInvalid) {\n return this.executePageChange(pageIndex);\n }\n\n const crossedPages = visibleIndices.filter((index) => index >= currentIndex && index < pageIndex);\n const firstInvalidPage = crossedPages.find((index) => !this.isPageValid(index));\n\n if (firstInvalidPage === undefined) {\n return this.executePageChange(pageIndex);\n }\n\n // Partial jump: land on the first invalid page and report the failure.\n this.executePageChange(firstInvalidPage);\n\n return {\n success: false,\n newPageIndex: firstInvalidPage,\n error: `Cannot navigate to page ${pageIndex}: page ${firstInvalidPage} has invalid fields`,\n };\n }\n\n /**\n * Performs the actual page change, with no validity gating.\n *\n * Validates bounds and target visibility, updates the active index, and emits\n * `PageChangeEvent`. All gated entry points funnel through here.\n *\n * @param pageIndex The target page index (0-based)\n * @returns Navigation result\n */\n private executePageChange(pageIndex: number): NavigationResult {\n const currentState = this.state();\n const totalPages = currentState.totalPages;\n\n // Validate page index bounds\n if (pageIndex < 0 || pageIndex >= totalPages) {\n return {\n success: false,\n newPageIndex: currentState.currentPageIndex,\n error: `Invalid page index: ${pageIndex}. Valid range is 0 to ${totalPages - 1}`,\n };\n }\n\n // Validate target page is visible\n const visibleIndices = this.visiblePageIndices();\n if (!visibleIndices.includes(pageIndex)) {\n return {\n success: false,\n newPageIndex: currentState.currentPageIndex,\n error: `Cannot navigate to hidden page at index ${pageIndex}. Visible pages: [${visibleIndices.join(', ')}]`,\n };\n }\n\n // Check if already on target page\n if (pageIndex === currentState.currentPageIndex) {\n return {\n success: true,\n newPageIndex: pageIndex,\n };\n }\n\n // Perform navigation\n const previousIndex = currentState.currentPageIndex;\n this.setCurrentPageIndex(pageIndex);\n\n // Emit page change event\n this.eventBus.dispatch(PageChangeEvent, pageIndex, totalPages, previousIndex);\n\n return {\n success: true,\n newPageIndex: pageIndex,\n };\n }\n\n /**\n * Finds the nearest visible page index to the given index.\n * Prefers the forward (higher index) page when equidistant.\n */\n private findNearestVisiblePage(currentIndex: number, visibleIndices: number[]): number {\n let nearest = -1;\n let minDistance = Infinity;\n\n for (const idx of visibleIndices) {\n const distance = Math.abs(idx - currentIndex);\n // Prefer forward (higher index) when tied\n if (distance < minDistance || (distance === minDistance && idx > nearest)) {\n minDistance = distance;\n nearest = idx;\n }\n }\n\n return nearest;\n }\n\n /** Set up event listeners for navigation events */\n private setupEventListeners(): void {\n // Listen for next page events\n this.eventBus\n .on<NextPageEvent>('next-page')\n .pipe(takeUntilDestroyed())\n .subscribe(() => {\n this.navigateToNextPage();\n });\n\n // Listen for previous page events\n this.eventBus\n .on<PreviousPageEvent>('previous-page')\n .pipe(takeUntilDestroyed())\n .subscribe(() => {\n this.navigateToPreviousPage();\n });\n\n // Programmatic jumps arrive as pending intent on FormStateManager rather than as a live\n // subscription here: this component mounts behind the render gate, so a request made on\n // `initialized` would otherwise reach the bus before this listener existed. Draining it\n // here keeps visibility and validity resolution in the one place that knows about them.\n explicitEffect([this.pendingPageRequest], ([request]) => {\n if (!request) return;\n this.stateManager?.pendingPageRequest.set(null);\n this.navigateToPage(request.index, request.options);\n });\n\n explicitEffect([this.state], ([state]) => this.eventBus.dispatch(PagerStateEvent, state));\n\n // Publish upward so navigation survives this pager being temporarily unmounted.\n explicitEffect([this.activePageOwnership], ([ownership]) => this.stateManager?.activePageState.set(ownership));\n }\n\n /**\n * Evaluates whether a page should be hidden based on its logic configuration.\n * A page is hidden if ANY of its hidden logic conditions evaluate to true.\n *\n * @param page The page field to evaluate\n * @returns true if the page should be hidden, false otherwise\n */\n private evaluatePageHidden(page: PageField): boolean {\n // If no logic defined, page is visible\n if (!page.logic || page.logic.length === 0) {\n return false;\n }\n\n // Filter to only hidden logic (pages only support hidden type)\n const hiddenLogic = page.logic.filter((l): l is ContainerLogicConfig => l.type === 'hidden');\n\n // If no hidden logic, page is visible\n if (hiddenLogic.length === 0) {\n return false;\n }\n\n // Check each hidden logic - if ANY condition is true, the page is hidden\n for (const logic of hiddenLogic) {\n // Handle static boolean conditions (fast path)\n if (typeof logic.condition === 'boolean') {\n if (logic.condition) {\n return true;\n }\n continue;\n }\n\n // Evaluate conditional expression using centralized context creation\n const condition = logic.condition as ConditionalExpression;\n const context = this.fieldContextRegistry.createDisplayOnlyContext(page.key || '', this.functionRegistry.getCustomFunctions());\n\n if (evaluateCondition(condition, context)) {\n return true;\n }\n }\n\n return false;\n }\n}\n","import { FieldDef, FieldWithValidation, isDerivationLogicConfig } from '@ng-forge/dynamic-forms/internal';\nimport { someField } from './field-traversal';\n\n/**\n * Cheap, eager predicate: does any field in the config declare a value or\n * property derivation — the shorthand `derivation` string, or a `logic[]` entry\n * of `type: 'derivation'` (the latter covers both value derivations and\n * `targetProperty` property derivations)?\n *\n * Deliberately reuses the collector's child resolution ({@link someField} shares\n * it with `traverseFieldsWithContext`) and detection predicate\n * ({@link isDerivationLogicConfig}) so this gate can never diverge from what\n * `createDerivationOrchestrator` would actually wire — including derivations\n * nested in containers and array-item templates.\n *\n * Stays lightweight (no dependency on the heavy derivation-orchestrator module)\n * so it can run eagerly to decide whether the orchestrator needs to be\n * lazy-loaded at all. Forms without derivations never pull the engine.\n *\n * @internal\n */\nexport function configHasDerivations(fields: FieldDef<unknown>[]): boolean {\n return someField(fields, (field) => {\n // Match the collector's keyless guard (derivation-collector.ts): a keyless\n // field never produces a derivation entry, so it must not trip the gate.\n // `someField` still recurses into its children.\n if (!field.key) return false;\n const validationField = field as FieldDef<unknown> & FieldWithValidation;\n return !!validationField.derivation || !!validationField.logic?.some(isDerivationLogicConfig);\n });\n}\n","import { computed, inject, Injector, InjectionToken, PendingTasks, runInInjectionContext, signal, Signal } from '@angular/core';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { DynamicFormLogger, FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { FormStateManager } from '../../state/form-state-manager';\nimport { configHasDerivations } from './config-has-derivations';\n\n/**\n * Form-scoped signal that is `false` only while a derivation-bearing config is\n * still waiting for the lazily-loaded derivation engine to wire up. `DynamicForm`\n * ANDs this into `shouldRender`, so a form that uses derivations does not render\n * its fields until the orchestrator has loaded and registered its\n * value/property overrides — fields render already-derived, with no flash.\n *\n * For configs without derivations the gate is always `true` (no waiting, no\n * lazy load), and the heavy orchestrator module is never imported.\n *\n * @internal\n */\nexport const DERIVATION_RENDER_GATE = new InjectionToken<Signal<boolean>>('DERIVATION_RENDER_GATE');\n\n/**\n * Factory for {@link DERIVATION_RENDER_GATE}. Watches the form setup and, the\n * first time it declares a derivation, dynamically imports the derivation engine\n * (the chunk boundary) and wires the orchestrator in the form's injection\n * context. Flips the gate open once that bootstrap has run.\n *\n * The lazy import runs inside an Angular `PendingTasks` task so server-side\n * rendering waits for the engine to wire before serializing — derivation-bearing\n * forms render server-side rather than as empty markup. If the chunk fails to\n * load the gate opens anyway (the form renders without derivations rather than\n * locking shut forever).\n *\n * Must be created within the form's injection context (it captures the form\n * `Injector` for the deferred `runInInjectionContext`).\n *\n * @internal\n */\nexport function createDerivationRenderGate(): Signal<boolean> {\n const stateManager = inject(FormStateManager);\n const injector = inject(Injector);\n const pendingTasks = inject(PendingTasks);\n const logger = inject(DynamicFormLogger);\n\n const hasDerivations = computed(() => {\n const setup = stateManager.formSetup();\n return !!setup && configHasDerivations(setup.schemaFields as FieldDef<unknown>[]);\n });\n\n // Single source of truth for the lazy engine's lifecycle. `idle` until a config\n // first needs it; `loading` once the import is in flight (guards against a\n // second orchestrator if derivations swap out and back in); `wired` once the\n // orchestrator is constructed; `failed` if the chunk could not be loaded.\n const engine = signal<'idle' | 'loading' | 'wired' | 'failed'>('idle');\n\n explicitEffect([hasDerivations], ([has]) => {\n if (!has || engine() !== 'idle') return;\n engine.set('loading');\n // Tracked as a pending task so SSR awaits the engine before serializing.\n pendingTasks.run(() =>\n import('./bootstrap-derivation-orchestrator')\n .then(({ bootstrapDerivationOrchestrator }) => {\n runInInjectionContext(injector, () => bootstrapDerivationOrchestrator());\n engine.set('wired');\n })\n .catch((error: unknown) => {\n // A failed chunk load must not lock the form shut — render it degraded\n // (derivations won't apply) and surface the failure.\n engine.set('failed');\n logger.error('Failed to load the derivation engine; derivations will not apply.', error);\n }),\n );\n });\n\n // Open when there are no derivations, once the engine is wired, or if it failed\n // to load (degraded render beats a permanently closed gate).\n return computed(() => {\n if (!hasDerivations()) return true;\n const state = engine();\n return state === 'wired' || state === 'failed';\n });\n}\n","import { InjectionToken } from '@angular/core';\n\n/**\n * Whether WebMCP tool registration is enabled at all. Absent (`false`) unless\n * `withExperimentalWebMcp()` is provided, which is what keeps the registrar chunk out of\n * builds that never opt in.\n *\n * @internal\n */\nexport const WEB_MCP_ENABLED = new InjectionToken<boolean>('WEB_MCP_ENABLED', {\n providedIn: 'root',\n factory: () => false,\n});\n","import { computed, DestroyRef, inject, InjectionToken, Injector, PLATFORM_ID, runInInjectionContext, signal, Signal } from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { DynamicFormLogger, WebMcpToolOptions } from '@ng-forge/dynamic-forms/internal';\nimport { FormStateManager } from '../../state/form-state-manager';\nimport { WEB_MCP_ENABLED } from '../../providers/features/web-mcp/web-mcp.token';\n\n/**\n * What the WebMCP layer is currently doing for this form. Reported by\n * `DynamicForm.webMcpStatus()`; `'active'` is the only state in which an agent\n * can see the form.\n *\n * @experimental\n */\nexport type WebMcpStatus =\n /** `withExperimentalWebMcp()` is not provided, or this is the server. */\n | 'disabled'\n /** Enabled, but the current config does not declare `options.webMcp`. */\n | 'idle'\n /** Loading the registrar or awaiting `registerTool()`. */\n | 'registering'\n /** Tools are registered against the browser's model context. */\n | 'active'\n /** The browser exposes no model context, so there is nothing to register against. */\n | 'unsupported'\n /** Registration was attempted and rejected. See the console for the reason. */\n | 'failed';\n\n/**\n * Form-scoped hook that keeps this form's WebMCP tools in step with its config.\n *\n * Deliberately NOT a render gate. Unlike the derivation engine, nothing about a\n * form's rendered output depends on whether an agent can see it, so this must\n * never hold `shouldRender` closed and must never register a `PendingTasks` task\n * (which would make SSR wait on a browser-only concern).\n *\n * @internal\n */\nexport const WEB_MCP_GATE = new InjectionToken<Signal<WebMcpStatus>>('WEB_MCP_GATE');\n\n/**\n * Factory for {@link WEB_MCP_GATE}.\n *\n * Registration follows the *effective* form options, not the first config that\n * happened to declare them. A registration that only ever ran once outlives what\n * it describes: swap the config and `fill_first` keeps writing into a form whose\n * fields it no longer matches; turn `allowSubmit` off and `submit_first` stays\n * callable, which quietly leaves an agent holding submission authority the app\n * has just revoked. So every change to the options opens a new epoch: the\n * previous epoch's `AbortController` is aborted first, which unregisters its\n * tools, and only then are the new ones registered.\n *\n * Chrome's guidance is the same — register a tool only while it is useful in the\n * current page state.\n *\n * @see https://developer.chrome.com/docs/ai/webmcp/best-practices\n *\n * Must be created within the form's injection context (it captures the form\n * `Injector` for the deferred `runInInjectionContext`).\n *\n * @internal\n */\nexport function createWebMcpGate(): Signal<WebMcpStatus> {\n const enabled = inject(WEB_MCP_ENABLED);\n const isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n const stateManager = inject(FormStateManager);\n const injector = inject(Injector);\n const destroyRef = inject(DestroyRef);\n const logger = inject(DynamicFormLogger);\n\n // Registration touches the browser's model context, so it is browser-only.\n // Bail before touching the config so SSR never even evaluates the predicate.\n if (!enabled || !isBrowser) return computed(() => 'disabled');\n\n /**\n * What a registration epoch is built from.\n *\n * The options come from the *effective* form options. `webMcp` is part of the\n * public `FormOptions`, so `[formOptions]` on the component is a legitimate\n * place to set it; reading `activeConfig().options` alone made that override\n * silently do nothing.\n *\n * `formSetup` is in here too, because a config swap that keeps the same tool\n * name and description still changes the form the tools describe. Without it,\n * the second config would be driven through the first one's schema.\n */\n const registration = computed(() => {\n const options = stateManager.effectiveFormOptions().webMcp;\n return options ? { options: options as WebMcpToolOptions, setup: stateManager.formSetup() } : undefined;\n });\n\n const status = signal<WebMcpStatus>('idle');\n\n /** Aborting this revokes the current epoch's tools. */\n let epoch: AbortController | undefined;\n /** Guards the lazy import: a resolution from a superseded epoch is discarded. */\n let epochId = 0;\n\n const closeEpoch = (): void => {\n epoch?.abort();\n epoch = undefined;\n };\n\n destroyRef.onDestroy(closeEpoch);\n\n explicitEffect([registration], ([input]) => {\n // Every change closes the previous epoch first: aborting its controller\n // unregisters the tools it owns, so nothing from the old config outlives it.\n closeEpoch();\n epochId += 1;\n const thisEpoch = epochId;\n\n if (!input) {\n status.set('idle');\n return;\n }\n\n const controller = new AbortController();\n epoch = controller;\n status.set('registering');\n\n void import('./bootstrap-web-mcp')\n .then(({ bootstrapWebMcp }) => {\n // The config may have changed again while the chunk was in flight.\n if (thisEpoch !== epochId || controller.signal.aborted) return;\n\n return runInInjectionContext(injector, () => bootstrapWebMcp(input.options, controller.signal));\n })\n .then((result) => {\n if (thisEpoch !== epochId || controller.signal.aborted) return;\n if (result) status.set(result);\n })\n .catch((error: unknown) => {\n if (thisEpoch !== epochId) return;\n // A failed chunk load must not break the form — it just stays invisible\n // to agents.\n status.set('failed');\n logger.error('Failed to load the WebMCP registrar; this form will not be exposed to agents.', error);\n });\n });\n\n return status.asReadonly();\n}\n","import { InjectionToken } from '@angular/core';\n\n/**\n * Multi-provider token. Each entry is resolved at form bootstrap purely for its\n * construction side effect — useful for orchestrators that need to wire reactive\n * streams before first render but don't need to be referenced at use-sites.\n *\n * @internal\n */\nexport const FORM_INITIALIZER = new InjectionToken<readonly unknown[]>('FORM_INITIALIZER');\n","import { computed, Injectable, Signal, signal } from '@angular/core';\n\nconst AUTO_ID_PREFIX = 'df-';\n\n/**\n * Root-singleton tracking mounted DynamicForm instances, driving auto-prefixing.\n *\n * Each form registers a `visible` signal (true while its host is rendered). Only\n * visible forms count toward \"more than one present\", so a cached but hidden page\n * — e.g. ionic's `ion-router-outlet` keeps the previous page in the DOM for\n * swipe-back — doesn't inflate the count. Counting signals (not the DOM) keeps\n * the computed pure; `_membership` only invalidates it on register/unregister,\n * since Map membership itself isn't reactive.\n *\n * Slots are recycled (lowest free `df-N`) so ids stay compact across navigation.\n */\n@Injectable({ providedIn: 'root' })\nexport class DynamicFormInstanceRegistry {\n private readonly slots = new Map<number, Signal<boolean>>();\n private readonly _membership = signal(0);\n\n /** True while more than one VISIBLE form is mounted — the trigger for auto-prefixing. */\n readonly multiplePresent: Signal<boolean> = computed(() => {\n this._membership();\n let visible = 0;\n for (const isVisible of this.slots.values()) {\n if (isVisible()) {\n visible += 1;\n if (visible > 1) return true;\n }\n }\n return false;\n });\n\n /** Registers a form's visibility signal; returns a stable, recycled auto-id. */\n register(visible: Signal<boolean>): string {\n let slot = 1;\n while (this.slots.has(slot)) slot++;\n this.slots.set(slot, visible);\n this._membership.update((m) => m + 1);\n return `${AUTO_ID_PREFIX}${slot}`;\n }\n\n unregister(id: string): void {\n this.slots.delete(Number(id.slice(AUTO_ID_PREFIX.length)));\n this._membership.update((m) => m + 1);\n }\n}\n","import { computed, DestroyRef, ElementRef, inject, Injectable, isDevMode, PLATFORM_ID, signal, Signal } from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { FORM_OPTIONS } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormInstanceRegistry } from './dynamic-form-instance-registry.service';\n\n// Whitespace breaks the space-separated aria-describedby list; punctuation breaks selectors.\nconst INVALID_ID_CHARS = /[^\\w-]+/g;\n\nfunction sanitizeIdPrefix(prefix: string): string {\n return prefix.replace(INVALID_ID_CHARS, '_');\n}\n\nfunction isRendered(host: HTMLElement): boolean {\n if (!host.isConnected) return false;\n if (typeof host.checkVisibility === 'function') return host.checkVisibility();\n const rect = host.getBoundingClientRect();\n return rect.width > 0 || rect.height > 0;\n}\n\n/**\n * Per-form owner of the DOM-id prefix, published through `FORM_ID_PREFIX`.\n * Resolution: explicit `options.idPrefix` (trimmed + sanitized) wins; else the\n * instance's auto-id while more than one form is *visibly* mounted; else `''`.\n *\n * Not latched: a form reverts to unprefixed once it's the only visible one, so\n * navigating away from a multi-form page (incl. ionic's cached `ion-router-outlet`\n * stack) doesn't leave it stuck-prefixed.\n */\n@Injectable()\nexport class FormIdPrefixService {\n private readonly registry = inject(DynamicFormInstanceRegistry);\n private readonly options = inject(FORM_OPTIONS, { optional: true });\n private readonly logger = inject(DynamicFormLogger, { optional: true });\n private readonly host = inject(ElementRef<HTMLElement>).nativeElement;\n\n // Optimistic: counts toward \"multiple present\" until the ResizeObserver confirms\n // whether it's actually rendered. Starting true keeps SSR and the client's first\n // render in agreement (both count-all), avoiding a hydration mismatch; the\n // observer corrects it after layout (a normal reactive update, not a hydration error).\n private readonly visible = signal(true);\n\n private readonly autoId = this.registry.register(this.visible);\n\n private readonly rawPrefix = computed(() => this.options?.()?.idPrefix?.trim() || undefined);\n\n readonly prefix: Signal<string> = computed(() => {\n const explicit = this.rawPrefix();\n if (explicit) return sanitizeIdPrefix(explicit);\n return this.registry.multiplePresent() ? this.autoId : '';\n });\n\n constructor() {\n const destroyRef = inject(DestroyRef);\n destroyRef.onDestroy(() => this.registry.unregister(this.autoId));\n\n // A host's box collapses to 0 on display:none and restores when shown. set() is\n // a no-op when the value is unchanged, so plain resizes don't churn field inputs.\n if (isPlatformBrowser(inject(PLATFORM_ID)) && typeof ResizeObserver !== 'undefined') {\n const ro = new ResizeObserver(() => this.visible.set(isRendered(this.host)));\n ro.observe(this.host);\n destroyRef.onDestroy(() => ro.disconnect());\n }\n\n if (isDevMode()) {\n explicitEffect([this.rawPrefix], ([raw]) => {\n const safe = raw ? sanitizeIdPrefix(raw) : raw;\n if (raw && safe !== raw) {\n this.logger?.warn(`idPrefix \"${raw}\" sanitized to \"${safe}\".`);\n }\n });\n }\n }\n}\n","import { computed, Provider, Signal } from '@angular/core';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { ArrayItemRegistryService } from '../core/registry/array-item-registry.service';\nimport { FieldContextRegistryService } from '@ng-forge/dynamic-forms/internal';\nimport { FunctionRegistryService } from '@ng-forge/dynamic-forms/internal';\nimport { RootFormRegistryService } from '@ng-forge/dynamic-forms/internal';\nimport { SchemaRegistryService } from '../core/registry/schema-registry.service';\nimport { FormIdPrefixService } from '../core/registry/form-id-prefix.service';\nimport { FieldViewportObserver } from '../directives/df-field-outlet/field-viewport-observer.service';\nimport { FormStateManager, FORM_STATE_DEPS, FormStateDeps } from '../state/form-state-manager';\nimport {\n DEFAULT_PROPS,\n DEFAULT_VALIDATION_MESSAGES,\n DEFAULT_WRAPPERS,\n EXTERNAL_DATA,\n FORM_ID_PREFIX,\n FORM_OPTIONS,\n} from '@ng-forge/dynamic-forms/internal';\nimport { DERIVATION_WARNING_TRACKER } from '../core/derivation/derivation-warning-tracker';\nimport { DEPRECATION_WARNING_TRACKER } from '@ng-forge/dynamic-forms/internal';\nimport { createWarningTracker } from '@ng-forge/dynamic-forms/internal';\nimport { createDerivationRenderGate, DERIVATION_RENDER_GATE } from '../core/derivation/derivation-render-gate';\nimport { createWebMcpGate, WEB_MCP_GATE } from '../core/web-mcp/web-mcp-gate';\nimport { CONTAINER_FIELD_PROCESSORS, createContainerFieldProcessors } from '../utils/container-utils/container-field-processors';\nimport { createPropertyOverrideStore, PROPERTY_OVERRIDE_STORE } from '../core/property-derivation/property-override-store';\nimport { HTTP_CONDITION_CACHE, HttpConditionCache } from '@ng-forge/dynamic-forms/internal';\nimport { LogicFunctionCacheService } from '@ng-forge/dynamic-forms/internal';\nimport { HttpConditionFunctionCacheService } from '@ng-forge/dynamic-forms/internal';\nimport { AsyncConditionFunctionCacheService } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicValueFunctionCacheService } from '@ng-forge/dynamic-forms/internal';\nimport { ADDON_ACTION_REGISTRY, createAddonActionRegistry } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Always-on providers for any DynamicForm: state machine, registries, signal-context tokens.\n * Pure form bootstrap — no derivation, HTTP, or async machinery.\n *\n * @internal\n */\nfunction coreProviders(): Provider[] {\n return [\n EventBus,\n { provide: CONTAINER_FIELD_PROCESSORS, useFactory: createContainerFieldProcessors },\n SchemaRegistryService,\n FunctionRegistryService,\n {\n provide: FORM_STATE_DEPS,\n useFactory: (): FormStateDeps => ({ config: null, formOptions: null, value: null, source: null }),\n },\n FormStateManager,\n {\n provide: RootFormRegistryService,\n useFactory: (stateManager: FormStateManager) =>\n new RootFormRegistryService(\n stateManager.formValue as Signal<Record<string, unknown>>,\n computed(() => stateManager.form()),\n ),\n deps: [FormStateManager],\n },\n FieldContextRegistryService,\n ArrayItemRegistryService,\n {\n provide: DEFAULT_PROPS,\n useFactory: (stateManager: FormStateManager) => computed(() => stateManager.activeConfig()?.defaultProps),\n deps: [FormStateManager],\n },\n {\n provide: DEFAULT_WRAPPERS,\n useFactory: (stateManager: FormStateManager) => computed(() => stateManager.activeConfig()?.defaultWrappers),\n deps: [FormStateManager],\n },\n {\n provide: DEFAULT_VALIDATION_MESSAGES,\n useFactory: (stateManager: FormStateManager) => computed(() => stateManager.activeConfig()?.defaultValidationMessages),\n deps: [FormStateManager],\n },\n {\n provide: FORM_OPTIONS,\n useFactory: (stateManager: FormStateManager) => stateManager.effectiveFormOptions,\n deps: [FormStateManager],\n },\n {\n provide: EXTERNAL_DATA,\n useFactory: (stateManager: FormStateManager) => computed(() => stateManager.activeConfig()?.externalData),\n deps: [FormStateManager],\n },\n // Per-form DOM-id prefix: registers this instance with the root registry for\n // multi-form collision detection and publishes the resolved prefix signal.\n FormIdPrefixService,\n // Form-scoped, never root: it holds a mutable observer map, and\n // module-scoped mutable state is shared across requests under SSR.\n FieldViewportObserver,\n {\n provide: FORM_ID_PREFIX,\n useFactory: (svc: FormIdPrefixService) => svc.prefix,\n deps: [FormIdPrefixService],\n },\n { provide: DEPRECATION_WARNING_TRACKER, useFactory: createWarningTracker },\n // ADDON_ACTION_REGISTRY must live at form scope (not root) because the\n // multi-provider source `ADDON_ACTION_HANDLERS` is contributed by\n // `withAddonActions(...)` features passed to `provideDynamicForm(...)`\n // — those entries are only visible inside the form's own injector tree.\n { provide: ADDON_ACTION_REGISTRY, useFactory: createAddonActionRegistry },\n ];\n}\n\n/**\n * Providers for the value-derivation engine: warning tracker + a lazy bootstrap\n * hook. The heavy orchestrator module (collectors, applicators, cycle detection,\n * and the value/property/HTTP/async stream factories) is NOT statically imported\n * here — it is dynamically imported the first time a config declares a derivation,\n * so forms without derivations never pay for the engine.\n *\n * @internal\n */\nfunction derivationProviders(): Provider[] {\n return [\n { provide: DERIVATION_WARNING_TRACKER, useFactory: createWarningTracker },\n // The render gate lazy-loads + wires the orchestrator on the first config\n // that declares a derivation, and holds `shouldRender` closed until it does\n // (so derivation-bearing fields render already-derived, no flash). The\n // orchestrator is component-scoped (it can't be `providedIn: 'root'`), so the\n // gate loads it with a plain dynamic `import()` + `runInInjectionContext`,\n // not `injectAsync`. `DynamicForm` injects the gate, which wakes the load.\n { provide: DERIVATION_RENDER_GATE, useFactory: createDerivationRenderGate },\n ];\n}\n\n/**\n * Provider for the property-derivation override store. The store is consumed\n * eagerly by field rendering (to apply derived hidden/disabled/readonly state),\n * so it stays eager even though the orchestrator that writes into it is lazy.\n *\n * @internal\n */\nfunction propertyDerivationProviders(): Provider[] {\n return [{ provide: PROPERTY_OVERRIDE_STORE, useFactory: createPropertyOverrideStore }];\n}\n\n/**\n * Providers for HTTP-backed condition expressions and validators.\n * Future: opt-in via withHttpExpressions() at a separate entry point.\n *\n * @internal\n */\nfunction httpExpressionProviders(): Provider[] {\n return [{ provide: HTTP_CONDITION_CACHE, useFactory: () => new HttpConditionCache(100) }, HttpConditionFunctionCacheService];\n}\n\n/**\n * Providers for async (Promise/Observable-returning) condition expressions.\n * Future: opt-in via withAsyncExpressions() at a separate entry point.\n *\n * @internal\n */\nfunction asyncExpressionProviders(): Provider[] {\n return [AsyncConditionFunctionCacheService];\n}\n\n/**\n * Providers for dynamic-value functions (numeric/string validator parameters resolved\n * from formValue expressions, e.g. `min: { expression: 'formValue.minAge' }`).\n * Future: opt-in via withDynamicValues() at a separate entry point.\n *\n * @internal\n */\nfunction dynamicValueProviders(): Provider[] {\n return [DynamicValueFunctionCacheService];\n}\n\n/**\n * Providers for the logic function cache (memoizes compiled state-logic conditions\n * — `when`, `disabled`, `readonly`, `hidden` predicates). Used universally by\n * validator-factory, logic-applicator, schema-application; treated as core for now.\n *\n * @internal\n */\nfunction logicProviders(): Provider[] {\n return [LogicFunctionCacheService];\n}\n\n/**\n * Composes all DynamicForm-level providers. Today: every feature group is included so\n * behavior matches the prior monolithic provider list. The grouped composition exists\n * so future feature flags / secondary entry points can drop groups consumers don't use\n * without re-touching every provider.\n *\n * @internal\n */\nexport function provideDynamicFormDI(): Provider[] {\n return [\n ...coreProviders(),\n ...logicProviders(),\n ...dynamicValueProviders(),\n ...httpExpressionProviders(),\n ...asyncExpressionProviders(),\n ...propertyDerivationProviders(),\n ...derivationProviders(),\n { provide: WEB_MCP_GATE, useFactory: createWebMcpGate },\n ];\n}\n","import { Injectable } from '@angular/core';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Injectable service for dispatching events into a DynamicForm from outside the form.\n *\n * @Component({\n * providers: [EventDispatcher],\n * template: `<form [dynamic-form]=\"config\" [(value)]=\"formValue\"></form>`\n * })\n * export class MyComponent {\n * readonly dispatcher = inject(EventDispatcher);\n * readonly formValue = signal<Record<string, unknown>>({});\n *\n * constructor() {\n * effect(() => {\n * const category = this.formValue()?.['category'] as string | undefined;\n * if (category) {\n * this.dispatcher.dispatch(\n * arrayEvent('tasks').append([{ key: 'name', type: 'input', label: 'Task', value: category }])\n * );\n * }\n * });\n * }\n * }\n * ```\n *\n * ## Multi-form note\n *\n * If multiple `DynamicForm` instances exist under the same provider scope, **all forms**\n * will receive dispatched events. To target a specific form, scope the provider to a\n * wrapper component that contains only that form.\n *\n * ## What events can be dispatched\n *\n * Any `FormEvent` instance is accepted — array events, reset/clear events, custom events, etc.\n * The `arrayEvent()` builder is the recommended way to construct array manipulation events:\n *\n * ```typescript\n * dispatcher.dispatch(arrayEvent('tasks').append(template));\n * dispatcher.dispatch(arrayEvent('tasks').removeAt(0));\n * dispatcher.dispatch(new FormResetEvent());\n * ```\n */\n@Injectable()\nexport class EventDispatcher {\n private bus: EventBus | undefined;\n\n /**\n * Dispatches a form event into the connected DynamicForm's event bus.\n * No-op if no form is currently connected.\n *\n * @param event - A FormEvent instance. Use the `arrayEvent()` builder for array operations.\n */\n dispatch(event: FormEvent): void {\n this.bus?.emitInstance(event);\n }\n\n /** @internal - Called by DynamicForm on init */\n connect(bus: EventBus): void {\n this.bus = bus;\n }\n\n /** @internal - Called by DynamicForm on destroy */\n disconnect(): void {\n this.bus = undefined;\n }\n}\n","import { Directive, Injectable, inject, input, Signal, signal, TemplateRef } from '@angular/core';\n\n/**\n * Marks an `<ng-template>` projected into `<df-dynamic-form>` content as\n * available to template addons by name.\n */\n@Directive({\n selector: 'ng-template[dfTemplate]',\n exportAs: 'dfTemplate',\n})\nexport class DfTemplate {\n /** Name this template registers under — referenced from `TemplateAddon.templateKey`. */\n readonly dfTemplate = input.required<string>();\n\n /** The wrapped template, captured for registration and `NgTemplateOutlet` rendering. */\n readonly templateRef: TemplateRef<unknown> = inject(TemplateRef);\n}\n\n/**\n * Holder service published at the `<df-dynamic-form>` component scope.\n * `DynamicForm` collects projected `<ng-template dfTemplate=\"...\">` via\n * `contentChildren(DfTemplate)` and pushes the resulting map through\n * `DfFieldTemplateRegistry.set(...)`. The {@link DF_FIELD_TEMPLATES}\n * injection token is provided as a factory that returns this service's\n * `map` signal, so template-addon components can resolve `templateKey`\n * without coupling to the host form's generic class.\n */\n@Injectable()\nexport class DfFieldTemplateRegistry {\n private readonly _map = signal<ReadonlyMap<string, TemplateRef<unknown>>>(new Map());\n\n /** Reactive view consumed by the `template` addon type via DI. */\n readonly map: Signal<ReadonlyMap<string, TemplateRef<unknown>>> = this._map.asReadonly();\n\n /** Replace the registry contents — called from `DynamicForm` when projected templates change. */\n set(value: ReadonlyMap<string, TemplateRef<unknown>>): void {\n this._map.set(value);\n }\n}\n","import {\n afterNextRender,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChildren,\n DestroyRef,\n EnvironmentInjector,\n inject,\n Injector,\n input,\n model,\n Signal,\n TemplateRef,\n WritableSignal,\n signal,\n} from '@angular/core';\nimport { DfFieldOutlet } from './directives/df-field-outlet/df-field-outlet.directive';\nimport { FieldTree } from '@angular/forms/signals';\nimport { outputFromObservable, takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\nimport { filter, shareReplay, take } from 'rxjs';\nimport { createSubmissionHandler } from './utils/submission-handler/submission-handler';\nimport { FormConfig, FormOptions } from '@ng-forge/dynamic-forms/internal';\nimport { RegisteredFieldTypes } from '@ng-forge/dynamic-forms/internal';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { FormSubmitEvent } from './events/constants/submit.event';\nimport { ComponentInitializedEvent } from '@ng-forge/dynamic-forms/internal';\nimport { InferFormModel } from '@ng-forge/dynamic-forms/internal';\nimport { isContainerField } from '@ng-forge/dynamic-forms/internal';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { injectFormComponentPreloader } from './utils/preload-form-components/preload-form-components';\nimport { PageOrchestratorComponent } from './core/page-orchestrator/page-orchestrator.component';\nimport { DERIVATION_RENDER_GATE } from './core/derivation/derivation-render-gate';\nimport { WEB_MCP_GATE } from './core/web-mcp/web-mcp-gate';\nimport { FORM_INITIALIZER } from './providers/form-initializer.token';\nimport { FormClearEvent } from './events/constants/form-clear.event';\nimport { FormResetEvent } from './events/constants/form-reset.event';\nimport { PageChangeEvent } from './events/constants/page-change.event';\nimport { PagerStateEvent } from './events/constants/pager-state.event';\nimport { ActivePageInitializedEvent } from './events/constants/active-page-initialized.event';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { FormStateManager, FORM_STATE_DEPS } from './state/form-state-manager';\nimport { provideDynamicFormDI } from './providers/dynamic-form-di';\nimport { FormIdPrefixService } from './core/registry/form-id-prefix.service';\nimport { EventDispatcher } from './events/event-dispatcher';\nimport { DfTemplate, DfFieldTemplateRegistry } from './directives/df-template.directive';\nimport { DF_FIELD_TEMPLATES } from '@ng-forge/dynamic-forms/internal';\nimport { getGridClassString } from '@ng-forge/dynamic-forms/internal';\nimport { ResolvedField } from './utils/resolve-field/resolve-field';\nimport { FIELD_WINDOWING } from './providers/features/field-windowing/field-windowing.token';\nimport { resolveFieldWindowing } from './providers/features/field-windowing/resolve-field-windowing';\nimport { collectInitializingContainerKeys, initializationComponentKey } from './utils/container-utils/container-utils';\n\n/**\n * Renders a form from a {@link FormConfig}. Attribute component on a native\n * `<form>` element (selector `form[dynamic-form]`); state management is\n * delegated to `FormStateManager`.\n *\n * Provide a UI adapter once via {@link provideDynamicForm} (for example\n * `provideDynamicForm(...withMaterialFields())`), then bind a config and\n * listen for `submitted`. Field-value types are inferred from the config when\n * it is authored with `as const satisfies FormConfig`.\n *\n * @example\n * ```ts\n * @Component({\n * imports: [DynamicForm],\n * template: `<form [dynamic-form]=\"config\" (submitted)=\"onSubmit($event)\"></form>`,\n * })\n * export class SignInComponent {\n * config = {\n * fields: [\n * { key: 'email', type: 'input', value: '', label: 'Email', required: true, email: true },\n * { type: 'submit', key: 'submit', label: 'Sign in' },\n * ],\n * } as const satisfies FormConfig;\n *\n * onSubmit(value: InferFormValue<typeof this.config.fields>) {\n * console.log(value); // inferred: { email: string }\n * }\n * }\n * ```\n */\n@Component({\n selector: 'form[dynamic-form]',\n imports: [DfFieldOutlet, PageOrchestratorComponent],\n template: `\n @if (shouldRender()) {\n @switch (formModeDetection().mode) {\n @case ('paged') {\n <div page-orchestrator [pageFields]=\"pageFieldDefinitions()\" [form]=\"form()\" [fieldSignalContext]=\"fieldSignalContext()\"></div>\n }\n @case ('non-paged') {\n @for (field of resolvedFields(); track field.key; let i = $index) {\n @if (windowsField(field, i)) {\n @if (!field.hidden()) {\n @defer (on viewport) {\n <ng-container *dfFieldOutlet=\"field; environmentInjector: environmentInjector\" />\n } @placeholder {\n <div\n [class]=\"placeholderGridClass(field)\"\n [style.min-height]=\"fieldWindowing().placeholderHeight\"\n [attr.data-field-key]=\"field.key\"\n aria-hidden=\"true\"\n ></div>\n }\n }\n } @else {\n <!-- DfFieldOutlet owns the hidden gate so an already-mounted field can be detached\n and restored without recreating its component and wrapper chain. -->\n <ng-container *dfFieldOutlet=\"field; environmentInjector: environmentInjector\" />\n }\n }\n }\n @default {\n never;\n }\n }\n }\n `,\n styleUrl: './dynamic-form.component.scss',\n providers: [\n provideDynamicFormDI(),\n DfFieldTemplateRegistry,\n { provide: DF_FIELD_TEMPLATES, useFactory: () => inject(DfFieldTemplateRegistry).map },\n ],\n host: {\n class: 'df-dynamic-form df-form',\n novalidate: '', // Disable browser validation - Angular Signal Forms handles validation\n '[class.disabled]': 'disabled()',\n '[class.df-form-paged]': 'formModeDetection().mode === \"paged\"',\n '[class.df-form-non-paged]': 'formModeDetection().mode === \"non-paged\"',\n '[attr.data-form-mode]': 'formModeDetection().mode',\n '[attr.id]': 'idPrefix() || null',\n '(submit)': 'onNativeSubmit($event)',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class DynamicForm<\n TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[],\n TModel extends Record<string, unknown> = InferFormModel<TFields>,\n> {\n // ─────────────────────────────────────────────────────────────────────────────\n // Inputs (must be declared BEFORE deps connection and stateManager injection)\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Form configuration defining the structure, validation, and behavior. */\n config = input.required<FormConfig<TFields>>({ alias: 'dynamic-form' });\n\n /** Runtime form options that override config options when provided. */\n formOptions = input<FormOptions | undefined>(undefined);\n\n /** Form values for two-way data binding. */\n value = model<Partial<TModel> | undefined>(undefined);\n\n /**\n * How lenient the addon validator is on `config.fields[...].addons`.\n * `'inline'` (default) keeps everything; `'json'` drops code-only types\n * with a warning. Read at form init and on every config swap — change\n * `source` AND the config to force re-validation mid-flight.\n */\n source = input<'inline' | 'json'>('inline');\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Dependencies\n // ─────────────────────────────────────────────────────────────────────────────\n\n private destroyRef = inject(DestroyRef);\n private injector = inject(Injector);\n protected environmentInjector = inject(EnvironmentInjector);\n private eventBus = inject(EventBus);\n private logger = inject(DynamicFormLogger);\n private dispatcher = inject(EventDispatcher, { optional: true });\n private templateRegistry = inject(DfFieldTemplateRegistry);\n private globalFieldWindowing = inject(FIELD_WINDOWING);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Projected templates — collected for the `template` addon type via DI.\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** All `<ng-template dfTemplate=\"...\">` instances projected into this form. */\n private readonly _projectedTemplates = contentChildren(DfTemplate);\n\n private readonly stateManager = this.connectDeps();\n\n /**\n * Owns this form's DOM-id prefix and registers the instance with the root\n * registry for multi-form collision detection. Injected eagerly (not lazily\n * via first field map) so the live-form count is accurate from construction.\n */\n private readonly formIdPrefix = inject(FormIdPrefixService);\n\n /** Active DOM-id prefix — empty unless explicitly set or multiple forms are mounted. */\n protected readonly idPrefix = this.formIdPrefix.prefix;\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Private State\n // ─────────────────────────────────────────────────────────────────────────────\n\n private componentId = 'dynamic-form';\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Signals - Direct pass-through from state manager\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** The currently active config used for form rendering */\n activeConfig = this.stateManager.activeConfig;\n\n /** Current render phase: 'render' = showing form, 'teardown' = hiding old components */\n renderPhase = this.stateManager.renderPhase;\n\n /** Computed form mode detection with validation */\n formModeDetection = this.stateManager.formModeDetection;\n\n /** Page field definitions for paged forms */\n pageFieldDefinitions = this.stateManager.pageFieldDefinitions;\n\n /** Effective form options (merged from config and input) */\n effectiveFormOptions = this.stateManager.effectiveFormOptions;\n\n /** Field signal context for injection into child components */\n fieldSignalContext = this.stateManager.fieldSignalContext;\n\n /** Default values computed from field definitions */\n defaultValues = this.stateManager.defaultValues;\n\n /** The Angular Signal Form instance */\n form = this.stateManager.form;\n\n /** Current form values (reactive) */\n formValue = this.stateManager.formValue;\n\n /** Whether the form is currently valid */\n valid = this.stateManager.valid;\n\n /** Whether the form is currently invalid */\n invalid = this.stateManager.invalid;\n\n /** Whether any form field has been modified */\n dirty = this.stateManager.dirty;\n\n /** Whether any form field has been touched (blurred) */\n touched = this.stateManager.touched;\n\n /** Current validation errors from all fields */\n errors = this.stateManager.errors;\n\n /** Whether the form is disabled (from options or form state) */\n disabled = this.stateManager.disabled;\n\n /** Whether the form is currently submitting */\n submitting = this.stateManager.submitting;\n\n /** Collects errors from async field component loading for error boundary patterns */\n fieldLoadingErrors = this.stateManager.fieldLoadingErrors;\n\n /** Whether to render the form template */\n // `derivationReady` is false only while a derivation-bearing config waits for\n // the lazily-loaded engine to wire, so fields render already-derived (no flash).\n private derivationReady = inject(DERIVATION_RENDER_GATE);\n shouldRender = computed(() => this.stateManager.shouldRender() && this.stateManager.formSchemaReady() && this.derivationReady());\n\n /**\n * What the experimental WebMCP layer is doing for this form.\n *\n * Injecting it is also what instantiates the gate (component providers are\n * lazy), which is what keeps the registrar lazily loaded. Intentionally absent\n * from `shouldRender`: agent visibility must never gate render.\n *\n * `'disabled'` unless `withExperimentalWebMcp()` is provided; `'idle'` until a\n * config declares `options.webMcp`; `'active'` once its tools are registered.\n * `'failed'` and `'unsupported'` are the two ways registration does not\n * happen, and are worth surfacing rather than guessing at.\n *\n * @experimental\n */\n readonly webMcpStatus = inject(WEB_MCP_GATE);\n\n /** Resolved fields ready for rendering */\n protected resolvedFields = this.stateManager.resolvedFields;\n\n /**\n * Effective field-windowing config for non-paged forms. Per-form\n * `FormOptions.fieldWindowing` wins over the global `withFieldWindowing()`\n * default; both fall back to disabled (fully eager).\n */\n protected readonly fieldWindowing = computed(() =>\n resolveFieldWindowing(this.globalFieldWindowing, this.effectiveFormOptions()?.fieldWindowing),\n );\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Computed Signals - Internal\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly initializedComponents = signal<ReadonlySet<string>>(new Set());\n private readonly initialPageReady = signal(false);\n\n private readonly initializationReady = computed(() => {\n const config = this.activeConfig();\n if (!config) return false;\n\n if (this.formModeDetection().mode === 'paged') return this.initialPageReady();\n\n const initialized = this.initializedComponents();\n const expected = [\n initializationComponentKey('dynamic-form', this.componentId),\n ...collectInitializingContainerKeys(config.fields ?? []),\n ];\n return expected.every((key) => initialized.has(key));\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Initialization\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Replayable readiness so late subscribers cannot miss hot EventBus announcements. */\n initialized$ = toObservable(this.initializationReady, { injector: this.injector }).pipe(\n filter((ready) => ready),\n take(1),\n shareReplay({ bufferSize: 1, refCount: false }),\n );\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Outputs\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Emits when form validity changes. */\n validityChange = outputFromObservable(toObservable(this.valid));\n\n /** Emits when form dirty state changes. */\n dirtyChange = outputFromObservable(toObservable(this.dirty));\n\n /** Emits form values when submitted (via FormSubmitEvent) and form is valid. */\n submitted = outputFromObservable(this.stateManager.submitted$);\n\n /** Emits when form is reset to default values. */\n reset = outputFromObservable(this.eventBus.on<FormResetEvent>('form-reset'));\n\n /** Emits when form is cleared to empty state. */\n cleared = outputFromObservable(this.eventBus.on<FormClearEvent>('form-clear'));\n\n /** Emits all form events for custom event handling. */\n events = outputFromObservable(this.eventBus.events$);\n\n /**\n * Emits when a non-paged form is fully initialized, or when the initially active page of a\n * paged form is ready for interaction. Virtualized inactive pages are not part of initial\n * readiness because they intentionally remain unmounted.\n */\n initialized = outputFromObservable(this.initialized$);\n\n /**\n * EXPERIMENTAL. Added alongside page preloading; the emission contract may change.\n *\n * Emits after the currently visible page and all of its visible fields render. Announced\n * once per visit to a page, and again when that page is returned to. Use this when work must\n * run after every page transition; `initialized` emits only for the initial page.\n */\n activePageInitialized = outputFromObservable(this.eventBus.on<ActivePageInitializedEvent>('active-page-initialized'));\n\n /** Emits when the current page changes in paged forms. */\n onPageChange = outputFromObservable(this.eventBus.on<PageChangeEvent>('page-change'));\n\n /** Emits when pager state changes (currentPageIndex, totalPages, isFirstPage, isLastPage). */\n onPageNavigationStateChange = outputFromObservable(this.eventBus.on<PagerStateEvent>('pager-state'));\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Constructor\n // ─────────────────────────────────────────────────────────────────────────────\n\n constructor() {\n this.eventBus\n .on<ComponentInitializedEvent>('component-initialized')\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((event) => {\n const key = initializationComponentKey(event.componentType, event.componentId);\n this.initializedComponents.update((current) => {\n if (current.has(key)) return current;\n const next = new Set(current);\n next.add(key);\n return next;\n });\n });\n this.eventBus\n .on<ActivePageInitializedEvent>('active-page-initialized')\n .pipe(takeUntilDestroyed(this.destroyRef), take(1))\n .subscribe(() => this.initialPageReady.set(true));\n\n this.dispatcher?.connect(this.eventBus);\n this.destroyRef.onDestroy(() => this.dispatcher?.disconnect());\n\n // Wake feature-provider orchestrators (derivation, property-derivation, …) so their\n // reactive streams are wired before first render. Each feature provider registers\n // itself via FORM_INITIALIZER multi-provider; resolving the array forces DI to\n // construct each entry. Without a feature provider, the array stays empty and no\n // static reference to that feature's classes leaks into this component.\n // Runs after dispatcher.connect() to preserve the prior bootstrap order.\n inject(FORM_INITIALIZER, { optional: true });\n\n // Start every field and wrapper chunk this config needs, in parallel, before\n // rendering asks for any of them. Wrapper chains are otherwise discovered\n // per-field inside DfFieldOutlet, which cannot exist until that field's own\n // component has loaded — a dependent waterfall that costs a round trip per\n // wave. Fire-and-forget: nothing here gates render.\n const preload = injectFormComponentPreloader();\n explicitEffect([this.config], ([config]) => preload.preloadConfig(config as FormConfig));\n\n this.setupEffects();\n this.setupEventHandlers();\n }\n\n /**\n * Handles native form submission triggered by:\n * - Pressing Enter in an input field\n * - Clicking a button with type=\"submit\"\n * - Programmatic form.submit() calls\n *\n * @param event - The native submit event from the form element\n */\n protected onNativeSubmit(event: Event): void {\n event.preventDefault();\n this.eventBus.dispatch(FormSubmitEvent);\n }\n\n /**\n * Whether a field should be deferred by field windowing. Containers are never\n * windowed: they emit `ComponentInitializedEvent`, which the form's init\n * tracker counts, so deferring one would stall `initialized` until it scrolls\n * into view. Leaf fields carry no such count, so they defer freely.\n */\n protected windowsField(field: ResolvedField, index: number): boolean {\n const w = this.fieldWindowing();\n return w.enabled && index >= w.eager && !isContainerField(field.fieldDef);\n }\n\n /** Class string for a windowed field's placeholder — matches the real field's grid column. */\n protected placeholderGridClass(field: ResolvedField): string {\n const grid = getGridClassString(field.fieldDef);\n return grid ? `df-field-placeholder ${grid}` : 'df-field-placeholder';\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Private Methods\n // ─────────────────────────────────────────────────────────────────────────────\n\n private setupEffects(): void {\n // Emit initialization event for paged forms\n explicitEffect([this.formModeDetection, this.pageFieldDefinitions], ([{ mode }, pages]) => {\n if (mode === 'paged' && pages.length > 0) {\n this.eventBus.dispatch(ComponentInitializedEvent, 'dynamic-form', this.componentId);\n }\n });\n\n // Emit initialization event for non-paged forms\n explicitEffect([this.resolvedFields, this.formModeDetection, this.activeConfig], ([, { mode }, config]) => {\n if (config && mode === 'non-paged') {\n afterNextRender(\n () => {\n this.eventBus.dispatch(ComponentInitializedEvent, 'dynamic-form', this.componentId);\n },\n { injector: this.injector },\n );\n }\n });\n\n // Mirror projected `<ng-template dfTemplate=\"...\">` into the template\n // registry so `template` addons can resolve `templateKey` via DI.\n explicitEffect([this._projectedTemplates], ([templates]) => {\n const map = new Map<string, TemplateRef<unknown>>();\n for (const t of templates) {\n map.set(t.dfTemplate(), t.templateRef);\n }\n this.templateRegistry.set(map);\n });\n }\n\n /**\n * Populates FORM_STATE_DEPS with this component's input signals, then injects\n * FormStateManager. Must be called as a field initializer (after the input signals\n * are declared) so that FormStateManager reads populated deps when it is constructed.\n * inject() is valid here because field initializers run inside the injection context.\n */\n private connectDeps(): FormStateManager<TFields, TModel> {\n const deps = inject(FORM_STATE_DEPS);\n deps.config = this.config as Signal<FormConfig<RegisteredFieldTypes[]>>;\n deps.formOptions = this.formOptions;\n deps.value = this.value as WritableSignal<Partial<unknown> | undefined>;\n deps.source = this.source;\n return inject(FormStateManager<TFields, TModel>);\n }\n\n private setupEventHandlers(): void {\n createSubmissionHandler<TFields, TModel>({\n eventBus: this.eventBus,\n configSignal: this.config,\n formSignal: this.form as Signal<FieldTree<TModel>>,\n validSignal: this.valid,\n logger: this.logger,\n })\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe({\n error: (err) => this.logger.error('Submission handler error', err),\n });\n }\n}\n","import { DynamicFormError } from '@ng-forge/dynamic-forms/internal';\nimport { AddonTypeDefinition } from '@ng-forge/dynamic-forms/internal';\n\n/** Built-in addon types shipped by core. */\nexport const BUILT_IN_ADDON_TYPES: readonly AddonTypeDefinition[] = [\n {\n type: 'text',\n loadComponent: () => import('../addons/text-addon.component').then((m) => m.TextAddonComponent),\n validate: (addon, fieldKey) => {\n const text = (addon as { text?: unknown }).text;\n // Validates structural presence: rejects missing / null / non-string-non-callable,\n // and rejects literal empty strings. DynamicText values that resolve to empty\n // at runtime (signal/observable yielding '') are NOT caught here — they're\n // legal as far as the config is concerned, just render an empty span.\n if (text === undefined || text === null) {\n throw new DynamicFormError(`Addon type 'text' requires a 'text' field (field: '${fieldKey}').`);\n }\n if (typeof text === 'string' && text.length === 0) {\n throw new DynamicFormError(`Addon type 'text' requires a non-empty 'text' string (field: '${fieldKey}').`);\n }\n },\n },\n {\n type: 'template',\n loadComponent: () => import('../addons/template-addon.component').then((m) => m.TemplateAddonComponent),\n validate: (addon, fieldKey) => {\n const key = (addon as { templateKey?: unknown }).templateKey;\n if (typeof key !== 'string' || key.length === 0) {\n throw new DynamicFormError(`Addon type 'template' requires a non-empty 'templateKey' string (field: '${fieldKey}').`);\n }\n },\n },\n {\n type: 'component',\n // The shape carries a function loader — not serialisable; dropped by the\n // validator when the form config originated from JSON.\n jsonSafe: false,\n loadComponent: () => import('../addons/component-addon.component').then((m) => m.ComponentAddonComponent),\n validate: (addon, fieldKey) => {\n const loader = (addon as { component?: unknown }).component;\n if (typeof loader !== 'function') {\n throw new DynamicFormError(`Addon type 'component' requires a 'component' loader function (field: '${fieldKey}').`);\n }\n },\n },\n] as const;\n","import { FieldTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { arrayFieldMapper } from '@ng-forge/dynamic-forms/internal';\nimport { groupFieldMapper } from '@ng-forge/dynamic-forms/internal';\nimport { rowFieldMapper } from '@ng-forge/dynamic-forms/internal';\nimport { pageFieldMapper } from '@ng-forge/dynamic-forms/internal';\nimport { textFieldMapper } from '@ng-forge/dynamic-forms/internal';\nimport { containerFieldMapper } from '@ng-forge/dynamic-forms/internal';\nimport { RowField } from '@ng-forge/dynamic-forms/internal';\nimport { GroupField } from '@ng-forge/dynamic-forms/internal';\nimport { HiddenField } from '@ng-forge/dynamic-forms/internal';\nimport { ArrayField } from '@ng-forge/dynamic-forms/internal';\nimport { PageField } from '@ng-forge/dynamic-forms/internal';\nimport { TextField } from '@ng-forge/dynamic-forms/internal';\nimport { ContainerField } from '@ng-forge/dynamic-forms/internal';\nimport { WrapperTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { CssWrapper } from '@ng-forge/dynamic-forms/internal';\nimport { RowWrapper } from '@ng-forge/dynamic-forms/internal';\nimport { FieldErrorsWrapper } from '@ng-forge/dynamic-forms/internal';\n\n/** Built-in field types provided by the dynamic form library. */\n/**\n * Base for container field types that consume the mapper-emitted `field` input\n * (row, group, array, page, container).\n */\nconst CONTAINER_FIELD_TYPES_BASE = {\n renderReadyWhen: ['field'],\n} as const;\n\n/**\n * Base for display-only fields (`text`) that render immediately without\n * waiting for form value integration.\n */\nconst DISPLAY_FIELD_TYPES_BASE = {\n renderReadyWhen: [],\n} as const;\n\n/** Built-in field types provided by the dynamic form library. */\nexport const BUILT_IN_FIELDS: FieldTypeDefinition[] = [\n {\n name: 'row',\n // `row` is a virtual field type: it maps to ContainerFieldComponent, and\n // the rowFieldMapper injects a `{ type: 'row' }` wrapper so the container\n // renders the flex/grid layout via RowWrapperComponent.\n loadComponent: () => import('../fields/container/container-field.component'),\n mapper: rowFieldMapper,\n valueHandling: 'flatten',\n ...CONTAINER_FIELD_TYPES_BASE,\n } satisfies FieldTypeDefinition<RowField>,\n {\n name: 'group',\n loadComponent: () => import('../fields/group/group-field.component'),\n mapper: groupFieldMapper,\n valueHandling: 'include',\n ...CONTAINER_FIELD_TYPES_BASE,\n } satisfies FieldTypeDefinition<GroupField>,\n {\n name: 'array',\n loadComponent: () => import('../fields/array/array-field.component'),\n mapper: arrayFieldMapper,\n valueHandling: 'include',\n ...CONTAINER_FIELD_TYPES_BASE,\n } satisfies FieldTypeDefinition<ArrayField>,\n {\n name: 'page',\n loadComponent: () => import('../fields/page/page-field.component'),\n mapper: pageFieldMapper,\n valueHandling: 'flatten',\n ...CONTAINER_FIELD_TYPES_BASE,\n } satisfies FieldTypeDefinition<PageField>,\n {\n name: 'text',\n loadComponent: () => import('../fields/text/text-field.component'),\n mapper: textFieldMapper,\n valueHandling: 'exclude',\n ...DISPLAY_FIELD_TYPES_BASE,\n } satisfies FieldTypeDefinition<TextField>,\n {\n name: 'hidden',\n // Componentless field - no loadComponent or mapper needed\n valueHandling: 'include',\n } satisfies FieldTypeDefinition<HiddenField>,\n {\n name: 'container',\n loadComponent: () => import('../fields/container/container-field.component'),\n mapper: containerFieldMapper,\n valueHandling: 'flatten',\n ...CONTAINER_FIELD_TYPES_BASE,\n } satisfies FieldTypeDefinition<ContainerField>,\n];\n\nexport const BUILT_IN_WRAPPERS: WrapperTypeDefinition[] = [\n {\n wrapperName: 'css',\n loadComponent: () => import('../wrappers/css/css-wrapper.component'),\n } satisfies WrapperTypeDefinition<CssWrapper>,\n {\n wrapperName: 'row',\n loadComponent: () => import('../wrappers/row/row-wrapper.component'),\n } satisfies WrapperTypeDefinition<RowWrapper>,\n {\n wrapperName: 'field-errors',\n loadComponent: () => import('../wrappers/field-errors/field-errors-wrapper.component'),\n rendersFieldErrors: true,\n } satisfies WrapperTypeDefinition<FieldErrorsWrapper>,\n];\n","import { LazyComponentLoader, WrapperTypeDefinition } from '@ng-forge/dynamic-forms/internal';\n\n/** User-facing wrapper registration shape used with `createWrappers(...)`. */\nexport interface WrapperRegistration<TName extends string = string, TConfig = unknown> {\n /** Unique identifier for the wrapper type */\n readonly wrapperName: TName;\n /** Lazy-loader for the wrapper component */\n readonly loadComponent: LazyComponentLoader;\n /** Field types this wrapper auto-applies to (merged lowest-priority during wrapper resolution) */\n readonly types?: readonly string[];\n /**\n * Type carrier only — runtime value is always `undefined`.\n * Use `wrapperProps<YourConfig>()` to thread the config type.\n */\n readonly props?: TConfig;\n}\n\n/** Branded bundle returned by `createWrappers(...)`. */\nexport interface WrappersBundle<T extends readonly WrapperRegistration[] = readonly WrapperRegistration[]> {\n readonly ɵkind: 'wrappers';\n readonly ɵregistrations: T;\n readonly ɵdefinitions: readonly WrapperTypeDefinition[];\n}\n\n/**\n * Bundle wrapper registrations into a single object that can be passed to\n * `provideDynamicForm(...)`.\n */\nexport function createWrappers<const T extends readonly WrapperRegistration[]>(...registrations: T): WrappersBundle<T> {\n return {\n ɵkind: 'wrappers',\n ɵregistrations: registrations,\n ɵdefinitions: registrations.map(({ wrapperName, loadComponent, types }) => ({\n wrapperName,\n loadComponent,\n types,\n })),\n };\n}\n\n/** Type guard for a `WrappersBundle`. */\nexport function isWrappersBundle(value: unknown): value is WrappersBundle {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'ɵkind' in value &&\n (value as { ɵkind: unknown }).ɵkind === 'wrappers' &&\n 'ɵdefinitions' in value &&\n Array.isArray((value as { ɵdefinitions: unknown }).ɵdefinitions)\n );\n}\n\n/** Derive the `FieldRegistryWrappers` augmentation shape from a wrapper bundle. */\nexport type InferWrapperRegistry<T> =\n T extends WrappersBundle<infer R>\n ? {\n [Reg in R[number] as Reg['wrapperName']]: Reg extends { props: infer P }\n ? Exclude<P, undefined>\n : { readonly type: Reg['wrapperName'] };\n }\n : never;\n","import { EnvironmentProviders, inject, makeEnvironmentProviders, Provider, Type } from '@angular/core';\nimport { ADDON_TYPE_COMPONENT_CACHE, ADDON_TYPE_REGISTRY, AddonTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { FIELD_REGISTRY, FieldTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { BUILT_IN_ADDON_TYPES } from './built-in-addons';\nimport { BUILT_IN_FIELDS, BUILT_IN_WRAPPERS } from './built-in-fields';\nimport { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormFeature, isDynamicFormFeature } from './features/dynamic-form-feature';\nimport { ADDON_TYPE_DEFINITIONS } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { ConsoleLogger } from './features/logger/console-logger';\nimport type { InferFormValue as RealInferFormValue } from '@ng-forge/dynamic-forms/internal';\nimport {\n isWrapperTypeDefinition,\n WrapperTypeDefinition,\n WRAPPER_AUTO_ASSOCIATIONS,\n WRAPPER_REGISTRY,\n WrapperConfig,\n} from '@ng-forge/dynamic-forms/internal';\nimport { isWrappersBundle, WrappersBundle } from '../wrappers/create-wrappers';\nimport { DEV_MODE } from '../utils/dev-mode';\n\n// Re-export global types for module augmentation\nexport type { DynamicFormFieldRegistry, AvailableFieldTypes } from '@ng-forge/dynamic-forms/internal';\nexport type { RegisteredFieldTypes } from '@ng-forge/dynamic-forms/internal';\n\n/** Extract FieldDef type from FieldTypeDefinition */\ntype ExtractFieldDef<T> = T extends FieldTypeDefinition<infer F> ? F : never;\n\n/** Union of all FieldDef types from provided field types */\ntype FieldDefUnion<T extends FieldTypeDefinition[]> = ExtractFieldDef<T[number]>;\n\n/** Infer form value type from field definitions using the real inference type. */\ntype InferFormValue<TFieldDefs extends FieldDef<unknown>[]> = RealInferFormValue<TFieldDefs>;\n\n/** Provider result with type inference */\ntype ProvideDynamicFormResult<T extends FieldTypeDefinition[]> = EnvironmentProviders & {\n __fieldDefs?: FieldDefUnion<T>;\n __formValue?: InferFormValue<FieldDefUnion<T>[]>;\n};\n\n/** Union type for items that can be passed to provideDynamicForm */\ntype FieldTypeOrFeature = FieldTypeDefinition | WrapperTypeDefinition | WrappersBundle | DynamicFormFeature;\n\n/** Extract only FieldTypeDefinition items from a tuple type */\ntype ExtractFieldTypes<T extends FieldTypeOrFeature[]> = {\n [K in keyof T]: T[K] extends FieldTypeDefinition ? T[K] : never;\n}[number] extends infer U\n ? U extends FieldTypeDefinition\n ? U[]\n : never\n : never;\n\n/**\n * Provider function to configure the dynamic form system with field types and options.\n *\n * @param items - Field type definitions and/or features (like withLoggerConfig)\n * @returns Environment providers for dependency injection with type inference\n * @typeParam T - Array of field type definitions for type inference\n */\nexport function provideDynamicForm<const T extends FieldTypeOrFeature[]>(\n ...items: T\n): ProvideDynamicFormResult<ExtractFieldTypes<T> extends FieldTypeDefinition[] ? ExtractFieldTypes<T> : FieldTypeDefinition[]> {\n // Separate field types, wrapper types, wrapper bundles, and features\n const fieldTypes = items.filter(\n (item): item is FieldTypeDefinition => !isDynamicFormFeature(item) && !isWrapperTypeDefinition(item) && !isWrappersBundle(item),\n );\n const wrapperTypes = items.filter(isWrapperTypeDefinition);\n const wrapperBundles = items.filter(isWrappersBundle);\n const features = items.filter(isDynamicFormFeature);\n\n const fields = [...BUILT_IN_FIELDS, ...fieldTypes];\n const customWrappers = [...wrapperTypes, ...wrapperBundles.flatMap((bundle) => bundle.ɵdefinitions)];\n const wrappers = [...BUILT_IN_WRAPPERS, ...customWrappers];\n\n // Extract providers from features (includes config features like material-config, bootstrap-config, etc.)\n const featureProviders: Provider[] = [];\n const hasLoggerFeature = features.some((feature) => feature.ɵkind === 'logger');\n features.forEach((feature) => {\n featureProviders.push(...feature.ɵproviders);\n });\n\n // Default logger provider (ConsoleLogger) if no logger feature was provided\n const defaultLoggerProvider: Provider[] = hasLoggerFeature ? [] : [{ provide: DynamicFormLogger, useValue: new ConsoleLogger() }];\n\n return makeEnvironmentProviders([\n ...defaultLoggerProvider,\n {\n provide: FIELD_REGISTRY,\n useFactory: () => {\n const logger = inject(DynamicFormLogger);\n const registry = new Map();\n // Add custom field types\n fields.forEach((fieldType) => {\n // Collision report only — last registration wins either way.\n if (DEV_MODE && registry.has(fieldType.name)) {\n logger.warn(`Field type \"${fieldType.name}\" is already registered. Overwriting.`);\n }\n registry.set(fieldType.name, fieldType);\n });\n // Back-compat: legacy camelCase array-action discriminants resolve to their\n // kebab-case canonical definitions. kebab is canonical as of 1.0; the camelCase\n // spellings are deprecated aliases kept so older/serialized configs keep working.\n const legacyTypeAliases: Record<string, string> = {\n addArrayItem: 'add-array-item',\n prependArrayItem: 'prepend-array-item',\n insertArrayItem: 'insert-array-item',\n removeArrayItem: 'remove-array-item',\n popArrayItem: 'pop-array-item',\n shiftArrayItem: 'shift-array-item',\n };\n for (const [legacy, canonical] of Object.entries(legacyTypeAliases)) {\n const def = registry.get(canonical);\n if (def && !registry.has(legacy)) registry.set(legacy, def);\n }\n return registry;\n },\n },\n // Always provide default Wrapper classes\n {\n provide: WRAPPER_REGISTRY,\n useFactory: () => {\n const logger = inject(DynamicFormLogger);\n const registry = new Map();\n // Seed the built-ins, then let later registrations replace them. Overriding a\n // built-in name is supported — an adapter restyles `field-errors` that way,\n // and an app may then override the adapter's — so those never warn. Only two\n // custom registrations colliding on a name of their own is a mistake.\n const builtInNames = new Set(BUILT_IN_WRAPPERS.map((w) => w.wrapperName));\n BUILT_IN_WRAPPERS.forEach((wrapperType) => registry.set(wrapperType.wrapperName, wrapperType));\n\n // `seenCustom` exists only to report duplicates — last registration wins either way.\n const seenCustom = DEV_MODE ? new Set<string>() : null;\n customWrappers.forEach((wrapperType) => {\n const name = wrapperType.wrapperName;\n if (seenCustom) {\n if (seenCustom.has(name) && !builtInNames.has(name)) {\n logger.warn(`Wrapper type \"${name}\" is already registered. Overwriting.`);\n }\n seenCustom.add(name);\n }\n registry.set(name, wrapperType);\n });\n return registry;\n },\n },\n // Pre-computed reverse index for auto-association lookup — built once so\n // resolveWrappers is O(1) per field render instead of scanning every\n // registered wrapper.\n {\n provide: WRAPPER_AUTO_ASSOCIATIONS,\n useFactory: () => {\n const autoMap = new Map<string, WrapperConfig[]>();\n for (const wrapperType of wrappers) {\n if (!wrapperType.types) continue;\n for (const fieldType of wrapperType.types) {\n const existing = autoMap.get(fieldType) ?? [];\n existing.push({ type: wrapperType.wrapperName } as WrapperConfig);\n autoMap.set(fieldType, existing);\n }\n }\n return autoMap;\n },\n },\n // Form-scoped addon type registry. Built from BUILT_IN_ADDON_TYPES plus\n // every kind contributed by `withCustomAddon(...)` features (via the\n // ADDON_TYPE_DEFINITIONS multi-provider). Overrides the empty\n // `providedIn: 'root'` default so contributions from form-scoped\n // providers are visible.\n {\n provide: ADDON_TYPE_REGISTRY,\n useFactory: () => {\n const logger = inject(DynamicFormLogger);\n const contributed = inject(ADDON_TYPE_DEFINITIONS, { optional: true }) ?? [];\n const registry = new Map<string, AddonTypeDefinition>();\n for (const def of BUILT_IN_ADDON_TYPES) {\n registry.set(def.type, def);\n }\n for (const def of contributed) {\n // Collision report only — last registration wins either way.\n if (DEV_MODE && registry.has(def.type)) {\n logger.warn(`Addon type \"${def.type}\" is already registered. Overwriting.`);\n }\n registry.set(def.type, def);\n }\n return registry;\n },\n },\n // Per-form addon-component cache (no root fallback — isolated by form scope).\n { provide: ADDON_TYPE_COMPONENT_CACHE, useFactory: () => new Map<string, Type<unknown>>() },\n ...featureProviders,\n ]) as ProvideDynamicFormResult<ExtractFieldTypes<T> extends FieldTypeDefinition[] ? ExtractFieldTypes<T> : FieldTypeDefinition[]>;\n}\n\n/** Extract FieldDef types from provider result */\nexport type ExtractFieldDefs<T> = T extends { __fieldDefs?: infer F } ? F : never;\n\n/** Extract form value type from provider result */\nexport type ExtractFormValue<T> = T extends { __formValue?: infer V } ? V : never;\n","import { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { EMIT_FORM_VALUE_ON_EVENTS } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Enables automatic form value attachment to all events dispatched through the EventBus.\n *\n * @remarks\n * **Precedence rules:**\n * 1. Per-form `false` - Disables for this form, regardless of global setting\n * 2. Per-form `true` - Enables for this form, regardless of global setting\n * 3. Per-form `undefined` - Uses global setting\n * 4. Global `withEventFormValue()` - Enables globally\n * 5. No global feature - Disabled globally (default)\n * @returns A DynamicFormFeature that enables form value attachment to events\n */\nexport function withEventFormValue(): DynamicFormFeature<'event-form-value'> {\n return createFeature('event-form-value', [{ provide: EMIT_FORM_VALUE_ON_EVENTS, useValue: true }]);\n}\n","import { ValueExclusionConfig } from '@ng-forge/dynamic-forms/internal';\nimport { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { VALUE_EXCLUSION_DEFAULTS } from './value-exclusion.token';\n\n/**\n * Configures global value exclusion defaults for form submission output.\n *\n * @remarks\n * **Precedence rules:**\n * 1. Per-field `excludeValueIf*` on `FieldDef` — wins for that field\n * 2. Per-form `excludeValueIf*` on `FormOptions` — wins for all fields in that form\n * 3. Global `withValueExclusionDefaults()` — baseline default\n * 4. No global feature — uses token default (all enabled)\n * @param config - Partial override of exclusion rules. Unspecified properties default to `true`.\n * @returns A DynamicFormFeature that configures value exclusion defaults\n */\nexport function withValueExclusionDefaults(config?: Partial<ValueExclusionConfig>): DynamicFormFeature<'value-exclusion'> {\n const resolved = {\n excludeValueIfHidden: config?.excludeValueIfHidden ?? true,\n excludeValueIfDisabled: config?.excludeValueIfDisabled ?? true,\n excludeValueIfReadonly: config?.excludeValueIfReadonly ?? true,\n };\n\n return createFeature('value-exclusion', [{ provide: VALUE_EXCLUSION_DEFAULTS, useValue: resolved }]);\n}\n","import { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { clampWindowSize } from '../clamp-window';\nimport { PAGE_PRELOAD_WINDOW } from './page-preload.token';\n\n/**\n * Configures the global page preload window for paged forms — how many pages on\n * each side of the current page are mounted during browser idle time.\n *\n * @remarks\n * Paged forms only ever display one page at a time, so mounting every page (the\n * fields, containers, and change-detection of pages the user may never reach)\n * is wasted work: it inflates initial-render time and makes every keystroke pay\n * change detection for off-screen pages. The preload window bounds how much is\n * mounted around the current page. The active page always renders directly;\n * eligible neighbours render on idle. Pages outside the window remain lightweight\n * placeholders until navigation or a window change makes them eligible.\n *\n * **Precedence:**\n * 1. Per-form `pagePreloadWindow` on `FormOptions` — wins for that form\n * 2. Global `withPagePreload(n)` — baseline default for all forms\n * 3. No feature — token default (`1`, i.e. current page ±1)\n *\n * @param window - Pages to preload on idle on each side of the current page. `0`\n * mounts only the current page; `1` (default) mounts ±1 for flicker-free sequential\n * navigation; higher values pre-warm more pages for jump navigation. Negative\n * values are clamped to `0`.\n * @returns A DynamicFormFeature that configures the global preload window\n *\n * @example\n * ```typescript\n * provideDynamicForm(...withMaterialFields(), withPagePreload(2));\n * ```\n */\nexport function withPagePreload(window: number): DynamicFormFeature<'page-preload'> {\n const resolved = clampWindowSize(window, 1);\n return createFeature('page-preload', [{ provide: PAGE_PRELOAD_WINDOW, useValue: resolved }]);\n}\n","import { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { clampWindowSize } from '../clamp-window';\nimport { FIELD_WINDOWING, FieldWindowingConfig } from './field-windowing.token';\nimport { FieldParkingOption, resolveFieldParking } from './resolve-field-windowing';\n\n/**\n * Configures global progressive field mounting (\"field windowing\") for large\n * flat (single-page) forms.\n *\n * @remarks\n * A flat form mounts every field eagerly, so a large form pays the full\n * initial-render cost up front and every keystroke walks all N live views —\n * even for fields far off-screen. Field windowing bounds how much is mounted:\n * the first `eager` fields render immediately, and the rest render as a\n * lightweight placeholder that mounts the moment it scrolls near/into view.\n * Validators, derivations, and values live at the Signal Forms schema level\n * (not the DOM), so unmounted fields keep full form semantics.\n *\n * Mounting is one-way — `@defer (on viewport)` never unmounts — so on its own\n * that bound is temporary: scroll a long form once and every field is live\n * again for the rest of the session. **Parking** closes the gap and comes on\n * with this feature (it is off when the feature is not used, since it changes\n * rendering behaviour). A field scrolled outside `park.margin` leaves change detection but\n * keeps its DOM, so it costs nothing per keystroke while staying findable by\n * browser search, fillable by autofill, and reachable by assistive tech. Its\n * own edits still reach the model: Angular binds `input` / `blur` with plain\n * DOM listeners, which keep firing on a detached view.\n *\n * **Precedence:**\n * 1. Per-form `fieldWindowing` on `FormOptions` — wins for that form\n * 2. Global `withFieldWindowing(...)` — baseline default for all forms\n * 3. No feature — token default (disabled, i.e. fully eager)\n *\n * @param config - `eager` (default `12`), `placeholderHeight` (default `'4rem'`)\n * and `park` (default on, margin `'100%'`) overrides. `eager` is clamped to a\n * non-negative integer.\n * @returns A DynamicFormFeature that enables the global field windowing default\n *\n * @example\n * ```typescript\n * provideDynamicForm(...withMaterialFields(), withFieldWindowing({ eager: 20 }));\n * ```\n */\nexport function withFieldWindowing(config?: {\n eager?: number;\n placeholderHeight?: string;\n park?: FieldParkingOption;\n}): DynamicFormFeature<'field-windowing'> {\n const resolved: FieldWindowingConfig = {\n enabled: true,\n eager: clampWindowSize(config?.eager, 12),\n placeholderHeight: config?.placeholderHeight ?? '4rem',\n park: resolveFieldParking({ enabled: true, margin: '100%' }, config?.park),\n };\n\n return createFeature('field-windowing', [{ provide: FIELD_WINDOWING, useValue: resolved }]);\n}\n","import { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { WEB_MCP_ENABLED } from './web-mcp.token';\n\n/**\n * Enables WebMCP tool registration for forms that declare `options.webMcp`.\n *\n * @experimental\n *\n * @remarks\n * WebMCP lets an AI agent running in the browser discover and drive a form\n * through structured tools rather than by simulating clicks. Each opted-in form\n * registers `fill_{name}`, which applies a partial patch of values to the form\n * and reports back what it set, which fields apply, which are still empty, and\n * any validation errors. Submission is a separate, per-form opt-in\n * (`options.webMcp.allowSubmit`); without it the agent stages values and a human\n * presses the button.\n *\n * The tool schema is generated from the form config, so agents see labels,\n * option enums with their human titles, and static validator constraints rather\n * than the bare types value-shape inference would produce. Agent arguments are\n * validated in code before anything is written, and a call that does not parse\n * is rejected whole rather than half-applied.\n *\n * Nothing is registered unless a form opts in, and the registrar module is\n * dynamically imported, so a form without `options.webMcp` never loads it — the\n * feature itself, the token and the form-scoped hook that decides are part of\n * the main bundle. Registration is browser-only and no-ops where the page\n * exposes no model context.\n *\n * Named `experimental` on purpose: WebMCP is a proposed standard, in an origin\n * trial as of Chrome 149, and the browser surface underneath this may still\n * change. Expect breaking changes outside a major version.\n *\n * @returns A DynamicFormFeature enabling WebMCP registration.\n *\n * @example\n * ```typescript\n * provideDynamicForm(...withMaterialFields(), withExperimentalWebMcp());\n *\n * const config = {\n * options: { webMcp: { name: 'signup', description: 'Sign a new user up.' } },\n * fields: [...],\n * } as const satisfies FormConfig;\n * ```\n */\nexport function withExperimentalWebMcp(): DynamicFormFeature<'web-mcp'> {\n return createFeature('web-mcp', [{ provide: WEB_MCP_ENABLED, useValue: true }]);\n}\n","import { ResolvedValidationExecutionConfig, ValidationExecutionConfig } from '@ng-forge/dynamic-forms/internal';\nimport { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { VALIDATION_EXECUTION_DEFAULTS } from './validation-execution.token';\n\n/**\n * Configures global validation execution defaults — when validators should run\n * relative to a field's reactive state.\n *\n * @remarks\n * **Precedence rules:**\n * 1. Per-field `FieldDef.validateWhenHidden` — wins for that field; inherits down to descendants\n * that don't override.\n * 2. Per-form `FormOptions.validateWhenHidden` — root inherited value for the form.\n * 3. Global `withValidationExecutionDefaults()` — fallback when no form/field setting.\n * 4. No feature configured — uses token default (`validateWhenHidden: false`).\n * @param config - Partial override. Unspecified properties keep their defaults.\n * @returns A `DynamicFormFeature` that configures validation execution defaults.\n */\nexport function withValidationExecutionDefaults(config?: Partial<ValidationExecutionConfig>): DynamicFormFeature<'validation-execution'> {\n const resolved: ResolvedValidationExecutionConfig = {\n validateWhenHidden: config?.validateWhenHidden ?? false,\n };\n\n return createFeature('validation-execution', [{ provide: VALIDATION_EXECUTION_DEFAULTS, useValue: resolved }]);\n}\n","import { provideSignalFormsConfig } from '@angular/forms/signals';\nimport { NG_STATUS_CLASSES } from '@angular/forms/signals/compat';\nimport { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\n\n/**\n * Opt into Angular Signal Forms' legacy `.ng-touched` / `.ng-invalid` /\n * `.ng-dirty` / `.ng-pristine` / `.ng-untouched` / `.ng-pending` /\n * `.ng-valid` CSS classes on form-bound elements.\n *\n * @returns A DynamicFormFeature that enables the legacy `ng-*` class strategy\n */\nexport function withLegacyStatusClasses(): DynamicFormFeature<'legacy-status-classes'> {\n return createFeature('legacy-status-classes', [...provideSignalFormsConfig({ classes: NG_STATUS_CLASSES })]);\n}\n","/** Zero-cost type carrier used in wrapper registrations. */\nexport function wrapperProps<T>(): T {\n return undefined as unknown as T;\n}\n","import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { TextAddon } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/internal';\nimport { WrapperFieldInputs } from '@ng-forge/dynamic-forms/internal';\n\n/** Renderer for the universal `text` addon type. */\n@Component({\n selector: 'df-text-addon',\n imports: [AsyncPipe, DynamicTextPipe],\n template: `<span>{{ addon().text | dynamicText | async }}</span>`,\n host: {\n '[attr.aria-hidden]': '\"true\"',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TextAddonComponent {\n readonly addon = input.required<TextAddon>();\n /** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every kind must declare it. */\n readonly fieldInputs = input<WrapperFieldInputs | undefined>();\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { TemplateAddon } from '@ng-forge/dynamic-forms/internal';\nimport { DF_FIELD_TEMPLATES } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { WrapperFieldInputs } from '@ng-forge/dynamic-forms/internal';\n\n/** Renderer for the universal `template` addon type. */\n@Component({\n selector: 'df-template-addon',\n imports: [NgTemplateOutlet],\n template: `\n @if (template(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: outletContext()\" />\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TemplateAddonComponent {\n private readonly templates = inject(DF_FIELD_TEMPLATES, { optional: true });\n private readonly logger = inject(DynamicFormLogger);\n\n readonly addon = input.required<TemplateAddon>();\n /** Forwarded by `df-addon-slot`; surfaced to the template as its implicit `$implicit` context. */\n readonly fieldInputs = input<WrapperFieldInputs | undefined>();\n\n // Pure computed: pure lookup, no side effects. Unresolved → null; the\n // `@if` in the template skips the outlet and renders nothing.\n protected readonly template = computed(() => {\n const map = this.templates?.();\n const key = this.addon().templateKey;\n return map?.get(key) ?? null;\n });\n\n /** Implicit context payload — template authors bind via `let-fi`. */\n protected readonly outletContext = computed(() => ({ $implicit: this.fieldInputs() }));\n\n constructor() {\n // Logging side effect lives in an effect, not the computed — keeps\n // the computed pure so signal-graph evaluations don't duplicate warnings.\n explicitEffect([this.template, this.addon], ([tpl, addon]) => {\n if (!tpl) {\n this.logger.warn(\n `Template addon: no <ng-template dfTemplate=\"${addon.templateKey}\"> found. Did you project it as a child of <df-dynamic-form>?`,\n );\n }\n });\n }\n}\n","import { NgComponentOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, inject, input, signal, Type } from '@angular/core';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport type { ComponentAddon } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { resolveDefaultExport } from '../utils/wrapper-chain/wrapper-chain';\nimport type { WrapperFieldInputs } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Renderer for the universal `component` addon type.\n *\n * @codeOnly The `component` loader is a function; this kind is dropped in\n * lenient validation when the config originated from JSON.\n */\n@Component({\n selector: 'df-component-addon',\n imports: [NgComponentOutlet],\n template: `\n @if (resolvedComponent(); as cmp) {\n <ng-container *ngComponentOutlet=\"cmp; inputs: inputs()\" />\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ComponentAddonComponent {\n private readonly logger = inject(DynamicFormLogger);\n\n readonly addon = input.required<ComponentAddon>();\n /** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every kind must declare it. */\n readonly fieldInputs = input<WrapperFieldInputs | undefined>();\n\n protected readonly inputs = computed(() => (this.addon().inputs ?? {}) as Record<string, unknown>);\n\n /**\n * Latest async-loaded `{ addon, component }` pair. Tagging the result with\n * its source addon lets `resolvedComponent` filter stale loads structurally\n * — same kind-tagging pattern `DfAddonSlot` uses. When `addon` swaps\n * mid-load, the prior loader still completes and writes here, but the\n * computed ignores it because the recorded addon no longer matches the\n * current one.\n */\n private readonly asyncLoaded = signal<{ addon: ComponentAddon; component: Type<unknown> } | undefined>(undefined);\n\n protected readonly resolvedComponent = computed<Type<unknown> | undefined>(() => {\n const current = this.addon();\n const loaded = this.asyncLoaded();\n return loaded?.addon === current ? loaded.component : undefined;\n });\n\n constructor() {\n explicitEffect([this.addon], ([addon]) => {\n Promise.resolve(addon.component())\n .then((mod) => {\n const component = resolveDefaultExport(mod);\n if (component) this.asyncLoaded.set({ addon, component });\n })\n .catch((error: unknown) => {\n this.logger.warn(\n `Failed to load component addon (slot: '${addon.slot}'): ${error instanceof Error ? error.message : String(error)}`,\n );\n });\n });\n }\n}\n","import { AddonTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { BaseAddon } from '@ng-forge/dynamic-forms/internal';\nimport { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { ADDON_TYPE_DEFINITIONS } from '@ng-forge/dynamic-forms/internal';\n\n/** Register a custom addon type with the form. */\nexport function withCustomAddon<T extends BaseAddon>(definition: AddonTypeDefinition<T>): DynamicFormFeature<'addons'> {\n return createFeature('addons', [\n {\n provide: ADDON_TYPE_DEFINITIONS,\n useValue: definition as AddonTypeDefinition,\n multi: true,\n },\n ]);\n}\n","import { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { AddonActionHandler, ADDON_ACTION_HANDLERS } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Typed feature returned by {@link withAddonActions}. Carries the\n * registered handler keys as a phantom type so consumers can derive the\n * `DynamicFormActionRegistry` augmentation in one line instead of hand-typing\n * every key.\n */\nexport type AddonActionsFeature<K extends string = string> = DynamicFormFeature<'addon-actions'> & {\n /** @internal Phantom field carrying the registered keys; never read at runtime. */\n readonly __handlerKeys?: K;\n};\n\n/** Register named action handlers reachable via JSON-driven addon configs. */\nexport function withAddonActions<const H extends Record<string, AddonActionHandler>>(handlers: H): AddonActionsFeature<keyof H & string> {\n return createFeature('addon-actions', [\n {\n provide: ADDON_ACTION_HANDLERS,\n useValue: handlers,\n multi: true,\n },\n ]) as AddonActionsFeature<keyof H & string>;\n}\n","import { inject } from '@angular/core';\nimport { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { ADDON_TYPE_REGISTRY } from '@ng-forge/dynamic-forms/internal';\nimport { FormConfig } from '@ng-forge/dynamic-forms/internal';\nimport { FIELD_REGISTRY } from '@ng-forge/dynamic-forms/internal';\nimport { Logger } from '@ng-forge/dynamic-forms/internal';\nimport { AddonWarning, formatAddonWarning } from './addon-warning';\nimport { walkAndValidateAddons } from './validate-field-addons';\n\n/** Options accepted by {@link sanitizeFormConfig}. */\nexport interface SanitizeFormConfigOptions {\n /**\n * Whether the config originated from JSON (server-driven) or inline\n * TypeScript code.\n */\n source?: 'json' | 'inline';\n}\n\n/** Result of a `sanitizeFormConfig` call. */\nexport interface SanitizedFormConfig {\n /** Sanitized config — invalid addons stripped from the field tree. */\n sanitized: FormConfig;\n /** Structured list of every addon that was dropped, and why. */\n warnings: readonly AddonWarning[];\n}\n\n/**\n * Walk a `FormConfig`, validate every field's addons against the active\n * `FIELD_REGISTRY` and `ADDON_TYPE_REGISTRY`, and return a sanitized copy\n * plus a list of dropped-addon warnings.\n *\n * @Component({ ... })\n * class AdminFormBuilder {\n * private readonly check = (cfg: FormConfig) => {\n * const { sanitized, warnings } = sanitizeFormConfig(cfg, { source: 'json' });\n * if (warnings.length > 0) {\n * this.diagnostics.set(warnings);\n * }\n * return sanitized;\n * };\n * }\n * ```\n */\nexport function sanitizeFormConfig(config: FormConfig, options: SanitizeFormConfigOptions = {}): SanitizedFormConfig {\n const fieldRegistry = inject(FIELD_REGISTRY);\n const typeRegistry = inject(ADDON_TYPE_REGISTRY);\n const source = options.source ?? 'inline';\n\n const { fields, warnings } = walkAndValidateAddons(\n (config.fields ?? []) as readonly FieldDef<unknown>[],\n fieldRegistry,\n typeRegistry,\n source,\n );\n\n return {\n sanitized: { ...config, fields: fields as FormConfig['fields'] },\n warnings,\n };\n}\n\n/**\n * Default warning sink. Pass a `DynamicFormLogger` to route through the\n * form's configured logger (respects `NoopLogger` opt-out); omit it to\n * fall back to `console.warn` for build-time / admin-UI use cases that\n * run outside an Angular injection context.\n */\nexport function logAddonWarnings(warnings: readonly AddonWarning[], logger?: Logger): void {\n for (const w of warnings) {\n if (logger) {\n logger.warn(formatAddonWarning(w));\n } else {\n console.warn('[Dynamic Forms]', formatAddonWarning(w));\n }\n }\n}\n\n/**\n * DI-free variant of {@link sanitizeFormConfig} for tooling that lives\n * outside Angular's injector — build-time linters, MCP-side checks, CLI\n * scripts.\n */\nexport function sanitizeFormConfigPure(\n config: FormConfig,\n fieldRegistry: ReadonlyMap<string, import('@ng-forge/dynamic-forms/internal').FieldTypeDefinition>,\n typeRegistry: ReadonlyMap<string, import('@ng-forge/dynamic-forms/internal').AddonTypeDefinition>,\n options: SanitizeFormConfigOptions = {},\n): SanitizedFormConfig {\n const source = options.source ?? 'inline';\n const { fields, warnings } = walkAndValidateAddons(\n (config.fields ?? []) as readonly FieldDef<unknown>[],\n fieldRegistry,\n typeRegistry,\n source,\n );\n return { sanitized: { ...config, fields: fields as FormConfig['fields'] }, warnings };\n}\n\nexport { formatAddonWarning } from './addon-warning';\nexport type { AddonWarning } from './addon-warning';\nexport { validateFieldAddons, walkAndValidateAddons } from './validate-field-addons';\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Per-dispatch overrides for a page jump. */\nexport interface PageNavigationOptions {\n /**\n * Whether to apply the forward-jump validity gate.\n *\n * Set `false` to land on the target regardless of earlier pages, which is what\n * restoring a saved session wants. Bounds and hidden-page checks still apply.\n *\n * @default true\n */\n validate?: boolean;\n}\n\n/**\n * Event dispatched to move a paged form to a specific page.\n *\n * Backward jumps are unconditional. Forward jumps validate every visible page\n * between the current one and the target (the target itself is not validated);\n * if one is invalid, navigation stops on the first invalid page. Pass\n * `{ validate: false }` to skip that gate and land on the target.\n */\nexport class GoToPageEvent implements FormEvent {\n readonly type = 'go-to-page' as const;\n\n constructor(\n /** The target page index (0-based) */\n public readonly pageIndex: number,\n /** Per-dispatch overrides; omit for the default gated behavior. */\n public readonly options?: PageNavigationOptions,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched to advance a paged form to the next page. */\nexport class NextPageEvent implements FormEvent {\n readonly type = 'next-page' as const;\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched to return a paged form to the previous page. */\nexport class PreviousPageEvent implements FormEvent {\n readonly type = 'previous-page' as const;\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched when the form should be reset to its default values. */\nexport class FormResetEvent implements FormEvent {\n readonly type = 'form-reset' as const;\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched when the form should be cleared. */\nexport class FormClearEvent implements FormEvent {\n readonly type = 'form-clear' as const;\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\nimport { ArrayItemDefinition, ArrayItemTemplate } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Template type for array items used in events.\n * Canonical definition lives in {@link ArrayItemDefinition} — this alias\n * preserves the events-specific naming convention.\n */\nexport type ArrayItemDefinitionTemplate = ArrayItemDefinition;\n\n// Re-export the canonical ArrayItemTemplate for backwards-compatible event API surface\nexport type { ArrayItemTemplate };\n\n/**\n * Event dispatched to append a new item at the END of an array field.\n *\n * @typeParam TTemplate - The type of the template (single field or array of fields)\n */\nexport class AppendArrayItemEvent<TTemplate extends ArrayItemDefinitionTemplate = ArrayItemDefinitionTemplate> implements FormEvent {\n readonly type = 'append-array-item' as const;\n\n constructor(\n /** The key of the array field to append an item to */\n public readonly arrayKey: string,\n /**\n * Template for the new array item. REQUIRED.\n * - Single field (FieldDef): Creates a primitive item (field's value is extracted directly)\n * - Array of fields (FieldDef[]): Creates an object item (fields merged into object)\n */\n public readonly template: TTemplate,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\nimport { ArrayItemDefinitionTemplate } from './append-array-item.event';\n\n/**\n * Event dispatched to prepend a new item at the BEGINNING of an array field.\n *\n * @typeParam TTemplate - The type of the template (single field or array of fields)\n */\nexport class PrependArrayItemEvent<TTemplate extends ArrayItemDefinitionTemplate = ArrayItemDefinitionTemplate> implements FormEvent {\n readonly type = 'prepend-array-item' as const;\n\n constructor(\n /** The key of the array field to prepend an item to */\n public readonly arrayKey: string,\n /**\n * Template for the new array item. REQUIRED.\n * - Single field (FieldDef): Creates a primitive item (field's value is extracted directly)\n * - Array of fields (FieldDef[]): Creates an object item (fields merged into object)\n */\n public readonly template: TTemplate,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\nimport { ArrayItemDefinitionTemplate } from './append-array-item.event';\n\n/**\n * Event dispatched to insert a new item at a SPECIFIC INDEX in an array field.\n *\n * @typeParam TTemplate - The type of the template (single field or array of fields)\n */\nexport class InsertArrayItemEvent<TTemplate extends ArrayItemDefinitionTemplate = ArrayItemDefinitionTemplate> implements FormEvent {\n readonly type = 'insert-array-item' as const;\n\n constructor(\n /** The key of the array field to insert an item into */\n public readonly arrayKey: string,\n /** The index at which to insert the new item */\n public readonly index: number,\n /**\n * Template for the new array item. REQUIRED.\n * - Single field (FieldDef): Creates a primitive item (field's value is extracted directly)\n * - Array of fields (FieldDef[]): Creates an object item (fields merged into object)\n */\n public readonly template: TTemplate,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched to remove the LAST item from an array field. */\nexport class PopArrayItemEvent implements FormEvent {\n readonly type = 'pop-array-item' as const;\n\n constructor(\n /** The key of the array field to remove the last item from */\n public readonly arrayKey: string,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched to remove the FIRST item from an array field. */\nexport class ShiftArrayItemEvent implements FormEvent {\n readonly type = 'shift-array-item' as const;\n\n constructor(\n /** The key of the array field to remove the first item from */\n public readonly arrayKey: string,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched to move an existing item from one index to another within an array field. */\nexport class MoveArrayItemEvent implements FormEvent {\n readonly type = 'move-array-item' as const;\n\n constructor(\n /** The key of the array field containing the item to move */\n public readonly arrayKey: string,\n /** The current index of the item to move */\n public readonly fromIndex: number,\n /** The target index to move the item to */\n public readonly toIndex: number,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched to remove an item at a SPECIFIC INDEX from an array field. */\nexport class RemoveAtIndexEvent implements FormEvent {\n readonly type = 'remove-at-index' as const;\n\n constructor(\n /** The key of the array field to remove an item from */\n public readonly arrayKey: string,\n /** The index of the item to remove */\n public readonly index: number,\n ) {}\n}\n","import { AppendArrayItemEvent, ArrayItemDefinitionTemplate } from './constants/append-array-item.event';\nimport { PrependArrayItemEvent } from './constants/prepend-array-item.event';\nimport { InsertArrayItemEvent } from './constants/insert-array-item.event';\nimport { MoveArrayItemEvent } from './constants/move-array-item.event';\nimport { PopArrayItemEvent } from './constants/pop-array-item.event';\nimport { ShiftArrayItemEvent } from './constants/shift-array-item.event';\nimport { RemoveAtIndexEvent } from './constants/remove-at-index.event';\n\n/**\n * Builder for array manipulation events.\n *\n * @param arrayKey - The key of the array field to operate on\n * @returns An object with methods for all 7 array operations\n */\nexport function arrayEvent(arrayKey: string) {\n return {\n /**\n * Append a new item at the END of the array.\n * This is the most common operation for adding items.\n *\n * @param template - Template for the new item (REQUIRED)\n * - Single field: Creates a primitive item (field's value is extracted directly)\n * - Array of fields: Creates an object item (fields merged into object)\n * @returns An AppendArrayItemEvent to dispatch\n */\n append: <T extends ArrayItemDefinitionTemplate>(template: T) => new AppendArrayItemEvent(arrayKey, template),\n\n /**\n * Prepend a new item at the BEGINNING of the array.\n * Use when new items should appear at the start.\n *\n * @param template - Template for the new item (REQUIRED)\n * - Single field: Creates a primitive item (field's value is extracted directly)\n * - Array of fields: Creates an object item (fields merged into object)\n * @returns A PrependArrayItemEvent to dispatch\n */\n prepend: <T extends ArrayItemDefinitionTemplate>(template: T) => new PrependArrayItemEvent(arrayKey, template),\n\n /**\n * Insert a new item at a SPECIFIC INDEX in the array.\n * Use when you need precise control over item placement.\n *\n * @param index - The position at which to insert the new item\n * @param template - Template for the new item (REQUIRED)\n * - Single field: Creates a primitive item (field's value is extracted directly)\n * - Array of fields: Creates an object item (fields merged into object)\n * @returns An InsertArrayItemEvent to dispatch\n */\n insertAt: <T extends ArrayItemDefinitionTemplate>(index: number, template: T) => new InsertArrayItemEvent(arrayKey, index, template),\n\n /**\n * Remove the LAST item from the array.\n * Equivalent to JavaScript's `Array.pop()`.\n *\n * @returns A PopArrayItemEvent to dispatch\n */\n pop: () => new PopArrayItemEvent(arrayKey),\n\n /**\n * Remove the FIRST item from the array.\n * Equivalent to JavaScript's `Array.shift()`.\n *\n * @returns A ShiftArrayItemEvent to dispatch\n */\n shift: () => new ShiftArrayItemEvent(arrayKey),\n\n /**\n * Remove an item at a SPECIFIC INDEX from the array.\n * Use when you need to remove a specific item by position.\n *\n * @param index - The position of the item to remove\n * @returns A RemoveAtIndexEvent to dispatch\n */\n removeAt: (index: number) => new RemoveAtIndexEvent(arrayKey, index),\n\n /**\n * Move an existing item from one position to another within the array.\n * This is an atomic reorder — the item is NOT destroyed and recreated.\n * The resolved component, form value, and stored template are preserved.\n *\n * @param from - The current index of the item to move\n * @param to - The target index to move the item to\n * @returns A MoveArrayItemEvent to dispatch\n */\n move: (from: number, to: number) => new MoveArrayItemEvent(arrayKey, from, to),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ng-forge-dynamic-forms.mjs","names":["isPageField","isRowField","DynamicFormLogger","DynamicFormLogger","DynamicFormLogger","DynamicFormLogger","isContainerField","DF_FIELD_TEMPLATES","DynamicFormError","isWrapperTypeDefinition","DynamicFormLogger","DF_FIELD_TEMPLATES","DynamicFormLogger","DynamicFormLogger"],"sources":["../../../../packages/dynamic-forms/src/lib/utils/submission-handler/submission-handler.ts","../../../../packages/dynamic-forms/src/lib/utils/preload-form-components/preload-form-components.ts","../../../../packages/dynamic-forms/src/lib/events/constants/page-change.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/pager-state.event.ts","../../../../packages/dynamic-forms/src/lib/providers/features/page-preload/page-preload.token.ts","../../../../packages/dynamic-forms/src/lib/utils/page-utils/collect-leaf-field-keys.ts","../../../../packages/dynamic-forms/src/lib/core/page-orchestrator/page-orchestrator.component.ts","../../../../packages/dynamic-forms/src/lib/core/derivation/config-has-derivations.ts","../../../../packages/dynamic-forms/src/lib/core/derivation/derivation-render-gate.ts","../../../../packages/dynamic-forms/src/lib/providers/features/web-mcp/web-mcp.token.ts","../../../../packages/dynamic-forms/src/lib/core/web-mcp/web-mcp-gate.ts","../../../../packages/dynamic-forms/src/lib/providers/form-initializer.token.ts","../../../../packages/dynamic-forms/src/lib/core/registry/dynamic-form-instance-registry.service.ts","../../../../packages/dynamic-forms/src/lib/core/registry/form-id-prefix.service.ts","../../../../packages/dynamic-forms/src/lib/providers/dynamic-form-di.ts","../../../../packages/dynamic-forms/src/lib/events/event-dispatcher.ts","../../../../packages/dynamic-forms/src/lib/directives/df-template.directive.ts","../../../../packages/dynamic-forms/src/lib/dynamic-form.component.ts","../../../../packages/dynamic-forms/src/lib/providers/built-in-addons.ts","../../../../packages/dynamic-forms/src/lib/providers/built-in-fields.ts","../../../../packages/dynamic-forms/src/lib/wrappers/create-wrappers.ts","../../../../packages/dynamic-forms/src/lib/providers/dynamic-form-providers.ts","../../../../packages/dynamic-forms/src/lib/providers/features/event-form-value/with-event-form-value.ts","../../../../packages/dynamic-forms/src/lib/providers/features/value-exclusion/with-value-exclusion-defaults.ts","../../../../packages/dynamic-forms/src/lib/providers/features/page-preload/with-page-preload.ts","../../../../packages/dynamic-forms/src/lib/providers/features/field-windowing/with-field-windowing.ts","../../../../packages/dynamic-forms/src/lib/providers/features/web-mcp/with-web-mcp.ts","../../../../packages/dynamic-forms/src/lib/providers/features/validation-execution/with-validation-execution-defaults.ts","../../../../packages/dynamic-forms/src/lib/providers/features/legacy-status-classes/with-legacy-status-classes.ts","../../../../packages/dynamic-forms/src/lib/wrappers/wrapper-props.ts","../../../../packages/dynamic-forms/src/lib/addons/text-addon.component.ts","../../../../packages/dynamic-forms/src/lib/addons/template-addon.component.ts","../../../../packages/dynamic-forms/src/lib/addons/component-addon.component.ts","../../../../packages/dynamic-forms/src/lib/providers/features/addons/with-custom-addon.ts","../../../../packages/dynamic-forms/src/lib/providers/features/addons/with-addon-actions.ts","../../../../packages/dynamic-forms/src/lib/utils/validate-form-config/validate-form-config.ts","../../../../packages/dynamic-forms/src/lib/events/constants/go-to-page.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/next-page.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/previous-page.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/form-reset.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/form-clear.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/append-array-item.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/prepend-array-item.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/insert-array-item.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/pop-array-item.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/shift-array-item.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/move-array-item.event.ts","../../../../packages/dynamic-forms/src/lib/events/constants/remove-at-index.event.ts","../../../../packages/dynamic-forms/src/lib/events/array-event.ts"],"sourcesContent":["import { Signal } from '@angular/core';\nimport { FieldTree, submit, TreeValidationResult } from '@angular/forms/signals';\nimport { catchError, defer, EMPTY, exhaustMap, firstValueFrom, from, isObservable, Observable, tap } from 'rxjs';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { FormSubmitEvent } from '../../events/constants/submit.event';\nimport { FormConfig } from '@ng-forge/dynamic-forms/internal';\nimport { RegisteredFieldTypes } from '@ng-forge/dynamic-forms/internal';\nimport type { InferFormModel } from '@ng-forge/dynamic-forms/internal';\nimport type { Logger } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Options for creating a submission handler.\n *\n * @typeParam TFields - Array of registered field types available for this form\n * @typeParam TModel - The form value model type (inferred from TFields by default)\n */\nexport interface SubmissionHandlerOptions<\n TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[],\n TModel extends Record<string, unknown> = InferFormModel<TFields>,\n> {\n /** Event bus instance for listening to submit events */\n eventBus: EventBus;\n /** Signal containing the form configuration */\n configSignal: Signal<FormConfig<TFields>>;\n /** Signal containing the form instance */\n formSignal: Signal<FieldTree<TModel>>;\n /** Signal indicating whether the form is currently valid */\n validSignal: Signal<boolean>;\n /** Logger instance for consistent error reporting */\n logger: Logger;\n}\n\n/**\n * Reads whether async validators are still resolving, so a skipped submission\n * can say *why* it was skipped rather than reporting a validation failure that\n * has not actually happened yet.\n */\nfunction isPending<TModel extends Record<string, unknown>>(formSignal: Signal<FieldTree<TModel>>): boolean {\n return formSignal()().pending();\n}\n\n/**\n * Whether a resolved action result is a `TreeValidationResult` carrying server errors.\n *\n * `SubmissionConfig.action` also permits arbitrary success payloads (an Observable\n * action is typically an HTTP call resolving to a response body), so anything that\n * is not shaped like one-or-many `ValidationError` is reported to `submit()` as\n * success rather than being misread as a validation failure.\n */\nfunction isTreeValidationErrors(result: unknown): result is TreeValidationResult {\n const isError = (v: unknown): boolean => typeof v === 'object' && v !== null && 'kind' in v;\n return Array.isArray(result) ? result.every(isError) && result.length > 0 : isError(result);\n}\n\n/**\n * Wraps a submission action to handle both Promise and Observable returns.\n * Converts Observables to Promises for compatibility with Angular Signal Forms' submit().\n *\n * The resolved value is handed back to `submit()` so that an action returning\n * `TreeValidationResult` has its server errors applied to the form.\n *\n * @param action - The submission action function\n * @returns A wrapped function that returns a Promise\n */\nfunction wrapSubmissionAction<TModel extends Record<string, unknown>>(\n action: (formTree: FieldTree<TModel>) => unknown,\n): (formTree: FieldTree<TModel>) => Promise<TreeValidationResult> {\n return async (formTree: FieldTree<TModel>): Promise<TreeValidationResult> => {\n const result = action(formTree);\n // If the action returns an Observable, take its first emission\n const resolved = isObservable(result) ? await firstValueFrom(result) : await Promise.resolve(result);\n\n return isTreeValidationErrors(resolved) ? resolved : undefined;\n };\n}\n\n/**\n * Creates an Observable that handles form submission with optional submission action.\n *\n * @param options - Configuration options for the submission handler\n * @returns Observable that processes submissions (emits when submission completes)\n */\nexport function createSubmissionHandler<\n TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[],\n TModel extends Record<string, unknown> = InferFormModel<TFields>,\n>(options: SubmissionHandlerOptions<TFields, TModel>): Observable<unknown> {\n const { eventBus, configSignal, formSignal, validSignal, logger } = options;\n\n // exhaustMap ensures first-submit-wins: a second submit event while the first\n // is in-flight is silently dropped rather than cancelling the running Promise.\n // switchMap would unsubscribe the Observable wrapper but cannot cancel the\n // underlying Promise, causing both side effects to execute.\n return eventBus.on<FormSubmitEvent>('submit').pipe(\n exhaustMap((event) => {\n // Taking the event is reported before anything else: a caller waiting on a\n // reply distinguishes \"dropped by exhaustMap\" from \"running\" by whether\n // this ran during its synchronous dispatch.\n const reply = event.reply;\n reply?.accept();\n\n const submissionConfig = configSignal().submission;\n\n // If no submission action is configured, let the submitted output handle it\n // This maintains backward compatibility for users handling submission manually\n if (!submissionConfig?.action) {\n reply?.settle(validSignal() ? { status: 'dispatched' } : { status: 'validation-failed' });\n return EMPTY;\n }\n\n // Guard: match the (submitted) output's safety contract — reject submission\n // when the form is invalid or has pending async validators.\n if (!validSignal()) {\n logger.debug('Submission action skipped: form is not valid (invalid or pending async validators)');\n reply?.settle(isPending(formSignal) ? { status: 'pending-validation' } : { status: 'validation-failed' });\n return EMPTY;\n }\n\n // Type assertion needed: submission.action accepts the form tree but its signature\n // is defined broadly in FormConfig. The actual runtime type is FieldTree<TModel>.\n const wrappedAction = wrapSubmissionAction<TModel>(submissionConfig.action as (formTree: FieldTree<TModel>) => unknown);\n\n // Use Angular Signal Forms' native submit() function\n // This automatically:\n // - Sets form.submitting() to true during execution\n // - Applies server errors to form fields on completion\n // - Sets form.submitting() to false when done\n // catchError keeps the exhaustMap stream alive after action failure —\n // without it, an unhandled error would terminate all future submissions.\n // `defer` so the form tree is read when the inner observable is subscribed,\n // keeping the post-submit error read on the same tree the action ran against.\n return defer(() => {\n const formTree = formSignal();\n\n return from(submit(formTree, wrappedAction)).pipe(\n // `submit()` resolves the same way whether the action succeeded or came\n // back with server errors — it applies them to the form rather than\n // rejecting — so the form's own errors are what separate the two.\n tap(() => {\n // Server errors land on the fields they belong to, so the whole-tree\n // summary is what distinguishes a rejected submission from a clean one.\n reply?.settle(formTree().errorSummary().length ? { status: 'server-errors' } : { status: 'success' });\n }),\n catchError((error: unknown) => {\n logger.error('Submission action failed:', error);\n reply?.settle({ status: 'action-failed', error });\n return EMPTY;\n }),\n );\n });\n }),\n );\n}\n","import { inject, Type } from '@angular/core';\nimport {\n DEFAULT_WRAPPERS,\n FieldDef,\n FormConfig,\n isPageField,\n WRAPPER_AUTO_ASSOCIATIONS,\n WRAPPER_COMPONENT_LOAD_CACHE,\n WRAPPER_REGISTRY,\n} from '@ng-forge/dynamic-forms/internal';\nimport { WRAPPER_COMPONENT_CACHE } from '@ng-forge/dynamic-forms/internal';\nimport { injectFieldRegistry } from '../inject-field-registry/inject-field-registry';\nimport { loadWrapperComponent } from '../wrapper-chain/wrapper-chain';\nimport { resolveWrappers } from '../resolve-wrappers/resolve-wrappers';\nimport { normalizeSimplifiedArrays } from '../array-field/normalize-simplified-arrays';\nimport { getNormalizedArrayMetadata } from '../array-field/normalized-array-metadata';\n\n/**\n * Collects every field type named anywhere in a config, including inside\n * containers. Containers hold their children under `fields`, and array item\n * templates under `fields` too, so one recursive walk covers both.\n */\nfunction collectFieldDefs(fields: readonly FieldDef<unknown>[] | undefined, out: FieldDef<unknown>[] = []): FieldDef<unknown>[] {\n for (const field of fields ?? []) {\n out.push(field);\n const children = (field as { fields?: unknown }).fields;\n if (Array.isArray(children)) {\n // Array item templates nest one level deeper: `fields: [[...template]]`.\n for (const child of children) {\n if (Array.isArray(child)) collectFieldDefs(child as FieldDef<unknown>[], out);\n else collectFieldDefs([child as FieldDef<unknown>], out);\n }\n }\n\n const metadata = getNormalizedArrayMetadata(field);\n const template = metadata?.template;\n if (Array.isArray(template)) collectFieldDefs(template as readonly FieldDef<unknown>[], out);\n else if (template) collectFieldDefs([template as FieldDef<unknown>], out);\n if (metadata?.autoRemoveButton) collectFieldDefs([metadata.autoRemoveButton], out);\n }\n return out;\n}\n\nexport interface FormComponentPreloader {\n /** Preload a complete non-paged form config. Paged configs are orchestrator-owned. */\n readonly preloadConfig: (config: FormConfig) => void;\n /** Preload the exact field subtree selected for rendering. */\n readonly preloadFields: (fields: readonly FieldDef<unknown>[]) => void;\n}\n\n/**\n * Warms the field- and wrapper-component caches for everything a config will\n * actually render, in parallel, as soon as the config is known.\n *\n * Without this the two sets load in sequence: a field's wrapper chain is\n * resolved inside `DfFieldOutlet`, which does not exist until that field's own\n * component has loaded. Measured on the 240-field fixture, that dependent\n * waterfall put the last wrapper chunk 30ms before first paint on localhost,\n * where a round trip costs ~1ms — on a real network each wave costs a full RTT.\n *\n * Only the current render scope is fetched: a flat form, or the active page\n * window selected by PageOrchestrator. Both loaders dedupe (field loads through\n * `COMPONENT_LOAD_CACHE`, wrapper loads through the module system's own\n * `import()` dedup), so racing the normal resolution path is safe.\n *\n * Warming the caches also lets the sync fast paths take over: `resolveFieldSync`\n * and the wrapper chain controller's \"every wrapper cached\" branch both skip\n * their async hop entirely once the cache is populated.\n *\n * Failures are swallowed on purpose. This is a head start, not a load-bearing\n * step — every one of these types is loaded again through the normal path,\n * which owns the real error reporting.\n */\nexport function injectFormComponentPreloader(): FormComponentPreloader {\n const fieldRegistry = injectFieldRegistry();\n const wrapperRegistry = inject(WRAPPER_REGISTRY);\n const wrapperCache = inject(WRAPPER_COMPONENT_CACHE);\n const wrapperLoadCache = inject(WRAPPER_COMPONENT_LOAD_CACHE);\n const autoAssociations = inject(WRAPPER_AUTO_ASSOCIATIONS);\n const defaultWrappers = inject(DEFAULT_WRAPPERS, { optional: true });\n const preloadedConfigs = new WeakSet<FormConfig>();\n const preloadedFieldRoots = new WeakSet<FieldDef<unknown>>();\n\n const preloadFields = (fields: readonly FieldDef<unknown>[]): void => {\n const unseenFields = fields.filter((field) => {\n if (preloadedFieldRoots.has(field)) return false;\n preloadedFieldRoots.add(field);\n return true;\n });\n if (unseenFields.length === 0) return;\n\n const normalizedFields = normalizeSimplifiedArrays(unseenFields);\n const defs = collectFieldDefs(normalizedFields);\n if (defs.length === 0) return;\n\n const fieldTypes = new Set<string>();\n const wrapperTypes = new Set<string>();\n\n for (const def of defs) {\n if (def.type) fieldTypes.add(def.type);\n // Pure function of the field def plus registry state, all of it known\n // here — which is what makes the wrapper set computable before any field\n // has rendered.\n for (const wrapper of resolveWrappers(def, defaultWrappers?.(), autoAssociations, wrapperRegistry)) {\n wrapperTypes.add(wrapper.type);\n }\n }\n\n const started: Promise<unknown>[] = [];\n for (const type of fieldTypes) {\n if (fieldRegistry.getLoadedComponent(type)) continue;\n started.push(Promise.resolve(fieldRegistry.loadTypeComponent(type)).catch(() => undefined));\n }\n for (const type of wrapperTypes) {\n if (wrapperCache.has(type)) continue;\n started.push(\n loadWrapperComponent(type, wrapperRegistry, wrapperCache, wrapperLoadCache).catch((): Type<unknown> | undefined => undefined),\n );\n }\n // Deliberately not awaited: rendering must not be gated on the head start.\n void Promise.allSettled(started);\n };\n\n return {\n preloadConfig: (config: FormConfig): void => {\n if (preloadedConfigs.has(config)) return;\n preloadedConfigs.add(config);\n\n const fields = config.fields as readonly FieldDef<unknown>[];\n // PageOrchestrator owns paged rendering and calls preloadFields for the\n // active page plus its configured neighbours. Walking the raw config here\n // would eagerly fetch chunks for every distant page.\n if (fields.length > 0 && fields.every(isPageField)) return;\n preloadFields(fields);\n },\n preloadFields,\n };\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event emitted when the active page of a paged form changes. */\nexport class PageChangeEvent implements FormEvent {\n readonly type = 'page-change' as const;\n\n constructor(\n /** The current page index (0-based) */\n public readonly currentPageIndex: number,\n /** Total number of pages */\n public readonly totalPages: number,\n /** Previous page index (0-based), undefined if first navigation */\n public readonly previousPageIndex?: number,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\nimport { PagerState } from '../../core/page-orchestrator/page-orchestrator.interfaces';\n\n/**\n * Event emitted whenever the pager state of a paged form changes.\n *\n * Unlike `PageChangeEvent`, which fires only when the active page changed, this\n * fires on any change to the derived state — including when `isFirstPage` /\n * `isLastPage` flip because a page's `hidden` logic toggled and the set of\n * visible pages shifted, with the active page never moving.\n */\nexport class PagerStateEvent implements FormEvent {\n readonly type = 'pager-state' as const;\n\n constructor(public state: PagerState) {}\n}\n","import { InjectionToken } from '@angular/core';\n\n/**\n * Global default for how many pages on each side of the current page a paged\n * form mounts during idle time (the \"preload window\").\n *\n * A window of `1` (the default) renders the current page directly and mounts its\n * immediate neighbours (±1) on idle, so sequential navigation is flicker-free while\n * distant pages stay unmounted. Larger windows pre-warm more pages (useful for\n * jump navigation) at the cost of more initial DOM + change detection; `0`\n * mounts only the current page.\n *\n * @internal\n */\nexport const PAGE_PRELOAD_WINDOW = new InjectionToken<number>('PAGE_PRELOAD_WINDOW', {\n providedIn: 'root',\n factory: () => 1,\n});\n","import { isGenericContainerField, isRowField } from '@ng-forge/dynamic-forms/internal';\nimport type { FieldDef } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Form-node keys owned by a page's fields.\n *\n * Layout containers (`row`, `container`) are flattened by `mapFieldToForm`, so no form node\n * exists under their own key — traverse their children instead. `group` and `array` own a node\n * whose `valid()` already aggregates descendants, so their key is used as-is.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any field shape for recursive traversal\nexport function collectLeafFieldKeys(fields: readonly FieldDef<any>[]): string[] {\n const keys: string[] = [];\n\n for (const field of fields) {\n if (isRowField(field) || isGenericContainerField(field)) {\n keys.push(...collectLeafFieldKeys(field.fields as readonly FieldDef<unknown>[]));\n } else if (field.key) {\n keys.push(field.key);\n }\n }\n\n return keys;\n}\n","import { ChangeDetectionStrategy, Component, computed, inject, input, linkedSignal, untracked } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { PageNavigationOptions } from '../../events/constants/go-to-page.event';\nimport { NextPageEvent } from '../../events/constants/next-page.event';\nimport { PageChangeEvent } from '../../events/constants/page-change.event';\nimport { PreviousPageEvent } from '../../events/constants/previous-page.event';\nimport { NavigationResult, PagerState } from './page-orchestrator.interfaces';\nimport { PageField } from '@ng-forge/dynamic-forms/internal';\nimport { ContainerLogicConfig } from '@ng-forge/dynamic-forms/internal';\nimport { FieldSignalContext } from '@ng-forge/dynamic-forms/internal';\nimport PageFieldComponent from '../../fields/page/page-field.component';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { PagerStateEvent } from '../../events/constants/pager-state.event';\nimport { FieldTree } from '@angular/forms/signals';\nimport { FIELD_SIGNAL_CONTEXT, FORM_OPTIONS } from '@ng-forge/dynamic-forms/internal';\nimport { ConditionalExpression } from '@ng-forge/dynamic-forms/internal';\nimport { evaluateCondition } from '@ng-forge/dynamic-forms/internal';\nimport { FunctionRegistryService } from '@ng-forge/dynamic-forms/internal';\nimport { FieldContextRegistryService } from '@ng-forge/dynamic-forms/internal';\nimport { PAGE_PRELOAD_WINDOW } from '../../providers/features/page-preload/page-preload.token';\nimport { clampWindowSize } from '../../providers/features/clamp-window';\nimport { collectLeafFieldKeys } from '../../utils/page-utils/collect-leaf-field-keys';\nimport { FormStateManager } from '../../state/form-state-manager';\nimport { injectFormComponentPreloader } from '../../utils/preload-form-components/preload-form-components';\n\n/**\n * PageOrchestrator manages page navigation and visibility for paged forms.\n * It acts as an intermediary between the DynamicForm component and PageField components,\n * handling page state management and navigation events without interfering with form data.\n */\n@Component({\n selector: 'div[page-orchestrator]',\n imports: [PageFieldComponent],\n template: `\n @for (page of pageRenderStates(); track page.field.key) {\n <!--\n Skip pages hidden by 'hidden' logic conditions entirely. FormStateManager\n derives schema/value/validators from config (not from mounted components),\n so unmounting a hidden page has no effect on form state — only on render +\n CD cost. This is the page-level equivalent of the existing field-level\n \\`@if (!field.hidden())\\` gate in page-field.component.ts.\n -->\n @if (!page.hidden) {\n @if (page.active || page.preload) {\n @defer (when page.active; on idle) {\n <section page-field [field]=\"page.field\" [key]=\"page.field.key\" [pageIndex]=\"page.index\" [isVisible]=\"page.active\"></section>\n } @placeholder {\n <div class=\"df-page-placeholder\" [attr.data-page-index]=\"page.index\" [attr.data-page-key]=\"page.field.key\"></div>\n }\n } @else {\n <!--\n Pages outside the preload window remain lightweight placeholders.\n Form state derives from config, so leaving their components unmounted\n does not affect validity, derivations, or navigation. The active page\n renders directly; configured neighbours preload declaratively on idle.\n -->\n <div class=\"df-page-placeholder\" [attr.data-page-index]=\"page.index\" [attr.data-page-key]=\"page.field.key\"></div>\n }\n }\n }\n `,\n styleUrl: './page-orchestrator.component.scss',\n host: {\n class: 'df-page-orchestrator',\n '[attr.data-current-page]': 'state().currentPageIndex',\n '[attr.data-total-pages]': 'state().totalPages',\n },\n providers: [\n {\n provide: FIELD_SIGNAL_CONTEXT,\n useFactory: (orchestrator: PageOrchestratorComponent) => orchestrator.extendedFieldSignalContext(),\n deps: [PageOrchestratorComponent],\n },\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class PageOrchestratorComponent {\n private readonly eventBus = inject(EventBus);\n private readonly fieldContextRegistry = inject(FieldContextRegistryService);\n private readonly functionRegistry = inject(FunctionRegistryService);\n private readonly formOptions = inject(FORM_OPTIONS, { optional: true });\n private readonly globalPreloadWindow = inject(PAGE_PRELOAD_WINDOW);\n private readonly stateManager = inject(FormStateManager, { optional: true });\n\n /** Pending programmatic page request, owned by FormStateManager. */\n private readonly pendingPageRequest = computed(() => this.stateManager?.pendingPageRequest() ?? null);\n\n /** Whether validation belongs to the page definitions currently being rendered. */\n private readonly schemaCurrent = computed(() => this.stateManager?.isSchemaCurrent() ?? true);\n\n /** Stable ownership scope; page arrays can be recreated during one config transition. */\n private readonly configScope = computed(() => this.stateManager?.activeConfig());\n\n /** Array of page field definitions to render */\n pageFields = input.required<PageField[]>();\n\n /**\n * Root form instance from parent DynamicForm.\n * Uses FieldTree<unknown> to accept any form type.\n */\n form = input.required<FieldTree<unknown>>();\n\n /** Field signal context for child fields */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- FieldSignalContext is contravariant in TModel, using any allows accepting any form type\n fieldSignalContext = input.required<FieldSignalContext<any>>();\n\n /**\n * Computed signal that tracks which pages are hidden.\n * Returns an array of booleans where true means the page is hidden.\n * This signal is reactive and will re-evaluate when form values change.\n */\n readonly pageHiddenStates = computed(() => {\n const pages = this.pageFields();\n\n return pages.map((page) => this.evaluatePageHidden(page));\n });\n\n /**\n * Computed signal that returns indices of visible (non-hidden) pages.\n * This is used for navigation to skip hidden pages.\n */\n readonly visiblePageIndices = computed(() => {\n const hiddenStates = this.pageHiddenStates();\n return hiddenStates\n .map((hidden, index) => ({ index, hidden }))\n .filter((item) => !item.hidden)\n .map((item) => item.index);\n });\n\n /** Current page ownership, reset atomically when the active config changes. */\n private readonly activePageOwnership = linkedSignal<\n object | undefined,\n {\n config: object | undefined;\n initialized: boolean;\n index: number;\n }\n >({\n source: this.configScope,\n computation: (config, previous) => {\n const totalPages = this.pageFields().length;\n\n if (totalPages === 0) return { config, initialized: true, index: 0 };\n\n // Untracked: re-land on a config swap, but never on a later validity or visibility change.\n return untracked(() => {\n // A newly mounted pager may restore ownership for the same config. An existing pager must\n // ignore ownership when the config changes because its outgoing effect can still publish\n // the previous index during that transition.\n const owned = this.stateManager?.activePageState();\n const mayRestore = previous === undefined || previous.source === config;\n if (\n mayRestore &&\n owned !== undefined &&\n owned.config === config &&\n owned.initialized &&\n owned.index >= 0 &&\n owned.index < totalPages\n ) {\n return { config, initialized: true, index: owned.index };\n }\n\n if (this.initialPage().validate && !this.schemaCurrent()) {\n return { config, initialized: false, index: 0 };\n }\n\n return { config, initialized: true, index: this.resolveInitialLanding() };\n });\n },\n });\n\n /** Actual page index, excluding hidden pages from its numbering. */\n private readonly currentPageIndex = computed(() => this.activePageOwnership().index);\n\n private setCurrentPageIndex(index: number): void {\n this.activePageOwnership.update((ownership) => ({ ...ownership, initialized: true, index }));\n }\n\n /** Where `initialPage` actually lands: hidden targets resolve forward, gated ones stop on the first invalid page. */\n private resolveInitialLanding(): number {\n const { index, validate } = this.initialPage();\n const visible = this.visiblePageIndices();\n if (index === 0 || visible.length === 0) return 0;\n\n const target = visible.includes(index) ? index : this.findNearestVisiblePage(index, visible);\n if (target <= 0) return Math.max(target, 0);\n if (!validate) return target;\n\n const firstInvalid = visible.filter((i) => i < target).find((i) => !this.isPageValid(i));\n return firstInvalid ?? target;\n }\n\n /** Resolved `FormOptions.initialPage`: out-of-range clamps to the last page, invalid values fall back to 0. */\n private readonly initialPage = computed<{ index: number; validate: boolean }>(() => {\n const raw = this.formOptions?.()?.initialPage;\n const totalPages = this.pageFields().length;\n const requested = typeof raw === 'number' ? raw : raw?.index;\n const validate = typeof raw === 'number' ? false : (raw?.validate ?? false);\n\n if (typeof requested !== 'number' || !Number.isFinite(requested) || requested < 0 || totalPages === 0) {\n return { index: 0, validate: false };\n }\n\n return { index: Math.min(Math.trunc(requested), totalPages - 1), validate };\n });\n\n /** Computed state for the orchestrator */\n readonly state = computed<PagerState>(() => {\n const currentIndex = this.currentPageIndex();\n const totalPages = this.pageFields().length;\n const visibleIndices = this.visiblePageIndices();\n\n // Find where the current index is in the visible pages list\n const currentVisiblePosition = visibleIndices.indexOf(currentIndex);\n const isFirstVisiblePage = currentVisiblePosition === 0 || currentVisiblePosition === -1;\n const isLastVisiblePage = currentVisiblePosition >= visibleIndices.length - 1;\n\n return {\n currentPageIndex: currentIndex,\n totalPages,\n isFirstPage: isFirstVisiblePage,\n isLastPage: isLastVisiblePage,\n };\n });\n\n /**\n * Signal indicating whether all fields on the current page are valid.\n *\n * @returns `true` if current page is valid, `false` otherwise\n */\n // Reports invalid while the schema is stale: the incoming page's fields are mounted but not\n // yet validated, so trusting them would let a second click skip a page.\n readonly currentPageValid = computed(() => (this.stateManager?.isSchemaCurrent() ?? true) && this.isPageValid(this.currentPageIndex()));\n\n /**\n * Whether all fields on the given page are currently valid.\n *\n * Form state derives from config, not from mounted components, so any page can\n * be checked without having been visited.\n *\n * @param pageIndex The page index (0-based)\n * @returns `true` if the page is valid or the index is out of range\n */\n private isPageValid(pageIndex: number): boolean {\n const pages = this.pageFields();\n const form = this.form();\n\n if (pageIndex < 0 || pageIndex >= pages.length) {\n return true;\n }\n\n // Collect all leaf field keys, recursively traversing group/row containers\n const leafKeys = collectLeafFieldKeys(pages[pageIndex].fields || []);\n\n // Check validity of each leaf field on the page\n // Fields are stored at root level in the form (pages don't add nesting)\n for (const fieldKey of leafKeys) {\n const field = (form as Record<string, unknown>)[fieldKey];\n if (field && typeof field === 'function') {\n const fieldState = (field as () => { valid: () => boolean })();\n if (fieldState && typeof fieldState.valid === 'function' && !fieldState.valid()) {\n return false;\n }\n }\n }\n\n return true;\n }\n\n /** Extended field signal context that includes currentPageValid. */\n readonly extendedFieldSignalContext = computed(() => ({\n ...this.fieldSignalContext(),\n currentPageValid: this.currentPageValid,\n }));\n\n /**\n * Effective preload window (pages preloaded on idle on each side of the current page).\n * Per-form `FormOptions.pagePreloadWindow` wins over the global\n * `withPagePreload(n)` default; both fall back to `1`. Clamped to `>= 0`.\n */\n readonly preloadWindow = computed(() => {\n const perForm = this.formOptions?.()?.pagePreloadWindow;\n // The global is already normalized; a non-finite per-form value falls back to it.\n return clampWindowSize(perForm, this.globalPreloadWindow);\n });\n\n /** Declarative render mode for every configured page. */\n readonly pageRenderStates = computed(() => {\n const activeIndex = this.currentPageIndex();\n const hiddenStates = this.pageHiddenStates();\n const preloadWindow = this.preloadWindow();\n\n return this.pageFields().map((field, index) => ({\n field,\n index,\n hidden: hiddenStates[index],\n active: index === activeIndex,\n preload: index !== activeIndex && Math.abs(index - activeIndex) <= preloadWindow,\n }));\n });\n\n constructor() {\n // Setup event listeners for navigation\n this.setupEventListeners();\n\n // Warm only the pages that can currently render. When navigation moves the\n // window this effect preloads the newly selected subtree before its deferred\n // page component discovers those chunks field by field.\n const preloader = injectFormComponentPreloader();\n explicitEffect([this.pageRenderStates], ([states]) => {\n preloader.preloadFields(states.filter((page) => !page.hidden && (page.active || page.preload)).map((page) => page.field));\n });\n\n // A config swap exposes its page definitions before their schema is current. Defer a gated\n // landing until those fields can be validated, then resolve it exactly once for this page set.\n explicitEffect([this.schemaCurrent, this.pageFields], ([schemaCurrent]) => {\n const ownership = this.activePageOwnership();\n if (!schemaCurrent || ownership.initialized) return;\n this.activePageOwnership.set({ ...ownership, initialized: true, index: this.resolveInitialLanding() });\n });\n\n // B15: Auto-navigate away when current page becomes hidden\n explicitEffect([this.state, this.visiblePageIndices], ([state, visibleIndices]) => {\n const currentVisiblePosition = visibleIndices.indexOf(state.currentPageIndex);\n if (currentVisiblePosition === -1 && visibleIndices.length > 0) {\n // Current page is hidden — navigate to the nearest visible page\n const nearest = this.findNearestVisiblePage(state.currentPageIndex, visibleIndices);\n if (nearest !== -1) {\n this.executePageChange(nearest);\n }\n }\n });\n }\n\n /**\n * Navigate to the next visible page, skipping hidden pages.\n *\n * @returns Navigation result\n */\n navigateToNextPage(): NavigationResult {\n // Guard: do not advance if current page has invalid fields.\n // Respects disableWhenPageInvalid option (defaults to true).\n const disableWhenPageInvalid = this.formOptions?.()?.nextButton?.disableWhenPageInvalid ?? true;\n if (disableWhenPageInvalid && !this.currentPageValid()) {\n return {\n success: false,\n newPageIndex: this.state().currentPageIndex,\n error: 'Current page has invalid fields',\n };\n }\n\n const currentState = this.state();\n const visibleIndices = this.visiblePageIndices();\n\n if (currentState.isLastPage) {\n return {\n success: false,\n newPageIndex: currentState.currentPageIndex,\n error: 'Already on the last visible page',\n };\n }\n\n // Find the next visible page after the current index\n const currentVisiblePosition = visibleIndices.indexOf(currentState.currentPageIndex);\n if (currentVisiblePosition === -1 || currentVisiblePosition >= visibleIndices.length - 1) {\n return {\n success: false,\n newPageIndex: currentState.currentPageIndex,\n error: 'No next visible page available',\n };\n }\n\n const nextVisiblePageIndex = visibleIndices[currentVisiblePosition + 1];\n return this.executePageChange(nextVisiblePageIndex);\n }\n\n /**\n * Navigate to the previous visible page, skipping hidden pages.\n *\n * @returns Navigation result\n */\n navigateToPreviousPage(): NavigationResult {\n const currentState = this.state();\n const visibleIndices = this.visiblePageIndices();\n\n if (currentState.isFirstPage) {\n return {\n success: false,\n newPageIndex: currentState.currentPageIndex,\n error: 'Already on the first visible page',\n };\n }\n\n // Find the previous visible page before the current index\n const currentVisiblePosition = visibleIndices.indexOf(currentState.currentPageIndex);\n if (currentVisiblePosition <= 0) {\n return {\n success: false,\n newPageIndex: currentState.currentPageIndex,\n error: 'No previous visible page available',\n };\n }\n\n const prevVisiblePageIndex = visibleIndices[currentVisiblePosition - 1];\n return this.executePageChange(prevVisiblePageIndex);\n }\n\n /**\n * Navigate to an arbitrary page, applying the jump validation semantics.\n *\n * Backward jumps are unconditional, matching `previous` having no validity gate.\n * Forward jumps validate every visible page crossed by the jump — from the\n * current page up to, but excluding, the target — because conditions may have\n * changed since those pages were last visited. On failure, navigation lands on\n * the first invalid page rather than staying put, so the user ends up where\n * work is required. Hidden pages are never validated.\n *\n * Respects `nextButton.disableWhenPageInvalid`, the same option that gates\n * next-page navigation.\n *\n * @param pageIndex The target page index (0-based)\n * @returns Navigation result\n */\n navigateToPage(pageIndex: number, options?: PageNavigationOptions): NavigationResult {\n const currentIndex = this.state().currentPageIndex;\n const visibleIndices = this.visiblePageIndices();\n\n // Backward jumps and no-ops need no gate. Out-of-bounds and hidden targets\n // fall through too — executePageChange reports those without navigating.\n if (pageIndex <= currentIndex || !visibleIndices.includes(pageIndex)) {\n return this.executePageChange(pageIndex);\n }\n\n // Per-dispatch opt-out, for restoring a saved session onto its exact page.\n if (options?.validate === false) {\n return this.executePageChange(pageIndex);\n }\n\n const disableWhenPageInvalid = this.formOptions?.()?.nextButton?.disableWhenPageInvalid ?? true;\n if (!disableWhenPageInvalid) {\n return this.executePageChange(pageIndex);\n }\n\n const crossedPages = visibleIndices.filter((index) => index >= currentIndex && index < pageIndex);\n const firstInvalidPage = crossedPages.find((index) => !this.isPageValid(index));\n\n if (firstInvalidPage === undefined) {\n return this.executePageChange(pageIndex);\n }\n\n // Partial jump: land on the first invalid page and report the failure.\n this.executePageChange(firstInvalidPage);\n\n return {\n success: false,\n newPageIndex: firstInvalidPage,\n error: `Cannot navigate to page ${pageIndex}: page ${firstInvalidPage} has invalid fields`,\n };\n }\n\n /**\n * Performs the actual page change, with no validity gating.\n *\n * Validates bounds and target visibility, updates the active index, and emits\n * `PageChangeEvent`. All gated entry points funnel through here.\n *\n * @param pageIndex The target page index (0-based)\n * @returns Navigation result\n */\n private executePageChange(pageIndex: number): NavigationResult {\n const currentState = this.state();\n const totalPages = currentState.totalPages;\n\n // Validate page index bounds\n if (pageIndex < 0 || pageIndex >= totalPages) {\n return {\n success: false,\n newPageIndex: currentState.currentPageIndex,\n error: `Invalid page index: ${pageIndex}. Valid range is 0 to ${totalPages - 1}`,\n };\n }\n\n // Validate target page is visible\n const visibleIndices = this.visiblePageIndices();\n if (!visibleIndices.includes(pageIndex)) {\n return {\n success: false,\n newPageIndex: currentState.currentPageIndex,\n error: `Cannot navigate to hidden page at index ${pageIndex}. Visible pages: [${visibleIndices.join(', ')}]`,\n };\n }\n\n // Check if already on target page\n if (pageIndex === currentState.currentPageIndex) {\n return {\n success: true,\n newPageIndex: pageIndex,\n };\n }\n\n // Perform navigation\n const previousIndex = currentState.currentPageIndex;\n this.setCurrentPageIndex(pageIndex);\n\n // Emit page change event\n this.eventBus.dispatch(PageChangeEvent, pageIndex, totalPages, previousIndex);\n\n return {\n success: true,\n newPageIndex: pageIndex,\n };\n }\n\n /**\n * Finds the nearest visible page index to the given index.\n * Prefers the forward (higher index) page when equidistant.\n */\n private findNearestVisiblePage(currentIndex: number, visibleIndices: number[]): number {\n let nearest = -1;\n let minDistance = Infinity;\n\n for (const idx of visibleIndices) {\n const distance = Math.abs(idx - currentIndex);\n // Prefer forward (higher index) when tied\n if (distance < minDistance || (distance === minDistance && idx > nearest)) {\n minDistance = distance;\n nearest = idx;\n }\n }\n\n return nearest;\n }\n\n /** Set up event listeners for navigation events */\n private setupEventListeners(): void {\n // Listen for next page events\n this.eventBus\n .on<NextPageEvent>('next-page')\n .pipe(takeUntilDestroyed())\n .subscribe(() => {\n this.navigateToNextPage();\n });\n\n // Listen for previous page events\n this.eventBus\n .on<PreviousPageEvent>('previous-page')\n .pipe(takeUntilDestroyed())\n .subscribe(() => {\n this.navigateToPreviousPage();\n });\n\n // Programmatic jumps arrive as pending intent on FormStateManager rather than as a live\n // subscription here: this component mounts behind the render gate, so a request made on\n // `initialized` would otherwise reach the bus before this listener existed. Draining it\n // here keeps visibility and validity resolution in the one place that knows about them.\n explicitEffect([this.pendingPageRequest], ([request]) => {\n if (!request) return;\n this.stateManager?.pendingPageRequest.set(null);\n this.navigateToPage(request.index, request.options);\n });\n\n explicitEffect([this.state], ([state]) => this.eventBus.dispatch(PagerStateEvent, state));\n\n // Publish upward so navigation survives this pager being temporarily unmounted.\n explicitEffect([this.activePageOwnership], ([ownership]) => this.stateManager?.activePageState.set(ownership));\n }\n\n /**\n * Evaluates whether a page should be hidden based on its logic configuration.\n * A page is hidden if ANY of its hidden logic conditions evaluate to true.\n *\n * @param page The page field to evaluate\n * @returns true if the page should be hidden, false otherwise\n */\n private evaluatePageHidden(page: PageField): boolean {\n // If no logic defined, page is visible\n if (!page.logic || page.logic.length === 0) {\n return false;\n }\n\n // Filter to only hidden logic (pages only support hidden type)\n const hiddenLogic = page.logic.filter((l): l is ContainerLogicConfig => l.type === 'hidden');\n\n // If no hidden logic, page is visible\n if (hiddenLogic.length === 0) {\n return false;\n }\n\n // Check each hidden logic - if ANY condition is true, the page is hidden\n for (const logic of hiddenLogic) {\n // Handle static boolean conditions (fast path)\n if (typeof logic.condition === 'boolean') {\n if (logic.condition) {\n return true;\n }\n continue;\n }\n\n // Evaluate conditional expression using centralized context creation\n const condition = logic.condition as ConditionalExpression;\n const context = this.fieldContextRegistry.createDisplayOnlyContext(page.key || '', this.functionRegistry.getCustomFunctions());\n\n if (evaluateCondition(condition, context)) {\n return true;\n }\n }\n\n return false;\n }\n}\n","import { FieldDef, FieldWithValidation, isDerivationLogicConfig } from '@ng-forge/dynamic-forms/internal';\nimport { someField } from './field-traversal';\n\n/**\n * Cheap, eager predicate: does any field in the config declare a value or\n * property derivation — the shorthand `derivation` string, or a `logic[]` entry\n * of `type: 'derivation'` (the latter covers both value derivations and\n * `targetProperty` property derivations)?\n *\n * Deliberately reuses the collector's child resolution ({@link someField} shares\n * it with `traverseFieldsWithContext`) and detection predicate\n * ({@link isDerivationLogicConfig}) so this gate can never diverge from what\n * `createDerivationOrchestrator` would actually wire — including derivations\n * nested in containers and array-item templates.\n *\n * Stays lightweight (no dependency on the heavy derivation-orchestrator module)\n * so it can run eagerly to decide whether the orchestrator needs to be\n * lazy-loaded at all. Forms without derivations never pull the engine.\n *\n * @internal\n */\nexport function configHasDerivations(fields: FieldDef<unknown>[]): boolean {\n return someField(fields, (field) => {\n // Match the collector's keyless guard (derivation-collector.ts): a keyless\n // field never produces a derivation entry, so it must not trip the gate.\n // `someField` still recurses into its children.\n if (!field.key) return false;\n const validationField = field as FieldDef<unknown> & FieldWithValidation;\n return !!validationField.derivation || !!validationField.logic?.some(isDerivationLogicConfig);\n });\n}\n","import { computed, inject, Injector, InjectionToken, PendingTasks, runInInjectionContext, signal, Signal } from '@angular/core';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { DynamicFormLogger, FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { FormStateManager } from '../../state/form-state-manager';\nimport { configHasDerivations } from './config-has-derivations';\n\n/**\n * Form-scoped signal that is `false` only while a derivation-bearing config is\n * still waiting for the lazily-loaded derivation engine to wire up. `DynamicForm`\n * ANDs this into `shouldRender`, so a form that uses derivations does not render\n * its fields until the orchestrator has loaded and registered its\n * value/property overrides — fields render already-derived, with no flash.\n *\n * For configs without derivations the gate is always `true` (no waiting, no\n * lazy load), and the heavy orchestrator module is never imported.\n *\n * @internal\n */\nexport const DERIVATION_RENDER_GATE = new InjectionToken<Signal<boolean>>('DERIVATION_RENDER_GATE');\n\n/**\n * Factory for {@link DERIVATION_RENDER_GATE}. Watches the form setup and, the\n * first time it declares a derivation, dynamically imports the derivation engine\n * (the chunk boundary) and wires the orchestrator in the form's injection\n * context. Flips the gate open once that bootstrap has run.\n *\n * The lazy import runs inside an Angular `PendingTasks` task so server-side\n * rendering waits for the engine to wire before serializing — derivation-bearing\n * forms render server-side rather than as empty markup. If the chunk fails to\n * load the gate opens anyway (the form renders without derivations rather than\n * locking shut forever).\n *\n * Must be created within the form's injection context (it captures the form\n * `Injector` for the deferred `runInInjectionContext`).\n *\n * @internal\n */\nexport function createDerivationRenderGate(): Signal<boolean> {\n const stateManager = inject(FormStateManager);\n const injector = inject(Injector);\n const pendingTasks = inject(PendingTasks);\n const logger = inject(DynamicFormLogger);\n\n const hasDerivations = computed(() => {\n const setup = stateManager.formSetup();\n return !!setup && configHasDerivations(setup.schemaFields as FieldDef<unknown>[]);\n });\n\n // Single source of truth for the lazy engine's lifecycle. `idle` until a config\n // first needs it; `loading` once the import is in flight (guards against a\n // second orchestrator if derivations swap out and back in); `wired` once the\n // orchestrator is constructed; `failed` if the chunk could not be loaded.\n const engine = signal<'idle' | 'loading' | 'wired' | 'failed'>('idle');\n\n explicitEffect([hasDerivations], ([has]) => {\n if (!has || engine() !== 'idle') return;\n engine.set('loading');\n // Tracked as a pending task so SSR awaits the engine before serializing.\n pendingTasks.run(() =>\n import('./bootstrap-derivation-orchestrator')\n .then(({ bootstrapDerivationOrchestrator }) => {\n runInInjectionContext(injector, () => bootstrapDerivationOrchestrator());\n engine.set('wired');\n })\n .catch((error: unknown) => {\n // A failed chunk load must not lock the form shut — render it degraded\n // (derivations won't apply) and surface the failure.\n engine.set('failed');\n logger.error('Failed to load the derivation engine; derivations will not apply.', error);\n }),\n );\n });\n\n // Open when there are no derivations, once the engine is wired, or if it failed\n // to load (degraded render beats a permanently closed gate).\n return computed(() => {\n if (!hasDerivations()) return true;\n const state = engine();\n return state === 'wired' || state === 'failed';\n });\n}\n","import { InjectionToken } from '@angular/core';\n\n/**\n * Whether WebMCP tool registration is enabled at all. Absent (`false`) unless\n * `withExperimentalWebMcp()` is provided, which is what keeps the registrar chunk out of\n * builds that never opt in.\n *\n * @internal\n */\nexport const WEB_MCP_ENABLED = new InjectionToken<boolean>('WEB_MCP_ENABLED', {\n providedIn: 'root',\n factory: () => false,\n});\n","import { computed, DestroyRef, inject, InjectionToken, Injector, PLATFORM_ID, runInInjectionContext, signal, Signal } from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { DynamicFormLogger, WebMcpToolOptions } from '@ng-forge/dynamic-forms/internal';\nimport { FormStateManager } from '../../state/form-state-manager';\nimport { WEB_MCP_ENABLED } from '../../providers/features/web-mcp/web-mcp.token';\n\n/**\n * What the WebMCP layer is currently doing for this form. Reported by\n * `DynamicForm.webMcpStatus()`; `'active'` is the only state in which an agent\n * can see the form.\n *\n * @experimental\n */\nexport type WebMcpStatus =\n /** `withExperimentalWebMcp()` is not provided, or this is the server. */\n | 'disabled'\n /** Enabled, but the current config does not declare `options.webMcp`. */\n | 'idle'\n /** Loading the registrar or awaiting `registerTool()`. */\n | 'registering'\n /** Tools are registered against the browser's model context. */\n | 'active'\n /** The browser exposes no model context, so there is nothing to register against. */\n | 'unsupported'\n /** Registration was attempted and rejected. See the console for the reason. */\n | 'failed';\n\n/**\n * Form-scoped hook that keeps this form's WebMCP tools in step with its config.\n *\n * Deliberately NOT a render gate. Unlike the derivation engine, nothing about a\n * form's rendered output depends on whether an agent can see it, so this must\n * never hold `shouldRender` closed and must never register a `PendingTasks` task\n * (which would make SSR wait on a browser-only concern).\n *\n * @internal\n */\nexport const WEB_MCP_GATE = new InjectionToken<Signal<WebMcpStatus>>('WEB_MCP_GATE');\n\n/**\n * Factory for {@link WEB_MCP_GATE}.\n *\n * Registration follows the *effective* form options, not the first config that\n * happened to declare them. A registration that only ever ran once outlives what\n * it describes: swap the config and `fill_first` keeps writing into a form whose\n * fields it no longer matches; turn `allowSubmit` off and `submit_first` stays\n * callable, which quietly leaves an agent holding submission authority the app\n * has just revoked. So every change to the options opens a new epoch: the\n * previous epoch's `AbortController` is aborted first, which unregisters its\n * tools, and only then are the new ones registered.\n *\n * Chrome's guidance is the same — register a tool only while it is useful in the\n * current page state.\n *\n * @see https://developer.chrome.com/docs/ai/webmcp/best-practices\n *\n * Must be created within the form's injection context (it captures the form\n * `Injector` for the deferred `runInInjectionContext`).\n *\n * @internal\n */\nexport function createWebMcpGate(): Signal<WebMcpStatus> {\n const enabled = inject(WEB_MCP_ENABLED);\n const isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n const stateManager = inject(FormStateManager);\n const injector = inject(Injector);\n const destroyRef = inject(DestroyRef);\n const logger = inject(DynamicFormLogger);\n\n // Registration touches the browser's model context, so it is browser-only.\n // Bail before touching the config so SSR never even evaluates the predicate.\n if (!enabled || !isBrowser) return computed(() => 'disabled');\n\n /**\n * What a registration epoch is built from.\n *\n * The options come from the *effective* form options. `webMcp` is part of the\n * public `FormOptions`, so `[formOptions]` on the component is a legitimate\n * place to set it; reading `activeConfig().options` alone made that override\n * silently do nothing.\n *\n * `formSetup` is in here too, because a config swap that keeps the same tool\n * name and description still changes the form the tools describe. Without it,\n * the second config would be driven through the first one's schema.\n */\n const registration = computed(() => {\n const options = stateManager.effectiveFormOptions().webMcp;\n return options ? { options: options as WebMcpToolOptions, setup: stateManager.formSetup() } : undefined;\n });\n\n const status = signal<WebMcpStatus>('idle');\n\n /** Aborting this revokes the current epoch's tools. */\n let epoch: AbortController | undefined;\n /** Guards the lazy import: a resolution from a superseded epoch is discarded. */\n let epochId = 0;\n\n const closeEpoch = (): void => {\n epoch?.abort();\n epoch = undefined;\n };\n\n destroyRef.onDestroy(closeEpoch);\n\n explicitEffect([registration], ([input]) => {\n // Every change closes the previous epoch first: aborting its controller\n // unregisters the tools it owns, so nothing from the old config outlives it.\n closeEpoch();\n epochId += 1;\n const thisEpoch = epochId;\n\n if (!input) {\n status.set('idle');\n return;\n }\n\n const controller = new AbortController();\n epoch = controller;\n status.set('registering');\n\n void import('./bootstrap-web-mcp')\n .then(({ bootstrapWebMcp }) => {\n // The config may have changed again while the chunk was in flight.\n if (thisEpoch !== epochId || controller.signal.aborted) return;\n\n return runInInjectionContext(injector, () => bootstrapWebMcp(input.options, controller.signal));\n })\n .then((result) => {\n if (thisEpoch !== epochId || controller.signal.aborted) return;\n if (result) status.set(result);\n })\n .catch((error: unknown) => {\n if (thisEpoch !== epochId) return;\n // A failed chunk load must not break the form — it just stays invisible\n // to agents.\n status.set('failed');\n logger.error('Failed to load the WebMCP registrar; this form will not be exposed to agents.', error);\n });\n });\n\n return status.asReadonly();\n}\n","import { InjectionToken } from '@angular/core';\n\n/**\n * Multi-provider token. Each entry is resolved at form bootstrap purely for its\n * construction side effect — useful for orchestrators that need to wire reactive\n * streams before first render but don't need to be referenced at use-sites.\n *\n * @internal\n */\nexport const FORM_INITIALIZER = new InjectionToken<readonly unknown[]>('FORM_INITIALIZER');\n","import { computed, Injectable, Signal, signal } from '@angular/core';\n\nconst AUTO_ID_PREFIX = 'df-';\n\n/**\n * Root-singleton tracking mounted DynamicForm instances, driving auto-prefixing.\n *\n * Each form registers a `visible` signal (true while its host is rendered). Only\n * visible forms count toward \"more than one present\", so a cached but hidden page\n * — e.g. ionic's `ion-router-outlet` keeps the previous page in the DOM for\n * swipe-back — doesn't inflate the count. Counting signals (not the DOM) keeps\n * the computed pure; `_membership` only invalidates it on register/unregister,\n * since Map membership itself isn't reactive.\n *\n * Slots are recycled (lowest free `df-N`) so ids stay compact across navigation.\n */\n@Injectable({ providedIn: 'root' })\nexport class DynamicFormInstanceRegistry {\n private readonly slots = new Map<number, Signal<boolean>>();\n private readonly _membership = signal(0);\n\n /** True while more than one VISIBLE form is mounted — the trigger for auto-prefixing. */\n readonly multiplePresent: Signal<boolean> = computed(() => {\n this._membership();\n let visible = 0;\n for (const isVisible of this.slots.values()) {\n if (isVisible()) {\n visible += 1;\n if (visible > 1) return true;\n }\n }\n return false;\n });\n\n /** Registers a form's visibility signal; returns a stable, recycled auto-id. */\n register(visible: Signal<boolean>): string {\n let slot = 1;\n while (this.slots.has(slot)) slot++;\n this.slots.set(slot, visible);\n this._membership.update((m) => m + 1);\n return `${AUTO_ID_PREFIX}${slot}`;\n }\n\n unregister(id: string): void {\n this.slots.delete(Number(id.slice(AUTO_ID_PREFIX.length)));\n this._membership.update((m) => m + 1);\n }\n}\n","import { computed, DestroyRef, ElementRef, inject, Injectable, isDevMode, PLATFORM_ID, signal, Signal } from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { FORM_OPTIONS } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormInstanceRegistry } from './dynamic-form-instance-registry.service';\n\n// Whitespace breaks the space-separated aria-describedby list; punctuation breaks selectors.\nconst INVALID_ID_CHARS = /[^\\w-]+/g;\n\nfunction sanitizeIdPrefix(prefix: string): string {\n return prefix.replace(INVALID_ID_CHARS, '_');\n}\n\nfunction isRendered(host: HTMLElement): boolean {\n if (!host.isConnected) return false;\n if (typeof host.checkVisibility === 'function') return host.checkVisibility();\n const rect = host.getBoundingClientRect();\n return rect.width > 0 || rect.height > 0;\n}\n\n/**\n * Per-form owner of the DOM-id prefix, published through `FORM_ID_PREFIX`.\n * Resolution: explicit `options.idPrefix` (trimmed + sanitized) wins; else the\n * instance's auto-id while more than one form is *visibly* mounted; else `''`.\n *\n * Not latched: a form reverts to unprefixed once it's the only visible one, so\n * navigating away from a multi-form page (incl. ionic's cached `ion-router-outlet`\n * stack) doesn't leave it stuck-prefixed.\n */\n@Injectable()\nexport class FormIdPrefixService {\n private readonly registry = inject(DynamicFormInstanceRegistry);\n private readonly options = inject(FORM_OPTIONS, { optional: true });\n private readonly logger = inject(DynamicFormLogger, { optional: true });\n private readonly host = inject(ElementRef<HTMLElement>).nativeElement;\n\n // Optimistic: counts toward \"multiple present\" until the ResizeObserver confirms\n // whether it's actually rendered. Starting true keeps SSR and the client's first\n // render in agreement (both count-all), avoiding a hydration mismatch; the\n // observer corrects it after layout (a normal reactive update, not a hydration error).\n private readonly visible = signal(true);\n\n private readonly autoId = this.registry.register(this.visible);\n\n private readonly rawPrefix = computed(() => this.options?.()?.idPrefix?.trim() || undefined);\n\n readonly prefix: Signal<string> = computed(() => {\n const explicit = this.rawPrefix();\n if (explicit) return sanitizeIdPrefix(explicit);\n return this.registry.multiplePresent() ? this.autoId : '';\n });\n\n constructor() {\n const destroyRef = inject(DestroyRef);\n destroyRef.onDestroy(() => this.registry.unregister(this.autoId));\n\n // A host's box collapses to 0 on display:none and restores when shown. set() is\n // a no-op when the value is unchanged, so plain resizes don't churn field inputs.\n if (isPlatformBrowser(inject(PLATFORM_ID)) && typeof ResizeObserver !== 'undefined') {\n const ro = new ResizeObserver(() => this.visible.set(isRendered(this.host)));\n ro.observe(this.host);\n destroyRef.onDestroy(() => ro.disconnect());\n }\n\n if (isDevMode()) {\n explicitEffect([this.rawPrefix], ([raw]) => {\n const safe = raw ? sanitizeIdPrefix(raw) : raw;\n if (raw && safe !== raw) {\n this.logger?.warn(`idPrefix \"${raw}\" sanitized to \"${safe}\".`);\n }\n });\n }\n }\n}\n","import { computed, Provider, Signal } from '@angular/core';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { ArrayItemRegistryService } from '../core/registry/array-item-registry.service';\nimport { FieldContextRegistryService } from '@ng-forge/dynamic-forms/internal';\nimport { FunctionRegistryService } from '@ng-forge/dynamic-forms/internal';\nimport { RootFormRegistryService } from '@ng-forge/dynamic-forms/internal';\nimport { SchemaRegistryService } from '../core/registry/schema-registry.service';\nimport { FormIdPrefixService } from '../core/registry/form-id-prefix.service';\nimport { FieldViewportObserver } from '../directives/df-field-outlet/field-viewport-observer.service';\nimport { FormStateManager, FORM_STATE_DEPS, FormStateDeps } from '../state/form-state-manager';\nimport {\n DEFAULT_PROPS,\n DEFAULT_VALIDATION_MESSAGES,\n DEFAULT_WRAPPERS,\n EXTERNAL_DATA,\n FORM_ID_PREFIX,\n FORM_OPTIONS,\n} from '@ng-forge/dynamic-forms/internal';\nimport { DERIVATION_WARNING_TRACKER } from '../core/derivation/derivation-warning-tracker';\nimport { DEPRECATION_WARNING_TRACKER } from '@ng-forge/dynamic-forms/internal';\nimport { createWarningTracker } from '@ng-forge/dynamic-forms/internal';\nimport { createDerivationRenderGate, DERIVATION_RENDER_GATE } from '../core/derivation/derivation-render-gate';\nimport { createWebMcpGate, WEB_MCP_GATE } from '../core/web-mcp/web-mcp-gate';\nimport { CONTAINER_FIELD_PROCESSORS, createContainerFieldProcessors } from '../utils/container-utils/container-field-processors';\nimport { createPropertyOverrideStore, PROPERTY_OVERRIDE_STORE } from '../core/property-derivation/property-override-store';\nimport { HTTP_CONDITION_CACHE, HttpConditionCache } from '@ng-forge/dynamic-forms/internal';\nimport { LogicFunctionCacheService } from '@ng-forge/dynamic-forms/internal';\nimport { HttpConditionFunctionCacheService } from '@ng-forge/dynamic-forms/internal';\nimport { AsyncConditionFunctionCacheService } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicValueFunctionCacheService } from '@ng-forge/dynamic-forms/internal';\nimport { ADDON_ACTION_REGISTRY, createAddonActionRegistry } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Always-on providers for any DynamicForm: state machine, registries, signal-context tokens.\n * Pure form bootstrap — no derivation, HTTP, or async machinery.\n *\n * @internal\n */\nfunction coreProviders(): Provider[] {\n return [\n EventBus,\n { provide: CONTAINER_FIELD_PROCESSORS, useFactory: createContainerFieldProcessors },\n SchemaRegistryService,\n FunctionRegistryService,\n {\n provide: FORM_STATE_DEPS,\n useFactory: (): FormStateDeps => ({ config: null, formOptions: null, value: null, source: null }),\n },\n FormStateManager,\n {\n provide: RootFormRegistryService,\n useFactory: (stateManager: FormStateManager) =>\n new RootFormRegistryService(\n stateManager.formValue as Signal<Record<string, unknown>>,\n computed(() => stateManager.form()),\n ),\n deps: [FormStateManager],\n },\n FieldContextRegistryService,\n ArrayItemRegistryService,\n {\n provide: DEFAULT_PROPS,\n useFactory: (stateManager: FormStateManager) => computed(() => stateManager.activeConfig()?.defaultProps),\n deps: [FormStateManager],\n },\n {\n provide: DEFAULT_WRAPPERS,\n useFactory: (stateManager: FormStateManager) => computed(() => stateManager.activeConfig()?.defaultWrappers),\n deps: [FormStateManager],\n },\n {\n provide: DEFAULT_VALIDATION_MESSAGES,\n useFactory: (stateManager: FormStateManager) => computed(() => stateManager.activeConfig()?.defaultValidationMessages),\n deps: [FormStateManager],\n },\n {\n provide: FORM_OPTIONS,\n useFactory: (stateManager: FormStateManager) => stateManager.effectiveFormOptions,\n deps: [FormStateManager],\n },\n {\n provide: EXTERNAL_DATA,\n useFactory: (stateManager: FormStateManager) => computed(() => stateManager.activeConfig()?.externalData),\n deps: [FormStateManager],\n },\n // Per-form DOM-id prefix: registers this instance with the root registry for\n // multi-form collision detection and publishes the resolved prefix signal.\n FormIdPrefixService,\n // Form-scoped, never root: it holds a mutable observer map, and\n // module-scoped mutable state is shared across requests under SSR.\n FieldViewportObserver,\n {\n provide: FORM_ID_PREFIX,\n useFactory: (svc: FormIdPrefixService) => svc.prefix,\n deps: [FormIdPrefixService],\n },\n { provide: DEPRECATION_WARNING_TRACKER, useFactory: createWarningTracker },\n // ADDON_ACTION_REGISTRY must live at form scope (not root) because the\n // multi-provider source `ADDON_ACTION_HANDLERS` is contributed by\n // `withAddonActions(...)` features passed to `provideDynamicForm(...)`\n // — those entries are only visible inside the form's own injector tree.\n { provide: ADDON_ACTION_REGISTRY, useFactory: createAddonActionRegistry },\n ];\n}\n\n/**\n * Providers for the value-derivation engine: warning tracker + a lazy bootstrap\n * hook. The heavy orchestrator module (collectors, applicators, cycle detection,\n * and the value/property/HTTP/async stream factories) is NOT statically imported\n * here — it is dynamically imported the first time a config declares a derivation,\n * so forms without derivations never pay for the engine.\n *\n * @internal\n */\nfunction derivationProviders(): Provider[] {\n return [\n { provide: DERIVATION_WARNING_TRACKER, useFactory: createWarningTracker },\n // The render gate lazy-loads + wires the orchestrator on the first config\n // that declares a derivation, and holds `shouldRender` closed until it does\n // (so derivation-bearing fields render already-derived, no flash). The\n // orchestrator is component-scoped (it can't be `providedIn: 'root'`), so the\n // gate loads it with a plain dynamic `import()` + `runInInjectionContext`,\n // not `injectAsync`. `DynamicForm` injects the gate, which wakes the load.\n { provide: DERIVATION_RENDER_GATE, useFactory: createDerivationRenderGate },\n ];\n}\n\n/**\n * Provider for the property-derivation override store. The store is consumed\n * eagerly by field rendering (to apply derived hidden/disabled/readonly state),\n * so it stays eager even though the orchestrator that writes into it is lazy.\n *\n * @internal\n */\nfunction propertyDerivationProviders(): Provider[] {\n return [{ provide: PROPERTY_OVERRIDE_STORE, useFactory: createPropertyOverrideStore }];\n}\n\n/**\n * Providers for HTTP-backed condition expressions and validators.\n * Future: opt-in via withHttpExpressions() at a separate entry point.\n *\n * @internal\n */\nfunction httpExpressionProviders(): Provider[] {\n return [{ provide: HTTP_CONDITION_CACHE, useFactory: () => new HttpConditionCache(100) }, HttpConditionFunctionCacheService];\n}\n\n/**\n * Providers for async (Promise/Observable-returning) condition expressions.\n * Future: opt-in via withAsyncExpressions() at a separate entry point.\n *\n * @internal\n */\nfunction asyncExpressionProviders(): Provider[] {\n return [AsyncConditionFunctionCacheService];\n}\n\n/**\n * Providers for dynamic-value functions (numeric/string validator parameters resolved\n * from formValue expressions, e.g. `min: { expression: 'formValue.minAge' }`).\n * Future: opt-in via withDynamicValues() at a separate entry point.\n *\n * @internal\n */\nfunction dynamicValueProviders(): Provider[] {\n return [DynamicValueFunctionCacheService];\n}\n\n/**\n * Providers for the logic function cache (memoizes compiled state-logic conditions\n * — `when`, `disabled`, `readonly`, `hidden` predicates). Used universally by\n * validator-factory, logic-applicator, schema-application; treated as core for now.\n *\n * @internal\n */\nfunction logicProviders(): Provider[] {\n return [LogicFunctionCacheService];\n}\n\n/**\n * Composes all DynamicForm-level providers. Today: every feature group is included so\n * behavior matches the prior monolithic provider list. The grouped composition exists\n * so future feature flags / secondary entry points can drop groups consumers don't use\n * without re-touching every provider.\n *\n * @internal\n */\nexport function provideDynamicFormDI(): Provider[] {\n return [\n ...coreProviders(),\n ...logicProviders(),\n ...dynamicValueProviders(),\n ...httpExpressionProviders(),\n ...asyncExpressionProviders(),\n ...propertyDerivationProviders(),\n ...derivationProviders(),\n { provide: WEB_MCP_GATE, useFactory: createWebMcpGate },\n ];\n}\n","import { Injectable } from '@angular/core';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Injectable service for dispatching events into a DynamicForm from outside the form.\n *\n * @Component({\n * providers: [EventDispatcher],\n * template: `<form [dynamic-form]=\"config\" [(value)]=\"formValue\"></form>`\n * })\n * export class MyComponent {\n * readonly dispatcher = inject(EventDispatcher);\n * readonly formValue = signal<Record<string, unknown>>({});\n *\n * constructor() {\n * effect(() => {\n * const category = this.formValue()?.['category'] as string | undefined;\n * if (category) {\n * this.dispatcher.dispatch(\n * arrayEvent('tasks').append([{ key: 'name', type: 'input', label: 'Task', value: category }])\n * );\n * }\n * });\n * }\n * }\n * ```\n *\n * ## Multi-form note\n *\n * If multiple `DynamicForm` instances exist under the same provider scope, **all forms**\n * will receive dispatched events. To target a specific form, scope the provider to a\n * wrapper component that contains only that form.\n *\n * ## What events can be dispatched\n *\n * Any `FormEvent` instance is accepted — array events, reset/clear events, custom events, etc.\n * The `arrayEvent()` builder is the recommended way to construct array manipulation events:\n *\n * ```typescript\n * dispatcher.dispatch(arrayEvent('tasks').append(template));\n * dispatcher.dispatch(arrayEvent('tasks').removeAt(0));\n * dispatcher.dispatch(new FormResetEvent());\n * ```\n */\n@Injectable()\nexport class EventDispatcher {\n private bus: EventBus | undefined;\n\n /**\n * Dispatches a form event into the connected DynamicForm's event bus.\n * No-op if no form is currently connected.\n *\n * @param event - A FormEvent instance. Use the `arrayEvent()` builder for array operations.\n */\n dispatch(event: FormEvent): void {\n this.bus?.emitInstance(event);\n }\n\n /** @internal - Called by DynamicForm on init */\n connect(bus: EventBus): void {\n this.bus = bus;\n }\n\n /** @internal - Called by DynamicForm on destroy */\n disconnect(): void {\n this.bus = undefined;\n }\n}\n","import { Directive, Injectable, inject, input, Signal, signal, TemplateRef } from '@angular/core';\n\n/**\n * Marks an `<ng-template>` projected into `<df-dynamic-form>` content as\n * available to template addons by name.\n */\n@Directive({\n selector: 'ng-template[dfTemplate]',\n exportAs: 'dfTemplate',\n})\nexport class DfTemplate {\n /** Name this template registers under — referenced from `TemplateAddon.templateKey`. */\n readonly dfTemplate = input.required<string>();\n\n /** The wrapped template, captured for registration and `NgTemplateOutlet` rendering. */\n readonly templateRef: TemplateRef<unknown> = inject(TemplateRef);\n}\n\n/**\n * Holder service published at the `<df-dynamic-form>` component scope.\n * `DynamicForm` collects projected `<ng-template dfTemplate=\"...\">` via\n * `contentChildren(DfTemplate)` and pushes the resulting map through\n * `DfFieldTemplateRegistry.set(...)`. The {@link DF_FIELD_TEMPLATES}\n * injection token is provided as a factory that returns this service's\n * `map` signal, so template-addon components can resolve `templateKey`\n * without coupling to the host form's generic class.\n */\n@Injectable()\nexport class DfFieldTemplateRegistry {\n private readonly _map = signal<ReadonlyMap<string, TemplateRef<unknown>>>(new Map());\n\n /** Reactive view consumed by the `template` addon type via DI. */\n readonly map: Signal<ReadonlyMap<string, TemplateRef<unknown>>> = this._map.asReadonly();\n\n /** Replace the registry contents — called from `DynamicForm` when projected templates change. */\n set(value: ReadonlyMap<string, TemplateRef<unknown>>): void {\n this._map.set(value);\n }\n}\n","import {\n afterNextRender,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChildren,\n DestroyRef,\n EnvironmentInjector,\n inject,\n Injector,\n input,\n model,\n Signal,\n TemplateRef,\n WritableSignal,\n signal,\n} from '@angular/core';\nimport { DfFieldOutlet } from './directives/df-field-outlet/df-field-outlet.directive';\nimport { FieldTree } from '@angular/forms/signals';\nimport { outputFromObservable, takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\nimport { filter, shareReplay, take } from 'rxjs';\nimport { createSubmissionHandler } from './utils/submission-handler/submission-handler';\nimport { FormConfig, FormOptions } from '@ng-forge/dynamic-forms/internal';\nimport { RegisteredFieldTypes } from '@ng-forge/dynamic-forms/internal';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { FormSubmitEvent } from './events/constants/submit.event';\nimport { ComponentInitializedEvent } from '@ng-forge/dynamic-forms/internal';\nimport { InferFormModel } from '@ng-forge/dynamic-forms/internal';\nimport { isContainerField } from '@ng-forge/dynamic-forms/internal';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { injectFormComponentPreloader } from './utils/preload-form-components/preload-form-components';\nimport { PageOrchestratorComponent } from './core/page-orchestrator/page-orchestrator.component';\nimport { DERIVATION_RENDER_GATE } from './core/derivation/derivation-render-gate';\nimport { WEB_MCP_GATE } from './core/web-mcp/web-mcp-gate';\nimport { FORM_INITIALIZER } from './providers/form-initializer.token';\nimport { FormClearEvent } from './events/constants/form-clear.event';\nimport { FormResetEvent } from './events/constants/form-reset.event';\nimport { PageChangeEvent } from './events/constants/page-change.event';\nimport { PagerStateEvent } from './events/constants/pager-state.event';\nimport { ActivePageInitializedEvent } from './events/constants/active-page-initialized.event';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { FormStateManager, FORM_STATE_DEPS } from './state/form-state-manager';\nimport { provideDynamicFormDI } from './providers/dynamic-form-di';\nimport { FormIdPrefixService } from './core/registry/form-id-prefix.service';\nimport { EventDispatcher } from './events/event-dispatcher';\nimport { DfTemplate, DfFieldTemplateRegistry } from './directives/df-template.directive';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n DfPlaceholder,\n DfPlaceholderRegistry,\n DF_FIELD_PLACEHOLDERS,\n type FieldPlaceholderContext,\n} from './directives/df-placeholder/df-placeholder.directive';\nimport { createPlaceholderContextCache, resolvePlaceholderTemplate } from './directives/df-placeholder/resolve-placeholder-template';\nimport { DF_FIELD_TEMPLATES } from '@ng-forge/dynamic-forms/internal';\nimport { getGridClassString } from '@ng-forge/dynamic-forms/internal';\nimport { ResolvedField } from './utils/resolve-field/resolve-field';\nimport { FIELD_WINDOWING } from './providers/features/field-windowing/field-windowing.token';\nimport { resolveFieldWindowing } from './providers/features/field-windowing/resolve-field-windowing';\nimport { collectInitializingContainerKeys, initializationComponentKey } from './utils/container-utils/container-utils';\n\n/**\n * Renders a form from a {@link FormConfig}. Attribute component on a native\n * `<form>` element (selector `form[dynamic-form]`); state management is\n * delegated to `FormStateManager`.\n *\n * Provide a UI adapter once via {@link provideDynamicForm} (for example\n * `provideDynamicForm(...withMaterialFields())`), then bind a config and\n * listen for `submitted`. Field-value types are inferred from the config when\n * it is authored with `as const satisfies FormConfig`.\n *\n * @example\n * ```ts\n * @Component({\n * imports: [DynamicForm],\n * template: `<form [dynamic-form]=\"config\" (submitted)=\"onSubmit($event)\"></form>`,\n * })\n * export class SignInComponent {\n * config = {\n * fields: [\n * { key: 'email', type: 'input', value: '', label: 'Email', required: true, email: true },\n * { type: 'submit', key: 'submit', label: 'Sign in' },\n * ],\n * } as const satisfies FormConfig;\n *\n * onSubmit(value: InferFormValue<typeof this.config.fields>) {\n * console.log(value); // inferred: { email: string }\n * }\n * }\n * ```\n */\n@Component({\n selector: 'form[dynamic-form]',\n imports: [DfFieldOutlet, PageOrchestratorComponent, NgTemplateOutlet],\n template: `\n @if (shouldRender()) {\n @switch (formModeDetection().mode) {\n @case ('paged') {\n <div page-orchestrator [pageFields]=\"pageFieldDefinitions()\" [form]=\"form()\" [fieldSignalContext]=\"fieldSignalContext()\"></div>\n }\n @case ('non-paged') {\n @for (field of resolvedFields(); track field.key; let i = $index) {\n @if (windowsField(field, i)) {\n @if (!field.hidden()) {\n @defer (on viewport) {\n <ng-container *dfFieldOutlet=\"field; environmentInjector: environmentInjector\" />\n } @placeholder {\n <div\n [class]=\"placeholderGridClass(field)\"\n [style.min-height]=\"fieldWindowing().placeholderHeight\"\n [attr.data-field-key]=\"field.key\"\n aria-hidden=\"true\"\n inert\n >\n @if (placeholderTemplate(field); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" [ngTemplateOutletContext]=\"placeholderContext(field)\" />\n }\n </div>\n }\n }\n } @else {\n <!-- DfFieldOutlet owns the hidden gate so an already-mounted field can be detached\n and restored without recreating its component and wrapper chain. -->\n <ng-container *dfFieldOutlet=\"field; environmentInjector: environmentInjector\" />\n }\n }\n }\n @default {\n never;\n }\n }\n }\n `,\n styleUrl: './dynamic-form.component.scss',\n providers: [\n provideDynamicFormDI(),\n DfFieldTemplateRegistry,\n { provide: DF_FIELD_TEMPLATES, useFactory: () => inject(DfFieldTemplateRegistry).map },\n DfPlaceholderRegistry,\n { provide: DF_FIELD_PLACEHOLDERS, useFactory: () => inject(DfPlaceholderRegistry).placeholders },\n ],\n host: {\n class: 'df-dynamic-form df-form',\n novalidate: '', // Disable browser validation - Angular Signal Forms handles validation\n '[class.disabled]': 'disabled()',\n '[class.df-form-paged]': 'formModeDetection().mode === \"paged\"',\n '[class.df-form-non-paged]': 'formModeDetection().mode === \"non-paged\"',\n '[attr.data-form-mode]': 'formModeDetection().mode',\n '[attr.id]': 'idPrefix() || null',\n '(submit)': 'onNativeSubmit($event)',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class DynamicForm<\n TFields extends RegisteredFieldTypes[] = RegisteredFieldTypes[],\n TModel extends Record<string, unknown> = InferFormModel<TFields>,\n> {\n // ─────────────────────────────────────────────────────────────────────────────\n // Inputs (must be declared BEFORE deps connection and stateManager injection)\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Form configuration defining the structure, validation, and behavior. */\n config = input.required<FormConfig<TFields>>({ alias: 'dynamic-form' });\n\n /** Runtime form options that override config options when provided. */\n formOptions = input<FormOptions | undefined>(undefined);\n\n /** Form values for two-way data binding. */\n value = model<Partial<TModel> | undefined>(undefined);\n\n /**\n * How lenient the addon validator is on `config.fields[...].addons`.\n * `'inline'` (default) keeps everything; `'json'` drops code-only types\n * with a warning. Read at form init and on every config swap — change\n * `source` AND the config to force re-validation mid-flight.\n */\n source = input<'inline' | 'json'>('inline');\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Dependencies\n // ─────────────────────────────────────────────────────────────────────────────\n\n private destroyRef = inject(DestroyRef);\n private injector = inject(Injector);\n protected environmentInjector = inject(EnvironmentInjector);\n private eventBus = inject(EventBus);\n private logger = inject(DynamicFormLogger);\n private dispatcher = inject(EventDispatcher, { optional: true });\n private templateRegistry = inject(DfFieldTemplateRegistry);\n private placeholderRegistry = inject(DfPlaceholderRegistry);\n private fieldPlaceholders = inject(DF_FIELD_PLACEHOLDERS);\n private globalFieldWindowing = inject(FIELD_WINDOWING);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Projected templates — collected for the `template` addon type via DI.\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** All `<ng-template dfTemplate=\"...\">` instances projected into this form. */\n private readonly _projectedTemplates = contentChildren(DfTemplate);\n\n /** All `<ng-template dfPlaceholder>` instances projected into this form. */\n private readonly _projectedPlaceholders = contentChildren(DfPlaceholder);\n\n private readonly placeholderContextFor = createPlaceholderContextCache();\n\n private readonly stateManager = this.connectDeps();\n\n /**\n * Owns this form's DOM-id prefix and registers the instance with the root\n * registry for multi-form collision detection. Injected eagerly (not lazily\n * via first field map) so the live-form count is accurate from construction.\n */\n private readonly formIdPrefix = inject(FormIdPrefixService);\n\n /** Active DOM-id prefix — empty unless explicitly set or multiple forms are mounted. */\n protected readonly idPrefix = this.formIdPrefix.prefix;\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Private State\n // ─────────────────────────────────────────────────────────────────────────────\n\n private componentId = 'dynamic-form';\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Signals - Direct pass-through from state manager\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** The currently active config used for form rendering */\n activeConfig = this.stateManager.activeConfig;\n\n /** Current render phase: 'render' = showing form, 'teardown' = hiding old components */\n renderPhase = this.stateManager.renderPhase;\n\n /** Computed form mode detection with validation */\n formModeDetection = this.stateManager.formModeDetection;\n\n /** Page field definitions for paged forms */\n pageFieldDefinitions = this.stateManager.pageFieldDefinitions;\n\n /** Effective form options (merged from config and input) */\n effectiveFormOptions = this.stateManager.effectiveFormOptions;\n\n /** Field signal context for injection into child components */\n fieldSignalContext = this.stateManager.fieldSignalContext;\n\n /** Default values computed from field definitions */\n defaultValues = this.stateManager.defaultValues;\n\n /** The Angular Signal Form instance */\n form = this.stateManager.form;\n\n /** Current form values (reactive) */\n formValue = this.stateManager.formValue;\n\n /** Whether the form is currently valid */\n valid = this.stateManager.valid;\n\n /** Whether the form is currently invalid */\n invalid = this.stateManager.invalid;\n\n /** Whether any form field has been modified */\n dirty = this.stateManager.dirty;\n\n /** Whether any form field has been touched (blurred) */\n touched = this.stateManager.touched;\n\n /** Current validation errors from all fields */\n errors = this.stateManager.errors;\n\n /** Whether the form is disabled (from options or form state) */\n disabled = this.stateManager.disabled;\n\n /** Whether the form is currently submitting */\n submitting = this.stateManager.submitting;\n\n /** Collects errors from async field component loading for error boundary patterns */\n fieldLoadingErrors = this.stateManager.fieldLoadingErrors;\n\n /** Whether to render the form template */\n // `derivationReady` is false only while a derivation-bearing config waits for\n // the lazily-loaded engine to wire, so fields render already-derived (no flash).\n private derivationReady = inject(DERIVATION_RENDER_GATE);\n shouldRender = computed(() => this.stateManager.shouldRender() && this.stateManager.formSchemaReady() && this.derivationReady());\n\n /**\n * What the experimental WebMCP layer is doing for this form.\n *\n * Injecting it is also what instantiates the gate (component providers are\n * lazy), which is what keeps the registrar lazily loaded. Intentionally absent\n * from `shouldRender`: agent visibility must never gate render.\n *\n * `'disabled'` unless `withExperimentalWebMcp()` is provided; `'idle'` until a\n * config declares `options.webMcp`; `'active'` once its tools are registered.\n * `'failed'` and `'unsupported'` are the two ways registration does not\n * happen, and are worth surfacing rather than guessing at.\n *\n * @experimental\n */\n readonly webMcpStatus = inject(WEB_MCP_GATE);\n\n /** Resolved fields ready for rendering */\n protected resolvedFields = this.stateManager.resolvedFields;\n\n /**\n * Effective field-windowing config for non-paged forms. Per-form\n * `FormOptions.fieldWindowing` wins over the global `withFieldWindowing()`\n * default; both fall back to disabled (fully eager).\n */\n protected readonly fieldWindowing = computed(() =>\n resolveFieldWindowing(this.globalFieldWindowing, this.effectiveFormOptions()?.fieldWindowing),\n );\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Computed Signals - Internal\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly initializedComponents = signal<ReadonlySet<string>>(new Set());\n private readonly initialPageReady = signal(false);\n\n private readonly initializationReady = computed(() => {\n const config = this.activeConfig();\n if (!config) return false;\n\n if (this.formModeDetection().mode === 'paged') return this.initialPageReady();\n\n const initialized = this.initializedComponents();\n const expected = [\n initializationComponentKey('dynamic-form', this.componentId),\n ...collectInitializingContainerKeys(config.fields ?? []),\n ];\n return expected.every((key) => initialized.has(key));\n });\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Initialization\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Replayable readiness so late subscribers cannot miss hot EventBus announcements. */\n initialized$ = toObservable(this.initializationReady, { injector: this.injector }).pipe(\n filter((ready) => ready),\n take(1),\n shareReplay({ bufferSize: 1, refCount: false }),\n );\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Outputs\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Emits when form validity changes. */\n validityChange = outputFromObservable(toObservable(this.valid));\n\n /** Emits when form dirty state changes. */\n dirtyChange = outputFromObservable(toObservable(this.dirty));\n\n /** Emits form values when submitted (via FormSubmitEvent) and form is valid. */\n submitted = outputFromObservable(this.stateManager.submitted$);\n\n /** Emits when form is reset to default values. */\n reset = outputFromObservable(this.eventBus.on<FormResetEvent>('form-reset'));\n\n /** Emits when form is cleared to empty state. */\n cleared = outputFromObservable(this.eventBus.on<FormClearEvent>('form-clear'));\n\n /** Emits all form events for custom event handling. */\n events = outputFromObservable(this.eventBus.events$);\n\n /**\n * Emits when a non-paged form is fully initialized, or when the initially active page of a\n * paged form is ready for interaction. Virtualized inactive pages are not part of initial\n * readiness because they intentionally remain unmounted.\n */\n initialized = outputFromObservable(this.initialized$);\n\n /**\n * EXPERIMENTAL. Added alongside page preloading; the emission contract may change.\n *\n * Emits after the currently visible page and all of its visible fields render. Announced\n * once per visit to a page, and again when that page is returned to. Use this when work must\n * run after every page transition; `initialized` emits only for the initial page.\n */\n activePageInitialized = outputFromObservable(this.eventBus.on<ActivePageInitializedEvent>('active-page-initialized'));\n\n /** Emits when the current page changes in paged forms. */\n onPageChange = outputFromObservable(this.eventBus.on<PageChangeEvent>('page-change'));\n\n /** Emits when pager state changes (currentPageIndex, totalPages, isFirstPage, isLastPage). */\n onPageNavigationStateChange = outputFromObservable(this.eventBus.on<PagerStateEvent>('pager-state'));\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Constructor\n // ─────────────────────────────────────────────────────────────────────────────\n\n constructor() {\n this.eventBus\n .on<ComponentInitializedEvent>('component-initialized')\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((event) => {\n const key = initializationComponentKey(event.componentType, event.componentId);\n this.initializedComponents.update((current) => {\n if (current.has(key)) return current;\n const next = new Set(current);\n next.add(key);\n return next;\n });\n });\n this.eventBus\n .on<ActivePageInitializedEvent>('active-page-initialized')\n .pipe(takeUntilDestroyed(this.destroyRef), take(1))\n .subscribe(() => this.initialPageReady.set(true));\n\n this.dispatcher?.connect(this.eventBus);\n this.destroyRef.onDestroy(() => this.dispatcher?.disconnect());\n\n // Wake feature-provider orchestrators (derivation, property-derivation, …) so their\n // reactive streams are wired before first render. Each feature provider registers\n // itself via FORM_INITIALIZER multi-provider; resolving the array forces DI to\n // construct each entry. Without a feature provider, the array stays empty and no\n // static reference to that feature's classes leaks into this component.\n // Runs after dispatcher.connect() to preserve the prior bootstrap order.\n inject(FORM_INITIALIZER, { optional: true });\n\n // Start every field and wrapper chunk this config needs, in parallel, before\n // rendering asks for any of them. Wrapper chains are otherwise discovered\n // per-field inside DfFieldOutlet, which cannot exist until that field's own\n // component has loaded — a dependent waterfall that costs a round trip per\n // wave. Fire-and-forget: nothing here gates render.\n const preload = injectFormComponentPreloader();\n explicitEffect([this.config], ([config]) => preload.preloadConfig(config as FormConfig));\n\n this.setupEffects();\n this.setupEventHandlers();\n }\n\n /**\n * Handles native form submission triggered by:\n * - Pressing Enter in an input field\n * - Clicking a button with type=\"submit\"\n * - Programmatic form.submit() calls\n *\n * @param event - The native submit event from the form element\n */\n protected onNativeSubmit(event: Event): void {\n event.preventDefault();\n this.eventBus.dispatch(FormSubmitEvent);\n }\n\n /**\n * Whether a field should be deferred by field windowing. Containers are never\n * windowed: they emit `ComponentInitializedEvent`, which the form's init\n * tracker counts, so deferring one would stall `initialized` until it scrolls\n * into view. Leaf fields carry no such count, so they defer freely.\n */\n protected windowsField(field: ResolvedField, index: number): boolean {\n const w = this.fieldWindowing();\n return w.enabled && index >= w.eager && !isContainerField(field.fieldDef);\n }\n\n /** Class string for a windowed field's placeholder — matches the real field's grid column. */\n protected placeholderGridClass(field: ResolvedField): string {\n const grid = getGridClassString(field.fieldDef);\n return grid ? `df-field-placeholder ${grid}` : 'df-field-placeholder';\n }\n\n /** Projected placeholder template for a windowed field, or null for the built-in bare div. */\n protected placeholderTemplate(field: ResolvedField): TemplateRef<FieldPlaceholderContext> | null {\n return resolvePlaceholderTemplate(this.fieldPlaceholders(), { key: field.key, type: field.fieldDef.type });\n }\n\n /** Memoised template context for a windowed field's projected placeholder. */\n protected placeholderContext(field: ResolvedField): FieldPlaceholderContext {\n return this.placeholderContextFor(field);\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Private Methods\n // ─────────────────────────────────────────────────────────────────────────────\n\n private setupEffects(): void {\n // Emit initialization event for paged forms\n explicitEffect([this.formModeDetection, this.pageFieldDefinitions], ([{ mode }, pages]) => {\n if (mode === 'paged' && pages.length > 0) {\n this.eventBus.dispatch(ComponentInitializedEvent, 'dynamic-form', this.componentId);\n }\n });\n\n // Emit initialization event for non-paged forms\n explicitEffect([this.resolvedFields, this.formModeDetection, this.activeConfig], ([, { mode }, config]) => {\n if (config && mode === 'non-paged') {\n afterNextRender(\n () => {\n this.eventBus.dispatch(ComponentInitializedEvent, 'dynamic-form', this.componentId);\n },\n { injector: this.injector },\n );\n }\n });\n\n // Mirror projected `<ng-template dfTemplate=\"...\">` into the template\n // registry so `template` addons can resolve `templateKey` via DI.\n explicitEffect([this._projectedTemplates], ([templates]) => {\n const map = new Map<string, TemplateRef<unknown>>();\n for (const t of templates) {\n map.set(t.dfTemplate(), t.templateRef);\n }\n this.templateRegistry.set(map);\n });\n\n // Mirror projected `<ng-template dfPlaceholder>` into the placeholder registry\n // so windowed pages/fields (including dynamically-rendered ones) can resolve them.\n this.placeholderRegistry.bind(this._projectedPlaceholders);\n }\n\n /**\n * Populates FORM_STATE_DEPS with this component's input signals, then injects\n * FormStateManager. Must be called as a field initializer (after the input signals\n * are declared) so that FormStateManager reads populated deps when it is constructed.\n * inject() is valid here because field initializers run inside the injection context.\n */\n private connectDeps(): FormStateManager<TFields, TModel> {\n const deps = inject(FORM_STATE_DEPS);\n deps.config = this.config as Signal<FormConfig<RegisteredFieldTypes[]>>;\n deps.formOptions = this.formOptions;\n deps.value = this.value as WritableSignal<Partial<unknown> | undefined>;\n deps.source = this.source;\n return inject(FormStateManager<TFields, TModel>);\n }\n\n private setupEventHandlers(): void {\n createSubmissionHandler<TFields, TModel>({\n eventBus: this.eventBus,\n configSignal: this.config,\n formSignal: this.form as Signal<FieldTree<TModel>>,\n validSignal: this.valid,\n logger: this.logger,\n })\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe({\n error: (err) => this.logger.error('Submission handler error', err),\n });\n }\n}\n","import { DynamicFormError } from '@ng-forge/dynamic-forms/internal';\nimport { AddonTypeDefinition } from '@ng-forge/dynamic-forms/internal';\n\n/** Built-in addon types shipped by core. */\nexport const BUILT_IN_ADDON_TYPES: readonly AddonTypeDefinition[] = [\n {\n type: 'text',\n loadComponent: () => import('../addons/text-addon.component').then((m) => m.TextAddonComponent),\n validate: (addon, fieldKey) => {\n const text = (addon as { text?: unknown }).text;\n // Validates structural presence: rejects missing / null / non-string-non-callable,\n // and rejects literal empty strings. DynamicText values that resolve to empty\n // at runtime (signal/observable yielding '') are NOT caught here — they're\n // legal as far as the config is concerned, just render an empty span.\n if (text === undefined || text === null) {\n throw new DynamicFormError(`Addon type 'text' requires a 'text' field (field: '${fieldKey}').`);\n }\n if (typeof text === 'string' && text.length === 0) {\n throw new DynamicFormError(`Addon type 'text' requires a non-empty 'text' string (field: '${fieldKey}').`);\n }\n },\n },\n {\n type: 'template',\n loadComponent: () => import('../addons/template-addon.component').then((m) => m.TemplateAddonComponent),\n validate: (addon, fieldKey) => {\n const key = (addon as { templateKey?: unknown }).templateKey;\n if (typeof key !== 'string' || key.length === 0) {\n throw new DynamicFormError(`Addon type 'template' requires a non-empty 'templateKey' string (field: '${fieldKey}').`);\n }\n },\n },\n {\n type: 'component',\n // The shape carries a function loader — not serialisable; dropped by the\n // validator when the form config originated from JSON.\n jsonSafe: false,\n loadComponent: () => import('../addons/component-addon.component').then((m) => m.ComponentAddonComponent),\n validate: (addon, fieldKey) => {\n const loader = (addon as { component?: unknown }).component;\n if (typeof loader !== 'function') {\n throw new DynamicFormError(`Addon type 'component' requires a 'component' loader function (field: '${fieldKey}').`);\n }\n },\n },\n] as const;\n","import { FieldTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { arrayFieldMapper } from '@ng-forge/dynamic-forms/internal';\nimport { groupFieldMapper } from '@ng-forge/dynamic-forms/internal';\nimport { rowFieldMapper } from '@ng-forge/dynamic-forms/internal';\nimport { pageFieldMapper } from '@ng-forge/dynamic-forms/internal';\nimport { textFieldMapper } from '@ng-forge/dynamic-forms/internal';\nimport { containerFieldMapper } from '@ng-forge/dynamic-forms/internal';\nimport { RowField } from '@ng-forge/dynamic-forms/internal';\nimport { GroupField } from '@ng-forge/dynamic-forms/internal';\nimport { HiddenField } from '@ng-forge/dynamic-forms/internal';\nimport { ArrayField } from '@ng-forge/dynamic-forms/internal';\nimport { PageField } from '@ng-forge/dynamic-forms/internal';\nimport { TextField } from '@ng-forge/dynamic-forms/internal';\nimport { ContainerField } from '@ng-forge/dynamic-forms/internal';\nimport { WrapperTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { CssWrapper } from '@ng-forge/dynamic-forms/internal';\nimport { RowWrapper } from '@ng-forge/dynamic-forms/internal';\nimport { FieldErrorsWrapper } from '@ng-forge/dynamic-forms/internal';\n\n/** Built-in field types provided by the dynamic form library. */\n/**\n * Base for container field types that consume the mapper-emitted `field` input\n * (row, group, array, page, container).\n */\nconst CONTAINER_FIELD_TYPES_BASE = {\n renderReadyWhen: ['field'],\n} as const;\n\n/**\n * Base for display-only fields (`text`) that render immediately without\n * waiting for form value integration.\n */\nconst DISPLAY_FIELD_TYPES_BASE = {\n renderReadyWhen: [],\n} as const;\n\n/** Built-in field types provided by the dynamic form library. */\nexport const BUILT_IN_FIELDS: FieldTypeDefinition[] = [\n {\n name: 'row',\n // `row` is a virtual field type: it maps to ContainerFieldComponent, and\n // the rowFieldMapper injects a `{ type: 'row' }` wrapper so the container\n // renders the flex/grid layout via RowWrapperComponent.\n loadComponent: () => import('../fields/container/container-field.component'),\n mapper: rowFieldMapper,\n valueHandling: 'flatten',\n ...CONTAINER_FIELD_TYPES_BASE,\n } satisfies FieldTypeDefinition<RowField>,\n {\n name: 'group',\n loadComponent: () => import('../fields/group/group-field.component'),\n mapper: groupFieldMapper,\n valueHandling: 'include',\n ...CONTAINER_FIELD_TYPES_BASE,\n } satisfies FieldTypeDefinition<GroupField>,\n {\n name: 'array',\n loadComponent: () => import('../fields/array/array-field.component'),\n mapper: arrayFieldMapper,\n valueHandling: 'include',\n ...CONTAINER_FIELD_TYPES_BASE,\n } satisfies FieldTypeDefinition<ArrayField>,\n {\n name: 'page',\n loadComponent: () => import('../fields/page/page-field.component'),\n mapper: pageFieldMapper,\n valueHandling: 'flatten',\n ...CONTAINER_FIELD_TYPES_BASE,\n } satisfies FieldTypeDefinition<PageField>,\n {\n name: 'text',\n loadComponent: () => import('../fields/text/text-field.component'),\n mapper: textFieldMapper,\n valueHandling: 'exclude',\n ...DISPLAY_FIELD_TYPES_BASE,\n } satisfies FieldTypeDefinition<TextField>,\n {\n name: 'hidden',\n // Componentless field - no loadComponent or mapper needed\n valueHandling: 'include',\n } satisfies FieldTypeDefinition<HiddenField>,\n {\n name: 'container',\n loadComponent: () => import('../fields/container/container-field.component'),\n mapper: containerFieldMapper,\n valueHandling: 'flatten',\n ...CONTAINER_FIELD_TYPES_BASE,\n } satisfies FieldTypeDefinition<ContainerField>,\n];\n\nexport const BUILT_IN_WRAPPERS: WrapperTypeDefinition[] = [\n {\n wrapperName: 'css',\n loadComponent: () => import('../wrappers/css/css-wrapper.component'),\n } satisfies WrapperTypeDefinition<CssWrapper>,\n {\n wrapperName: 'row',\n loadComponent: () => import('../wrappers/row/row-wrapper.component'),\n } satisfies WrapperTypeDefinition<RowWrapper>,\n {\n wrapperName: 'field-errors',\n loadComponent: () => import('../wrappers/field-errors/field-errors-wrapper.component'),\n rendersFieldErrors: true,\n } satisfies WrapperTypeDefinition<FieldErrorsWrapper>,\n];\n","import { LazyComponentLoader, WrapperTypeDefinition } from '@ng-forge/dynamic-forms/internal';\n\n/** User-facing wrapper registration shape used with `createWrappers(...)`. */\nexport interface WrapperRegistration<TName extends string = string, TConfig = unknown> {\n /** Unique identifier for the wrapper type */\n readonly wrapperName: TName;\n /** Lazy-loader for the wrapper component */\n readonly loadComponent: LazyComponentLoader;\n /** Field types this wrapper auto-applies to (merged lowest-priority during wrapper resolution) */\n readonly types?: readonly string[];\n /**\n * Type carrier only — runtime value is always `undefined`.\n * Use `wrapperProps<YourConfig>()` to thread the config type.\n */\n readonly props?: TConfig;\n}\n\n/** Branded bundle returned by `createWrappers(...)`. */\nexport interface WrappersBundle<T extends readonly WrapperRegistration[] = readonly WrapperRegistration[]> {\n readonly ɵkind: 'wrappers';\n readonly ɵregistrations: T;\n readonly ɵdefinitions: readonly WrapperTypeDefinition[];\n}\n\n/**\n * Bundle wrapper registrations into a single object that can be passed to\n * `provideDynamicForm(...)`.\n */\nexport function createWrappers<const T extends readonly WrapperRegistration[]>(...registrations: T): WrappersBundle<T> {\n return {\n ɵkind: 'wrappers',\n ɵregistrations: registrations,\n ɵdefinitions: registrations.map(({ wrapperName, loadComponent, types }) => ({\n wrapperName,\n loadComponent,\n types,\n })),\n };\n}\n\n/** Type guard for a `WrappersBundle`. */\nexport function isWrappersBundle(value: unknown): value is WrappersBundle {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'ɵkind' in value &&\n (value as { ɵkind: unknown }).ɵkind === 'wrappers' &&\n 'ɵdefinitions' in value &&\n Array.isArray((value as { ɵdefinitions: unknown }).ɵdefinitions)\n );\n}\n\n/** Derive the `FieldRegistryWrappers` augmentation shape from a wrapper bundle. */\nexport type InferWrapperRegistry<T> =\n T extends WrappersBundle<infer R>\n ? {\n [Reg in R[number] as Reg['wrapperName']]: Reg extends { props: infer P }\n ? Exclude<P, undefined>\n : { readonly type: Reg['wrapperName'] };\n }\n : never;\n","import { EnvironmentProviders, inject, makeEnvironmentProviders, Provider, Type } from '@angular/core';\nimport { ADDON_TYPE_COMPONENT_CACHE, ADDON_TYPE_REGISTRY, AddonTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { FIELD_REGISTRY, FieldTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { BUILT_IN_ADDON_TYPES } from './built-in-addons';\nimport { BUILT_IN_FIELDS, BUILT_IN_WRAPPERS } from './built-in-fields';\nimport { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormFeature, isDynamicFormFeature } from './features/dynamic-form-feature';\nimport { ADDON_TYPE_DEFINITIONS } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { ConsoleLogger } from './features/logger/console-logger';\nimport type { InferFormValue as RealInferFormValue } from '@ng-forge/dynamic-forms/internal';\nimport {\n isWrapperTypeDefinition,\n WrapperTypeDefinition,\n WRAPPER_AUTO_ASSOCIATIONS,\n WRAPPER_REGISTRY,\n WrapperConfig,\n} from '@ng-forge/dynamic-forms/internal';\nimport { isWrappersBundle, WrappersBundle } from '../wrappers/create-wrappers';\nimport { DEV_MODE } from '../utils/dev-mode';\n\n// Re-export global types for module augmentation\nexport type { DynamicFormFieldRegistry, AvailableFieldTypes } from '@ng-forge/dynamic-forms/internal';\nexport type { RegisteredFieldTypes } from '@ng-forge/dynamic-forms/internal';\n\n/** Extract FieldDef type from FieldTypeDefinition */\ntype ExtractFieldDef<T> = T extends FieldTypeDefinition<infer F> ? F : never;\n\n/** Union of all FieldDef types from provided field types */\ntype FieldDefUnion<T extends FieldTypeDefinition[]> = ExtractFieldDef<T[number]>;\n\n/** Infer form value type from field definitions using the real inference type. */\ntype InferFormValue<TFieldDefs extends FieldDef<unknown>[]> = RealInferFormValue<TFieldDefs>;\n\n/** Provider result with type inference */\ntype ProvideDynamicFormResult<T extends FieldTypeDefinition[]> = EnvironmentProviders & {\n __fieldDefs?: FieldDefUnion<T>;\n __formValue?: InferFormValue<FieldDefUnion<T>[]>;\n};\n\n/** Union type for items that can be passed to provideDynamicForm */\ntype FieldTypeOrFeature = FieldTypeDefinition | WrapperTypeDefinition | WrappersBundle | DynamicFormFeature;\n\n/** Extract only FieldTypeDefinition items from a tuple type */\ntype ExtractFieldTypes<T extends FieldTypeOrFeature[]> = {\n [K in keyof T]: T[K] extends FieldTypeDefinition ? T[K] : never;\n}[number] extends infer U\n ? U extends FieldTypeDefinition\n ? U[]\n : never\n : never;\n\n/**\n * Provider function to configure the dynamic form system with field types and options.\n *\n * @param items - Field type definitions and/or features (like withLoggerConfig)\n * @returns Environment providers for dependency injection with type inference\n * @typeParam T - Array of field type definitions for type inference\n */\nexport function provideDynamicForm<const T extends FieldTypeOrFeature[]>(\n ...items: T\n): ProvideDynamicFormResult<ExtractFieldTypes<T> extends FieldTypeDefinition[] ? ExtractFieldTypes<T> : FieldTypeDefinition[]> {\n // Separate field types, wrapper types, wrapper bundles, and features\n const fieldTypes = items.filter(\n (item): item is FieldTypeDefinition => !isDynamicFormFeature(item) && !isWrapperTypeDefinition(item) && !isWrappersBundle(item),\n );\n const wrapperTypes = items.filter(isWrapperTypeDefinition);\n const wrapperBundles = items.filter(isWrappersBundle);\n const features = items.filter(isDynamicFormFeature);\n\n const fields = [...BUILT_IN_FIELDS, ...fieldTypes];\n const customWrappers = [...wrapperTypes, ...wrapperBundles.flatMap((bundle) => bundle.ɵdefinitions)];\n const wrappers = [...BUILT_IN_WRAPPERS, ...customWrappers];\n\n // Extract providers from features (includes config features like material-config, bootstrap-config, etc.)\n const featureProviders: Provider[] = [];\n const hasLoggerFeature = features.some((feature) => feature.ɵkind === 'logger');\n features.forEach((feature) => {\n featureProviders.push(...feature.ɵproviders);\n });\n\n // Default logger provider (ConsoleLogger) if no logger feature was provided\n const defaultLoggerProvider: Provider[] = hasLoggerFeature ? [] : [{ provide: DynamicFormLogger, useValue: new ConsoleLogger() }];\n\n return makeEnvironmentProviders([\n ...defaultLoggerProvider,\n {\n provide: FIELD_REGISTRY,\n useFactory: () => {\n const logger = inject(DynamicFormLogger);\n const registry = new Map();\n // Add custom field types\n fields.forEach((fieldType) => {\n // Collision report only — last registration wins either way.\n if (DEV_MODE && registry.has(fieldType.name)) {\n logger.warn(`Field type \"${fieldType.name}\" is already registered. Overwriting.`);\n }\n registry.set(fieldType.name, fieldType);\n });\n // Back-compat: legacy camelCase array-action discriminants resolve to their\n // kebab-case canonical definitions. kebab is canonical as of 1.0; the camelCase\n // spellings are deprecated aliases kept so older/serialized configs keep working.\n const legacyTypeAliases: Record<string, string> = {\n addArrayItem: 'add-array-item',\n prependArrayItem: 'prepend-array-item',\n insertArrayItem: 'insert-array-item',\n removeArrayItem: 'remove-array-item',\n popArrayItem: 'pop-array-item',\n shiftArrayItem: 'shift-array-item',\n };\n for (const [legacy, canonical] of Object.entries(legacyTypeAliases)) {\n const def = registry.get(canonical);\n if (def && !registry.has(legacy)) registry.set(legacy, def);\n }\n return registry;\n },\n },\n // Always provide default Wrapper classes\n {\n provide: WRAPPER_REGISTRY,\n useFactory: () => {\n const logger = inject(DynamicFormLogger);\n const registry = new Map();\n // Seed the built-ins, then let later registrations replace them. Overriding a\n // built-in name is supported — an adapter restyles `field-errors` that way,\n // and an app may then override the adapter's — so those never warn. Only two\n // custom registrations colliding on a name of their own is a mistake.\n const builtInNames = new Set(BUILT_IN_WRAPPERS.map((w) => w.wrapperName));\n BUILT_IN_WRAPPERS.forEach((wrapperType) => registry.set(wrapperType.wrapperName, wrapperType));\n\n // `seenCustom` exists only to report duplicates — last registration wins either way.\n const seenCustom = DEV_MODE ? new Set<string>() : null;\n customWrappers.forEach((wrapperType) => {\n const name = wrapperType.wrapperName;\n if (seenCustom) {\n if (seenCustom.has(name) && !builtInNames.has(name)) {\n logger.warn(`Wrapper type \"${name}\" is already registered. Overwriting.`);\n }\n seenCustom.add(name);\n }\n registry.set(name, wrapperType);\n });\n return registry;\n },\n },\n // Pre-computed reverse index for auto-association lookup — built once so\n // resolveWrappers is O(1) per field render instead of scanning every\n // registered wrapper.\n {\n provide: WRAPPER_AUTO_ASSOCIATIONS,\n useFactory: () => {\n const autoMap = new Map<string, WrapperConfig[]>();\n for (const wrapperType of wrappers) {\n if (!wrapperType.types) continue;\n for (const fieldType of wrapperType.types) {\n const existing = autoMap.get(fieldType) ?? [];\n existing.push({ type: wrapperType.wrapperName } as WrapperConfig);\n autoMap.set(fieldType, existing);\n }\n }\n return autoMap;\n },\n },\n // Form-scoped addon type registry. Built from BUILT_IN_ADDON_TYPES plus\n // every kind contributed by `withCustomAddon(...)` features (via the\n // ADDON_TYPE_DEFINITIONS multi-provider). Overrides the empty\n // `providedIn: 'root'` default so contributions from form-scoped\n // providers are visible.\n {\n provide: ADDON_TYPE_REGISTRY,\n useFactory: () => {\n const logger = inject(DynamicFormLogger);\n const contributed = inject(ADDON_TYPE_DEFINITIONS, { optional: true }) ?? [];\n const registry = new Map<string, AddonTypeDefinition>();\n for (const def of BUILT_IN_ADDON_TYPES) {\n registry.set(def.type, def);\n }\n for (const def of contributed) {\n // Collision report only — last registration wins either way.\n if (DEV_MODE && registry.has(def.type)) {\n logger.warn(`Addon type \"${def.type}\" is already registered. Overwriting.`);\n }\n registry.set(def.type, def);\n }\n return registry;\n },\n },\n // Per-form addon-component cache (no root fallback — isolated by form scope).\n { provide: ADDON_TYPE_COMPONENT_CACHE, useFactory: () => new Map<string, Type<unknown>>() },\n ...featureProviders,\n ]) as ProvideDynamicFormResult<ExtractFieldTypes<T> extends FieldTypeDefinition[] ? ExtractFieldTypes<T> : FieldTypeDefinition[]>;\n}\n\n/** Extract FieldDef types from provider result */\nexport type ExtractFieldDefs<T> = T extends { __fieldDefs?: infer F } ? F : never;\n\n/** Extract form value type from provider result */\nexport type ExtractFormValue<T> = T extends { __formValue?: infer V } ? V : never;\n","import { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { EMIT_FORM_VALUE_ON_EVENTS } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Enables automatic form value attachment to all events dispatched through the EventBus.\n *\n * @remarks\n * **Precedence rules:**\n * 1. Per-form `false` - Disables for this form, regardless of global setting\n * 2. Per-form `true` - Enables for this form, regardless of global setting\n * 3. Per-form `undefined` - Uses global setting\n * 4. Global `withEventFormValue()` - Enables globally\n * 5. No global feature - Disabled globally (default)\n * @returns A DynamicFormFeature that enables form value attachment to events\n */\nexport function withEventFormValue(): DynamicFormFeature<'event-form-value'> {\n return createFeature('event-form-value', [{ provide: EMIT_FORM_VALUE_ON_EVENTS, useValue: true }]);\n}\n","import { ValueExclusionConfig } from '@ng-forge/dynamic-forms/internal';\nimport { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { VALUE_EXCLUSION_DEFAULTS } from './value-exclusion.token';\n\n/**\n * Configures global value exclusion defaults for form submission output.\n *\n * @remarks\n * **Precedence rules:**\n * 1. Per-field `excludeValueIf*` on `FieldDef` — wins for that field\n * 2. Per-form `excludeValueIf*` on `FormOptions` — wins for all fields in that form\n * 3. Global `withValueExclusionDefaults()` — baseline default\n * 4. No global feature — uses token default (all enabled)\n * @param config - Partial override of exclusion rules. Unspecified properties default to `true`.\n * @returns A DynamicFormFeature that configures value exclusion defaults\n */\nexport function withValueExclusionDefaults(config?: Partial<ValueExclusionConfig>): DynamicFormFeature<'value-exclusion'> {\n const resolved = {\n excludeValueIfHidden: config?.excludeValueIfHidden ?? true,\n excludeValueIfDisabled: config?.excludeValueIfDisabled ?? true,\n excludeValueIfReadonly: config?.excludeValueIfReadonly ?? true,\n };\n\n return createFeature('value-exclusion', [{ provide: VALUE_EXCLUSION_DEFAULTS, useValue: resolved }]);\n}\n","import { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { clampWindowSize } from '../clamp-window';\nimport { PAGE_PRELOAD_WINDOW } from './page-preload.token';\n\n/**\n * Configures the global page preload window for paged forms — how many pages on\n * each side of the current page are mounted during browser idle time.\n *\n * @remarks\n * Paged forms only ever display one page at a time, so mounting every page (the\n * fields, containers, and change-detection of pages the user may never reach)\n * is wasted work: it inflates initial-render time and makes every keystroke pay\n * change detection for off-screen pages. The preload window bounds how much is\n * mounted around the current page. The active page always renders directly;\n * eligible neighbours render on idle. Pages outside the window remain lightweight\n * placeholders until navigation or a window change makes them eligible.\n *\n * **Precedence:**\n * 1. Per-form `pagePreloadWindow` on `FormOptions` — wins for that form\n * 2. Global `withPagePreload(n)` — baseline default for all forms\n * 3. No feature — token default (`1`, i.e. current page ±1)\n *\n * @param window - Pages to preload on idle on each side of the current page. `0`\n * mounts only the current page; `1` (default) mounts ±1 for flicker-free sequential\n * navigation; higher values pre-warm more pages for jump navigation. Negative\n * values are clamped to `0`.\n * @returns A DynamicFormFeature that configures the global preload window\n *\n * @example\n * ```typescript\n * provideDynamicForm(...withMaterialFields(), withPagePreload(2));\n * ```\n */\nexport function withPagePreload(window: number): DynamicFormFeature<'page-preload'> {\n const resolved = clampWindowSize(window, 1);\n return createFeature('page-preload', [{ provide: PAGE_PRELOAD_WINDOW, useValue: resolved }]);\n}\n","import { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { clampWindowSize } from '../clamp-window';\nimport { FIELD_WINDOWING, FieldWindowingConfig } from './field-windowing.token';\nimport { FieldParkingOption, resolveFieldParking } from './resolve-field-windowing';\n\n/**\n * Configures global progressive field mounting (\"field windowing\") for large\n * flat (single-page) forms.\n *\n * @remarks\n * A flat form mounts every field eagerly, so a large form pays the full\n * initial-render cost up front and every keystroke walks all N live views —\n * even for fields far off-screen. Field windowing bounds how much is mounted:\n * the first `eager` fields render immediately, and the rest render as a\n * lightweight placeholder that mounts the moment it scrolls near/into view.\n * Validators, derivations, and values live at the Signal Forms schema level\n * (not the DOM), so unmounted fields keep full form semantics.\n *\n * Mounting is one-way — `@defer (on viewport)` never unmounts — so on its own\n * that bound is temporary: scroll a long form once and every field is live\n * again for the rest of the session. **Parking** closes the gap and comes on\n * with this feature (it is off when the feature is not used, since it changes\n * rendering behaviour). A field scrolled outside `park.margin` leaves change detection but\n * keeps its DOM, so it costs nothing per keystroke while staying findable by\n * browser search, fillable by autofill, and reachable by assistive tech. Its\n * own edits still reach the model: Angular binds `input` / `blur` with plain\n * DOM listeners, which keep firing on a detached view.\n *\n * **Precedence:**\n * 1. Per-form `fieldWindowing` on `FormOptions` — wins for that form\n * 2. Global `withFieldWindowing(...)` — baseline default for all forms\n * 3. No feature — token default (disabled, i.e. fully eager)\n *\n * @param config - `eager` (default `12`), `placeholderHeight` (default `'4rem'`)\n * and `park` (default on, margin `'100%'`) overrides. `eager` is clamped to a\n * non-negative integer.\n * @returns A DynamicFormFeature that enables the global field windowing default\n *\n * @example\n * ```typescript\n * provideDynamicForm(...withMaterialFields(), withFieldWindowing({ eager: 20 }));\n * ```\n */\nexport function withFieldWindowing(config?: {\n eager?: number;\n placeholderHeight?: string;\n park?: FieldParkingOption;\n}): DynamicFormFeature<'field-windowing'> {\n const resolved: FieldWindowingConfig = {\n enabled: true,\n eager: clampWindowSize(config?.eager, 12),\n placeholderHeight: config?.placeholderHeight ?? '4rem',\n park: resolveFieldParking({ enabled: true, margin: '100%' }, config?.park),\n };\n\n return createFeature('field-windowing', [{ provide: FIELD_WINDOWING, useValue: resolved }]);\n}\n","import { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { WEB_MCP_ENABLED } from './web-mcp.token';\n\n/**\n * Enables WebMCP tool registration for forms that declare `options.webMcp`.\n *\n * @experimental\n *\n * @remarks\n * WebMCP lets an AI agent running in the browser discover and drive a form\n * through structured tools rather than by simulating clicks. Each opted-in form\n * registers `fill_{name}`, which applies a partial patch of values to the form\n * and reports back what it set, which fields apply, which are still empty, and\n * any validation errors. Submission is a separate, per-form opt-in\n * (`options.webMcp.allowSubmit`); without it the agent stages values and a human\n * presses the button.\n *\n * The tool schema is generated from the form config, so agents see labels,\n * option enums with their human titles, and static validator constraints rather\n * than the bare types value-shape inference would produce. Agent arguments are\n * validated in code before anything is written, and a call that does not parse\n * is rejected whole rather than half-applied.\n *\n * Nothing is registered unless a form opts in, and the registrar module is\n * dynamically imported, so a form without `options.webMcp` never loads it — the\n * feature itself, the token and the form-scoped hook that decides are part of\n * the main bundle. Registration is browser-only and no-ops where the page\n * exposes no model context.\n *\n * Named `experimental` on purpose: WebMCP is a proposed standard, in an origin\n * trial as of Chrome 149, and the browser surface underneath this may still\n * change. Expect breaking changes outside a major version.\n *\n * @returns A DynamicFormFeature enabling WebMCP registration.\n *\n * @example\n * ```typescript\n * provideDynamicForm(...withMaterialFields(), withExperimentalWebMcp());\n *\n * const config = {\n * options: { webMcp: { name: 'signup', description: 'Sign a new user up.' } },\n * fields: [...],\n * } as const satisfies FormConfig;\n * ```\n */\nexport function withExperimentalWebMcp(): DynamicFormFeature<'web-mcp'> {\n return createFeature('web-mcp', [{ provide: WEB_MCP_ENABLED, useValue: true }]);\n}\n","import { ResolvedValidationExecutionConfig, ValidationExecutionConfig } from '@ng-forge/dynamic-forms/internal';\nimport { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { VALIDATION_EXECUTION_DEFAULTS } from './validation-execution.token';\n\n/**\n * Configures global validation execution defaults — when validators should run\n * relative to a field's reactive state.\n *\n * @remarks\n * **Precedence rules:**\n * 1. Per-field `FieldDef.validateWhenHidden` — wins for that field; inherits down to descendants\n * that don't override.\n * 2. Per-form `FormOptions.validateWhenHidden` — root inherited value for the form.\n * 3. Global `withValidationExecutionDefaults()` — fallback when no form/field setting.\n * 4. No feature configured — uses token default (`validateWhenHidden: false`).\n * @param config - Partial override. Unspecified properties keep their defaults.\n * @returns A `DynamicFormFeature` that configures validation execution defaults.\n */\nexport function withValidationExecutionDefaults(config?: Partial<ValidationExecutionConfig>): DynamicFormFeature<'validation-execution'> {\n const resolved: ResolvedValidationExecutionConfig = {\n validateWhenHidden: config?.validateWhenHidden ?? false,\n };\n\n return createFeature('validation-execution', [{ provide: VALIDATION_EXECUTION_DEFAULTS, useValue: resolved }]);\n}\n","import { provideSignalFormsConfig } from '@angular/forms/signals';\nimport { NG_STATUS_CLASSES } from '@angular/forms/signals/compat';\nimport { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\n\n/**\n * Opt into Angular Signal Forms' legacy `.ng-touched` / `.ng-invalid` /\n * `.ng-dirty` / `.ng-pristine` / `.ng-untouched` / `.ng-pending` /\n * `.ng-valid` CSS classes on form-bound elements.\n *\n * @returns A DynamicFormFeature that enables the legacy `ng-*` class strategy\n */\nexport function withLegacyStatusClasses(): DynamicFormFeature<'legacy-status-classes'> {\n return createFeature('legacy-status-classes', [...provideSignalFormsConfig({ classes: NG_STATUS_CLASSES })]);\n}\n","/** Zero-cost type carrier used in wrapper registrations. */\nexport function wrapperProps<T>(): T {\n return undefined as unknown as T;\n}\n","import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { TextAddon } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/internal';\nimport { WrapperFieldInputs } from '@ng-forge/dynamic-forms/internal';\n\n/** Renderer for the universal `text` addon type. */\n@Component({\n selector: 'df-text-addon',\n imports: [AsyncPipe, DynamicTextPipe],\n template: `<span>{{ addon().text | dynamicText | async }}</span>`,\n host: {\n '[attr.aria-hidden]': '\"true\"',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TextAddonComponent {\n readonly addon = input.required<TextAddon>();\n /** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every kind must declare it. */\n readonly fieldInputs = input<WrapperFieldInputs | undefined>();\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { TemplateAddon } from '@ng-forge/dynamic-forms/internal';\nimport { DF_FIELD_TEMPLATES } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { WrapperFieldInputs } from '@ng-forge/dynamic-forms/internal';\n\n/** Renderer for the universal `template` addon type. */\n@Component({\n selector: 'df-template-addon',\n imports: [NgTemplateOutlet],\n template: `\n @if (template(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: outletContext()\" />\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TemplateAddonComponent {\n private readonly templates = inject(DF_FIELD_TEMPLATES, { optional: true });\n private readonly logger = inject(DynamicFormLogger);\n\n readonly addon = input.required<TemplateAddon>();\n /** Forwarded by `df-addon-slot`; surfaced to the template as its implicit `$implicit` context. */\n readonly fieldInputs = input<WrapperFieldInputs | undefined>();\n\n // Pure computed: pure lookup, no side effects. Unresolved → null; the\n // `@if` in the template skips the outlet and renders nothing.\n protected readonly template = computed(() => {\n const map = this.templates?.();\n const key = this.addon().templateKey;\n return map?.get(key) ?? null;\n });\n\n /** Implicit context payload — template authors bind via `let-fi`. */\n protected readonly outletContext = computed(() => ({ $implicit: this.fieldInputs() }));\n\n constructor() {\n // Logging side effect lives in an effect, not the computed — keeps\n // the computed pure so signal-graph evaluations don't duplicate warnings.\n explicitEffect([this.template, this.addon], ([tpl, addon]) => {\n if (!tpl) {\n this.logger.warn(\n `Template addon: no <ng-template dfTemplate=\"${addon.templateKey}\"> found. Did you project it as a child of <df-dynamic-form>?`,\n );\n }\n });\n }\n}\n","import { NgComponentOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, inject, input, signal, Type } from '@angular/core';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport type { ComponentAddon } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { resolveDefaultExport } from '../utils/wrapper-chain/wrapper-chain';\nimport type { WrapperFieldInputs } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Renderer for the universal `component` addon type.\n *\n * @codeOnly The `component` loader is a function; this kind is dropped in\n * lenient validation when the config originated from JSON.\n */\n@Component({\n selector: 'df-component-addon',\n imports: [NgComponentOutlet],\n template: `\n @if (resolvedComponent(); as cmp) {\n <ng-container *ngComponentOutlet=\"cmp; inputs: inputs()\" />\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ComponentAddonComponent {\n private readonly logger = inject(DynamicFormLogger);\n\n readonly addon = input.required<ComponentAddon>();\n /** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every kind must declare it. */\n readonly fieldInputs = input<WrapperFieldInputs | undefined>();\n\n protected readonly inputs = computed(() => (this.addon().inputs ?? {}) as Record<string, unknown>);\n\n /**\n * Latest async-loaded `{ addon, component }` pair. Tagging the result with\n * its source addon lets `resolvedComponent` filter stale loads structurally\n * — same kind-tagging pattern `DfAddonSlot` uses. When `addon` swaps\n * mid-load, the prior loader still completes and writes here, but the\n * computed ignores it because the recorded addon no longer matches the\n * current one.\n */\n private readonly asyncLoaded = signal<{ addon: ComponentAddon; component: Type<unknown> } | undefined>(undefined);\n\n protected readonly resolvedComponent = computed<Type<unknown> | undefined>(() => {\n const current = this.addon();\n const loaded = this.asyncLoaded();\n return loaded?.addon === current ? loaded.component : undefined;\n });\n\n constructor() {\n explicitEffect([this.addon], ([addon]) => {\n Promise.resolve(addon.component())\n .then((mod) => {\n const component = resolveDefaultExport(mod);\n if (component) this.asyncLoaded.set({ addon, component });\n })\n .catch((error: unknown) => {\n this.logger.warn(\n `Failed to load component addon (slot: '${addon.slot}'): ${error instanceof Error ? error.message : String(error)}`,\n );\n });\n });\n }\n}\n","import { AddonTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { BaseAddon } from '@ng-forge/dynamic-forms/internal';\nimport { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { ADDON_TYPE_DEFINITIONS } from '@ng-forge/dynamic-forms/internal';\n\n/** Register a custom addon type with the form. */\nexport function withCustomAddon<T extends BaseAddon>(definition: AddonTypeDefinition<T>): DynamicFormFeature<'addons'> {\n return createFeature('addons', [\n {\n provide: ADDON_TYPE_DEFINITIONS,\n useValue: definition as AddonTypeDefinition,\n multi: true,\n },\n ]);\n}\n","import { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { AddonActionHandler, ADDON_ACTION_HANDLERS } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Typed feature returned by {@link withAddonActions}. Carries the\n * registered handler keys as a phantom type so consumers can derive the\n * `DynamicFormActionRegistry` augmentation in one line instead of hand-typing\n * every key.\n */\nexport type AddonActionsFeature<K extends string = string> = DynamicFormFeature<'addon-actions'> & {\n /** @internal Phantom field carrying the registered keys; never read at runtime. */\n readonly __handlerKeys?: K;\n};\n\n/** Register named action handlers reachable via JSON-driven addon configs. */\nexport function withAddonActions<const H extends Record<string, AddonActionHandler>>(handlers: H): AddonActionsFeature<keyof H & string> {\n return createFeature('addon-actions', [\n {\n provide: ADDON_ACTION_HANDLERS,\n useValue: handlers,\n multi: true,\n },\n ]) as AddonActionsFeature<keyof H & string>;\n}\n","import { inject } from '@angular/core';\nimport { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { ADDON_TYPE_REGISTRY } from '@ng-forge/dynamic-forms/internal';\nimport { FormConfig } from '@ng-forge/dynamic-forms/internal';\nimport { FIELD_REGISTRY } from '@ng-forge/dynamic-forms/internal';\nimport { Logger } from '@ng-forge/dynamic-forms/internal';\nimport { AddonWarning, formatAddonWarning } from './addon-warning';\nimport { walkAndValidateAddons } from './validate-field-addons';\n\n/** Options accepted by {@link sanitizeFormConfig}. */\nexport interface SanitizeFormConfigOptions {\n /**\n * Whether the config originated from JSON (server-driven) or inline\n * TypeScript code.\n */\n source?: 'json' | 'inline';\n}\n\n/** Result of a `sanitizeFormConfig` call. */\nexport interface SanitizedFormConfig {\n /** Sanitized config — invalid addons stripped from the field tree. */\n sanitized: FormConfig;\n /** Structured list of every addon that was dropped, and why. */\n warnings: readonly AddonWarning[];\n}\n\n/**\n * Walk a `FormConfig`, validate every field's addons against the active\n * `FIELD_REGISTRY` and `ADDON_TYPE_REGISTRY`, and return a sanitized copy\n * plus a list of dropped-addon warnings.\n *\n * @Component({ ... })\n * class AdminFormBuilder {\n * private readonly check = (cfg: FormConfig) => {\n * const { sanitized, warnings } = sanitizeFormConfig(cfg, { source: 'json' });\n * if (warnings.length > 0) {\n * this.diagnostics.set(warnings);\n * }\n * return sanitized;\n * };\n * }\n * ```\n */\nexport function sanitizeFormConfig(config: FormConfig, options: SanitizeFormConfigOptions = {}): SanitizedFormConfig {\n const fieldRegistry = inject(FIELD_REGISTRY);\n const typeRegistry = inject(ADDON_TYPE_REGISTRY);\n const source = options.source ?? 'inline';\n\n const { fields, warnings } = walkAndValidateAddons(\n (config.fields ?? []) as readonly FieldDef<unknown>[],\n fieldRegistry,\n typeRegistry,\n source,\n );\n\n return {\n sanitized: { ...config, fields: fields as FormConfig['fields'] },\n warnings,\n };\n}\n\n/**\n * Default warning sink. Pass a `DynamicFormLogger` to route through the\n * form's configured logger (respects `NoopLogger` opt-out); omit it to\n * fall back to `console.warn` for build-time / admin-UI use cases that\n * run outside an Angular injection context.\n */\nexport function logAddonWarnings(warnings: readonly AddonWarning[], logger?: Logger): void {\n for (const w of warnings) {\n if (logger) {\n logger.warn(formatAddonWarning(w));\n } else {\n console.warn('[Dynamic Forms]', formatAddonWarning(w));\n }\n }\n}\n\n/**\n * DI-free variant of {@link sanitizeFormConfig} for tooling that lives\n * outside Angular's injector — build-time linters, MCP-side checks, CLI\n * scripts.\n */\nexport function sanitizeFormConfigPure(\n config: FormConfig,\n fieldRegistry: ReadonlyMap<string, import('@ng-forge/dynamic-forms/internal').FieldTypeDefinition>,\n typeRegistry: ReadonlyMap<string, import('@ng-forge/dynamic-forms/internal').AddonTypeDefinition>,\n options: SanitizeFormConfigOptions = {},\n): SanitizedFormConfig {\n const source = options.source ?? 'inline';\n const { fields, warnings } = walkAndValidateAddons(\n (config.fields ?? []) as readonly FieldDef<unknown>[],\n fieldRegistry,\n typeRegistry,\n source,\n );\n return { sanitized: { ...config, fields: fields as FormConfig['fields'] }, warnings };\n}\n\nexport { formatAddonWarning } from './addon-warning';\nexport type { AddonWarning } from './addon-warning';\nexport { validateFieldAddons, walkAndValidateAddons } from './validate-field-addons';\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Per-dispatch overrides for a page jump. */\nexport interface PageNavigationOptions {\n /**\n * Whether to apply the forward-jump validity gate.\n *\n * Set `false` to land on the target regardless of earlier pages, which is what\n * restoring a saved session wants. Bounds and hidden-page checks still apply.\n *\n * @default true\n */\n validate?: boolean;\n}\n\n/**\n * Event dispatched to move a paged form to a specific page.\n *\n * Backward jumps are unconditional. Forward jumps validate every visible page\n * between the current one and the target (the target itself is not validated);\n * if one is invalid, navigation stops on the first invalid page. Pass\n * `{ validate: false }` to skip that gate and land on the target.\n */\nexport class GoToPageEvent implements FormEvent {\n readonly type = 'go-to-page' as const;\n\n constructor(\n /** The target page index (0-based) */\n public readonly pageIndex: number,\n /** Per-dispatch overrides; omit for the default gated behavior. */\n public readonly options?: PageNavigationOptions,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched to advance a paged form to the next page. */\nexport class NextPageEvent implements FormEvent {\n readonly type = 'next-page' as const;\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched to return a paged form to the previous page. */\nexport class PreviousPageEvent implements FormEvent {\n readonly type = 'previous-page' as const;\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched when the form should be reset to its default values. */\nexport class FormResetEvent implements FormEvent {\n readonly type = 'form-reset' as const;\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched when the form should be cleared. */\nexport class FormClearEvent implements FormEvent {\n readonly type = 'form-clear' as const;\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\nimport { ArrayItemDefinition, ArrayItemTemplate } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Template type for array items used in events.\n * Canonical definition lives in {@link ArrayItemDefinition} — this alias\n * preserves the events-specific naming convention.\n */\nexport type ArrayItemDefinitionTemplate = ArrayItemDefinition;\n\n// Re-export the canonical ArrayItemTemplate for backwards-compatible event API surface\nexport type { ArrayItemTemplate };\n\n/**\n * Event dispatched to append a new item at the END of an array field.\n *\n * @typeParam TTemplate - The type of the template (single field or array of fields)\n */\nexport class AppendArrayItemEvent<TTemplate extends ArrayItemDefinitionTemplate = ArrayItemDefinitionTemplate> implements FormEvent {\n readonly type = 'append-array-item' as const;\n\n constructor(\n /** The key of the array field to append an item to */\n public readonly arrayKey: string,\n /**\n * Template for the new array item. REQUIRED.\n * - Single field (FieldDef): Creates a primitive item (field's value is extracted directly)\n * - Array of fields (FieldDef[]): Creates an object item (fields merged into object)\n */\n public readonly template: TTemplate,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\nimport { ArrayItemDefinitionTemplate } from './append-array-item.event';\n\n/**\n * Event dispatched to prepend a new item at the BEGINNING of an array field.\n *\n * @typeParam TTemplate - The type of the template (single field or array of fields)\n */\nexport class PrependArrayItemEvent<TTemplate extends ArrayItemDefinitionTemplate = ArrayItemDefinitionTemplate> implements FormEvent {\n readonly type = 'prepend-array-item' as const;\n\n constructor(\n /** The key of the array field to prepend an item to */\n public readonly arrayKey: string,\n /**\n * Template for the new array item. REQUIRED.\n * - Single field (FieldDef): Creates a primitive item (field's value is extracted directly)\n * - Array of fields (FieldDef[]): Creates an object item (fields merged into object)\n */\n public readonly template: TTemplate,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\nimport { ArrayItemDefinitionTemplate } from './append-array-item.event';\n\n/**\n * Event dispatched to insert a new item at a SPECIFIC INDEX in an array field.\n *\n * @typeParam TTemplate - The type of the template (single field or array of fields)\n */\nexport class InsertArrayItemEvent<TTemplate extends ArrayItemDefinitionTemplate = ArrayItemDefinitionTemplate> implements FormEvent {\n readonly type = 'insert-array-item' as const;\n\n constructor(\n /** The key of the array field to insert an item into */\n public readonly arrayKey: string,\n /** The index at which to insert the new item */\n public readonly index: number,\n /**\n * Template for the new array item. REQUIRED.\n * - Single field (FieldDef): Creates a primitive item (field's value is extracted directly)\n * - Array of fields (FieldDef[]): Creates an object item (fields merged into object)\n */\n public readonly template: TTemplate,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched to remove the LAST item from an array field. */\nexport class PopArrayItemEvent implements FormEvent {\n readonly type = 'pop-array-item' as const;\n\n constructor(\n /** The key of the array field to remove the last item from */\n public readonly arrayKey: string,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched to remove the FIRST item from an array field. */\nexport class ShiftArrayItemEvent implements FormEvent {\n readonly type = 'shift-array-item' as const;\n\n constructor(\n /** The key of the array field to remove the first item from */\n public readonly arrayKey: string,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched to move an existing item from one index to another within an array field. */\nexport class MoveArrayItemEvent implements FormEvent {\n readonly type = 'move-array-item' as const;\n\n constructor(\n /** The key of the array field containing the item to move */\n public readonly arrayKey: string,\n /** The current index of the item to move */\n public readonly fromIndex: number,\n /** The target index to move the item to */\n public readonly toIndex: number,\n ) {}\n}\n","import { FormEvent } from '@ng-forge/dynamic-forms/internal';\n\n/** Event dispatched to remove an item at a SPECIFIC INDEX from an array field. */\nexport class RemoveAtIndexEvent implements FormEvent {\n readonly type = 'remove-at-index' as const;\n\n constructor(\n /** The key of the array field to remove an item from */\n public readonly arrayKey: string,\n /** The index of the item to remove */\n public readonly index: number,\n ) {}\n}\n","import { AppendArrayItemEvent, ArrayItemDefinitionTemplate } from './constants/append-array-item.event';\nimport { PrependArrayItemEvent } from './constants/prepend-array-item.event';\nimport { InsertArrayItemEvent } from './constants/insert-array-item.event';\nimport { MoveArrayItemEvent } from './constants/move-array-item.event';\nimport { PopArrayItemEvent } from './constants/pop-array-item.event';\nimport { ShiftArrayItemEvent } from './constants/shift-array-item.event';\nimport { RemoveAtIndexEvent } from './constants/remove-at-index.event';\n\n/**\n * Builder for array manipulation events.\n *\n * @param arrayKey - The key of the array field to operate on\n * @returns An object with methods for all 7 array operations\n */\nexport function arrayEvent(arrayKey: string) {\n return {\n /**\n * Append a new item at the END of the array.\n * This is the most common operation for adding items.\n *\n * @param template - Template for the new item (REQUIRED)\n * - Single field: Creates a primitive item (field's value is extracted directly)\n * - Array of fields: Creates an object item (fields merged into object)\n * @returns An AppendArrayItemEvent to dispatch\n */\n append: <T extends ArrayItemDefinitionTemplate>(template: T) => new AppendArrayItemEvent(arrayKey, template),\n\n /**\n * Prepend a new item at the BEGINNING of the array.\n * Use when new items should appear at the start.\n *\n * @param template - Template for the new item (REQUIRED)\n * - Single field: Creates a primitive item (field's value is extracted directly)\n * - Array of fields: Creates an object item (fields merged into object)\n * @returns A PrependArrayItemEvent to dispatch\n */\n prepend: <T extends ArrayItemDefinitionTemplate>(template: T) => new PrependArrayItemEvent(arrayKey, template),\n\n /**\n * Insert a new item at a SPECIFIC INDEX in the array.\n * Use when you need precise control over item placement.\n *\n * @param index - The position at which to insert the new item\n * @param template - Template for the new item (REQUIRED)\n * - Single field: Creates a primitive item (field's value is extracted directly)\n * - Array of fields: Creates an object item (fields merged into object)\n * @returns An InsertArrayItemEvent to dispatch\n */\n insertAt: <T extends ArrayItemDefinitionTemplate>(index: number, template: T) => new InsertArrayItemEvent(arrayKey, index, template),\n\n /**\n * Remove the LAST item from the array.\n * Equivalent to JavaScript's `Array.pop()`.\n *\n * @returns A PopArrayItemEvent to dispatch\n */\n pop: () => new PopArrayItemEvent(arrayKey),\n\n /**\n * Remove the FIRST item from the array.\n * Equivalent to JavaScript's `Array.shift()`.\n *\n * @returns A ShiftArrayItemEvent to dispatch\n */\n shift: () => new ShiftArrayItemEvent(arrayKey),\n\n /**\n * Remove an item at a SPECIFIC INDEX from the array.\n * Use when you need to remove a specific item by position.\n *\n * @param index - The position of the item to remove\n * @returns A RemoveAtIndexEvent to dispatch\n */\n removeAt: (index: number) => new RemoveAtIndexEvent(arrayKey, index),\n\n /**\n * Move an existing item from one position to another within the array.\n * This is an atomic reorder — the item is NOT destroyed and recreated.\n * The resolved component, form value, and stored template are preserved.\n *\n * @param from - The current index of the item to move\n * @param to - The target index to move the item to\n * @returns A MoveArrayItemEvent to dispatch\n */\n move: (from: number, to: number) => new MoveArrayItemEvent(arrayKey, from, to),\n };\n}\n"],"mappings":"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"}
|