import * as _angular_core from '@angular/core'; import { Provider, EnvironmentProviders, InjectionToken, Signal, OnInit, OnDestroy, PipeTransform, Type, ElementRef } from '@angular/core'; import * as ngx_t_forms_types from 'ngx-t-forms-types'; import { NgxTFormsConfig, IFormActions, FormInterface, FormSlideInterface, InClassFormUtilsInterface, IWorkflowDocumentPicker, IBasicFormInput, IFileUploadInput, IDateRangePickerInput, ITextareaProperties, IToggleInput, IMatrixInput, IMultiple, IGetTreeResponse, IRunPipelineResponse, IPipelineGenerationResponse, InputDataTypes, FormInputBasicOptionInterface, LocalFormStateSelectorInterface, FormsStoreSelectorsInterface, FormListSection, ITowerFormSteps, WorkflowFunctionTypes, FileData, FormSubmissionStatus, IFormValidationOverride, FormColumnInputs, IFormChangeHistory, IStepOption, FormBuilderFunctions, ElementEditorTypes, ElementEditorInnerSectionElementInterface, ScoaInnerInput, IWorkflowOption, BlurHandleTypes, ITowerStepColumn, TreeNode, FlatNode, IArrayFunction, DocumentLitsLabelConfigInterfaceValueType, InputPipeTypes, EncryptedData, ImportProgress, ImportRowState, ValidationError, ElementTypes, DialogConfig, PropertyPath, DeepPropertyValue, FileUploadInputValueInterface, FormInterfaceMigration, ConfigurationValidTestInterface } from 'ngx-t-forms-types'; export { BlurHandleTypes, ConfigurationValidTestInterface, DeepPropertyValue, DialogConfig, DocumentLitsLabelConfigInterfaceValueType, ElementEditorInnerSectionElementInterface, ElementEditorTypes, EncryptedData, FileUploadInputValueInterface, FormBuilderFunctions, FormColumnInputs, FormInputBasicOptionInterface, FormInterface, FormInterfaceMigration, FormListSection, FormSubmissionStatus, IArrayFunction, IFormActions, IFormChangeHistory, IFormTour, IFormValidationOverride, IGetTreeResponse, IScoaAccount, ITowerStepColumn, IWorkflowOption, ImportProgress, ImportRowState, ImportRowStatus, InClassFormUtilsInterface, InputDataTypes, InputPipeTypes, LocalFormStateSelectorInterface, NgxTFormsConfig, OLD_FormInterface, PropertyPath, TreeNode, ValidationError, WorkflowFunctionTypes } from 'ngx-t-forms-types'; import * as rxjs from 'rxjs'; import { Observable, Subject } from 'rxjs'; import { PipelineStage } from 'mongoose'; import { s } from '@hashbrownai/core'; import { Router, ActivatedRoute } from '@angular/router'; import { MatStepper } from '@angular/material/stepper'; import { StepperSelectionEvent, StepState } from '@angular/cdk/stepper'; import { HttpClient } from '@angular/common/http'; import { FormGroup, FormControl } from '@angular/forms'; import * as ngx_ui_tour_core from 'ngx-ui-tour-core'; import { IStepOption as IStepOption$1 } from 'ngx-ui-tour-md-menu'; import { FlatTreeControl } from '@angular/cdk/tree'; import { MatTreeFlattener, MatTreeFlatDataSource } from '@angular/material/tree'; import { MatDialogRef } from '@angular/material/dialog'; /** @internal */ declare const enum NgxTFormsFeatureKind { SilencedConsole = 0, FormBuilder = 1, ImportTower = 2, HttpPipeline = 3, InputSecret = 4, RouterFormId = 5, FormSuggestions = 6 } interface NgxTFormsFeature { readonly kind: NgxTFormsFeatureKind; readonly providers: Provider[]; } /** * Registers ngx-t-forms with the application injector. * * @param config Runtime configuration (form actions, builder, etc.). * @param features Optional with*() extension features. * @returns EnvironmentProviders ready to drop into `bootstrapApplication`. * * @example * bootstrapApplication(AppComponent, { * providers: [ * provideNgxTForms(myConfig, withSilencedConsole(), withFormBuilder()), * ], * }); */ declare function provideNgxTForms(config: NgxTFormsConfig, ...features: NgxTFormsFeature[]): EnvironmentProviders; /** * @public * * Binds the default HTTP-backed {@link HttpPipelineRepository} to * {@link PIPELINE_REPOSITORY}. Required when the consumer uses any * pipeline-running feature (e.g. the pipeline-generator UI) and wants the * built-in HTTP transport. * * Consumers that supply their own {@link PipelineRepository} implementation * should bind it directly to {@link PIPELINE_REPOSITORY} instead of (or after) * calling this — provider order resolution applies. * * @example * bootstrapApplication(AppComponent, { * providers: [ * provideHttpClient(), * provideNgxTForms(config, withHttpPipeline()), * ], * }); */ declare function withHttpPipeline(): NgxTFormsFeature; /** * Registers the HMAC secret used to derive per-input encryption keys for the * signature input. Required only when the signature input is in use — if the * token is unbound at the point of encryption/decryption the library throws a * clear error rather than silently falling back to a baked-in default. * * @param secret High-entropy string supplied by the consumer (e.g. read from * their own `environment.ts` or a runtime config endpoint). * * @example * provideNgxTForms( * myConfig, * withInputSecret(environment.ngxTFormsInputSecret), * ) */ declare function withInputSecret(secret: string): NgxTFormsFeature; /** * Feeds {@link FormBuilderComponent} its `formId` from the activated route, * preserving the historical route-driven form loading. Shipped by default in * `provideNgxTForms`, so existing consumers see identical behaviour (D-B2 / §5.5); * a router-free build resolves {@link FORM_ROUTE_SOURCE} to `EMPTY` and the * builder loads from its `formId` input only. * * @example * provideNgxTForms(config, withRouterFormId()) * * @public */ declare function withRouterFormId(): NgxTFormsFeature; /** * @public * * Enables the **AI edit-suggestion reporting layer**. Binds the default * {@link FormSuggestionRegistryService} to {@link FORM_SUGGESTION_REGISTRY}, so * every live form tower reports its editable schema / values / validation and * external systems can propose optional edits through the token. * * Opt-in and tree-shakeable: without this feature the token is unbound and form * towers (which inject it `{ optional: true }`) do no suggestion work at all. * * Consumers that supply their own {@link FormSuggestionRegistry} implementation * should bind it directly to {@link FORM_SUGGESTION_REGISTRY} instead of (or * after) calling this — provider order resolution applies. * * @example * bootstrapApplication(AppComponent, { * providers: [ * provideNgxTForms(config, withFormSuggestions()), * ], * }); */ declare function withFormSuggestions(): NgxTFormsFeature; /** * Provides the action handlers (submit, save, cancel, etc.) that the forms * runtime invokes when the user interacts with form controls. Bound from the * `formActions` field of `NgxTFormsConfig` when the consumer calls * `provideNgxTForms`. * * @see provideNgxTForms */ declare const FORM_ACTIONS_TOKEN: InjectionToken; /** * Provides the active `FormInterface` definition rendered by the forms * runtime. Components downstream of the form host inject this token to read * the form configuration without coupling to the store. * * @see provideNgxTForms */ declare const FORM_CONFIG_TOKEN: InjectionToken; /** * Provides the active `FormSlideInterface` (the slide/step currently being * rendered). Scoped per slide by the form host so individual inputs can read * their slide context. * * @see provideNgxTForms */ declare const FORM_SLIDES_TOKEN: InjectionToken; /** * Provides the in-class utility object (`InClassFormUtilsInterface`) that * exposes shared helper functions to form input components — formatting, * validation helpers, and cross-input lookups. * * @see provideNgxTForms */ declare const UTILS_OBJECT_TOKEN: InjectionToken; /** * Provides the merged form-input descriptor injected into each individual * input element. The descriptor is an intersection of every supported input * shape (`IWorkflowDocumentPicker & IBasicFormInput & IFileUploadInput & * IDateRangePickerInput & ITextareaProperties & IToggleInput & IMatrixInput * & IMultiple`) so a single token can describe any rendered input. * * @see provideNgxTForms */ declare const FORM_INPUTS_TOKEN: InjectionToken; /** * Provides the `IMultiple` configuration to "multiple"-type inputs (inputs * that produce an array of values). Scoped per input instance. * * @see provideNgxTForms */ declare const MULTIPLE_FORM_INPUT_TOKEN: InjectionToken; /** * Provides a factory function that returns an `Observable` * representing the MSCOA chart-of-accounts tree. Consumers bind this token * to their backend lookup so MSCOA-aware inputs can lazily fetch the tree * without depending on a concrete HTTP client. * * @see provideNgxTForms */ declare const MSCOA_TREE_PROVIDER: InjectionToken<() => Observable>; /** * Provides the top-level `NgxTFormsConfig` supplied by the consumer when * calling `provideNgxTForms`. This is the root configuration token from * which `formActions`, `formBuilder`, and other runtime concerns are read. * * @see provideNgxTForms */ declare const NGX_T_FORMS_CONFIG_TOKEN: InjectionToken; /** * @public * * Abstract repository for MongoDB-aggregation-pipeline operations used by the * library's pipeline-generator UI. The default HTTP-backed implementation is * {@link HttpPipelineRepository}, bound by {@link withHttpPipeline}. * * Consumers may bind a custom implementation against * {@link PIPELINE_REPOSITORY} (e.g. for offline / mocked environments) by * providing an alternative `useClass` against the same token instead of (or * after) `withHttpPipeline()`. * * Only the methods that cross the HTTP boundary are abstracted here; pipeline * orchestration state (`pipeline$`, `chatHistory$`, etc.) remains inside the * adapter / generator UI per LP §9 (the repository owns I/O, not UI state). */ declare abstract class PipelineRepository { /** * Execute the given aggregation pipeline against the configured backend for * the supplied workflow. * * @param pipeline - Validated MongoDB aggregation stages to run. * @param workflowId - Identifier of the workflow whose schema the pipeline * targets. * @returns An observable that emits exactly one {@link IRunPipelineResponse} * then completes. Errors surface as a typed Error. */ abstract runPipeline(pipeline: PipelineStage[], workflowId: string): Observable; /** * Ask the configured backend to generate (or refine) an aggregation pipeline * from a natural-language query plus the workflow's document schema. * * @param query - The user's prompt. * @param schema - Document schema the generator should target. * @param threadId - Optional generator-session id (continues an in-flight * chat). * @param existingPipeline - The pipeline-so-far, for incremental refinement. * @param previousError - The last execution error to feed back into the * model, when applicable. */ abstract generatePipeline(query: string, schema: object, threadId: string | undefined, existingPipeline: PipelineStage[], previousError: string): Observable; /** * Fetch the document schema for the supplied workflow. * * @param workflowId - Identifier of the workflow whose schema to load. */ abstract getSchema(workflowId: string): Observable<{ schema: object; }>; } /** * @public * * Token binding the {@link PipelineRepository} abstraction. The default * HTTP-backed implementation is {@link HttpPipelineRepository}, registered by * {@link withHttpPipeline}. Consumers may substitute their own implementation * by binding `useClass` (or `useValue` for a mock) against this token. */ declare const PIPELINE_REPOSITORY: InjectionToken; /** * Secret used to derive per-input HMAC keys for client-side encryption of * sensitive form values (currently: signature input payloads). * * Consumers MUST configure this via {@link withInputSecret} when the * signature input is in use. The library does not ship a default — hardcoding * a secret inside a published library would render it public. * * Treat the value as opaque, high-entropy, and never derived from anything * the browser can read (e.g. `environment.ts` baked into the bundle is * acceptable for low-sensitivity rotation; HSM-backed values are better). * * @see withInputSecret */ declare const INPUT_SECRET_TOKEN: InjectionToken; /** * Optional source of the form id to load into {@link FormBuilderComponent}. * * Bound by `withRouterFormId()` (shipped by default in `provideNgxTForms`) to the * activated route's `formId` param. When unbound — e.g. a router-free build — the * builder loads from its `formId` input only. This decouples the builder from a * direct `ActivatedRoute` dependency (plan D-B2 / §5.5). * * @public */ declare const FORM_ROUTE_SOURCE: InjectionToken>; /** * @file Pure domain types for the **AI edit-suggestion reporting layer**. * * These types describe the read-only, real-time view of a live form that an * external AI system observes (the *editable schema* + current values + * validation state) and the shape of the *optional* value edits it may propose * for a user to preview and accept/reject. They are the wire contract between a * running form tower and the {@link FormSuggestionRegistry}. * * **Inner-ring rule (CLAUDE.md §0.3):** this module imports only `@angular/core` * (the `Signal` *type*) and type-only symbols from `ngx-t-forms-types` — all * erased at compile time. No runtime Angular concretions, no library internals. * * @see FormSuggestionRegistry — the injection-token port external AI consumes. */ /** * A single validation message currently surfaced for an editable field. * * Mirrors the engine's overridable-validation model: a `canOverride === true` * error does not block submission outright (the user may motivate a bypass), * whereas a blocking error (standard validators, business rules) must be * resolved. An external system can use this to avoid proposing values that * would re-trip a known constraint. */ interface EditableFieldError { /** Human-readable validation message. */ readonly message: string; /** `true` when the form may still submit with this error if motivated. */ readonly canOverride: boolean; /** The custom validator's id, when the error originates from one. */ readonly validatorId?: string; } /** * Validation constraints and live error state for one editable field. The * constraint fields are the static rules authored on the column; `errors` is the * live set failing right now (recomputed as values change). */ interface EditableFieldValidation { /** Whether a non-empty value is required. */ readonly required: boolean; /** Regex pattern the value must match, when authored. */ readonly pattern?: string; /** Minimum numeric/date constraint, when authored as a plain value. */ readonly min?: number | string; /** Maximum numeric/date constraint, when authored as a plain value. */ readonly max?: number | string; /** Minimum string length, when authored. */ readonly minLength?: number | string; /** Maximum string length, when authored. */ readonly maxLength?: number | string; /** Live validation messages currently failing on the field. */ readonly errors: readonly EditableFieldError[]; } /** * How a field's value must be expressed in a suggestion — the contract that * tells an external system whether it may send a raw value or a structured * intent the engine resolves: * - `scalar` — a plain value (string/number/boolean/date). * - `choice` — one of the field's {@link EditableFieldSchema.options} values. * - `multipleRow` — an item list; suggest rows via {@link MultipleRowSuggestionValue}. * - `mscoa` — an account selection; suggest an intent via {@link MscoaSuggestionValue} * (never a raw value — the engine resolves accounts via the host's search). */ type EditableFieldKind = 'scalar' | 'choice' | 'multipleRow' | 'mscoa'; /** One selectable segment of an MSCOA field (per accounting basis). */ interface MscoaSegmentDescriptor { /** The segment key a suggestion references (the input's `customSegment` || `segment`). */ readonly segment: string; /** Display label. */ readonly label: string; /** Which accounting basis this segment belongs to. */ readonly basis: 'accrual' | 'cash'; /** When `true`, one account fills both debit + credit (suggest `accountType: 'single'`). */ readonly singleSelect: boolean; /** Whether VAT selection is active for this segment. */ readonly vat: boolean; } /** One custom inner input of an MSCOA field (segment-scoped or account-level). */ interface MscoaInnerInputDescriptor { /** The input key a suggestion references (its `formControlName`). */ readonly key: string; /** Display label. */ readonly label: string; /** The element kind, as a string. */ readonly element: string; /** The segment id this input is scoped to, or absent for an account-level input. */ readonly segmentId?: string; } /** One currently-selected account on an MSCOA field, by account code, for delta proposals. */ interface MscoaCurrentSelection { readonly basis: 'accrual' | 'cash'; readonly segment: string; /** Currently-selected debit account code (`SCOAAccount`), if any. */ readonly debit?: string; /** Currently-selected credit account code (`SCOAAccount`), if any. */ readonly credit?: string; } /** * The capability block describing an MSCOA field — everything an external * system needs to propose a valid account selection without hand-building the * (un-authorable) `IScoaAccount` value objects. */ interface MscoaFieldCapability { /** `'accrual'`, `'cash'`, or `'dual'` (both). */ readonly accountingBasis: 'accrual' | 'cash' | 'dual'; /** Selectable segments across the active basis(es). */ readonly segments: readonly MscoaSegmentDescriptor[]; /** Custom inner inputs that can also carry suggested values. */ readonly inputs: readonly MscoaInnerInputDescriptor[]; /** Currently-selected accounts (by code) per basis/segment. */ readonly currentSelections: readonly MscoaCurrentSelection[]; } /** * The AI-visible projection of one **editable** form field. Excludes * structural, system, calculated, read-only/disabled, view-only and * tower-derived inputs — only fields a user (and therefore a suggestion) could * legitimately change. */ interface EditableFieldSchema { /** The field's stable id (the suggestion target — see {@link FieldSuggestion.fieldId}). */ readonly id: string; /** The field's `formControlName` (its key in the submitted payload). */ readonly formControlName: string; /** Id of the section the field belongs to. */ readonly sectionId: string; /** Display label. */ readonly label: string; /** The element kind (e.g. `'input'`, `'select'`, `'textarea'`), as a string. */ readonly element: string; /** The field's data type, for value coercion/formatting by the consumer. */ readonly dataType: InputDataTypes; /** * The value contract for suggesting to this field — tells the proposer whether * to send a raw value, a choice, an item-list of rows, or an MSCOA intent. */ readonly kind: EditableFieldKind; /** The field's current live value. */ readonly currentValue: unknown; /** * Selectable options (static or resolved from an API), when the field is a * choice input. Absent for free-text/numeric fields. */ readonly options?: readonly FormInputBasicOptionInterface[]; /** * The per-row child-field schema, present only for `kind: 'multipleRow'`. A * proposed row is an object keyed by these fields' `formControlName`s. */ readonly rowFields?: readonly EditableFieldSchema[]; /** The account-selection contract, present only for `kind: 'mscoa'`. */ readonly mscoa?: MscoaFieldCapability; /** Validation constraints + live error state. */ readonly validation: EditableFieldValidation; } /** * A point-in-time snapshot of a form's editable surface, as observed by an * external suggestion provider. Recomputed reactively as the tower adapts to * user input and async data loads. */ interface FormSuggestionSnapshot { /** The form's id, when the definition carries one. */ readonly formId: string | undefined; /** Every currently-editable field. */ readonly fields: readonly EditableFieldSchema[]; /** Whether the form is currently submittable (no blocking/unmotivated errors). */ readonly canSubmit: boolean; /** Whether any async work (calculation/fetch/submission) is in flight. */ readonly isBusy: boolean; } /** * A single proposed value edit for one editable field. Purely advisory — it is * staged for user review and never mutates the live form on its own. * * The shape of `value` is dictated by the target field's * {@link EditableFieldSchema.kind}: * - `scalar` / `choice` → the raw value (a `choice` must be an allowed option value). * - `multipleRow` → a {@link MultipleRowSuggestionValue} (or a bare rows array → appended). * - `mscoa` → a {@link MscoaSuggestionValue} intent (the engine resolves accounts). * A value that does not satisfy the field's kind is rejected on accept — it is * never written to the live form. */ interface FieldSuggestion { /** Target field id (matches {@link EditableFieldSchema.id}). */ readonly fieldId: string; /** The proposed value (shape per the field's {@link EditableFieldSchema.kind}). */ readonly value: unknown; /** Optional natural-language explanation, shown to the user during review. */ readonly rationale?: string; /** Optional model confidence in `[0, 1]`, shown to the user during review. */ readonly confidence?: number; } /** One account-selection intent for an MSCOA field (resolved by the engine). */ interface MscoaAccountSelection { /** Which accounting basis to write. */ readonly basis: 'accrual' | 'cash'; /** The target segment key (see {@link MscoaSegmentDescriptor.segment}). */ readonly segment: string; /** * Which leg to set. `'single'` (or omitted on a single-select segment) fills * both debit and credit with the resolved account. */ readonly accountType?: 'debit' | 'credit' | 'single'; /** Account code / number to resolve via the host account search (e.g. `SCOAAccount`). */ readonly query: string; } /** * The intent payload for an `mscoa` field suggestion. The engine resolves each * selection's `query` to a full account via the host's account search, assembles * the canonical MSCOA value, validates it, and only then commits. */ interface MscoaSuggestionValue { /** Per-(basis, segment) account selections to apply. */ readonly selections: readonly MscoaAccountSelection[]; /** Optional custom inner-input values to apply alongside the account selections. */ readonly inputs?: readonly { readonly basis?: 'accrual' | 'cash'; readonly segment?: string; readonly key: string; readonly value: unknown; }[]; } /** * The payload for a `multipleRow` field suggestion: rows to add to (or replace) * the item list. Each row is keyed by the child fields' `formControlName`s * (see {@link EditableFieldSchema.rowFields}). */ interface MultipleRowSuggestionValue { /** `'append'` (default) adds rows to the existing list; `'replace'` overwrites it. */ readonly mode?: 'append' | 'replace'; /** The proposed rows, each keyed by child `formControlName`. */ readonly rows: readonly Record[]; } /** * A batch of proposed edits from one external provider, addressed to a specific * form by id. */ interface SuggestionBatch { /** The form the batch targets (matches {@link FormSuggestionSnapshot.formId}). */ readonly formId: string | undefined; /** Identifier of the proposing system (for audit/attribution). */ readonly source: string; /** The proposed edits. */ readonly suggestions: readonly FieldSuggestion[]; } /** * A staged suggestion the user can preview and act on. Carries the value that * was current at propose time (`previousValue`) so a preview diff can be shown * and a reject can be reasoned about. Status moves `pending → accepted | rejected`. */ interface StagedSuggestion extends FieldSuggestion { /** Stage id, unique within the tower. */ readonly id: string; /** Identifier of the proposing system (carried from {@link SuggestionBatch.source}). */ readonly source: string; /** The field's value at the moment the suggestion was staged. */ readonly previousValue: unknown; /** * Lifecycle status: `pending` → user review; `resolving` → an async commit is * in flight (MSCOA account resolution); `accepted` → committed to the live * form; `rejected` → dismissed by the user; `invalid` → could not be applied * (see {@link StagedSuggestion.invalidReason}), never written. */ readonly status: 'pending' | 'resolving' | 'accepted' | 'rejected' | 'invalid'; /** Why the suggestion was rejected as invalid (present only when `status === 'invalid'`). */ readonly invalidReason?: string; } /** * The handle a live form tower hands the {@link FormSuggestionRegistry} when it * registers, exposing its reactive snapshot for AI subscribers and a sink that * routes proposed batches back into the tower's staging area. */ interface FormSuggestionChannel { /** The registering form's id (the registry's lookup key). */ readonly formId: string | undefined; /** Reactive editable-surface snapshot of the registering form. */ readonly snapshot: Signal; /** Routes a proposed batch into the tower's staging area for user review. */ readonly propose: (batch: SuggestionBatch) => void; } /** * @file The abstract **suggestion registry** port — the injection-token surface * an external AI system uses to observe live forms and propose optional edits. * * It mirrors the library's established port pattern (see * {@link PipelineRepository}): an abstract class in `domain/`, bound to a token * in `tokens/`, and wired to a concrete implementation by a `with*()` feature in * `config/`. Consumers inject the {@link FORM_SUGGESTION_REGISTRY} token, never a * concrete class. * * The registry is a pure **mediator**: it holds no form logic. Live form towers * register a {@link FormSuggestionChannel} when they initialize and deregister on * teardown; AI subscribers read snapshots and route proposals through it. */ /** * @public * * Port for external AI systems to observe live, editable forms and propose * optional value edits. Bound to {@link FORM_SUGGESTION_REGISTRY} by * {@link withFormSuggestions}. * * Addressing is by `formId`: several form towers can be live at once * (a user form, a builder preview, …), so subscribers target a specific form by * id and proposals carry the id they apply to. Transient import-row towers do * not register. * * @example * // In an AI integration service: * readonly #registry = inject(FORM_SUGGESTION_REGISTRY); * * suggest(formId: string): void { * this.#registry.snapshot(formId) * .pipe(takeUntilDestroyed(this.#destroyRef)) * .subscribe(async snapshot => { * if (!snapshot) return; * const suggestions = await this.model.propose(snapshot.fields); * this.#registry.propose({ formId, source: 'my-model', suggestions }); * }); * } */ declare abstract class FormSuggestionRegistry { /** * Reactive editable-surface snapshot for one form, by id. Emits `undefined` * while no form with that id is registered, then the live snapshot once one * registers (and again whenever its schema/values/validation change). Lazy — * the underlying schema is only computed while subscribed. * * @param formId - The target form's id. * @returns An observable of the form's snapshot, or `undefined` when absent. */ abstract snapshot(formId: string): Observable; /** * Reactive snapshots of every currently-registered form. Emits a new array * whenever a form registers/deregisters or any registered form's snapshot * changes. * * @returns An observable of all live form snapshots. */ abstract snapshots(): Observable; /** * The ids of the currently-registered live forms (forms with an `undefined` * id are omitted). Reactive — recomputes as towers register/deregister. * * @returns A signal of the active form ids. */ abstract activeFormIds(): Signal; /** * Route a batch of proposed edits to the registered form matching * `batch.formId`. The proposals are staged for user review on that form (the * live form is not mutated). No-op when no matching form is registered. * * @param batch - The proposed edits and their target form id. */ abstract propose(batch: SuggestionBatch): void; /** * Register a live form's channel. Called by the form tower on initialize. * * @internal * @param channel - The tower's snapshot + proposal sink. * @returns A handle used to {@link FormSuggestionRegistry.deregister} this exact registration. */ abstract register(channel: FormSuggestionChannel): object; /** * Deregister a previously-registered channel by its handle. Called by the * form tower on teardown / re-initialization. * * @internal * @param handle - The handle returned by {@link FormSuggestionRegistry.register}. */ abstract deregister(handle: object): void; } /** * @public * * Token binding the {@link FormSuggestionRegistry} port — the surface external * AI systems use to observe live editable forms and propose optional edits. * Bound to the default {@link FormSuggestionRegistryService} by * {@link withFormSuggestions}; consumers may substitute their own implementation * by binding `useClass` (or `useValue` for a mock) against this token instead. * * Unbound by default — the suggestion layer is opt-in and fully tree-shakeable. * Form towers inject it `{ optional: true }`, so when the feature is not * installed they simply do not report (zero cost). */ declare const FORM_SUGGESTION_REGISTRY: InjectionToken; /** * @public * * Default HTTP-backed implementation of {@link PipelineRepository}. Bound by * {@link withHttpPipeline}; consumers needing a different transport should * provide their own implementation against {@link PIPELINE_REPOSITORY}. * * The endpoint host (`http://localhost:5000`) is preserved from the pre-Phase-2 * `PipelineService` for I-1 parity. Configurable endpoints are tracked for a * later phase — do not widen this surface ad-hoc. */ declare class HttpPipelineRepository implements PipelineRepository { #private; runPipeline(pipeline: PipelineStage[], workflowId: string): Observable; generatePipeline(query: string, schema: object, threadId: string | undefined, existingPipeline: PipelineStage[], previousError: string): Observable; getSchema(workflowId: string): Observable<{ schema: object; }>; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵprov: _angular_core.ɵɵInjectableDeclaration; } /** * @file Default {@link FormSuggestionRegistry} implementation — a root-level * mediator between per-component form towers and external AI subscribers. * * Holds a reactive set of registered {@link FormSuggestionChannel}s. Towers * register on initialize / deregister on teardown; subscribers read snapshots * and route proposals. The service owns **no form logic** — `propose` simply * forwards a batch to the channel whose `formId` matches. * * Provided **only** via {@link withFormSuggestions} (no `providedIn` — it has no * config but is opt-in, so it must not auto-register at root; LP §8 / LIB-02). */ declare class FormSuggestionRegistryService extends FormSuggestionRegistry { #private; /** @internal */ register(channel: FormSuggestionChannel): object; /** @internal */ deregister(handle: object): void; snapshots(): Observable; snapshot(formId: string): Observable; activeFormIds(): Signal; propose(batch: SuggestionBatch): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵprov: _angular_core.ɵɵInjectableDeclaration; } /** * @file Builds a Hashbrown **Skillet** schema (`@hashbrownai/core`) from a live * {@link FormSuggestionSnapshot}, so an LLM's structured output is constrained to * the form's *actual* dynamic shape — correct per-field types, enumerated * options, item-list row objects, and MSCOA account-selection intent. * * The schema regenerates from each snapshot, so it adapts as the tower adapts * (new fields, resolved options, changed validation). Each builder takes a human * description first, which the model reads as guidance. * * `@hashbrownai/core` is a **peer dependency** — the consuming app owns and * installs it; importing this builder is what pulls it in. * * @see toSuggestionBatch — converts the LLM's output back into a SuggestionBatch. */ /** * Builds a Skillet schema describing the suggestions an LLM may propose for a * form, keyed by field id: each value is the field's correctly-typed schema or * `null` (leave unchanged). Feed the result to a Hashbrown structured-output API * (e.g. `structuredCompletionResource({ schema })`), then convert the model's * output with {@link toSuggestionBatch} and route it to `FORM_SUGGESTION_REGISTRY`. * * @param snapshot - A live editable-form snapshot (from `FORM_SUGGESTION_REGISTRY.snapshot()`). * @param options - `streaming: true` builds a streamable schema (`s.streaming.object`). * @returns A Skillet schema (`s.object` / `s.streaming.object`) for the suggestion payload. * * @example * const schema = buildSuggestionSchema(snapshot); * const result = structuredCompletionResource({ model, input, schema }); * registry.propose(toSuggestionBatch(snapshot.formId, 'my-model', result.value() ?? {})); */ declare function buildSuggestionSchema(snapshot: FormSuggestionSnapshot, options?: { streaming?: boolean; }): s.HashbrownType; /** * @file Converts the keyed output of an LLM structured completion (driven by * {@link buildSuggestionSchema}) back into a {@link SuggestionBatch} ready for * `FORM_SUGGESTION_REGISTRY.propose()`. * * The schema is keyed by field id with `null` meaning "leave unchanged", so this * simply drops `null`/`undefined` entries and forwards each remaining value * verbatim — the engine's per-kind resolvers interpret it (raw scalar/choice, * a `MultipleRowSuggestionValue` rows array, or an `MscoaSuggestionValue`). */ /** * Builds a {@link SuggestionBatch} from a Skillet structured-output result. * * @param formId - The form the suggestions target (use the snapshot's `formId`). * @param source - Identifier of the proposing system (for audit/attribution). * @param output - The LLM output keyed by field id (values, or `null` to skip). * @returns A batch containing one {@link FieldSuggestion} per non-null field. */ declare function toSuggestionBatch(formId: string | undefined, source: string, output: Record): SuggestionBatch; /** * Renders the list of forms a user can open, edit, or build, with search, * grouping (system vs custom), and section switching (active / archived / * deleted) wired through the consumer-supplied `formBuilder` config. * * @remarks * The component reads its data from `FormsStoreService` (provided locally) * and reads the consumer's `NgxTFormsConfig` from {@link NGX_T_FORMS_CONFIG_TOKEN} * to discover the close-button template and form CRUD callbacks * (`editForm`, `addNewForm`). * * Inputs: * - _None._ The component is driven entirely by the activated route and * the injected forms store. * * Outputs: * - _None._ User intents (archive / unarchive / delete / edit / add) are * delegated to the store and to the consumer's `formBuilder` config. */ declare class FormsComponent implements OnInit { #private; selectFormsList$: Observable; selectGroupedForms$: Observable>; searchQuery$: Observable; selectHasActiveSearch$: Observable; selectFilteredGroupedForms$: Observable>; selectLoadingForms$: Observable; selectErrors$: FormsStoreSelectorsInterface['selectErrors$']; selectFormListSection$: Observable; NGX_T_FORMS_CONFIG: ngx_t_forms_types.NgxTFormsConfig; closeButton: ngx_t_forms_types.ActionButton; get formListSections(): Array<{ value: FormListSection; label: string; }>; viewportWidth: number; ngOnInit(): void; labels: { label: string; formControlName: string; }[]; activeForm: string | null; getCols(): number; getFormAvatar(formTitle: string): string; archive(form: LocalFormStateSelectorInterface, event: Event): Promise; unarchive(form: LocalFormStateSelectorInterface, event: Event): Promise; delete(form: LocalFormStateSelectorInterface, event: Event): Promise; loadForms(): void; router: Router; activatedRoute: ActivatedRoute; setSection(value: FormListSection): void; editForm(form: LocalFormStateSelectorInterface): void; addNewForm(): void; clearSearch(): void; get searchQuery(): string; set searchQuery(v: string); static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } /** * Editor surface for authoring a form definition — sections, steps, and * the individual inputs in each step. Hosts the section stepper, input * editor, builder menu, and missing-config diagnostics. * * @remarks * The component reads its state and effects from a locally provided * `FormsStoreService` and pulls the consumer-supplied close-button template * from {@link NGX_T_FORMS_CONFIG_TOKEN}. Form loading is driven either by * the `formId` input or by the activated route's `formId` param. * * Inputs: * - `formId: string` (optional) — when set, triggers `loadForm$` on the store. * * Outputs: * - _None._ All save/refresh intents are dispatched through the local store. * * @public * @deprecated Migrating to the strict library mandates. Public surface is * preserved verbatim; internal authoring is being refactored. */ declare class FormBuilderComponent { #private; /** Form-load spinner. */ readonly selectLoadingForm: _angular_core.Signal; /** Builder busy (saving / mutating). */ readonly selectFormBuilderIsBusy: _angular_core.Signal; /** "Updated N days ago" label, or null. */ readonly selectFormUpdated: _angular_core.Signal; /** Whether the current form passes validation and can be saved. */ readonly canSaveForm: _angular_core.Signal; /** Whether the form in edit is unsaved (no formId yet). */ readonly isNewForm: _angular_core.Signal; /** Optional form identifier. When set, triggers `loadForm$` on the local store. */ readonly formId: _angular_core.InputSignal; /** Whether a form id is present in the store. */ readonly selectHasFormId: _angular_core.Signal; /** Whether the form has missing/invalid configuration. */ readonly hasMissingConfigs: _angular_core.Signal; /** Whether an input editor panel is currently open. */ readonly elementEditorOpen: _angular_core.Signal; pendingExternalRefresh: _angular_core.Signal<{ form: ngx_t_forms_types.FormInterface; timestamp: Date; } | null>; refreshCountdown: _angular_core.WritableSignal; constructor(); triggerRefreshNow(): void; readonly NGX_T_FORMS_CONFIG: ngx_t_forms_types.NgxTFormsConfig; readonly closeButton: ngx_t_forms_types.ActionButton; saveForm: () => void; /** Editable form title — seeded from the store, overridable by local edits. */ protected readonly titleValue: _angular_core.WritableSignal; /** Pushes a title edit to the store (schedule-only refresh, matching `setFormTitle`). */ protected setTitleValue(value: string): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } /** * Angular-aware view of {@link ITowerFormSteps}. The shared `ngx-t-forms-types` * package keeps `sectionForm` opaque (`unknown`) so it carries no `@angular/forms` * dependency. Inside this library the value is always a reactive `FormGroup`, so * we re-narrow it here for template binding and call-site type safety. A * `TowerFormStep` remains assignable to `ITowerFormSteps`. */ interface TowerFormStep extends Omit { sectionForm: FormGroup | null; } /** * Workflow function-type enum, upstreamed to `ngx-t-forms-types` as * {@link WorkflowFunctionTypes} per DECISIONS.md D-016. Re-exported here under * its historical name `FunctionTypes` to preserve every existing local import * path (including the immutable `form-tower-controller.service.ts` per D-007). * * @public */ declare const FunctionTypes: typeof WorkflowFunctionTypes; type FunctionTypes = WorkflowFunctionTypes; declare enum HintType { WARNING = "warning", ERROR = "error", SUCCESS = "success", LOADING = "loading", INFO = "info", QUESTION = "question", CRITICAL = "critical", PENDING = "pending", BLOCKED = "blocked", COMPLETED = "completed", CANCELLED = "cancelled", DEFAULT = "default", QUERY_SUCCESS = "query_success", DB_LOAD = "db_load", CALCULATED = "calculated", TAG = "tag", DOCUMENT = "document", HISTORY = "history" } /** * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare function textIconsForUserHints(hint: string, type: HintType): string; /** * @file Pure helpers for the **overridable validation** submission gate. * * A custom validator declared with `canOverride === true` does not block * submission outright. The gate distinguishes two error classes across the * settled form: * * - **Blocking** — every error that is NOT an overridable custom-validator * error: standard validators (`required`, `email`, `minlength`, …), MSCOA * business-rule errors, and custom validators with `canOverride === false`. * These MUST be resolved before the form can be submitted. * - **Overridable** — a custom-validator error whose value object carries * `canOverride === true`. The form may be submitted with these still failing * **provided each one is motivated** with a non-empty comment. * * The error-record shape these helpers read is produced verbatim by the * {@link FunctionTypes.ManualValueValidation} builder * (`build-manual-validation.ts`): `{ [validatorId]: { message, canOverride } }`, * merged onto `control.errors` by the W11 projection adapter. A validator id is * a uuid unique per `(input, validator)`, so it uniquely keys an override * reason. * * All functions here are pure reads over the projected `FormGroup` tree and the * tower's `allFormInputs()` index — no signal writes, no Angular runtime * primitives created. They are safe to call from template getters during change * detection (mirrors `getSubmissionStatus.ts`). */ /** * A still-failing overridable custom validation surfaced to the override UI. */ interface OverridableError { /** The custom validator's id — the `control.errors` key and the reason key. */ validatorId: string; /** The owning input's id (its control name within the section group). */ inputId: string; /** The owning input's `formControlName`, used to build the submission entry. */ formControlName: string; /** The input's display label, for the override-reason prompt. */ label: string; /** The validator's human-readable message. */ message: string; } /** * A single captured override motivation, keyed in the engine by `validatorId`. */ interface OverrideReason { /** User-supplied motivation. Must be non-empty (trimmed) to unlock submission. */ comment: string; /** Optional supporting file, carried as base64 {@link FileData}. */ attachment?: FileData; } /** Map of `validatorId → captured reason`. The engine's override-reason state. */ type OverrideReasons = Record; /** * Core orchestrator for a runtime form (the "tower") — abstract because every * concrete consumer (`TFormEngine`, the import row instance) extends it and * Angular's DI provides {@link HttpClient} + {@link NGX_T_FORMS_CONFIG_TOKEN}. * * ### Lifecycle (Phase 1) * 1. **{@link FormTowerControllerService.initialize}** — prepPopulate + * loadSystemInputs + formGenerator + setFirstStepAsActive, then builds the * per-input `#derived` signal graph (in injection context) and wires the * FormGroup-projection + persist effects. There is NO `valueChanges` * subscription and NO dependency-graph build. * 2. **{@link FormTowerControllerService.initializeFormValues}** — writes * user/import values into `#model` (tower-owned derived inputs are skipped * structurally) and forces a liveness lead-read so lazy resources start. * 3. User interaction / `updateValue` → writes `#model` (or a sourced * `linkedSignal.set`) → derived signals + resources recompute automatically. * 4. **{@link FormTowerControllerService.waitUntilSettled}** — used by headless * consumers (import) to wait for all in-flight async work to drain. * 5. **{@link FormTowerControllerService.ngOnDestroy}** — explicitly destroys * every resource, the projection/persist effects, the `isBusy$` * subscription, and clears hint/error timers. * * ### Why an abstract `@Directive()`? * Angular requires the `@Directive()` decorator on classes that participate in * DI inheritance + `OnDestroy`. Subclasses can be plain `@Injectable()` (see * {@link TFormEngine}). */ declare abstract class FormTowerControllerService implements OnDestroy { #private; private _http; /** Resolved tower config (HTTP functions, file upload, getFinacialCycles, …). */ readonly NGX_T_FORMS_CONFIG: ngx_t_forms_types.NgxTFormsConfig; /** Convenience pass-through to the financial-cycles fetcher from config. */ readonly getFinacialCycles: () => Observable; constructor(_http: HttpClient); /** Emits exactly once on tower destruction. `takeUntil` anchor for long-lived subscriptions. */ protected _destroyed$: Subject; /** Live root `FormGroup` — the Material carrier (Blueprint §2.7). Built by `formGenerator`. */ protected _mainForm: FormGroup | undefined; /** The values record last passed to {@link FormTowerControllerService.initializeFormValues}. */ protected _initialFormValue: Record; /** Last reported submission state — drives the toolbar/spinner UI. */ submittingStatus: FormSubmissionStatus | undefined; /** True while a form submission is in flight. Counts toward {@link FormTowerControllerService.isBusy}. */ get submittingForm(): boolean; set submittingForm(value: boolean); /** * The still-failing overridable (`canOverride === true`) validations on the * settled form, one per failing validator, each carrying the input's * `formControlName` / `label` and the validator message — the data the * override-reason UI renders a motivation prompt from. * * Reads the projected control tree, so it reflects the latest validity. When * there are blocking errors as well, those still prevent submission — see * {@link FormTowerControllerService.canSubmit}. */ overridableErrors: () => OverridableError[]; /** * `true` when at least one blocking (non-overridable) error remains on the * form. While this holds, submission is impossible regardless of motivations. */ hasBlockingErrors: () => boolean; /** * Whether the form may be submitted: no blocking errors AND every overridable * error has a non-empty motivation. Replaces the blunt `mainForm.invalid` * submit gate — an overridable error with a reason no longer blocks. */ canSubmit: () => boolean; /** The currently captured override motivations, keyed by validator id. */ get overrideReasons(): OverrideReasons; /** * Records (or updates) the motivation comment for one overridable validation. * * @param validatorId - The validator's id (the `control.errors` key). * @param comment - The user's motivation; an empty/whitespace value * re-locks submission for that error. */ setOverrideComment: (validatorId: string, comment: string) => void; /** * Attaches (or clears) a supporting file for one overridable validation. * * @param validatorId - The validator's id (the `control.errors` key). * @param attachment - The base64 {@link FileData}, or `undefined` to clear. */ setOverrideAttachment: (validatorId: string, attachment: FileData | undefined) => void; /** * Drops the captured reasons for the given validator ids. Called once a * MultipleInput sub-row is saved — its motivations move from the live * reason map into {@link FormTowerControllerService.#rowOverrides}, and the * transient controls (and thus the live overridable errors) are removed. * * @param validatorIds - The validator ids whose live reasons to drop. */ clearOverrideReasons: (validatorIds: readonly string[]) => void; /** * Records (or clears) the captured override entries for one MultipleInput * sub-row. Replacing on every save keeps a re-edited row's motivations * current; passing an empty list removes the row's entry. * * @param inputId - The MultipleInput's id. * @param rowId - The sub-row's id (`${inputId}.id` value). * @param entries - The override entries captured for the row. */ setRowOverrides: (inputId: string, rowId: string, entries: IFormValidationOverride[]) => void; /** * Builds the override entries for the currently-open inner inputs of a * MultipleInput sub-row, pairing each overridable error with its captured * motivation. Returns the entries plus the validator ids consumed (so the * caller can move them out of the live reason map after the row is saved). * * @param inputId - The MultipleInput's id. * @param innerInputs - The sub-row's inner inputs (composite-id form inputs). * @returns The sub-row's override state: motivated `entries` ready to persist, * the `validatorIds` consumed, and the inner input ids that are blocking or * still unmotivated (for save-gate messaging). */ collectRowOverrideState: (inputId: string, innerInputs: FormColumnInputs[]) => { entries: IFormValidationOverride[]; validatorIds: string[]; blockingInputIds: string[]; unmotivatedInputIds: string[]; }; /** The current form definition (post-{@link prepPopulateForm}). */ get form(): FormInterface | undefined; set form(value: FormInterface | undefined); /** System inputs loaded by `loadSystemInputs`, prepended to {@link FormTowerControllerService.allFormInputs}. */ get systemInputs(): FormColumnInputs[]; set systemInputs(value: FormColumnInputs[]); /** Live root `FormGroup` — `undefined` before {@link FormTowerControllerService.initialize}. */ get mainForm(): FormGroup | undefined; /** Append-only change history; used by {@link FormTowerControllerService.revertBackHistory}. */ get changeHistory(): IFormChangeHistory[]; set changeHistory(value: IFormChangeHistory[]); /** * Whether a form input is currently revealed by its conditional-display rules. * * Reads the input's live visibility signal, so calling this from a template or * a `computed` makes that consumer re-evaluate whenever the rule's observed * inputs change. An input that declares no `conditionalInputConfig` is always * visible and costs nothing to ask about. * * @param inputId - The input id. For MultipleInput sub-row fields and mSCOA * inner inputs this is the composite `${columnId}.${childId}`. * @returns `true` when the input is revealed, `false` when it is hidden. * * @example * ```ts * const visibleColumns = computed(() => * step.columns.filter((col) => tower.isInputVisible(col.id)), * ); * ``` */ isInputVisible: (inputId: string) => boolean; /** * Whether a section still has anything to show. * * A section whose every column is hidden by a conditional rule is not an empty * step to page through — it is a section that does not apply. It is reported * hidden so the stepper can drop it entirely. * * A section that was authored with **no columns at all** stays visible: that is * an empty section the author made, not one this feature emptied, and hiding it * would change the behaviour of forms that declare no rules. * * Reads the visibility signals of the section's columns, so a consumer calling * this from a template or `computed` re-evaluates when a rule flips. * * @param sectionId - The slide's `sectionId`. * @returns `true` when the section should be rendered. * * @example * ```ts * const steps = computed(() => * tower.selectFormSteps().filter((s) => tower.isSectionVisible(s.sectionId)), * ); * ``` */ isSectionVisible: (sectionId: string) => boolean; /** * Busy iff a submission is in flight OR any value/options resource is * `'loading'`. Reading every resource's `status()` here is what ACTIVATES the * lazy resources — workers MUST NOT short-circuit before iterating * (resource-activation contract, Blueprint §2.4 / HAZARD 2). */ protected readonly isBusyComputed: Signal; /** Strict complement of {@link FormTowerControllerService.isBusyComputed}. */ protected readonly settled: Signal; /** Synchronous snapshot of the busy state. */ get isBusy(): boolean; /** * Reactive stream of the tower's busy state. Emits `true` while any * calculation/API/validation is in flight or the form is submitting, `false` * once everything settles. Backed by `toObservable(isBusy)`. */ get isBusy$(): Observable; /** * Resolves once the tower has finished all in-flight async work (calculations, * API fetches, sourced values). Used by headless consumers (import). * * **Contract (Blueprint §5 / §6, never changes):** * - Performs a one-tick liveness lead-read FIRST (reads `value()` + every * resource `status()` + flushes effects) so lazy resources start even when * no template reads them (HAZARD 2). * - Waits for the first `settled() === true` emission. * - On `timeoutMs` it resolves with `undefined` — it NEVER rejects and NEVER * hangs (`timeout` + `defaultIfEmpty`-equivalent via `catchError`). * * @param debounceMs - Accepted for signature parity; the signal graph needs no * debounce, so it is treated as a no-op lead time. * @param timeoutMs - Hard timeout before resolving with `undefined` (default 30s). * @returns A promise that always resolves (with `void`). */ waitUntilSettled(debounceMs?: number, timeoutMs?: number): Promise; /** * Tears the tower down. Fires `_destroyed$`, runs * {@link FormTowerControllerService.clearFormState} (which destroys resources * + effects), completes the `isBusy$` subscription, and clears pending * hint/error timers (HAZARD 7 / Blueprint §2.8). */ ngOnDestroy(): void; /** * Boots the tower against a form definition. * * Performs, in order: * 1. {@link FormTowerControllerService.clearFormState} — wipe prior state + * destroy any prior resources/effects. * 2. {@link prepPopulateForm} — merge `_initialFormValue` into the columns. * 3. {@link loadSystemInputs} — load financial cycle, current user, etc. * 4. {@link formGenerator} — build the nested `FormGroup` carrier. * 5. Re-open any `MultipleInput` that was open before re-init. * 6. Build the `#derived` signal graph + wire the projection/persist effects * — ALL inside `runInInjectionContext(this.#injector, …)` (HAZARD 1). * * @param form - The form definition to drive. * @param options - Optional behaviour flags. * @param options.skipInitialFunctions - **Documented no-op (parity).** The * old engine used this to suppress a premature change-monitor cycle in the * headless import path. The signal graph has no such race (resources fire * lazily once read; the liveness lead-read in * {@link FormTowerControllerService.initializeFormValues} + * {@link FormTowerControllerService.waitUntilSettled} activates them), so * the flag is accepted for signature parity and otherwise ignored. */ initialize: (form: FormInterface, options?: { skipInitialFunctions?: boolean; }) => Promise; /** * Marks the form's first slide as active. Called during * {@link FormTowerControllerService.initialize}. */ setFirstStepAsActive: () => void; /** * Returns the form's settled values keyed by **formControlName** (the * canonical external shape). Reads {@link FormTowerControllerService.value}. */ getFormValueNames: () => Record; /** * All form inputs that participate in the form, including system inputs. * Returns a fresh outer array each call (preserves the prior contract that * callers may mutate the returned array), but the expensive flatten beneath it * is memoized by {@link FormTowerControllerService.#allInputsMemo}. */ readonly allFormInputs: () => FormColumnInputs[]; /** @deprecated unused field, kept for backwards compatibility. */ prevValue: any; /** * Mark a logical operation in flight for DOM badge rendering. Phase 1: no * longer affects {@link FormTowerControllerService.isBusy} (busy is * resource-derived) — forwards to the DOM-status helper only. */ setInputStatus: (inputId: string, statusId: string, status: string) => void; /** Companion to {@link FormTowerControllerService.setInputStatus} — clears the DOM badge. */ removeInputStatus: (inputId: string, statusId: string) => void; /** * Programmatic write to a form input. * * - **Sourced inputs** (InputSourcedValue) → routes to the entry's writable * `linkedSignal.set(value)` (transient override; reset on next source change). * - **All other inputs** → writes `#model[inputId]`. * * A **MultipleInput** row array is passed through * {@link FormTowerControllerService.#withRowIds} first, so no row can enter the * tower without an id (see {@link ensureMultipleInputRowIds}). This is the * choke point for every non-derived ingress: prefill/import * ({@link FormTowerControllerService.initializeFormValues}), accepted * suggestions, row deletes from the table view, and direct consumer writes. * * Appends the change to history IMPERATIVELY (HAZARD 4). The projection effect * patches the FormControl from the signal graph — this does NOT touch the * FormGroup directly (no `valueChanges` feedback loop). * * @param inputId - The input to write. * @param value - The new value. */ updateValue: (inputId: string, value: any) => void; /** * Apply an external values record onto the form (user prefill / import row). * * Per input: * - **Tower-owned non-MultipleInput** (calc/API/sourced) → SKIP structurally * (it never enters `#model`; the derived signal/resource owns the value). * - **MultipleInput** → ALWAYS apply the row array (its rows are user-authored * source data). The array-remap branch is UNCHANGED (Phase 2 fence). * - **Everything else** → write `#model` from the dotted-path or top-level value. * * Ends with a liveness lead-read so lazy resources start even in the headless * import path (no template reader) — HAZARD 2 / Blueprint §2.7. * * @param initialValues - The external values record (formControlName-keyed). */ initializeFormValues: (initialValues: Record) => void; /** * Snapshot of the inputId-keyed flat form value. Re-points to the merged * {@link FormTowerControllerService.value} computed (was the old `_formValue`). * Passed to legacy helpers (refresh) that expect a `() => Record` accessor. */ getFormValue: () => Record; /** * Resets all internal state — definition, FormGroup, signal graph (resources + * effects destroyed), busy/model/history — so the tower can be re-initialized. * Called at the start of {@link FormTowerControllerService.initialize} and from * {@link FormTowerControllerService.ngOnDestroy}. * * Explicitly `.destroy()`s every `ResourceRef` and the projection/persist * effects (HAZARD 7 / Blueprint §2.8 — per-row import towers are torn down by * manual `ngOnDestroy`, not injector destruction). */ clearFormState: () => void; _hintTimeoutIds: Record; setTemporaryHint: (inputId: string, hint: string, type: HintType) => void; _onFormInputConfigChange?: (inputId: string, config: FormColumnInputs) => void; registerFormInputConfigChangeFn: (fn: (inputId: string, config: FormColumnInputs) => void) => (inputId: string, config: FormColumnInputs) => void; httpPostDataFunction: (url: string, data: any, options?: any) => Observable; httpGetDataFunction: (url: string, options?: any) => Observable; httpPutDataFunction: (url: string, data: any, options?: any) => Observable; _errorTimeoutIds: Record; setInputTemporaryError: (inputId: string, message: string) => void; setInputError: (err: Record, inputId: string) => void; updateFormInputConfig: (inputId: string, config: FormColumnInputs) => void; handleStepChange: (event: StepperSelectionEvent) => void; selectFormSteps: () => TowerFormStep[]; selectAllFormTours: () => ngx_t_forms_types.IFormTour[]; setSectionAsSeen: (sectionId: string) => void; setSectionAsActive: (sectionId: string) => void; setInputAsTouchedAndDirty: (inputId: string) => void; formProgress: () => number; formSubmissionMessage: () => string; setSubmissionStatusValue: (status: FormSubmissionStatus) => FormSubmissionStatus; /** * Legacy-shaped per-input function registry, reconstructed from `#derived` * (Decision D3). Each present `(inputId, functionType)` maps to an * `Observable` that, on subscription, drives the underlying primitive: * - resource/options entries → `.reload()` then complete when status leaves * `'loading'`; * - value/sourced/validation entries → a synchronous read then complete. * * Kept so `refreshInputWithDependencies` / `refreshInput` / * `runMultipleInputPrepopulationFunctions` / `getTopologicalExecutionOrder` * compile + behave unchanged. The return TYPE is unchanged (api:check parity). */ get inputFunctionsCollection(): Record>>>; /** * Submits the form to the configured backend pipeline. Builds a payload by * un-flattening the settled values, delegates to {@link formHttpSubmissions}, * and reports status. Errors surface as `FormSubmissionStatus.FAILED` — they * do not throw to the caller. * * @param passData - Extra context handed through to the submission pipeline. */ submitForm: (passData: Record) => void; /** Toggle a MultipleInput element + its associated form controls. */ toggleMultipleInput: (inputId: string, open: boolean, rowInEditId?: string) => boolean; /** Persist the open MultipleInput sub-form back into the parent control's array value. */ saveMultipleInputForm: (inputId: string) => boolean; /** Open the MultipleInput sub-form prepopulated with `rowId`'s values. */ multipleInputEditRow: (inputId: string, rowId: string) => boolean; /** Duplicate `rowId` and open the sub-form on the new row. */ multipleInputDuplicateRow: (inputId: string, rowId: string) => boolean; /** * Bridges live edits of an OPEN MultipleInput sub-row into the signal graph. * * Subscribes every sub-row control (`${inputId}.${childId}`) — except the * `${inputId}.id` row-bookkeeping control — to `updateValue(controlName, …)`, * so a sub-row field behaves exactly like a primary-form input: dependent * calculations / value-fetches / validators (whether they live in the same * row or in the primary form) re-fire the moment a dependency changes. * * Idempotent per `inputId` (re-binding tears down the prior subscription * first). Each inner subscription is `takeUntil(this._destroyed$)`-anchored so * a re-init also drops it. Called by `toggleMultipleInput` on open; mirrored * by {@link FormTowerControllerService.unbindMultipleInputRowControls} on close. * * @param inputId - The MultipleInput whose open sub-row controls to bridge. */ bindMultipleInputRowControls: (inputId: string) => void; /** * Tears down the live sub-row `valueChanges` bridge wired by * {@link FormTowerControllerService.bindMultipleInputRowControls}. Called by * `toggleMultipleInput` on close (and implicitly on re-open / re-init). * * @param inputId - The MultipleInput whose sub-row bridge to drop. */ unbindMultipleInputRowControls: (inputId: string) => void; /** * Bridges live edits of mSCOA inner inputs — the custom form inputs configured * inside an `MscoaSelection` column (e.g. `budgetValue`, `department`) and * rendered inline by the MSCOA chart via a `ComponentPortal` — into the signal * graph. * * Each inner input is a `${mscoaColId}.${innerId}` control sitting in the mSCOA * column's section group. The engine already lists it in `allFormInputs`, so * its derived calc / value-API / options graph is built at init (the OUTPUT * half). But a `ComponentPortal` forwards inputs only and never subscribes the * host's `valueChange` output, so the user's typed value never reached `#model` * — leaving dependent calculations / value-fetches / options blind to it. This * subscribes each such control's `valueChanges` → `updateValue(controlName, …)`, * restoring the INPUT half so an mSCOA custom input behaves exactly like a * primary-form input. Direct mirror of * {@link FormTowerControllerService.bindMultipleInputRowControls}. * * Idempotent (tears down the prior bridge first) and anchored to `_destroyed$`, * so the re-init `clearFormState` drops every inner subscription. */ bindScoaInnerInputControls: () => void; /** * Bridges live edits of **DateRangePicker half controls** into the signal * graph. * * A date-range column is flattened into two synthetic inputs whose ids (and * control names) are `${columnId}.${startKey}` / `${columnId}.${endKey}`. * The range element writes those controls directly (`control.setValue`), and * the generic value bridge in `t-form-input` deliberately no-ops for date * ranges — so before this bridge existed a user-picked range never reached * `#model`, and every dependent value/options POST keyed on the range stayed * permanently `idle` (owner decision 2026-08-18: fixed, with the builders' * name-keyed snapshot fix). Direct mirror of * {@link FormTowerControllerService.bindScoaInnerInputControls}. * * Idempotent (tears down the prior bridge first) and anchored to * `_destroyed$`, so re-init/destroy drops every half subscription. */ bindDateRangeHalfControls: () => void; /** * Re-runs every refreshable function for inputs in `sectionId` (resource * `.reload()` + dependency order). Returns an Observable that completes when * the section's refresh chain drains. * * @param sectionId - The section to refresh. * @returns An Observable completing when the section is refreshed. */ refreshSection: (sectionId: string) => Observable; /** * Fire-and-forget refresh of whichever slide is currently active. Returns * `void` (parity — the consumer-map row claiming `Observable` is wrong). */ refreshActiveSection: () => void; /** * Refresh a single input plus everything it transitively depends on. * * @param inputId - The input to refresh. * @returns An Observable completing when the refresh drains. */ refreshInput: (inputId: string) => Observable; /** True iff the input has at least one refreshable `#derived` entry. */ canRefreshFn: (inputId: string) => boolean; /** * True iff any input in the section is refreshable. The HTML refresh-button * gate (`user-form-stepper.component.html`) depends on this exact truth value * (Blueprint §4 / W13). */ canRefreshSection: (sectionId: string) => boolean; /** * Pop the last change-history entry and re-apply the PRIOR snapshot via * {@link FormTowerControllerService.updateValue} (restores to second-to-last, * matching the old semantics exactly). Decorates each restored input with a * transient hint. History append stays imperative (HAZARD 4). */ revertBackHistory: () => void; /** * The staged AI suggestions for this form (the preview/accept/reject queue). * A `pending` entry overlays {@link FormTowerControllerService.previewFormValue} * but never the live form until {@link FormTowerControllerService.acceptSuggestion}. */ readonly stagedSuggestions: Signal; /** * Real-time, read-only snapshot of the form's EDITABLE surface — each field's * current value, selectable options, and validation constraints + live errors * — plus the form's submittable / busy state. Excludes structural, system, * calculated, read-only / disabled, view-only and tower-derived inputs (a * suggestion to any of those is un-committable). * * Lazy and non-impacting: a pure `computed` that costs nothing until read * (e.g. once an AI subscriber observes it through {@link FORM_SUGGESTION_REGISTRY}). * It recomputes as values, resolved options and override-reasons change. */ readonly editableFormSchema: Signal; /** * The form value with every PENDING staged suggestion overlaid — the * non-destructive preview a review UI renders. A pure overlay over * {@link FormTowerControllerService.getFormValue}; it is NEVER projected to the * live `FormGroup` (only `acceptSuggestion` writes the live form), so previewing * a suggestion can never disturb form state. */ readonly previewFormValue: Signal>; /** * Stage a batch of externally-proposed edits for user review. Each suggestion * targeting a currently-editable field is recorded as `pending` with a snapshot * of the field's value at propose time; suggestions to unknown / non-editable * fields are dropped. Does NOT mutate the live form. * * @param batch - The proposed edits (typically routed via {@link FORM_SUGGESTION_REGISTRY}). */ proposeSuggestions: (batch: SuggestionBatch) => void; /** * Accept one pending staged suggestion, applying it through the path its field * **kind** requires: * - `scalar` → `updateValue`. * - `choice` → only if the value is an allowed option (else `'invalid'`). * - `multipleRow` → validate + remap rows, then append/replace (else `'invalid'`). * - `mscoa` → resolve the account intent asynchronously via the host account * search (status `'resolving'`), then commit or mark `'invalid'`. * * A value that does not satisfy its field's contract is parked as `'invalid'` * and never written to the live form (this is the apply-guard). No-op when the * id is unknown or already resolved. * * @param stageId - The staged suggestion's id. */ acceptSuggestion: (stageId: string) => void; /** * Reject one pending staged suggestion: mark it rejected and drop it from the * preview overlay. The live form is left untouched. No-op when the id is * unknown or already resolved. * * @param stageId - The staged suggestion's id. */ rejectSuggestion: (stageId: string) => void; /** * Accept every pending staged suggestion. Each is routed through * {@link FormTowerControllerService.acceptSuggestion}, so per-kind validation / * remap / async MSCOA resolution apply (an invalid one parks as `'invalid'` * rather than blocking the rest). */ acceptAllSuggestions: () => void; /** Reject every pending staged suggestion (leaves the live form untouched). */ rejectAllSuggestions: () => void; /** * Hard reset: tear down current state and re-initialize from the same form * definition + originally supplied values. * * **D4 (deliberate, signed-off):** AWAITS `initialize(form)` BEFORE calling * `initializeFormValues(...)`, fixing the old unawaited mis-ordering where * `initializeFormValues` could run before `_mainForm` was rebuilt. The public * signature is unchanged. */ reset(): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * Per-component runtime form engine. * * `TFormEngine` is the **composition seam** introduced by SIGNAL_FORMS migration * Phase 0 (see `docs/migration/SIGNAL_FORMS_MIGRATION_PLAN.md` §5.1/§6.0 and * DECISIONS.md D-023/D-025). Consumers previously **extended** * {@link FormTowerControllerService} directly; they now **hold** a `TFormEngine` * instance via `inject(TFormEngine)` (provided per-component, not * `providedIn: 'root'`) and reach the tower's surface through it. * * Phase 0 moves **no logic**: this façade is a thin subclass of the existing * tower so the full member surface is preserved verbatim and consumer behaviour * stays under the I-1 Parity invariant. Phase 1 will rewrite the tower internals * behind this same façade without touching the three consumers again. * * Internal to the library — not part of the public API. Provide it on the * component that needs it: * * @example * @Component({ * // … * providers: [TFormEngine], * }) * export class UserFormStepperComponent { * protected readonly engine = inject(TFormEngine); * } */ declare class TFormEngine extends FormTowerControllerService { constructor(http: HttpClient); static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵprov: _angular_core.ɵɵInjectableDeclaration; } declare class TourManagerService { private readonly tourService; userProfile: this; constructor(); startTourByOption(steps: IStepOption[]): { stepShow$: rxjs.Subject>; stepHide$: rxjs.Subject>; initialize$: rxjs.Subject; start$: rxjs.Subject; end$: rxjs.Subject; pause$: rxjs.Subject; resume$: rxjs.Subject; }; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵprov: _angular_core.ɵɵInjectableDeclaration; } /** * End-user surface for filling out a form. Extends `FormTowerControllerService` * to drive a `MatStepper` of form sections and renders each section's inputs * via `TFormInputComponent`. Loads the form definition through the consumer's * `formBuilder.getForm` hook on `NgxTFormsConfig`, supports undo (Ctrl+Z), * initial values, and per-instance global system inputs. * * Inputs: * - `formId: string | undefined` — when set, fetches the form * definition and initialises the tower controller. * - `initialValues: Record | undefined` — seed the form * with previously captured values; only re-initialises when the value * actually changes. * - `globalSystemInputs: FormColumnInputs[]` — system-level inputs * merged into every step of the form; re-initialises the form when set. * - `passParamsOnSubmit: Record | undefined` — extra params * passed through to the consumer's submit handler. * - `showAiSuggestions: boolean` — when `true` (and `withFormSuggestions()` is * installed), renders the built-in review panel for pending AI-proposed edits * so the user can accept/reject them. Off by default. * * Outputs: * - _None._ Submission and lifecycle events are dispatched through the * inherited `FormTowerControllerService` and the consumer's * `formActions` / `formBuilder` callbacks. */ declare class UserFormStepperComponent { #private; /** * Runtime form engine, held by composition (SIGNAL_FORMS Phase 0, D-025). * Provided per-component instance; the component reaches the former * inherited tower surface through this façade. */ protected readonly engine: TFormEngine; /** Form definition id; when set, the component fetches and initialises the form. */ readonly formId: _angular_core.InputSignal; /** * Seed values applied to the form once it is initialised. * * A keyed record of previously captured values (raw API payloads, partial * form values, nested objects). The downstream `initializeFormValues` * consumes the entries defensively; callers narrow specific value shapes. */ readonly initialValues: _angular_core.InputSignal | undefined>; /** System-level inputs merged into every step of the form. */ readonly globalSystemInputs: _angular_core.InputSignal; /** * Extra params forwarded to the consumer's submit handler. * * A keyed record merged into the submission payload; only meaningful to the * consumer's own submit handler, which narrows the individual values. */ readonly passParamsOnSubmit: _angular_core.InputSignal | undefined>; /** * Shows the built-in AI edit-suggestion review panel above the form when an * external system has proposed pending edits (requires `withFormSuggestions()` * at bootstrap). Off by default — opt in to render the turnkey panel; leave it * off to drive the suggestion stream / your own review UI via * `FORM_SUGGESTION_REGISTRY` instead. */ readonly showAiSuggestions: _angular_core.InputSignal; /** Underlying Material stepper instance (may be undefined before first CD pass). */ readonly stepper: _angular_core.Signal; /** True when the engine holds at least one pending (unreviewed) AI suggestion. */ protected readonly hasPendingSuggestions: _angular_core.Signal; /** * The form's steps with every conditionally-hidden input removed — what this * stepper renders. * * The filter lives HERE rather than in `selectFormSteps` because that selector * is shared with the form builder's own section stepper. Filtering centrally * would make a conditional field invisible, undraggable and un-editable to the * author the moment its condition happened to be false. The builder must see * every column; only the person filling the form in should not. * * A hidden MultipleInput sub-row field is dropped by replacing the column's * `formInputs` with a filtered copy. That array flows down through * `[inputConfig]` → `t-form-input` → `*ngComponentOutlet` → * `multiple-input-table-edit.innerInputs()`, so the sub-row editor, the * saved-rows table and `formInvalid()` all drop the field with no edits of * their own. * * Reading `engine.isInputVisible` makes this computed a consumer of the * visibility signals, so a rule flipping re-renders the affected columns and * nothing else. */ protected readonly visibleSteps: _angular_core.Signal; /** Whether the form is editable / can be navigated freely. */ isEditable: boolean; /** True while the form definition is being fetched. */ readonly loading: _angular_core.WritableSignal; protected readonly tourManagerService: TourManagerService; protected readonly formIdBridge: _angular_core.EffectRef; protected readonly initialValuesBridge: _angular_core.EffectRef; protected readonly globalSystemInputsBridge: _angular_core.EffectRef; /** * Handles the key down event and reverts the form's last history entry on Ctrl+Z. * @param event The keyboard event object. */ onKeyDown(event: KeyboardEvent): void; loadForm(formId: string | undefined): void; /** * Builder-function shim passed to inputs that need callbacks (e.g. * MultipleInput, MSCOA). The user form surface only implements the subset * relevant to runtime input editing; builder-only members (`editInput`, * `deleteInput`, `addFunction`, `reorderItems`, `multipleInputToggleLabel`) * are stubbed because they have no meaning outside the form builder. */ get formBuilderFunctions(): FormBuilderFunctions; getStepState(step: ITowerFormSteps, index: number): StepState; getPreviousStepLabel(): string | undefined; getNextStepLabel(): string | undefined; canProceedToNextStep(step: ITowerFormSteps): boolean; get getSubmissionStatus(): string; handleSubmit(): void; /** Still-failing overridable validations the user may motivate to submit. */ get overridableErrors(): OverridableError[]; /** True while a blocking (non-overridable) error keeps submission impossible. */ get hasBlockingErrors(): boolean; /** True once every blocking error is resolved and every override is motivated. */ get canSubmit(): boolean; /** * Overridable validations that still lack a non-empty motivation — the count * shown on the "Provide reason" button and what keeps submission gated. */ get pendingOverrideCount(): number; /** * Opens the override-reasons dialog so the user can add or edit a motivation * (and optional supporting file) for each overridable validation. The dialog * writes back through the engine, so the submit gate updates live on close. */ openOverrideDialog(): void; get hasTour(): boolean; /** * Initiates and configures a dynamic, multi-step tutorial tour for the form. * The tour guides the user through the form's title, sections, and individual fields. */ startTour(): void; refreshASection(sectionId: string): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } interface IConfigElementError { key: string; message: string; } /** * Builder-side editor for a single configurable property on a form input — * dispatches to the correct editor (selection options, REST API setup, * value-access rules, pipeline, validators, MSCOA segment config, slider, * chip list, data source picker, document list label config, workflow * picker, EditorJS, record list manager, etc.) based on the supplied * `ElementEditorInnerSectionElementInterface`. * * @remarks * Emits debounced value changes (and a separate `blur` event when the * editor is a free-text expression) so the form builder can persist edits * without re-reading the underlying form on every keystroke. * * Inputs: * - `editorConfig: ElementEditorInnerSectionElementInterface | undefined` * — descriptor of the editor to render. * - `formInputs: FormColumnInputs[]` — the set of inputs the * editor can reference (used by expression / value-access editors). * - `data: unknown` — current value being edited; resets the value * pipeline when changed by reference. * - `validationErrors: IConfigElementError[] | null` — validation errors * surfaced by the parent for display. * * Outputs: * - `valueChange` — fires when the edited value changes (debounced). * - `blur` — fires when an inner editor loses focus * (used for expression-style editors). */ declare class TDynamicDataEditComponent { #private; protected readonly elementEditorTypes: typeof ElementEditorTypes; /** Descriptor of the editor to render. */ readonly editorConfig: _angular_core.InputSignal; /** The set of inputs the editor can reference (used by expression / value-access editors). */ readonly formInputs: _angular_core.InputSignal; /** * Current value being edited; resets the value pipeline when changed by reference. * @remarks Heterogeneous across consumers (ITowerStepColumn, plain records, etc.), * so it is typed as a keyed record; the editor pipeline reads individual fields * via `deepBind` paths and callers narrow specific value shapes. */ readonly data: _angular_core.InputSignal; /** Validation errors surfaced by the parent for display. */ readonly validationErrors: _angular_core.InputSignal; /** * Builder-only: creates or updates an account-level MSCOA custom input (a peer * of the segments) from the segment-config quick editor. Forwarded to that * editor; absent outside the form builder, which hides the related affordance. */ readonly mscoaSaveCustomInput: _angular_core.InputSignal<((sectionId: string, scoaInputId: string, config: Pick & { id?: string; }) => void) | undefined>; /** Builder-only: opens an MSCOA custom input in the input editor for advanced configuration. */ readonly mscoaEditInput: _angular_core.InputSignal<((input: FormColumnInputs) => void) | undefined>; /** Builder-only: removes an MSCOA custom input from the config. */ readonly mscoaDeleteInput: _angular_core.InputSignal<((input: FormColumnInputs) => void) | undefined>; /** Fires when the edited value changes (debounced). */ readonly valueChange: _angular_core.OutputEmitterRef; /** Fires when an inner editor loses focus (used for expression-style editors). */ readonly blur: _angular_core.OutputEmitterRef; protected readonly editorConfigBridge: _angular_core.EffectRef; protected readonly dataBridge: _angular_core.EffectRef; protected readonly editorConfigValue$: Observable; protected readonly dataValue$: Observable | undefined>; protected get getMscoaTree$(): Observable; protected get getWorkflowOptions$(): Observable; protected get value$(): Observable; protected get dataOptions$(): Observable; protected get disabled$(): Observable; inputChange(event: unknown): void; valueChanged(value: unknown): void; manualValueChange(event: { value: unknown; deepBind: Array; }): void; blurOff: boolean; elementBlur(event: unknown): void; protected get inputHasBlurFunction$(): Observable; blurFunctionTooltip(blurHandle: BlurHandleTypes | undefined): string; /** Slider label formatter — Mat slider's `displayWith` accepts `string | number`. */ formatLabel: (value: number) => string | number; protected vm$: Observable<{ editorConfigValue: ElementEditorInnerSectionElementInterface | undefined; isFormFieldControl: boolean; value: any; dataOptions: any; disabled: boolean | undefined; inputHasBlurFunction: BlurHandleTypes | undefined; dataValue: Record | undefined; inputConfig: Partial; }>; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } declare class TreeComponent { activePath: TreeNode[]; pathInEdit: TreeNode | null; get activeLevel(): number; private _transformer; setupPath(node: TreeNode): void; updateStateFromPath(path: TreeNode[]): void; selectNode(node: FlatNode): TreeNode[] | undefined; saveNodeInEdit(): { children: undefined; value: undefined; key: string; name: string; inEdit?: boolean; path: string[]; keyIsArrayIndex?: boolean; functions: IArrayFunction[]; }[] | undefined; resetNode(): void; removeFunction(id: string): void; closeEdit(): void; nodeIsExpandable(node: TreeNode): boolean; showNode(node: FlatNode): boolean; hasANodeInEdit(): boolean; nodeIsChecked(node: FlatNode): boolean; treeControl: FlatTreeControl; treeFlattener: MatTreeFlattener; dataSource: MatTreeFlatDataSource; private dynamicObject; constructor(); computeTreeData(dynamicObject: unknown): void; assignDataSourceData(tree: TreeNode[]): void; hasChild: (_: number, node: FlatNode) => boolean; getValue(): unknown; addNewFunction(): void; functionChanged(value: string): void; } /** * Read-only tree view for an arbitrary JSON-shaped value. Converts the input * into a flat tree (via `TreeComponent`) and renders each leaf with a typed * style class (`value-string`, `value-number`, `value-boolean`, `value-null`). */ declare class TDynamicDataViewComponent { /** Arbitrary JSON-shaped value to render. Recomputes the tree on structural change. */ readonly data: _angular_core.InputSignal; protected readonly treeClass: TreeComponent; constructor(); protected formatKey(key: string): string; protected getDisplayValue(value: unknown): string; protected getValueClass(value: unknown): string; protected getLevelArray(node: unknown): readonly number[]; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } /** * Renders the queue of pending AI-proposed edits for a form and lets the user * accept or reject each one (or all at once). It is **presentational only** — it * holds no engine reference and mutates nothing; the host wires its inputs to the * tower's reporting signals and its outputs back to the tower's accept/reject * methods, so a per-component form engine is never pulled into this component's * injector. * * @example * */ declare class TSuggestionReviewComponent { /** Staged suggestions to review (typically `engine.stagedSuggestions()`). */ readonly suggestions: _angular_core.InputSignal; /** The form's editable schema (typically `engine.editableFormSchema()`), used for field labels. */ readonly schema: _angular_core.InputSignal; /** The form value with pending suggestions overlaid (typically `engine.previewFormValue()`). */ readonly previewValue: _angular_core.InputSignal>; /** Emits the stage id of a suggestion the user accepted. */ readonly accept: _angular_core.OutputEmitterRef; /** Emits the stage id of a suggestion the user rejected. */ readonly reject: _angular_core.OutputEmitterRef; /** Emits when the user accepts every pending suggestion. */ readonly acceptAll: _angular_core.OutputEmitterRef; /** Emits when the user rejects every pending suggestion. */ readonly rejectAll: _angular_core.OutputEmitterRef; /** The pending suggestions — the only ones offered for review. */ protected readonly pending: _angular_core.Signal; /** Suggestions that could not be applied (shown informationally with a reason). */ protected readonly invalid: _angular_core.Signal; /** Whether there is nothing to show (no pending and no invalid). */ protected readonly isEmpty: _angular_core.Signal; /** `fieldId → schema` index for label / kind lookup. */ protected readonly schemaById: _angular_core.Signal>; /** * Resolves a field's display label, falling back to its id. * * @param fieldId - The target field's id. * @returns The field's label, or the id when the field is unknown. */ protected labelFor(fieldId: string): string; /** The kind of the suggestion's target field, when known. */ protected kindOf(fieldId: string): EditableFieldKind | undefined; /** Structured fields (mscoa / multipleRow) show an action summary, not a raw diff. */ protected isStructured(s: StagedSuggestion): boolean; /** A short human description of what a structured suggestion will do. */ protected describeAction(s: StagedSuggestion): string; /** Renders an arbitrary value as a short string for the from → to diff. */ protected display(value: unknown): string; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } declare class FormatDataPipe implements PipeTransform { /** * Formats an arbitrary input value for display according to `dataType`. * * `value` is typed `unknown` (a pipe can be handed any binding) and each * branch narrows it to the shape it needs. The return is the set of * display-primitive types (`string | number | null | undefined`) so it * binds cleanly to interpolation and `matTooltip`; "passthrough" branches * return the original value (asserted to the display-primitive union — its * runtime value is unchanged and Angular string-coerces it for display). * * @param value - The raw value to format. * @param dataType - Which formatting branch to apply. * @param pipeConfig - Optional pipe configuration (currency code, nested pipe type). * @returns The formatted representation, or the original value when no formatting applies. */ transform(value: unknown, dataType: DocumentLitsLabelConfigInterfaceValueType | InputDataTypes | undefined | InputPipeTypes, pipeConfig?: FormColumnInputs['pipe'] | undefined): string | number | null | undefined; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵpipe: _angular_core.ɵɵPipeDeclaration; } declare function decrypt(encrypted: EncryptedData, secret: string): Promise; /** * Derives a deterministic 32-char HMAC key for a given form input, salted by * the consumer-supplied secret. The secret must be configured via * `withInputSecret()` and read from `INPUT_SECRET_TOKEN` at the callsite — * this function does not (and cannot, as a free helper) inject it itself. * * @param input Input descriptor; its identity fields seed the primary digest. * @param secret Consumer-supplied HMAC secret. Throws if missing. */ declare const generateSecretKey: (input: FormColumnInputs, secret: string) => Promise; /** * @public * @deprecated Reachable for one minor cycle only as part of the Phase 1 public-surface * lockdown. Target removal: v3.0.0. No replacement — this is the empty * `ng generate library` stub and will be deleted in Phase 2. */ declare class NgxTFormsService { constructor(); static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵprov: _angular_core.ɵɵInjectableDeclaration; } /** * @public * @deprecated Reachable for one minor cycle only as part of the Phase 1 public-surface * lockdown. Target removal: v3.0.0. No replacement — this is the empty * `ng generate library` stub and will be deleted in Phase 2. */ declare class NgxTFormsComponent { static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } /** * Public entry-point for bulk imports. * * Typical usage: * ```ts * const importController = inject(TFormImportController); * importController.progress$.subscribe(p => render(p)); // optional reactive UI * const results = await importController.runImport(form, rows); * const validRows = results.filter(r => r.isValid); * ``` * * Singleton (`providedIn: 'root'`) because all import sessions share the same * caches/injector wiring. Call {@link TFormImportController.reset} between * runs only if you want to force consumers of `progress$` to see an empty * baseline; `runImport` already clears caches on entry and exit. * * @public * @deprecated Reachable for one minor cycle only as part of the Phase 1 public-surface * lockdown. Target removal: v3.0.0. Consumers should switch to wiring an import flow * through the `withImportTower()` feature; the controller will move under that * feature tree in Phase 2. */ declare class TFormImportController { private readonly _injector; private readonly _rows$; /** * Per-session HTTP caches. * Key: serialized request identity → shared Observable (shareReplay). * Populated at the start of runImport and cleared when it finishes, * so every import session starts cold but identical in-flight requests * across concurrent rows reuse a single HTTP call. */ private _getCache; private _postCache; /** * Registry of pre-processors keyed by ElementType. * Add an entry here to handle a new input type in _preProcessRow — no other * changes needed. Each processor receives the column definition and the raw * row and must return `{ value?, errors[] }`. * `value` is written to processedRow[formControlName] when defined; * `errors` accumulates in colErrors[formControlName]. */ private readonly _inputPreProcessors; /** * Shared financial-cycles observable for the current import session. * loadSystemInputs calls getFinacialCycles() directly via NGX_T_FORMS_CONFIG * (not through utils), so HTTP-function patching alone cannot deduplicate it. * We intercept it at the config level by providing a wrapped token in each * tower's child injector that returns this shared observable instead. */ private _financialCycles$; /** * Reactive progress stream — subscribe to track each row in real time. */ readonly progress$: Observable; /** * Snapshot of the current progress (non-reactive). */ get currentProgress(): ImportProgress; /** * Runs an import session. * * For each row a fresh tower instance is spun up via a child injector, * prepopulated, and left to settle (calculations + API fetches) before * recording the final value and validation status. * All rows are processed concurrently. * * Usage: * ```ts * const results = await importController.runImport(form, rows); * const valid = results.filter(r => r.isValid); * ``` * * @param form The form definition every row is validated against. * @param rows Raw data objects — one per import row. */ runImport(form: FormInterface, rows: Record[]): Promise; /** Clears all row state. */ reset(): void; /** * Creates an isolated tower instance through a short-lived child injector. * * The child injector delegates all token resolution to the parent, so * HttpClient, NGX_T_FORMS_CONFIG_TOKEN, and any other deps the tower needs * are found automatically — no manual wiring required here. * * After creation the tower's HTTP functions are replaced with cache-aware * wrappers so that identical requests fired by different rows share one * in-flight Observable instead of each issuing their own HTTP call. */ private _createTower; /** * Returns a shared Observable for a GET request. * On cache miss the original function is called once and its result is * multicasted via shareReplay(1) so every concurrent subscriber (row) that * asks for the same URL+options receives the same response without an * additional HTTP call. */ private _cachedGet; /** * Returns a shared Observable for a POST request. * Keyed by URL + serialised body + serialised options so only truly * identical requests are deduplicated. */ private _cachedPost; /** * End-to-end pipeline for a single import row. Runs concurrently with every * other row in the session. * * Steps (any thrown error short-circuits to `status: 'error'`): * 1. Mark the row `processing`. * 2. Spin up an isolated tower via {@link TFormImportController._createTower}. * 3. `initialize(form, { skipInitialFunctions: true })` — see the flag's * docs; this avoids the timing race between the tower's initial async * work and our synchronous `initializeFormValues`. * 4. `_preProcessRow` resolves nested formats (SCOA codes, multi-select * strings, MultipleInput sub-rows) into the shape `initializeFormValues` * expects. * 5. Apply the resolved row → tower's changeMonitor cycle fires dependent * functions → busy=true. * 6. `waitUntilSettled()` blocks until every async op drains. * 7. `markAllAsTouched()` so required-field validators surface even on * untouched controls. * 8. {@link TFormImportController._recomputeAllValidationErrors} re-runs * sync validators across the whole tree (matches what * `getInputErrorMessage` reports in the interactive UI). * 9. Collect settled values + per-input + per-column errors and update the * row's state. * * `finally` always destroys the tower so child injectors / valueChanges * subscriptions don't leak across rows. */ private _processRow; /** * Dispatches each column that has a registered pre-processor, collects * resolved values and errors, then returns the enriched row. * * To support a new input type add an entry to `_inputPreProcessors` — * nothing else needs to change here. */ private _preProcessRow; /** * Pre-processor for MscoaSelection inputs. * * Resolves flat account codes into full IScoaAccount objects. * Column naming convention expected in the raw row: * {formControlName}.{basisKey}.{SEGMENT}.debit e.g. "glAccount.accrual.FUND.debit" * {formControlName}.{basisKey}.{SEGMENT}.credit e.g. "glAccount.cash.COSTING.credit" * * Returns the nested structure that `initializeFormValues` / the mscoa * component store expect: * { accrual: { FUND: { debit: IScoaAccount, credit: IScoaAccount } }, cash: { ... } } */ private _processMscoaInput; /** * Pre-processor for MultipleInput inputs. * * Expects `row[input.formControlName]` to be an array of objects where each * object's keys are the formControlNames declared in `input.formInputs`. * * For each item the full tower lifecycle is run against a one-slide mock form * (the same sequence as _processRow on the main form), so Angular validators, * async validators, API calls, and calculated fields all fire and settle before * errors are collected. Pre-processors (e.g. MscoaSelection) are applied first * so resolved objects are in place when the tower initializes. * * Errors are prefixed with the item index: "[0].subField.errorCode". */ private _processMultipleFormInput; /** * Rewrites a MultipleInput sub-input's cross-field dependency references from * the live form's COMPOUND id scheme back to the SIMPLE id the per-row mock * form uses. * * In the real form, {@link allFormInputs} flattens a MultipleInput's children * and rewrites each child's id to `${multipleInputId}.${childId}`. Every * dependent field's `mapTo.inputId` (value/options-API `minimumInputRequired`) * is authored against that compound id — so `readDep(compoundId)` resolves and * the dependent fetch fires. The mock form built in * {@link TFormImportController._processMultipleFormInput} hoists those children * to top-level columns, so they keep their SIMPLE ids; the baked-in compound * `mapTo.inputId` references then resolve to nothing, `validateMinInput` fails, * the value-API `params` stay `undefined`, and the resource never fetches — * leaving every derived sub-field null (and dropped by `getFormValueNames`). * * Deep-clones `node` (never mutates the shared form definition) and strips the * `${parentId}.` prefix from any `inputId` that targets a sibling in THIS * MultipleInput, so the sub-tower's signal graph resolves dependencies exactly * as the live form does. * * @param node - The sub-input config (or any nested fragment) to rewrite. * @param parentId - The owning MultipleInput's id (the compound prefix). */ private _localizeSubInputDeps; /** * Parses a string MultipleInput cell into an array of row objects. * * Spreadsheet cells are primitives, so a MultipleInput column arrives as a * JSON-stringified array. Returns the parsed array on success; returns the * raw value unchanged on failure (empty string, plain text, malformed JSON, * or a non-array JSON value) so the caller's `Array.isArray` check treats it * as "no rows" rather than throwing. */ private _tryParseJsonArray; /** * Resolves a single account code to an IScoaAccount. * Routed through `_cachedGet` so identical codes across concurrent rows share * one in-flight Observable (shareReplay) — the same mechanism used for all * other HTTP calls in this class. */ private _lookupScoaAccount; /** * Pre-processor for `Select` and `PaginatedSelectionTable` inputs. * * Single-select inputs pass through unchanged. * * Multi-select inputs accept the value in any of: * - `string[]` — taken as-is, each entry trimmed. * - `'["a","b"]'` — JSON-stringified array. * - `'a, b, c'` — comma-separated string. * - `'[a, b]'` (malformed JSON) — fallback: strip brackets, split, strip quotes. * * If the input declares custom (in-config) options, every parsed value is * checked against the option set. Any mismatches are returned as errors of * the form `'invalidOption:'` and `value` is omitted (so the parent * form control keeps its original/empty state and the row is flagged * invalid). API-fetched options are NOT validated here — see the comments * in {@link FormTowerControllerService.initialize} on why deferring those * lookups is safe in import mode. */ private _processSelectInput; /** * Re-runs sync validation across the WHOLE form tree against the settled values. * * **Why this is still required after the signal-forms migration (Phase 1.5 finding; * kept until Phase 3):** it is NOT a settle-timing workaround — Phase 1 already made * `waitUntilSettled` deterministic. It compensates for two reactive-forms semantics * the signal-graph engine does not change: * * 1. **Cross-field validators.** Custom validators (commonFormOperations * `createCustomValidator`) read OTHER fields via `getFormValue()`. Angular only * re-runs a control's validators when ITS OWN value changes, and the engine's * projection effect likewise only `setValue`s controls whose value actually * changed — so a control whose value is unchanged keeps STALE cross-field errors * until a whole-tree `updateValueAndValidity` forces re-evaluation. * 2. **Disabled controls.** Angular never validates disabled controls (formGenerator * disables them from `input.disabled`); import temporarily enables the tree, * validates, then restores the disabled flags. * * Phase 3 (`@angular/forms/signals` `validate()`/`validateAsync()`) makes validation * reactive over observed fields and disabled-aware — at which point this method, its * enable/disable dance, and this call site can be deleted. */ private _recomputeAllValidationErrors; /** * Walks `{ [sectionId]: FormGroup { [inputId]: FormControl } }` and * collects every control that has validation errors (from `control.errors`). */ private _collectValidationErrors; /** * Groups the flat overridable-error list from {@link partitionFormErrors} into * an `inputId → messages[]` map for {@link ImportRowState.overridableErrors}. */ private _groupOverridableByInput; /** * Builds a formControlName-keyed error map from the settled form. * Multiple error keys on one control are joined with '.'. */ private _collectColErrors; /** * Collects the MultipleInput columns whose value is tower-derived — i.e. they * carry a value-API fetch (`matOptions.fetch.value.source === 'api'`) or a * value-producing calculation. These are the columns whose import rows are * overridden by the tower's own value graph and therefore need the * tower-favored deep merge applied in {@link TFormImportController._processRow}. */ private _valueDerivedMultipleInputs; /** True iff the column derives its value from a value-API fetch or a calculation. */ private _isValueDerivedColumn; /** * Deep-merges two values with the **override** (tower-derived) value favored * and the **base** (import) value filling every gap it leaves. * * Rules (mirrors the import-merge contract): * - `override` wins for scalars and for any key it defines. * - Keys present only on `base` are preserved (import fills gaps). * - Arrays merge **element-wise by index** (each element deep-merged), so a * tower row that omits an import-only field keeps that field. * - An **empty** `override` array (or `null`/`undefined`) falls back entirely * to `base` — a tower value that resolves empty never erases the import rows. */ private _deepMergePreferTower; /** * Immutable row update — clones the rows array and the targeted row before * pushing through `_rows$` so subscribers downstream of `progress$` always * receive a fresh reference (cheap change detection in components). */ private _patchRow; /** * Compute the {@link ImportProgress} aggregate from the row array. Pure — * driven by `progress$` and `currentProgress`. */ private _toProgress; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵprov: _angular_core.ɵɵInjectableDeclaration; } /** * Provides a unique identifier for each tower instance created during an * import run — one id per imported row. The form import controller uses this * to disambiguate concurrent tower contexts when materialising rows into * form submissions. * * @see provideNgxTForms * * @public * @deprecated Internal token used by `TFormImportController`. Will be relocated * under the `withImportTower()` feature tree in Phase 2; the token (or its * renamed/improved successor) will remain callable. See DECISIONS.md D-014. */ declare const IMPORT_TOWER_INSTANCE_ID: InjectionToken; /** * Generates a hierarchical form with nested FormGroups based on section IDs. * Parent form listens to all descendant changes, with validation cascading upward. * * @param inputs Array of form inputs with their configurations * @param getFormValue Record of form values used for custom validation * @returns A FormGroup with nested FormGroups for each section * * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare function formGenerator(inputs: Array, getFormValue: () => Record): FormGroup; /** * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare function getSectionElements(elements: ElementEditorInnerSectionElementInterface[], inputInEdit: (FormColumnInputs) | undefined, NGX_T_FORMS_CONFIG: NgxTFormsConfig, utils: InClassFormUtilsInterface, errors?: ValidationError[]): ElementEditorInnerSectionElementInterface[]; /** * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare const returnMappedPathValue: (pathMap: TreeNode[], obj: unknown) => unknown; /** * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare const getValueFromValueAccessor: (valueAccessRules: FormInputBasicOptionInterface | TreeNode[] | Record, data: unknown) => unknown; /** * One entry in the polymorphic-input registry. Maps an `ElementTypes` value to * a lazily-loaded renderer plus the metadata the host needs to wire it. * * Each `load()` is a dynamic `import()`, so every renderer is code-split out of * the host bundle — a form with only text fields never downloads the editor, * camera, signature pad, MSCOA charts, etc. The dynamic boundary also breaks * the otherwise-circular import between the host and `ImageCapture`. */ interface ElementEntry { /** Lazy loader for the concrete renderer component. */ readonly load: () => Promise>; /** * `true` when the renderer also accepts `editorMode` and * `formBuilderFunctions` inputs. The host only forwards those two inputs to * builder-aware entries, so `NgComponentOutlet` never tries to set an input * the target component does not declare. */ readonly builderAware?: boolean; } type TFormInputFormGroup = FormGroup<{ [sectionId: string]: FormGroup<{ [inputId: string]: FormControl; }>; }> | undefined | null; /** * Polymorphic input host — given an `ITowerStepColumn` descriptor, selects * and renders the correct concrete input component (text, select, date, * file upload, signature, geo-location, MSCOA, document picker, workflow * adjudication, etc.) and wires it to the parent reactive `FormGroup`. * * @remarks * Accepts portal-style prop injection via the optional `'COMPONENT_PROPS'` * token so it can be rendered through `ComponentPortal` with inputs supplied * dynamically. * * Inputs: * - `inputConfig: ITowerStepColumn | undefined` — descriptor of the input * to render; the `element` field selects the concrete renderer. * - `formGroup: FormGroup<{...}> | undefined | null` — the parent reactive * form group keyed by section id then input id. * - `editorMode: boolean` — default `false`; when `true`, renders the * builder-side variant. * - `formBuilderFunctions: FormBuilderFunctions | undefined` — builder * hooks passed through to inputs that need them (e.g., MSCOA). * * Outputs: * - `valueChange: unknown` — emits the input's new value whenever the user * edits the bound `FormControl`. Concrete child inputs are rendered through * `NgComponentOutlet` (which forwards inputs only, never outputs) and write * their value through the shared `FormGroup` via `ControlValueAccessor`, so * this host bridges those control edits into a single output the tower wires * to `engine.updateValue(col.id, $event)`. Without this bridge user edits * reach the projected `FormGroup` (so submission works) but never reach the * engine's `#model`, leaving the signal graph blind to user input — no * dependent calculation, value-fetch, or options-fetch ever re-fires. * * @public */ declare class TFormInputComponent { #private; /** * Descriptor of the input to render. `element` selects the concrete renderer. * * Modeled as a `model()` (not `input()`) so that portal-style injection via * `'COMPONENT_PROPS'` can write into the signal at construction time — signal * inputs are read-only at runtime, but model signals are writable via `.set()`. */ readonly inputConfig: _angular_core.ModelSignal; /** Parent reactive `FormGroup` keyed by section id then input id. */ readonly formGroup: _angular_core.ModelSignal; /** When `true`, renders the builder-side variant. */ readonly editorMode: _angular_core.ModelSignal; /** Builder hooks passed through to inputs that need them (e.g., MSCOA). */ readonly formBuilderFunctions: _angular_core.ModelSignal; /** * Emits the input's new value on every user-originated edit of the bound * control. The tower binds this to `engine.updateValue(col.id, $event)`, * which is the ONLY path user input takes into the engine's `#model` (and * therefore the signal-graph dependency reactivity). The projection effect * patches controls with `{ emitEvent: false }`, so signal→control writes do * NOT echo back here — only genuine user edits emit. */ readonly valueChange: _angular_core.OutputEmitterRef; protected readonly elementTypes: typeof ElementTypes; /** * Polymorphic-host control flag — true when the bound `FormGroup` already * has a `FormControl` (or, for `DateRangePicker`, both start/end controls) * matching the descriptor's `id`. */ protected readonly hasFormControlInstance: _angular_core.Signal; /** * Registry entry for the current descriptor's element type. Resolves to the * basic-input fallback for unknown types, mirroring the former `@default` * switch branch. `undefined` only while no descriptor is bound. */ protected readonly elementEntry: _angular_core.Signal; /** * Lazily-loaded renderer component for the current element type, unwrapped in * the template via the `async` pipe. The promise is re-created only when the * resolved entry changes, so editing other descriptor fields does not reload * the component. */ protected readonly elementComponent: _angular_core.Signal> | null>; /** * Inputs forwarded to the resolved renderer. Builder-aware renderers also * receive `editorMode` and `formBuilderFunctions`; every other renderer gets * only `inputConfig` and `formGroup`, so `NgComponentOutlet` never sets an * input the target component does not declare. */ protected readonly elementInputs: _angular_core.Signal>; constructor(props: Record | null); static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } /** * Renders an MSCOA (Municipal Standard Chart of Accounts) form input — a * segmented reactive form field that lets the user pick an account by * walking the MSCOA tree. Surfaces validation status via * `TFormInputStatusComponent`. * * Inputs: * - `inputConfig: ITowerStepColumn` — required, descriptor for this MSCOA input. * - `editorMode: boolean` — default `false`; when `true`, renders in * builder-editor mode rather than user-facing mode. * - `formGroup: FormGroup` — required, the parent reactive form group that * owns this input's controls. * - `formBuilderFunctions: FormBuilderFunctions | undefined` — optional * builder hooks supplied when used inside the form builder. * * Outputs: * - `reload: void` — fires when the input requests its * container reload the underlying data (e.g., after a tree refresh). */ declare class MscoaFormInputComponent { /** Descriptor for this MSCOA input. */ readonly inputConfig: _angular_core.InputSignal; /** When `true`, renders in builder-editor mode rather than user-facing mode. */ readonly editorMode: _angular_core.InputSignal; /** Parent reactive form group that owns this input's controls. */ readonly formGroup: _angular_core.InputSignal>; /** Optional builder hooks supplied when used inside the form builder. */ readonly formBuilderFunctions: _angular_core.InputSignal; /** Fires when the input requests its container reload the underlying data. */ readonly reload: _angular_core.OutputEmitterRef; protected get errorMessage(): string | string[] | undefined; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } /** * Form input that captures a hand-drawn signature via `SignaturePadInputComponent` * and writes the resulting image to the bound `FormGroup` control. Surfaces * validation state through `TFormInputStatusComponent`. * * Inputs: * - `inputConfig: ITowerStepColumn` — required, descriptor for this input. * - `formGroup: FormGroup` — required, the parent reactive form group. * * Outputs: * - `reload: void` — fires when the input requests its container reload * (e.g., after clearing the pad). * * @public */ declare class SignatureInputElementComponent { readonly inputConfig: _angular_core.InputSignal; readonly formGroup: _angular_core.InputSignal>; readonly reload: _angular_core.OutputEmitterRef; protected readonly errorMessage: _angular_core.Signal; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } /** * @file Round-trip bridge between the guided condition builder in * `lib-validators-config` and a custom validator's `expression` **string** plus * its `inputsObservedForChanges` dependency list — both part of the frozen * {@link FormControlCustomValidatorsInterface} contract. * * The validator engine evaluates `expression` with the shared predicate DSL * ({@link evaluatePredicate}) where **`true` means the field is INVALID**. The * scope it evaluates against is `{ [variable]: }` for * every entry in `inputsObservedForChanges` (see `build-manual-validation.ts`). * * Because the grammar is identical to the array-access predicate builder, this * module reuses {@link PREDICATE_OPERATORS} so the operator labels stay in lock * step with `lib-data-tree`. The model differs in one validator-specific way: * the right-hand side of a comparison may be **another field** (e.g. an * "end date is before start date" rule), not only a typed literal — so the * serializer must emit a bare variable token rather than a quoted string in * that case. * * {@link parseConditions} best-effort parses an expression into the structured * model; when it cannot (parentheses, mixed `&&`/`||`, unary `!`, an unknown * operator), it returns `null` and the UI falls back to the raw editor — power * users and legacy expressions are never locked out. * * @internal */ /** A single guided comparison: `field operator (value | field)`. */ interface ValidatorCondition { /** Left operand — always a referenced field's variable name. */ field: string; /** One of the {@link PREDICATE_OPERATORS} values (`===`, `>`, `includes`, …). */ operator: string; /** Whether the right operand is a typed literal or another field. */ compareTo: 'value' | 'field'; /** Literal text, or the variable name of the compared field. */ value: string; } /** A flat list of conditions joined by a single connector. */ interface ValidatorConditionGroup { connector: '&&' | '||'; conditions: ValidatorCondition[]; } /** A field the guided builder can reference, with a friendly label. */ interface ExpressionFieldOption { readonly variable: string; readonly label: string; /** The step the field belongs to, used to group the dropdown (`null` = ungrouped). */ readonly stepName: string | null; } /** A set of field options sharing a step, rendered as one ``. */ interface ExpressionFieldGroup { /** The `` label, or `null` to render the options without a group. */ readonly label: string | null; readonly options: readonly ExpressionFieldOption[]; } /** * Builder-side editor for authoring a boolean expression (used for guarded * navigation, conditional validation, and API path-selection rules). Validates * the expression's syntax in real time and exposes the typed tree of value- * access references the expression depends on. * * Inputs: * - `hint: string` — helper text shown beneath the expression field. * - `label: string` — label for the expression field (default * `'Validation Expression'`). * - `formInputs: FormColumnInputs[]` — inputs the expression may reference. * - `data: unknown` — sample data used to test the expression. * - `expression: string` — initial expression string written into the editor * control. * - `valueAccessRules: Record` — current value-access * tree for variables referenced by the expression. * * Outputs: * - `expressionChange` — fires when either the expression text or its derived * value-access tree changes. * * @public * @deprecated Internal builder UI re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare class ValidationExpressioCreatorComponent { #private; /** Helper text shown beneath the expression field. */ readonly hint: _angular_core.InputSignal; /** Label for the expression field. */ readonly label: _angular_core.InputSignal; /** Inputs the expression may reference. */ readonly formInputs: _angular_core.InputSignal; /** Sample data used to test the expression. Heterogeneous shape from parent template binding. */ readonly data: _angular_core.InputSignal; /** Initial expression string written into the editor control. */ readonly expression: _angular_core.InputSignal; /** Current value-access tree for variables referenced by the expression. */ readonly valueAccessRules: _angular_core.InputSignal>; /** Fires when either the expression text or its derived value-access tree changes. */ readonly expressionChange: _angular_core.OutputEmitterRef<{ expression: string | null; valueAccessRules: Record; }>; protected readonly textareaElementRef: _angular_core.Signal | undefined>; protected readonly expressionControl: FormControl; protected readonly showSuggestions: _angular_core.WritableSignal; protected readonly optionsSearch: _angular_core.WritableSignal; protected readonly variableInEdit: _angular_core.WritableSignal; /** Operator choices, shared with the validators builder for label parity. */ protected readonly operators: readonly { value: string; label: string; }[]; protected readonly mode: _angular_core.Signal<"guided" | "advanced">; protected readonly group: _angular_core.Signal; protected readonly expressionText: _angular_core.Signal; /** Fields the guided builder can reference, as friendly options. */ protected readonly fieldOptions: _angular_core.Signal; /** * Field options grouped by their `stepName` for the dropdowns, preserving * first-seen order. Fields without a step collapse into a single ungrouped * bucket (rendered without an ``), so forms that don't carry step * names degrade to a plain flat list. */ protected readonly fieldOptionGroups: _angular_core.Signal; /** Whether the current expression can be represented by the guided builder. */ protected readonly canUseGuided: _angular_core.Signal; protected readonly methods: { label: string; hint: string; value: string; }[]; /** * Bridge the `expression` input into the FormControl and seed the guided * builder. Reparsing is `untracked` so this only re-runs when the `expression` * input changes — never when the user edits inside either mode. * * A host that echoes `expressionChange` back into `expression` (the intended * controlled-component usage) makes that input change on every keystroke. Those * echoes are this component's own output coming home, not a new expression to * seed from, so they are skipped entirely. */ protected readonly expressionBridge: _angular_core.EffectRef; /** Mirror the `valueAccessRules` input into the local mutable copy. */ protected readonly valueAccessRulesBridge: _angular_core.EffectRef; protected readonly valueAccessOptions: _angular_core.Signal; protected readonly allInputs: _angular_core.Signal; constructor(); protected getMethods(): { label: string; hint: string; value: string; }[]; protected get errorMessage(): string | null; protected getValueAccessRule(key: string): TreeNode[]; protected onTextChange(expression: string): Promise; protected cleanValueAccessRules(): void; protected selectSuggestionInput(suggestion: string): void; protected onFocus(): void; /** Read the value-event target as a string. */ protected inputValue(event: Event): string; /** Switch the All/Any connector joining the conditions. */ protected setConnector(connector: '&&' | '||'): void; /** Append a fresh condition defaulting its field to the first available one. */ protected addCondition(): void; /** Apply a partial change to the condition at `index`. */ protected updateCondition(index: number, patch: Partial): void; /** Flip a condition between comparing to a typed value and another field. */ protected toggleCompareTo(index: number): void; /** Remove the condition at `index`. */ protected removeCondition(index: number): void; /** Switch to the raw expression editor (the escape hatch for power users). */ protected useAdvanced(): void; /** Switch back to the guided builder, reparsing the current expression. */ protected useGuided(): void; protected toggleVariableInEdit(variable: string): void; protected activeVariableChanged(value: TreeNode[] | string | { [key: string]: TreeNode[] | string; }): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } /** * Generic Material dialog shell used by the forms runtime to surface * confirmation prompts and short-lived informational dialogs. Reads its * configuration (title, body, button labels) from `MAT_DIALOG_DATA` as a * `DialogConfig` and resolves its `MatDialogRef` with `true` when the user * proceeds. * * Inputs: * - _None._ Configuration arrives through `MAT_DIALOG_DATA` (`DialogConfig`). * * Outputs: * - _None._ Result is delivered via `MatDialogRef.close(true)`. * * @public * @deprecated Internal Material dialog template re-exported via the `_deprecated/` * compatibility barrel; remains functional. A renamed/improved replacement may be * introduced in a future minor; the original symbol stays callable. See * DECISIONS.md D-014. */ declare class DialogTemplateComponent { readonly dialogRef: MatDialogRef; readonly data: DialogConfig; proceed(): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } /** * Custom error class for property access errors in deep object traversal. * * @class PropertyAccessError * @extends Error * * @property {PropertyPath} path - The path segment where the error occurred. * @property {string | number | symbol} segment - The specific path segment that caused the error. * * @description * This error is thrown when there's an issue accessing a property during deep object traversal. * It provides detailed information about where in the path the error occurred and what caused it. * * @example * try { * const result = returnDeepProperty(obj, ['a', 'b', 'c']); * } catch (error) { * if (error instanceof PropertyAccessError) { * console.log(`Error at path: ${error.path.join('.')}`); * console.log(`Problem segment: ${String(error.segment)}`); * console.log(`Error message: ${error.message}`); * } * } * * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare class PropertyAccessError extends Error { path: PropertyPath; segment: string | number | IArrayFunction[]; constructor(message: string, path: PropertyPath, segment: string | number | IArrayFunction[]); } /** * Retrieves a deeply nested property from an object using a path array. * * @function returnDeepProperty * * @param {unknown} item - The object to traverse. * @param {(string|number|symbol)[]} path - An array representing the path to the desired property. * Each element in the array can be a string (for object properties), * a number (for array indices), or a symbol. * * @returns {DeepPropertyValue} The value of the deep property if it exists, otherwise undefined. * * @throws {Error} If the input item is null or undefined, or if the path is not a non-empty array. * * @example * const obj = { * a: { * b: [ * { c: 1 }, * { c: 2 } * ] * } * }; * * returnDeepProperty(obj, ['a', 'b', 1, 'c']); // Returns 2 * returnDeepProperty(obj, ['a', 'x']); // Returns undefined * * @description * This function allows for safe traversal of nested objects and arrays. * It can handle various types of keys including strings, numbers, and symbols. * The function is optimized for performance and can handle very deep object structures. * * Key features: * - Iterative approach for better performance with deep structures * - Handles array indices (both as numbers and strings) * - Supports symbol keys * - Safely returns undefined for non-existent paths without throwing errors * - Type-safe with TypeScript * * Performance considerations: * - Efficient for very deep object structures (tested up to 1000 levels deep) * - Faster than naive recursive approaches for deep traversal * * Error handling: * - Returns undefined for non-existent paths or when trying to access properties of non-objects * - Throws an error if the input item is null/undefined or if the path is invalid * * @see safeReturnDeepProperty for a version that never throws and returns an object with value and error properties * * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare const returnDeepProperty: (item: unknown, path: PropertyPath) => DeepPropertyValue; /** * Safely retrieves a deeply nested property from an object using a path array. * * @function safeReturnDeepProperty * * @param {unknown} item - The object to traverse. * @param {(string|number|symbol)[]} path - An array representing the path to the desired property. * Each element in the array can be a string (for object properties), * a number (for array indices), or a symbol. * * @returns {{value: DeepPropertyValue, error: string|null}} An object containing: * - value: The value of the deep property if found, otherwise undefined. * - error: A string describing the error if one occurred, otherwise null. * * @example * const obj = { * a: { * b: [ * { c: 1 }, * { c: 2 } * ] * } * }; * * safeReturnDeepProperty(obj, ['a', 'b', 1, 'c']); * // Returns { value: 2, error: null } * * safeReturnDeepProperty(obj, ['a', 'x']); * // Returns { value: undefined, error: "Property 'x' does not exist" } * * safeReturnDeepProperty(null, ['a']); * // Returns { value: undefined, error: "Item cannot be null or undefined" } * * @description * This function is a wrapper around returnDeepProperty that never throws exceptions. * Instead, it returns an object with both the retrieved value and any error message. * This makes it suitable for use in situations where you want to handle all possible * errors without try/catch blocks. * * Key features: * - Never throws exceptions * - Provides both the retrieved value and error information * - Handles the same range of inputs as returnDeepProperty * * Use this function when you need to: * - Safely traverse objects without worrying about exceptions * - Get detailed error information along with the result * - Implement error handling in a functional programming style * * @see returnDeepProperty for the core implementation that this function wraps * * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare const safeReturnDeepProperty: (item: unknown, path: PropertyPath) => { value: DeepPropertyValue; error: string | null; }; /** * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare function assignDeepPropertyToObject(item: any, path: Array, value: any): any; /** * Creates a file upload data object from a Base64 string. * * @param fileName The desired name for the file (e.g., 'my-image.png'). * @param contentType The MIME type of the file (e.g., 'image/png'). * @param base64Content The raw Base64 encoded content of the file. * @returns A populated FileUploadInputValueInterface object. * * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare const createFileFromBase64: (fileName: string, contentType: string, base64Content: string) => FileUploadInputValueInterface; /** * Creates a sample value for a given form input configuration. * It determines the value based on the input's element type, specific input type (e.g., email, number), * or data type, with a fallback to a default value. * * @param {FormColumnInputs} input - The configuration object for the form input. * @returns {any} A sample value appropriate for the input type. * * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare function getSampleValueForInput(input: FormColumnInputs): any; /** * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare function getPipedValueFromDataType(dataType: InputDataTypes | undefined | DocumentLitsLabelConfigInterfaceValueType, value: any, pipe: FormColumnInputs['pipe'] | undefined): any; /** * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare const initFormConfigToV2: (formConfig: FormInterfaceMigration) => FormInterface; /** * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare function getUrl(url: string, variables: NgxTFormsConfig): string; /** * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare const sheetConsolodation: (allSheets: Record[]>) => Record[]; /** * Validates an object against a validation expression. * * @param {string} expression - The validation expression to evaluate. * @param {object} object - The object to validate. * @returns {boolean} - A boolean indicating whether the object is valid according to the expression. * * Backed by the shared predicate evaluator ({@link evaluatePredicate}), a * paren-aware, backward-compatible superset of the original space-split DSL. It * supports `===`/`==`/`!==`/`!=`/`>`/`<`/`>=`/`<=`, `&&`/`||` with correct * precedence and grouping, unary `!`, deep-path operands, multi-word quoted * strings, the keyword operators `includes`/`in`/`startsWith`/`endsWith`/`matches`, * and bare-operand truthiness. */ /** * Public callers pass either a plain object (e.g. `{ age: 1 }`) or an array * value (`item as T[]` from {@link evaluateArrayAccessRules}). Both are valid * index containers for the DSL (arrays support `length`, numeric indices, and * the `in` operator on string keys), so accept `object` and narrow internally. */ type ValidationTarget = object; /** * Validates an object against a predicate expression. Delegates to the shared, * paren-aware predicate evaluator (a backward-compatible superset of the * original space-split DSL). Throws on a structurally invalid expression. */ declare const validateObjectAgainstString: (expression: string, object: ValidationTarget) => boolean; /** * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare function validateExpressionSyntax(expression: string): string | null; /** * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. */ declare function testAgainstItem(test: ConfigurationValidTestInterface, item: unknown): boolean; /** * @public * @deprecated Internal helper re-exported via the `_deprecated/` compatibility * barrel; remains functional. A renamed/improved replacement may be introduced * in a future minor; the original symbol stays callable. See DECISIONS.md D-014. * * **Breaking (v2.x):** now requires `secret` as a third argument — the * hardcoded library secret was removed (LIB-05). Read it from * `INPUT_SECRET_TOKEN` in your component / service before calling. */ declare const getSignatureImage: (inputConfig: FormColumnInputs, value: EncryptedData | undefined, secret: string) => Promise; export { DialogTemplateComponent, FORM_ACTIONS_TOKEN, FORM_CONFIG_TOKEN, FORM_INPUTS_TOKEN, FORM_ROUTE_SOURCE, FORM_SLIDES_TOKEN, FORM_SUGGESTION_REGISTRY, FormBuilderComponent, FormSuggestionRegistry, FormSuggestionRegistryService, FormTowerControllerService, FormatDataPipe, FormsComponent, HttpPipelineRepository, IMPORT_TOWER_INSTANCE_ID, INPUT_SECRET_TOKEN, MSCOA_TREE_PROVIDER, MULTIPLE_FORM_INPUT_TOKEN, MscoaFormInputComponent, NGX_T_FORMS_CONFIG_TOKEN, NgxTFormsComponent, NgxTFormsService, PIPELINE_REPOSITORY, PipelineRepository, PropertyAccessError, SignatureInputElementComponent, TDynamicDataEditComponent, TDynamicDataViewComponent, TFormImportController, TFormInputComponent, TSuggestionReviewComponent, UTILS_OBJECT_TOKEN, UserFormStepperComponent, ValidationExpressioCreatorComponent, assignDeepPropertyToObject, buildSuggestionSchema, createFileFromBase64, decrypt as decryptSecuredInputValue, formGenerator, generateSecretKey as generateInputSecretKey, getPipedValueFromDataType, getSampleValueForInput, getSectionElements, getSignatureImage, getUrl, getValueFromValueAccessor, initFormConfigToV2, provideNgxTForms, returnDeepProperty, returnMappedPathValue, safeReturnDeepProperty, sheetConsolodation, testAgainstItem, textIconsForUserHints, toSuggestionBatch, validateExpressionSyntax, validateObjectAgainstString, withFormSuggestions, withHttpPipeline, withInputSecret, withRouterFormId }; export type { EditableFieldError, EditableFieldKind, EditableFieldSchema, EditableFieldValidation, FieldSuggestion, FormSuggestionChannel, FormSuggestionSnapshot, MscoaAccountSelection, MscoaCurrentSelection, MscoaFieldCapability, MscoaInnerInputDescriptor, MscoaSegmentDescriptor, MscoaSuggestionValue, MultipleRowSuggestionValue, StagedSuggestion, SuggestionBatch };