@ng-forge/dynamic-forms 1.2.0-next.2 → 1.2.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 (18) hide show
  1. package/fesm2022/{ng-forge-dynamic-forms-array-field.component-B5t7W5fo.mjs → ng-forge-dynamic-forms-array-field.component-BLPWSurR.mjs} +2 -2
  2. package/fesm2022/{ng-forge-dynamic-forms-array-field.component-B5t7W5fo.mjs.map → ng-forge-dynamic-forms-array-field.component-BLPWSurR.mjs.map} +1 -1
  3. package/fesm2022/{ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-D_DGkAXj.mjs → ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-jHiY95pr.mjs} +2 -2
  4. package/fesm2022/{ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-D_DGkAXj.mjs.map → ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-jHiY95pr.mjs.map} +1 -1
  5. package/fesm2022/{ng-forge-dynamic-forms-container-field.component-CrWGMLMJ.mjs → ng-forge-dynamic-forms-container-field.component-ug5tp6kt.mjs} +2 -2
  6. package/fesm2022/{ng-forge-dynamic-forms-container-field.component-CrWGMLMJ.mjs.map → ng-forge-dynamic-forms-container-field.component-ug5tp6kt.mjs.map} +1 -1
  7. package/fesm2022/{ng-forge-dynamic-forms-group-field.component-Ds_k0Tkn.mjs → ng-forge-dynamic-forms-group-field.component-DyD00a1U.mjs} +2 -2
  8. package/fesm2022/{ng-forge-dynamic-forms-group-field.component-Ds_k0Tkn.mjs.map → ng-forge-dynamic-forms-group-field.component-DyD00a1U.mjs.map} +1 -1
  9. package/fesm2022/ng-forge-dynamic-forms-internal.mjs +4 -5
  10. package/fesm2022/ng-forge-dynamic-forms-internal.mjs.map +1 -1
  11. package/fesm2022/{ng-forge-dynamic-forms-ng-forge-dynamic-forms-DtnrCyH2.mjs → ng-forge-dynamic-forms-ng-forge-dynamic-forms-BGRxIQ2V.mjs} +166 -145
  12. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-BGRxIQ2V.mjs.map +1 -0
  13. package/fesm2022/{ng-forge-dynamic-forms-page-field.component-PWJ-9bnw.mjs → ng-forge-dynamic-forms-page-field.component-B7A2v1vN.mjs} +2 -2
  14. package/fesm2022/{ng-forge-dynamic-forms-page-field.component-PWJ-9bnw.mjs.map → ng-forge-dynamic-forms-page-field.component-B7A2v1vN.mjs.map} +1 -1
  15. package/fesm2022/ng-forge-dynamic-forms.mjs +1 -1
  16. package/package.json +1 -1
  17. package/types/ng-forge-dynamic-forms.d.ts +36 -14
  18. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-DtnrCyH2.mjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, DestroyRef, Injector, EnvironmentInjector, input, computed, ChangeDetectionStrategy, Component } from '@angular/core';
3
- import { i as injectFieldRegistry, F as FIELD_WINDOWING, j as resolveFieldWindowing, c as createFieldResolutionPipe, D as DfFieldOutlet } from './ng-forge-dynamic-forms-ng-forge-dynamic-forms-DtnrCyH2.mjs';
3
+ import { i as injectFieldRegistry, F as FIELD_WINDOWING, j as resolveFieldWindowing, c as createFieldResolutionPipe, D as DfFieldOutlet } from './ng-forge-dynamic-forms-ng-forge-dynamic-forms-BGRxIQ2V.mjs';
4
4
  import { outputFromObservable } from '@angular/core/rxjs-interop';
5
5
  import { explicitEffect } from 'ngxtension/explicit-effect';
6
6
  import { EventBus, DynamicFormLogger, FORM_OPTIONS, validatePageNesting, derivedFromDeferred, isContainerField, getGridClassString } from '@ng-forge/dynamic-forms/internal';
@@ -132,4 +132,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
132
132
  }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], pageIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageIndex", required: true }] }], isVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "isVisible", required: true }] }], nextPage: [{ type: i0.Output, args: ["nextPage"] }], previousPage: [{ type: i0.Output, args: ["previousPage"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }] } });
133
133
 
