@ng-forge/dynamic-forms 1.3.0-next.1 → 1.3.0-next.3
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-CiKN-mcc.mjs +12 -0
- package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-CiKN-mcc.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-array-field.component-Dv9mPnJ3.mjs +770 -0
- package/fesm2022/ng-forge-dynamic-forms-array-field.component-Dv9mPnJ3.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-array-item-registry.service-D-AxVLdk.mjs +83 -0
- package/fesm2022/ng-forge-dynamic-forms-array-item-registry.service-D-AxVLdk.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-EuYCbquo.mjs +1887 -0
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-EuYCbquo.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-2wQK_wPp.mjs +954 -0
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-2wQK_wPp.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-container-field-processors-C_JRvaVt.mjs +117 -0
- package/fesm2022/ng-forge-dynamic-forms-container-field-processors-C_JRvaVt.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-container-field.component-Bg7Win9n.mjs +228 -0
- package/fesm2022/ng-forge-dynamic-forms-container-field.component-Bg7Win9n.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-R2yc-H0T.mjs +102 -0
- package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-R2yc-H0T.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-debounce-CG3uP5B-.mjs +4 -0
- package/fesm2022/{ng-forge-dynamic-forms-debounce-C9F4v1Ke.mjs.map → ng-forge-dynamic-forms-debounce-CG3uP5B-.mjs.map} +1 -1
- package/fesm2022/ng-forge-dynamic-forms-default-value-D5M4MNE-.mjs +77 -0
- package/fesm2022/ng-forge-dynamic-forms-default-value-D5M4MNE-.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-dev-mode-4rbYBBo_.mjs +4 -0
- package/fesm2022/ng-forge-dynamic-forms-dev-mode-4rbYBBo_.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-df-field-outlet.directive-CQsDMV-s.mjs +644 -0
- package/fesm2022/ng-forge-dynamic-forms-df-field-outlet.directive-CQsDMV-s.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-DKgkpIpG.mjs +56 -0
- package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-DKgkpIpG.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-form-schema.service-Dd-gHJ_7.mjs +38 -0
- 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
- package/fesm2022/ng-forge-dynamic-forms-form-state-manager-DcOXRFRL.mjs +1522 -0
- package/fesm2022/ng-forge-dynamic-forms-form-state-manager-DcOXRFRL.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-group-field.component-BjZi0bhq.mjs +292 -0
- package/fesm2022/ng-forge-dynamic-forms-group-field.component-BjZi0bhq.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs +1318 -843
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs.map +1 -1
- package/fesm2022/ng-forge-dynamic-forms-internal.mjs +3326 -3641
- package/fesm2022/ng-forge-dynamic-forms-internal.mjs.map +1 -1
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-BRjQmWC9.mjs +295 -0
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-BRjQmWC9.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-resolve-field-ByGa5cpo.mjs +329 -0
- package/fesm2022/ng-forge-dynamic-forms-resolve-field-ByGa5cpo.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-CuFycQb-.mjs +81 -0
- package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-CuFycQb-.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-schema-builder-C62afItJ.mjs +400 -0
- package/fesm2022/ng-forge-dynamic-forms-schema-builder-C62afItJ.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-schema-registry.service-axBV9FBH.mjs +45 -0
- package/fesm2022/ng-forge-dynamic-forms-schema-registry.service-axBV9FBH.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-schema.mjs +8 -14
- package/fesm2022/ng-forge-dynamic-forms-schema.mjs.map +1 -1
- package/fesm2022/ng-forge-dynamic-forms-testing.mjs +68 -73
- package/fesm2022/ng-forge-dynamic-forms-testing.mjs.map +1 -1
- package/fesm2022/ng-forge-dynamic-forms-text-field.component--MAh_h4Q.mjs +257 -0
- package/fesm2022/ng-forge-dynamic-forms-text-field.component--MAh_h4Q.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-validation-execution.token-BFyySKtp.mjs +8 -0
- package/fesm2022/ng-forge-dynamic-forms-validation-execution.token-BFyySKtp.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-with-logger-config-BAATqYY0.mjs +94 -0
- package/fesm2022/ng-forge-dynamic-forms-with-logger-config-BAATqYY0.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-wrapper-chain-BnntfNU1.mjs +115 -0
- package/fesm2022/ng-forge-dynamic-forms-wrapper-chain-BnntfNU1.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms.mjs +2136 -3
- package/fesm2022/ng-forge-dynamic-forms.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ng-forge-dynamic-forms-integration.d.ts +543 -415
- package/types/ng-forge-dynamic-forms-internal.d.ts +2319 -2436
- package/types/ng-forge-dynamic-forms-schema.d.ts +13 -16
- package/types/ng-forge-dynamic-forms-testing.d.ts +34 -37
- package/types/ng-forge-dynamic-forms.d.ts +735 -722
- package/fesm2022/ng-forge-dynamic-forms-array-field.component-CSCKq_1K.mjs +0 -750
- package/fesm2022/ng-forge-dynamic-forms-array-field.component-CSCKq_1K.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-CTOTwzzw.mjs +0 -2394
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-CTOTwzzw.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-BtjqeJOj.mjs +0 -1054
- package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-BtjqeJOj.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-container-field.component-Dc3ROhHL.mjs +0 -86
- package/fesm2022/ng-forge-dynamic-forms-container-field.component-Dc3ROhHL.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-BzgX8lAD.mjs +0 -33
- package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-BzgX8lAD.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-debounce-C9F4v1Ke.mjs +0 -17
- package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-CIKbWqYA.mjs +0 -25
- package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-CIKbWqYA.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-form-schema.service-Dx5Dlb15.mjs +0 -24
- package/fesm2022/ng-forge-dynamic-forms-group-field.component-DAC3P9DC.mjs +0 -177
- package/fesm2022/ng-forge-dynamic-forms-group-field.component-DAC3P9DC.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-CXQe_5td.mjs +0 -5133
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-CXQe_5td.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-DPKJcwUO.mjs +0 -176
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-DPKJcwUO.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-DMEeKZny.mjs +0 -19
- package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-DMEeKZny.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-schema-builder-BvDTzfdM.mjs +0 -570
- package/fesm2022/ng-forge-dynamic-forms-schema-builder-BvDTzfdM.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-text-field.component-BB-jutBq.mjs +0 -126
- package/fesm2022/ng-forge-dynamic-forms-text-field.component-BB-jutBq.mjs.map +0 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { t as DEV_MODE } from "./ng-forge-dynamic-forms-dev-mode-4rbYBBo_.mjs";
|
|
2
|
+
import { Injector, reflectComponentType } from "@angular/core";
|
|
3
|
+
import { catchError, forkJoin, from, map, of } from "rxjs";
|
|
4
|
+
const inputNamesCache = /* @__PURE__ */ new WeakMap();
|
|
5
|
+
function getDeclaredInputs(componentType) {
|
|
6
|
+
let inputs = inputNamesCache.get(componentType);
|
|
7
|
+
if (!inputs) {
|
|
8
|
+
const meta = reflectComponentType(componentType);
|
|
9
|
+
inputs = new Set(meta?.inputs.map((i) => i.templateName) ?? []);
|
|
10
|
+
inputNamesCache.set(componentType, inputs);
|
|
11
|
+
}
|
|
12
|
+
return inputs;
|
|
13
|
+
}
|
|
14
|
+
function setInputIfDeclared(ref, inputName, value) {
|
|
15
|
+
if (getDeclaredInputs(ref.componentType).has(inputName)) ref.setInput(inputName, value);
|
|
16
|
+
}
|
|
17
|
+
function hasDefaultExport(value) {
|
|
18
|
+
return typeof value === "object" && value !== null && "default" in value && !!value.default;
|
|
19
|
+
}
|
|
20
|
+
function resolveDefaultExport(result) {
|
|
21
|
+
return hasDefaultExport(result) ? result.default : result;
|
|
22
|
+
}
|
|
23
|
+
async function loadWrapperComponent(type, registry, cache, loadCache) {
|
|
24
|
+
const cached = cache.get(type);
|
|
25
|
+
if (cached) return cached;
|
|
26
|
+
const pending = loadCache?.get(type);
|
|
27
|
+
if (pending) return pending;
|
|
28
|
+
const definition = registry.get(type);
|
|
29
|
+
if (!definition) return void 0;
|
|
30
|
+
const load = (async () => {
|
|
31
|
+
const component = resolveDefaultExport(await definition.loadComponent());
|
|
32
|
+
if (component) cache.set(type, component);
|
|
33
|
+
return component;
|
|
34
|
+
})().finally(() => loadCache?.delete(type));
|
|
35
|
+
loadCache?.set(type, load);
|
|
36
|
+
return load;
|
|
37
|
+
}
|
|
38
|
+
function loadWrapperComponents(configs, registry, cache, logger, loadCache) {
|
|
39
|
+
if (configs.length === 0) return of([]);
|
|
40
|
+
return forkJoin(configs.map((config) => from(loadWrapperComponent(config.type, registry, cache, loadCache)).pipe(catchError(() => of(void 0)), map((component) => {
|
|
41
|
+
if (!component) {
|
|
42
|
+
if (DEV_MODE) logger.error(`Wrapper type '${config.type}' could not be loaded. Ensure it is registered via provideDynamicForm().`);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
config,
|
|
47
|
+
component
|
|
48
|
+
};
|
|
49
|
+
})))).pipe(map((results) => results.some((r) => r === null) ? [] : results));
|
|
50
|
+
}
|
|
51
|
+
function renderWrapperChain(options) {
|
|
52
|
+
const refs = [];
|
|
53
|
+
renderStep(options.outerContainer, options.loadedWrappers, options, refs);
|
|
54
|
+
if (options.outermostHostClasses && refs.length > 0) {
|
|
55
|
+
const tokens = options.outermostHostClasses.split(/\s+/).filter(Boolean);
|
|
56
|
+
if (tokens.length > 0) refs[0].location.nativeElement.classList.add(...tokens);
|
|
57
|
+
}
|
|
58
|
+
return refs;
|
|
59
|
+
}
|
|
60
|
+
function renderStep(slot, remaining, options, refs) {
|
|
61
|
+
if (remaining.length === 0) {
|
|
62
|
+
options.renderInnermost(slot);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const [wrapper, ...rest] = remaining;
|
|
66
|
+
const wrapperInjector = options.fieldInjector ? createWrapperAwareInjector(options.fieldInjector, slot.injector) : slot.injector;
|
|
67
|
+
const ref = slot.createComponent(wrapper.component, {
|
|
68
|
+
environmentInjector: options.environmentInjector,
|
|
69
|
+
injector: wrapperInjector
|
|
70
|
+
});
|
|
71
|
+
refs.push(ref);
|
|
72
|
+
for (const [key, value] of Object.entries(wrapper.config)) {
|
|
73
|
+
if (key === "type" || key === "fieldInputs") continue;
|
|
74
|
+
setInputIfDeclared(ref, key, value);
|
|
75
|
+
}
|
|
76
|
+
if (options.fieldInputs !== void 0) setInputIfDeclared(ref, "fieldInputs", options.fieldInputs);
|
|
77
|
+
ref.changeDetectorRef.detectChanges();
|
|
78
|
+
const inner = resolveInnerSlot(ref);
|
|
79
|
+
if (!inner) {
|
|
80
|
+
if (DEV_MODE) options.logger.error(`Wrapper component for type '${wrapper.config.type}' does not provide a 'fieldComponent' ViewContainerRef. Ensure the wrapper component has a viewChild('fieldComponent', { read: ViewContainerRef }) query and that #fieldComponent is not inside a conditional (@if, @defer).`);
|
|
81
|
+
while (refs.length) refs.pop().destroy();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
renderStep(inner, rest, options, refs);
|
|
85
|
+
}
|
|
86
|
+
function resolveInnerSlot(ref) {
|
|
87
|
+
const contract = ref.instance;
|
|
88
|
+
try {
|
|
89
|
+
return contract.fieldComponent?.();
|
|
90
|
+
} catch {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function createWrapperAwareInjector(fieldInjector, elementInjector) {
|
|
95
|
+
if (fieldInjector === elementInjector) return fieldInjector;
|
|
96
|
+
return new WrapperAwareInjector(fieldInjector, elementInjector);
|
|
97
|
+
}
|
|
98
|
+
const WRAPPER_NOT_FOUND = {};
|
|
99
|
+
var WrapperAwareInjector = class extends Injector {
|
|
100
|
+
fieldInjector;
|
|
101
|
+
elementInjector;
|
|
102
|
+
constructor(fieldInjector, elementInjector) {
|
|
103
|
+
super();
|
|
104
|
+
this.fieldInjector = fieldInjector;
|
|
105
|
+
this.elementInjector = elementInjector;
|
|
106
|
+
}
|
|
107
|
+
get(token, notFoundValue, options) {
|
|
108
|
+
const field = this.fieldInjector.get(token, WRAPPER_NOT_FOUND, options);
|
|
109
|
+
if (field !== WRAPPER_NOT_FOUND) return field;
|
|
110
|
+
return this.elementInjector.get(token, notFoundValue, options);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
export { resolveDefaultExport as a, renderWrapperChain as i, loadWrapperComponent as n, setInputIfDeclared as o, loadWrapperComponents as r, createWrapperAwareInjector as t };
|
|
114
|
+
|
|
115
|
+
//# sourceMappingURL=ng-forge-dynamic-forms-wrapper-chain-BnntfNU1.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ng-forge-dynamic-forms-wrapper-chain-BnntfNU1.mjs","names":[],"sources":["../../../../packages/dynamic-forms/src/lib/utils/wrapper-chain/wrapper-chain.ts"],"sourcesContent":["import {\n ComponentRef,\n EnvironmentInjector,\n InjectOptions,\n Injector,\n ProviderToken,\n reflectComponentType,\n Type,\n ViewContainerRef,\n} from '@angular/core';\nimport { catchError, forkJoin, from, map, Observable, of } from 'rxjs';\nimport { FieldWrapper, WrapperConfig, WrapperTypeDefinition } from '@ng-forge/dynamic-forms/internal';\nimport { Logger } from '@ng-forge/dynamic-forms/internal';\nimport { WrapperFieldInputs } from '@ng-forge/dynamic-forms/internal';\nimport { DEV_MODE } from '../dev-mode';\n\n/**\n * Module-level cache keyed by component class. `reflectComponentType` returns\n * immutable metadata per class, so we probe it once and reuse the resulting\n * `Set<templateName>` for every `setInputIfDeclared` call afterwards.\n */\nconst inputNamesCache = new WeakMap<Type<unknown>, Set<string>>();\n\nfunction getDeclaredInputs(componentType: Type<unknown>): Set<string> {\n let inputs = inputNamesCache.get(componentType);\n if (!inputs) {\n const meta = reflectComponentType(componentType);\n inputs = new Set(meta?.inputs.map((i) => i.templateName) ?? []);\n inputNamesCache.set(componentType, inputs);\n }\n return inputs;\n}\n\n/** Set an input on a ComponentRef only when the target component actually declares it. */\nexport function setInputIfDeclared(ref: ComponentRef<unknown>, inputName: string, value: unknown): void {\n if (getDeclaredInputs(ref.componentType).has(inputName)) {\n ref.setInput(inputName, value);\n }\n}\n\n/** A wrapper whose component has been resolved and loaded. */\nexport interface LoadedWrapper {\n readonly config: WrapperConfig;\n readonly component: Type<unknown>;\n}\n\n/**\n * Narrows an ES-module-with-default-export from a bare component class.\n * Lazy component loaders may return either shape depending on how the user\n * wrote the import expression (`import('./x')` vs `import('./x').then(m => m.Foo)`).\n */\nexport function hasDefaultExport<T>(value: unknown): value is { default: T } {\n return typeof value === 'object' && value !== null && 'default' in value && !!(value as { default: unknown }).default;\n}\n\n/** Pick the component class out of whatever a lazy loader returned. */\nexport function resolveDefaultExport<T>(result: Type<T> | { default: Type<T> }): Type<T> {\n return hasDefaultExport<Type<T>>(result) ? result.default : result;\n}\n\n/** Resolve a wrapper type name to its component class, with DI-scoped caching. */\nexport async function loadWrapperComponent(\n type: string,\n registry: ReadonlyMap<string, WrapperTypeDefinition>,\n cache: Map<string, Type<unknown>>,\n loadCache?: Map<string, Promise<Type<unknown> | undefined>>,\n): Promise<Type<unknown> | undefined> {\n const cached = cache.get(type);\n if (cached) return cached;\n\n const pending = loadCache?.get(type);\n if (pending) return pending;\n\n const definition = registry.get(type);\n if (!definition) return undefined;\n\n const load = (async () => {\n const component = resolveDefaultExport(await definition.loadComponent());\n if (component) cache.set(type, component);\n return component;\n })().finally(() => loadCache?.delete(type));\n loadCache?.set(type, load);\n return load;\n}\n\n/**\n * Load every wrapper for a chain, all-or-nothing. A single failed load\n * aborts the whole chain (emits `[]`) so the field renders bare rather\n * than in a partially-wrapped, visually-misleading state. Each failure\n * is logged; field-type resolution still throws — this isn't silent.\n */\nexport function loadWrapperComponents(\n configs: readonly WrapperConfig[],\n registry: ReadonlyMap<string, WrapperTypeDefinition>,\n cache: Map<string, Type<unknown>>,\n logger: Logger,\n loadCache?: Map<string, Promise<Type<unknown> | undefined>>,\n): Observable<LoadedWrapper[]> {\n if (configs.length === 0) return of([]);\n\n return forkJoin(\n configs.map((config) =>\n from(loadWrapperComponent(config.type, registry, cache, loadCache)).pipe(\n catchError(() => of(undefined)),\n map((component) => {\n if (!component) {\n // Diagnostic only — dropping the wrapper is what keeps the chain usable.\n if (DEV_MODE) {\n logger.error(`Wrapper type '${config.type}' could not be loaded. Ensure it is registered via provideDynamicForm().`);\n }\n return null;\n }\n return { config, component } satisfies LoadedWrapper;\n }),\n ),\n ),\n ).pipe(map((results) => (results.some((r) => r === null) ? [] : (results as LoadedWrapper[]))));\n}\n\n/** Options for building a wrapper chain. */\nexport interface RenderWrapperChainOptions {\n readonly outerContainer: ViewContainerRef;\n readonly loadedWrappers: readonly LoadedWrapper[];\n readonly environmentInjector: EnvironmentInjector;\n readonly logger: Logger;\n /**\n * Optional mapper outputs to set as `fieldInputs` on each wrapper in the chain.\n * Container usages omit this (the children template is the innermost content,\n * not a single field).\n */\n readonly fieldInputs?: WrapperFieldInputs;\n /**\n * Optional field-level injector (e.g. `ResolvedField.injector`). When provided,\n * each wrapper is created with a merged injector that checks the field's\n * tokens first (`FIELD_SIGNAL_CONTEXT`, `ARRAY_CONTEXT`, …) and falls back to\n * the element injector — so wrappers can inject both field context AND outer\n * wrappers up the element hierarchy.\n */\n readonly fieldInjector?: Injector;\n /**\n * Classes added imperatively to the outermost wrapper host (the row's direct\n * flex child, where grid CSS matches). Sampled at render time, not reactive.\n */\n readonly outermostHostClasses?: string;\n /** Renders whatever belongs at the innermost slot (a field component, a children template, …). */\n readonly renderInnermost: (slot: ViewContainerRef) => void;\n}\n\n/**\n * Recursively create each wrapper component, threading the next one (or the\n * innermost content) into its `#fieldComponent` slot.\n */\nexport function renderWrapperChain(options: RenderWrapperChainOptions): ComponentRef<unknown>[] {\n const refs: ComponentRef<unknown>[] = [];\n renderStep(options.outerContainer, options.loadedWrappers, options, refs);\n // Empty chain = the field host itself is the flex child and already carries the class.\n if (options.outermostHostClasses && refs.length > 0) {\n const tokens = options.outermostHostClasses.split(/\\s+/).filter(Boolean);\n if (tokens.length > 0) {\n (refs[0].location.nativeElement as HTMLElement).classList.add(...tokens);\n }\n }\n return refs;\n}\n\nfunction renderStep(\n slot: ViewContainerRef,\n remaining: readonly LoadedWrapper[],\n options: RenderWrapperChainOptions,\n refs: ComponentRef<unknown>[],\n): void {\n if (remaining.length === 0) {\n options.renderInnermost(slot);\n return;\n }\n\n const [wrapper, ...rest] = remaining;\n\n // `slot.injector` is the element injector seen from inside the current slot —\n // for nested slots that includes the outer wrapper's component, enabling\n // `inject(OuterWrapper)`. When a field injector is provided we merge it in\n // front so tokens like `ARRAY_CONTEXT` also resolve.\n const wrapperInjector = options.fieldInjector ? createWrapperAwareInjector(options.fieldInjector, slot.injector) : slot.injector;\n\n const ref = slot.createComponent(wrapper.component, {\n environmentInjector: options.environmentInjector,\n injector: wrapperInjector,\n });\n refs.push(ref);\n\n for (const [key, value] of Object.entries(wrapper.config)) {\n // `type` is the registry discriminant; `fieldInputs` is set explicitly\n // below. Don't let a stray config key override either.\n if (key === 'type' || key === 'fieldInputs') continue;\n setInputIfDeclared(ref, key, value);\n }\n\n if (options.fieldInputs !== undefined) {\n setInputIfDeclared(ref, 'fieldInputs', options.fieldInputs);\n }\n\n // Required to resolve `viewChild.required('fieldComponent')` before we\n // recurse into the slot. O(chain length) CD passes per rebuild — acceptable\n // for typical chains (≤3); refactor to a template-based render if it bites.\n ref.changeDetectorRef.detectChanges();\n\n const inner = resolveInnerSlot(ref);\n if (!inner) {\n // Diagnostic only — the unwind below is what keeps the DOM consistent.\n if (DEV_MODE) {\n options.logger.error(\n `Wrapper component for type '${wrapper.config.type}' does not provide a 'fieldComponent' ViewContainerRef. ` +\n `Ensure the wrapper component has a viewChild('fieldComponent', { read: ViewContainerRef }) query ` +\n `and that #fieldComponent is not inside a conditional (@if, @defer).`,\n );\n }\n // Unwind: destroy every wrapper built so far, including this one, so the\n // caller doesn't end up with a partial chain left in the DOM.\n while (refs.length) refs.pop()!.destroy();\n return;\n }\n\n renderStep(inner, rest, options, refs);\n}\n\n/**\n * Read a wrapper's `#fieldComponent` ViewContainerRef. `viewChild.required`\n * throws when the query can't resolve (missing template ref, or ref sitting\n * inside `@if` / `@defer` / `@for`); any throw from this pure signal read\n * means the slot is unusable, so we return undefined and let the caller log\n * the actionable \"wrapper missing fieldComponent\" message.\n */\nfunction resolveInnerSlot(ref: ComponentRef<unknown>): ViewContainerRef | undefined {\n const contract = ref.instance as FieldWrapper;\n try {\n return contract.fieldComponent?.();\n } catch {\n return undefined;\n }\n}\n\n/**\n * Merged injector: check the field-level injector first (for tokens like\n * `ARRAY_CONTEXT` / `FIELD_SIGNAL_CONTEXT`), fall back to the element-chain\n * injector (so nested wrappers can still `inject(OuterWrapper)`).\n */\nexport function createWrapperAwareInjector(fieldInjector: Injector, elementInjector: Injector): Injector {\n if (fieldInjector === elementInjector) return fieldInjector;\n return new WrapperAwareInjector(fieldInjector, elementInjector);\n}\n\n/** Sentinel — distinguishes \"token not found\" from a legitimate `undefined` provider value. */\nconst WRAPPER_NOT_FOUND = {};\n\nclass WrapperAwareInjector extends Injector {\n constructor(\n private readonly fieldInjector: Injector,\n private readonly elementInjector: Injector,\n ) {\n super();\n }\n\n override get<T>(token: ProviderToken<T>, notFoundValue?: T, options?: InjectOptions): T;\n override get(token: unknown, notFoundValue?: unknown, options?: InjectOptions): unknown {\n const field = this.fieldInjector.get(token as ProviderToken<unknown>, WRAPPER_NOT_FOUND, options);\n if (field !== WRAPPER_NOT_FOUND) return field;\n return this.elementInjector.get(token as ProviderToken<unknown>, notFoundValue, options);\n }\n}\n"],"mappings":"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"}
|