@ng-forge/dynamic-forms 1.3.0-next.2 → 1.3.0-next.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-bnrwNw7Y.mjs +156 -0
  2. package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-bnrwNw7Y.mjs.map +1 -0
  3. package/fesm2022/ng-forge-dynamic-forms-array-field.component-Dv9mPnJ3.mjs +770 -0
  4. package/fesm2022/ng-forge-dynamic-forms-array-field.component-Dv9mPnJ3.mjs.map +1 -0
  5. package/fesm2022/ng-forge-dynamic-forms-array-item-registry.service-D-AxVLdk.mjs +83 -0
  6. package/fesm2022/ng-forge-dynamic-forms-array-item-registry.service-D-AxVLdk.mjs.map +1 -0
  7. package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-B6WH0Etk.mjs +1887 -0
  8. package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-B6WH0Etk.mjs.map +1 -0
  9. package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-VjJn-JeD.mjs +954 -0
  10. package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-VjJn-JeD.mjs.map +1 -0
  11. package/fesm2022/ng-forge-dynamic-forms-container-field-processors-C_JRvaVt.mjs +117 -0
  12. package/fesm2022/ng-forge-dynamic-forms-container-field-processors-C_JRvaVt.mjs.map +1 -0
  13. package/fesm2022/ng-forge-dynamic-forms-container-field.component-Bg7Win9n.mjs +228 -0
  14. package/fesm2022/ng-forge-dynamic-forms-container-field.component-Bg7Win9n.mjs.map +1 -0
  15. package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-R2yc-H0T.mjs +102 -0
  16. package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-R2yc-H0T.mjs.map +1 -0
  17. package/fesm2022/ng-forge-dynamic-forms-debounce-CG3uP5B-.mjs +4 -0
  18. package/fesm2022/{ng-forge-dynamic-forms-debounce-C9F4v1Ke.mjs.map → ng-forge-dynamic-forms-debounce-CG3uP5B-.mjs.map} +1 -1
  19. package/fesm2022/ng-forge-dynamic-forms-default-value-D5M4MNE-.mjs +77 -0
  20. package/fesm2022/ng-forge-dynamic-forms-default-value-D5M4MNE-.mjs.map +1 -0
  21. package/fesm2022/ng-forge-dynamic-forms-dev-mode-4rbYBBo_.mjs +4 -0
  22. package/fesm2022/ng-forge-dynamic-forms-dev-mode-4rbYBBo_.mjs.map +1 -0
  23. package/fesm2022/ng-forge-dynamic-forms-df-field-outlet.directive-CQsDMV-s.mjs +644 -0
  24. package/fesm2022/ng-forge-dynamic-forms-df-field-outlet.directive-CQsDMV-s.mjs.map +1 -0
  25. package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-DKgkpIpG.mjs +56 -0
  26. package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-DKgkpIpG.mjs.map +1 -0
  27. package/fesm2022/ng-forge-dynamic-forms-form-schema.service-Dd-gHJ_7.mjs +38 -0
  28. package/fesm2022/{ng-forge-dynamic-forms-form-schema.service-Dx5Dlb15.mjs.map → ng-forge-dynamic-forms-form-schema.service-Dd-gHJ_7.mjs.map} +1 -1
  29. package/fesm2022/ng-forge-dynamic-forms-form-state-manager-BJKBX4FL.mjs +1545 -0
  30. package/fesm2022/ng-forge-dynamic-forms-form-state-manager-BJKBX4FL.mjs.map +1 -0
  31. package/fesm2022/ng-forge-dynamic-forms-group-field.component-BjZi0bhq.mjs +292 -0
  32. package/fesm2022/ng-forge-dynamic-forms-group-field.component-BjZi0bhq.mjs.map +1 -0
  33. package/fesm2022/ng-forge-dynamic-forms-integration.mjs +1318 -843
  34. package/fesm2022/ng-forge-dynamic-forms-integration.mjs.map +1 -1
  35. package/fesm2022/ng-forge-dynamic-forms-internal.mjs +3421 -3641
  36. package/fesm2022/ng-forge-dynamic-forms-internal.mjs.map +1 -1
  37. package/fesm2022/ng-forge-dynamic-forms-page-field.component-Bsd8YpzL.mjs +327 -0
  38. package/fesm2022/ng-forge-dynamic-forms-page-field.component-Bsd8YpzL.mjs.map +1 -0
  39. package/fesm2022/ng-forge-dynamic-forms-resolve-field-ByGa5cpo.mjs +329 -0
  40. package/fesm2022/ng-forge-dynamic-forms-resolve-field-ByGa5cpo.mjs.map +1 -0
  41. package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-CuFycQb-.mjs +81 -0
  42. package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-CuFycQb-.mjs.map +1 -0
  43. package/fesm2022/ng-forge-dynamic-forms-schema-builder-C62afItJ.mjs +400 -0
  44. package/fesm2022/ng-forge-dynamic-forms-schema-builder-C62afItJ.mjs.map +1 -0
  45. package/fesm2022/ng-forge-dynamic-forms-schema-registry.service-axBV9FBH.mjs +45 -0
  46. package/fesm2022/ng-forge-dynamic-forms-schema-registry.service-axBV9FBH.mjs.map +1 -0
  47. package/fesm2022/ng-forge-dynamic-forms-schema.mjs +8 -14
  48. package/fesm2022/ng-forge-dynamic-forms-schema.mjs.map +1 -1
  49. package/fesm2022/ng-forge-dynamic-forms-testing.mjs +68 -73
  50. package/fesm2022/ng-forge-dynamic-forms-testing.mjs.map +1 -1
  51. package/fesm2022/ng-forge-dynamic-forms-text-field.component--MAh_h4Q.mjs +257 -0
  52. package/fesm2022/ng-forge-dynamic-forms-text-field.component--MAh_h4Q.mjs.map +1 -0
  53. package/fesm2022/ng-forge-dynamic-forms-validation-execution.token-BFyySKtp.mjs +8 -0
  54. package/fesm2022/ng-forge-dynamic-forms-validation-execution.token-BFyySKtp.mjs.map +1 -0
  55. package/fesm2022/ng-forge-dynamic-forms-with-logger-config-BAATqYY0.mjs +94 -0
  56. package/fesm2022/ng-forge-dynamic-forms-with-logger-config-BAATqYY0.mjs.map +1 -0
  57. package/fesm2022/ng-forge-dynamic-forms-wrapper-chain-BnntfNU1.mjs +115 -0
  58. package/fesm2022/ng-forge-dynamic-forms-wrapper-chain-BnntfNU1.mjs.map +1 -0
  59. package/fesm2022/ng-forge-dynamic-forms.mjs +2195 -3
  60. package/fesm2022/ng-forge-dynamic-forms.mjs.map +1 -1
  61. package/package.json +1 -1
  62. package/types/ng-forge-dynamic-forms-integration.d.ts +543 -415
  63. package/types/ng-forge-dynamic-forms-internal.d.ts +2329 -2437
  64. package/types/ng-forge-dynamic-forms-schema.d.ts +13 -16
  65. package/types/ng-forge-dynamic-forms-testing.d.ts +34 -37
  66. package/types/ng-forge-dynamic-forms.d.ts +796 -722
  67. package/fesm2022/ng-forge-dynamic-forms-array-field.component-CSCKq_1K.mjs +0 -750
  68. package/fesm2022/ng-forge-dynamic-forms-array-field.component-CSCKq_1K.mjs.map +0 -1
  69. package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-CTOTwzzw.mjs +0 -2394
  70. package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-CTOTwzzw.mjs.map +0 -1
  71. package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-BtjqeJOj.mjs +0 -1054
  72. package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-BtjqeJOj.mjs.map +0 -1
  73. package/fesm2022/ng-forge-dynamic-forms-container-field.component-Dc3ROhHL.mjs +0 -86
  74. package/fesm2022/ng-forge-dynamic-forms-container-field.component-Dc3ROhHL.mjs.map +0 -1
  75. package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-BzgX8lAD.mjs +0 -33
  76. package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-BzgX8lAD.mjs.map +0 -1
  77. package/fesm2022/ng-forge-dynamic-forms-debounce-C9F4v1Ke.mjs +0 -17
  78. package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-CIKbWqYA.mjs +0 -25
  79. package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-CIKbWqYA.mjs.map +0 -1
  80. package/fesm2022/ng-forge-dynamic-forms-form-schema.service-Dx5Dlb15.mjs +0 -24
  81. package/fesm2022/ng-forge-dynamic-forms-group-field.component-DAC3P9DC.mjs +0 -177
  82. package/fesm2022/ng-forge-dynamic-forms-group-field.component-DAC3P9DC.mjs.map +0 -1
  83. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-CXQe_5td.mjs +0 -5133
  84. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-CXQe_5td.mjs.map +0 -1
  85. package/fesm2022/ng-forge-dynamic-forms-page-field.component-DPKJcwUO.mjs +0 -176
  86. package/fesm2022/ng-forge-dynamic-forms-page-field.component-DPKJcwUO.mjs.map +0 -1
  87. package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-DMEeKZny.mjs +0 -19
  88. package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-DMEeKZny.mjs.map +0 -1
  89. package/fesm2022/ng-forge-dynamic-forms-schema-builder-BvDTzfdM.mjs +0 -570
  90. package/fesm2022/ng-forge-dynamic-forms-schema-builder-BvDTzfdM.mjs.map +0 -1
  91. package/fesm2022/ng-forge-dynamic-forms-text-field.component-BB-jutBq.mjs +0 -126
  92. package/fesm2022/ng-forge-dynamic-forms-text-field.component-BB-jutBq.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ng-forge-dynamic-forms-df-field-outlet.directive-CQsDMV-s.mjs","names":[],"sources":["../../../../packages/dynamic-forms/src/lib/providers/features/field-windowing/field-windowing.token.ts","../../../../packages/dynamic-forms/src/lib/providers/features/clamp-window.ts","../../../../packages/dynamic-forms/src/lib/providers/features/field-windowing/field-parking-margin.ts","../../../../packages/dynamic-forms/src/lib/providers/features/field-windowing/resolve-field-windowing.ts","../../../../packages/dynamic-forms/src/lib/directives/df-field-outlet/field-viewport-observer.service.ts","../../../../packages/dynamic-forms/src/lib/utils/resolve-wrappers/resolve-wrappers.ts","../../../../packages/dynamic-forms/src/lib/utils/wrapper-chain/wrapper-chain-controller.ts","../../../../packages/dynamic-forms/src/lib/utils/build-field-inputs/build-field-inputs.ts","../../../../packages/dynamic-forms/src/lib/directives/df-field-outlet/field-component-slot.ts","../../../../packages/dynamic-forms/src/lib/utils/emit-initialization/emit-initialization.ts","../../../../packages/dynamic-forms/src/lib/utils/container-utils/container-utils.ts","../../../../packages/dynamic-forms/src/lib/directives/df-field-outlet/field-parking-state.ts","../../../../packages/dynamic-forms/src/lib/directives/df-field-outlet/df-field-outlet.directive.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\n/**\n * Global default configuration for progressive field mounting (\"field\n * windowing\"): fields beyond `eager` render as `@defer (on viewport)`\n * placeholders instead of mounting immediately, and mount only once scrolled\n * near/into view.\n *\n * @internal\n */\nexport interface FieldWindowingConfig {\n /** Whether field windowing is active. */\n readonly enabled: boolean;\n /** Number of leading fields mounted eagerly (not windowed). */\n readonly eager: number;\n /** CSS `min-height` reserved for each unmounted field's placeholder. */\n readonly placeholderHeight: string;\n /** Parking: hold scrolled-away fields out of change detection, DOM intact. */\n readonly park: FieldParkingConfig;\n}\n\n/**\n * Parking config. `@defer (on viewport)` only ever mounts — it never unmounts —\n * so without parking a form that has been scrolled through ends up with every\n * field live again, and the windowing win is handed back for the rest of the\n * session. Parking closes that: a field that scrolls away leaves change\n * detection but keeps its DOM, so it stays findable, autofillable and\n * reachable by assistive tech.\n *\n * Off in this default, on whenever `withFieldWindowing()` is used. Parking\n * suspends model → DOM updates for a scrolled-away field until it returns, so\n * it is a rendering behaviour change and is not something a form should get\n * without asking. It exists to bound what windowing leaves mounted, which is\n * why enabling windowing enables it too.\n *\n * @internal\n */\nexport interface FieldParkingConfig {\n /** Whether scrolled-away fields are held out of change detection. */\n readonly enabled: boolean;\n /** `IntersectionObserver` rootMargin — how far outside the viewport stays live. */\n readonly margin: string;\n}\n\nexport const FIELD_WINDOWING = new InjectionToken<FieldWindowingConfig>('FIELD_WINDOWING', {\n providedIn: 'root',\n factory: () => ({ enabled: false, eager: 12, placeholderHeight: '4rem', park: { enabled: false, margin: '100%' } }),\n});\n","/**\n * Normalizes a preload/eager window size to a non-negative integer.\n *\n * Guards the non-finite cases `Math.floor` lets through: `NaN` (which would make\n * every `<= window` comparison false, mounting nothing) and `Infinity` (which\n * would remove the bound, mounting everything). Both fall back to `fallback`, as\n * does `undefined`.\n */\nexport function clampWindowSize(value: number | undefined, fallback: number): number {\n if (value === undefined || !Number.isFinite(value)) return fallback;\n return Math.max(0, Math.floor(value));\n}\n","const DEFAULT_MARGIN = '100%';\nconst ROOT_MARGIN_PART = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?(?:px|%)$/i;\n\n/**\n * IntersectionObserver accepts one to four whitespace-separated pixel or\n * percentage lengths. Invalid public configuration must not make its\n * constructor throw and abort form rendering.\n */\nexport function normalizeFieldParkingMargin(value: string | undefined, fallback = DEFAULT_MARGIN): string {\n const normalizedFallback = isValidRootMargin(fallback) ? fallback.trim() : DEFAULT_MARGIN;\n if (!value || !isValidRootMargin(value)) return normalizedFallback;\n return value.trim().split(/\\s+/).join(' ');\n}\n\nfunction isValidRootMargin(value: string): boolean {\n const parts = value.trim().split(/\\s+/);\n return parts.length >= 1 && parts.length <= 4 && parts.every((part) => ROOT_MARGIN_PART.test(part));\n}\n","import { FieldParkingConfig, FieldWindowingConfig } from './field-windowing.token';\nimport { clampWindowSize } from '../clamp-window';\nimport { normalizeFieldParkingMargin } from './field-parking-margin';\n\n/** Per-form override shape for parking. `false` opts out; an object tunes the margin. */\nexport type FieldParkingOption =\n | boolean\n | {\n /** IntersectionObserver root margin. Supports one to four `px` or `%` values. */\n margin?: string;\n };\n\n/** Per-form override shape for `FormOptions.fieldWindowing`. */\nexport type FieldWindowingOption = boolean | { eager?: number; placeholderHeight?: string; park?: FieldParkingOption };\n\n/**\n * Resolves the effective field-windowing config for a form: per-form\n * `FormOptions.fieldWindowing` wins over the global `withFieldWindowing()`\n * default (`global`, the injected `FIELD_WINDOWING` value).\n *\n * - `undefined` — use `global` as-is\n * - `false` — force-disable for this form\n * - `true` — force-enable, using `global`'s `eager` / `placeholderHeight` / `park`\n * - object — force-enable; per-form keys win over `global`'s\n *\n * A `park`-only object is the one exception: parking and progressive mounting\n * are independent, so tuning parking must not silently switch a form over to\n * deferred mounting. `{ park: false }` means \"don't park\", not \"start\n * deferring everything\".\n */\nexport function resolveFieldWindowing(global: FieldWindowingConfig, perForm: FieldWindowingOption | undefined): FieldWindowingConfig {\n if (perForm === undefined) {\n return global;\n }\n\n if (typeof perForm === 'boolean') {\n return { ...global, enabled: perForm };\n }\n\n const configuresMounting = 'eager' in perForm || 'placeholderHeight' in perForm || Object.keys(perForm).length === 0;\n\n return {\n enabled: configuresMounting ? true : global.enabled,\n eager: clampWindowSize(perForm.eager, global.eager),\n placeholderHeight: perForm.placeholderHeight ?? global.placeholderHeight,\n park: resolveFieldParking(global.park, perForm.park),\n };\n}\n\n/**\n * A form inherits whatever parking the global config sets — off by default, on\n * when `withFieldWindowing()` is in play — and can override it either way.\n * `{ park: true }` on a form that isn't windowed is legal and does park; the two\n * are independent axes.\n */\nexport function resolveFieldParking(global: FieldParkingConfig, perForm: FieldParkingOption | undefined): FieldParkingConfig {\n if (perForm === undefined) return global;\n if (typeof perForm === 'boolean') return { ...global, enabled: perForm };\n return { enabled: true, margin: normalizeFieldParkingMargin(perForm.margin, global.margin) };\n}\n","import { DestroyRef, inject, Injectable, PLATFORM_ID } from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport { distinctUntilChanged, Observable, of } from 'rxjs';\nimport { normalizeFieldParkingMargin } from '../../providers/features/field-windowing/field-parking-margin';\n\nconst ALWAYS_VISIBLE = of(true);\n\ntype VisibilityListener = (visible: boolean) => void;\n\ninterface ObserverEntry {\n readonly observer: IntersectionObserver;\n readonly listeners: Map<Element, Set<VisibilityListener>>;\n}\n\n/**\n * Shares one native observer per margin. Subscriptions own element cleanup;\n * SSR and unsupported browsers always report visible.\n */\n@Injectable()\nexport class FieldViewportObserver {\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID)) && typeof IntersectionObserver !== 'undefined';\n private readonly observers = new Map<string, ObserverEntry>();\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n for (const { observer } of this.observers.values()) observer.disconnect();\n this.observers.clear();\n });\n }\n\n observe(el: Element, rootMargin: string): Observable<boolean> {\n if (!this.isBrowser) return ALWAYS_VISIBLE;\n rootMargin = normalizeFieldParkingMargin(rootMargin);\n\n return new Observable<boolean>((subscriber) => {\n const listener: VisibilityListener = (visible) => subscriber.next(visible);\n this.startObserving(el, rootMargin, listener);\n // Native callbacks are asynchronous. Keep fields live until the first one.\n subscriber.next(true);\n return () => this.stopObserving(el, rootMargin, listener);\n }).pipe(distinctUntilChanged());\n }\n\n private startObserving(el: Element, rootMargin: string, listener: VisibilityListener): void {\n const entry = this.observerFor(rootMargin);\n const listeners = entry.listeners.get(el);\n if (listeners) {\n listeners.add(listener);\n return;\n }\n entry.listeners.set(el, new Set([listener]));\n entry.observer.observe(el);\n }\n\n private stopObserving(el: Element, rootMargin: string, listener: VisibilityListener): void {\n const entry = this.observers.get(rootMargin);\n if (!entry) return;\n const listeners = entry.listeners.get(el);\n if (!listeners) return;\n listeners.delete(listener);\n if (listeners.size > 0) return;\n\n entry.observer.unobserve(el);\n entry.listeners.delete(el);\n if (entry.listeners.size > 0) return;\n entry.observer.disconnect();\n this.observers.delete(rootMargin);\n }\n\n private observerFor(rootMargin: string): ObserverEntry {\n const existing = this.observers.get(rootMargin);\n if (existing) return existing;\n\n const listeners = new Map<Element, Set<VisibilityListener>>();\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n for (const listener of listeners.get(entry.target) ?? []) listener(entry.isIntersecting);\n }\n },\n { rootMargin },\n );\n const entry = { observer, listeners };\n this.observers.set(rootMargin, entry);\n return entry;\n }\n}\n","import { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { ContainerValidation, WrapperAutoAssociations, WrapperConfig, WrapperTypeDefinition } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Shared empty chain — returned when no wrappers apply so callers get a\n * stable reference. Freezing makes accidental mutation observable.\n */\nconst EMPTY_WRAPPERS: readonly WrapperConfig[] = Object.freeze([]);\n\n/** Wrapper type name — must match the `BUILT_IN_WRAPPERS` registration. */\nconst FIELD_ERRORS_WRAPPER = 'field-errors';\n\n/** Frozen so the appended entry keeps its identity and `isSameWrapperChain` still memoises. */\nconst FIELD_ERRORS_CONFIG = Object.freeze({ type: FIELD_ERRORS_WRAPPER }) as WrapperConfig;\n\n/** The subset of a field this resolver reads. */\ntype ResolvableField = Pick<FieldDef<unknown>, 'type' | 'wrappers' | 'skipAutoWrappers' | 'skipDefaultWrappers'> &\n Partial<ContainerValidation>;\n\n/**\n * Element-wise identity (`===`) comparator for wrapper chains. Used as the\n * `equal` option on signal memoisation so reconciled `FieldDef`s with the\n * same chain don't churn downstream — relies on `WrapperConfig` objects\n * being stable across ticks, which holds for configs declared in\n * `FormConfig` / `createWrappers(...)`.\n */\nexport function isSameWrapperChain(a: readonly WrapperConfig[], b: readonly WrapperConfig[]): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\n/** Resolves the wrapper chain for a field. */\nexport function resolveWrappers(\n field: ResolvableField,\n defaultWrappers: readonly WrapperConfig[] | undefined,\n autoAssociations: WrapperAutoAssociations,\n wrapperRegistry: ReadonlyMap<string, WrapperTypeDefinition>,\n): readonly WrapperConfig[] {\n // Absolute escape hatch: no wrappers at all, error message included.\n if (field.wrappers === null) {\n return EMPTY_WRAPPERS;\n }\n\n const autoWrappers = field.skipAutoWrappers ? EMPTY_WRAPPERS : (autoAssociations.get(field.type) ?? EMPTY_WRAPPERS);\n const defaults = field.skipDefaultWrappers ? EMPTY_WRAPPERS : (defaultWrappers ?? EMPTY_WRAPPERS);\n const fieldLevel = field.wrappers ?? EMPTY_WRAPPERS;\n\n const composed = [...autoWrappers, ...defaults, ...fieldLevel];\n\n // A container validator (#568) has no field component to render its message. Appended\n // after all layers compose, so a custom error wrapper counts from any of them.\n if (needsErrorWrapper(field, composed, wrapperRegistry)) {\n composed.push(FIELD_ERRORS_CONFIG);\n }\n\n return composed.length === 0 ? EMPTY_WRAPPERS : composed;\n}\n\n/** Field types that own a schema path and so can carry their own validators (#568). */\nconst VALIDATABLE_CONTAINERS: ReadonlySet<string> = new Set(['group', 'array']);\n\n/** True when the field declares container validators and nothing in the chain renders them. */\nfunction needsErrorWrapper(\n field: ResolvableField,\n composed: readonly WrapperConfig[],\n wrapperRegistry: ReadonlyMap<string, WrapperTypeDefinition>,\n): boolean {\n // Leaves render their own errors in the field component; only containers need the wrapper.\n if (!VALIDATABLE_CONTAINERS.has(field.type)) return false;\n if (!field.validators || field.validators.length === 0) return false;\n\n return !composed.some((w) => w.type === FIELD_ERRORS_WRAPPER || wrapperRegistry.get(w.type)?.rendersFieldErrors);\n}\n","import {\n ComponentRef,\n computed,\n DestroyRef,\n EnvironmentInjector,\n inject,\n Injector,\n Signal,\n ViewContainerRef,\n ViewRef,\n} from '@angular/core';\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { map, Observable, of, switchMap } from 'rxjs';\nimport {\n WRAPPER_COMPONENT_CACHE,\n WRAPPER_COMPONENT_LOAD_CACHE,\n WRAPPER_REGISTRY,\n WrapperConfig,\n WrapperTypeDefinition,\n} from '@ng-forge/dynamic-forms/internal';\nimport { Logger } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { WrapperFieldInputs } from '@ng-forge/dynamic-forms/internal';\nimport { isSameWrapperChain } from '../resolve-wrappers/resolve-wrappers';\nimport { LoadedWrapper, loadWrapperComponents, renderWrapperChain, setInputIfDeclared } from './wrapper-chain';\n\nexport interface WrapperChainControllerOptions {\n /**\n * The outer slot where the wrapper chain is mounted. Sampled only at render\n * time — safe to pass a `viewChild.required` signal that resolves post-init.\n */\n readonly vcr: Signal<ViewContainerRef>;\n /**\n * Signal of the wrapper chain. Ref-stable memoisation (e.g.\n * `isSameWrapperChain`) is recommended — `WrapperConfig` entries should be\n * singletons so the controller can tell a real chain change from ref churn.\n */\n readonly wrappers: Signal<readonly WrapperConfig[]>;\n /**\n * Optional gating signal. When `false`, the chain is not mounted (initial)\n * or left untouched (post-mount flicker). `DfFieldOutlet` passes\n * `renderReady`; containers omit the gate.\n */\n readonly gate?: Signal<boolean>;\n /**\n * Optional mapper-outputs signal. When present, the controller pushes it to\n * each wrapper's `fieldInputs` input at render time AND on every subsequent\n * change. Must always produce a value once subscribed — don't emit undefined.\n * Containers render a children template (no field), so they omit this.\n */\n readonly fieldInputs?: Signal<WrapperFieldInputs>;\n /**\n * Optional extra rebuild trigger. `DfFieldOutlet` passes the innermost\n * component class so that a reconciled field with the same wrapper chain\n * but a different `component` forces a rebuild. Compared by identity.\n */\n readonly rebuildKey?: Signal<unknown>;\n /**\n * Optional field-level injector signal (e.g. `ResolvedField.injector`). When\n * provided, wrapper components see a merged injector — field tokens first\n * (`ARRAY_CONTEXT`, `FIELD_SIGNAL_CONTEXT`), element chain behind\n * (parent wrappers). Containers omit this.\n */\n readonly fieldInjector?: Signal<Injector>;\n /**\n * Grid classes (e.g. `df-col-6`) for the outermost wrapper host, sampled on\n * each structural rebuild. Containers omit this.\n */\n readonly outermostHostClasses?: Signal<string | undefined>;\n /**\n * Renders whatever belongs at the innermost slot (a field component, a children\n * template, …). Called each time the chain mounts or structurally rebuilds.\n */\n readonly renderInnermost: (slot: ViewContainerRef) => void;\n /**\n * Called right before the mounted chain is cleared on a structural change.\n * Lets the caller detach views it wants to preserve — e.g. `DfFieldOutlet`\n * detaches the innermost field's hostView so focus / caret / scroll survive\n * when only the wrapper chain changes. Return true when the caller owns the\n * controller's already-detached outer view and will reinsert it itself. Not\n * invoked on the pre-first-render path.\n */\n readonly beforeRebuild?: () => boolean | void;\n}\n\n/**\n * Owns the wrapper-chain lifecycle for a field or container: async component\n * loading, switchMap-based cancellation of stale loads, flicker-tolerant\n * rebuilds (only structural changes tear down), and `fieldInputs` push-through.\n * Must be called from a DI injection context.\n */\nexport function createWrapperChainController(opts: WrapperChainControllerOptions): void {\n const deps = injectChainDeps();\n const state = createStateSignal(opts);\n\n const mounted = { value: null as MountedChain | null };\n const detached = { value: null as ViewRef | null };\n let refs: ComponentRef<unknown>[] = [];\n\n // INVARIANT: toObservable schedules emissions as microtasks, so `renderInnermost`\n // runs outside any parent CD pass. Don't swap for sync signal wiring without\n // restoring df-field-outlet's detectChanges — NG0950 would re-surface.\n buildEmissionStream(state, deps)\n .pipe(takeUntilDestroyed(deps.destroyRef))\n .subscribe((emission) => {\n // Wrap the whole render path — a throw here (bad wrapper template,\n // caller's renderInnermost blew up, etc.) would otherwise terminate\n // the subscription and silently freeze subsequent chain updates.\n try {\n refs = applyEmission(emission, { opts, deps, mounted, refs, detached });\n } catch (err) {\n deps.logger.error('Wrapper chain render failed; tearing down partial state.', err);\n opts.vcr().clear();\n refs = [];\n mounted.value = null;\n // Same reason as the teardown branch: clear() cannot reach a detached view.\n detached.value?.destroy();\n detached.value = null;\n }\n });\n\n pushFieldInputsOnChange(opts, () => refs);\n deps.destroyRef.onDestroy(() => {\n detached.value?.destroy();\n opts.vcr().clear();\n });\n}\n\ninterface ChainDeps {\n readonly registry: ReadonlyMap<string, WrapperTypeDefinition>;\n readonly cache: Map<string, import('@angular/core').Type<unknown>>;\n readonly loadCache: Map<string, Promise<import('@angular/core').Type<unknown> | undefined>>;\n readonly logger: Logger;\n readonly destroyRef: DestroyRef;\n readonly environmentInjector: EnvironmentInjector;\n}\n\ninterface ChainState {\n readonly open: boolean;\n readonly wrappers: readonly WrapperConfig[];\n readonly rebuildKey: unknown;\n}\n\ninterface MountedChain {\n readonly wrappers: readonly WrapperConfig[];\n readonly rebuildKey: unknown;\n}\n\ninterface ChainEmission {\n readonly state: ChainState;\n readonly loaded: readonly LoadedWrapper[] | null;\n}\n\ninterface EmissionApplyContext {\n readonly opts: WrapperChainControllerOptions;\n readonly deps: ChainDeps;\n readonly mounted: { value: MountedChain | null };\n readonly refs: ComponentRef<unknown>[];\n /** View detached while the gate is closed, re-inserted when it reopens. */\n readonly detached: { value: ViewRef | null };\n}\n\nfunction injectChainDeps(): ChainDeps {\n return {\n registry: inject(WRAPPER_REGISTRY),\n cache: inject(WRAPPER_COMPONENT_CACHE),\n loadCache: inject(WRAPPER_COMPONENT_LOAD_CACHE),\n logger: inject(DynamicFormLogger),\n destroyRef: inject(DestroyRef),\n environmentInjector: inject(EnvironmentInjector),\n };\n}\n\nfunction createStateSignal(opts: WrapperChainControllerOptions): Signal<ChainState> {\n return computed(\n () => ({\n open: opts.gate?.() ?? true,\n wrappers: opts.wrappers(),\n rebuildKey: opts.rebuildKey?.(),\n }),\n { equal: (a, b) => a.open === b.open && a.rebuildKey === b.rebuildKey && isSameWrapperChain(a.wrappers, b.wrappers) },\n );\n}\n\n/**\n * Resolve a `ChainState` into a `ChainEmission`. `switchMap` cancellation\n * guarantees in-flight async loads are discarded when a newer state arrives.\n */\nfunction buildEmissionStream(state: Signal<ChainState>, deps: ChainDeps): Observable<ChainEmission> {\n return toObservable(state).pipe(switchMap((s) => resolveLoadedWrappers(s, deps)));\n}\n\nfunction resolveLoadedWrappers(state: ChainState, deps: ChainDeps): Observable<ChainEmission> {\n if (!state.open) {\n return of({ state, loaded: null });\n }\n\n if (state.wrappers.every((w) => deps.cache.has(w.type))) {\n // Sync fast-path — the cache only holds SUCCESSFUL loads, so \"every cached\"\n // means every wrapper was previously resolved cleanly. No need to re-log.\n const loaded = state.wrappers.map((config) => ({ config, component: deps.cache.get(config.type)! }) satisfies LoadedWrapper);\n return of({ state, loaded });\n }\n\n return loadWrapperComponents(state.wrappers, deps.registry, deps.cache, deps.logger, deps.loadCache).pipe(\n map((loaded) => ({ state, loaded })),\n );\n}\n\n/**\n * Diff what's mounted against the next state and act:\n * - Gate-only flicker → no-op (preserve the mounted chain)\n * - Structural change → beforeRebuild → vcr.clear → render fresh\n * - Idempotent re-emission → no-op\n */\nfunction applyEmission({ state, loaded }: ChainEmission, ctx: EmissionApplyContext): ComponentRef<unknown>[] {\n const { opts, deps, mounted, refs } = ctx;\n const vcr = opts.vcr();\n const structurallyChanged = isStructurallyDifferent(mounted.value, state);\n\n // Gate-only flicker after first mount — keep the chain alive so the user's\n // focus / caret / scroll survive, and detach it so it leaves the DOM and stops\n // taking change detection. Rebuilding instead costs ~5x the teardown.\n if (!structurallyChanged && !state.open) {\n if (vcr.length > 0) ctx.detached.value = vcr.detach(0) ?? ctx.detached.value;\n return refs;\n }\n\n // Re-opening a chain we detached rather than destroyed: put the view back.\n if (state.open && !structurallyChanged && mounted.value !== null && ctx.detached.value) {\n vcr.insert(ctx.detached.value);\n ctx.detached.value = null;\n return refs;\n }\n\n // Real structural change — tear down. Angular cascades destroy through\n // every nested ComponentRef, so walking `refs` manually is redundant.\n // `beforeRebuild` gives the caller a chance to detach views it wants to\n // preserve (e.g. the innermost field when only wrappers changed).\n if (structurallyChanged && mounted.value !== null) {\n // Preserve the innermost field before destroying a detached outer chain. Destroying the\n // ancestor first also destroys the field ref and leaves the caller holding a dead view.\n const preservesDetachedOuterView = opts.beforeRebuild?.() === true;\n // A view detached by an earlier gate close is not in the container, so vcr.clear() cannot\n // reach it. Once the preservable inner view is detached, destroy the remaining chain.\n if (ctx.detached.value && !preservesDetachedOuterView) ctx.detached.value.destroy();\n ctx.detached.value = null;\n vcr.clear();\n mounted.value = null;\n }\n\n if (!state.open || loaded === null) return [];\n // Same structure + already mounted — idempotent re-emission, nothing to do.\n if (mounted.value !== null) return refs;\n\n const newRefs = renderWrapperChain({\n outerContainer: vcr,\n loadedWrappers: loaded,\n environmentInjector: deps.environmentInjector,\n logger: deps.logger,\n fieldInputs: opts.fieldInputs?.(),\n fieldInjector: opts.fieldInjector?.(),\n outermostHostClasses: opts.outermostHostClasses?.(),\n renderInnermost: opts.renderInnermost,\n });\n mounted.value = { wrappers: state.wrappers, rebuildKey: state.rebuildKey };\n return newRefs;\n}\n\nfunction isStructurallyDifferent(mounted: MountedChain | null, next: ChainState): boolean {\n if (mounted === null) return true;\n if (mounted.rebuildKey !== next.rebuildKey) return true;\n return !isSameWrapperChain(mounted.wrappers, next.wrappers);\n}\n\n/**\n * Push the latest `fieldInputs` bag to every mounted wrapper whenever it\n * changes — without rebuilding the chain. No-op when the chain is empty\n * (gated off, or nothing rendered yet).\n */\nfunction pushFieldInputsOnChange(opts: WrapperChainControllerOptions, getRefs: () => readonly ComponentRef<unknown>[]): void {\n if (!opts.fieldInputs) return;\n explicitEffect([opts.fieldInputs], ([fi]) => {\n for (const ref of getRefs()) setInputIfDeclared(ref, 'fieldInputs', fi);\n });\n}\n","import { FieldTree } from '@angular/forms/signals';\nimport { ReadonlyFieldTree, toReadonlyFieldTreeCached, writeToFieldValue } from '@ng-forge/dynamic-forms/internal';\nimport { WrapperFieldInputs } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Convert a field's raw mapper outputs into the {@link WrapperFieldInputs}\n * bag consumed by wrappers and addons.\n *\n * @param rawInputs Mapper outputs (`{ key, label, props, field?: FieldTree, ... }`).\n * @param cache `WeakMap<FieldTree, ReadonlyFieldTree>` provided via\n * {@link READONLY_FIELD_TREE_CACHE}.\n * @param fieldType Optional field-type discriminant. Injected here (rather\n * than via the field mapper) because `type` is the\n * registry key, not a component input — but addons and\n * wrappers legitimately need it.\n */\nexport function buildFieldInputs(\n rawInputs: Record<string, unknown>,\n cache: WeakMap<FieldTree<unknown>, ReadonlyFieldTree<unknown>>,\n fieldType?: string,\n validationMessages?: Record<string, unknown>,\n): WrapperFieldInputs {\n const fieldTreeCandidate = rawInputs['field'];\n // FieldTree is callable: `(): FieldState`. Anything else (undefined,\n // primitive) means the field is rendered before the form is bound.\n const hasFieldTree = fieldTreeCandidate !== undefined && typeof fieldTreeCandidate === 'function';\n const readonlyField = hasFieldTree ? toReadonlyFieldTreeCached(cache, fieldTreeCandidate as FieldTree<unknown>) : undefined;\n // Lazy writer keyed on the raw FieldTree. Addons (e.g., `prime-button`\n // presets) call this to mutate the host field. `writeToFieldValue`\n // centralises the `Signal → WritableSignal` cast and warns at runtime\n // if Signal Forms ever changes the contract.\n const setValue = hasFieldTree\n ? (next: unknown) => writeToFieldValue((fieldTreeCandidate as FieldTree<unknown>)().value, next)\n : undefined;\n // Shallow spread — relies on the mapper contract (see WrapperFieldInputs)\n // that rawInputs are emitted as fresh snapshots, not mutated in place.\n return {\n ...rawInputs,\n type: fieldType,\n field: readonlyField,\n setValue,\n // Containers can't emit this as a mapper output (no such component input), so it rides\n // the wrapper-facing bag only — where the error wrapper reads messages from.\n ...(validationMessages !== undefined && { validationMessages }),\n } as WrapperFieldInputs;\n}\n","import { ComponentRef, EnvironmentInjector, Injector, signal, Type, ViewContainerRef } from '@angular/core';\nimport { createWrapperAwareInjector, setInputIfDeclared } from '../../utils/wrapper-chain/wrapper-chain';\nimport type { WrapperFieldInputs } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Captured focus + caret for one detach/reinsert cycle. Tied to a single\n * mounted-detached-mounted round trip; never persisted across a component-\n * class swap (the fresh `Mounted` state starts with no snapshot).\n */\ninterface FocusSnapshot {\n readonly element: HTMLElement;\n readonly selectionStart: number | null;\n readonly selectionEnd: number | null;\n}\n\n/**\n * Explicit lifecycle states for `FieldComponentSlot`. The discriminant carries\n * exactly the data each phase needs, so nothing in the slot is \"optional state\n * that might be undefined\" — the type forces every code path to handle the\n * empty/mounted/detached cases distinctly.\n */\nexport type FieldSlotState =\n | { readonly phase: 'empty' }\n | {\n readonly phase: 'mounted';\n readonly ref: ComponentRef<unknown>;\n readonly slot: ViewContainerRef;\n }\n | {\n readonly phase: 'detached';\n readonly ref: ComponentRef<unknown>;\n readonly focusSnapshot: FocusSnapshot | null;\n };\n\nconst EMPTY_STATE: FieldSlotState = Object.freeze({ phase: 'empty' });\n\n/**\n * Encapsulates the imperative `ViewContainerRef` / `ComponentRef` lifecycle\n * for the innermost field component. Pulled out of `DfFieldOutlet` so the\n * directive itself stays declarative — signals + constructor wiring — while\n * the unavoidable mutable bookkeeping (Angular's view container API is\n * imperative) lives in one place behind a small, focused surface.\n */\nexport class FieldComponentSlot {\n private readonly state = signal<FieldSlotState>(EMPTY_STATE);\n /**\n * Per-key cache for `pushInputs`. Lives outside the lifecycle state machine on\n * purpose — it's a `setInput`-call optimization that changes on every keystroke,\n * not a phase transition. Keeping it here means the `state` signal only emits\n * on real `empty ⇄ mounted ⇄ detached` transitions (≈ once per\n * mount/destroy cycle), not once per input emission.\n */\n private lastInputs: Record<string, unknown> | null = null;\n\n /**\n * Parking intent, not a record of what was done to the LView. Orthogonal to\n * `phase` — it's about whether the mounted ref's own view participates in\n * change detection, not about where the view lives — so it isn't folded into\n * the state discriminant. Held as intent because `ViewContainerRef.insert()`\n * re-attaches the view it inserts, so a reuse-path remount silently undoes\n * the detach and `mountOrReuse` has to re-apply it.\n */\n private readonly _parked = signal(false);\n\n /** Read-only view of the lifecycle phase. Useful for tests and assertions. */\n readonly phase = () => this.state().phase;\n /** Read-only view of the full state. Exposed so tests can assert ref stability. */\n readonly snapshot = () => this.state();\n /** Whether this field's view is currently held out of change detection. */\n readonly parked = this._parked.asReadonly();\n\n /**\n * Mount the field component into `slot`. Reuses the existing `ComponentRef`\n * when its component type matches (preserving DOM/focus/caret across a\n * wrapper-chain rebuild); otherwise discards the old ref and creates a fresh\n * one.\n */\n mountOrReuse(\n slot: ViewContainerRef,\n component: Type<unknown>,\n fieldInjector: Injector,\n environmentInjector: EnvironmentInjector,\n rawInputs: Record<string, unknown>,\n fieldInputs?: WrapperFieldInputs,\n ): void {\n const current = this.state();\n\n if (current.phase !== 'empty' && current.ref.componentType === component) {\n slot.insert(current.ref.hostView);\n this.lastInputs = null;\n this.state.set(Object.freeze({ phase: 'mounted', ref: current.ref, slot }));\n // `slot.insert` re-attaches the host view to change detection, so a\n // standing park intent has to be re-applied before anything can refresh.\n if (this._parked()) current.ref.changeDetectorRef.detach();\n this.pushInputs(rawInputs, fieldInputs);\n if (current.phase === 'detached') this.replayFocus(current.focusSnapshot);\n return;\n }\n\n // Different component class — destroy the prior ref (if any) and create\n // a fresh one. The `empty` transition before `createComponent` ensures a\n // throw inside the factory doesn't leave a dangling ref the next mount\n // would try to re-insert.\n if (current.phase !== 'empty') current.ref.destroy();\n this.lastInputs = null;\n // A different component class is a different field shape — the old ref's\n // parked state says nothing about the new one, which mounts live.\n this._parked.set(false);\n this.state.set(EMPTY_STATE);\n const ref = slot.createComponent(component, {\n environmentInjector,\n injector: createWrapperAwareInjector(fieldInjector, slot.injector),\n });\n this.state.set(Object.freeze({ phase: 'mounted', ref, slot }));\n this.pushInputs(rawInputs, fieldInputs);\n }\n\n /**\n * Push mapper inputs onto the mounted component. Per-key reference compare\n * skips `setInput` for unchanged values — necessary in dev mode where\n * `setInput` on unknown keys logs NG0303 per call (Angular 21 is lenient\n * at runtime but warns); without the cache, every emission would re-warn\n * for every undeclared mapper key.\n */\n pushInputs(rawInputs: Record<string, unknown>, fieldInputs?: WrapperFieldInputs): void {\n const current = this.state();\n if (current.phase !== 'mounted') return;\n const prev = this.lastInputs;\n if (prev === rawInputs) return;\n for (const [key, value] of Object.entries(rawInputs)) {\n if (prev && prev[key] === value) continue;\n current.ref.setInput(key, value);\n }\n // Side-channel forwarding for the `fieldInputs` bag — gated on\n // `setInputIfDeclared` so leaf fields that don't declare it (most\n // non-addon-aware components) skip silently rather than triggering\n // NG0303 in dev. Pushed unconditionally on every emission since the bag\n // changes identity when `rawInputs` does.\n if (fieldInputs !== undefined) {\n setInputIfDeclared(current.ref, 'fieldInputs', fieldInputs);\n }\n this.lastInputs = rawInputs;\n }\n\n /**\n * Detach the host view from its current slot, capturing focus + caret so the\n * next `mountOrReuse()` can replay them after re-inserting into the new\n * slot. Returns true when the outer wrapper controller already detached this\n * exact unwrapped field view, so it can transfer ownership without destroying it.\n */\n detach(): boolean {\n const current = this.state();\n if (current.phase !== 'mounted') return false;\n const focusSnapshot = this.captureFocus(current.ref);\n const idx = current.slot.indexOf(current.ref.hostView);\n if (idx >= 0) current.slot.detach(idx);\n this.lastInputs = null;\n this.state.set(Object.freeze({ phase: 'detached', ref: current.ref, focusSnapshot }));\n // When the outer chain is already detached and there are no wrappers, the field's\n // host view is that outer view. Tell the controller not to destroy its detached handle.\n return idx < 0;\n }\n\n /**\n * Detach the mounted component's view from change detection, leaving its DOM\n * in place. Angular's `[formField]` reads all 16 pieces of field state from\n * inside the view's update pass, and a detached view is skipped before its\n * producers are even polled — so parking takes the field out of the\n * per-keystroke cost entirely while keeping it findable, autofillable and\n * reachable by assistive tech.\n *\n * User input still writes through: Angular binds `input` / `blur` with plain\n * DOM listeners that set the model synchronously, and those are not\n * view-scoped. Only the model → DOM direction is suspended.\n *\n * Policy (never park the focused field, never park a field showing an error)\n * belongs to the caller; this is the mechanism only.\n */\n park(): void {\n const current = this.state();\n if (current.phase === 'empty' || this._parked()) return;\n current.ref.changeDetectorRef.detach();\n this._parked.set(true);\n }\n\n /** Refresh a parked view once without returning it to the application CD tree. */\n refresh(): void {\n const current = this.state();\n if (current.phase === 'empty' || !this._parked()) return;\n current.ref.changeDetectorRef.detectChanges();\n }\n\n /**\n * Re-attach a parked view and force one refresh, so the DOM catches up with\n * every model change it slept through. `markForCheck` is required as well as\n * `reattach` — reattaching alone leaves an `OnPush` view clean.\n */\n unpark(): void {\n const current = this.state();\n if (current.phase === 'empty' || !this._parked()) return;\n current.ref.changeDetectorRef.reattach();\n current.ref.changeDetectorRef.markForCheck();\n this._parked.set(false);\n }\n\n /**\n * Called on directive teardown. Only destroys when the host view is still\n * detached — otherwise the outer `vcr.clear()` cascade has already destroyed\n * it (calling `.destroy()` again would throw).\n */\n destroyOnTeardown(): void {\n const current = this.state();\n if (current.phase === 'detached') current.ref.destroy();\n this.lastInputs = null;\n this._parked.set(false);\n this.state.set(EMPTY_STATE);\n }\n\n private captureFocus(ref: ComponentRef<unknown>): FocusSnapshot | null {\n const hostEl = ref.location.nativeElement as HTMLElement;\n const active = document.activeElement;\n if (!(active instanceof HTMLElement) || !hostEl.contains(active)) return null;\n const sel = active as HTMLInputElement & HTMLTextAreaElement;\n return {\n element: active,\n selectionStart: typeof sel.selectionStart === 'number' ? sel.selectionStart : null,\n selectionEnd: typeof sel.selectionEnd === 'number' ? sel.selectionEnd : null,\n };\n }\n\n private replayFocus(snap: FocusSnapshot | null): void {\n if (!snap || !snap.element.isConnected) return;\n snap.element.focus();\n if (snap.selectionStart !== null && snap.selectionEnd !== null && 'setSelectionRange' in snap.element) {\n (snap.element as HTMLInputElement).setSelectionRange(snap.selectionStart, snap.selectionEnd);\n }\n }\n}\n","import { afterNextRender, Injector } from '@angular/core';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { ComponentInitializedEvent } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\n\n/** Component type for initialization events. */\nexport type InitializationComponentType = 'dynamic-form' | 'group' | 'page' | 'array' | 'container';\n\n/**\n * Emits a component initialization event after the next render cycle.\n *\n * @param eventBus - The EventBus instance to dispatch the event on\n * @param componentType - The type of component being initialized\n * @param componentKey - The unique key/id of the component\n * @param injector - The injector to use for afterNextRender scheduling\n */\nexport function emitComponentInitialized(\n eventBus: EventBus,\n componentType: InitializationComponentType,\n componentKey: string,\n injector: Injector,\n): void {\n const logger = injector.get(DynamicFormLogger);\n\n afterNextRender(\n () => {\n try {\n eventBus.dispatch(ComponentInitializedEvent, componentType, componentKey);\n } catch (error: unknown) {\n logger.error(`Failed to emit initialization event for ${componentType} '${componentKey}'`, error);\n }\n },\n { injector },\n );\n}\n","import { computed, Injector, Signal } from '@angular/core';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { emitComponentInitialized, InitializationComponentType } from '../emit-initialization/emit-initialization';\nimport { ResolvedField } from '../resolve-field/resolve-field';\nimport {\n FieldDef,\n hasChildFields,\n isArrayField,\n isGenericContainerField,\n isGroupField,\n isPageField,\n isRowField,\n normalizeFieldsArray,\n} from '@ng-forge/dynamic-forms/internal';\n\n/** Event identity used by containers that participate in initialization readiness. */\nexport function initializationComponentKey(type: InitializationComponentType, key: string): string {\n return `${type}:${key}`;\n}\n\n/** Joins a container's local key to its group scope for initialization identity. */\nexport function initializationComponentPath(key: string, groupPath?: string): string {\n return groupPath ? `${groupPath}.${key}` : key;\n}\n\n/** Component-initialization identity emitted by a rendered container field. */\nexport function initializationComponentType(field: FieldDef<unknown>): InitializationComponentType | undefined {\n if (isPageField(field)) return 'page';\n if (isGroupField(field)) return 'group';\n if (isArrayField(field)) return 'array';\n if (isRowField(field) || isGenericContainerField(field)) return 'container';\n return undefined;\n}\n\nexport interface InitializationComponentIdentity {\n readonly type: InitializationComponentType;\n readonly path: string;\n}\n\n/** Collects the initialization identities expected from rendered container components. */\nexport function collectInitializingContainers(fields: readonly FieldDef<unknown>[], groupPath = ''): InitializationComponentIdentity[] {\n const identities: InitializationComponentIdentity[] = [];\n\n for (const field of fields) {\n // A statically hidden container never mounts, and neither can its descendants.\n if (field.hidden === true) continue;\n\n const type = initializationComponentType(field);\n const componentPath = initializationComponentPath(field.key, groupPath);\n if (type && field.key) identities.push({ type, path: componentPath });\n\n if (!hasChildFields(field)) continue;\n const childGroupPath = isGroupField(field) ? componentPath : groupPath;\n for (const child of normalizeFieldsArray(field.fields)) {\n identities.push(\n ...collectInitializingContainers((Array.isArray(child) ? child : [child]) as readonly FieldDef<unknown>[], childGroupPath),\n );\n }\n }\n\n return identities;\n}\n\n/** Collects the initialization events expected from rendered container components. */\nexport function collectInitializingContainerKeys(fields: readonly FieldDef<unknown>[], groupPath = ''): string[] {\n return collectInitializingContainers(fields, groupPath).map(({ type, path }) => initializationComponentKey(type, path));\n}\n\n/**\n * Computes the host class string for a container component.\n *\n * @param containerType - The CSS class suffix (e.g., 'group', 'row', 'page-field')\n * @param className - Optional custom class name to append\n * @returns The computed host class string\n */\nexport function computeContainerHostClasses(containerType: string, className: string | undefined): string {\n const base = `df-field df-${containerType}`;\n return className ? `${base} ${className}` : base;\n}\n\n/**\n * Sets up the initialization effect common to all container components.\n *\n * @param resolvedFields - Signal of resolved fields\n * @param eventBus - EventBus for dispatching initialization events\n * @param componentType - Static type, or a getter evaluated at emission time\n * @param fieldKeyFn - Function returning the field's key\n * @param injector - Injector for afterNextRender scheduling\n */\nexport function setupContainerInitEffect(\n resolvedFields: Signal<ResolvedField[]>,\n eventBus: EventBus,\n componentType: InitializationComponentType | (() => InitializationComponentType),\n fieldKeyFn: () => string,\n injector: Injector,\n): void {\n const allReady = computed(() => {\n const fields = resolvedFields();\n return fields.length > 0 && fields.every((field) => field.renderReady());\n });\n\n explicitEffect([allReady], ([ready]) => {\n if (ready) {\n const type = typeof componentType === 'function' ? componentType() : componentType;\n emitComponentInitialized(eventBus, type, fieldKeyFn(), injector);\n }\n });\n}\n","import type { Signal } from '@angular/core';\n\nexport interface ParkedFieldState {\n readonly disabled?: Signal<boolean>;\n readonly readonly?: Signal<boolean>;\n readonly required?: Signal<boolean>;\n readonly touched?: Signal<boolean>;\n readonly dirty?: Signal<boolean>;\n readonly errors?: Signal<readonly unknown[]>;\n}\n\nexport type ParkableFieldTree = () => ParkedFieldState;\n\nexport interface ParkedDomState {\n readonly disabled: boolean;\n readonly readonly: boolean;\n readonly required: boolean;\n readonly touched: boolean;\n readonly dirty: boolean;\n readonly errors: readonly unknown[];\n}\n\nconst EMPTY_ERRORS: readonly unknown[] = Object.freeze([]);\n\nexport function snapshotParkedDomState(fieldTree: ParkableFieldTree | undefined): ParkedDomState | null {\n const state = fieldTree?.();\n if (!state) return null;\n return {\n disabled: state.disabled?.() ?? false,\n readonly: state.readonly?.() ?? false,\n required: state.required?.() ?? false,\n touched: state.touched?.() ?? false,\n dirty: state.dirty?.() ?? false,\n errors: state.errors?.() ?? EMPTY_ERRORS,\n };\n}\n\nexport function isSameParkedDomState(a: ParkedDomState | null, b: ParkedDomState | null): boolean {\n return (\n a === b ||\n (a !== null &&\n b !== null &&\n a.disabled === b.disabled &&\n a.readonly === b.readonly &&\n a.required === b.required &&\n a.touched === b.touched &&\n a.dirty === b.dirty &&\n a.errors === b.errors)\n );\n}\n","import {\n computed,\n DestroyRef,\n Directive,\n EnvironmentInjector,\n inject,\n Injector,\n input,\n Signal,\n signal,\n Type,\n ViewContainerRef,\n} from '@angular/core';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { derivedFrom } from 'ngxtension/derived-from';\nimport { of, pipe, switchMap } from 'rxjs';\nimport { FORM_OPTIONS } from '@ng-forge/dynamic-forms/internal';\nimport { FIELD_WINDOWING } from '../../providers/features/field-windowing/field-windowing.token';\nimport { resolveFieldWindowing } from '../../providers/features/field-windowing/resolve-field-windowing';\nimport { FieldViewportObserver } from './field-viewport-observer.service';\nimport { ResolvedField } from '../../utils/resolve-field/resolve-field';\nimport { WRAPPER_REGISTRY, WRAPPER_AUTO_ASSOCIATIONS } from '@ng-forge/dynamic-forms/internal';\nimport { DEFAULT_WRAPPERS } from '@ng-forge/dynamic-forms/internal';\nimport { createWrapperChainController } from '../../utils/wrapper-chain/wrapper-chain-controller';\nimport { isSameWrapperChain, resolveWrappers } from '../../utils/resolve-wrappers/resolve-wrappers';\nimport { READONLY_FIELD_TREE_CACHE } from '@ng-forge/dynamic-forms/internal';\nimport { getGridClassString } from '@ng-forge/dynamic-forms/internal';\nimport { buildFieldInputs } from '../../utils/build-field-inputs/build-field-inputs';\nimport { WrapperFieldInputs } from '@ng-forge/dynamic-forms/internal';\nimport { FieldComponentSlot } from './field-component-slot';\nimport { EventBus, GROUP_CONTEXT } from '@ng-forge/dynamic-forms/internal';\nimport { emitComponentInitialized } from '../../utils/emit-initialization/emit-initialization';\nimport { collectInitializingContainers } from '../../utils/container-utils/container-utils';\nimport { isSameParkedDomState, snapshotParkedDomState } from './field-parking-state';\nimport type { ParkableFieldTree, ParkedDomState } from './field-parking-state';\n\n/**\n * Structural directive that renders a `ResolvedField` with its effective\n * wrapper chain.\n */\n@Directive({\n selector: '[dfFieldOutlet]',\n})\nexport class DfFieldOutlet {\n // Named to match the structural directive microsyntax directly\n // (`*dfFieldOutlet=\"field; environmentInjector: env\"`) so no aliasing is needed.\n readonly dfFieldOutlet = input.required<ResolvedField>();\n readonly dfFieldOutletEnvironmentInjector = input<EnvironmentInjector | undefined>(undefined);\n\n private readonly vcrRef = inject(ViewContainerRef);\n private readonly vcr: Signal<ViewContainerRef> = signal(this.vcrRef).asReadonly();\n private readonly destroyRef = inject(DestroyRef);\n private readonly wrapperAutoAssociations = inject(WRAPPER_AUTO_ASSOCIATIONS);\n private readonly wrapperRegistry = inject(WRAPPER_REGISTRY);\n private readonly defaultWrappersSignal = inject(DEFAULT_WRAPPERS, { optional: true });\n private readonly readonlyFieldCache = inject(READONLY_FIELD_TREE_CACHE);\n private readonly eventBus = inject(EventBus, { optional: true });\n private readonly injector = inject(Injector);\n\n private readonly fieldComponent = new FieldComponentSlot();\n\n private readonly componentIdentity: Signal<Type<unknown>> = computed(() => this.dfFieldOutlet().component);\n /** Avoids the NG01916 window between `renderReady` and hidden state settling. */\n private readonly renderReady: Signal<boolean> = computed(() => this.dfFieldOutlet().renderReady() && !this.dfFieldOutlet().hidden());\n private readonly hidden = computed(() => this.dfFieldOutlet().hidden());\n private readonly rawInputs = computed(() => this.dfFieldOutlet().inputs());\n\n /** Preserve wrapper identity across reconciled field snapshots. */\n private readonly wrappers = computed(\n () =>\n resolveWrappers(this.dfFieldOutlet().fieldDef, this.defaultWrappersSignal?.(), this.wrapperAutoAssociations, this.wrapperRegistry),\n { equal: isSameWrapperChain },\n );\n\n /** Shared input view for wrappers and addon-aware leaf components. */\n private readonly fieldInputs = computed<WrapperFieldInputs>(() =>\n buildFieldInputs(\n this.rawInputs(),\n this.readonlyFieldCache,\n this.dfFieldOutlet().fieldDef.type,\n (this.dfFieldOutlet().fieldDef as { validationMessages?: Record<string, unknown> }).validationMessages,\n ),\n );\n\n private readonly defaultEnvInjector = inject(EnvironmentInjector);\n private readonly fieldEnvInjector = computed(() => this.dfFieldOutletEnvironmentInjector() ?? this.defaultEnvInjector);\n private readonly fieldInjector = computed(() => this.dfFieldOutlet().injector);\n /** The outer wrapper is the row's grid child when wrappers exist. */\n private readonly outermostHostClasses = computed(() => getGridClassString(this.dfFieldOutlet().fieldDef) || undefined);\n\n private readonly formOptions = inject(FORM_OPTIONS, { optional: true });\n private readonly globalFieldWindowing = inject(FIELD_WINDOWING);\n private readonly viewportObserver = inject(FieldViewportObserver, { optional: true });\n\n private readonly parking = computed(() => resolveFieldWindowing(this.globalFieldWindowing, this.formOptions?.()?.fieldWindowing).park);\n\n /** A structural directive observes the mounted component's host element. */\n private readonly observedElement = computed(() => {\n const state = this.fieldComponent.snapshot();\n return state.phase === 'empty' ? null : (state.ref.location.nativeElement as HTMLElement);\n });\n\n private readonly visibility = derivedFrom(\n [this.observedElement, this.parking],\n pipe(\n switchMap(([element, parking]) => {\n const observer = this.viewportObserver;\n return parking.enabled && element && observer ? observer.observe(element, parking.margin) : of(true);\n }),\n ),\n { initialValue: true },\n );\n\n private readonly focusEpoch = signal(0);\n\n private readonly parked = computed(() => this.parking().enabled && !this.visibility());\n private readonly fieldTree = computed(\n () => {\n const candidate = this.rawInputs()['field'];\n return typeof candidate === 'function' ? (candidate as ParkableFieldTree) : undefined;\n },\n { equal: Object.is },\n );\n /** Subscribe to field state only while its view is parked. */\n private readonly parkedDomState = computed<ParkedDomState | null>(\n () => (this.parked() ? snapshotParkedDomState(this.fieldTree()) : null),\n { equal: isSameParkedDomState },\n );\n\n constructor() {\n createWrapperChainController({\n vcr: this.vcr,\n wrappers: this.wrappers,\n gate: this.renderReady,\n rebuildKey: this.componentIdentity,\n fieldInputs: this.fieldInputs,\n fieldInjector: this.fieldInjector,\n outermostHostClasses: this.outermostHostClasses,\n beforeRebuild: () => this.fieldComponent.detach(),\n renderInnermost: (slot) => {\n const resolved = this.dfFieldOutlet();\n this.fieldComponent.mountOrReuse(\n slot,\n resolved.component,\n resolved.injector,\n this.fieldEnvInjector(),\n this.rawInputs(),\n this.fieldInputs(),\n );\n },\n });\n\n // The slot deduplicates the initial render and this reactive push.\n explicitEffect([this.rawInputs, this.fieldInputs], ([rawInputs, fieldInputs]) =>\n this.fieldComponent.pushInputs(rawInputs, fieldInputs),\n );\n\n // Hidden containers still need to release ancestor initialization trackers.\n explicitEffect([this.hidden], ([hidden]) => {\n if (!hidden || !this.eventBus) return;\n const resolved = this.dfFieldOutlet();\n const groupContext = resolved.injector.get(GROUP_CONTEXT, null);\n for (const { type, path } of collectInitializingContainers([resolved.fieldDef], groupContext?.groupPath())) {\n emitComponentInitialized(this.eventBus, type, path, this.injector);\n }\n });\n\n // Focus changes can make an otherwise offscreen field safe to park.\n explicitEffect([this.observedElement, this.parking], ([element, parking], onCleanup) => {\n if (!parking.enabled || !element) return;\n // Reactive disabling can move focus during render; defer past NG0600.\n const bumpEpoch = () =>\n queueMicrotask(() => {\n if (!this.destroyRef.destroyed) this.focusEpoch.update((n) => n + 1);\n });\n element.addEventListener('focusin', bumpEpoch);\n element.addEventListener('focusout', bumpEpoch);\n onCleanup(() => {\n element.removeEventListener('focusin', bumpEpoch);\n element.removeEventListener('focusout', bumpEpoch);\n });\n });\n\n // Refresh safety state without returning a parked view to application CD.\n explicitEffect([this.parked, this.focusEpoch, this.parkedDomState], ([parked, , domState]) => {\n if (parked && this.canPark(domState)) {\n const alreadyParked = this.fieldComponent.parked();\n this.fieldComponent.park();\n if (alreadyParked) this.fieldComponent.refresh();\n } else {\n this.fieldComponent.unpark();\n }\n });\n\n this.destroyRef.onDestroy(() => this.fieldComponent.destroyOnTeardown());\n }\n\n /** Focused and invalid fields must keep their DOM live. */\n private canPark(domState: ParkedDomState | null): boolean {\n const element = this.observedElement();\n if (!element) return false;\n if (element.contains(document.activeElement)) return false;\n return (domState?.errors.length ?? 0) === 0;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component } from "@angular/core";
3
+ import { FieldErrorsWrapperBase, provideFieldErrorDisplay } from "@ng-forge/dynamic-forms/internal";
4
+ var FieldErrorsWrapperComponent = class FieldErrorsWrapperComponent extends FieldErrorsWrapperBase {
5
+ static ɵfac = i0.ɵɵngDeclareFactory({
6
+ minVersion: "12.0.0",
7
+ version: "22.2.5",
8
+ ngImport: i0,
9
+ type: FieldErrorsWrapperComponent,
10
+ deps: null,
11
+ target: i0.ɵɵFactoryTarget.Component
12
+ });
13
+ static ɵcmp = i0.ɵɵngDeclareComponent({
14
+ minVersion: "17.0.0",
15
+ version: "22.2.5",
16
+ type: FieldErrorsWrapperComponent,
17
+ isStandalone: true,
18
+ selector: "df-field-errors-wrapper",
19
+ providers: [provideFieldErrorDisplay(() => FieldErrorsWrapperComponent)],
20
+ usesInheritance: true,
21
+ ngImport: i0,
22
+ template: `
23
+ <ng-container #fieldComponent></ng-container>
24
+ @if (ngf.errorsToDisplay()[0]; as error) {
25
+ <div class="df-field-error" role="alert" [id]="ngf.errorId()">{{ error.message }}</div>
26
+ }
27
+ `,
28
+ isInline: true,
29
+ styles: [".df-field-error{color:var(--df-error-color, #dc3545);font-size:var(--df-error-font-size, .875rem);margin-top:var(--df-field-gap, .5rem)}\n"],
30
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
31
+ });
32
+ };
33
+ i0.ɵɵngDeclareClassMetadata({
34
+ minVersion: "12.0.0",
35
+ version: "22.2.5",
36
+ ngImport: i0,
37
+ type: FieldErrorsWrapperComponent,
38
+ decorators: [{
39
+ type: Component,
40
+ args: [{
41
+ selector: "df-field-errors-wrapper",
42
+ template: `
43
+ <ng-container #fieldComponent></ng-container>
44
+ @if (ngf.errorsToDisplay()[0]; as error) {
45
+ <div class="df-field-error" role="alert" [id]="ngf.errorId()">{{ error.message }}</div>
46
+ }
47
+ `,
48
+ changeDetection: ChangeDetectionStrategy.OnPush,
49
+ providers: [provideFieldErrorDisplay(() => FieldErrorsWrapperComponent)],
50
+ styles: [".df-field-error{color:var(--df-error-color, #dc3545);font-size:var(--df-error-font-size, .875rem);margin-top:var(--df-field-gap, .5rem)}\n"]
51
+ }]
52
+ }]
53
+ });
54
+ export { FieldErrorsWrapperComponent, FieldErrorsWrapperComponent as default };
55
+
56
+ //# sourceMappingURL=ng-forge-dynamic-forms-field-errors-wrapper.component-DKgkpIpG.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ng-forge-dynamic-forms-field-errors-wrapper.component-DKgkpIpG.mjs","names":[],"sources":["../../../../packages/dynamic-forms/src/lib/wrappers/field-errors/field-errors-wrapper.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { FieldErrorsWrapperBase, provideFieldErrorDisplay } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Neutral default rendering of a validation message for the wrapped field.\n * Follows the `--df-error-*` conventions; adapters register their own under the same name.\n */\n@Component({\n selector: 'df-field-errors-wrapper',\n template: `\n <ng-container #fieldComponent></ng-container>\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"df-field-error\" role=\"alert\" [id]=\"ngf.errorId()\">{{ error.message }}</div>\n }\n `,\n styleUrl: './field-errors-wrapper.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [provideFieldErrorDisplay(() => FieldErrorsWrapperComponent)],\n})\nexport default class FieldErrorsWrapperComponent extends FieldErrorsWrapperBase {}\n\nexport { FieldErrorsWrapperComponent };\n"],"mappings":";;;AAmBA,IAAqB,8BAArB,MAAqB,oCAAoC,uBAAsB;CAA1D,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA2B,MAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAA3B,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAA2B,cAAA;EAAA,UAAA;EAAA,WAFnC,CAAC,+BAA+B,2BAA2B,CAAC;EAAC,iBAAA;EAAA,UAAA;EAAA,UAR9D;;;;;;EAKT,UAAA;EAAA,QAAA,CAAA,4IAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAKkB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA2B,YAAA,CAAA;EAZ/C,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAyB,UACzB;;;;;;GAKT,iBAEgB,wBAAwB;GAAM,WACpC,CAAC,+BAA8B,2BAA4B,CAAC;GAAC,QAAA,CAAA,4IAAA;EAAA,CAAA"}
@@ -0,0 +1,38 @@
1
+ import { n as createFormLevelSchema, t as createSchemaFromFields } from "./ng-forge-dynamic-forms-schema-builder-C62afItJ.mjs";
2
+ import * as i0 from "@angular/core";
3
+ import { Service } from "@angular/core";
4
+ import { DynamicFormError } from "@ng-forge/dynamic-forms/internal";
5
+ var FormSchemaService = class FormSchemaService {
6
+ create({ fields, registry, formLevelSchema, validateWhenHidden }) {
7
+ if (fields.length > 0) return createSchemaFromFields(fields, registry, {
8
+ formLevelSchema,
9
+ validateWhenHidden
10
+ });
11
+ if (formLevelSchema) return createFormLevelSchema(formLevelSchema);
12
+ throw new DynamicFormError("The form schema service was requested without fields or a form-level schema.");
13
+ }
14
+ static ɵfac = i0.ɵɵngDeclareFactory({
15
+ minVersion: "12.0.0",
16
+ version: "22.2.5",
17
+ ngImport: i0,
18
+ type: FormSchemaService,
19
+ deps: [],
20
+ target: i0.ɵɵFactoryTarget.Service
21
+ });
22
+ static ɵprov = i0.ɵɵngDeclareService({
23
+ minVersion: "22.0.0",
24
+ version: "22.2.5",
25
+ ngImport: i0,
26
+ type: FormSchemaService
27
+ });
28
+ };
29
+ i0.ɵɵngDeclareClassMetadata({
30
+ minVersion: "12.0.0",
31
+ version: "22.2.5",
32
+ ngImport: i0,
33
+ type: FormSchemaService,
34
+ decorators: [{ type: Service }]
35
+ });
36
+ export { FormSchemaService as default };
37
+
38
+ //# sourceMappingURL=ng-forge-dynamic-forms-form-schema.service-Dd-gHJ_7.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-form-schema.service-Dx5Dlb15.mjs","mappings":";;;;;AAsBc;;AAEV;AACE;;;AAIA;;AAGF","names":[],"ignoreList":[],"sources":["../../../../packages/dynamic-forms/src/lib/core/form-schema.service.ts"],"sourcesContent":["import { Service } from '@angular/core';\nimport type { Schema } from '@angular/forms/signals';\nimport { DynamicFormError } from '@ng-forge/dynamic-forms/internal';\nimport type { FieldDef, FieldTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport type { FormSchema } from '@ng-forge/dynamic-forms/schema';\nimport { createFormLevelSchema } from './form-schema-merger';\nimport { createSchemaFromFields } from './schema-builder';\n\nexport interface FormSchemaRequest {\n readonly fields: FieldDef<unknown>[];\n readonly registry: Map<string, FieldTypeDefinition>;\n readonly formLevelSchema: FormSchema<unknown> | undefined;\n readonly validateWhenHidden: boolean | undefined;\n}\n\n/**\n * Lazy schema compiler requested by a form when its first value-bearing field is encountered.\n *\n * The service is stateless and auto-provided so Angular's `injectAsync()` can keep this module,\n * including form mapping, validators, schemas, and expression logic, out of the eager graph.\n */\n@Service()\nexport default class FormSchemaService {\n create({ fields, registry, formLevelSchema, validateWhenHidden }: FormSchemaRequest): Schema<unknown> {\n if (fields.length > 0) {\n return createSchemaFromFields(fields, registry, { formLevelSchema, validateWhenHidden });\n }\n\n if (formLevelSchema) {\n return createFormLevelSchema(formLevelSchema);\n }\n\n throw new DynamicFormError('The form schema service was requested without fields or a form-level schema.');\n }\n}\n"]}
1
+ {"version":3,"file":"ng-forge-dynamic-forms-form-schema.service-Dd-gHJ_7.mjs","names":[],"sources":["../../../../packages/dynamic-forms/src/lib/core/form-schema.service.ts"],"sourcesContent":["import { Service } from '@angular/core';\nimport type { Schema } from '@angular/forms/signals';\nimport { DynamicFormError } from '@ng-forge/dynamic-forms/internal';\nimport type { FieldDef, FieldTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport type { FormSchema } from '@ng-forge/dynamic-forms/schema';\nimport { createFormLevelSchema } from './form-schema-merger';\nimport { createSchemaFromFields } from './schema-builder';\n\nexport interface FormSchemaRequest {\n readonly fields: FieldDef<unknown>[];\n readonly registry: Map<string, FieldTypeDefinition>;\n readonly formLevelSchema: FormSchema<unknown> | undefined;\n readonly validateWhenHidden: boolean | undefined;\n}\n\n/**\n * Lazy schema compiler requested by a form when its first value-bearing field is encountered.\n *\n * The service is stateless and auto-provided so Angular's `injectAsync()` can keep this module,\n * including form mapping, validators, schemas, and expression logic, out of the eager graph.\n */\n@Service()\nexport default class FormSchemaService {\n create({ fields, registry, formLevelSchema, validateWhenHidden }: FormSchemaRequest): Schema<unknown> {\n if (fields.length > 0) {\n return createSchemaFromFields(fields, registry, { formLevelSchema, validateWhenHidden });\n }\n\n if (formLevelSchema) {\n return createFormLevelSchema(formLevelSchema);\n }\n\n throw new DynamicFormError('The form schema service was requested without fields or a form-level schema.');\n }\n}\n"],"mappings":";;;;AAsBA,IAAqB,oBAArB,MAAqB,kBAAiB;CACpC,OAAO,EAAE,QAAQ,UAAU,iBAAiB,sBAAuC;EACjF,IAAI,OAAO,SAAS,GAClB,OAAO,uBAAuB,QAAQ,UAAU;GAAE;GAAiB;EAAkB,CAAE;EAGzF,IAAI,iBACF,OAAO,sBAAsB,eAAe;EAG9C,MAAM,IAAI,iBAAiB,8EAA8E;CAC3G;CAXmB,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAiB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAjB,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAiB,CAAA;;AAAjB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAiB,YAAA,CAAA,EADrC,MAAA,Q"}