134
134
  export { PageFieldComponent as default };
135
- //# sourceMappingURL=ng-forge-dynamic-forms-page-field.component-PWJ-9bnw.mjs.map
135
+ //# sourceMappingURL=ng-forge-dynamic-forms-page-field.component-B7A2v1vN.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-page-field.component-PWJ-9bnw.mjs","mappings":";;;;;;;;AAwDc;YAKK;;AAEA;AACE;AACF;AACA;;AAEA;;;;;AAQjB;;;;;;YAQS;;AAEA;;AAEA;;AAET,IAKmB;;;;YAUV;AACA;AACA;YAMQ;AACf;AACE;;;;;AAKe;AAGf;AACA;;;AAGA;AACE;;;;AAOH;YAQH;;;AAIA;AAOE;AACA;;IAIQ;;;;;;AAYR;;;;;AAQA;;;AA3HiB;;;;;;;;;;;;;;;;;;;;;;;AAnCT;;;;;;;;;;;;;;;;;;;;AAwBR;AACA;AACA;AACA;AACA;AACA;AACA;AACA","names":[],"ignoreList":[],"sources":["../../../../packages/dynamic-forms/src/lib/fields/page/page-field.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, DestroyRef, EnvironmentInjector, inject, Injector, input } from '@angular/core';\nimport { DfFieldOutlet } from '../../directives/df-field-outlet/df-field-outlet.directive';\nimport { outputFromObservable } from '@angular/core/rxjs-interop';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { derivedFromDeferred } from '@ng-forge/dynamic-forms/internal';\nimport { createFieldResolutionPipe, ResolvedField } from '../../utils/resolve-field/resolve-field';\nimport { computeContainerHostClasses, setupContainerInitEffect } from '../../utils/container-utils/container-utils';\nimport { PageField, validatePageNesting } from '@ng-forge/dynamic-forms/internal';\nimport { injectFieldRegistry } from '../../utils/inject-field-registry/inject-field-registry';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { NextPageEvent, PageChangeEvent, PreviousPageEvent } from '../../events/constants';\nimport { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { FORM_OPTIONS } from '@ng-forge/dynamic-forms/internal';\nimport { getGridClassString } from '@ng-forge/dynamic-forms/internal';\nimport { isContainerField } 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';\n\n/** Renders a single page in multi-page (wizard) forms. */\n@Component({\n selector: 'section[page-field]',\n imports: [DfFieldOutlet],\n template: `\n @for (field of resolvedFields(); track field.key; let i = $index) {\n @if (!field.hidden()) {\n @if (windowsField(field, i)) {\n @defer (on viewport) {\n <ng-container *dfFieldOutlet=\"field; environmentInjector: environmentInjector\" />\n } @placeholder {\n <div\n [class]=\"placeholderGridClass(field)\"\n [style.min-height]=\"fieldWindowing().placeholderHeight\"\n [attr.data-field-key]=\"field.key\"\n aria-hidden=\"true\"\n ></div>\n }\n } @else {\n <ng-container *dfFieldOutlet=\"field; environmentInjector: environmentInjector\" />\n }\n }\n }\n `,\n styleUrl: './page-field.component.scss',\n host: {\n '[class]': 'hostClasses()',\n '[class.disabled]': 'disabled()',\n '[class.df-page-visible]': 'isVisible()',\n '[class.df-page-hidden]': '!isVisible()',\n '[attr.aria-hidden]': '!isVisible()',\n '[attr.data-page-index]': 'pageIndex()',\n '[id]': '`${key()}`',\n '[attr.data-testid]': 'key()',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class PageFieldComponent {\n // ─────────────────────────────────────────────────────────────────────────────\n // Dependencies\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly destroyRef = inject(DestroyRef);\n private readonly fieldRegistry = injectFieldRegistry();\n private readonly injector = inject(Injector);\n protected readonly environmentInjector = inject(EnvironmentInjector);\n private readonly eventBus = inject(EventBus);\n private readonly logger = inject(DynamicFormLogger);\n private readonly formOptions = inject(FORM_OPTIONS, { optional: true });\n private readonly globalFieldWindowing = inject(FIELD_WINDOWING);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Inputs\n // ─────────────────────────────────────────────────────────────────────────────\n\n field = input.required<PageField>();\n key = input.required<string>();\n className = input<string>();\n pageIndex = input.required<number>();\n isVisible = input.required<boolean>();\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Computed Signals\n // ─────────────────────────────────────────────────────────────────────────────\n\n readonly hostClasses = computed(() => computeContainerHostClasses('page-field', this.className()));\n\n readonly disabled = computed(() => this.field().disabled || false);\n\n readonly isValid = computed(() => validatePageNesting(this.field()));\n\n /**\n * Effective field-windowing config for this page. Per-form\n * `FormOptions.fieldWindowing` wins over the global `withFieldWindowing()`\n * default; both fall back to disabled (fully eager).\n */\n protected readonly fieldWindowing = computed(() =>\n resolveFieldWindowing(this.globalFieldWindowing, this.formOptions?.()?.fieldWindowing),\n );\n\n private readonly rawFieldRegistry = computed(() => this.fieldRegistry.raw);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Outputs\n // ─────────────────────────────────────────────────────────────────────────────\n\n readonly nextPage = outputFromObservable(this.eventBus.on<NextPageEvent>('next-page'));\n readonly previousPage = outputFromObservable(this.eventBus.on<PreviousPageEvent>('previous-page'));\n readonly pageChange = outputFromObservable(this.eventBus.on<PageChangeEvent>('page-change'));\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Field Resolution\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly fieldsSource = computed(() => {\n if (!this.isValid()) {\n return [];\n }\n return this.field().fields || [];\n });\n\n protected readonly resolvedFields = derivedFromDeferred(\n this.fieldsSource,\n createFieldResolutionPipe(() => ({\n loadTypeComponent: (type: string) => this.fieldRegistry.loadTypeComponent(type),\n registry: this.rawFieldRegistry(),\n injector: this.injector,\n destroyRef: this.destroyRef,\n onError: (fieldDef: FieldDef<unknown>, error: unknown) => {\n const fieldKey = fieldDef.key || '<no key>';\n this.logger.error(\n `Failed to load component for field type '${fieldDef.type}' (key: ${fieldKey}) ` +\n `within page '${this.field().key}'. Ensure the field type is registered in your field registry.`,\n error,\n );\n },\n })),\n { initialValue: [] as ResolvedField[], injector: this.injector },\n );\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Constructor\n // ─────────────────────────────────────────────────────────────────────────────\n\n constructor() {\n this.setupEffects();\n }\n\n /**\n * Whether a field should be deferred by field windowing. Containers are never\n * windowed: they emit `ComponentInitializedEvent`, which the form's init\n * tracker counts, so deferring one would stall `initialized` until it scrolls\n * into view. Leaf fields carry no such count, so they defer freely.\n */\n protected windowsField(field: ResolvedField, index: number): boolean {\n const w = this.fieldWindowing();\n return w.enabled && index >= w.eager && !isContainerField(field.fieldDef);\n }\n\n /** Class string for a windowed field's placeholder — matches the real field's grid column. */\n protected placeholderGridClass(field: ResolvedField): string {\n const grid = getGridClassString(field.fieldDef);\n return grid ? `df-field-placeholder ${grid}` : 'df-field-placeholder';\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Private Methods\n // ─────────────────────────────────────────────────────────────────────────────\n\n private setupEffects(): void {\n setupContainerInitEffect(this.resolvedFields, this.eventBus, 'page', () => this.field().key, this.injector);\n\n explicitEffect([this.isValid, this.field], ([valid, pageField]) => {\n if (!valid) {\n this.logger.error(\n `Invalid configuration: Page '${pageField.key}' contains nested page fields. ` +\n `Pages cannot contain other pages. Consider using groups or rows for nested structure.`,\n pageField,\n );\n }\n });\n }\n}\n"]}
1
+ {"version":3,"file":"ng-forge-dynamic-forms-page-field.component-B7A2v1vN.mjs","mappings":";;;;;;;;AAwDc;YAKK;;AAEA;AACE;AACF;AACA;;AAEA;;;;;AAQjB;;;;;;YAQS;;AAEA;;AAEA;;AAET,IAKmB;;;;YAUV;AACA;AACA;YAMQ;AACf;AACE;;;;;AAKe;AAGf;AACA;;;AAGA;AACE;;;;AAOH;YAQH;;;AAIA;AAOE;AACA;;IAIQ;;;;;;AAYR;;;;;AAQA;;;AA3HiB;;;;;;;;;;;;;;;;;;;;;;;AAnCT;;;;;;;;;;;;;;;;;;;;AAwBR;AACA;AACA;AACA;AACA;AACA;AACA;AACA","names":[],"ignoreList":[],"sources":["../../../../packages/dynamic-forms/src/lib/fields/page/page-field.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, DestroyRef, EnvironmentInjector, inject, Injector, input } from '@angular/core';\nimport { DfFieldOutlet } from '../../directives/df-field-outlet/df-field-outlet.directive';\nimport { outputFromObservable } from '@angular/core/rxjs-interop';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { derivedFromDeferred } from '@ng-forge/dynamic-forms/internal';\nimport { createFieldResolutionPipe, ResolvedField } from '../../utils/resolve-field/resolve-field';\nimport { computeContainerHostClasses, setupContainerInitEffect } from '../../utils/container-utils/container-utils';\nimport { PageField, validatePageNesting } from '@ng-forge/dynamic-forms/internal';\nimport { injectFieldRegistry } from '../../utils/inject-field-registry/inject-field-registry';\nimport { EventBus } from '@ng-forge/dynamic-forms/internal';\nimport { NextPageEvent, PageChangeEvent, PreviousPageEvent } from '../../events/constants';\nimport { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { FORM_OPTIONS } from '@ng-forge/dynamic-forms/internal';\nimport { getGridClassString } from '@ng-forge/dynamic-forms/internal';\nimport { isContainerField } 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';\n\n/** Renders a single page in multi-page (wizard) forms. */\n@Component({\n selector: 'section[page-field]',\n imports: [DfFieldOutlet],\n template: `\n @for (field of resolvedFields(); track field.key; let i = $index) {\n @if (!field.hidden()) {\n @if (windowsField(field, i)) {\n @defer (on viewport) {\n <ng-container *dfFieldOutlet=\"field; environmentInjector: environmentInjector\" />\n } @placeholder {\n <div\n [class]=\"placeholderGridClass(field)\"\n [style.min-height]=\"fieldWindowing().placeholderHeight\"\n [attr.data-field-key]=\"field.key\"\n aria-hidden=\"true\"\n ></div>\n }\n } @else {\n <ng-container *dfFieldOutlet=\"field; environmentInjector: environmentInjector\" />\n }\n }\n }\n `,\n styleUrl: './page-field.component.scss',\n host: {\n '[class]': 'hostClasses()',\n '[class.disabled]': 'disabled()',\n '[class.df-page-visible]': 'isVisible()',\n '[class.df-page-hidden]': '!isVisible()',\n '[attr.aria-hidden]': '!isVisible()',\n '[attr.data-page-index]': 'pageIndex()',\n '[id]': '`${key()}`',\n '[attr.data-testid]': 'key()',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class PageFieldComponent {\n // ─────────────────────────────────────────────────────────────────────────────\n // Dependencies\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly destroyRef = inject(DestroyRef);\n private readonly fieldRegistry = injectFieldRegistry();\n private readonly injector = inject(Injector);\n protected readonly environmentInjector = inject(EnvironmentInjector);\n private readonly eventBus = inject(EventBus);\n private readonly logger = inject(DynamicFormLogger);\n private readonly formOptions = inject(FORM_OPTIONS, { optional: true });\n private readonly globalFieldWindowing = inject(FIELD_WINDOWING);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Inputs\n // ─────────────────────────────────────────────────────────────────────────────\n\n field = input.required<PageField>();\n key = input.required<string>();\n className = input<string>();\n pageIndex = input.required<number>();\n isVisible = input.required<boolean>();\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Computed Signals\n // ─────────────────────────────────────────────────────────────────────────────\n\n readonly hostClasses = computed(() => computeContainerHostClasses('page-field', this.className()));\n\n readonly disabled = computed(() => this.field().disabled || false);\n\n readonly isValid = computed(() => validatePageNesting(this.field()));\n\n /**\n * Effective field-windowing config for this page. Per-form\n * `FormOptions.fieldWindowing` wins over the global `withFieldWindowing()`\n * default; both fall back to disabled (fully eager).\n */\n protected readonly fieldWindowing = computed(() =>\n resolveFieldWindowing(this.globalFieldWindowing, this.formOptions?.()?.fieldWindowing),\n );\n\n private readonly rawFieldRegistry = computed(() => this.fieldRegistry.raw);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Outputs\n // ─────────────────────────────────────────────────────────────────────────────\n\n readonly nextPage = outputFromObservable(this.eventBus.on<NextPageEvent>('next-page'));\n readonly previousPage = outputFromObservable(this.eventBus.on<PreviousPageEvent>('previous-page'));\n readonly pageChange = outputFromObservable(this.eventBus.on<PageChangeEvent>('page-change'));\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Field Resolution\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly fieldsSource = computed(() => {\n if (!this.isValid()) {\n return [];\n }\n return this.field().fields || [];\n });\n\n protected readonly resolvedFields = derivedFromDeferred(\n this.fieldsSource,\n createFieldResolutionPipe(() => ({\n loadTypeComponent: (type: string) => this.fieldRegistry.loadTypeComponent(type),\n registry: this.rawFieldRegistry(),\n injector: this.injector,\n destroyRef: this.destroyRef,\n onError: (fieldDef: FieldDef<unknown>, error: unknown) => {\n const fieldKey = fieldDef.key || '<no key>';\n this.logger.error(\n `Failed to load component for field type '${fieldDef.type}' (key: ${fieldKey}) ` +\n `within page '${this.field().key}'. Ensure the field type is registered in your field registry.`,\n error,\n );\n },\n })),\n { initialValue: [] as ResolvedField[], injector: this.injector },\n );\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Constructor\n // ─────────────────────────────────────────────────────────────────────────────\n\n constructor() {\n this.setupEffects();\n }\n\n /**\n * Whether a field should be deferred by field windowing. Containers are never\n * windowed: they emit `ComponentInitializedEvent`, which the form's init\n * tracker counts, so deferring one would stall `initialized` until it scrolls\n * into view. Leaf fields carry no such count, so they defer freely.\n */\n protected windowsField(field: ResolvedField, index: number): boolean {\n const w = this.fieldWindowing();\n return w.enabled && index >= w.eager && !isContainerField(field.fieldDef);\n }\n\n /** Class string for a windowed field's placeholder — matches the real field's grid column. */\n protected placeholderGridClass(field: ResolvedField): string {\n const grid = getGridClassString(field.fieldDef);\n return grid ? `df-field-placeholder ${grid}` : 'df-field-placeholder';\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Private Methods\n // ─────────────────────────────────────────────────────────────────────────────\n\n private setupEffects(): void {\n setupContainerInitEffect(this.resolvedFields, this.eventBus, 'page', () => this.field().key, this.injector);\n\n explicitEffect([this.isValid, this.field], ([valid, pageField]) => {\n if (!valid) {\n this.logger.error(\n `Invalid configuration: Page '${pageField.key}' contains nested page fields. ` +\n `Pages cannot contain other pages. Consider using groups or rows for nested structure.`,\n pageField,\n );\n }\n });\n }\n}\n"]}
@@ -1,3 +1,3 @@
1
- export { q as AppendArrayItemEvent, B as BUILT_IN_FIELDS, s as ComponentAddonComponent, u as ConsoleLogger, v as DfTemplate, w as DynamicForm, E as EventDispatcher, x as FormClearEvent, y as FormResetEvent, z as FormSubmitEvent, I as InsertArrayItemEvent, M as MoveArrayItemEvent, N as NextPageEvent, G as PageChangeEvent, H as PopArrayItemEvent, J as PrependArrayItemEvent, K as PreviousPageEvent, R as RemoveAtIndexEvent, S as ShiftArrayItemEvent, T as TemplateAddonComponent, L as TextAddonComponent, O as arrayEvent, Q as createWrappers, U as isWrappersBundle, V as provideDynamicForm, W as sanitizeFormConfig, X as withAddonActions, Y as withCustomAddon, Z as withEventFormValue, _ as withFieldWindowing, $ as withLegacyStatusClasses, a0 as withLoggerConfig, a1 as withPagePreload, a2 as withValidationExecutionDefaults, a3 as withValueExclusionDefaults, a4 as wrapperProps } from './ng-forge-dynamic-forms-ng-forge-dynamic-forms-DtnrCyH2.mjs';
1
+ export { q as AppendArrayItemEvent, B as BUILT_IN_FIELDS, s as ComponentAddonComponent, u as ConsoleLogger, v as DfTemplate, w as DynamicForm, E as EventDispatcher, x as FormClearEvent, y as FormResetEvent, z as FormSubmitEvent, G as GoToPageEvent, I as InsertArrayItemEvent, M as MoveArrayItemEvent, N as NextPageEvent, H as PageChangeEvent, J as PagerStateEvent, K as PopArrayItemEvent, L as PrependArrayItemEvent, O as PreviousPageEvent, R as RemoveAtIndexEvent, S as ShiftArrayItemEvent, T as TemplateAddonComponent, Q as TextAddonComponent, U as arrayEvent, V as createWrappers, W as isWrappersBundle, X as provideDynamicForm, Y as sanitizeFormConfig, Z as withAddonActions, _ as withCustomAddon, $ as withEventFormValue, a0 as withFieldWindowing, a1 as withLegacyStatusClasses, a2 as withLoggerConfig, a3 as withPagePreload, a4 as withValidationExecutionDefaults, a5 as withValueExclusionDefaults, a6 as wrapperProps } from './ng-forge-dynamic-forms-ng-forge-dynamic-forms-BGRxIQ2V.mjs';
2
2
  export { DF_FIELD_TEMPLATES, DynamicFormError, DynamicFormLogger, NoopLogger, hasFormValue, isArrayField, isContainerField, isDisplayOnlyField, isFieldBoundContext, isFormStateCondition, isGroupField, isHiddenField, isLeafField, isPageField, isRowField, isSimplifiedArrayField, isValueBearingField, isWrapperTypeDefinition, resolveDynamicValue } from '@ng-forge/dynamic-forms/internal';
3
3
  //# sourceMappingURL=ng-forge-dynamic-forms.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-forge/dynamic-forms",
3
- "version": "1.2.0-next.2",
3
+ "version": "1.2.0-next.4",
4
4
  "description": "Type-safe, signal-powered dynamic forms for Angular. Build complex forms from configuration with full TypeScript inference.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -61,24 +61,30 @@ declare class PageChangeEvent implements FormEvent {
61
61
  previousPageIndex?: number | undefined);
62
62
  }
63
63
 
64
- /** State interface for the page orchestrator */
65
- interface PageOrchestratorState {
64
+ /** Navigation state of a paged form, as emitted by `PagerStateEvent`. */
65
+ interface PagerState {
66
66
  /** Current page index (0-based) */
67
67
  currentPageIndex: number;
68
68
  /** Total number of pages */
69
69
  totalPages: number;
70
- /** Whether the current page is the first page */
70
+ /** Whether the current page is the first visible page */
71
71
  isFirstPage: boolean;
72
- /** Whether the current page is the last page */
72
+ /** Whether the current page is the last visible page */
73
73
  isLastPage: boolean;
74
- /** Whether navigation is currently disabled */
75
- navigationDisabled: boolean;
76
74
  }
77
75
 
78
- declare class PageNavigationStateChangeEvent implements FormEvent {
79
- state: PageOrchestratorState;
80
- type: "page-navigation-state-change";
81
- constructor(state: PageOrchestratorState);
76
+ /**
77
+ * Event emitted whenever the pager state of a paged form changes.
78
+ *
79
+ * Unlike `PageChangeEvent`, which fires only when the active page changed, this
80
+ * fires on any change to the derived state — including when `isFirstPage` /
81
+ * `isLastPage` flip because a page's `hidden` logic toggled and the set of
82
+ * visible pages shifted, with the active page never moving.
83
+ */
84
+ declare class PagerStateEvent implements FormEvent {
85
+ state: PagerState;
86
+ readonly type: "pager-state";
87
+ constructor(state: PagerState);
82
88
  }
83
89
 
84
90
  /** Resolved field ready for rendering with ngComponentOutlet / DfFieldOutlet. */
@@ -251,8 +257,8 @@ declare class DynamicForm<TFields extends RegisteredFieldTypes[] = RegisteredFie
251
257
  initialized: _angular_core.OutputRef<boolean>;
252
258
  /** Emits when the current page changes in paged forms. */
253
259
  onPageChange: _angular_core.OutputRef<PageChangeEvent>;
254
- /** Emits when page navigation state changes (canGoNext, canGoPrevious, etc.). */
255
- onPageNavigationStateChange: _angular_core.OutputRef<PageNavigationStateChangeEvent>;
260
+ /** Emits when pager state changes (currentPageIndex, totalPages, isFirstPage, isLastPage). */
261
+ onPageNavigationStateChange: _angular_core.OutputRef<PagerStateEvent>;
256
262
  constructor();
257
263
  /**
258
264
  * Handles native form submission triggered by:
@@ -740,6 +746,22 @@ declare class FormSubmitEvent implements FormEvent {
740
746
  readonly type: "submit";
741
747
  }
742
748
 
749
+ /**
750
+ * Event dispatched to move a paged form to a specific page.
751
+ *
752
+ * Backward jumps are unconditional. Forward jumps validate every visible page
753
+ * between the current one and the target (the target itself is not validated);
754
+ * if one is invalid, navigation stops on the first invalid page.
755
+ */
756
+ declare class GoToPageEvent implements FormEvent {
757
+ /** The target page index (0-based) */
758
+ readonly pageIndex: number;
759
+ readonly type: "go-to-page";
760
+ constructor(
761
+ /** The target page index (0-based) */
762
+ pageIndex: number);
763
+ }
764
+
743
765
  /** Event dispatched to advance a paged form to the next page. */
744
766
  declare class NextPageEvent implements FormEvent {
745
767
  readonly type: "next-page";
@@ -978,5 +1000,5 @@ interface ArrayItemContext {
978
1000
  formValue?: unknown;
979
1001
  }
980
1002
 
981
- export { AppendArrayItemEvent, BUILT_IN_FIELDS, ComponentAddonComponent, ConsoleLogger, DfTemplate, DynamicForm, EventDispatcher, FormClearEvent, FormResetEvent, FormSubmitEvent, InsertArrayItemEvent, MoveArrayItemEvent, NextPageEvent, PageChangeEvent, PopArrayItemEvent, PrependArrayItemEvent, PreviousPageEvent, RemoveAtIndexEvent, ShiftArrayItemEvent, TemplateAddonComponent, TextAddonComponent, arrayEvent, createWrappers, isWrappersBundle, provideDynamicForm, sanitizeFormConfig, withAddonActions, withCustomAddon, withEventFormValue, withFieldWindowing, withLegacyStatusClasses, withLoggerConfig, withPagePreload, withValidationExecutionDefaults, withValueExclusionDefaults, wrapperProps };
982
- export type { AddonActionsFeature, AddonWarning, ArrayItemContext, ArrayItemDefinitionTemplate, ExtractFieldDefs, ExtractFormValue, InferWrapperRegistry, SanitizeFormConfigOptions, SanitizedFormConfig, WrapperRegistration, WrappersBundle };
1003
+ export { AppendArrayItemEvent, BUILT_IN_FIELDS, ComponentAddonComponent, ConsoleLogger, DfTemplate, DynamicForm, EventDispatcher, FormClearEvent, FormResetEvent, FormSubmitEvent, GoToPageEvent, InsertArrayItemEvent, MoveArrayItemEvent, NextPageEvent, PageChangeEvent, PagerStateEvent, PopArrayItemEvent, PrependArrayItemEvent, PreviousPageEvent, RemoveAtIndexEvent, ShiftArrayItemEvent, TemplateAddonComponent, TextAddonComponent, arrayEvent, createWrappers, isWrappersBundle, provideDynamicForm, sanitizeFormConfig, withAddonActions, withCustomAddon, withEventFormValue, withFieldWindowing, withLegacyStatusClasses, withLoggerConfig, withPagePreload, withValidationExecutionDefaults, withValueExclusionDefaults, wrapperProps };
1004
+ export type { AddonActionsFeature, AddonWarning, ArrayItemContext, ArrayItemDefinitionTemplate, ExtractFieldDefs, ExtractFormValue, InferWrapperRegistry, PagerState, SanitizeFormConfigOptions, SanitizedFormConfig, WrapperRegistration, WrappersBundle };