ngx-dynamic-entity 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"ngx-dynamic-entity.mjs","sources":["../../src/lib/services/entity-ref-cache.ts","../../src/lib/tokens/injection-tokens.ts","../../src/lib/providers/provide-ngx-dynamic-entity.ts","../../src/lib/services/validation-messages.service.ts","../../src/lib/field-types/field-dom-id.ts","../../src/lib/field-types/text-field.component.ts","../../src/lib/field-types/textarea-field.component.ts","../../src/lib/services/ui-text.service.ts","../../src/lib/field-types/markdown-field.component.ts","../../src/lib/field-types/number-field.component.ts","../../src/lib/field-types/currency-field.component.ts","../../src/lib/field-types/email-field.component.ts","../../src/lib/field-types/password-field.component.ts","../../src/lib/field-types/checkbox-field.component.ts","../../src/lib/field-types/boolean-field.component.ts","../../src/lib/field-types/date-field.component.ts","../../src/lib/field-types/date-time-field.component.ts","../../src/lib/field-types/time-field.component.ts","../../src/lib/field-types/month-year-field.component.ts","../../src/lib/services/lookup-registry.service.ts","../../src/lib/field-types/dropdown-field.component.ts","../../src/lib/field-types/radio-field.component.ts","../../src/lib/field-types/multi-select-field.component.ts","../../src/lib/services/entity-ref-registry.service.ts","../../src/lib/services/entity-reference.service.ts","../../src/lib/services/cascade-data.service.ts","../../src/lib/services/entity-ref-selection.service.ts","../../src/lib/field-types/entity-ref-field.component.ts","../../src/lib/services/field-registry.service.ts","../../src/lib/services/rbac.service.ts","../../src/lib/form/dynamic-field/dynamic-field.component.ts","../../src/lib/field-types/group-field.component.ts","../../src/lib/services/validator-registry.service.ts","../../src/lib/field-types/array-field.component.ts","../../src/lib/services/file-upload.service.ts","../../src/lib/field-types/image-field.component.ts","../../src/lib/field-types/file-field.component.ts","../../src/lib/providers/provide-field-types.ts","../../src/lib/services/hook-registry.service.ts","../../src/lib/services/rules-evaluation.service.ts","../../src/lib/services/config-source.service.ts","../../src/lib/form/form-structure.service.ts","../../src/lib/form/dynamic-form.component.ts","../../src/lib/form/dynamic-form.component.html","../../src/lib/form/dynamic-record-form.component.ts","../../src/lib/form/dynamic-record-form.component.html","../../src/lib/import/import-contracts.ts","../../src/lib/import/sheet-parser.ts","../../src/lib/import/local-import-transport.ts","../../src/lib/import/http-import-transport.ts","../../src/lib/import/import-errors.component.ts","../../src/lib/import/import-mapper.component.ts","../../src/lib/import/import-preview.component.ts","../../src/lib/import/import-template.component.ts","../../src/lib/import/entity-import.component.ts","../../src/public-api.ts","../../src/ngx-dynamic-entity.ts"],"sourcesContent":["import type { ReferenceOption } from '@dynamic-entity/core';\n\n/**\n * Backing store for cached reference options.\n *\n * Pluggable on purpose. The reference implementation kept its cache in a service instance,\n * so every entity label was re-fetched on a browser refresh (issue #22 in the architecture\n * doc). A consumer that wants the cache to survive a reload can back this with\n * sessionStorage; the default keeps it in memory, which is the right call for a library\n * that must not silently persist a tenant's data.\n */\nexport interface EntityRefCacheStore {\n get(key: string): ReferenceOption[] | undefined;\n set(key: string, value: ReferenceOption[]): void;\n delete(key: string): void;\n /** Every key currently held — used for prefix invalidation of one entity. */\n keys(): string[];\n clear(): void;\n}\n\n/** Default in-memory store. Lives as long as the injector that created it. */\nexport class InMemoryEntityRefCacheStore implements EntityRefCacheStore {\n private readonly map = new Map<string, ReferenceOption[]>();\n\n get(key: string): ReferenceOption[] | undefined {\n return this.map.get(key);\n }\n\n set(key: string, value: ReferenceOption[]): void {\n this.map.set(key, value);\n }\n\n delete(key: string): void {\n this.map.delete(key);\n }\n\n keys(): string[] {\n return [...this.map.keys()];\n }\n\n clear(): void {\n this.map.clear();\n }\n}\n","import { InjectionToken } from '@angular/core';\nimport type { Type } from '@angular/core';\nimport type {\n CommonModuleEntry,\n EntityReferenceLoader,\n FileUploadHandler,\n LookupListSource,\n RecordMigration,\n} from '@dynamic-entity/core';\nimport { InMemoryEntityRefCacheStore, type EntityRefCacheStore } from '../services/entity-ref-cache';\nimport type { UiTextOverrides } from '../services/ui-text.service';\nimport type { ImportTransport, SheetParser } from '../import/import-contracts';\n\n/** Roles that see XXXXXXXXX for masked fields. Presentational only — enforce authz server-side. */\nexport const MASKED_ROLES = new InjectionToken<string[]>('MASKED_ROLES');\n\n/**\n * Consumer **overrides**: fieldType string → Angular component class.\n * Highest priority — beats anything registered through `provideFieldTypes()`.\n */\nexport const FIELD_TYPE_REGISTRY = new InjectionToken<Map<string, Type<any>>>('FIELD_TYPE_REGISTRY');\n\n/**\n * Multi-provider of field-type sets, contributed by `provideFieldTypes()` /\n * `provideBuiltInFieldTypes()`. Multi so several calls compose instead of clobbering;\n * later sets win on key collision. This is the seam that keeps unused field components\n * out of the bundle — nothing is imported until a set names it.\n */\nexport const FIELD_TYPE_SETS = new InjectionToken<Record<string, Type<any>>[]>('FIELD_TYPE_SETS');\n\n/**\n * Registry: entity key → option loader.\n *\n * A loader receives a `ReferenceLoaderContext` (`parentValue`, `filters`, `lang`) and may\n * return an array, a Promise, or an Observable of `ReferenceOption[]`. `ctx` is optional,\n * so a zero-arg loader (`() => svc.list()`) is still a valid registration.\n */\nexport const ENTITY_REF_REGISTRY = new InjectionToken<Map<string, EntityReferenceLoader>>('ENTITY_REF_REGISTRY');\n\n/**\n * Registry: list name → the values of a named master list (`field.listName`).\n *\n * A source may be the values themselves (array / Promise / Observable) or a **loader function**,\n * which is what you want for anything fetched: a bare Promise is created when the provider is\n * built, so every list would load whether or not a form uses it.\n *\n * Values are normalised by `normalizeLookupValues` — bare strings and `LocalizedText` are\n * accepted alongside the full `{ code, name, sortOrder }` shape.\n *\n * @example\n * provideNgxDynamicEntity({\n * lookups: {\n * employeeStatus: () => listService.getByName('employeeStatus'),\n * grades: ['Junior', 'Senior'],\n * },\n * })\n */\nexport const LOOKUP_REGISTRY = new InjectionToken<Map<string, LookupListSource>>('LOOKUP_REGISTRY');\n\n/**\n * Ordered steps that move a saved record forward when a config's `version` increases.\n *\n * Without these, `EntityFormConfig.version` and `VersionedRecord._configVersion` are\n * declarations nothing acts on: a schema can be edited freely while records keep their old\n * shape, and nothing reconciles the two. Registering migrations makes the version numbers\n * mean something.\n *\n * @example\n * provideNgxDynamicEntity({\n * migrations: [\n * { from: 1, to: 2, description: 'split name', migrate: r => ({ ...r, firstName: r['name'] }) },\n * ],\n * })\n */\nexport const RECORD_MIGRATIONS = new InjectionToken<RecordMigration[]>('RECORD_MIGRATIONS');\n\n/**\n * Overrides for the messages shown under an invalid field, keyed by Angular error key\n * (`required`, `minlength`, `pattern`, …) plus a few field-specific keys.\n *\n * The built-in messages are English literals. Registering here is what makes a non-English\n * form possible without re-implementing every field component; unlisted keys keep their\n * default, so overriding one does not mean supplying them all.\n */\nexport const VALIDATION_MESSAGES = new InjectionToken<Record<string, any>>('VALIDATION_MESSAGES');\n\n/** Registry: validator key → ValidatorFn */\nexport const VALIDATOR_REGISTRY = new InjectionToken<Map<string, any>>('VALIDATOR_REGISTRY');\n\n/**\n * Registry: validator key → AsyncValidatorFn.\n *\n * Kept separate from VALIDATOR_REGISTRY because Angular applies the two differently: an async\n * validator runs only once the synchronous ones pass, and puts the control into `pending`\n * while it does. Name them from a schema with `validators: { customAsync: ['uniqueEmail'] }`.\n */\nexport const ASYNC_VALIDATOR_REGISTRY = new InjectionToken<Map<string, any>>('ASYNC_VALIDATOR_REGISTRY');\n\n/**\n * A registered hook: receives the payload, returns it (or a replacement), sync or async.\n *\n * Spelled out rather than typed as `Function`, which accepts class declarations and any\n * arity and gives a consumer no signature to write against.\n */\nexport type HookFn = (data: any, context?: unknown) => unknown | Promise<unknown>;\n\n/** Registry: hook key → async (data, context) => data */\nexport const HOOK_REGISTRY = new InjectionToken<Map<string, HookFn>>('HOOK_REGISTRY');\n\n/**\n * Consumer-registered list of common module tabs (documents, audit, tasks, etc.).\n * The library ships no built-in implementations. Consumers provide their own list\n * so the builder's module-picker and the renderer's tab switcher know what's available.\n *\n * `component` must be the component **class**: it is mounted through `ngComponentOutlet`,\n * which takes a type, not a selector. An entry naming a selector string renders nothing and\n * warns — `COMMON_MODULES` in core is a catalogue of names for the builder's picker, and\n * offering a module the renderer cannot mount is the one way to get this wrong.\n *\n * @example\n * providers: [\n * {\n * provide: COMMON_MODULES_REGISTRY,\n * useValue: [\n * { id: 'documents', label: { en: 'Documents' }, component: DocumentsViewComponent },\n * { id: 'audit', label: { en: 'Audit Log' }, component: AuditLogComponent },\n * ] satisfies CommonModuleEntry[]\n * }\n * ]\n */\nexport const COMMON_MODULES_REGISTRY = new InjectionToken<CommonModuleEntry[]>('COMMON_MODULES_REGISTRY');\n\n/**\n * Consumer-provided file/image upload handler.\n * When supplied, image-field and file-field call it to persist the File and receive a stable\n * URL back. Without it the field stores `{ file, name, size, mimeType }` for the consumer to\n * upload on submit. May return the result directly, as a Promise, or as an Observable.\n *\n * @example\n * { provide: UPLOAD_HANDLER, useFactory: () => (file: File) => myUploadService.upload(file) }\n */\nexport const UPLOAD_HANDLER = new InjectionToken<FileUploadHandler>('UPLOAD_HANDLER');\n\n/**\n * Reads an uploaded spreadsheet into headers and positional rows, for the import wizard.\n *\n * Unregistered, the wizard reads CSV with the dependency-free parser in\n * `@dynamic-entity/core`, so it works with nothing provided. Register one to accept `.xlsx`\n * — which spreadsheet library that uses stays the consumer's choice, and this package keeps\n * having no runtime dependency.\n *\n * Rows come back **positional** (`string[][]`) rather than keyed by header, because a real\n * sheet has duplicate headers and blank ones; a header-keyed row silently loses the second\n * of two columns both called \"Notes\".\n *\n * @example\n * provideNgxDynamicEntity({\n * sheetParser: async file => {\n * const wb = XLSX.read(await file.arrayBuffer());\n * const rows = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], {\n * header: 1, raw: false, defval: '',\n * }) as string[][];\n * return { headers: rows[0] ?? [], rows: rows.slice(1) };\n * },\n * })\n */\nexport const SHEET_PARSER = new InjectionToken<SheetParser>('SHEET_PARSER');\n\n/**\n * Where an import's work happens.\n *\n * Unregistered, everything runs in the browser through `@dynamic-entity/core` and nothing\n * touches the network — the wizard is fully usable with no backend. Register one that posts\n * to a server and the same components drive that instead, over the same pure mapping engine,\n * which is what keeps a client-side import and a server-side one from disagreeing about what\n * they produced.\n *\n * The reason to register one is size: the default reads the whole file into memory, which is\n * right for a sheet somebody assembled and wrong for a fifty-thousand-row export.\n *\n * @example\n * { provide: IMPORT_TRANSPORT, useClass: HttpImportTransport }\n */\nexport const IMPORT_TRANSPORT = new InjectionToken<ImportTransport>('IMPORT_TRANSPORT');\n\n/**\n * Backing store for the entity-reference options cache. Defaults to in-memory.\n * Provide your own to make the cache outlive a page refresh.\n *\n * @example\n * { provide: ENTITY_REF_CACHE_STORE, useClass: SessionStorageRefCache }\n */\nexport const ENTITY_REF_CACHE_STORE = new InjectionToken<EntityRefCacheStore>('ENTITY_REF_CACHE_STORE', {\n providedIn: 'root',\n factory: () => new InMemoryEntityRefCacheStore(),\n});\n\n/**\n * Consumer-provided predicate function to check whether user roles can edit system default tabs or fields.\n * Defaults to allowing edits if not provided.\n */\nexport const SYSTEM_DEFAULT_CAN_EDIT = new InjectionToken<(roles: string[]) => boolean>('SYSTEM_DEFAULT_CAN_EDIT');\n\nexport type ConfigSourceHandler = (entityKey: string) => any;\n\n/**\n * Registry/Resolver for resolving an EntityFormConfig by entity key across entities (Phase 8).\n * Enables cross-entity field referencing (`isReferenced`, `referencedEntityKey`, `referencedFieldId`, `hasDrift`).\n */\nexport const CONFIG_SOURCE = new InjectionToken<ConfigSourceHandler>('CONFIG_SOURCE');\n\n/**\n * Turns the markdown a `markdown` field stores into HTML for display.\n *\n * Optional, and deliberately not bundled: these packages declare no runtime dependencies\n * beyond `tslib`, and a markdown parser is a large one to force on every consumer. Without\n * a renderer the field still works — it stores and shows the source text, with line breaks\n * preserved and nothing interpreted.\n *\n * The returned HTML is bound through `[innerHTML]`, so Angular's sanitizer strips scripts\n * and event handlers before it reaches the DOM. That is a backstop, not a licence: a\n * renderer should still be configured to escape raw HTML in its input, because sanitizing\n * removes the dangerous parts silently rather than telling the author their content was\n * altered.\n *\n * @example\n * import { marked } from 'marked';\n * { provide: MARKDOWN_RENDERER, useValue: (src: string) => marked.parse(src) as string }\n */\nexport const MARKDOWN_RENDERER = new InjectionToken<(source: string) => string>('MARKDOWN_RENDERER');\n\n/**\n * The text a masked field shows in place of its value. Defaults to `XXXXXXXXX`.\n *\n * Masking is presentational — see SECURITY.md — and what it prints is a product decision:\n * `••••••••` reads as a redaction, \"Hidden\" reads as a permission, and a localized string\n * reads as neither in English. It was a literal repeated across every field component, so\n * there was no way to choose.\n *\n * @example\n * { provide: MASKED_PLACEHOLDER, useValue: '••••••••' }\n */\nexport const MASKED_PLACEHOLDER = new InjectionToken<string>('MASKED_PLACEHOLDER');\n\n/**\n * Overrides for the library's own chrome — Save, Reset, \"No rows yet.\", and the rest.\n *\n * Field labels and options come from the config as `LocalizedText` and already follow the\n * form's `language`. This is the text *around* them, which was English literals in the\n * templates: an application in German rendered German labels around English buttons.\n *\n * The library does no translating — it publishes the keys it renders and resolves whatever\n * a host hands back. `DEFAULT_UI_TEXT` is the full list of keys with their English source\n * strings, so a translation file can be generated from it rather than transcribed. Anything\n * left out keeps its English default.\n *\n * @example The config's own shape — `LocalizedText` per key, resolved against `language`\n * {\n * provide: UI_TEXT,\n * useValue: {\n * save: { en: 'Save', de: 'Speichern' },\n * reset: { en: 'Reset', de: 'Zurücksetzen' },\n * },\n * }\n *\n * @example One language, or a host that re-provides on switch\n * { provide: UI_TEXT, useValue: { save: 'Speichern', reset: 'Zurücksetzen' } }\n *\n * @example An existing i18n layer (ngx-translate, Transloco, $localize)\n * {\n * provide: UI_TEXT,\n * useFactory: () => {\n * const translate = inject(TranslateService);\n * return (key, defaultText) => translate.instant(`dynamicEntity.${key}`) || defaultText;\n * },\n * }\n *\n * A resolver is read during change detection, so it must be synchronous and cheap.\n */\nexport const UI_TEXT = new InjectionToken<UiTextOverrides>('UI_TEXT');\n","import { EnvironmentProviders, makeEnvironmentProviders, Type } from '@angular/core';\nimport type { EntityReferenceLoader, LookupListSource, RecordMigration } from '@dynamic-entity/core';\nimport {\n ENTITY_REF_REGISTRY,\n FIELD_TYPE_REGISTRY,\n HOOK_REGISTRY,\n type HookFn,\n ASYNC_VALIDATOR_REGISTRY,\n RECORD_MIGRATIONS,\n VALIDATION_MESSAGES,\n LOOKUP_REGISTRY,\n MASKED_ROLES,\n UI_TEXT,\n VALIDATOR_REGISTRY,\n SHEET_PARSER,\n IMPORT_TRANSPORT,\n} from '../tokens/injection-tokens';\nimport type { UiTextOverrides } from '../services/ui-text.service';\nimport type { ImportTransport, SheetParser } from '../import/import-contracts';\n\nexport interface NgxDynamicEntityConfig {\n /** Roles that see masked field values as XXXXXXXXX */\n maskedRoles?: string[];\n /** Custom field type components keyed by type string */\n fieldTypes?: Record<string, Type<any>>;\n /**\n * Entity-ref option loaders keyed by entity key.\n * Each receives `{ parentValue, filters, lang }` and may return an array, Promise, or Observable.\n */\n entityRefs?: Record<string, EntityReferenceLoader>;\n /**\n * Named master lists keyed by list name, for fields that set `listName`.\n * Each may be the values themselves (array/Promise/Observable) or a loader function — prefer\n * a loader for anything fetched, so an unused list is never loaded.\n */\n lookups?: Record<string, LookupListSource>;\n /**\n * Override the messages shown under invalid fields, keyed by Angular error key. A value is\n * a string, or a function receiving `(language, error)` when it needs the error's detail.\n * Unlisted keys keep their English default.\n */\n validationMessages?: Record<string, string | ((language: string, error: any) => string)>;\n /**\n * Override the library's own chrome — Save, Reset, \"No rows yet.\". Either a partial map\n * keyed by `UiTextKey`, whose values are strings or the same `LocalizedText` a field label\n * uses (`{ en, de }`, resolved against the form's `language`), or a resolver\n * `(key, defaultText, language) => string` that hands the key to an existing i18n layer.\n * `DEFAULT_UI_TEXT` lists every key with its English source string; unlisted keys keep it.\n */\n uiText?: UiTextOverrides;\n /**\n * Async validator functions keyed by name, for checks that need a server — uniqueness,\n * availability, a remote rule. Name them from a schema with\n * `validators: { customAsync: ['uniqueEmail'] }`.\n *\n * Each is an Angular `AsyncValidatorFn`: it receives the control and returns a Promise or\n * Observable of `ValidationErrors | null`. The control is `pending` while it runs, and the\n * form cannot be submitted until every pending check settles.\n */\n asyncValidators?: Record<string, any>;\n /** Custom validator functions keyed by validator name */\n validators?: Record<string, any>;\n /** Hook functions keyed by hook name */\n hooks?: Record<string, HookFn>;\n /**\n * Ordered steps that upgrade a saved record when `EntityFormConfig.version` moves ahead\n * of the record's `_configVersion`. Applied to `initialData` before the form is patched.\n */\n migrations?: RecordMigration[];\n /**\n * Reads an uploaded spreadsheet for the import wizard, as `{ headers, rows }` with rows\n * positional rather than keyed by header.\n *\n * Omit it and CSV is read by the dependency-free parser in `@dynamic-entity/core`; supply\n * one to accept `.xlsx`, using whichever spreadsheet library you already have.\n */\n sheetParser?: SheetParser;\n /**\n * Where an import's work happens. Omit it and the whole import runs in the browser with no\n * network at all; supply one that posts to a server for files too large to hold in memory.\n * Either way the mapping, coercion and validation are the same pure functions.\n */\n importTransport?: ImportTransport;\n}\n\n/**\n * Provider function for ngx-dynamic-entity.\n * All options are optional — consumers provide only what they use (ISP).\n *\n * Usage in app.config.ts:\n * provideNgxDynamicEntity({\n * maskedRoles: ['IT_SUPPORT'],\n * entityRefs: { clients: () => clientService.getOptions() },\n * })\n */\nexport const provideNgxDynamicEntity = (config: NgxDynamicEntityConfig = {}): EnvironmentProviders =>\n makeEnvironmentProviders([\n { provide: MASKED_ROLES, useValue: config.maskedRoles ?? [] },\n { provide: FIELD_TYPE_REGISTRY, useValue: new Map(Object.entries(config.fieldTypes ?? {})) },\n { provide: ENTITY_REF_REGISTRY, useValue: new Map(Object.entries(config.entityRefs ?? {})) },\n { provide: LOOKUP_REGISTRY, useValue: new Map(Object.entries(config.lookups ?? {})) },\n { provide: VALIDATOR_REGISTRY, useValue: new Map(Object.entries(config.validators ?? {})) },\n {\n provide: ASYNC_VALIDATOR_REGISTRY,\n useValue: new Map(Object.entries(config.asyncValidators ?? {})),\n },\n { provide: HOOK_REGISTRY, useValue: new Map(Object.entries(config.hooks ?? {})) },\n { provide: RECORD_MIGRATIONS, useValue: config.migrations ?? [] },\n { provide: VALIDATION_MESSAGES, useValue: config.validationMessages ?? {} },\n { provide: UI_TEXT, useValue: config.uiText ?? {} },\n // Both optional and both null when unset: the wizard falls back to the built-in CSV\n // parser and the in-browser transport, so it works with nothing registered.\n { provide: SHEET_PARSER, useValue: config.sheetParser ?? null },\n { provide: IMPORT_TRANSPORT, useValue: config.importTransport ?? null },\n ]);\n","import { Injectable, inject } from '@angular/core';\nimport type { ValidationErrors } from '@angular/forms';\nimport { VALIDATION_MESSAGES } from '../tokens/injection-tokens';\n\n/**\n * Resolves an Angular `ValidationErrors` object to the message shown under a field.\n *\n * These strings used to be hardcoded English literals inside each field component, so a\n * German form meant re-implementing every field type — the labels honoured `language` while\n * the errors underneath them did not.\n *\n * A message is a plain string, or a function when it needs the error's own detail\n * (`minlength.requiredLength`, `min.min`, and so on). The active `language` is passed\n * through, so one registration can serve every locale:\n *\n * ```typescript\n * provideNgxDynamicEntity({\n * validationMessages: {\n * required: lang => (lang === 'de' ? 'Pflichtfeld.' : 'This field is required.'),\n * minlength: (lang, err) => `Mindestens ${err['requiredLength']} Zeichen.`,\n * },\n * });\n * ```\n *\n * Unregistered keys fall back to the defaults below, so overriding one message does not\n * mean supplying them all.\n */\nexport type ValidationMessage = string | ((language: string, error: any) => string);\n\n/** The built-in English messages. Every key here can be overridden individually. */\nexport const DEFAULT_VALIDATION_MESSAGES: Record<string, ValidationMessage> = {\n required: 'This field is required.',\n requiredSelection: 'Please select an option.',\n email: 'Please enter a valid email address.',\n pattern: 'Invalid format.',\n minlength: (_lang, err) => `Minimum ${err?.requiredLength} characters required.`,\n maxlength: (_lang, err) => `Maximum ${err?.requiredLength} characters allowed.`,\n min: (_lang, err) => `Value must be at least ${err?.min}.`,\n max: (_lang, err) => `Value must not exceed ${err?.max}.`,\n invalid: 'Invalid value.',\n invalidNumber: 'Invalid number.',\n invalidSelection: 'Invalid selection.',\n};\n\n/** An error key, or a pair mapping one to a different message key. */\nexport type MessageOrderEntry = string | readonly [errorKey: string, messageKey: string];\n\n/**\n * The keys a plain input can raise, most specific first.\n *\n * A type that cannot raise one of these is unaffected by its presence — `resolve` returns the\n * first error actually on the control — so the shared list costs nothing and spares every\n * field component a near-identical copy of it.\n */\nconst COMMON_ORDER: readonly MessageOrderEntry[] = ['required', 'email', 'min', 'max', 'minlength', 'maxlength', 'pattern'];\n\n/**\n * Where a field type disagrees with the common list.\n *\n * Only three do, and each for a reason about how the control reads rather than what it can\n * raise: a select says \"Please select an option\" where an input says \"This field is\n * required\"; a number that is neither required nor out of range is not \"invalid\", it is not a\n * number; and a control with no text in it cannot fail a length or format rule.\n */\nconst ORDER_BY_FIELD_TYPE: Readonly<Record<string, { order: readonly MessageOrderEntry[]; fallback: string }>> = {\n dropdown: { order: [['required', 'requiredSelection']], fallback: 'invalidSelection' },\n number: { order: ['required', 'min', 'max'], fallback: 'invalidNumber' },\n boolean: { order: ['required', 'pattern'], fallback: 'invalid' },\n checkbox: { order: ['required', 'pattern'], fallback: 'invalid' },\n file: { order: ['required', 'pattern'], fallback: 'invalid' },\n image: { order: ['required', 'pattern'], fallback: 'invalid' },\n};\n\n@Injectable({ providedIn: 'root' })\nexport class ValidationMessagesService {\n private readonly overrides = inject(VALIDATION_MESSAGES, { optional: true }) ?? {};\n\n /**\n * The message for the first error present, in the order the caller lists.\n *\n * Order is the caller's because it is field-specific: a dropdown wants\n * `requiredSelection` where a text input wants `required`, and the first match wins so the\n * most specific message is the one shown.\n */\n resolve(\n errors: ValidationErrors | null | undefined,\n language: string,\n order: readonly (string | readonly [errorKey: string, messageKey: string])[],\n fallbackKey = 'invalid',\n ): string {\n if (!errors) return '';\n\n for (const entry of order) {\n // A tuple maps an Angular error key to a different message key: a dropdown raises the\n // standard `required` error but reads better as \"Please select an option\", and both\n // messages stay independently overridable.\n const [errorKey, messageKey] = typeof entry === 'string' ? [entry, entry] : entry;\n // `errors[errorKey]` is usually an object of detail, but `required` is simply `true`.\n if (errors[errorKey] === undefined) continue;\n return this.messageFor(messageKey, language, errors[errorKey]);\n }\n return this.messageFor(fallbackKey, language, null);\n }\n\n /**\n * The message for a field, chosen by its **type** rather than by a list the caller supplies.\n *\n * Every field component used to pass its own copy of the key order, and the copies were\n * near-identical — which was tolerable while the field itself was the only thing that\n * rendered a message. It stopped being tolerable when the error summary above the form\n * started naming what is wrong with each field: the summary has no field component to ask\n * (the offending field is usually on a tab that is not rendered), so it would have needed a\n * second copy of the same table, and a dropdown would have said \"This field is required\" in\n * the summary and \"Please select an option\" under the control.\n *\n * One table, read from both places, is what keeps those two sentences the same sentence.\n */\n resolveForField(errors: ValidationErrors | null | undefined, language: string, fieldType: string): string {\n const { order, fallback } = this.orderFor(fieldType);\n return this.resolve(errors, language, order, fallback);\n }\n\n /** A field type's key order. An unrecognised type — a consumer's own — gets the common list. */\n orderFor(fieldType: string): { order: readonly MessageOrderEntry[]; fallback: string } {\n return ORDER_BY_FIELD_TYPE[fieldType] ?? { order: COMMON_ORDER, fallback: 'invalid' };\n }\n\n /** One message by key, honouring an override before the default. */\n messageFor(key: string, language: string, error: unknown): string {\n const message = this.overrides[key] ?? DEFAULT_VALIDATION_MESSAGES[key];\n if (message === undefined) return '';\n return typeof message === 'function' ? message(language, error) : message;\n }\n}\n","/**\n * DOM ids that survive being rendered more than once.\n *\n * A field component used to derive its control's id straight from `field.id`. That is unique\n * in a config and *not* unique in a document: an `array` field renders the same child fields\n * once per row, so a two-row Contacts array put two `#name` inputs on the page. `<label for>`\n * resolves to the first match in document order, so clicking the second row's label focused\n * the first row's input, and a screen reader read the same association twice. Duplicate ids on\n * focusable elements are also a WCAG failure in their own right.\n *\n * The fix is a counter, which is what Angular Material does for the same reason: the id stays\n * readable — `email-de7` — and is unique for the lifetime of the page. It is deliberately not\n * derived from the row index, because a field component is given exactly five inputs and none\n * of them says where it is; adding a sixth would change the contract every custom field type\n * implements.\n *\n * Ids are not a public contract. Address a control in a test through its `data-testid`, which\n * is stable, or through its label, which is what a user sees.\n */\nlet sequence = 0;\n\n/** A token unique to one component instance, for the lifetime of the page. */\nexport function nextFieldInstanceId(): string {\n sequence += 1;\n return `de${sequence}`;\n}\n\n/**\n * `{fieldId}-{instance}{suffix}` — the field first, so the id still reads as the field it\n * belongs to when someone is looking at the DOM.\n *\n * `field` is undefined until the renderer assigns it, and a template can be checked once\n * before that happens.\n */\nexport function fieldDomId(field: { id?: string } | undefined, instance: string, suffix = ''): string {\n return `${field?.id ?? 'field'}-${instance}${suffix}`;\n}\n\n/**\n * The `aria-describedby` a control needs, given what is rendered beside it right now.\n *\n * A field can show two things under its control — the author's help text and, once touched, a\n * validation message — and a screen reader announces only what this attribute names. Three\n * field components named the error; the other sixteen named nothing at all, so their error\n * messages were on screen and silent. Help text would have inherited the same gap.\n *\n * Order matters: the hint describes the field and the error describes the attempt, so the hint\n * is read first. `null` rather than an empty string when there is nothing to describe — an\n * empty `aria-describedby` is a dangling reference, not an absent one.\n *\n * Shared rather than written into each of the twenty-one field components, because the rule is\n * the same everywhere and getting it wrong is invisible until somebody uses a screen reader.\n */\nexport function fieldDescribedBy(\n domId: (suffix?: string) => string,\n parts: { hint?: boolean; error?: boolean },\n): string | null {\n const ids: string[] = [];\n if (parts.hint) ids.push(domId('-hint'));\n if (parts.error) ids.push(domId('-error'));\n return ids.length ? ids.join(' ') : null;\n}\n","import { Component, Input, OnDestroy, inject, ChangeDetectionStrategy, signal } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport { Subscription } from 'rxjs';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-text-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--text\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n [class.ngx-field--invalid]=\"control && control.invalid && control.touched\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\"\n >{{ label }}\n @if (field.validators?.required) {\n <span class=\"ngx-field__req\">*</span>\n }\n </label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{ displayValue() ?? '—' }}</span>\n } @else {\n <input\n [id]=\"domId()\"\n type=\"text\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [formControl]=\"$any(control)\"\n [placeholder]=\"placeholder\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-invalid]=\"control.invalid && control.touched\"\n [attr.aria-describedby]=\"describedBy()\"\n />\n @if (errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class TextFieldComponent implements OnDestroy {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n private displaySub?: Subscription;\n\n @Input() field!: NestedFieldConfig;\n @Input()\n set control(value: AbstractControl) {\n this._control = value;\n this.displaySub?.unsubscribe();\n this.displayValue.set(value?.value ?? null);\n this.displaySub = value?.valueChanges.subscribe(v => this.displayValue.set(v));\n }\n get control(): AbstractControl {\n return this._control;\n }\n private _control!: AbstractControl;\n\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n /** Readonly markup reads this signal so an external patch (autoPatch) is visible under OnPush. */\n readonly displayValue = signal<unknown>(null);\n\n ngOnDestroy(): void {\n this.displaySub?.unsubscribe();\n }\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control || !this.control.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-textarea-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--textarea\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{ control.value }}</span>\n } @else {\n <textarea\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [placeholder]=\"placeholder\"\n [attr.disabled]=\"field.disabled ? true : null\"\n rows=\"3\"\n ></textarea>\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class TextareaFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport { resolveLabel, type LocalizedText } from '@dynamic-entity/core';\nimport { UI_TEXT } from '../tokens/injection-tokens';\n\n/** `{name}` — the slot a `UiTextParams` entry fills. */\nconst PLACEHOLDER = new RegExp('[{]([a-zA-Z0-9_]+)[}]', 'g');\n\n/**\n * Every word this library puts on screen that does not come from a config.\n *\n * Field labels, placeholders and options are `LocalizedText` and already follow the form's\n * `language`. The library's *own* chrome — Save, Reset, \"No rows yet.\" — was English\n * literals in twenty-odd templates, so an application in German rendered German labels\n * around English buttons. There was no way to change them short of forking a component.\n *\n * This map is the whole surface: the keys are what a host translates, and the values are\n * the English source strings to translate *from*. It is exported so a translation file can\n * be generated from it rather than transcribed by hand.\n *\n * Keys are grouped by where they appear rather than alphabetically, because a translator\n * works screen by screen and a list sorted by name hides which strings sit together.\n */\nexport const DEFAULT_UI_TEXT = {\n // Form actions\n save: 'Save',\n saving: 'Saving…',\n reset: 'Reset',\n saveShortcutHint: 'Shortcut: Ctrl+S',\n loading: 'Loading…',\n\n // Why a save was refused — the summary above the form, and the count on each tab\n errorSummaryTitle: '{count} field(s) need attention before this can be saved.',\n tabErrorCount: '{count} field(s) need attention on this tab',\n\n // Record view — the per-tab edit flow\n editSection: 'Edit section',\n saveSection: 'Save section',\n editingSection: 'Editing this section',\n cancel: 'Cancel',\n edit: 'Edit',\n delete: 'Delete',\n\n // Array rows\n addRow: '+ Row',\n addItem: '+ Add Item',\n itemNumber: 'Item #{number}',\n addRowTitle: 'Add {field} row',\n editRowTitle: 'Edit {field} row',\n saveRow: 'Save row',\n remove: 'Remove',\n noRows: 'No rows yet.',\n noItems: 'No items added yet.',\n\n // Choice fields\n selectPlaceholder: 'Select...',\n selectParentFirst: 'Select {field} first.',\n\n // Boolean and checkbox display\n yes: 'Yes',\n no: 'No',\n\n // Files and images\n uploading: 'Uploading…',\n chooseFile: 'Choose file',\n replaceFile: 'Replace file',\n removeFile: 'Remove file',\n downloadFile: 'Download file',\n noImage: 'No image',\n uploadImage: 'Upload',\n changeImage: 'Change',\n\n // Month / year pickers\n month: 'Month',\n year: 'Year',\n\n // Markdown editor\n write: 'Write',\n preview: 'Preview',\n markdownEditorMode: '{label} editor mode',\n\n // Accessible names for icon-only controls\n showPassword: 'Show password',\n hidePassword: 'Hide password',\n lockField: 'Lock {field}',\n unlockField: 'Unlock {field}',\n criticalFieldLockHint: 'Critical field — click to lock',\n criticalFieldUnlockHint: 'Critical field — click to unlock for editing',\n dismissBanner: 'Dismiss: {message}',\n jumpToField: 'Click to jump to {field}',\n\n // Import wizard — the steps, in order\n importUpload: 'Choose a file',\n importMap: 'Match columns',\n importReview: 'Review',\n importDone: 'Done',\n\n // Import wizard — choosing a file\n importChooseFile: 'Choose a spreadsheet',\n importFileChosen: '{name} — {rows} row(s)',\n importReading: 'Reading the file…',\n importNeedFile: 'Choose a file to continue.',\n\n // Import wizard — the template a user can start from\n importTemplateHeading: 'Start from a template',\n importTemplateExplain: 'Download a sheet with the right columns, fill it in, and upload it.',\n importTemplateDownload: 'Download template',\n importTemplateSelectAll: 'Select all',\n importTemplateSelectNone: 'Select none',\n importTemplateUnsupported: '{count} field(s) cannot be carried by a spreadsheet.',\n\n // Import wizard — matching columns\n importColumnInFile: 'Column in your file',\n importTargetField: 'Field',\n importUnmapped: 'Not imported',\n importGuessed: 'Guessed',\n importMappedCount: '{mapped} of {total} field(s) matched.',\n importRequiredUnmapped: '{count} required field(s) still need a column.',\n\n // Import wizard — review and result\n importPreviewHeading: 'First {count} row(s), as they will be saved',\n importRowRejected: 'This row will not be imported: {reason}',\n importRunImport: 'Import {count} row(s)',\n importImporting: 'Importing…',\n importSucceeded: 'Imported {count} record(s).',\n importSkippedRows: '{count} blank row(s) skipped.',\n importFailedRows: '{count} row(s) could not be imported.',\n // A streaming transport caps what it retains — fifty thousand error objects is the same\n // unbounded growth as holding the file — so the count and the sample are different numbers\n // and the user is told which they are looking at.\n importErrorsTruncated: 'Showing the first {shown} of {count} problem(s).',\n importStartOver: 'Import another file',\n\n // Import wizard — what went wrong\n importErrorsHeading: 'Rows that need attention',\n importErrorRow: 'Row {row}',\n importErrorField: 'Field',\n importErrorReason: 'Reason',\n importPlanProblem: 'This mapping cannot be used: {message}',\n\n // Banners and whole-record states\n entityLabel: 'Entity: {entity}',\n criticalFieldChanged: '🔒 Critical field changed: {fields} — this differs from the value at the start of this session.',\n recordModified: '🔒 Record modified from session baseline — unsaved changes pending.',\n accessDenied: 'You do not have permission to view this record.',\n};\n\n/**\n * The keys above, as a union. Templates are checked against it, so a mistyped key is an\n * AOT error rather than a blank button, and a host writing overrides gets completion.\n */\nexport type UiTextKey = keyof typeof DEFAULT_UI_TEXT;\n\n/**\n * One replacement: a plain string, or the same `LocalizedText` map a config uses for a\n * field label — `{ en: 'Save', de: 'Speichern' }`, resolved against the form's `language`\n * by the very function that resolves the labels beside it.\n */\nexport type UiTextValue = string | LocalizedText;\n\n/**\n * Asked for one key at render time, given the English default to fall back on and the\n * form's active language.\n *\n * This is the seam for an existing i18n setup — `$localize`, ngx-translate, Transloco —\n * whose catalogue is language-first (`de.json`) rather than key-first, and which already\n * holds its own idea of the current language. Take `language` or ignore it accordingly.\n */\nexport type UiTextResolverFor<K extends string> = (key: K, defaultText: string, language: string) => string;\n\n/** The resolver for this library's own keys. */\nexport type UiTextResolver = UiTextResolverFor<UiTextKey>;\n\n/**\n * Values substituted into a `{placeholder}` in the text.\n *\n * A sentence with a name in the middle has to travel as one string: word order moves\n * between languages, so splitting it into fragments around an interpolation produces\n * grammatical nonsense in the ones it was not written for.\n */\nexport type UiTextParams = Record<string, string | number>;\n\n/** Either a partial map of replacements, or a resolver that answers per key. */\nexport type UiTextOverridesFor<K extends string> = Partial<Record<K, UiTextValue>> | UiTextResolverFor<K>;\n\n/** The overrides for this library's own keys. */\nexport type UiTextOverrides = UiTextOverridesFor<UiTextKey>;\n\n/**\n * The resolution rule itself, over any key vocabulary.\n *\n * Exported because the builder package renders a second, disjoint set of words and needs\n * the same rule — overrides first, then the English default, per key, with `{placeholder}`\n * substitution. Sharing the function rather than the vocabulary is what keeps a renderer\n * consumer from seeing a hundred and fifty builder keys in completion.\n */\nexport function resolveUiText<K extends string>(\n overrides: UiTextOverridesFor<K> | null | undefined,\n defaults: Readonly<Record<K, string>>,\n key: K,\n language: string,\n params?: UiTextParams,\n): string {\n const fallback = ownString(defaults, key);\n const resolved = !overrides\n ? fallback\n : typeof overrides === 'function'\n ? askResolver(overrides, key, fallback, language)\n : // `resolveLabel` handles a bare string at runtime but does not say so in its\n // signature, so the branch is taken here rather than leaning on an undeclared one.\n resolveOne(own<UiTextValue | undefined>(overrides, key), language) || fallback;\n\n return interpolate(resolved, params);\n}\n\n/**\n * An **own** entry, or `undefined`.\n *\n * `map[key]` walks the prototype chain, so `toString` answers with `Function` and\n * `__proto__` with `Object.prototype` — neither of which is a string, and both of which\n * reach `interpolate` and then a template. The key type rules that out in TypeScript; a key\n * arriving from a translation catalogue at runtime, or from a host written in JavaScript,\n * does not.\n */\nfunction own<T>(map: Partial<Record<string, T>>, key: string): T | undefined {\n return Object.prototype.hasOwnProperty.call(map, key) ? map[key] : undefined;\n}\n\nfunction ownString<K extends string>(defaults: Readonly<Record<K, string>>, key: K): string {\n const value = own(defaults as Record<string, unknown>, key);\n return typeof value === 'string' ? value : '';\n}\n\n/**\n * A resolver runs inside change detection, once per label per pass, in someone else's code.\n *\n * If it throws, the exception surfaces from a template expression and the form does not\n * render at all — every form in the application, over one bad catalogue entry. Falling back\n * to English is the same answer this function already gives for a resolver that returns\n * nothing, and it keeps a translation fault a translation fault rather than an outage.\n */\nfunction askResolver<K extends string>(resolver: UiTextResolverFor<K>, key: K, fallback: string, language: string): string {\n try {\n const answer = resolver(key, fallback, language);\n return typeof answer === 'string' && answer ? answer : fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction resolveOne(value: UiTextValue | undefined, language: string): string {\n if (typeof value === 'string') return value;\n const resolved = resolveLabel(value, language);\n // `resolveLabel` is typed to return a string and does, for every shape it is documented\n // to take. A host handing it a number reaches `Object.values(42)`, which is empty.\n return typeof resolved === 'string' ? resolved : '';\n}\n\n/**\n * Resolves the library's own UI text, honouring `UI_TEXT` before the defaults.\n *\n * Resolution is per key, not all-or-nothing, so a host replacing three buttons does not\n * have to supply the other thirty — and an override that yields nothing for a key still\n * renders English rather than a gap, which is what a translation catalogue asked for a\n * missing entry typically hands back.\n */\n@Injectable({ providedIn: 'root' })\nexport class UiTextService {\n private readonly overrides = inject(UI_TEXT, { optional: true });\n\n /**\n * One label by key, in `language`; English if nothing overrides it. `params` fill the\n * `{placeholder}` slots, in whatever position the translation puts them.\n */\n text(key: UiTextKey, language = 'en', params?: UiTextParams): string {\n return resolveUiText(this.overrides, DEFAULT_UI_TEXT, key, language, params);\n }\n}\n\n/** A placeholder with no matching param is left as written, which is visible in review. */\nfunction interpolate(text: string, params?: UiTextParams): string {\n if (!params) return text;\n // `name in params` would answer for `toString` and `constructor` too, substituting a\n // function body into a sentence. Only what the caller actually passed counts.\n return text.replace(PLACEHOLDER, (match, name) => {\n const value = own(params as Record<string, unknown>, name);\n return value === undefined || value === null ? match : String(value);\n });\n}\n","import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n DestroyRef,\n Input,\n OnChanges,\n SimpleChanges,\n inject,\n signal,\n} from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { MARKDOWN_RENDERER, MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/**\n * Markdown field: a long-form input that stores **markdown source**, never HTML.\n *\n * Storing the source rather than rendered HTML is the whole design. The record stays plain\n * text — diffable, portable, safe to log, and impossible to turn into stored XSS by writing\n * it into a database. Rendering happens at display time and only when a consumer asks for\n * it, via `MARKDOWN_RENDERER`.\n *\n * Without a renderer this degrades to exactly what `textarea` does, plus preserved line\n * breaks: the source is shown as text with nothing interpreted. That is the default because\n * these packages declare no runtime dependencies beyond `tslib`, and a markdown parser is a\n * large thing to force on a consumer who wanted a form library.\n *\n * With a renderer, its HTML is bound through `[innerHTML]`, which Angular sanitizes — see\n * the token's own note on why that is a backstop rather than a licence.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-markdown-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--markdown\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n @if (rendered(); as html) {\n <div\n class=\"ngx-field__value ngx-field__markdown\"\n [attr.data-testid]=\"'field-' + field.id + '-value'\"\n [innerHTML]=\"html\"\n ></div>\n } @else {\n <!-- No renderer: the source is the display. The stylesheet keeps its line\n breaks with white-space: pre-wrap, and interpolation escapes it. -->\n <span class=\"ngx-field__value ngx-field__markdown--source\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n control.value\n }}</span>\n }\n } @else {\n <div class=\"ngx-field__markdown-editor\">\n @if (canPreview) {\n <div\n class=\"ngx-field__markdown-tabs\"\n role=\"group\"\n [attr.aria-label]=\"ui.text('markdownEditorMode', language, { label })\"\n >\n <button\n type=\"button\"\n class=\"ngx-field__markdown-tab\"\n [attr.data-testid]=\"'field-' + field.id + '-write'\"\n [attr.aria-pressed]=\"!previewing()\"\n (click)=\"previewing.set(false)\"\n >\n {{ ui.text('write', language) }}\n </button>\n <button\n type=\"button\"\n class=\"ngx-field__markdown-tab\"\n [attr.data-testid]=\"'field-' + field.id + '-preview'\"\n [attr.aria-pressed]=\"previewing()\"\n (click)=\"previewing.set(true)\"\n >\n {{ ui.text('preview', language) }}\n </button>\n </div>\n }\n\n @if (previewing()) {\n <div\n class=\"ngx-field__markdown ngx-field__markdown--preview\"\n [attr.data-testid]=\"'field-' + field.id + '-preview-body'\"\n [innerHTML]=\"rendered()\"\n ></div>\n } @else {\n <textarea\n [id]=\"domId()\"\n class=\"ngx-field__input ngx-field__input--markdown\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [placeholder]=\"placeholder\"\n [attr.disabled]=\"field.disabled ? true : null\"\n rows=\"6\"\n ></textarea>\n }\n </div>\n\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class MarkdownFieldComponent implements OnChanges {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n /** Optional — the field is fully usable without one. */\n private readonly render = inject(MARKDOWN_RENDERER, { optional: true });\n private readonly cdr = inject(ChangeDetectorRef);\n private readonly destroyRef = inject(DestroyRef);\n\n protected readonly previewing = signal(false);\n\n private valueSub?: { unsubscribe(): void };\n\n /**\n * Re-render when the value changes from outside this component.\n *\n * `rendered()` reads `control.value`, which under OnPush is neither an input nor a\n * template event: typing in the textarea updates through `formControl`, but a host\n * calling `patchValue`, a rule, or an `autoPatch` mapping does not mark this component\n * dirty. The preview and the read-only view would keep showing the previous document\n * while the record already held a different one.\n */\n ngOnChanges(changes: SimpleChanges): void {\n if (!changes['control']) return;\n this.valueSub?.unsubscribe();\n this.valueSub = this.control?.valueChanges?.subscribe(() => this.cdr.markForCheck());\n if (this.valueSub) this.destroyRef.onDestroy(() => this.valueSub?.unsubscribe());\n }\n\n /** A Preview tab that can only ever show the source back is worse than no tab. */\n protected get canPreview(): boolean {\n return !!this.render;\n }\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n /**\n * Rendered HTML, or null when there is no renderer or nothing to render.\n *\n * A renderer is consumer code and may throw on input it does not like. Letting that\n * escape would take down the whole form over one malformed field, so it falls back to the\n * source text — which is what the field would have shown with no renderer at all.\n *\n * Memoised on the source, because this is called from the template: without it the\n * consumer's markdown parser ran on every change-detection pass, for every markdown field\n * on screen, over the whole document — which on a form holding a few long ones is a parse\n * per keystroke *elsewhere* in the form. The cache is keyed by the exact source string,\n * so a value that comes back to something already rendered is free too.\n */\n private cached?: { source: string; html: string | null };\n\n protected rendered(): string | null {\n const source = this.control?.value;\n if (!this.render || typeof source !== 'string' || source === '') return null;\n if (this.cached?.source === source) return this.cached.html;\n\n let html: string | null;\n try {\n html = this.render(source);\n } catch {\n html = null;\n }\n this.cached = { source, html };\n return html;\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, inject, ChangeDetectionStrategy } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-number-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--number\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n [class.ngx-field--invalid]=\"control && control.invalid && control.touched\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">\n {{ label }}\n @if (field.validators?.required) {\n <span class=\"ngx-field__req\">*</span>\n }\n </label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{ control.value ?? '—' }}</span>\n } @else {\n <input\n [id]=\"domId()\"\n type=\"number\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [formControl]=\"$any(control)\"\n [placeholder]=\"placeholder\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-invalid]=\"control.invalid && control.touched\"\n [attr.aria-describedby]=\"describedBy()\"\n />\n @if (errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class NumberFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control || !this.control.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/** Currency field: number input with locale-aware currency symbol prefix. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-currency-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--currency\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\"\n >{{ symbol }}{{ control.value }}</span\n >\n } @else {\n <div class=\"ngx-field__currency-wrap\">\n <span class=\"ngx-field__currency-symbol\">{{ symbol }}</span>\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input ngx-field__input--currency\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n type=\"number\"\n step=\"0.01\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [placeholder]=\"placeholder || '0.00'\"\n [attr.disabled]=\"field.disabled ? true : null\"\n />\n </div>\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class CurrencyFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n /** Picks the currency symbol from the locale — defaults to '$'. */\n get symbol(): string {\n try {\n return (\n (0)\n .toLocaleString(this.language, { style: 'currency', currency: 'USD', minimumFractionDigits: 0 })\n .replace(/[\\d,.\\s]/g, '')\n .trim() || '$'\n );\n } catch {\n return '$';\n }\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/** Email field: type=\"email\" input with inline validation hint. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-email-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--email\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">\n <a [href]=\"'mailto:' + control.value\" class=\"ngx-field__email-link\">{{ control.value || '—' }}</a>\n </span>\n } @else {\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n type=\"email\"\n autocomplete=\"email\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [placeholder]=\"placeholder || 'you@example.com'\"\n [attr.disabled]=\"field.disabled ? true : null\"\n />\n @if (errorMessage) {\n <!-- One branch, resolved by the service. The template used to spell out \"Email is\n required\" and \"Enter a valid email address\" itself, so a host configuring\n validationMessages was overridden by markup it could not reach. The service\n defaults say the same thing. -->\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class EmailFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, signal, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/** Password field: masked input with show/hide eye toggle. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-password-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--password\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">••••••••</span>\n } @else {\n <div class=\"ngx-field__password-wrap\">\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [type]=\"visible() ? 'text' : 'password'\"\n autocomplete=\"current-password\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [placeholder]=\"placeholder || '••••••••'\"\n [attr.disabled]=\"field.disabled ? true : null\"\n />\n <button\n type=\"button\"\n class=\"ngx-field__eye-btn\"\n (click)=\"toggleVisibility()\"\n [attr.aria-label]=\"ui.text(visible() ? 'hidePassword' : 'showPassword', language)\"\n >\n {{ visible() ? '🙈' : '👁' }}\n </button>\n </div>\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class PasswordFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n readonly visible = signal(false);\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n toggleVisibility(): void {\n this.visible.update(v => !v);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-checkbox-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--checkbox\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n @if (masked) {\n <label class=\"ngx-field__label\">{{ label }}</label>\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <label class=\"ngx-field__label\">{{ label }}</label>\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n control.value ? ui.text('yes', language) : ui.text('no', language)\n }}</span>\n } @else {\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n type=\"checkbox\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.disabled]=\"field.disabled ? true : null\"\n />\n {{ label }}\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </label>\n @if (errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class CheckboxFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n /**\n * Configured messages reach this field too.\n *\n * It rendered no error element at all, so a required checkbox left unticked told the user\n * nothing — and `validationMessages` could not reach a field that never displayed one.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/**\n * Boolean field: a slide-toggle style switch (true/false).\n * Distinct from `checkbox` (which is a standalone bool) in that it renders as a\n * toggle switch with Yes/No labels for clearer binary state communication.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-boolean-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--boolean\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n @if (masked) {\n <label class=\"ngx-field__label\">{{ label }}</label>\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <label class=\"ngx-field__label\">{{ label }}</label>\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n control.value ? ui.text('yes', language) : ui.text('no', language)\n }}</span>\n } @else {\n <div class=\"ngx-field__toggle-wrap\">\n <label class=\"ngx-field__toggle-label\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n <label class=\"ngx-field__toggle-switch\" [class.ngx-field__toggle-switch--checked]=\"control.value\">\n <input\n class=\"ngx-field__toggle-input\"\n type=\"checkbox\"\n role=\"switch\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-checked]=\"control.value\"\n />\n <span class=\"ngx-field__toggle-track\">\n <span class=\"ngx-field__toggle-thumb\"></span>\n </span>\n <span class=\"ngx-field__toggle-text\">{{\n control.value ? ui.text('yes', language) : ui.text('no', language)\n }}</span>\n </label>\n </div>\n @if (errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class BooleanFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n /**\n * Configured messages reach this field too.\n *\n * It rendered no error element at all, so a required checkbox left unticked told the user\n * nothing — and `validationMessages` could not reach a field that never displayed one.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { formatDisplayValue, resolveLabel } from '@dynamic-entity/core';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-date-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--date\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n formatDate(control.value)\n }}</span>\n } @else {\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n type=\"date\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.disabled]=\"field.disabled ? true : null\"\n />\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class DateFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n /**\n * ISO 8601 date → display string, through the formatter the host configured.\n *\n * This used to call `toLocaleDateString()` directly, which meant `setDateFormatters` — the\n * one seam for choosing how a date is rendered — reached the record summary and the `time`\n * field but not this one. A host that configured formatters got them almost everywhere,\n * and silently did not get them on the field type most likely to be the reason they\n * configured formatters at all.\n *\n * The default formatter is `toLocaleDateString()` with no locale, so an application that\n * has not called `setDateFormatters` renders exactly what it rendered before.\n */\n formatDate(value: string | null): string {\n if (!value) return '—';\n // `new Date('nonsense')` does not throw and `toLocaleDateString()` returns the *string*\n // \"Invalid Date\", so the try/catch this replaced never fired and readers saw that text\n // instead of their data. Records outlive schemas — a field retyped from text to date can\n // hold anything — so an unparseable value is shown as stored, and never reaches the\n // formatter.\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) return value;\n return formatDisplayValue('date', undefined, value, this.language);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { formatDisplayValue, resolveLabel } from '@dynamic-entity/core';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n/**\n * Reads a stored value into a `Date`.\n *\n * A bare calendar date is pinned to *local* midnight. `new Date('2020-01-01')` reads a\n * date-only string as UTC midnight, which renders as the previous day anywhere west of\n * Greenwich — and every legacy `datetime` value has exactly that shape, because the type\n * used to render through `DateFieldComponent` and its `type=\"date\"` input.\n */\nfunction parseStored(value: unknown): Date | null {\n if (value === null || value === undefined || value === '') return null;\n if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;\n\n const raw = String(value);\n const dateOnly = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(raw);\n if (dateOnly) return new Date(+dateOnly[1], +dateOnly[2] - 1, +dateOnly[3]);\n\n const parsed = new Date(raw);\n return Number.isNaN(parsed.getTime()) ? null : parsed;\n}\n\nconst pad = (n: number): string => String(n).padStart(2, '0');\n\n/**\n * Date & Time field: a single `datetime-local` input.\n *\n * The type is stored as ISO 8601 UTC, per the same convention `date` follows, while the\n * input works in the viewer's local zone — `datetime-local` has no offset, so the two\n * conversions here are what keep a value stable across a round trip.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-date-time-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--datetime\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n formatDateTime(control.value)\n }}</span>\n } @else {\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n type=\"datetime-local\"\n [value]=\"inputValue\"\n (change)=\"onInput($any($event.target).value)\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n />\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class DateTimeFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n /** Stored ISO 8601 → the `YYYY-MM-DDTHH:mm` local form the input requires. */\n get inputValue(): string {\n const d = parseStored(this.control?.value);\n if (!d) return '';\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;\n }\n\n /** The input's local `YYYY-MM-DDTHH:mm` → stored ISO 8601 UTC. */\n onInput(value: string): void {\n if (!value) {\n this.control.setValue(null);\n this.control.markAsTouched();\n return;\n }\n const d = new Date(value);\n // An unparseable value is stored verbatim rather than silently discarded, so a validator\n // sees what the user actually entered.\n this.control.setValue(Number.isNaN(d.getTime()) ? value : d.toISOString());\n this.control.markAsTouched();\n }\n\n /**\n * Displays date *and* time, through the formatter the host configured.\n *\n * Two rounds of the same fault. First this called `toLocaleDateString()`, so a datetime\n * read back through the field showed no time while the record summary showed it. Then it\n * called `toLocaleString()` directly, which fixed the time but kept the field outside\n * `setDateFormatters` — so a host that configured formatters still saw them apply to the\n * summary and not to the field. Going through `formatDisplayValue` is what makes the two\n * paths agree by construction rather than by matching literals.\n *\n * `parseStored` accepts shapes `new Date(raw)` alone does not, so the *parsed* instant is\n * handed on as ISO rather than the raw value.\n */\n formatDateTime(value: unknown): string {\n const d = parseStored(value);\n if (!d) return '—';\n return formatDisplayValue('datetime', undefined, d.toISOString(), this.language);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { formatDisplayValue, resolveLabel } from '@dynamic-entity/core';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n/**\n * Time field: a bare time of day, with no date and no zone attached.\n *\n * Stored as `HH:mm` — exactly the value `<input type=\"time\">` reads and writes, so the\n * control binds straight through with no conversion. That is the whole reason this is a\n * separate type from `datetime`: a recurring 09:00 opening time is not a moment in time,\n * and converting it to UTC would move it whenever the offset changed.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-time-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--time\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n formatTime(control.value)\n }}</span>\n } @else {\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n type=\"time\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.disabled]=\"field.disabled ? true : null\"\n />\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class TimeFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n /**\n * Defers to core rather than parsing `HH:mm` locally. The other date-ish components each\n * grew their own formatter, and `datetime` ended up showing one thing in the field and\n * another in the record summary because the two drifted apart.\n */\n formatTime(value: unknown): string {\n return formatDisplayValue('time', undefined, value, this.language);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\nconst MONTH_NAMES = [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December',\n];\n\nconst CURRENT_YEAR = new Date().getFullYear();\nconst YEARS = Array.from({ length: 80 }, (_, i) => CURRENT_YEAR - i);\n\n/**\n * Month-Year field: two linked selects (Month + Year).\n * Value stored as ISO partial date string \"YYYY-MM\" for unambiguous storage.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-month-year-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--month-year\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <!--\n Points at the month select: one visible label stands in front of two controls, and a\n label pointing at neither of them announces as nothing and focuses nothing when\n clicked. Each select then carries its own name below, because \"Billing Cycle\" alone\n does not say which half of the pair the screen reader has landed on.\n -->\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId('-month')\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n formatValue(control.value)\n }}</span>\n } @else {\n <div class=\"ngx-field__month-year-wrap\">\n <select\n [id]=\"domId('-month')\"\n class=\"ngx-field__input ngx-field__input--month\"\n [attr.aria-label]=\"label + ' ' + ui.text('month', language)\"\n [attr.data-testid]=\"'field-' + field.id + '-month'\"\n [value]=\"selectedMonth\"\n (change)=\"onMonthChange($any($event.target).value)\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n >\n <option value=\"\">{{ ui.text('month', language) }}</option>\n @for (m of months; track m.value) {\n <option [value]=\"m.value\">{{ m.label }}</option>\n }\n </select>\n <select\n [id]=\"domId('-year')\"\n class=\"ngx-field__input ngx-field__input--year\"\n [attr.aria-label]=\"label + ' ' + ui.text('year', language)\"\n [attr.data-testid]=\"'field-' + field.id + '-year'\"\n [value]=\"selectedYear\"\n (change)=\"onYearChange($any($event.target).value)\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n >\n <option value=\"\">{{ ui.text('year', language) }}</option>\n @for (y of years; track y) {\n <option [value]=\"y\">{{ y }}</option>\n }\n </select>\n </div>\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class MonthYearFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n readonly months = MONTH_NAMES.map((label, i) => ({ value: String(i + 1).padStart(2, '0'), label }));\n readonly years = YEARS;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n /** Parses \"YYYY-MM\" or \"YYYY-MM-DD\" stored value → month part. */\n get selectedMonth(): string {\n const v = String(this.control.value ?? '');\n return v.length >= 7 ? v.substring(5, 7) : '';\n }\n\n get selectedYear(): string {\n const v = String(this.control.value ?? '');\n return v.length >= 4 ? v.substring(0, 4) : '';\n }\n\n onMonthChange(month: string): void {\n const year = this.selectedYear || new Date().getFullYear().toString();\n this.control.setValue(month ? `${year}-${month}` : null);\n this.control.markAsTouched();\n }\n\n onYearChange(year: string): void {\n const month = this.selectedMonth || '01';\n this.control.setValue(year ? `${year}-${month}` : null);\n this.control.markAsTouched();\n }\n\n formatValue(value: unknown): string {\n if (!value) return '—';\n const [year, monthNum] = String(value).split('-');\n const monthName = MONTH_NAMES[parseInt(monthNum, 10) - 1];\n return monthName && year ? `${monthName} ${year}` : String(value);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Injectable, inject, type WritableSignal } from '@angular/core';\nimport type {\n DropdownOption,\n LookupListLoader,\n LookupListResult,\n LookupListSource,\n LookupListValue,\n NestedFieldConfig,\n RawLookupListValue,\n Subscribable,\n} from '@dynamic-entity/core';\nimport { lookupValuesToOptions, normalizeLookupValues, resolveLabel } from '@dynamic-entity/core';\nimport { LOOKUP_REGISTRY } from '../tokens/injection-tokens';\n\n/** Cache-key field separator. Kept out of template literals so it stays visible in source. */\nconst SEP = '|';\n\n/**\n * LookupRegistryService — the cache in front of consumer-registered master lists.\n *\n * Three layers, deliberately the same shape as `EntityReferenceService`, because the problem is\n * the same: one list is typically used by many fields across many entities.\n * 1. **options** — resolved `DropdownOption[]` per (list name, lang).\n * 2. **in-flight** — the pending Promise, so N fields on one list trigger one load, not N.\n * 3. **labels** — synchronous value → text (parity plan §6.2). This is not a nicety: since\n * `viewMode` defaults to true a record opens read-only, so rendering a stored value as\n * text is the *first* thing a `listName` field has to do. An async-only registry would\n * paint the raw stored value and then flip, on every record open.\n *\n * A failed load rejects and caches nothing, so one transient error does not serve an empty\n * list forever — the same fix made for entity references in phase 5.\n */\n@Injectable({ providedIn: 'root' })\nexport class LookupRegistryService {\n private readonly registry =\n inject(LOOKUP_REGISTRY, { optional: true }) ?? new Map<string, LookupListSource>();\n\n /** `listName|lang` -> resolved options. */\n private readonly options = new Map<string, DropdownOption[]>();\n /** `listName|lang` -> normalised values, so a consumer can reach `code` / `isSystemDefined`. */\n private readonly values = new Map<string, LookupListValue[]>();\n /** Loads in progress, keyed as above. */\n private readonly inFlight = new Map<string, Promise<DropdownOption[]>>();\n /** `listName|lang|text` -> display text, for the synchronous read-only path. */\n private readonly labels = new Map<string, string>();\n\n has(listName: string): boolean {\n return this.registry.has(listName);\n }\n\n /**\n * Options for a named list, from cache when present.\n * Concurrent callers with the same key share one load.\n */\n async load(listName: string, lang = 'en'): Promise<DropdownOption[]> {\n const key = this.cacheKey(listName, lang);\n\n const cached = this.options.get(key);\n if (cached) return cached;\n\n const pending = this.inFlight.get(key);\n if (pending) return pending;\n\n const source = this.registry.get(listName);\n if (source === undefined) return [];\n\n const load = this.invoke(source, lang).then(raw => {\n const values = normalizeLookupValues(raw);\n const options = lookupValuesToOptions(values);\n this.values.set(key, values);\n this.options.set(key, options);\n this.rememberLabels(listName, lang, options);\n return options;\n });\n\n // Only the `.then` above writes to the cache, and a rejection skips it: the caller still\n // gets an empty list, but the next call retries instead of reading a poisoned entry.\n const guarded = load\n .catch(() => [] as DropdownOption[])\n .finally(() => this.inFlight.delete(key));\n\n this.inFlight.set(key, guarded);\n return guarded;\n }\n\n /** Cached options without triggering a load. `undefined` when not loaded. */\n peek(listName: string, lang = 'en'): DropdownOption[] | undefined {\n return this.options.get(this.cacheKey(listName, lang));\n }\n\n /**\n * Cached list values, carrying `_id`, `code`, `isSystemDefined` and `from`.\n * The library never reads those; this is the seam for a consumer that needs them.\n */\n valuesFor(listName: string, lang = 'en'): LookupListValue[] | undefined {\n return this.values.get(this.cacheKey(listName, lang));\n }\n\n /**\n * Display text for a stored value, synchronously. `undefined` when the list has not loaded\n * or holds no matching value — the caller keeps its own fallback, which is the stored text.\n *\n * Every language of an option is indexed, so a record saved under one language renders in\n * another: a value stored as `'Aktiv'` resolves to `'Active'` under `lang: 'en'`.\n */\n labelFor(listName: string | undefined, value: unknown, lang = 'en'): string | undefined {\n if (!listName || value === null || value === undefined || value === '') return undefined;\n for (const text of this.candidateTexts(value, lang)) {\n const hit = this.labels.get(this.labelKey(listName, lang, text));\n if (hit) return hit;\n }\n return undefined;\n }\n\n // ─── Field-level resolution — inline options win, else `listName` ────────────\n\n /** True when this field's options have to come from the registry. */\n needsResolve(field: NestedFieldConfig | undefined): boolean {\n return !!field?.listName && !field.options?.length;\n }\n\n /**\n * The options to render right now, without awaiting: inline options, else whatever the\n * registry already holds. Empty on a cold miss — pair with `resolveOptions`.\n */\n optionsFor(field: NestedFieldConfig | undefined, lang = 'en'): DropdownOption[] {\n if (!field) return [];\n if (field.options?.length) return field.options;\n if (!field.listName) return [];\n return this.peek(field.listName, lang) ?? [];\n }\n\n /** The options for a field, loading the named list if needed. */\n resolveOptions(field: NestedFieldConfig | undefined, lang = 'en'): Promise<DropdownOption[]> {\n if (!this.needsResolve(field)) return Promise.resolve(this.optionsFor(field, lang));\n return this.load(field!.listName!, lang);\n }\n\n /** Drop everything cached for one list, leaving other lists intact. */\n invalidate(listName: string): void {\n const prefix = `${listName}${SEP}`;\n for (const map of [this.options, this.values, this.inFlight]) {\n for (const key of [...map.keys()]) {\n if (key.startsWith(prefix)) map.delete(key);\n }\n }\n for (const key of [...this.labels.keys()]) {\n if (key.startsWith(prefix)) this.labels.delete(key);\n }\n }\n\n clear(): void {\n this.options.clear();\n this.values.clear();\n this.inFlight.clear();\n this.labels.clear();\n }\n\n // ─── Internals ──────────────────────────────────────────────────────────────\n\n private cacheKey(listName: string, lang: string): string {\n return [listName, lang].join(SEP);\n }\n\n private labelKey(listName: string, lang: string, text: string): string {\n return [listName, lang, text].join(SEP);\n }\n\n /** Index an option under every language it carries, so any stored spelling finds it. */\n private rememberLabels(listName: string, lang: string, options: DropdownOption[]): void {\n for (const option of options) {\n const display = resolveLabel(option, lang);\n if (!display) continue;\n for (const text of Object.values(option)) {\n if (typeof text === 'string' && text !== '') {\n this.labels.set(this.labelKey(listName, lang, text), display);\n }\n }\n }\n }\n\n /** The texts a stored value could have been indexed under. */\n private candidateTexts(value: unknown, lang: string): string[] {\n if (typeof value === 'object') {\n const texts = Object.values(value as Record<string, unknown>).filter(\n (v): v is string => typeof v === 'string' && v !== '',\n );\n const resolved = resolveLabel(value as Record<string, string>, lang);\n return resolved ? [resolved, ...texts] : texts;\n }\n return [String(value)];\n }\n\n // ─── Source coercion (values | loader, array | Promise | Observable) ─────────\n\n private invoke(source: LookupListSource, lang: string): Promise<RawLookupListValue[]> {\n let result: LookupListResult;\n try {\n result = typeof source === 'function' ? (source as LookupListLoader)({ lang }) : source;\n } catch (err) {\n // Reject rather than resolve empty: `load` must be able to tell failure from an empty\n // list, or it would cache the failure.\n return Promise.reject(err);\n }\n return this.toPromise(result);\n }\n\n private toPromise(result: LookupListResult): Promise<RawLookupListValue[]> {\n if (Array.isArray(result)) return Promise.resolve(result);\n if (this.isSubscribable(result)) {\n // First emission wins, so a stream that stays open still resolves the load.\n return new Promise<RawLookupListValue[]>((resolve, reject) => {\n let settled = false;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n fn();\n };\n result.subscribe({\n next: value => settle(() => resolve(value ?? [])),\n error: err => settle(() => reject(err)),\n // Completing without emitting is a legitimate empty list, and is cached.\n complete: () => settle(() => resolve([])),\n });\n });\n }\n return Promise.resolve(result as Promise<RawLookupListValue[]>);\n }\n\n private isSubscribable(value: unknown): value is Subscribable<RawLookupListValue[]> {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Subscribable<RawLookupListValue[]>).subscribe === 'function'\n );\n }\n}\n\n/** A choice field component, as far as option resolution is concerned. */\nexport interface ChoiceOptionHost {\n readonly field: NestedFieldConfig | undefined;\n readonly language: string;\n readonly options: WritableSignal<DropdownOption[]>;\n}\n\nconst hostLastConfig = new WeakMap<ChoiceOptionHost, { field?: NestedFieldConfig; lang?: string }>();\n\n/**\n * Point a choice component's `options` signal at the right source (parity plan §6.3).\n *\n * Called from the `field` / `language` input setters of `dropdown`, `radio` and `multiSelect` —\n * the wiring is theirs, the decision is the service's, which is what keeps the field\n * five-input contract intact: options are never pushed in as a sixth input.\n *\n * Setters rather than `ngOnChanges` on purpose. `ngOnChanges` only fires for inputs Angular\n * itself sets, so a component whose `field` is assigned directly — which the field specs do,\n * and any consumer holding a `ComponentRef` may do — would render no options at all.\n *\n * Paints synchronously first (inline options, or a warm list), then fills in when a cold list\n * lands. The late result is dropped if the field or language changed while it was in flight.\n */\nexport function refreshChoiceOptions(host: ChoiceOptionHost, lookups: LookupRegistryService): void {\n const last = hostLastConfig.get(host);\n if (last && last.field === host.field && last.lang === host.language) {\n return;\n }\n hostLastConfig.set(host, { field: host.field, lang: host.language });\n\n host.options.set(lookups.optionsFor(host.field, host.language));\n if (!lookups.needsResolve(host.field)) return;\n\n const listName = host.field?.listName;\n const lang = host.language;\n void lookups.resolveOptions(host.field, host.language).then(options => {\n if (host.field?.listName === listName && host.language === lang) host.options.set(options);\n });\n}\n","import { Component, Input, inject, signal, ChangeDetectionStrategy } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { DropdownOption, NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { resolveLabel, resolveOptionLabel, valuesMatch } from '@dynamic-entity/core';\nimport { LookupRegistryService, refreshChoiceOptions } from '../services/lookup-registry.service';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-dropdown-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--dropdown\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n [class.ngx-field--invalid]=\"control && control.invalid && control.touched\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">\n {{ label }}\n @if (field.validators?.required) {\n <span class=\"ngx-field__req\">*</span>\n }\n </label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n getLabel(control.value)\n }}</span>\n } @else {\n <select\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [formControl]=\"$any(control)\"\n [compareWith]=\"compareFn\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-invalid]=\"control.invalid && control.touched\"\n [attr.aria-describedby]=\"describedBy()\"\n >\n <option [value]=\"''\">{{ placeholder || ui.text('selectPlaceholder', language) }}</option>\n @for (option of options(); track getOptLabel(option)) {\n @if (isObjectVal(option)) {\n <option [ngValue]=\"getOptStoredVal(option)\">{{ getOptLabel(option) }}</option>\n } @else {\n <option [value]=\"getOptStoredVal(option)\">{{ getOptLabel(option) }}</option>\n }\n }\n </select>\n @if (errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class DropdownFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly lookups = inject(LookupRegistryService);\n private readonly messages = inject(ValidationMessagesService);\n\n private _field!: NestedFieldConfig;\n private _language = 'en';\n\n /** Setter-based so options resolve however the input is set — see `refreshChoiceOptions`. */\n @Input() set field(value: NestedFieldConfig) {\n this._field = value;\n refreshChoiceOptions(this, this.lookups);\n }\n get field(): NestedFieldConfig {\n return this._field;\n }\n\n @Input() set language(value: string) {\n this._language = value || 'en';\n refreshChoiceOptions(this, this.lookups);\n }\n get language(): string {\n return this._language;\n }\n\n @Input() control!: AbstractControl;\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n /** Inline `options`, or the field's named list resolved through the registry (§6.3). */\n readonly options = signal<DropdownOption[]>([]);\n\n readonly compareFn = (o1: unknown, o2: unknown): boolean => valuesMatch(o1, o2, this.language);\n\n isObjectVal(option: DropdownOption): boolean {\n return typeof option === 'object' && option !== null;\n }\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n /**\n * The value this option stores — the option object itself.\n *\n * Kept as a method rather than binding `option` straight into the template, because it is\n * the one place that says *why* the two are the same thing. It used to delegate to\n * `getOptionStoredValue`, an exported identity function whose two branches returned their\n * argument unchanged; naming a transformation that does not happen is worse than naming\n * nothing, because a reader has to go and check.\n */\n getOptStoredVal(option: DropdownOption): unknown {\n return option;\n }\n\n getOptLabel(option: DropdownOption): string {\n return resolveOptionLabel(option, this.language);\n }\n\n /**\n * Read-only display. Never awaits (§6.2): a warm list resolves the label, a cold one falls\n * back to the stored text — which under the §2 contract *is* the display value, so it is\n * never wrong, only unlocalised.\n */\n getLabel(value: unknown): string {\n if (value == null || value === '') return '—';\n const option = this.options().find(o => valuesMatch(o, value, this.language));\n if (option) return this.getOptLabel(option);\n const cached = this.lookups.labelFor(this.field?.listName, value, this.language);\n if (cached) return cached;\n return typeof value === 'object' ? resolveLabel(value as Record<string, string>, this.language) : String(value ?? '—');\n }\n\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control || !this.control.errors || !this.control.touched) return '';\n // `requiredSelection` rather than `required`: \"Please select an option\" reads better on a\n // dropdown than \"This field is required\", and both stay independently overridable.\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, inject, signal, ChangeDetectionStrategy } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { DropdownOption, NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport {\n resolveLabel,\n resolveOptionLabel,\n resolveOptionValue,\n valuesMatch,\n} from '@dynamic-entity/core';\nimport { LookupRegistryService, refreshChoiceOptions } from '../services/lookup-registry.service';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n/** Radio field: a group of radio buttons built from field.options. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-radio-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--radio\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <fieldset class=\"ngx-field__fieldset\">\n <legend class=\"ngx-field__label\">\n {{ label }}\n @if (hint) {\n <!--\n Inside the legend rather than beside it: a fieldset allows exactly one legend\n and it must be the first child, so a sibling row would be invalid here.\n -->\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </legend>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{ getSelectedLabel() }}</span>\n } @else {\n <div class=\"ngx-field__radio-group\">\n @for (option of options(); track getOptLabel(option)) {\n <label class=\"ngx-field__radio-option\" [attr.for]=\"getRadioId(option)\">\n <input\n [id]=\"getRadioId(option)\"\n [attr.data-testid]=\"'field-' + field.id + '-option-' + optionSlug(option)\"\n type=\"radio\"\n class=\"ngx-field__radio-input\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [value]=\"getOptStoredVal(option)\"\n [attr.disabled]=\"field.disabled ? true : null\"\n />\n <span class=\"ngx-field__radio-label\">{{ getOptLabel(option) }}</span>\n </label>\n }\n </div>\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </fieldset>\n </div>\n `,\n})\nexport class RadioFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n private readonly lookups = inject(LookupRegistryService);\n\n private _field!: NestedFieldConfig;\n private _language = 'en';\n\n /** Setter-based so options resolve however the input is set — see `refreshChoiceOptions`. */\n @Input() set field(value: NestedFieldConfig) {\n this._field = value;\n refreshChoiceOptions(this, this.lookups);\n }\n get field(): NestedFieldConfig {\n return this._field;\n }\n\n @Input() set language(value: string) {\n this._language = value || 'en';\n refreshChoiceOptions(this, this.lookups);\n }\n get language(): string {\n return this._language;\n }\n\n @Input() control!: AbstractControl;\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n /** Inline `options`, or the field's named list resolved through the registry (§6.3). */\n readonly options = signal<DropdownOption[]>([]);\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n /**\n * The value this option stores — the option object itself.\n *\n * Kept as a method rather than binding `option` straight into the template, because it is\n * the one place that says *why* the two are the same thing. It used to delegate to\n * `getOptionStoredValue`, an exported identity function whose two branches returned their\n * argument unchanged; naming a transformation that does not happen is worse than naming\n * nothing, because a reader has to go and check.\n */\n getOptStoredVal(option: DropdownOption): unknown {\n return option;\n }\n\n /**\n * Stable DOM id for one radio, so the <label for> association works.\n * Slugified because the option text is the value now — \"On Leave\" must not put a space\n * into an id attribute.\n */\n getRadioId(option: DropdownOption): string {\n return this.domId(`-${this.optionSlug(option)}`);\n }\n\n /**\n * The option's part of an id or a test hook.\n *\n * `??` cannot fire here: `resolveOptionValue` returns '' for an empty option, not null, so\n * every valueless option produced the same slug — and two radios sharing an id break the\n * `for` that ties each label to its input.\n */\n optionSlug(option: DropdownOption): string {\n const raw = String(this.getOptVal(option) ?? '').trim();\n const text = raw || 'opt';\n return text.trim().replace(/\\s+/g, '_').toLowerCase();\n }\n\n getOptVal(option: DropdownOption): string | number | boolean {\n return resolveOptionValue(option, this.language);\n }\n\n getOptLabel(option: DropdownOption): string {\n return resolveOptionLabel(option, this.language);\n }\n\n /** Read-only display — synchronous, per §6.2. See `DropdownFieldComponent.getLabel`. */\n getSelectedLabel(): string {\n const value = this.control?.value;\n // `typeof null === 'object'`, so without this guard an empty value fell through to\n // `resolveLabel(null)` and rendered as blank — dropdown and multiSelect both show an em dash.\n if (value === null || value === undefined || value === '') return '—';\n const selected = this.options().find(o => valuesMatch(o, value, this.language));\n if (selected) return this.getOptLabel(selected);\n const cached = this.lookups.labelFor(this.field?.listName, value, this.language);\n if (cached) return cached;\n return typeof value === 'object' ? resolveLabel(value as Record<string, string>, this.language) : String(value ?? '—');\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, inject, signal, ChangeDetectionStrategy } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { DropdownOption, NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel, resolveOptionLabel, valuesMatch } from '@dynamic-entity/core';\nimport { LookupRegistryService, refreshChoiceOptions } from '../services/lookup-registry.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-multi-select-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--multiSelect\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n getLabels(control.value)\n }}</span>\n } @else {\n <select\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [compareWith]=\"compareFn\"\n [attr.disabled]=\"field.disabled ? true : null\"\n multiple\n size=\"4\"\n >\n @for (option of options(); track getOptLabel(option)) {\n @if (isObjectVal(option)) {\n <option [ngValue]=\"getOptStoredVal(option)\">{{ getOptLabel(option) }}</option>\n } @else {\n <option [value]=\"getOptStoredVal(option)\">{{ getOptLabel(option) }}</option>\n }\n }\n </select>\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class MultiSelectFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n private readonly lookups = inject(LookupRegistryService);\n\n private _field!: NestedFieldConfig;\n private _language = 'en';\n\n /** Setter-based so options resolve however the input is set — see `refreshChoiceOptions`. */\n @Input() set field(value: NestedFieldConfig) {\n this._field = value;\n refreshChoiceOptions(this, this.lookups);\n }\n get field(): NestedFieldConfig {\n return this._field;\n }\n\n @Input() set language(value: string) {\n this._language = value || 'en';\n refreshChoiceOptions(this, this.lookups);\n }\n get language(): string {\n return this._language;\n }\n\n @Input() control!: AbstractControl;\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n /** Inline `options`, or the field's named list resolved through the registry (§6.3). */\n readonly options = signal<DropdownOption[]>([]);\n\n readonly compareFn = (o1: unknown, o2: unknown): boolean => valuesMatch(o1, o2, this.language);\n\n isObjectVal(option: DropdownOption): boolean {\n return typeof option === 'object' && option !== null;\n }\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n /**\n * The value this option stores — the option object itself.\n *\n * Kept as a method rather than binding `option` straight into the template, because it is\n * the one place that says *why* the two are the same thing. It used to delegate to\n * `getOptionStoredValue`, an exported identity function whose two branches returned their\n * argument unchanged; naming a transformation that does not happen is worse than naming\n * nothing, because a reader has to go and check.\n */\n getOptStoredVal(option: DropdownOption): unknown {\n return option;\n }\n\n getOptLabel(option: DropdownOption): string {\n return resolveOptionLabel(option, this.language);\n }\n\n /** Read-only display — synchronous, per §6.2. See `DropdownFieldComponent.getLabel`. */\n getLabels(values: unknown): string {\n if (!Array.isArray(values) || !values.length) return '—';\n return values\n .map(v => {\n const opt = this.options().find(o => valuesMatch(o, v, this.language));\n if (opt) return this.getOptLabel(opt);\n const cached = this.lookups.labelFor(this.field?.listName, v, this.language);\n if (cached) return cached;\n return typeof v === 'object' && v !== null ? resolveLabel(v as Record<string, string>, this.language) : String(v);\n })\n .join(', ');\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport type { EntityReferenceLoader } from '@dynamic-entity/core';\nimport { ENTITY_REF_REGISTRY } from '../tokens/injection-tokens';\n\n/**\n * EntityRefRegistryService — resolves entity-ref option loader functions.\n * Entity-ref options come ONLY from this registry.\n * Never pass loaders via @Input() on field components.\n *\n * Consumers register loaders via provideNgxDynamicEntity({ entityRefs: { clients: () => [...] } }).\n * EntityRefFieldComponent injects this service and calls resolve(field.component ?? field.id).\n */\n@Injectable({ providedIn: 'root' })\nexport class EntityRefRegistryService {\n private readonly registry =\n inject(ENTITY_REF_REGISTRY, { optional: true }) ?? new Map<string, EntityReferenceLoader>();\n\n /**\n * Get the option loader for an entity key.\n * @returns The loader, or null if none is registered.\n */\n resolve(entityKey: string): EntityReferenceLoader | null {\n return this.registry.get(entityKey) ?? null;\n }\n\n has(entityKey: string): boolean {\n return this.registry.has(entityKey);\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport type {\n EntityReferenceLoader,\n RawReferenceItem,\n ReferenceLoaderContext,\n ReferenceLoaderResult,\n ReferenceOption,\n Subscribable,\n} from '@dynamic-entity/core';\nimport {\n buildReferenceCacheKey,\n entityKeyFromCacheKey,\n normalizeReferenceOptions,\n resolveLabel,\n valuesMatch,\n} from '@dynamic-entity/core';\nimport { ENTITY_REF_CACHE_STORE } from '../tokens/injection-tokens';\nimport { EntityRefRegistryService } from './entity-ref-registry.service';\n\n/** Label-cache field separator. Kept out of template literals so it stays visible in source. */\nconst LABEL_SEP = '|';\n\n/**\n * EntityReferenceService — the cache in front of consumer-registered option loaders.\n *\n * Three layers, matching the reference implementation:\n * 1. **options** — resolved `ReferenceOption[]` per (entity, lang, displayFields, filters).\n * 2. **in-flight** — the pending Promise, so N fields referencing one entity trigger one\n * load rather than N. This is the layer that actually removes duplicate HTTP calls;\n * an options cache alone does nothing for concurrent first loads.\n * 3. **labels** — synchronous value → text, for rendering a stored reference without\n * waiting on a load.\n *\n * Invalidation is per entity, not global. The reference could only `clearCache()` everything\n * (issue #16), so saving one record re-fetched every entity's options.\n */\n@Injectable({ providedIn: 'root' })\nexport class EntityReferenceService {\n private readonly registry = inject(EntityRefRegistryService);\n private readonly store = inject(ENTITY_REF_CACHE_STORE);\n\n /** Loads in progress, keyed the same way as the options cache. */\n private readonly inFlight = new Map<string, Promise<ReferenceOption[]>>();\n /** `entityKey|lang|canonicalValue` -> display text. */\n private readonly labels = new Map<string, string>();\n\n /**\n * Options for an entity, from cache when present.\n * Concurrent callers with the same key share one load.\n */\n async load(entityKey: string, ctx: ReferenceLoaderContext = {}): Promise<ReferenceOption[]> {\n const key = buildReferenceCacheKey(entityKey, {\n lang: ctx.lang,\n filters: ctx.filters,\n displayFields: ctx.displayFields,\n parentValue: ctx.parentValue,\n });\n\n const cached = this.store.get(key);\n if (cached) return cached;\n\n const pending = this.inFlight.get(key);\n if (pending) return pending;\n\n const loader = this.registry.resolve(entityKey);\n if (!loader) return [];\n\n const load = this.invoke(loader, ctx)\n .then(raw => {\n // displayFields drive label building, which is why they are part of the cache key.\n const options = normalizeReferenceOptions(\n raw as RawReferenceItem[],\n ctx.displayFields ? { enabled: true, displayFields: ctx.displayFields } : undefined,\n ctx.lang ?? 'en',\n );\n this.store.set(key, options);\n this.rememberLabels(entityKey, ctx.lang ?? 'en', options);\n return options;\n });\n\n // A failed load resolves to [] for the caller but is never written to the store, so a\n // transient error is retried on the next call instead of poisoning the cache. Only the\n // `.then` above caches, and a rejection skips it.\n const guarded = load\n .catch(() => [] as ReferenceOption[])\n .finally(() => this.inFlight.delete(key));\n\n this.inFlight.set(key, guarded);\n return guarded;\n }\n\n /** Cached options without triggering a load. `undefined` when not cached. */\n peek(entityKey: string, ctx: ReferenceLoaderContext = {}): ReferenceOption[] | undefined {\n return this.store.get(\n buildReferenceCacheKey(entityKey, {\n lang: ctx.lang,\n filters: ctx.filters,\n displayFields: ctx.displayFields,\n parentValue: ctx.parentValue,\n }),\n );\n }\n\n /**\n * Display text for a stored reference value, synchronously.\n * Returns `undefined` when the entity's options have never been loaded.\n */\n labelFor(entityKey: string, value: unknown, lang = 'en'): string | undefined {\n return this.labels.get(this.labelKey(entityKey, lang, value));\n }\n\n /** Drop everything cached for one entity, leaving other entities intact. */\n invalidate(entityKey: string): void {\n for (const key of this.store.keys()) {\n if (entityKeyFromCacheKey(key) === entityKey) this.store.delete(key);\n }\n for (const key of [...this.inFlight.keys()]) {\n if (entityKeyFromCacheKey(key) === entityKey) this.inFlight.delete(key);\n }\n const prefix = `${entityKey}${LABEL_SEP}`;\n for (const key of [...this.labels.keys()]) {\n if (key.startsWith(prefix)) this.labels.delete(key);\n }\n }\n\n clear(): void {\n this.store.clear();\n this.inFlight.clear();\n this.labels.clear();\n }\n\n private rememberLabels(entityKey: string, lang: string, options: ReferenceOption[]): void {\n for (const option of options) {\n this.labels.set(this.labelKey(entityKey, lang, option.value), option.label);\n }\n }\n\n /** Label-cache key. An object value collapses to its resolved text for the active language. */\n private labelKey(entityKey: string, lang: string, value: unknown): string {\n const canonical =\n value !== null && typeof value === 'object'\n ? resolveLabel(value as Record<string, string>, lang)\n : String(value ?? '');\n return [entityKey, lang, canonical].join(LABEL_SEP);\n }\n\n // ─── Loader result coercion (array | Promise | Observable) ──────────────────\n\n private invoke(\n loader: EntityReferenceLoader,\n ctx: ReferenceLoaderContext,\n ): Promise<ReferenceOption[]> {\n let result: ReferenceLoaderResult;\n try {\n result = loader(ctx);\n } catch (err) {\n // Reject rather than resolve empty: `load` must be able to tell failure from\n // \"no matches\", or it would cache the failure.\n return Promise.reject(err);\n }\n return this.toPromise(result);\n }\n\n private toPromise(result: ReferenceLoaderResult): Promise<ReferenceOption[]> {\n if (Array.isArray(result)) return Promise.resolve(result);\n if (this.isSubscribable(result)) {\n // First emission wins, so an Observable that stays open still resolves the load.\n return new Promise<ReferenceOption[]>((resolve, reject) => {\n let settled = false;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n fn();\n };\n result.subscribe({\n next: value => settle(() => resolve(value ?? [])),\n // An erroring stream is a failed load, not an empty one — see `invoke`.\n error: err => settle(() => reject(err)),\n // Completing without emitting is a legitimate empty result, and is cached.\n complete: () => settle(() => resolve([])),\n });\n });\n }\n return Promise.resolve(result as Promise<ReferenceOption[]>);\n }\n\n private isSubscribable(value: unknown): value is Subscribable<ReferenceOption[]> {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Subscribable<ReferenceOption[]>).subscribe === 'function'\n );\n }\n\n /** Exposed for cascade filtering, which matches a parent value against option values. */\n matches(a: unknown, b: unknown, lang = 'en'): boolean {\n return valuesMatch(a, b, lang);\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport type {\n EntityFormConfig,\n NestedFieldConfig,\n NestedTabConfig,\n ReferenceLoaderContext,\n ReferenceOption,\n} from '@dynamic-entity/core';\nimport { applyCascadeFilter } from '@dynamic-entity/core';\nimport { EntityRefRegistryService } from './entity-ref-registry.service';\nimport { EntityReferenceService } from './entity-reference.service';\n\n/**\n * CascadeDataService — loads entity-reference options and applies parent→child cascades.\n *\n * Loaders come from the registry only. This service owns the three things a\n * field component should not: resolving the loader, coercing whatever it returned\n * (array | Promise | Observable) into a Promise, and filtering by the parent's value.\n */\n@Injectable({ providedIn: 'root' })\nexport class CascadeDataService {\n private readonly registry = inject(EntityRefRegistryService);\n private readonly references = inject(EntityReferenceService);\n\n /** Preload runs by formConfigId, so a second call joins the first rather than re-fetching. */\n private readonly preloads = new Map<string, Promise<void>>();\n\n /** Registry key for a field: explicit `linkedEntityKey`, else the field id. */\n entityKeyFor(field: NestedFieldConfig): string {\n return field.entityReference?.linkedEntityKey ?? field.id;\n }\n\n /** Whether a loader is registered for this field. */\n canLoad(field: NestedFieldConfig): boolean {\n return this.registry.has(this.entityKeyFor(field));\n }\n\n /**\n * Load the options for a field, cascade-filtered against `parentValue`.\n * Returns `[]` when no loader is registered, or when a cascade child has no parent value yet.\n */\n async load(\n field: NestedFieldConfig,\n ctx: ReferenceLoaderContext = {},\n ): Promise<ReferenceOption[]> {\n const cfg = field.entityReference;\n if (!this.canLoad(field)) return [];\n\n // A cascade child with no parent selection must offer nothing.\n const hasParentValue =\n ctx.parentValue !== null && ctx.parentValue !== undefined && ctx.parentValue !== '';\n if (cfg?.parentField && !hasParentValue) return [];\n\n const lang = ctx.lang ?? 'en';\n\n // When the cascade can be resolved locally (`lookupFilter`/`lookupPath`), fetch the\n // unfiltered set once and filter per parent below — switching parent then costs nothing.\n // Otherwise the loader is the only thing that can narrow the list, so `parentValue` is\n // passed through and becomes part of the cache identity (one entry per parent).\n const filtersLocally = !!(cfg?.lookupFilter || cfg?.lookupPath);\n\n const options = await this.references.load(this.entityKeyFor(field), {\n ...ctx,\n parentValue: filtersLocally ? undefined : ctx.parentValue,\n filters: { ...(cfg?.filters ?? {}), ...(ctx.filters ?? {}) },\n displayFields: cfg?.displayFields,\n lang,\n });\n\n return applyCascadeFilter(options, ctx.parentValue, cfg, lang);\n }\n\n // ─── Preload ────────────────────────────────────────────────────────────────\n\n /**\n * Warm the cache for every entity a config's cascades depend on, so changing a parent\n * resolves from memory instead of a round-trip.\n *\n * Idempotent per `formConfigId`: calling it again returns the in-flight or completed run\n * rather than re-fetching.\n */\n initializeCascadeData(formConfigId: string, config: EntityFormConfig, lang = 'en'): Promise<void> {\n const existing = this.preloads.get(formConfigId);\n if (existing) return existing;\n\n const fields = this.cascadeFields(config);\n const run = Promise.all(\n fields.map(field =>\n this.references.load(this.entityKeyFor(field), {\n filters: field.entityReference?.filters,\n displayFields: field.entityReference?.displayFields,\n lang,\n }),\n ),\n ).then(() => undefined);\n\n this.preloads.set(formConfigId, run);\n return run;\n }\n\n /** Resolves true once `initializeCascadeData` for this config has finished. */\n async waitForData(formConfigId: string): Promise<boolean> {\n const run = this.preloads.get(formConfigId);\n if (!run) return false;\n await run;\n return true;\n }\n\n /**\n * Child options for a parent selection, from cache only — no load is triggered.\n * Returns `[]` when the entity has not been preloaded.\n */\n getCachedChildOptions(\n field: NestedFieldConfig,\n parentValue: unknown,\n lang = 'en',\n ): ReferenceOption[] {\n const cfg = field.entityReference;\n const cached = this.references.peek(this.entityKeyFor(field), {\n filters: cfg?.filters,\n displayFields: cfg?.displayFields,\n lang,\n });\n if (!cached) return [];\n return applyCascadeFilter(cached, parentValue, cfg, lang);\n }\n\n /** Forget the preload for one config. The option cache itself is untouched. */\n clearCache(formConfigId: string): void {\n this.preloads.delete(formConfigId);\n }\n\n /** Every entity-ref field in the config that participates in a cascade. */\n private cascadeFields(config: EntityFormConfig): NestedFieldConfig[] {\n const found: NestedFieldConfig[] = [];\n const walkFields = (fields: NestedFieldConfig[] | undefined) => {\n for (const field of fields ?? []) {\n const cfg = field.entityReference;\n if (cfg?.enabled && (cfg.parentField || cfg.lookupPath || cfg.lookupFilter)) {\n found.push(field);\n }\n walkFields(field.children);\n }\n };\n const walkTabs = (tabs: NestedTabConfig[] | undefined) => {\n for (const tab of tabs ?? []) {\n walkFields(tab.fields);\n walkTabs(tab.children);\n }\n };\n walkTabs(config?.tabs);\n return found;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport type { ReferenceOption } from '@dynamic-entity/core';\n\nexport interface EntityRefSelection {\n fieldId: string;\n /** The chosen option, or `null` when the selection was cleared. */\n option: ReferenceOption | null;\n}\n\n/**\n * EntityRefSelectionService — the channel an entity-ref field uses to publish *which record*\n * the user picked, so the owning form can run `autoPatch` against it.\n *\n * The control value alone is not enough: `autoPatch` copies fields out of the selected\n * record, which only the field component has after loading its options.\n *\n * Provided at `DynamicFormComponent` level so each form instance gets its own channel;\n * the `root` fallback keeps standalone field components injectable in isolation.\n */\n@Injectable({ providedIn: 'root' })\nexport class EntityRefSelectionService {\n private readonly subject = new Subject<EntityRefSelection>();\n\n readonly selection$ = this.subject.asObservable();\n\n emit(fieldId: string, option: ReferenceOption | null): void {\n this.subject.next({ fieldId, option });\n }\n}\n","import { Component, DestroyRef, Input, OnInit, inject, signal, ChangeDetectionStrategy } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig, ReferenceOption } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { CascadeDataService } from '../services/cascade-data.service';\nimport { EntityRefSelectionService } from '../services/entity-ref-selection.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/**\n * EntityRefFieldComponent — a select populated from a consumer-registered loader.\n *\n * Cascades: when `entityReference.parentField` is set, the component watches that sibling\n * control (via `control.parent`) and reloads its own options on every parent change,\n * clearing a now-invalid selection. It publishes the picked record on\n * `EntityRefSelectionService` so the owning form can run `autoPatch`.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-entity-ref-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--entity-ref\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n getLabel(control.value)\n }}</span>\n } @else {\n @if (loading()) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-loading'\" role=\"status\">{{\n ui.text('loading', language)\n }}</span>\n } @else {\n <select\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [id]=\"domId()\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.disabled]=\"field.disabled ? true : null\"\n >\n <option value=\"\">{{ placeholder || ui.text('selectPlaceholder', language) }}</option>\n @for (option of options(); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </select>\n @if (awaitingParent()) {\n <span class=\"ngx-field__hint\" [attr.data-testid]=\"'field-' + field.id + '-hint'\">{{\n ui.text('selectParentFirst', language, { field: parentFieldId ?? '' })\n }}</span>\n }\n }\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class EntityRefFieldComponent implements OnInit {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n private readonly cascade = inject(CascadeDataService);\n private readonly selectionBus = inject(EntityRefSelectionService);\n private readonly destroyRef = inject(DestroyRef);\n\n readonly options = signal<ReferenceOption[]>([]);\n readonly loading = signal(false);\n /** True when this field cascades but its parent has no value yet. */\n readonly awaitingParent = signal(false);\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n get parentFieldId(): string | undefined {\n return this.field?.entityReference?.parentField;\n }\n\n ngOnInit(): void {\n if (this.masked) return;\n void this.reload();\n this.watchParent();\n this.control?.valueChanges\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(value => this.publishSelection(String(value ?? '')));\n }\n\n /** Reload options against the parent's current value. */\n async reload(): Promise<void> {\n const parentValue = this.parentValue();\n this.awaitingParent.set(\n !!this.parentFieldId && (parentValue === null || parentValue === undefined || parentValue === ''),\n );\n\n if (!this.cascade.canLoad(this.field)) {\n this.options.set([]);\n return;\n }\n\n this.loading.set(true);\n try {\n this.options.set(await this.cascade.load(this.field, { parentValue, lang: this.language }));\n } finally {\n this.loading.set(false);\n }\n }\n\n /**\n * Publish the selected option so autoPatch can copy from its record.\n *\n * Driven from `valueChanges` rather than the select's `change` event: that event is the\n * same one the `formControl` directive listens to, so reading the control inside a\n * template `(change)` handler can see the previous value. `valueChanges` fires after the\n * model has updated — including Playwright `selectOption`, which updates the control\n * through the value accessor.\n */\n onSelectionChange(value?: string): void {\n this.publishSelection(value ?? String(this.control?.value ?? ''));\n }\n\n private publishSelection(current: string): void {\n const selected = this.options().find(o => String(o.value) === current);\n this.selectionBus.emit(this.field.id, selected ?? null);\n }\n\n getLabel(value: any): string {\n const option = this.options().find(o => String(o.value) === String(value));\n return option?.label ?? value ?? '—';\n }\n\n private parentValue(): unknown {\n const parentId = this.parentFieldId;\n if (!parentId) return undefined;\n return this.control?.parent?.get(parentId)?.value;\n }\n\n /** Reload (and drop a stale selection) whenever the parent control changes. */\n private watchParent(): void {\n const parentId = this.parentFieldId;\n if (!parentId) return;\n const parentControl = this.control?.parent?.get(parentId);\n if (!parentControl) return;\n\n parentControl.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {\n if (this.control.value) {\n this.control.setValue('', { emitEvent: false });\n this.selectionBus.emit(this.field.id, null);\n }\n void this.reload();\n });\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Injectable, Type, inject } from '@angular/core';\nimport { FIELD_TYPE_REGISTRY, FIELD_TYPE_SETS } from '../tokens/injection-tokens';\n\n/**\n * FieldRegistryService — resolves field type strings to Angular component classes.\n *\n * **Tree-shaking contract:** this service holds *no* static imports of field components.\n * Nothing is bundled until something registers it, which is what makes the built-ins\n * opt-in. Register them with `provideBuiltInFieldTypes()` (all 21 keys) or a narrower\n * subset via `provideFieldTypes({ ... })` — see `providers/provide-field-types.ts`.\n *\n * Resolution order: consumer token registry → runtime registrations → nothing.\n */\n@Injectable({ providedIn: 'root' })\nexport class FieldRegistryService {\n private readonly consumerRegistry =\n inject(FIELD_TYPE_REGISTRY, { optional: true }) ?? new Map<string, Type<any>>();\n private readonly dynamicRegistry = new Map<string, Type<any>>();\n\n constructor() {\n // Sets contributed by provideFieldTypes()/provideBuiltInFieldTypes(), in declaration order.\n for (const set of inject(FIELD_TYPE_SETS, { optional: true }) ?? []) {\n this.registerAll(set);\n }\n }\n\n /** Register a field type component mapping at runtime. */\n register(type: string, component: Type<any>): void {\n this.dynamicRegistry.set(type, component);\n }\n\n /** Register multiple field type component mappings at runtime. */\n registerAll(map: Record<string, Type<any>>): void {\n for (const [type, comp] of Object.entries(map)) {\n this.dynamicRegistry.set(type, comp);\n }\n }\n\n /**\n * Resolve a field type string to a component class.\n * Consumer token registry takes priority over runtime registrations.\n */\n resolve(fieldType: string): Type<any> | null {\n return this.consumerRegistry.get(fieldType) ?? this.dynamicRegistry.get(fieldType) ?? null;\n }\n\n /** Check if a field type has a registered component. */\n has(fieldType: string): boolean {\n return this.consumerRegistry.has(fieldType) || this.dynamicRegistry.has(fieldType);\n }\n\n /** Every registered field type key. Consumer overrides and runtime registrations combined. */\n registeredTypes(): string[] {\n return [...new Set([...this.dynamicRegistry.keys(), ...this.consumerRegistry.keys()])].sort();\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport type { EntityFormConfig, NestedFieldConfig, NestedTabConfig } from '@dynamic-entity/core';\nimport { shouldMaskField as coreShouldMaskField, resolveEffectiveMask as coreResolveEffectiveMask } from '@dynamic-entity/core';\nimport { MASKED_ROLES } from '../tokens/injection-tokens';\n\n/**\n * RbacService — ALL permission checks and masking logic live here.\n */\n@Injectable({ providedIn: 'root' })\nexport class RbacService {\n private readonly maskedRoles = inject(MASKED_ROLES, { optional: true }) ?? [];\n\n /**\n * Check if any of the user's roles satisfy the required roles.\n * hasPermission(roles, undefined) → true (no restriction).\n */\n hasPermission(userRoles: string[], requiredRoles?: string[]): boolean {\n if (!requiredRoles?.length) return true;\n return userRoles.some(r => requiredRoles.includes(r));\n }\n\n /** 3-level OR resolution */\n resolveEffectiveMask(formMask?: boolean, tabMask?: boolean, fieldMask?: boolean): boolean {\n return coreResolveEffectiveMask(formMask, tabMask, fieldMask);\n }\n\n /** Check if the user's roles include any masked role */\n isUserMaskedRole(userRoles: string[]): boolean {\n return this.maskedRoles.some(r => userRoles.includes(r));\n }\n\n /** Determine if a specific field should be masked for this user */\n shouldMaskField(field: NestedFieldConfig, tab: NestedTabConfig | undefined, config: EntityFormConfig, userRoles: string[]): boolean {\n return coreShouldMaskField(field, tab, config, userRoles, this.maskedRoles);\n }\n\n /** Get view/edit/delete permissions for a config */\n getPermissions(config: EntityFormConfig, userRoles: string[]) {\n return {\n canView: this.hasPermission(userRoles, config.permissions?.view),\n canEdit: this.hasPermission(userRoles, config.permissions?.edit),\n canDelete: this.hasPermission(userRoles, config.permissions?.delete),\n };\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ComponentRef,\n Injector,\n Input,\n OnChanges, OnDestroy,\n SimpleChanges,\n ViewChild,\n ViewContainerRef,\n inject,\n isDevMode,\n} from '@angular/core';\nimport { AbstractControl } from '@angular/forms';\nimport { Subscription } from 'rxjs';\nimport type { NestedFieldConfig, EntityFormConfig, NestedTabConfig } from '@dynamic-entity/core';\nimport { findTab } from '@dynamic-entity/core';\nimport { FieldRegistryService } from '../../services/field-registry.service';\nimport { RbacService } from '../../services/rbac.service';\n\n/**\n * DynamicFieldComponent — mounts the correct field component for a given NestedFieldConfig.\n * Uses ViewContainerRef.createComponent() and passes inputs via setInput(); see\n * DynamicFieldComponentContract for the five inputs every field component receives.\n * Never add field-type-specific logic here — this component must remain generic.\n *\n * The 5 inputs (field, control, language, readonly, masked) are passed to every mounted\n * component uniformly — no special-casing per type.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-dynamic-field',\n standalone: true,\n template: `<ng-container #fieldHost></ng-container>`,\n})\nexport class DynamicFieldComponent implements OnChanges, OnDestroy {\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() config!: EntityFormConfig;\n @Input() currentTabId?: string;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() userRoles: string[] = [];\n\n @ViewChild('fieldHost', { read: ViewContainerRef, static: true })\n private readonly fieldHost!: ViewContainerRef;\n\n private readonly fieldRegistry = inject(FieldRegistryService);\n private readonly rbacService = inject(RbacService);\n /**\n * Passed into `createComponent` so a hosted field sees this host's injector — including\n * `DynamicFormComponent`'s scoped `EntityRefSelectionService`. Without it, a standalone\n * field resolves the root bus and `autoPatch` never runs.\n */\n private readonly injector = inject(Injector);\n\n private componentRef: ComponentRef<unknown> | null = null;\n\n ngOnChanges(_changes: SimpleChanges): void {\n this.mountField();\n }\n\n private mountField(): void {\n if (!this.field || !this.control) return;\n\n const ComponentClass = this.fieldRegistry.resolve(this.field.type);\n if (!ComponentClass) {\n this.warnUnresolved(this.field.type);\n return; // Unknown field type — render nothing\n }\n\n // Determine masking for this specific field\n const tab: NestedTabConfig | null = this.currentTabId ? findTab(this.config?.tabs, this.currentTabId) : null;\n const masked = this.rbacService.shouldMaskField(this.field, tab ?? undefined, this.config, this.userRoles);\n\n // Re-use existing component if same type, otherwise recreate\n if (this.componentRef && this.componentRef.instance instanceof ComponentClass) {\n this.setInputs(this.componentRef, masked);\n return;\n }\n\n this.fieldHost.clear();\n this.componentRef = this.fieldHost.createComponent(ComponentClass, {\n injector: this.injector,\n });\n this.setInputs(this.componentRef, masked);\n this.watchControl();\n this.componentRef.changeDetectorRef.detectChanges();\n }\n\n /**\n * Field types are opt-in (see `provideFieldTypes` / `provideBuiltInFieldTypes`), so an\n * unregistered type renders nothing. Say so once per type in dev builds rather than\n * leaving a silently blank slot.\n */\n private warnUnresolved(type: string): void {\n if (!isDevMode() || DynamicFieldComponent.warnedTypes.has(type)) return;\n DynamicFieldComponent.warnedTypes.add(type);\n console.warn(\n `[ngx-dynamic-entity] No component registered for field type \"${type}\" — the field was not rendered. ` +\n `Register it with provideFieldTypes({ '${type}': MyComponent }) or provideBuiltInFieldTypes().`,\n );\n }\n\n private static readonly warnedTypes = new Set<string>();\n\n /**\n * Re-check the hosted field component.\n *\n * The field components are OnPush, so they re-render on an input change, an event from\n * their own template, or a signal they read. `form.markAllAsTouched()` is none of those —\n * it flips `touched` from outside, and every field's error message depends on it. Without\n * this, a blocked submit would mark the form touched and no error would appear.\n */\n refresh(): void {\n this.componentRef?.changeDetectorRef.detectChanges();\n }\n\n /**\n * Re-check the hosted component whenever its control changes from outside.\n *\n * The field components are OnPush, so they re-render on an input change or an event from\n * their own template. A control mutated externally is neither — and that is not an edge\n * case: patchForm, reset, autoPatch and patchOnTrue all do exactly that. Without this, a\n * field patched from a record would keep rendering its previous value.\n *\n * `detectChanges()` rather than `markForCheck()`: a selection that arrives from a native\n * `change` event (or Playwright) may not be followed by another Angular tick, so a dirty\n * flag would never be flushed. Running CD on the hosted component now is the copy showing up.\n *\n * Done here rather than in each of the eighteen field components: the host owns the\n * component reference, so one subscription covers every type including custom ones.\n */\n private watchControl(): void {\n this.controlSub?.unsubscribe();\n if (!this.control) return;\n\n this.controlSub = this.control.valueChanges.subscribe(() => this.refresh());\n }\n\n private controlSub?: Subscription;\n\n ngOnDestroy(): void {\n this.controlSub?.unsubscribe();\n }\n\n /**\n * Pass all 5 contract inputs via ComponentRef.setInput() — uniform for all types.\n * The public shape is DynamicFieldComponentContract.\n * Must use setInput(), not property assignment: the field components declare inputs with\n * definite assignment and no initializer, and the lib compiles with\n * useDefineForClassFields:false, so `'field' in instance` is false until first set.\n */\n private setInputs(ref: ComponentRef<unknown>, masked: boolean): void {\n ref.setInput('field', this.field);\n ref.setInput('control', this.control);\n ref.setInput('language', this.language);\n ref.setInput('readonly', this.readonly || !!this.field.readonly);\n ref.setInput('masked', masked);\n }\n}\n","import { Component, Input, forwardRef, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig, EntityFormConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { DynamicFieldComponent } from '../form/dynamic-field/dynamic-field.component';\n\n/** Renders a nested fieldset container for a group field's children. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-group-field',\n standalone: true,\n imports: [ReactiveFormsModule, forwardRef(() => DynamicFieldComponent)],\n template: `\n <fieldset\n class=\"ngx-field ngx-field--group\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <legend class=\"ngx-field__legend\">\n {{ label }}\n @if (hint) {\n <!-- A group's hint describes the whole section, so it hangs off the section's name. -->\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span class=\"ngx-field__hint\" role=\"tooltip\" [attr.data-testid]=\"'field-' + field.id + '-hint'\">{{ hint }}</span>\n </span>\n }\n </legend>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else {\n <div class=\"ngx-field__group-children\">\n @for (child of field.children ?? []; track child.id) {\n @if (child.visibility !== false) {\n <ngx-dynamic-field\n [field]=\"child\"\n [control]=\"getChildControl(child.id)\"\n [config]=\"config\"\n [language]=\"language\"\n [readonly]=\"readonly || !!child.readonly\"\n [userRoles]=\"userRoles\"\n />\n }\n }\n </div>\n }\n </fieldset>\n `,\n styles: [\n `\n .ngx-field--group {\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n padding: 16px;\n margin-bottom: 16px;\n background: #fafafa;\n }\n .ngx-field__legend {\n font-weight: 600;\n font-size: 14px;\n padding: 0 8px;\n color: #334155;\n }\n .ngx-field__group-children {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n `,\n ],\n})\nexport class GroupFieldComponent {\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() config!: EntityFormConfig;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n @Input() userRoles: string[] = [];\n\n /** Author help text for the section as a whole. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n getChildControl(childId: string): AbstractControl {\n const group = this.control as FormGroup;\n return group?.get(childId) as AbstractControl;\n }\n}\n","import { Injectable, inject, isDevMode } from '@angular/core';\nimport { AsyncValidatorFn, ValidatorFn, Validators } from '@angular/forms';\nimport type { FieldValidators } from '@dynamic-entity/core';\nimport { ASYNC_VALIDATOR_REGISTRY, VALIDATOR_REGISTRY } from '../tokens/injection-tokens';\n\n/**\n * ValidatorRegistryService — resolves validator configs / key strings to Angular ValidatorFns.\n */\n@Injectable({ providedIn: 'root' })\nexport class ValidatorRegistryService {\n private readonly consumerRegistry = inject(VALIDATOR_REGISTRY, { optional: true }) ?? new Map();\n private readonly asyncRegistry = inject(ASYNC_VALIDATOR_REGISTRY, { optional: true }) ?? new Map();\n\n /**\n * Resolve a validator key string to a ValidatorFn.\n * Supports parameterized built-ins like 'min:0', 'maxLength:255'.\n */\n resolve(validatorKey: string): ValidatorFn | null {\n if (this.consumerRegistry.has(validatorKey)) {\n return this.consumerRegistry.get(validatorKey);\n }\n\n if (validatorKey === 'required') return Validators.required;\n if (validatorKey === 'email') return Validators.email;\n\n const [name, param] = validatorKey.split(':');\n const value = parseFloat(param);\n\n if (name === 'min' && !isNaN(value)) return Validators.min(value);\n if (name === 'max' && !isNaN(value)) return Validators.max(value);\n if (name === 'minLength' && !isNaN(value)) return Validators.minLength(value);\n if (name === 'maxLength' && !isNaN(value)) return Validators.maxLength(value);\n\n return null;\n }\n\n /** Resolve multiple validator keys into a ValidatorFn[] */\n resolveAll(validatorKeys: string[] = []): ValidatorFn[] {\n return validatorKeys.map(k => this.resolve(k)).filter((v): v is ValidatorFn => v !== null);\n }\n\n /** Resolve a FieldValidators object or string[] into ValidatorFn[] */\n resolveFromConfig(config?: FieldValidators | string[]): ValidatorFn[] {\n if (!config) return [];\n if (Array.isArray(config)) return this.resolveAll(config);\n\n const fnList: ValidatorFn[] = [];\n if (config.required) fnList.push(Validators.required);\n if (config.min !== undefined) fnList.push(Validators.min(config.min));\n if (config.max !== undefined) fnList.push(Validators.max(config.max));\n if (config.minLength !== undefined) fnList.push(Validators.minLength(config.minLength));\n if (config.maxLength !== undefined) fnList.push(Validators.maxLength(config.maxLength));\n if (config.pattern) {\n // `Validators.pattern` compiles the string, so an unparseable one threw here — during\n // control construction, which takes the whole form down rather than one field's format\n // check. `validateConfig` reports it as an error; at runtime the field degrades to no\n // pattern validation, which is exactly what the server-side import path already does.\n try {\n fnList.push(Validators.pattern(config.pattern));\n } catch (err) {\n this.warnOnce(\n `pattern:${config.pattern}`,\n `The pattern \"${config.pattern}\" is not a valid regular expression ` +\n `(${err instanceof Error ? err.message : String(err)}), so no format check is ` +\n `applied to this field. Run \"dynamic-entity validate\" over the config to find it.`,\n );\n }\n }\n if (config.email) fnList.push(Validators.email);\n\n // Named validators from the consumer registry. This branch previously hardcoded the\n // built-ins and consulted the registry only for the `string[]` form of this config, so\n // a validator the consumer had registered could not be named from a typed schema\n // without casting it to `any`.\n for (const key of config.custom ?? []) {\n const fn = this.resolve(key);\n if (fn) fnList.push(fn);\n else this.warnUnresolved('custom', key);\n }\n\n return fnList;\n }\n\n /**\n * Resolve the async validators a field names, in `validators.customAsync`.\n *\n * Async validators are deliberately a separate registry and a separate config key: Angular\n * attaches them through `setAsyncValidators`, runs them only once the synchronous ones\n * pass, and holds the control in `pending` until they settle. Mixing them into the\n * synchronous list would silently never run them.\n *\n * An unknown name is skipped rather than throwing, matching the synchronous behaviour.\n */\n resolveAsyncFromConfig(config?: FieldValidators | string[]): AsyncValidatorFn[] {\n if (!config || Array.isArray(config)) return [];\n\n const out: AsyncValidatorFn[] = [];\n for (const key of config.customAsync ?? []) {\n const fn = this.asyncRegistry.get(key);\n if (fn) out.push(fn);\n else this.warnUnresolved('customAsync', key);\n }\n return out;\n }\n\n /**\n * Say when a named validator resolved to nothing.\n *\n * It used to be dropped in silence, which is the worst failure mode this library has: the\n * schema says the field is checked, the field is not checked, the form saves, and nothing\n * anywhere said so. For `customAsync` that is typically a uniqueness check, so the duplicate\n * lands in the database.\n *\n * Dev only, once per name — this runs while controls are built, which happens on every\n * config change. `validateConfig` with `knownValidators` is the build-time version of the\n * same check, and it fails CI rather than a console.\n */\n private warnUnresolved(kind: 'custom' | 'customAsync', key: string): void {\n this.warnOnce(\n `${kind}:${key}`,\n `No validator named \"${key}\" is registered, so validators.${kind} drops it and it never ` +\n `runs. Register it with provideNgxDynamicEntity({ ${\n kind === 'customAsync' ? 'asyncValidators' : 'validators'\n }: { '${key}': ... } }).`,\n );\n }\n\n /** Per service instance, which is per injector — so a test gets a clean slate. */\n private readonly warned = new Set<string>();\n\n private warnOnce(id: string, message: string): void {\n if (!isDevMode() || this.warned.has(id)) return;\n this.warned.add(id);\n console.warn(`[ngx-dynamic-entity] ${message}`);\n }\n}\n","import { Component, Input, inject, forwardRef, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';\nimport { AbstractControl, FormArray, FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig, EntityFormConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { DynamicFieldComponent } from '../form/dynamic-field/dynamic-field.component';\nimport { ValidatorRegistryService } from '../services/validator-registry.service';\nimport { UiTextService } from '../services/ui-text.service';\n\n/** Renders repeating rows for a FormArray, with Add Item and Remove. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-array-field',\n standalone: true,\n imports: [ReactiveFormsModule, forwardRef(() => DynamicFieldComponent)],\n template: `\n <div\n class=\"ngx-field ngx-field--array\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__array-header\">\n <label class=\"ngx-field__label\">\n {{ label }}\n @if (hint) {\n <!-- Explains the set of rows, so it hangs off their name rather than any one row. -->\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span class=\"ngx-field__hint\" role=\"tooltip\" [attr.data-testid]=\"'field-' + field.id + '-hint'\">{{\n hint\n }}</span>\n </span>\n }\n </label>\n @if (!readonly && !masked) {\n <button\n type=\"button\"\n class=\"ngx-field__array-add-btn\"\n [attr.data-testid]=\"'field-' + field.id + '-add'\"\n (click)=\"addItem()\"\n >\n {{ ui.text('addItem', language) }}\n </button>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else {\n <div class=\"ngx-field__array-list\">\n @for (itemGroup of formArray.controls; track idx; let idx = $index) {\n <div class=\"ngx-field__array-item\" [attr.data-testid]=\"'field-' + field.id + '-row'\">\n <div class=\"ngx-field__array-item-header\">\n <span class=\"ngx-field__array-item-title\">{{ ui.text('itemNumber', language, { number: idx + 1 }) }}</span>\n @if (!readonly) {\n <button\n type=\"button\"\n class=\"ngx-field__array-remove-btn\"\n [attr.data-testid]=\"'field-' + field.id + '-remove-' + idx\"\n (click)=\"removeItem(idx)\"\n >\n {{ ui.text('remove', language) }}\n </button>\n }\n </div>\n <div class=\"ngx-field__array-item-fields\">\n @for (child of field.children ?? []; track child.id) {\n @if (child.visibility !== false) {\n <ngx-dynamic-field\n [field]=\"child\"\n [control]=\"getItemChildControl(itemGroup, child.id)\"\n [config]=\"config\"\n [language]=\"language\"\n [readonly]=\"readonly || !!child.readonly\"\n [userRoles]=\"userRoles\"\n />\n }\n }\n </div>\n </div>\n }\n @if (formArray.controls.length === 0) {\n <div class=\"ngx-field__array-empty\" [attr.data-testid]=\"'field-' + field.id + '-empty'\">\n {{ ui.text('noItems', language) }}\n </div>\n }\n </div>\n }\n </div>\n `,\n styles: [\n `\n .ngx-field--array {\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n padding: 16px;\n margin-bottom: 16px;\n background: #f8fafc;\n }\n .ngx-field__array-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 12px;\n }\n .ngx-field__array-add-btn {\n background: #2563eb;\n color: #fff;\n border: none;\n padding: 6px 12px;\n border-radius: 4px;\n font-weight: 500;\n cursor: pointer;\n }\n .ngx-field__array-add-btn:hover {\n background: #1d4ed8;\n }\n .ngx-field__array-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n .ngx-field__array-item {\n background: #fff;\n border: 1px solid #cbd5e1;\n border-radius: 6px;\n padding: 12px;\n }\n .ngx-field__array-item-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n border-bottom: 1px solid #f1f5f9;\n padding-bottom: 6px;\n }\n .ngx-field__array-item-title {\n font-weight: 600;\n font-size: 13px;\n color: #475569;\n }\n .ngx-field__array-remove-btn {\n background: #ef4444;\n color: #fff;\n border: none;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 12px;\n cursor: pointer;\n }\n .ngx-field__array-empty {\n color: #94a3b8;\n font-style: italic;\n font-size: 13px;\n }\n `,\n ],\n})\nexport class ArrayFieldComponent {\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n /**\n * addItem/removeItem are public and may be called from outside this component's template,\n * which under OnPush would not re-render. The host also watches the control, but this\n * keeps the component correct on its own.\n */\n private readonly cdr = inject(ChangeDetectorRef);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() config!: EntityFormConfig;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n @Input() userRoles: string[] = [];\n\n private readonly fb = inject(FormBuilder);\n private readonly validatorRegistry = inject(ValidatorRegistryService);\n\n /** Author help text for the section as a whole. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get formArray(): FormArray {\n return this.control as FormArray;\n }\n\n getItemChildControl(itemGroup: AbstractControl, childId: string): AbstractControl {\n return (itemGroup as FormGroup).get(childId) as AbstractControl;\n }\n\n addItem(): void {\n const controls: Record<string, any> = {};\n for (const child of this.field.children ?? []) {\n const validators = this.validatorRegistry.resolveFromConfig(child.validators);\n controls[child.id] = [child.defaultValue ?? null, validators];\n }\n const group = this.fb.group(controls);\n this.formArray.push(group);\n this.cdr.markForCheck();\n }\n\n removeItem(index: number): void {\n this.formArray.removeAt(index);\n this.cdr.markForCheck();\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport type { FileRef, Subscribable, UploadResult } from '@dynamic-entity/core';\nimport { UPLOAD_HANDLER } from '../tokens/injection-tokens';\n\n/**\n * FileUploadService — the single place image-field and file-field agree on how a\n * selected `File` becomes a `FileRef`.\n *\n * With `UPLOAD_HANDLER` registered the file is persisted and stored as `{ url }`;\n * without one it is stored as `{ file }` for the consumer to upload at submit time.\n */\n@Injectable({ providedIn: 'root' })\nexport class FileUploadService {\n private readonly handler = inject(UPLOAD_HANDLER, { optional: true });\n\n get hasHandler(): boolean {\n return !!this.handler;\n }\n\n /** Metadata common to both persisted and unpersisted refs. */\n private describe(file: File): FileRef {\n return { name: file.name, size: file.size, mimeType: file.type };\n }\n\n /**\n * Turn a selected File into the value to store on the control.\n * @throws when a registered handler rejects — callers surface it as a field error.\n */\n async toFileRef(file: File): Promise<FileRef> {\n const meta = this.describe(file);\n if (!this.handler) return { ...meta, file };\n\n const result = await this.normalize(this.handler(file));\n return { ...meta, url: result.url, name: result.name ?? meta.name };\n }\n\n /** Object URL for previewing an unpersisted File. Callers must revoke it. */\n previewUrlFor(ref: FileRef | null | undefined): string | null {\n if (!ref) return null;\n if (ref.url) return ref.url;\n if (ref.file && typeof URL !== 'undefined' && typeof URL.createObjectURL === 'function') {\n return URL.createObjectURL(ref.file);\n }\n return null;\n }\n\n revokePreviewUrl(url: string | null): void {\n if (!url || !url.startsWith('blob:')) return;\n if (typeof URL !== 'undefined' && typeof URL.revokeObjectURL === 'function') {\n URL.revokeObjectURL(url);\n }\n }\n\n private normalize(\n result: UploadResult | Promise<UploadResult> | Subscribable<UploadResult>,\n ): Promise<UploadResult> {\n if (this.isSubscribable(result)) {\n return new Promise<UploadResult>((resolve, reject) => {\n let settled = false;\n result.subscribe({\n next: value => {\n if (settled) return;\n settled = true;\n resolve(value);\n },\n error: err => {\n if (settled) return;\n settled = true;\n reject(err);\n },\n complete: () => {\n if (settled) return;\n settled = true;\n reject(new Error('Upload handler completed without emitting a result.'));\n },\n });\n });\n }\n return Promise.resolve(result as UploadResult | Promise<UploadResult>);\n }\n\n private isSubscribable(value: unknown): value is Subscribable<UploadResult> {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Subscribable<UploadResult>).subscribe === 'function'\n );\n }\n}\n","import { Component, OnDestroy, inject, Input, signal, ChangeDetectionStrategy } from '@angular/core';\nimport { AbstractControl } from '@angular/forms';\nimport type { FileRef, NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { FileUploadService } from '../services/file-upload.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/**\n * Image field: preview thumbnail + upload button.\n *\n * With `UPLOAD_HANDLER` registered the file is persisted and stored as `{ url }`; without one\n * it is stored as `{ file }` and previewed from an object URL (revoked when replaced/destroyed).\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-image-field',\n standalone: true,\n imports: [],\n template: `\n <div\n class=\"ngx-field ngx-field--image\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else {\n <div class=\"ngx-field__image-wrap\">\n @if (previewUrl()) {\n <img class=\"ngx-field__image-preview\" [src]=\"previewUrl()\" [alt]=\"label\" />\n } @else {\n <div class=\"ngx-field__image-placeholder\">\n <span>📷</span>\n <span>{{ ui.text('noImage', language) }}</span>\n </div>\n }\n @if (!readonly) {\n <div class=\"ngx-field__image-actions\">\n <label class=\"ngx-field__upload-btn\" [class.ngx-field__upload-btn--loading]=\"uploading()\">\n @if (uploading()) {\n <span>{{ ui.text('uploading', language) }}</span>\n } @else {\n <span>{{ ui.text(previewUrl() ? 'changeImage' : 'uploadImage', language) }}</span>\n <input\n type=\"file\"\n class=\"ngx-field__file-input\"\n [id]=\"domId()\"\n accept=\"image/*\"\n [disabled]=\"field.disabled || uploading()\"\n (change)=\"onFileSelect($any($event.target).files[0])\"\n [attr.aria-describedby]=\"describedBy()\"\n />\n }\n </label>\n @if (previewUrl()) {\n <button type=\"button\" class=\"ngx-field__remove-btn\" (click)=\"remove()\">\n {{ ui.text('remove', language) }}\n </button>\n }\n </div>\n }\n </div>\n <!-- An upload failure and an unmet validator are different problems, and this only\n ever showed the first. A required file left unchosen said nothing, and a\n configured required message had no element to appear in. -->\n @if (uploadError() || errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ uploadError() || errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class ImageFieldComponent implements OnDestroy {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n private readonly uploads = inject(FileUploadService);\n\n readonly uploading = signal(false);\n readonly uploadError = signal<string | null>(null);\n\n /** Cached so an object URL is minted once per File, not once per change-detection pass. */\n private previewSource: FileRef | null = null;\n private previewCache: string | null = null;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n previewUrl(): string | null {\n const value = (this.control?.value as FileRef | null) ?? null;\n if (value === this.previewSource) return this.previewCache;\n\n this.uploads.revokePreviewUrl(this.previewCache);\n this.previewSource = value;\n this.previewCache = this.uploads.previewUrlFor(value);\n return this.previewCache;\n }\n\n async onFileSelect(file: File | undefined): Promise<void> {\n if (!file) return;\n this.uploadError.set(null);\n this.uploading.set(true);\n try {\n this.control.setValue(await this.uploads.toFileRef(file));\n this.control.markAsTouched();\n } catch {\n this.uploadError.set('Upload failed. Please try again.');\n } finally {\n this.uploading.set(false);\n }\n }\n\n remove(): void {\n this.control.setValue(null);\n this.control.markAsTouched();\n }\n\n ngOnDestroy(): void {\n this.uploads.revokePreviewUrl(this.previewCache);\n }\n /** Validation, as distinct from the upload failures this field already reported. */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, inject, Input, signal, ChangeDetectionStrategy } from '@angular/core';\nimport { AbstractControl } from '@angular/forms';\nimport type { FileRef, NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { fileRefName, resolveLabel } from '@dynamic-entity/core';\nimport { FileUploadService } from '../services/file-upload.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/**\n * File field: file input with filename display and download link.\n * Shares the `FileRef` / `UPLOAD_HANDLER` contract with image-field via FileUploadService.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-file-field',\n standalone: true,\n imports: [],\n template: `\n <div\n class=\"ngx-field ngx-field--file\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n @if (fileUrl()) {\n <a class=\"ngx-field__file-link\" [href]=\"fileUrl()!\" target=\"_blank\" rel=\"noopener\">\n 📎 {{ fileName() || ui.text('downloadFile', language) }}\n </a>\n } @else {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">—</span>\n }\n } @else {\n <div class=\"ngx-field__file-wrap\">\n @if (fileName()) {\n <div class=\"ngx-field__file-selected\">\n <span class=\"ngx-field__file-name\">📎 {{ fileName() }}</span>\n <button\n type=\"button\"\n class=\"ngx-field__remove-btn\"\n (click)=\"remove()\"\n [attr.aria-label]=\"ui.text('removeFile', language)\"\n >\n ✕\n </button>\n </div>\n }\n <label class=\"ngx-field__upload-btn\" [class.ngx-field__upload-btn--loading]=\"uploading()\">\n @if (uploading()) {\n <span>{{ ui.text('uploading', language) }}</span>\n } @else {\n <span>{{ fileName() ? ui.text('replaceFile', language) : ui.text('chooseFile', language) }}</span>\n <input\n type=\"file\"\n class=\"ngx-field__file-input\"\n [id]=\"domId()\"\n [disabled]=\"field.disabled || uploading()\"\n (change)=\"onFileSelect($any($event.target).files[0])\"\n [attr.aria-describedby]=\"describedBy()\"\n />\n }\n </label>\n </div>\n <!-- An upload failure and an unmet validator are different problems, and this only\n ever showed the first. A required file left unchosen said nothing, and a\n configured required message had no element to appear in. -->\n @if (uploadError() || errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ uploadError() || errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class FileFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n private readonly uploads = inject(FileUploadService);\n\n readonly uploading = signal(false);\n readonly uploadError = signal<string | null>(null);\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n private get value(): FileRef | null {\n return (this.control?.value as FileRef | null) ?? null;\n }\n\n fileUrl(): string | null {\n return this.value?.url ?? null;\n }\n\n fileName(): string | null {\n return fileRefName(this.value) || null;\n }\n\n async onFileSelect(file: File | undefined): Promise<void> {\n if (!file) return;\n this.uploadError.set(null);\n this.uploading.set(true);\n try {\n this.control.setValue(await this.uploads.toFileRef(file));\n this.control.markAsTouched();\n } catch {\n this.uploadError.set('Upload failed. Please try again.');\n } finally {\n this.uploading.set(false);\n }\n }\n\n remove(): void {\n this.control.setValue(null);\n this.control.markAsTouched();\n }\n /** Validation, as distinct from the upload failures this field already reported. */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { EnvironmentProviders, Type, makeEnvironmentProviders } from '@angular/core';\nimport { FIELD_TYPE_SETS } from '../tokens/injection-tokens';\n\nimport { TextFieldComponent } from '../field-types/text-field.component';\nimport { TextareaFieldComponent } from '../field-types/textarea-field.component';\nimport { MarkdownFieldComponent } from '../field-types/markdown-field.component';\nimport { NumberFieldComponent } from '../field-types/number-field.component';\nimport { CurrencyFieldComponent } from '../field-types/currency-field.component';\nimport { EmailFieldComponent } from '../field-types/email-field.component';\nimport { PasswordFieldComponent } from '../field-types/password-field.component';\nimport { CheckboxFieldComponent } from '../field-types/checkbox-field.component';\nimport { BooleanFieldComponent } from '../field-types/boolean-field.component';\nimport { DateFieldComponent } from '../field-types/date-field.component';\nimport { DateTimeFieldComponent } from '../field-types/date-time-field.component';\nimport { TimeFieldComponent } from '../field-types/time-field.component';\nimport { MonthYearFieldComponent } from '../field-types/month-year-field.component';\nimport { DropdownFieldComponent } from '../field-types/dropdown-field.component';\nimport { RadioFieldComponent } from '../field-types/radio-field.component';\nimport { MultiSelectFieldComponent } from '../field-types/multi-select-field.component';\nimport { EntityRefFieldComponent } from '../field-types/entity-ref-field.component';\nimport { GroupFieldComponent } from '../field-types/group-field.component';\nimport { ArrayFieldComponent } from '../field-types/array-field.component';\nimport { ImageFieldComponent } from '../field-types/image-field.component';\nimport { FileFieldComponent } from '../field-types/file-field.component';\n\n/**\n * Field-type registration — the tree-shaking seam.\n *\n * `FieldRegistryService` imports no components. Whatever you register here is what gets\n * bundled, so an app that only uses text/number/dropdown pays for three components and\n * their imports, not twenty-one.\n *\n * ```ts\n * // Everything (convenient; bundles all built-ins):\n * provideNgxDynamicEntity(), provideBuiltInFieldTypes()\n *\n * // Only what this app renders:\n * provideFieldTypes({ text: TextFieldComponent, number: NumberFieldComponent })\n * ```\n *\n * Both merge into `FIELD_TYPE_REGISTRY`; later registrations win on key collision.\n */\n\n/** Map of every built-in field type key → component. Referencing this pulls in all of them. */\nexport function builtInFieldTypes(): Record<string, Type<any>> {\n return {\n text: TextFieldComponent,\n textarea: TextareaFieldComponent,\n markdown: MarkdownFieldComponent,\n number: NumberFieldComponent,\n currency: CurrencyFieldComponent,\n email: EmailFieldComponent,\n password: PasswordFieldComponent,\n checkbox: CheckboxFieldComponent,\n boolean: BooleanFieldComponent,\n date: DateFieldComponent,\n datetime: DateTimeFieldComponent,\n time: TimeFieldComponent,\n monthYear: MonthYearFieldComponent,\n dropdown: DropdownFieldComponent,\n radio: RadioFieldComponent,\n multiSelect: MultiSelectFieldComponent,\n 'entity-ref': EntityRefFieldComponent,\n group: GroupFieldComponent,\n array: ArrayFieldComponent,\n image: ImageFieldComponent,\n file: FileFieldComponent,\n };\n}\n\n/** Register a specific set of field types. Only the components you name are bundled. */\nexport function provideFieldTypes(types: Record<string, Type<any>>): EnvironmentProviders {\n return makeEnvironmentProviders([\n { provide: FIELD_TYPE_SETS, useValue: types, multi: true },\n ]);\n}\n\n/** Register all 21 built-in field type keys. Convenience for apps that use most of them. */\nexport function provideBuiltInFieldTypes(): EnvironmentProviders {\n return provideFieldTypes(builtInFieldTypes());\n}\n","import { Injectable, inject } from '@angular/core';\nimport { HOOK_REGISTRY } from '../tokens/injection-tokens';\n\n/**\n * HookRegistryService — stores and runs Angular-side pre/post hooks.\n * Consumers register hooks via provideNgxDynamicEntity({ hooks: { 'clients:beforeSave': fn } }).\n */\n@Injectable({ providedIn: 'root' })\nexport class HookRegistryService {\n private readonly registry = inject(HOOK_REGISTRY, { optional: true }) ?? new Map();\n\n has(key: string): boolean {\n return this.registry.has(key);\n }\n\n async run(key: string, data: any, context: any = {}): Promise<any> {\n const hook = this.registry.get(key);\n if (!hook) return data;\n return hook(data, context);\n }\n}\n","import { Injectable } from '@angular/core';\nimport type {\n EntityFormConfig,\n EvaluateFormRulesOptions,\n FieldScopeEntry,\n FormRule,\n NestedFieldConfig,\n NestedTabConfig,\n RuleEvaluationResult,\n} from '@dynamic-entity/core';\nimport type { AbstractControl } from '@angular/forms';\nimport { evaluateFieldVisibility, evaluateFormRules, filterRulesForTab } from '@dynamic-entity/core';\n\n/** What `syncHiddenFieldState` needs from the form it is operating on. */\nexport interface RuleSyncContext {\n result: RuleEvaluationResult;\n /** The values `showWhen` is evaluated against — the flat map the rules engine reads. */\n values: Record<string, unknown>;\n /** Every name a field answers to: its bare id, and its bracketed path. */\n namesOf(field: NestedFieldConfig): readonly string[];\n /**\n * The field's dotted address, unbracketed — `personal.address.city`.\n *\n * Separate from `namesOf` because it is compared as a *prefix*: a container hides its\n * descendants, and `[personal.address]` is not a prefix of `[personal.address.city]` once\n * the brackets are in the way.\n */\n addressOf(field: NestedFieldConfig): string;\n /** The control a scope entry addresses, or `null` when it has no static path. */\n controlFor(entry: FieldScopeEntry): AbstractControl | null;\n}\n\n/**\n * RulesEvaluationService — evaluates rules, and owns what a result *means*.\n *\n * It used to be two passthrough methods, with the interpretation spread across the component:\n * the render filter decided one way what a rule result did to a field, and the validity sync\n * decided again forty lines further down. They disagreed about what \"every field\" meant, and\n * the consequence was a required field inside a `group` that a rule had hidden holding\n * `form.invalid` true forever with nothing on screen to explain it.\n *\n * Precedence lives here now, in one method that both callers go through. Still stateless —\n * every method takes the result it is interpreting, so there is nothing to go stale against a\n * rebuilt form and nothing to reset between configs.\n */\n@Injectable({ providedIn: 'root' })\nexport class RulesEvaluationService {\n /**\n * Evaluate rules against form values and optional original baseline values.\n */\n evaluate(\n rules: FormRule[] | undefined | null,\n values: Record<string, unknown>,\n originalValues?: Record<string, unknown>,\n options?: EvaluateFormRulesOptions,\n ): RuleEvaluationResult {\n return evaluateFormRules(rules, values, originalValues, options);\n }\n\n /**\n * Filter rules pertinent to a single tab.\n */\n filterForTab(rules: FormRule[] | undefined | null, tabId: string, config: EntityFormConfig): FormRule[] {\n return filterRulesForTab(rules, tabId, config);\n }\n\n /**\n * Whether a field renders, under the precedence documented on `RuleEvaluationResult`.\n *\n * An explicit hide beats everything. A show beats static hiding — `visibility: false`, or a\n * `showWhen` that does not currently hold — because a rule that could only hide what the\n * config already hides would have nothing to say, and `{ visibility: true }` was a\n * documented no-op until it did. Otherwise the config's own visibility decides.\n */\n isFieldVisible(\n result: RuleEvaluationResult,\n field: NestedFieldConfig,\n names: readonly string[],\n values: Record<string, unknown>,\n ): boolean {\n const sets = this.nameSets(result);\n if (names.some(name => sets.hidden.has(name))) return false;\n if (names.some(name => sets.shown.has(name))) return true;\n return evaluateFieldVisibility(field, values);\n }\n\n /** The same precedence for a tab. */\n isTabVisible(result: RuleEvaluationResult, tab: NestedTabConfig): boolean {\n if (result.hiddenTabs.includes(tab.id)) return false;\n return tab.visibility !== false || result.shownTabs.includes(tab.id);\n }\n\n /**\n * Keep a hidden field's control out of form validity.\n *\n * A field hidden by a rule or a `showWhen` is filtered out of the render, but its\n * validators stay attached — so a hidden *required* field holds `form.invalid` true\n * forever, permanently disabling Save with nothing on screen to explain why.\n *\n * Disabling is the fix rather than stripping validators: Angular excludes disabled controls\n * from validity, and the field's own validators survive intact for when it comes back.\n * Values are untouched — a disabled control still carries its value, so rule evaluation and\n * the emitted record see exactly what they saw before. That also keeps this from feeding\n * back on itself: hiding a field cannot change the values the rules are evaluated over.\n *\n * The predicate is `isFieldVisible`, the same one the render filter uses, so what is on\n * screen and what counts toward validity cannot drift apart.\n *\n * Entries must arrive parent-first, which is what `collectFieldScopes` yields: a container's\n * children are skipped once the container itself is hidden, because Angular's `disable()`\n * cascades to descendants and a child's `enable()` walks back up recalculating ancestors.\n * Toggling a child inside a hidden group would fight its parent.\n */\n syncHiddenFieldState(entries: readonly FieldScopeEntry[], ctx: RuleSyncContext): void {\n const hiddenContainers: string[] = [];\n\n for (const entry of entries) {\n const field = entry.field;\n if (!field?.id) continue;\n\n const address = ctx.addressOf(field);\n if (hiddenContainers.some(prefix => address.startsWith(`${prefix}.`))) continue;\n\n const hidden = !this.isFieldVisible(ctx.result, field, ctx.namesOf(field), ctx.values);\n if (hidden && (field.type === 'group' || field.type === 'array')) hiddenContainers.push(address);\n\n const ctrl = ctx.controlFor(entry);\n if (!ctrl) continue;\n\n if (hidden) {\n if (ctrl.enabled) ctrl.disable({ emitEvent: false });\n } else if (ctrl.disabled && !field.disabled) {\n ctrl.enable({ emitEvent: false });\n }\n }\n }\n\n /**\n * The hidden and shown names as sets, memoised against the result they came from.\n *\n * `isFieldVisible` runs once per field per change-detection pass; building two sets from\n * two arrays each time turns a rule result into allocation proportional to the form. A\n * `WeakMap` keyed by the result means it is built once per evaluation and collected with it.\n */\n private nameSets(result: RuleEvaluationResult): { hidden: Set<string>; shown: Set<string> } {\n let sets = this.nameSetCache.get(result);\n if (!sets) {\n sets = { hidden: new Set(result.hiddenFields), shown: new Set(result.shownFields) };\n this.nameSetCache.set(result, sets);\n }\n return sets;\n }\n\n private readonly nameSetCache = new WeakMap<\n RuleEvaluationResult,\n { hidden: Set<string>; shown: Set<string> }\n >();\n}\n","import { Injectable, Inject, Optional } from '@angular/core';\nimport type { EntityFormConfig } from '@dynamic-entity/core';\nimport { isObservable, firstValueFrom } from 'rxjs';\nimport { CONFIG_SOURCE, type ConfigSourceHandler } from '../tokens/injection-tokens';\n\n@Injectable({ providedIn: 'root' })\nexport class ConfigSourceService {\n private readonly cache = new Map<string, EntityFormConfig>();\n private readonly inFlight = new Map<string, Promise<EntityFormConfig | undefined>>();\n\n private readonly handler?: ConfigSourceHandler;\n\n constructor(@Optional() @Inject(CONFIG_SOURCE) handler?: any) {\n this.handler = handler;\n }\n\n /** Retrieve an entity config by key, with caching and in-flight deduplication. */\n async getConfig(entityKey: string): Promise<EntityFormConfig | undefined> {\n if (!entityKey || !this.handler) return undefined;\n if (this.cache.has(entityKey)) return this.cache.get(entityKey);\n if (this.inFlight.has(entityKey)) return this.inFlight.get(entityKey);\n\n const promise = (async () => {\n try {\n const raw = this.handler!(entityKey);\n let resolved: EntityFormConfig | undefined;\n\n if (isObservable(raw)) {\n resolved = await firstValueFrom(raw as any);\n } else {\n resolved = await Promise.resolve(raw as any);\n }\n\n if (resolved) {\n this.cache.set(entityKey, resolved);\n }\n return resolved;\n } catch (err) {\n console.warn(`ConfigSourceService failed to load config for entity \"${entityKey}\"`, err);\n return undefined;\n } finally {\n this.inFlight.delete(entityKey);\n }\n })();\n\n this.inFlight.set(entityKey, promise);\n return promise;\n }\n\n /** Clear cached configs (e.g. after a config edit in the builder). */\n clearCache(entityKey?: string): void {\n if (entityKey) {\n this.cache.delete(entityKey);\n } else {\n this.cache.clear();\n }\n }\n}\n","import { Injectable, inject, isDevMode } from '@angular/core';\nimport { AbstractControl, FormArray, FormBuilder, FormGroup } from '@angular/forms';\nimport type { EntityFormConfig, NestedFieldConfig, NestedTabConfig } from '@dynamic-entity/core';\nimport {\n getTabData,\n getTabPath,\n getValueByPath,\n normalizeArrayStructures,\n parseFieldRef,\n setTabData,\n setValueByPath,\n} from '@dynamic-entity/core';\nimport { ValidatorRegistryService } from '../services/validator-registry.service';\n\n/**\n * FormStructureService — config ⇄ `FormGroup`, and nothing else.\n *\n * The one question this answers is *where a value lives*: which control a field owns, how\n * the tab tree nests into groups, how a record is read out of the tree and patched back in.\n * It was half of `DynamicFormComponent`, mixed in with tab state, focus management, rule\n * evaluation and RBAC — and the cost of that was not length but ownership: the bug Phase 2\n * fixed was two methods forty lines apart disagreeing about what \"every field\" meant.\n *\n * Deliberately stateless. Every method takes the form and the config it is operating on, so\n * there is no cached `this.form` to go stale against a rebuilt one, and every method is\n * testable without a component or a TestBed.\n *\n * Provided at the component, not the root: `FormBuilder` and the validator registry are the\n * only things injected, but keeping the service per form leaves room for that to change\n * without turning into shared mutable state.\n */\n@Injectable()\nexport class FormStructureService {\n private readonly fb = inject(FormBuilder);\n private readonly validatorRegistry = inject(ValidatorRegistryService);\n\n /**\n * Build the control tree for a config.\n *\n * The tree mirrors the record's shape exactly: a tab opens a `FormGroup` under its id, a\n * `flatData` tab merges into its parent's, and a `group` field opens one for its children.\n * That correspondence is what lets a `[path]` ref resolve through `form.get()` and name\n * exactly one control — see `getControl`.\n */\n buildForm(config: EntityFormConfig): FormGroup {\n const group: Record<string, AbstractControl> = {};\n\n const buildTabControls = (tabs: NestedTabConfig[], parentGroup: Record<string, AbstractControl>) => {\n for (const tab of tabs) {\n if (tab.flatData) {\n for (const field of tab.fields || []) {\n this.buildFieldControl(field, parentGroup);\n }\n if (tab.children) buildTabControls(tab.children, parentGroup);\n } else {\n const tabGroup: Record<string, AbstractControl> = {};\n for (const field of tab.fields || []) {\n this.buildFieldControl(field, tabGroup);\n }\n if (tab.children) buildTabControls(tab.children, tabGroup);\n parentGroup[tab.id] = this.fb.group(tabGroup);\n }\n }\n };\n\n buildTabControls(config.tabs || [], group);\n return this.fb.group(group);\n }\n\n /** One field's control: a nested group, an empty array, or a leaf carrying its validators. */\n buildFieldControl(field: NestedFieldConfig, group: Record<string, AbstractControl>): void {\n if (field.type === 'group') {\n const subGroup: Record<string, AbstractControl> = {};\n for (const child of field.children || []) {\n this.buildFieldControl(child, subGroup);\n }\n group[field.id] = this.fb.group(subGroup);\n } else if (field.type === 'array') {\n group[field.id] = this.fb.array([]);\n } else {\n const validators = this.validatorRegistry.resolveFromConfig(field.validators);\n const asyncValidators = this.validatorRegistry.resolveAsyncFromConfig(field.validators);\n group[field.id] = this.fb.control(\n { value: field.defaultValue ?? null, disabled: field.disabled ?? false },\n validators,\n asyncValidators,\n );\n }\n }\n\n /** One row of an `array` field: a FormGroup when the field declares columns, else a bare control. */\n buildArrayRow(field: NestedFieldConfig | undefined, item: unknown): AbstractControl {\n if (!field?.children?.length) return this.fb.control(item);\n\n const rowGroup: Record<string, AbstractControl> = {};\n for (const child of field.children) {\n this.buildFieldControl(child, rowGroup);\n }\n const group = this.fb.group(rowGroup);\n if (item && typeof item === 'object') group.patchValue(item as Record<string, unknown>);\n return group;\n }\n\n /** The `FormGroup` a tab's fields live in, honouring `flatData`. */\n getTabGroup(form: FormGroup | null, config: EntityFormConfig | null | undefined, tabId: string): FormGroup | null {\n if (!form) return null;\n const path = getTabPath(config?.tabs, tabId);\n if (!path || path.length === 0) return form;\n\n let curr: AbstractControl | null = form;\n for (const p of path) {\n if (!curr || !(curr instanceof FormGroup)) return null;\n curr = curr.get(p);\n }\n return curr instanceof FormGroup ? curr : null;\n }\n\n /**\n * Find a control by reference: a bracketed path, or a bare field id.\n *\n * A bracketed path names exactly one control, because the tree nests exactly as the path\n * does — so `form.get('work.address.city')` walks straight to it. A bare id is what every\n * config written before paths existed uses: it is looked for on `currentTabId` first, then\n * at the root, then by a recursive search whose result is whichever the walk reaches first.\n * That last branch is the ambiguity refs exist to remove, and callers that can name a path\n * should.\n */\n getControl(\n form: FormGroup | null,\n config: EntityFormConfig | null | undefined,\n fieldId: string,\n currentTabId?: string,\n ): AbstractControl | null {\n if (!form) return null;\n\n const parsed = parseFieldRef(fieldId);\n if (parsed.kind === 'ref') return form.get(parsed.value);\n\n if (currentTabId) {\n const tabGrp = this.getTabGroup(form, config, currentTabId);\n const ctrl = tabGrp?.get(fieldId);\n if (ctrl) return ctrl;\n }\n\n const rootCtrl = form.get(fieldId);\n if (rootCtrl) return rootCtrl;\n\n const findInGroup = (group: FormGroup): AbstractControl | null => {\n for (const key of Object.keys(group.controls)) {\n const c = group.controls[key];\n if (key === fieldId) return c;\n if (c instanceof FormGroup) {\n const found = findInGroup(c);\n if (found) return found;\n }\n }\n return null;\n };\n\n return findInGroup(form);\n }\n\n /** Assemble the full nested record from per-tab groups, respecting flatData, refererField & arrays. */\n extractRecord(form: FormGroup | null, config: EntityFormConfig | null | undefined): Record<string, any> {\n if (!form || !config) return {};\n let record: Record<string, any> = {};\n\n const walkTabs = (tabs: NestedTabConfig[]) => {\n for (const tab of tabs) {\n const fieldValBag: Record<string, unknown> = {};\n for (const field of tab.fields || []) {\n const ctrl = this.getControl(form, config, field.id, tab.id);\n if (ctrl) fieldValBag[field.id] = ctrl.value;\n }\n\n setTabData(record, tab.id, fieldValBag, config);\n\n for (const field of tab.fields || []) {\n if (field.refererField) {\n const ctrl = this.getControl(form, config, field.id, tab.id);\n if (ctrl) setValueByPath(record, field.refererField, ctrl.value);\n }\n }\n\n if (tab.children) walkTabs(tab.children);\n }\n };\n\n walkTabs(config.tabs || []);\n record = normalizeArrayStructures(record, config);\n return record;\n }\n\n /**\n * Write a record into the control tree.\n *\n * Returns the top-level keys that named a known field and were *not* consumed, so the\n * caller can say so — see `DynamicFormComponent.warnUnconsumedInitialData`. Reporting\n * rather than logging keeps the \"warn once per form\" bookkeeping with the form, and keeps\n * this service free of console output.\n */\n patchForm(\n form: FormGroup | null,\n config: EntityFormConfig | null | undefined,\n data: Record<string, any>,\n fieldsById: Map<string, NestedFieldConfig>,\n ): string[] {\n if (!data || !form || !config) return [];\n const patchedFieldIds = new Set<string>();\n\n const walkTabs = (tabs: NestedTabConfig[]) => {\n for (const tab of tabs) {\n const tabData = getTabData(tab.id, data, config);\n for (const field of tab.fields || []) {\n let val = tabData && typeof tabData === 'object' ? tabData[field.id] : undefined;\n if (field.refererField) {\n const refVal = getValueByPath(data, field.refererField);\n if (refVal !== undefined) val = refVal;\n }\n if (val === undefined) continue;\n\n const ctrl = this.getControl(form, config, field.id, tab.id);\n if (!ctrl) continue;\n\n if (ctrl instanceof FormArray && Array.isArray(val)) {\n ctrl.clear();\n for (const item of val) {\n ctrl.push(this.buildArrayRow(fieldsById.get(field.id), item));\n }\n } else {\n ctrl.patchValue(val, { emitEvent: false });\n }\n patchedFieldIds.add(field.id);\n }\n if (tab.children) walkTabs(tab.children);\n }\n };\n\n walkTabs(config.tabs || []);\n return this.unconsumedKeys(config, data, fieldsById, patchedFieldIds);\n }\n\n /**\n * Top-level keys that name a field but reached no control.\n *\n * A record is nested by tab id (`{ tabId: { fieldId: value } }`) unless the tab sets\n * `flatData: true`. Handing a flat record to a nested tab finds nothing, so the fields stay\n * empty — with no error and no clue.\n *\n * Only keys matching a known field id count: anything else is the consumer's own record\n * metadata (ids, timestamps, `_configVersion`) and is not our business.\n */\n private unconsumedKeys(\n config: EntityFormConfig,\n data: Record<string, any>,\n fieldsById: Map<string, NestedFieldConfig>,\n patchedFieldIds: Set<string>,\n ): string[] {\n if (!isDevMode()) return [];\n\n const tabIds = new Set<string>();\n const collectTabIds = (tabs: NestedTabConfig[]) => {\n for (const tab of tabs) {\n tabIds.add(tab.id);\n if (tab.children) collectTabIds(tab.children);\n }\n };\n collectTabIds(config.tabs || []);\n\n return Object.keys(data).filter(\n key =>\n // A tab id at the root is the nested container, not a stray field.\n !tabIds.has(key) &&\n data[key] !== undefined &&\n fieldsById.has(key) &&\n !patchedFieldIds.has(key),\n );\n }\n}\n","import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n Injector,\n Input,\n Output,\n EventEmitter,\n OnChanges,\n OnDestroy,\n OnInit,\n SimpleChange,\n SimpleChanges,\n afterNextRender,\n signal,\n computed,\n inject,\n isDevMode,\n ElementRef,\n ViewChild,\n ViewChildren,\n QueryList,\n HostListener,\n} from '@angular/core';\nimport { NgComponentOutlet } from '@angular/common';\nimport { AbstractControl, FormArray, FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport { Subscription } from 'rxjs';\nimport { debounceTime } from 'rxjs/operators';\nimport type { AutoPatchConfig, EntityFormConfig, FormRule, NestedFieldConfig, NestedTabConfig } from '@dynamic-entity/core';\nimport type { FieldScopeEntry } from '@dynamic-entity/core';\nimport {\n ambiguousFieldIds,\n collectFieldScopes,\n fieldRefFor,\n parseFieldRef,\n refOf,\n toRefToken,\n valuesEqual,\n applyAutoPatch,\n applyPatchOnTrue,\n fieldsUnderTab,\n migrateRecord,\n findTab,\n normalizeConfigOptions,\n resolveLabel,\n} from '@dynamic-entity/core';\nimport { DynamicFieldComponent } from './dynamic-field/dynamic-field.component';\nimport { FormStructureService } from './form-structure.service';\nimport { COMMON_MODULES_REGISTRY, RECORD_MIGRATIONS } from '../tokens/injection-tokens';\nimport { ValidatorRegistryService } from '../services/validator-registry.service';\nimport { HookRegistryService } from '../services/hook-registry.service';\nimport { RbacService } from '../services/rbac.service';\nimport { RulesEvaluationService } from '../services/rules-evaluation.service';\nimport { EntityRefSelectionService } from '../services/entity-ref-selection.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\n\n/**\n * Grid width per field type, used only under `layout=\"auto\"` and only where the field itself\n * names no `colSpan`.\n *\n * The rule behind the numbers is how much *content* the control holds, not how much room it\n * would happily fill: a date is eight characters and a currency amount is rarely more, so\n * giving either a full row buys nothing but scrolling. Anything that holds a paragraph, a\n * picture, or a form of its own keeps all twelve.\n *\n * A type missing from this table falls back to twelve, which is what an unrecognised custom\n * field type should get: the layout is conservative about controls it knows nothing about.\n */\nconst AUTO_COL_SPAN: Readonly<Record<string, number>> = {\n text: 6,\n email: 6,\n password: 6,\n number: 4,\n currency: 4,\n date: 4,\n datetime: 4,\n time: 4,\n monthYear: 4,\n dropdown: 6,\n radio: 6,\n multiSelect: 6,\n boolean: 4,\n checkbox: 4,\n 'entity-ref': 6,\n // Left at the full width deliberately — textarea, markdown, image, file, group and array\n // each hold something a half-row would crop.\n};\n\n/** A field the form will not save, with what is wrong and where to find it. */\nexport interface InvalidField {\n field: NestedFieldConfig;\n /** The same message the field renders under itself. */\n message: string;\n tabId: string;\n subTabId?: string;\n}\n\n/**\n * DynamicFormComponent — the main form component.\n * Renders a reactive form from EntityFormConfig with tab support, responsive 12-col grid,\n * rules evaluation, conditional visibility, autoPatch/patchOnTrue, criticalField locking,\n * keyboard shortcuts (Ctrl+S, Esc), and RBAC-gated submission.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-dynamic-form',\n standalone: true,\n imports: [ReactiveFormsModule, DynamicFieldComponent, NgComponentOutlet],\n // Scoped per form instance: entity-ref selections must not leak between concurrent forms,\n // and the structure service is deliberately per form rather than shared.\n providers: [EntityRefSelectionService, FormStructureService],\n templateUrl: './dynamic-form.component.html',\n /*\n * The grid is structural, so it lives here rather than in the optional stylesheet.\n *\n * `getFieldSpan` writes `grid-column` inline on every slot, and a consumer who never\n * imports `ngx-dynamic-entity/styles.css` still has to get a laid-out form rather than a\n * column of unpositioned divs. That makes this the authoritative copy, and the reason the\n * stylesheet deliberately does not restate it: a component stylesheet is injected after a\n * global one and carries an attribute selector, so a duplicate there would lose every tie\n * and sit in the file looking authoritative while doing nothing.\n *\n * Every value that a design might want to move is read from the same tokens the stylesheet\n * sets, with a fallback for the consumer who imports nothing.\n */\n styles: [\n `\n .ngx-form__panel {\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n gap: var(--ngx-gap, 18px);\n align-items: start;\n }\n /*\n * A read-only record is a table of values, not a form.\n *\n * With every field at its authored span the record view spent a screen on six values —\n * and no control is being sized here, so the width a text input needs is not the width\n * a value needs. auto-fit packs them, and a long note still takes its own row when the\n * content demands one.\n */\n .ngx-form--readonly .ngx-form__panel {\n grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));\n gap: 2px var(--ngx-gap, 18px);\n }\n .ngx-form--readonly .ngx-form__field-slot {\n grid-column: auto;\n }\n .ngx-form__field-slot {\n display: flex;\n align-items: flex-start;\n gap: 6px;\n min-width: 0;\n }\n .ngx-form__field-slot ngx-dynamic-field {\n flex: 1;\n min-width: 0;\n }\n .ngx-form__lock {\n flex: 0 0 auto;\n margin-top: 22px;\n background: none;\n border: 1px solid transparent;\n border-radius: var(--ngx-radius-sm, 6px);\n cursor: pointer;\n font-size: 14px;\n line-height: 1;\n padding: 4px 6px;\n }\n .ngx-form__lock:hover {\n border-color: var(--ngx-color-border, #d1d5db);\n background: var(--ngx-color-surface-alt, #f9fafb);\n }\n /* Matches the stylesheet's own breakpoint — a 12-column grid is unreadable below it. */\n @media (max-width: 640px) {\n .ngx-form__panel,\n .ngx-form--readonly .ngx-form__panel {\n grid-template-columns: minmax(0, 1fr);\n }\n .ngx-form__field-slot {\n grid-column: 1 / -1 !important;\n }\n }\n `,\n ],\n})\nexport class DynamicFormComponent implements OnInit, OnChanges, OnDestroy {\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n // ─── Inputs ───────────────────────────────────────────────────────────────\n /**\n * The schema to render.\n *\n * An accessor pair rather than a plain field: `ngOnChanges` normalises the option shape,\n * and that result is kept here instead of being written back over the input. Reassigning\n * an `@Input` works, but it mutates what the parent handed us — and a parent using OnPush\n * or signals would never observe the replacement anyway.\n *\n * Reads of `this.config` get the normalised copy once it exists, so every internal caller\n * is unaffected.\n */\n @Input()\n set config(value: EntityFormConfig) {\n this.rawConfig = value;\n this.normalizedConfig = undefined; // re-normalised in ngOnChanges\n }\n get config(): EntityFormConfig {\n return this.normalizedConfig ?? this.rawConfig;\n }\n private rawConfig!: EntityFormConfig;\n private normalizedConfig?: EntityFormConfig;\n @Input() rules?: FormRule[];\n @Input() initialData?: Record<string, any>;\n /** Session-original values for `VALUE_CHANGED` rules. Captured from the first build when omitted. */\n @Input() originalData?: Record<string, any>;\n @Input() userRoles: string[] = [];\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n /** Field ids forced read-only while the rest of the form stays editable. */\n @Input() readOnlyFields: string[] = [];\n /**\n * Render rule `info` banners inline. The record editor sets this false and renders its\n * own dismissible versions, so the two do not double up.\n */\n @Input() showInfoBanners: boolean = true;\n @Input() loading: boolean = false;\n @Input() error: string | null = null;\n /**\n * Milliseconds to debounce `formChange`. The reference debounces at 300ms so a consumer\n * re-rendering on every value change is not driven per keystroke. Zero emits\n * synchronously, which the record editor relies on for its own bookkeeping.\n */\n @Input() changeDebounceMs: number = 0;\n /**\n * Preview mode: seed one empty row per `array` field so the structure is visible, then\n * disable the form. Used by the builder's live preview.\n */\n @Input() preview: boolean = false;\n /**\n * How a field with no `colSpan` of its own is sized in the 12-column grid.\n *\n * `stack` — the historic behaviour — gives every such field the full twelve, so a form of\n * eight short text fields renders as an eight-row ladder with two thirds of its width\n * empty. `auto` sizes them by field type instead: a date or a number is half a row, a\n * textarea or a nested group still takes all twelve.\n *\n * An explicit `colSpan` always wins in both modes, so turning `auto` on cannot override a\n * layout somebody authored. The default stays `stack` because changing how existing configs\n * render is not this input's business — opting in is.\n */\n @Input() layout: 'stack' | 'auto' = 'stack';\n\n // ─── Outputs ──────────────────────────────────────────────────────────────\n @Output() formSubmit = new EventEmitter<Record<string, any>>();\n @Output() formChange = new EventEmitter<Record<string, any>>();\n @Output() formReset = new EventEmitter<void>();\n /** The visible tab changed. Lets a host track it without reaching into this component. */\n @Output() activeTabChange = new EventEmitter<string>();\n /**\n * Emitted when a `beforeSave` hook aborted the save — by returning false or throwing.\n * `formSubmit` does not fire in that case.\n */\n @Output() saveRejected = new EventEmitter<{ reason: string; error?: unknown }>();\n\n // ─── Services ─────────────────────────────────────────────────────────────\n private readonly cdr = inject(ChangeDetectorRef);\n private readonly fb = inject(FormBuilder);\n private readonly validatorRegistry = inject(ValidatorRegistryService);\n private readonly hookRegistry = inject(HookRegistryService);\n private readonly rbacService = inject(RbacService);\n private readonly rulesEvaluation = inject(RulesEvaluationService);\n /** config ⇄ FormGroup: where a value lives. See `FormStructureService`. */\n private readonly structure = inject(FormStructureService);\n /** Resolves what is wrong with a field, for the error summary — see `resolveForField`. */\n private readonly messages = inject(ValidationMessagesService);\n private readonly entityRefSelection = inject(EntityRefSelectionService);\n private readonly commonModulesRegistry = inject(COMMON_MODULES_REGISTRY, { optional: true });\n private readonly migrations = inject(RECORD_MIGRATIONS, { optional: true }) ?? [];\n /** Scopes the field-slot lookup a jump does, so the library never touches global `document`. */\n private readonly host = inject(ElementRef) as ElementRef<HTMLElement>;\n /** Ties `afterNextRender` to this component, so destroying it cancels a pending jump. */\n private readonly injector = inject(Injector);\n\n protected readonly Object = Object;\n\n // ─── Signals (local reactive state) ───────────────────────────────────────\n readonly activeTab = signal<string>('');\n readonly activeSubTab = signal<string>('');\n readonly isSaving = signal(false);\n readonly formValues = signal<Record<string, any>>({});\n /** Baseline captured at first build, used when `originalData` is not supplied. */\n readonly sessionBaseline = signal<Record<string, any>>({});\n /** Critical fields the user has explicitly unlocked for editing. */\n readonly unlockedFields = signal<ReadonlySet<string>>(new Set<string>());\n\n /** The active tab's field panel, focused after a tab switch. */\n @ViewChild('formPanel') private formPanel?: ElementRef<HTMLElement>;\n\n /** The hosted field components, so an external control-state change can reach them. */\n @ViewChildren(DynamicFieldComponent) private fieldHosts?: QueryList<DynamicFieldComponent>;\n\n // ─── Form ─────────────────────────────────────────────────────────────────\n form!: FormGroup;\n\n private valueSub?: Subscription;\n private statusSub?: Subscription;\n private selectionSub?: Subscription;\n /** Previous values, for detecting `patchOnTrue` false→true transitions. */\n private previousValues: Record<string, any> = {};\n\n // ─── Keyboard Shortcuts ───────────────────────────────────────────────────\n @HostListener('window:keydown', ['$event'])\n handleKeyboardEvent(event: KeyboardEvent): void {\n if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') {\n event.preventDefault();\n // No `form.valid` check: the shortcut is the Save button, and pressing Save on an\n // invalid form is what produces the error summary. Guarding here instead meant Ctrl+S\n // on an incomplete form did nothing at all — and unlike the button, a shortcut cannot\n // even look disabled.\n // `void`, not an `await`: a `@HostListener` cannot be async without changing what\n // Angular does with its return value, and `submit()` reports its own failures through\n // `saveRejected`. Nothing here would have anywhere to put a rejection.\n if (!this.readonly && this.canSubmit) void this.submit();\n }\n }\n\n // ─── Computed ─────────────────────────────────────────────────────────────\n readonly ruleResult = computed(() =>\n this.rulesEvaluation.evaluate(this.rules, this.formValues(), this.baseline(), {\n // The engine reports rather than logs, because it also runs on a server. This is the\n // client's answer: say it once per distinct problem, in dev only. A rule the author\n // half-finished used to throw out of change detection; now it is skipped, and a\n // silently skipped rule is exactly as hard to diagnose as a thrown one.\n onProblem: message => this.warnOnce(message),\n }),\n );\n\n /** Warned-about rule problems, per component instance — see `warnedAmbiguousIds`. */\n private readonly warnedProblems = new Set<string>();\n\n private warnOnce(message: string): void {\n if (!isDevMode() || this.warnedProblems.has(message)) return;\n this.warnedProblems.add(message);\n console.warn(`[ngx-dynamic-entity] ${message}`);\n }\n\n /**\n * Critical fields whose value differs from the session baseline.\n * These drive the deferred `VALUE_CHANGED` banner — a critical edit is announced once,\n * against the value the record had when the session started, not per keystroke.\n */\n readonly changedCriticalFields = computed<NestedFieldConfig[]>(() => {\n const baseline = this.baseline();\n if (!baseline || Object.keys(baseline).length === 0) return [];\n const values = this.formValues();\n return this.allFields().filter(f => f.criticalField && !this.sameValue(values[f.id], baseline[f.id]));\n });\n\n get tabs(): NestedTabConfig[] {\n return this.config?.tabs || [];\n }\n\n get visibleTabs(): NestedTabConfig[] {\n return this.tabs.filter(tab => this.isTabVisible(tab));\n }\n\n private isTabVisible(tab: NestedTabConfig): boolean {\n return this.rulesEvaluation.isTabVisible(this.ruleResult(), tab);\n }\n\n get activeTabConfig(): NestedTabConfig | null {\n const tabId = this.activeTab();\n if (!tabId) return this.visibleTabs[0] ?? null;\n return findTab(this.tabs, tabId);\n }\n\n get visibleSubTabs(): NestedTabConfig[] {\n const active = this.activeTabConfig;\n if (!active?.children || active.children.length === 0) return [];\n return active.children.filter(tab => this.isTabVisible(tab));\n }\n\n get activeSubTabConfig(): NestedTabConfig | null {\n const subTabs = this.visibleSubTabs;\n if (!subTabs.length) return null;\n const subId = this.activeSubTab();\n return subTabs.find(s => s.id === subId) ?? subTabs[0];\n }\n\n /**\n * The component to mount for the active tab, or `null` if there is nothing to mount.\n *\n * A registry entry may name its component with a **selector string** — `COMMON_MODULES`\n * is a catalogue of names for the builder's picker, and the token's own example showed\n * one. `ngComponentOutlet` mounts a component *type*, so a string reached it and Angular\n * threw an assertion the moment somebody opened that tab. Following the documented shape\n * broke the feature, which is worse than the feature not existing.\n *\n * A string now resolves to nothing renderable and says why, once per module.\n */\n get activeTabModuleComponent(): any | null {\n const active = this.activeSubTabConfig ?? this.activeTabConfig;\n if (!active?.moduleName || !this.commonModulesRegistry) return null;\n const entry = this.commonModulesRegistry.find(m => m.id === active.moduleName || m.component === active.moduleName);\n if (!entry) return null;\n if (typeof entry.component === 'string') {\n this.warnSelectorModule(entry.id, entry.component);\n return null;\n }\n return entry.component;\n }\n\n /** Warned once per module id, because a getter runs on every change-detection pass. */\n private readonly warnedSelectorModules = new Set<string>();\n\n private warnSelectorModule(id: string, selector: string): void {\n if (this.warnedSelectorModules.has(id)) return;\n this.warnedSelectorModules.add(id);\n console.warn(\n `[ngx-dynamic-entity] The common module '${id}' is registered with the selector ` +\n `'${selector}' rather than a component class, so there is nothing to mount for its ` +\n `tab. Register the component itself: ` +\n `{ id: '${id}', label: {...}, component: MyComponent }.`,\n );\n }\n\n get fieldsForActiveTab(): NestedFieldConfig[] {\n const active = this.activeSubTabConfig ?? this.activeTabConfig;\n if (active?.moduleName) return [];\n const rawFields = active ? active.fields || [] : (this.config?.tabs || []).flatMap(t => t.fields || []);\n const currentValues = this.formValues();\n\n return rawFields.filter(field => this.isFieldVisible(field, currentValues));\n }\n\n /**\n * Whether a field renders. Precedence lives in `RulesEvaluationService`, which is also\n * what `syncHiddenFieldState` asks — so what is on screen and what counts toward validity\n * cannot drift apart.\n */\n private isFieldVisible(field: NestedFieldConfig, values: Record<string, unknown>): boolean {\n return this.rulesEvaluation.isFieldVisible(this.ruleResult(), field, this.namesOf(field), values);\n }\n\n /**\n * Entity-level permissions for the current roles.\n *\n * Cached rather than recomputed: this is read from the template several times per change\n * detection pass, and a fresh object each time is both wasted allocation and a new\n * identity for anything comparing by reference. Invalidated in `ngOnChanges` when\n * `config` or `userRoles` change, which are its only inputs.\n */\n get permissions(): ReturnType<RbacService['getPermissions']> {\n return (this.permissionsCache ??= this.rbacService.getPermissions(this.config, this.userRoles));\n }\n\n private permissionsCache: ReturnType<RbacService['getPermissions']> | null = null;\n\n /**\n * Whether the current roles may see this record at all.\n *\n * `permissions.view` used to be computed and thrown away — a user whose roles failed it\n * still received the complete form with every value in the DOM. It is honoured now.\n *\n * As with masking, this is presentational: it stops the browser rendering data, it does\n * not stop the data reaching the browser. Authorize on the server.\n */\n get canView(): boolean {\n return this.permissions.canView;\n }\n\n /**\n * Whether the current roles may delete this record.\n *\n * The library ships no delete affordance, so this is surfaced for the consumer to gate\n * their own — exposed rather than dropped, because a permission the schema declares\n * should be answerable.\n */\n get canDelete(): boolean {\n return this.permissions.canDelete;\n }\n\n get canSubmit(): boolean {\n return this.canView && this.permissions.canEdit && !this.readonly;\n }\n\n /**\n * Errors raised by `validation` rules, keyed by the target they point at.\n *\n * A rule can declare the record invalid independently of Angular's validators, so form\n * validity alone is not the whole picture. `DynamicRecordFormComponent.saveSection()`\n * has always honoured these; `submit()` did not, which meant the same rule blocked one\n * save path and merely painted a banner on the other — and anything wiring\n * `(formSubmit)` to persistence wrote records the rules engine had already rejected.\n */\n get ruleValidationErrors(): Record<string, string> {\n return this.ruleResult().validationErrors;\n }\n\n /** True when a `validation` rule is currently blocking submission. */\n get hasRuleErrors(): boolean {\n return Object.keys(this.ruleValidationErrors).length > 0;\n }\n\n /**\n * True while an async validator is still running.\n *\n * Angular reports a control with an outstanding async check as `pending`, and `invalid` is\n * false until it settles — so without this a form could be submitted in the gap before a\n * uniqueness check came back.\n */\n get isValidating(): boolean {\n return this.form.pending;\n }\n\n /**\n * Whether a submit would be refused. The guard `submit()` checks — not the button's state.\n *\n * See `submitDisabled` for why those are no longer the same question.\n */\n get submitBlocked(): boolean {\n return this.form.invalid || this.form.pending || this.hasRuleErrors;\n }\n\n /**\n * Whether the Save button is unavailable.\n *\n * This used to be `submitBlocked`, so an invalid form greyed Save out — and a greyed button\n * is the worst possible answer to \"why can't I save?\". It cannot be clicked, so there is no\n * moment at which the form gets to say which field is at fault or which tab it is on; the\n * user is left comparing a disabled button against a form that looks, to them, filled in.\n * On a tabbed form the offending field is usually not even on screen.\n *\n * Save now stays available while the form is merely invalid. Clicking it still saves\n * nothing — `submit()` checks `submitBlocked` and refuses — but the refusal is where the\n * error summary, the tab badges and the jump to the first bad field come from, so pressing\n * Save produces an explanation instead of silence.\n *\n * What is still disabled is what a *retry cannot fix*: a save already in flight, and an\n * async validator whose answer has not come back. Those are moments where the right answer\n * is genuinely \"wait\", and a button that accepts a click would be lying.\n */\n get submitDisabled(): boolean {\n return this.isSaving() || this.loading || this.form.pending;\n }\n\n ngOnInit(): void {\n this.selectionSub = this.entityRefSelection.selection$.subscribe(({ fieldId, option }) => {\n this.runAutoPatch(fieldId, option?.record);\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['config'] || changes['userRoles']) {\n this.permissionsCache = null;\n }\n if (changes['config'] && this.rawConfig) {\n // Configs arrive as plain JSON from storage or an API, where TypeScript cannot enforce\n // the option shape. Normalise here, at the library boundary, so everything downstream\n // can rely on an option being a LocalizedText. Returns the same object when it already\n // is, so a well-formed config costs nothing.\n // Kept in a field of our own rather than written back to the @Input. Reassigning an\n // input works, but it surprises a parent that holds the same object — and a parent\n // using OnPush or signals would not see the replacement anyway.\n this.normalizedConfig = normalizeConfigOptions(this.config);\n }\n if (changes['config'] || changes['initialData']) {\n this.buildForm();\n\n // Clear *before* the guard below, not after it.\n //\n // The reset used to sit behind `if (visibleTabs.length === 0) return`, so a swap that\n // arrived while no tab was visible — a config still being applied, or every tab hidden\n // by a rule at that instant — skipped it entirely and the previous record's tab\n // survived into the next one. Clearing is unconditional and cheap, and safe on its own\n // because `activeTabConfig` already falls back to the first visible tab when nothing\n // is selected. Selecting the tab is what needs tabs to exist; forgetting the old one\n // does not.\n if (changes['config'] || this.isRecordSwap(changes['initialData'])) {\n this.activeTab.set('');\n this.activeSubTab.set('');\n }\n\n if (this.visibleTabs.length === 0) return;\n\n // The first tab used to be chosen only when no tab was active yet, and nothing ever\n // cleared `activeTab` — so a form that stays mounted while `initialData` is swapped\n // opened the next record on the tab the previous one was left on. The demo escaped it\n // by destroying the form between records; a host that keeps it mounted did not.\n //\n // Resetting here is consistent with what already happens: `buildForm` assigns a brand\n // new FormGroup, so a changed `initialData` has already discarded every control and\n // all validation state. The tab was the one thing pretending nothing had changed.\n if (!this.activeTab()) {\n // No focus steal: the panel gains focus when a *user* picks a tab, not when a host\n // swaps the record underneath them.\n this.setActiveTab(this.visibleTabs[0].id, { focusPanel: false });\n }\n }\n }\n\n /**\n * Whether an `initialData` change represents loading a different record.\n *\n * Not every change does. A template binding like `[initialData]=\"record() || {}\"` yields a\n * fresh object literal on each evaluation, so `ngOnChanges` fires with two empty objects\n * and nothing has actually been loaded — resetting there would drag someone back to the\n * first tab while they were filling in a new record on the third.\n */\n private isRecordSwap(change: SimpleChange | undefined): boolean {\n if (!change || change.isFirstChange()) return false;\n const empty = (v: unknown): boolean =>\n v === null || v === undefined || (typeof v === 'object' && Object.keys(v as object).length === 0);\n return !(empty(change.previousValue) && empty(change.currentValue));\n }\n\n ngOnDestroy(): void {\n this.valueSub?.unsubscribe();\n this.statusSub?.unsubscribe();\n this.selectionSub?.unsubscribe();\n }\n\n /**\n * `focusPanel: false` is for a caller that is about to focus something more specific.\n *\n * Activating a tab moves focus into its panel, which is right for a keyboard user pressing\n * a tab. A quick-jump also switches tabs, but then focuses the field it was aiming at — and\n * the panel focus runs on `requestAnimationFrame`, after `afterNextRender`, so it landed\n * second and took the focus back every time. Saying so is better than out-timing it.\n */\n setActiveTab(tabId: string, options?: { focusPanel?: boolean }): void {\n const changed = this.activeTab() !== tabId;\n if (changed) this.activeTabChange.emit(tabId);\n this.activeTab.set(tabId);\n if (changed && options?.focusPanel !== false) this.focusActivePanel();\n const parent = findTab(this.tabs, tabId);\n if (parent?.children?.length) {\n this.activeSubTab.set(parent.children[0].id);\n } else {\n this.activeSubTab.set('');\n }\n }\n\n setActiveSubTab(subTabId: string, options?: { focusPanel?: boolean }): void {\n const changed = this.activeSubTab() !== subTabId;\n this.activeSubTab.set(subTabId);\n if (changed && options?.focusPanel !== false) this.focusActivePanel();\n }\n\n getFieldSpan(field: NestedFieldConfig): string {\n const span = field.colSpan ?? (this.layout === 'auto' ? (AUTO_COL_SPAN[field.type] ?? 12) : 12);\n return `span ${Math.min(12, Math.max(1, span))}`;\n }\n\n // ─── Validation recovery ──────────────────────────────────────────────────\n\n /**\n * Set by a submit that validation refused, cleared by one that went through.\n *\n * Gates the error summary rather than `form.invalid` doing it: a form opened on an empty\n * required field is invalid from the first render, and leading with a block of red before\n * the user has typed anything is an accusation, not help. The summary is the answer to\n * \"why did Save do nothing\", so it appears when Save does nothing.\n */\n readonly submitAttempted = signal(false);\n\n /**\n * Every rendered field whose control is currently invalid, with the tab it lives on.\n *\n * Read by the tab badges, the error summary and the jump, so all three agree on what\n * counts. Hidden fields are excluded because `syncHiddenFieldState` disables them and a\n * disabled control is not part of validity — pointing the user at one would send them to a\n * field that is not on screen, or worse, switch tabs to show them nothing.\n *\n * Cached per change-detection pass. The walk calls `getControl` once per field and that\n * falls back to a recursive search of the whole form; the template reads this three times\n * for the summary and once per tab for the badges, so recomputing it each time turns one\n * traversal into a dozen on every keystroke. `form.statusChanges` is the only thing that\n * can alter the answer, and it already runs `markForCheck` — dropping the cache there keeps\n * it honest without a second subscription.\n */\n invalidFields(): InvalidField[] {\n if (this.invalidFieldsCache) return this.invalidFieldsCache;\n\n const out: InvalidField[] = [];\n\n /*\n * Descends into `group` children rather than stopping at the container.\n *\n * A `FormGroup` is invalid whenever any descendant is, so reporting the container said\n * \"Contacts is invalid\" and left the user to open it and hunt. The offending leaf is\n * both the useful answer and the one `jumpToField` can actually move focus to.\n *\n * An `array` is reported as itself: its rows are built and destroyed at runtime, so\n * there is no configured child to name and nothing stable to jump to.\n */\n const collectField = (field: NestedFieldConfig, tab: NestedTabConfig, parentId?: string) => {\n const control = this.getControl(field.id, tab.id);\n if (!control || control.disabled || control.valid || control.pending) return;\n\n if (field.type === 'group' && field.children?.length) {\n for (const child of field.children) collectField(child, tab, parentId);\n return;\n }\n\n // The same message the field renders under itself — see `resolveForField`. Saying\n // only *which* field is wrong leaves the user to go and look at each one; saying what\n // is wrong with it is usually enough to fix it without leaving the summary.\n const message = this.messages.resolveForField(control.errors, this.language, field.type);\n out.push(\n parentId\n ? { field, message, tabId: parentId, subTabId: tab.id }\n : { field, message, tabId: tab.id },\n );\n };\n\n const collect = (tab: NestedTabConfig, parentId?: string) => {\n for (const field of tab.fields ?? []) collectField(field, tab, parentId);\n for (const child of tab.children ?? []) collect(child, parentId ?? tab.id);\n };\n for (const tab of this.visibleTabs) collect(tab);\n\n return (this.invalidFieldsCache = out);\n }\n\n private invalidFieldsCache?: InvalidField[];\n\n /** How many invalid fields sit on a tab — its own and its sub-tabs'. */\n tabErrorCount(tab: NestedTabConfig): number {\n if (!this.submitAttempted()) return 0;\n return this.invalidFields().filter(entry => entry.tabId === tab.id).length;\n }\n\n /** The same count for a sub-tab, which is addressed by its own id rather than its parent's. */\n subTabErrorCount(subTab: NestedTabConfig): number {\n if (!this.submitAttempted()) return 0;\n return this.invalidFields().filter(entry => entry.subTabId === subTab.id).length;\n }\n\n /**\n * Switch to the tab holding `fieldId`, scroll it into view, and move focus onto it.\n *\n * `afterNextRender` rather than a timer: the panel the field lives in is rendered by the\n * change detection this call is part of, so the element does not exist yet — and a timeout\n * is both a guess at how long that takes and something that keeps running after the\n * component is destroyed. The query is scoped to this component's own element, so the\n * library never reaches for the global `document`.\n */\n jumpToField(fieldId: string): void {\n const location = this.invalidFields().find(entry => entry.field.id === fieldId) ?? this.locateField(fieldId);\n if (!location) return;\n\n // The panel must not take focus back — this jump is going to focus the field itself.\n this.setActiveTab(location.tabId, { focusPanel: false });\n // `setActiveTab` resets to a tab's first child, so the sub-tab is selected after it.\n if (location.subTabId) this.setActiveSubTab(location.subTabId, { focusPanel: false });\n\n afterNextRender(\n () => {\n // The id comes from config, so it never goes into a selector string: no escaping to\n // get wrong, and no need for `CSS.escape`, which jsdom does not provide.\n const wanted = `field-container-${fieldId}`;\n const el = Array.from(this.host.nativeElement.querySelectorAll<HTMLElement>('[id^=\"field-container-\"]')).find(\n slot => slot.id === wanted,\n );\n if (!el) return;\n el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n // The slot carries tabindex=\"-1\", so this actually moves focus rather than only\n // scrolling and leaving focus behind on the link that was clicked.\n el.focus();\n },\n { injector: this.injector },\n );\n }\n\n /**\n * Which tab (and sub-tab) holds a field.\n *\n * Descends into `group`/`array` children: this compared top-level fields only, so \"jump to\n * the first invalid field\" found nothing for a nested one and silently did nothing. Only\n * sub-tabs one level deep are named, because that is what the tab strip can select —\n * anything deeper resolves to the ancestor it renders under.\n */\n private locateField(fieldId: string): { tabId: string; subTabId?: string } | null {\n const holds = (fields: NestedFieldConfig[] | undefined): boolean =>\n (fields ?? []).some(f => f?.id === fieldId || holds(f?.children));\n\n const search = (tabs: NestedTabConfig[] | undefined, tabId?: string, subTabId?: string):\n | { tabId: string; subTabId?: string }\n | null => {\n for (const tab of tabs ?? []) {\n if (!tab?.id) continue;\n const at = tabId ?? tab.id;\n const sub = tabId ? (subTabId ?? tab.id) : undefined;\n if (holds(tab.fields)) return sub ? { tabId: at, subTabId: sub } : { tabId: at };\n const found = search(tab.children, at, sub);\n if (found) return found;\n }\n return null;\n };\n\n return search(this.tabs);\n }\n\n // ─── criticalField locking ────────────────────────────────────────────────\n\n /** A critical field stays read-only until the user deliberately unlocks it. */\n isFieldLocked(field: NestedFieldConfig): boolean {\n return !!field.criticalField && !this.unlockedFields().has(field.id);\n }\n\n /**\n * Whether this field renders read-only, from any of the four reasons: the whole form,\n * the field's own flag, a caller-supplied `readOnlyFields` entry, or a criticalField lock.\n */\n isFieldReadonly(field: NestedFieldConfig): boolean {\n return (\n this.readonly ||\n // `permissions.edit` gated the Save button and nothing else, so a role without edit\n // rights received a fully editable form: it could type into every field, and only\n // discovered the record was not theirs to change when no Save button appeared. The\n // permission means the record may not be edited, so the fields say so.\n !this.permissions.canEdit ||\n !!field.readonly ||\n this.readOnlyFields.includes(field.id) ||\n this.isFieldLocked(field)\n );\n }\n\n toggleFieldLock(field: NestedFieldConfig): void {\n // Unlocking is an edit. Without the permission check a viewer could open the lock on a\n // critical field, which is the one control that exists to make editing deliberate.\n if (!field.criticalField || this.readonly || !this.permissions.canEdit) return;\n const next = new Set(this.unlockedFields());\n if (next.has(field.id)) next.delete(field.id);\n else next.add(field.id);\n this.unlockedFields.set(next);\n }\n\n /**\n * A field's label in the form's language, falling back to its id.\n *\n * The fallback matters wherever the label stands alone rather than beside its control: an\n * error-summary chip or a critical-change banner naming a field with no label for this\n * language would otherwise be blank, and a blank chip is worse than a raw id.\n */\n resolveFieldLabel(field: NestedFieldConfig): string {\n return resolveLabel(field.label, this.language) || field.id;\n }\n\n /**\n * The changed critical fields as one comma-separated string.\n *\n * Joined here rather than looped in the template because the banner is a sentence with the\n * list inside it, and a sentence has to reach `UI_TEXT` whole — a translation moves the\n * list somewhere else in the clause.\n */\n changedCriticalFieldLabels(): string {\n return this.changedCriticalFields()\n .map(field => this.resolveFieldLabel(field))\n .join(', ');\n }\n\n // ─── Form construction ────────────────────────────────────────────────────\n\n private buildForm(): void {\n if (!this.config) return;\n this.form = this.structure.buildForm(this.config);\n // A rebuild replaces every control, and the scope index is keyed by config identity.\n this.scopeCache = undefined;\n this.warnAmbiguousRuleReferences();\n\n if (this.initialData) {\n this.patchForm(this.upgradeRecord(this.initialData));\n }\n\n const initialFlattened = this.flattenFormValues();\n this.formValues.set(initialFlattened);\n this.previousValues = { ...initialFlattened };\n this.sessionBaseline.set({ ...initialFlattened });\n this.unlockedFields.set(new Set<string>());\n this.syncHiddenFieldState(initialFlattened);\n\n if (this.preview) {\n // Show what an array field looks like rather than an empty slot, then freeze.\n for (const field of this.allFields()) {\n if (field.type !== 'array') continue;\n const array = this.getArrayControl(field.id);\n if (array && array.length === 0) array.push(this.buildArrayRow(field, undefined));\n }\n this.form.disable({ emitEvent: false });\n }\n\n // Rebuilding must not stack subscriptions on successive config/data changes.\n this.valueSub?.unsubscribe();\n const changes$ =\n this.changeDebounceMs > 0 ? this.form.valueChanges.pipe(debounceTime(this.changeDebounceMs)) : this.form.valueChanges;\n // Validity is not value: an async validator settling flips `pending` and then `invalid`\n // with no value change and no template event, so under OnPush the Save button would\n // never re-enable. submitBlocked reads form.pending and form.invalid, so this is what\n // keeps it honest.\n this.statusSub?.unsubscribe();\n // A rebuild replaces every control, so anything cached against the old ones is stale.\n this.invalidFieldsCache = undefined;\n this.statusSub = this.form.statusChanges.subscribe(() => {\n // The only thing that can change which fields are invalid — see `invalidFields`.\n this.invalidFieldsCache = undefined;\n this.cdr.markForCheck();\n });\n\n this.valueSub = changes$.subscribe(() => {\n const flattened = this.flattenFormValues();\n this.formValues.set(flattened);\n this.runPatchOnTrue(flattened);\n this.syncHiddenFieldState(flattened);\n this.previousValues = { ...flattened };\n this.formChange.emit(this.extractRecord());\n });\n }\n\n /**\n * The `FormArray` behind an `array` field, for callers that manage rows themselves —\n * the record editor's inline row drawer.\n */\n getArrayControl(fieldId: string, tabId?: string): FormArray | null {\n const ctrl = this.getControl(fieldId, tabId);\n return ctrl instanceof FormArray ? ctrl : null;\n }\n\n /**\n * Build one detached row for an `array` field, with the field's own validators applied.\n * Exposed so a row can be edited outside the form and pushed on save.\n */\n createArrayRow(field: NestedFieldConfig, value?: unknown): AbstractControl {\n return this.buildArrayRow(field, value);\n }\n\n private buildArrayRow(field: NestedFieldConfig | undefined, item: unknown): AbstractControl {\n return this.structure.buildArrayRow(field, item);\n }\n\n /**\n * Mark every control touched, then re-check the field components.\n *\n * They are OnPush and `touched` is flipped from outside their own template, so the second\n * half is what makes the error messages actually appear.\n */\n private markAllTouched(): void {\n this.form.markAllAsTouched();\n this.fieldHosts?.forEach(host => host.refresh());\n }\n\n /**\n * Bring a record up to the config's `version` before it reaches the form.\n *\n * Done here because this is the one place a record enters the renderer, so a consumer\n * cannot forget it. Migration is a no-op unless the consumer registered steps *and* the\n * record is behind — an unstamped record is deliberately left alone (see `migrateRecord`).\n *\n * A missing or broken step throws from core. That is not swallowed: rendering a\n * half-understood record would write it back in a shape matching neither schema.\n */\n private upgradeRecord(data: Record<string, any>): Record<string, any> {\n if (!this.migrations.length || !this.config) return data;\n\n const result = migrateRecord(data, this.config, this.migrations);\n if (result.applied.length && isDevMode()) {\n console.info(\n `[ngx-dynamic-entity] Migrated a \"${this.config.entity}\" record from config version ` +\n `${result.from} to ${result.to} (steps: ${result.applied.join(', ')}).`,\n );\n }\n return result.record;\n }\n\n private patchForm(data: Record<string, any>): void {\n if (!data || !this.form || !this.config) return;\n const fieldsById = new Map(this.allFields().map(f => [f.id, f]));\n const unconsumed = this.structure.patchForm(this.form, this.config, data, fieldsById);\n this.warnUnconsumedInitialData(unconsumed);\n }\n\n /**\n * A record is nested by tab id (`{ tabId: { fieldId: value } }`) unless the tab sets\n * `flatData: true`. Handing a flat record to a nested tab finds nothing, so the fields\n * stay empty — with no error and no clue. That silent miss is the most expensive way to\n * lose an hour with this library, so name it in dev builds.\n *\n * Which keys were missed is `FormStructureService`'s answer; warning once per key per form\n * is this component's, because it is the thing that lives as long as the form does.\n */\n private warnUnconsumedInitialData(keys: readonly string[]): void {\n const fresh = keys.filter(key => !this.warnedUnconsumedKeys.has(key));\n if (!fresh.length) return;\n\n for (const key of fresh) this.warnedUnconsumedKeys.add(key);\n\n const shown = fresh.slice(0, 5).join(', ');\n const more = fresh.length > 5 ? ` (+${fresh.length - 5} more)` : '';\n const plural = fresh.length === 1;\n console.warn(\n `[ngx-dynamic-entity] initialData has top-level ${plural ? 'key' : 'keys'} matching ` +\n `${plural ? 'a field that was' : 'fields that were'} not populated: ${shown}${more}. ` +\n `A record is nested by tab id ({ tabId: { fieldId: value } }) unless the tab sets ` +\n `flatData: true. Either nest the value under its tab id, or set flatData: true on ` +\n `the tab holding ${plural ? 'that field' : 'those fields'}.`,\n );\n }\n\n /** Warn once per key per form instance — patchForm re-runs on every initialData change. */\n private readonly warnedUnconsumedKeys = new Set<string>();\n\n /** Assemble full nested record from per-tab FormGroups, respecting flatData, refererField & arrays. */\n extractRecord(): Record<string, any> {\n return this.structure.extractRecord(this.form, this.config);\n }\n\n /**\n * Warns when a rule names a field id that two scopes define.\n *\n * Field ids are unique per scope, so `address` may exist on both Personal Details and Work\n * Details — but a rule carries a bare id and no scope, so it cannot say which one it means.\n * `flattenFormValues` keys by bare id, so one of the two silently wins and the rule reads\n * whichever landed there.\n *\n * `validateConfig({ rules })` catches this statically. The check here remains because\n * consumers that never call the validator still get a signal in development.\n */\n private warnAmbiguousRuleReferences(): void {\n if (!isDevMode() || !this.rules?.length || !this.config) return;\n\n const ambiguous = ambiguousFieldIds(this.config);\n if (ambiguous.size === 0) return;\n\n const referenced = new Set<string>();\n for (const rule of this.rules) {\n if (rule.fieldId) referenced.add(rule.fieldId);\n for (const condition of rule.conditions ?? []) {\n if (condition.compareToField) referenced.add(condition.compareToField);\n }\n for (const target of rule.targets ?? []) {\n if (target.type === 'field' && target.id) referenced.add(target.id);\n }\n }\n\n for (const raw of referenced) {\n const parsed = parseFieldRef(raw);\n if (parsed.kind === 'ref') continue;\n const id = parsed.value;\n const scopes = ambiguous.get(id);\n if (!scopes || this.warnedAmbiguousIds.has(id)) continue;\n this.warnedAmbiguousIds.add(id);\n console.warn(\n `[ngx-dynamic-entity] A rule references field \"${id}\", which is defined in ${scopes.join(' and ')}. ` +\n `A bare id cannot say which one is meant, so the rule will read whichever the form finds first. ` +\n `Name it by path instead, as [${scopes[0]}.${id}].`,\n );\n }\n }\n\n /**\n * Ids already warned about, per component instance.\n *\n * This was `private static`, so it was module-global mutable state that nothing ever\n * cleared: under SSR every render of every form in the process accumulated into one set\n * that lived as long as the server did, and the first request to render a config\n * suppressed the warning for every request after it. Per instance, the warning is once per\n * form — which is what \"warn once\" was meant to mean.\n */\n private readonly warnedAmbiguousIds = new Set<string>();\n\n /**\n * The value map rules and `showWhen` are evaluated against.\n *\n * Every field appears under two keys: its bare id, and its `refererField` path wrapped in brackets.\n * The bare id is what every config written so far uses and is kept exactly as it was — but\n * ids are unique per scope, so when two scopes define one the last field walked wins and\n * the rule reads whichever that is. `[personal.address]` names one field and cannot be\n * ambiguous, which is why a rule that has to distinguish them uses the ref.\n *\n * Both live in one flat map on purpose: `evaluateFormRules` takes a `Record<string,\n * unknown>` and needs no knowledge of refs at all — the extra keys simply resolve.\n */\n /**\n * Every name a rule may address this field by.\n *\n * A rule target is either a bare field id — how every config so far addresses a field — or\n * a bracketed path, which is the only way to name one of two fields that share an id. Both\n * have to match, or a rule written either way would fail to hide what it targeted.\n *\n * The path comes last, and `syncHiddenFieldState` relies on that: it uses the last entry\n * as the field's address when deciding whether a hidden container already covers it.\n */\n private namesOf(field: NestedFieldConfig): readonly string[] {\n const path = field.refererField ?? this.pathFor(field);\n return path ? [field.id, toRefToken(path)] : [field.id];\n }\n\n /**\n * The field's dotted address, unbracketed.\n *\n * The positional path rather than an authored `refererField`: this is compared as a prefix\n * to decide whether a hidden container already covers a field, and containment is a fact\n * about where the field *is*. A `refererField` is a binding override — it says where the\n * value goes, not which group renders it.\n */\n private addressOf(field: NestedFieldConfig): string {\n return this.pathFor(field) ?? field.id;\n }\n\n /** The field's declared path, or the one its position implies when it carries none. */\n private pathFor(field: NestedFieldConfig): string | null {\n const entry = this.scopeEntryFor(field);\n return entry ? fieldRefFor(entry.scope, field.id) : null;\n }\n\n /**\n * Every field in the config with the scope its value is stored under, cached per config.\n *\n * `collectFieldScopes` walks the whole tree. It was called once per field from `pathFor`,\n * which `namesField` calls, which the render filter calls for every field on the active\n * tab — a quadratic walk on every change-detection pass. Keyed by config identity, so a\n * new config invalidates it without an explicit lifecycle hook to forget.\n */\n private fieldScopes(): FieldScopeEntry[] {\n if (this.scopeCache?.config !== this.config) {\n const entries = collectFieldScopes(this.config);\n this.scopeCache = {\n config: this.config,\n entries,\n byField: new Map(entries.map(entry => [entry.field, entry])),\n };\n }\n return this.scopeCache.entries;\n }\n\n private scopeEntryFor(field: NestedFieldConfig): FieldScopeEntry | undefined {\n this.fieldScopes();\n return this.scopeCache?.byField.get(field);\n }\n\n private scopeCache?: {\n config: EntityFormConfig | null | undefined;\n entries: FieldScopeEntry[];\n byField: Map<NestedFieldConfig, FieldScopeEntry>;\n };\n\n /**\n * The control a scope entry addresses, named by path rather than by bare id.\n *\n * `getControl(field.id)` with no tab falls through to a first-match recursive search of the\n * whole form, so with `address` on two tabs, hiding one disabled the other. The control\n * tree mirrors the scope path exactly — `buildTabControls` nests by tab id and\n * `buildFieldControl` nests a `group` under its own id — so a `[path]` ref resolves through\n * `form.get()` on `getControl`'s first branch and names exactly one control.\n *\n * A field inside an `array` has no static path: its controls live in `FormArray` rows built\n * per row. `form.get()` returns null for those and they are left alone, which is correct —\n * a row's controls are created and destroyed with the row.\n */\n private controlForEntry(entry: FieldScopeEntry): AbstractControl | null {\n return this.getControl(toRefToken(fieldRefFor(entry.scope, entry.field.id)));\n }\n\n\n\n private flattenFormValues(): Record<string, any> {\n const out: Record<string, any> = {};\n for (const entry of collectFieldScopes(this.config)) {\n const field = entry.field;\n if (!field?.id) continue;\n const ctrl = this.getControl(field.id, entry.scope.split('.').pop());\n if (!ctrl) continue;\n out[field.id] = ctrl.value;\n out[toRefToken(refOf(field, entry.scope))] = ctrl.value;\n }\n return out;\n }\n\n // ─── autoPatch / patchOnTrue ──────────────────────────────────────────────\n\n /**\n * `autoPatch` — copy mapped fields out of the record the user just selected in an\n * entity-ref field into the configured target tab's controls.\n */\n private runAutoPatch(fieldId: string, record: Record<string, unknown> | undefined): void {\n if (!record) return;\n const field = this.allFields().find(f => f.id === fieldId);\n const autoPatch = field?.autoPatch;\n if (!autoPatch) return;\n\n const patch = applyAutoPatch(autoPatch, record);\n for (const [targetId, value] of Object.entries(patch)) {\n const control = this.resolveTargetControl(autoPatch, targetId);\n control?.patchValue(value);\n }\n // Readonly targets interpolate `control.value` under OnPush. `detectChanges` on the\n // hosted component flushes that write immediately — `markForCheck` waits for a later\n // tick that a Playwright selection never schedules.\n this.fieldHosts?.forEach(host => host.refresh());\n }\n\n /**\n * `patchOnTrue` — when a boolean/checkbox field transitions to `true`,\n * copy `from` → `to` within the current record.\n */\n private runPatchOnTrue(values: Record<string, any>): void {\n for (const field of this.allFields()) {\n const mappings = field.patchOnTrue;\n if (!mappings?.length) continue;\n\n const wasTrue = this.previousValues[field.id] === true;\n const isTrue = values[field.id] === true;\n if (!isTrue || wasTrue) continue;\n\n const patch = applyPatchOnTrue(mappings, values);\n for (const [targetId, value] of Object.entries(patch)) {\n this.getControl(targetId)?.patchValue(value, { emitEvent: false });\n }\n }\n }\n\n /**\n * Prefer a control declared on the configured target tab; fall back to a top-level control.\n *\n * \"Declared on the tab\" now means anywhere under it, sub-tabs and `group` children\n * included. It meant the tab's own top-level fields only, so an `autoPatch` mapping onto a\n * field inside a group resolved to `null` and copied nothing, silently.\n */\n private resolveTargetControl(autoPatch: AutoPatchConfig, targetId: string): AbstractControl | null {\n const tab = findTab(this.tabs, autoPatch.targetTab);\n if (!tab) return this.getControl(targetId, autoPatch.targetTab);\n\n const entry = fieldsUnderTab(this.config, autoPatch.targetTab).find(e => {\n if (!e.field?.id) return false;\n const parsed = parseFieldRef(targetId);\n return parsed.kind === 'ref'\n ? fieldRefFor(e.scope, e.field.id) === parsed.value\n : e.field.id === parsed.value;\n });\n if (!entry) return null;\n return this.controlForEntry(entry);\n }\n\n // ─── Helpers ──────────────────────────────────────────────────────────────\n\n /**\n * Keep a hidden field's control out of form validity — see\n * `RulesEvaluationService.syncHiddenFieldState`, which owns the rule and the reasoning.\n *\n * This supplies the three things it cannot know: which fields exist and in what order\n * (`collectFieldScopes`, parent-first), what each one is called, and which control each\n * one addresses.\n */\n private syncHiddenFieldState(values: Record<string, any>): void {\n if (this.preview) return; // preview freezes the whole form on purpose\n\n this.rulesEvaluation.syncHiddenFieldState(this.fieldScopes(), {\n result: this.ruleResult(),\n values,\n namesOf: field => this.namesOf(field),\n addressOf: field => this.addressOf(field),\n controlFor: entry => this.controlForEntry(entry),\n });\n }\n\n /** Every field in the config, including `group`/`array` children. */\n private allFields(): NestedFieldConfig[] {\n const out: NestedFieldConfig[] = [];\n const walkFields = (fields: NestedFieldConfig[] | undefined) => {\n for (const f of fields ?? []) {\n out.push(f);\n if (f.children?.length) walkFields(f.children);\n }\n };\n const walkTabs = (tabs: NestedTabConfig[] | undefined) => {\n for (const t of tabs ?? []) {\n walkFields(t.fields);\n walkTabs(t.children);\n }\n };\n walkTabs(this.config?.tabs);\n return out;\n }\n\n /** An empty `originalData` counts as \"not supplied\" — fall back to the captured baseline. */\n private baseline(): Record<string, any> {\n const supplied = this.originalData;\n if (supplied && Object.keys(supplied).length > 0) return supplied;\n return this.sessionBaseline();\n }\n\n /**\n * Whether a critical field still holds what it held when the session started.\n *\n * The same question `VALUE_CHANGED` asks, so it is answered by the same comparator rather\n * than by a third one. The local version compared objects through `JSON.stringify`, which\n * is key-order sensitive — two serialisers writing the same option in a different key\n * order made the field read as edited — and had its own idea of which values count as\n * empty. `valuesEqual` is order-independent and treats `null` and `undefined` as the same\n * absence; the empty-string case is kept here, because a cleared text input is not an edit.\n */\n private sameValue(a: unknown, b: unknown): boolean {\n const aEmpty = a === null || a === undefined || a === '';\n const bEmpty = b === null || b === undefined || b === '';\n if (aEmpty && bEmpty) return true;\n return valuesEqual(a, b);\n }\n\n /**\n * Find a control by a bracketed path or a bare field id.\n *\n * Public API, so it stays on the component and delegates — see `FormStructureService`,\n * which owns the resolution rule and is where the behaviour is documented.\n */\n getControl(fieldId: string, currentTabId?: string): AbstractControl | null {\n return this.structure.getControl(this.form, this.config, fieldId, currentTabId);\n }\n\n /**\n * Move focus into the newly shown panel.\n *\n * Activating a tab replaces everything below it while focus stays on the tab button, so a\n * screen-reader or keyboard user is given no indication that the content changed and must\n * tab back through the strip to reach it. Deferred a frame because the panel's contents\n * are rendered by the change detection this call is part of.\n */\n private focusActivePanel(): void {\n if (typeof requestAnimationFrame !== 'function') return;\n requestAnimationFrame(() =>\n // `preventScroll` because this focus exists to tell a screen reader the panel changed,\n // not to move the page. The default scrolls the panel into view, which on a short\n // viewport jumps the layout — enough that a Save button below it moves out from under\n // a tap. The panel sits directly beneath the tab strip and is already on screen.\n this.formPanel?.nativeElement?.focus?.({ preventScroll: true }),\n );\n }\n\n /** Accessible name for the field panel — it is the tabpanel for the active tab. */\n get activeTabLabel(): string {\n const tab = this.activeSubTabConfig ?? this.activeTabConfig;\n return tab ? this.resolveTabLabel(tab) : '';\n }\n\n /**\n * Why a referenced field is flagged.\n *\n * `hasDrift` was written by the builder and read by nothing at runtime, so a field whose\n * source definition had changed since it was linked looked entirely normal to the person\n * filling the form in.\n */\n driftHint(field: NestedFieldConfig): string {\n const source = field.referencedEntityKey ? `\"${field.referencedEntityKey}\"` : 'its source entity';\n return `This field is linked to ${source} and its definition there has changed since it was linked.`;\n }\n\n resolveTabLabel(tab: NestedTabConfig): string {\n return resolveLabel(tab.label, this.language);\n }\n\n async submit(): Promise<void> {\n if (!this.canSubmit || this.submitBlocked) {\n /*\n * A refused save used to mark every control touched and stop there.\n *\n * On a tabbed form that is indistinguishable from a broken button: the errors appear on\n * whichever tabs hold them, the user is looking at a different one, and nothing on\n * screen changes. Three things fix it, and all three are needed — the summary says how\n * many and which, the tab badges say where, and this jump takes the user to the first.\n */\n this.markAllTouched();\n this.submitAttempted.set(true);\n const first = this.invalidFields()[0];\n if (first) this.jumpToField(first.field.id);\n return;\n }\n\n // Whatever the last attempt complained about is settled, so the summary goes away.\n this.submitAttempted.set(false);\n\n const rawData = this.extractRecord();\n let processedData = rawData;\n\n this.isSaving.set(true);\n try {\n // beforeSave can now abort the save: returning false, or throwing, stops it. Previously\n // its return value simply replaced the payload and the submit proceeded regardless, so\n // a hook that wanted to veto — a server-side check, a confirmation — had no way to.\n const hookKey = `${this.config?.entity}:beforeSave`;\n if (this.hookRegistry.has(hookKey)) {\n const result = await this.hookRegistry.run(hookKey, processedData);\n if (result === false) {\n this.saveRejected.emit({ reason: 'beforeSave returned false' });\n return;\n }\n // Anything else is the payload to submit; `undefined` means \"unchanged\".\n if (result !== undefined && result !== true) processedData = result;\n }\n\n this.formSubmit.emit(processedData);\n } catch (err) {\n // A hook that throws aborts the save and reports why, rather than the error escaping\n // into an unhandled rejection with the form left looking as though it saved.\n this.saveRejected.emit({ reason: err instanceof Error ? err.message : String(err), error: err });\n } finally {\n this.isSaving.set(false);\n }\n }\n\n reset(): void {\n this.form.reset();\n if (this.initialData) this.patchForm(this.initialData);\n const values = this.flattenFormValues();\n this.formValues.set(values);\n this.previousValues = { ...values };\n this.unlockedFields.set(new Set<string>());\n // Nothing has been attempted against the restored values, so the old complaint is stale.\n this.submitAttempted.set(false);\n this.formReset.emit();\n }\n}\n","@if (canView) {\n <form [formGroup]=\"form\" (ngSubmit)=\"submit()\" class=\"ngx-form\" [class.ngx-form--readonly]=\"readonly\" novalidate>\n <!-- Error message banner -->\n @if (error) {\n <div class=\"ngx-form__error-banner\" role=\"alert\" data-testid=\"form-error\">{{ error }}</div>\n }\n\n <!--\n Why the last Save did nothing.\n Only after a refused submit — see `submitAttempted`. Each entry jumps to its field,\n switching tabs on the way, because the field is usually not the one on screen.\n -->\n @if (submitAttempted() && invalidFields().length > 0) {\n <div class=\"ngx-form__error-summary\" role=\"alert\" data-testid=\"error-summary\" tabindex=\"-1\">\n <!--\n `error-summary-heading`, not `-title`: the links below are `error-summary-<fieldId>`,\n and a field whose id happens to be `title` would then share a test id with this line.\n The `extensions` entity has exactly such a field.\n -->\n <p class=\"ngx-form__error-summary-title\" data-testid=\"error-summary-heading\">\n {{ ui.text('errorSummaryTitle', language, { count: invalidFields().length }) }}\n </p>\n <ul class=\"ngx-form__error-summary-list\">\n @for (entry of invalidFields(); track entry.field.id) {\n <li>\n <!--\n The field, and what is wrong with it — the same sentence the field renders\n under itself, so the summary is not a second opinion. Naming only the field\n left the user to visit each one to find out what it wanted.\n -->\n <button\n type=\"button\"\n class=\"ngx-form__error-summary-link\"\n [attr.data-testid]=\"'error-summary-' + entry.field.id\"\n (click)=\"jumpToField(entry.field.id)\"\n >\n <span class=\"ngx-form__error-summary-field\">{{ resolveFieldLabel(entry.field) }}</span>\n @if (entry.message) {\n <span class=\"ngx-form__error-summary-reason\">{{ entry.message }}</span>\n }\n </button>\n </li>\n }\n </ul>\n </div>\n }\n\n <!-- Rules Info Banners -->\n @for (infoKey of showInfoBanners ? Object.keys(ruleResult().infoBanners) : []; track infoKey) {\n <div class=\"ngx-form__info-banner\" role=\"status\" [attr.data-testid]=\"'info-banner-' + infoKey\">\n ℹ️ {{ ruleResult().infoBanners[infoKey] }}\n </div>\n }\n\n <!-- Rules Validation Errors & Warnings -->\n @for (errKey of Object.keys(ruleResult().validationErrors); track errKey) {\n <div class=\"ngx-form__error-banner\" role=\"alert\" [attr.data-testid]=\"'rule-error-' + errKey\">\n ⚠️ {{ ruleResult().validationErrors[errKey] }}\n </div>\n }\n @for (warnKey of Object.keys(ruleResult().validationWarnings); track warnKey) {\n <div class=\"ngx-form__warning-banner\" role=\"status\" [attr.data-testid]=\"'rule-warning-' + warnKey\">\n ⚡ {{ ruleResult().validationWarnings[warnKey] }}\n </div>\n }\n\n <!-- Deferred VALUE_CHANGED notice for criticalField edits (vs session baseline) -->\n @if (changedCriticalFields().length > 0) {\n <div class=\"ngx-form__warning-banner\" role=\"status\" data-testid=\"critical-change-banner\">\n {{ ui.text('criticalFieldChanged', language, { fields: changedCriticalFieldLabels() }) }}\n </div>\n }\n\n <!-- Primary Tab bar — only if visible tabs defined -->\n @if (visibleTabs.length > 0) {\n <div class=\"ngx-form__tabs\" role=\"tablist\" data-testid=\"tab-strip\">\n @for (tab of visibleTabs; track tab.id) {\n <button\n type=\"button\"\n class=\"ngx-form__tab\"\n [attr.data-testid]=\"'tab-' + tab.id\"\n [class.ngx-form__tab--active]=\"activeTab() === tab.id\"\n (click)=\"setActiveTab(tab.id)\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab() === tab.id\"\n >\n {{ resolveTabLabel(tab) }}\n <!--\n How many fields on this tab are stopping the save.\n The count is in the accessible name rather than the badge, because \"3\" read out\n after a tab name says nothing about what it counts.\n -->\n @if (tabErrorCount(tab); as errors) {\n <span\n class=\"ngx-form__tab-badge\"\n [attr.data-testid]=\"'tab-errors-' + tab.id\"\n [attr.aria-label]=\"ui.text('tabErrorCount', language, { count: errors })\"\n >{{ errors }}</span\n >\n }\n </button>\n }\n </div>\n }\n\n <!-- Sub-tab bar — only if active tab has sub-tabs -->\n @if (visibleSubTabs.length > 0) {\n <div\n class=\"ngx-form__tabs ngx-form__tabs--sub\"\n role=\"tablist\"\n data-testid=\"subtab-strip\"\n style=\"margin-top: -12px; margin-bottom: 12px; font-size: 13px\"\n >\n @for (subTab of visibleSubTabs; track subTab.id) {\n <button\n type=\"button\"\n class=\"ngx-form__tab ngx-form__tab--sub\"\n [attr.data-testid]=\"'subtab-' + subTab.id\"\n [class.ngx-form__tab--active]=\"activeSubTabConfig?.id === subTab.id\"\n (click)=\"setActiveSubTab(subTab.id)\"\n role=\"tab\"\n [attr.aria-selected]=\"activeSubTabConfig?.id === subTab.id\"\n >\n {{ resolveTabLabel(subTab) }}\n @if (subTabErrorCount(subTab); as errors) {\n <span\n class=\"ngx-form__tab-badge\"\n [attr.data-testid]=\"'subtab-errors-' + subTab.id\"\n [attr.aria-label]=\"ui.text('tabErrorCount', language, { count: errors })\"\n >{{ errors }}</span\n >\n }\n </button>\n }\n </div>\n }\n\n <!--\n One tabpanel per tab, wrapping both branches. Focus moves here on a tab switch, and a\n module tab is still a tab — putting the panel semantics on only the fields branch left\n a module tab with nowhere for focus to land.\n -->\n <div role=\"tabpanel\" tabindex=\"-1\" #formPanel class=\"ngx-form__tabpanel\" [attr.aria-label]=\"activeTabLabel\">\n @if (activeTabModuleComponent) {\n <div class=\"ngx-form__module-panel\" data-testid=\"module-panel\">\n <ng-container\n *ngComponentOutlet=\"activeTabModuleComponent; inputs: (activeSubTabConfig || activeTabConfig)?.moduleInputs\"\n ></ng-container>\n </div>\n } @else {\n <!-- Fields for active tab (Responsive 12-column grid) -->\n <div class=\"ngx-form__panel\" data-testid=\"form-panel\">\n @for (field of fieldsForActiveTab; track field.id) {\n <div\n class=\"ngx-form__field-slot\"\n [style.gridColumn]=\"getFieldSpan(field)\"\n [attr.id]=\"'field-container-' + field.id\"\n tabindex=\"-1\"\n >\n <ngx-dynamic-field\n [field]=\"field\"\n [control]=\"getControl(field.id, (activeSubTabConfig || activeTabConfig)?.id)!\"\n [config]=\"config\"\n [currentTabId]=\"(activeSubTabConfig || activeTabConfig)?.id\"\n [language]=\"language\"\n [readonly]=\"isFieldReadonly(field)\"\n [userRoles]=\"userRoles\"\n />\n @if (field.hasDrift) {\n <!--\n Drift was previously visible only in the builder, so a referenced field whose\n source had changed looked completely normal to the person filling the form in.\n role=\"status\" rather than \"alert\": it is information, not an error.\n -->\n <span\n class=\"ngx-field__drift\"\n role=\"status\"\n [attr.data-testid]=\"'field-' + field.id + '-drift'\"\n [title]=\"driftHint(field)\"\n >⚠ {{ driftHint(field) }}</span\n >\n }\n @if (field.criticalField && !readonly) {\n <button\n type=\"button\"\n class=\"ngx-form__lock\"\n [attr.data-testid]=\"'lock-' + field.id\"\n [attr.aria-pressed]=\"!isFieldLocked(field)\"\n [attr.aria-label]=\"\n ui.text(isFieldLocked(field) ? 'unlockField' : 'lockField', language, {\n field: resolveFieldLabel(field),\n })\n \"\n [title]=\"ui.text(isFieldLocked(field) ? 'criticalFieldUnlockHint' : 'criticalFieldLockHint', language)\"\n (click)=\"toggleFieldLock(field)\"\n >\n {{ isFieldLocked(field) ? '🔒' : '🔓' }}\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Submit button — gated by RBAC and isSaving lock -->\n @if (!readonly && permissions.canEdit) {\n <div class=\"ngx-form__actions\" data-testid=\"form-actions\">\n <button type=\"button\" class=\"ngx-form__reset\" data-testid=\"form-reset\" (click)=\"reset()\" [disabled]=\"isSaving()\">\n {{ ui.text('reset', language) }}\n </button>\n <!--\n Two different \"unavailable\" states, and they are not the same thing.\n\n `disabled` is for what a retry cannot fix — a save in flight, an async check still\n outstanding. `data-blocked` is for validation: the button stays fully operable,\n because pressing it is how the user gets the error summary, but it should not look\n ready either. The stylesheet mutes it without taking the click away.\n\n Deliberately not `aria-disabled`. That announces a control as present-but-inoperable,\n and this one is operable and useful — pressing it raises a `role=\"alert\"` naming\n every field at fault, which is more than a disabled button could ever say. Tooling\n agrees: Playwright refuses to click through `aria-disabled`, and it would be right\n to, because the attribute would be claiming something untrue.\n -->\n <button\n type=\"submit\"\n class=\"ngx-form__submit\"\n data-testid=\"form-submit\"\n [disabled]=\"submitDisabled\"\n [attr.data-blocked]=\"submitBlocked ? '' : null\"\n [title]=\"ui.text('saveShortcutHint', language)\"\n >\n @if (isSaving() || loading) {\n {{ ui.text('saving', language) }}\n } @else {\n {{ ui.text('save', language) }}\n }\n </button>\n </div>\n }\n </form>\n} @else {\n <!-- permissions.view denied: render nothing of the record.\n Presentational only — the server must not send data this user may not see. -->\n <div class=\"ngx-form__denied\" role=\"status\" data-testid=\"form-access-denied\">\n {{ ui.text('accessDenied', language) }}\n </div>\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n Input,\n Output,\n EventEmitter,\n OnChanges,\n SimpleChanges,\n signal,\n computed,\n inject,\n ViewChild,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { AbstractControl, FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport type { EntityFormConfig, FormRule, NestedFieldConfig, NestedTabConfig } from '@dynamic-entity/core';\nimport { findTab, formatDisplayValue, getTabData, resolveLabel } from '@dynamic-entity/core';\nimport { DynamicFormComponent } from './dynamic-form.component';\nimport { DynamicFieldComponent } from './dynamic-field/dynamic-field.component';\nimport { HookRegistryService } from '../services/hook-registry.service';\nimport { RulesEvaluationService } from '../services/rules-evaluation.service';\nimport { RbacService } from '../services/rbac.service';\nimport { UiTextService } from '../services/ui-text.service';\n\n/**\n * Distinguishes \"no tab holds this field\" from \"the field holds undefined\", so the tab walk\n * can keep searching in the first case and stop in the second.\n */\nconst FIELD_NOT_FOUND = Symbol('field-not-found');\n\n/**\n * DynamicRecordFormComponent — comprehensive tabbed record view & edit component.\n * Supports cross-tab rule evaluation, profile header, summary drawer (showOnMinimize),\n * interactive quick-jump links, and baseline modification tracking.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-dynamic-record-form',\n standalone: true,\n imports: [CommonModule, ReactiveFormsModule, DynamicFormComponent, DynamicFieldComponent],\n templateUrl: './dynamic-record-form.component.html',\n /*\n * The record editor's own baseline, for a consumer who imports no stylesheet.\n *\n * Every value reads the token `ngx-dynamic-entity/styles.css` sets, with the previous\n * hard-coded literal as its fallback — so importing that file re-skins this component\n * instead of fighting it. It used to be literals all the way down, and because a component\n * stylesheet is injected after a global one and carries an attribute selector, the\n * stylesheet's whole `.ngx-record-editor__*` section lost every tie and did nothing at all.\n */\n styles: [\n `\n .ngx-record-editor {\n display: flex;\n flex-direction: column;\n gap: var(--ngx-gap, 16px);\n background: var(--ngx-color-surface, #ffffff);\n border: 1px solid var(--ngx-color-border, #e5e7eb);\n border-radius: var(--ngx-radius, 12px);\n padding: 20px;\n }\n .ngx-record-editor__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 14px;\n padding-bottom: var(--ngx-gap-sm, 16px);\n border-bottom: 1px solid var(--ngx-color-border, #f3f4f6);\n }\n .ngx-record-editor__title-group {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n }\n .ngx-record-editor__avatar {\n width: 44px;\n height: 44px;\n border-radius: 50%;\n object-fit: cover;\n background: var(--ngx-color-accent-soft, #e0e7ff);\n color: var(--ngx-color-accent, #4f46e5);\n border: 1px solid var(--ngx-color-border, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n font-size: 17px;\n flex: none;\n }\n .ngx-record-editor__title {\n font-size: 19px;\n font-weight: 700;\n color: var(--ngx-color-text, #111827);\n margin: 0;\n letter-spacing: -0.01em;\n }\n .ngx-record-editor__subtitle {\n font-size: var(--ngx-hint-size, 13px);\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-record-editor__header-toggle {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: var(--ngx-label-size, 13px);\n font-weight: var(--ngx-label-weight, 600);\n color: var(--ngx-color-text, #374151);\n }\n .ngx-record-editor__header-toggle-text {\n font-weight: 600;\n }\n .ngx-record-editor__banner {\n padding: 11px 14px;\n border-radius: var(--ngx-radius-sm, 8px);\n font-size: var(--ngx-font-size, 13px);\n border: 1px solid transparent;\n border-left-width: 3px;\n }\n .ngx-record-editor__banner--info {\n background: var(--ngx-color-info-soft, #eff6ff);\n border-color: var(--ngx-color-border, #dbeafe);\n border-left-color: var(--ngx-color-info, #1d4ed8);\n color: var(--ngx-color-info, #1d4ed8);\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n }\n .ngx-record-editor__banner--error {\n background: var(--ngx-color-error-soft, #fef2f2);\n border-color: var(--ngx-color-border, #fecaca);\n border-left-color: var(--ngx-color-error, #b91c1c);\n color: var(--ngx-color-error, #b91c1c);\n }\n .ngx-record-editor__banner--warning {\n background: var(--ngx-color-warning-soft, #fffbeb);\n border-color: var(--ngx-color-border, #fef3c7);\n border-left-color: var(--ngx-color-warning, #b45309);\n color: var(--ngx-color-warning, #b45309);\n }\n .ngx-record-editor__banner-dismiss {\n background: none;\n border: none;\n cursor: pointer;\n color: inherit;\n font-size: 14px;\n line-height: 1;\n padding: 2px 6px;\n border-radius: 4px;\n }\n .ngx-record-editor__banner-dismiss:hover {\n background: rgba(0, 0, 0, 0.06);\n }\n .ngx-record-editor__section-bar {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n flex-wrap: wrap;\n gap: 8px;\n }\n .ngx-record-editor__section-hint {\n margin-right: auto;\n font-size: var(--ngx-hint-size, 12px);\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-record-editor__rows {\n border: 1px solid var(--ngx-color-border, #f3f4f6);\n border-radius: var(--ngx-radius-sm, 8px);\n padding: 12px 14px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .ngx-record-editor__rows-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n .ngx-record-editor__row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-surface-alt, #f9fafb);\n }\n .ngx-record-editor__row-text {\n flex: 1;\n font-size: var(--ngx-font-size, 13px);\n overflow-wrap: anywhere;\n }\n .ngx-record-editor__row-btn {\n background: var(--ngx-color-surface, none);\n border: 1px solid var(--ngx-color-border, #e5e7eb);\n border-radius: var(--ngx-radius-sm, 6px);\n cursor: pointer;\n font: inherit;\n font-size: var(--ngx-hint-size, 12px);\n font-weight: var(--ngx-label-weight, 600);\n color: inherit;\n padding: 4px 10px;\n }\n .ngx-record-editor__row-btn:hover {\n border-color: var(--ngx-color-accent, #e5e7eb);\n color: var(--ngx-color-accent, inherit);\n }\n .ngx-record-editor__row-empty {\n font-size: var(--ngx-hint-size, 12px);\n color: var(--ngx-color-muted, #6b7280);\n margin: 0;\n }\n .ngx-record-editor__drawer {\n border: 1px solid var(--ngx-color-border, #dbeafe);\n background: var(--ngx-color-surface-alt, #f8fafc);\n border-radius: var(--ngx-radius, 8px);\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n /*\n * Label/value pairs, laid out as pairs. Stacked one per row this cost a full screen to\n * show six values that fit comfortably in two; auto-fit is what packs them, at whatever\n * width the panel happens to have.\n */\n .ngx-record-editor__summary-panel {\n background: var(--ngx-color-surface-alt, #f9fafb);\n border: 1px solid var(--ngx-color-border, #f3f4f6);\n border-radius: var(--ngx-radius, 8px);\n padding: 12px 16px;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));\n gap: 4px var(--ngx-gap, 12px);\n }\n .ngx-record-editor__summary-item {\n display: flex;\n flex-direction: column;\n cursor: pointer;\n padding: 6px 10px;\n border-radius: var(--ngx-radius-sm, 6px);\n min-width: 0;\n transition: background 0.15s;\n }\n .ngx-record-editor__summary-item:hover {\n background: var(--ngx-color-accent-soft, #eff6ff);\n }\n .ngx-record-editor__summary-label {\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--ngx-color-muted, #6b7280);\n font-weight: 600;\n }\n .ngx-record-editor__summary-val {\n font-size: var(--ngx-font-size, 14px);\n font-weight: 600;\n color: var(--ngx-color-text, #1f2937);\n overflow-wrap: anywhere;\n }\n @media (prefers-reduced-motion: reduce) {\n .ngx-record-editor__summary-item {\n transition: none;\n }\n }\n `,\n ],\n})\nexport class DynamicRecordFormComponent implements OnChanges {\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n @Input() config!: EntityFormConfig;\n @Input() rules?: FormRule[];\n @Input() initialData?: Record<string, any>;\n @Input() userRoles: string[] = [];\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() loading: boolean = false;\n @Input() error: string | null = null;\n /** Whole record read-only, regardless of RBAC. Equivalent to the reference's `isReadOnly`. */\n @Input() isReadOnly: boolean = false;\n /** Specific field ids forced read-only while the rest of the record stays editable. */\n @Input() readOnlyFields: string[] = [];\n /** Forwarded verbatim to the hosted form — see `DynamicFormComponent.layout`. */\n @Input() layout: 'stack' | 'auto' = 'stack';\n /**\n * Open the record read-only, with a per-tab \"Edit section\" flow — one tab is edited and\n * validated at a time. This is the framework's `EntityRecordComponent` model and the\n * default here.\n *\n * Set false for a directly editable record with no view/edit distinction.\n */\n @Input() viewMode: boolean = true;\n\n @Output() formSubmit = new EventEmitter<Record<string, any>>();\n @Output() formChange = new EventEmitter<Record<string, any>>();\n @Output() formReset = new EventEmitter<void>();\n /** One tab section was saved. Carries the whole record, plus which tab was edited. */\n @Output() sectionSave = new EventEmitter<{ tabId: string; record: Record<string, any> }>();\n /**\n * A `beforeSave` hook aborted the save — by returning false or throwing.\n *\n * Re-exposed from the embedded `ngx-dynamic-form`, and emitted by `saveSection` too. The\n * inner form already ran the hook and already refused the save, but nothing carried that\n * out to a host binding this component: the veto worked and looked exactly like a Save\n * button that did nothing, which is the failure `saveRejected` exists to prevent.\n */\n @Output() saveRejected = new EventEmitter<{ reason: string; error?: unknown }>();\n\n @ViewChild(DynamicFormComponent) dynamicFormComp?: DynamicFormComponent;\n\n private readonly rulesEvaluation = inject(RulesEvaluationService);\n private readonly rbacService = inject(RbacService);\n private readonly hookRegistry = inject(HookRegistryService);\n\n readonly currentData = signal<Record<string, any>>({});\n readonly originalBaseline = signal<Record<string, any>>({});\n\n /**\n * Info banners the user has dismissed, by field id.\n *\n * The reference's contract: an info banner persists until dismissed, **not** until the\n * value changes. Dismissal is keyed by field so re-triggering a different field's rule\n * still shows. Re-armed when a different record is loaded.\n */\n private readonly dismissed = signal<ReadonlySet<string>>(new Set<string>());\n\n /**\n * Info banners from the rules engine that are still showing.\n *\n * A getter, not a `computed`: the source is `dynamicFormComp`, a ViewChild. A computed\n * evaluated before the view initialises would capture no dependency on the child's\n * `ruleResult` signal and then never recompute. Read per change-detection pass instead.\n */\n get infoBanners(): { fieldId: string; message: string }[] {\n const result = this.dynamicFormComp?.ruleResult();\n const gone = this.dismissed();\n return Object.entries(result?.infoBanners ?? {})\n .filter(([fieldId]) => !gone.has(fieldId))\n .map(([fieldId, message]) => ({ fieldId, message: String(message) }));\n }\n\n dismissInfoBanner(fieldId: string): void {\n this.dismissed.set(new Set(this.dismissed()).add(fieldId));\n }\n\n /**\n * Whether the current roles may edit this record.\n *\n * `userRoles` was declared as an input here and then read by nothing at all — this\n * component computed no permissions of any kind, so the record view was fully editable\n * for every role while the plain form at least hid its Save button. Cached on the same\n * terms as the sibling component: it depends only on `config` and `userRoles`.\n */\n private permissionsCache: ReturnType<RbacService['getPermissions']> | null = null;\n\n get permissions(): ReturnType<RbacService['getPermissions']> {\n return (this.permissionsCache ??= this.rbacService.getPermissions(this.config, this.userRoles));\n }\n\n /** True when nothing in the record may be edited. */\n get recordReadOnly(): boolean {\n return this.readonly || this.isReadOnly || !this.permissions.canEdit;\n }\n\n // ─── Inline array-row editing ───────────────────────────────────────────────\n\n /**\n * A row of an `array` field is edited in a drawer, not inline in the tab panel.\n *\n * The drawer is rendered outside the tab container on purpose: the reference found that\n * building a row's FormGroup inside the tab view races the tab's own initialisation, so\n * the row form is kept detached and only pushed into the FormArray on save.\n */\n readonly inlineRowField = signal<NestedFieldConfig | null>(null);\n readonly inlineRowIndex = signal<number | null>(null);\n inlineRowForm: FormGroup | null = null;\n\n /** `array` fields on the tab currently shown, so the template can list their rows. */\n get arrayFieldsForActiveTab(): NestedFieldConfig[] {\n const tabId = this.activeTabId;\n const tab = tabId ? findTab(this.config?.tabs, tabId) : null;\n return (tab?.fields ?? []).filter(f => f.type === 'array');\n }\n\n /**\n * Rows currently held by an `array` field, read from the record value.\n *\n * Deliberately not read off the child's FormArray: that control only exists once the\n * child has initialised, so rendering from it changed value mid-pass. `currentData` is a\n * signal seeded from `initialData` and kept current by the child's `formChange`.\n */\n rowsOf(field: NestedFieldConfig): Record<string, unknown>[] {\n const tabId = this.activeTabId;\n const tabData = tabId ? getTabData(tabId, this.currentData(), this.config) : null;\n const rows = (tabData as Record<string, unknown> | null)?.[field.id];\n return Array.isArray(rows) ? (rows as Record<string, unknown>[]) : [];\n }\n\n /** One row rendered as text, so the list is readable without opening the drawer. */\n rowSummary(field: NestedFieldConfig, row: Record<string, unknown>): string {\n const value = row ?? {};\n const parts = (field.children ?? [])\n .map(child => value[child.id])\n .filter(v => v !== null && v !== undefined && v !== '')\n .map(v => (typeof v === 'object' ? JSON.stringify(v) : String(v)));\n return parts.length ? parts.join(' · ') : '(empty)';\n }\n\n openAddRow(field: NestedFieldConfig): void {\n if (this.sectionReadOnly) return;\n this.inlineRowField.set(field);\n this.inlineRowIndex.set(null);\n this.inlineRowForm = this.dynamicFormComp?.createArrayRow(field) as FormGroup;\n }\n\n openEditRow(field: NestedFieldConfig, index: number): void {\n if (this.sectionReadOnly) return;\n this.inlineRowField.set(field);\n this.inlineRowIndex.set(index);\n this.inlineRowForm = this.dynamicFormComp?.createArrayRow(field, this.rowsOf(field)[index]) as FormGroup;\n }\n\n cancelRow(): void {\n this.inlineRowField.set(null);\n this.inlineRowIndex.set(null);\n this.inlineRowForm = null;\n }\n\n /** Commit the drawer into the FormArray. Rules re-evaluate off the resulting value change. */\n saveRow(): void {\n const field = this.inlineRowField();\n const form = this.dynamicFormComp;\n if (!field || !form || !this.inlineRowForm) return;\n\n if (this.inlineRowForm.invalid) {\n this.inlineRowForm.markAllAsTouched();\n return;\n }\n\n const array = form.getArrayControl(field.id, this.activeTabId ?? undefined);\n if (!array) return;\n\n const index = this.inlineRowIndex();\n if (index === null) array.push(form.createArrayRow(field, this.inlineRowForm.value));\n else array.at(index).patchValue(this.inlineRowForm.value);\n\n array.updateValueAndValidity();\n this.currentData.set(form.extractRecord());\n this.cancelRow();\n }\n\n deleteRow(field: NestedFieldConfig, index: number): void {\n if (this.sectionReadOnly) return;\n const array = this.dynamicFormComp?.getArrayControl(field.id, this.activeTabId ?? undefined);\n array?.removeAt(index);\n array?.updateValueAndValidity();\n if (this.dynamicFormComp) this.currentData.set(this.dynamicFormComp.extractRecord());\n if (this.inlineRowIndex() === index) this.cancelRow();\n }\n\n // ─── Per-tab section editing ────────────────────────────────────────────────\n\n /**\n * The tab currently open for editing, or null when the record is being viewed.\n *\n * The reference edits one tab section at a time rather than the whole record, and\n * validates only that section on save — a required field on an untouched tab must not\n * block saving the tab you are actually working on.\n */\n readonly editingTabId = signal<string | null>(null);\n\n /**\n * The tab the inner form is showing.\n *\n * Tracked here rather than read off the ViewChild. The child resolves its first tab as\n * part of its own initialisation, so reading it during this component's render changed\n * value mid-pass — an ExpressionChangedAfterItHasBeenChecked error. Seeded from the\n * config and kept in step by the child's `activeTabChange` output.\n */\n private readonly activeTabIdSig = signal<string | null>(null);\n\n get activeTabId(): string | null {\n return this.activeTabIdSig();\n }\n\n onActiveTabChange(tabId: string): void {\n if (this.activeTabIdSig() === tabId) return;\n this.activeTabIdSig.set(tabId);\n // Editing does not follow the user to another tab.\n this.editingTabId.set(null);\n this.cancelRow();\n }\n\n /** First tab a user can see, used to seed the active tab before the child reports one. */\n private firstVisibleTabId(): string | null {\n return this.config?.tabs?.find(t => t.visibility !== false)?.id ?? null;\n }\n\n /** Errors from the last save attempt, by field id. */\n readonly sectionErrors = signal<Record<string, string>>({});\n\n /** Template access to `Object.keys` for iterating the error map. */\n protected readonly Object = Object;\n\n get isEditingActiveTab(): boolean {\n // Without view mode there is no view/edit distinction — everything is always editable.\n if (!this.viewMode) return true;\n return !!this.activeTabId && this.editingTabId() === this.activeTabId;\n }\n\n /** Fields render read-only unless their own tab is the one being edited. */\n get sectionReadOnly(): boolean {\n return this.recordReadOnly || !this.isEditingActiveTab;\n }\n\n editSection(): void {\n if (!this.viewMode || this.recordReadOnly || !this.activeTabId) return;\n this.sectionErrors.set({});\n this.editingTabId.set(this.activeTabId);\n }\n\n /** Discard this section's edits, restoring each field from the session baseline. */\n cancelSection(): void {\n const tabId = this.editingTabId();\n const form = this.dynamicFormComp;\n if (tabId && form) {\n const tab = findTab(this.config?.tabs, tabId);\n const baselineTab = (getTabData(tabId, this.originalBaseline(), this.config) ?? {}) as Record<string, unknown>;\n for (const field of tab?.fields ?? []) {\n const baselineValue = baselineTab[field.id];\n\n // A FormArray cannot be restored with setValue — that demands a value shaped exactly\n // like the current rows. Rebuild it from the baseline rows instead.\n const array = form.getArrayControl(field.id, tabId);\n if (array) {\n array.clear();\n for (const row of Array.isArray(baselineValue) ? baselineValue : []) {\n array.push(form.createArrayRow(field, row));\n }\n array.updateValueAndValidity();\n continue;\n }\n\n form.getControl(field.id, tabId)?.setValue(baselineValue ?? null);\n }\n this.currentData.set(form.extractRecord());\n }\n this.sectionErrors.set({});\n this.editingTabId.set(null);\n }\n\n /**\n * Validate this section only, then emit it. Validation is scoped two ways: Angular\n * validity of the tab's own controls, and rules filtered to this tab — a rule targeting\n * a hidden tab must not block the save (the reference's OV0-968 fix).\n */\n async saveSection(): Promise<void> {\n const tabId = this.editingTabId();\n const form = this.dynamicFormComp;\n if (!tabId || !form) return;\n\n const tab = findTab(this.config?.tabs, tabId);\n const errors: Record<string, string> = {};\n\n for (const field of tab?.fields ?? []) {\n const ctrl = form.getControl(field.id, tabId);\n if (ctrl?.invalid) {\n ctrl.markAsTouched();\n errors[field.id] = `${resolveLabel(field.label, this.language)} is invalid.`;\n }\n }\n\n const scoped = this.rulesEvaluation.filterForTab(this.rules, tabId, this.config);\n const ruleErrors = this.rulesEvaluation.evaluate(scoped, form.formValues(), this.originalBaseline()).validationErrors;\n Object.assign(errors, ruleErrors);\n\n if (Object.keys(errors).length > 0) {\n this.sectionErrors.set(errors);\n return;\n }\n\n this.sectionErrors.set({});\n\n const record = form.extractRecord();\n\n // Only await when there is something to await. An async function runs synchronously up\n // to its first `await`, so this keeps `sectionSave` firing in the same tick for the\n // hosts that register no hook — which is how it has always behaved, and which a host\n // may well depend on. Awaiting an already-resolved promise would defer the emit by a\n // microtask for everybody, to no purpose.\n const hookKey = `${this.config?.entity}:beforeSave`;\n const reviewed = this.hookRegistry.has(hookKey) ? await this.runBeforeSave(record) : record;\n // Vetoed: the section stays open, exactly as the whole-record form stays open, so the\n // user is looking at the values the hook refused rather than at a closed section.\n if (reviewed === null) return;\n\n this.editingTabId.set(null);\n this.currentData.set(reviewed);\n this.sectionSave.emit({ tabId, record: reviewed });\n }\n\n /**\n * Put a record to the entity's `beforeSave` hook.\n *\n * `sectionSave` carries the *whole* record — `extractRecord()`, not the tab's slice — so\n * the same payload reached persistence through two buttons, one of which asked the hook\n * and one of which did not. A hook registered to veto a save is a data-integrity\n * mechanism; having a second route around it made it advisory.\n *\n * @returns the record to emit, or `null` when the hook aborted (already reported).\n */\n private async runBeforeSave(record: Record<string, any>): Promise<Record<string, any> | null> {\n const hookKey = `${this.config?.entity}:beforeSave`;\n // Defensive: `saveSection` checks this before awaiting, but a later caller may not.\n if (!this.hookRegistry.has(hookKey)) return record;\n\n try {\n const result = await this.hookRegistry.run(hookKey, record);\n if (result === false) {\n this.saveRejected.emit({ reason: 'beforeSave returned false' });\n return null;\n }\n // Anything else is the payload to save; `undefined`/`true` mean \"unchanged\".\n return result === undefined || result === true ? record : (result as Record<string, any>);\n } catch (err) {\n this.saveRejected.emit({ reason: err instanceof Error ? err.message : String(err), error: err });\n return null;\n }\n }\n\n /**\n * Seed the session baseline from the loaded record so `VALUE_CHANGED` rules and the\n * modification banner compare against the record as it was opened — not as it was\n * after the first keystroke.\n */\n ngOnChanges(changes: SimpleChanges): void {\n // Permissions depend on these two and nothing else; a stale cache would keep a record\n // editable after a role switch.\n if (changes['config'] || changes['userRoles']) {\n this.permissionsCache = null;\n }\n if (changes['initialData'] || changes['config']) {\n this.originalBaseline.set({ ...(this.initialData ?? {}) });\n this.currentData.set({ ...(this.initialData ?? {}) });\n this.activeTabIdSig.set(this.firstVisibleTabId());\n // A different record is a different set of banners — re-arm them.\n this.dismissed.set(new Set<string>());\n }\n }\n\n get recordTitle(): string {\n if (!this.config) return 'Record';\n return this.config.name ? resolveLabel(this.config.name, this.language) : this.config.entity;\n }\n\n /**\n * What this record is called, as opposed to what kind of thing it is.\n *\n * The header used to show the entity's name twice — \"clients\", with \"Entity: clients\"\n * underneath — so the one question a record header exists to answer, *which* record am I\n * looking at, was the one thing it did not say. The entity keeps the subtitle; this takes\n * the heading.\n *\n * The order is deliberate. `showOnMinimize` is the author saying \"this is what identifies a\n * record\" — it is what the summary panel and the collapsed view already show — so it is\n * asked first. A text or email field is the fallback because those are what a name is\n * stored in; a number or a date is a property of the record, not its identity, and would\n * give a header reading \"42\". When neither exists there is nothing to name it with and the\n * entity label stands in, which is the behaviour this replaced.\n *\n * A masked field is never a candidate. Masking is presentational (see SECURITY.md), but\n * that is exactly why: the whole point is that this role does not get to read the value, and\n * promoting it into the page heading would print in full what every field renders as\n * `XXXXXXXXX`. A record whose only text field is masked keeps the entity label.\n *\n * One pass rather than two filtered ones: this is a getter the header reads on every change\n * detection, and the preferred candidate is usually the first field it meets.\n */\n get recordHeading(): string {\n const named = (field: NestedFieldConfig): string | null => {\n const value = this.fieldValue(field.id);\n if (typeof value !== 'string' && typeof value !== 'number') return null;\n const text = String(value).trim();\n return text.length ? text : null;\n };\n\n let fallback: string | null = null;\n for (const field of this.allFields()) {\n if (field.visibility === false) continue;\n if (this.rbacService.shouldMaskField(field, undefined, this.config, this.userRoles)) continue;\n\n if (field.showOnMinimize) {\n const preferred = named(field);\n if (preferred) return preferred;\n } else if (!fallback && (field.type === 'text' || field.type === 'email')) {\n fallback = named(field);\n }\n }\n return fallback ?? this.recordTitle;\n }\n\n get avatarLetter(): string {\n return (this.recordHeading || 'R').charAt(0).toUpperCase();\n }\n\n // ─── Header fields (isProfileImage / isHeaderToggle) ────────────────────────\n\n /** Every field in the config, at any depth. */\n private allFields(): NestedFieldConfig[] {\n const out: NestedFieldConfig[] = [];\n const walkFields = (fields: NestedFieldConfig[] | undefined) => {\n for (const f of fields ?? []) {\n out.push(f);\n walkFields(f.children);\n }\n };\n const walkTabs = (tabs: NestedTabConfig[] | undefined) => {\n for (const t of tabs ?? []) {\n walkFields(t.fields);\n walkTabs(t.children);\n }\n };\n walkTabs(this.config?.tabs);\n return out;\n }\n\n /** The field flagged `isProfileImage`, rendered as the record avatar. */\n get headerProfileField(): NestedFieldConfig | null {\n return this.allFields().find(f => f.isProfileImage) ?? null;\n }\n\n /** The field flagged `isHeaderToggle`, rendered as a status switch in the header. */\n get headerToggleField(): NestedFieldConfig | null {\n return this.allFields().find(f => f.isHeaderToggle) ?? null;\n }\n\n /** Avatar image URL, when the profile field holds a persisted FileRef. */\n get profileImageUrl(): string | null {\n const field = this.headerProfileField;\n if (!field) return null;\n const value = this.fieldValue(field.id) as { url?: string } | null;\n return value?.url ?? null;\n }\n\n get headerToggleValue(): boolean {\n const field = this.headerToggleField;\n return field ? this.fieldValue(field.id) === true : false;\n }\n\n /**\n * Flip the header toggle. It writes straight to the control rather than going through\n * section editing — the reference treats it as a record-level status switch, not part of\n * any one tab's section.\n */\n toggleHeaderStatus(): void {\n const field = this.headerToggleField;\n if (!field || this.recordReadOnly) return;\n const ctrl = this.controlFor(field.id);\n if (!ctrl) return;\n ctrl.setValue(!this.headerToggleValue);\n if (this.dynamicFormComp) this.currentData.set(this.dynamicFormComp.extractRecord());\n }\n\n /** Locate a field's control wherever it lives, since header fields may be on any tab. */\n private controlFor(fieldId: string): AbstractControl | null {\n return this.dynamicFormComp?.getControl(fieldId) ?? null;\n }\n\n /**\n * A field's current value, read from the record so it is stable during render.\n *\n * Resolved through `getTabData` so it honours exactly the nesting contract the form\n * patches with — `{ tabId: { fieldId } }`, or the record root when the tab sets\n * `flatData`. Reading the record flat instead is not a shortcut: it makes the summary\n * display values the form never loaded, which reads as \"the data is there\" while every\n * control behind it is empty.\n *\n * Walks sub-tabs as well: a summary, header, or profile field may sit on any tab at any\n * depth.\n */\n private fieldValue(fieldId: string): unknown {\n const visit = (tabs: NestedTabConfig[] = []): unknown => {\n for (const tab of tabs) {\n const data = getTabData(tab.id, this.currentData(), this.config) as Record<string, unknown> | null;\n if (data && fieldId in data) return data[fieldId];\n if (tab.children) {\n const found = visit(tab.children);\n if (found !== FIELD_NOT_FOUND) return found;\n }\n }\n return FIELD_NOT_FOUND;\n };\n\n const result = visit(this.config?.tabs);\n return result === FIELD_NOT_FOUND ? undefined : result;\n }\n\n readonly isModified = computed(() => {\n const orig = this.originalBaseline();\n const curr = this.currentData();\n if (!orig || !curr || Object.keys(orig).length === 0) return false;\n return JSON.stringify(orig) !== JSON.stringify(curr);\n });\n\n readonly summaryFields = computed<NestedFieldConfig[]>(() => {\n const fields: NestedFieldConfig[] = [];\n const walkTabs = (tabs: NestedTabConfig[] = []) => {\n for (const t of tabs) {\n for (const f of t.fields ?? []) {\n if (f.showOnMinimize) fields.push(f);\n }\n if (t.children) walkTabs(t.children);\n }\n };\n walkTabs(this.config?.tabs);\n return fields;\n });\n\n onFormChange(data: Record<string, any>): void {\n // Baseline is seeded from `initialData` in ngOnChanges; only fill it here when the\n // record was opened empty (create flow), so the first emitted shape becomes the baseline.\n if (Object.keys(this.originalBaseline()).length === 0) {\n this.originalBaseline.set({ ...data });\n }\n this.currentData.set(data);\n this.formChange.emit(data);\n }\n\n onFormSubmit(data: Record<string, any>): void {\n this.formSubmit.emit(data);\n }\n\n onFormReset(): void {\n this.formReset.emit();\n }\n\n formatFieldLabel(field: NestedFieldConfig): string {\n return resolveLabel(field.label, this.language);\n }\n\n /** \"Add <field> row\" / \"Edit <field> row\" — one key each, because word order moves. */\n rowDrawerTitle(field: NestedFieldConfig): string {\n const key = this.inlineRowIndex() === null ? 'addRowTitle' : 'editRowTitle';\n return this.ui.text(key, this.language, { field: this.formatFieldLabel(field) });\n }\n\n /** Summary values render through the shared core formatter, not a local stringifier. */\n formatFieldValue(field: NestedFieldConfig): string {\n return formatDisplayValue(field.type, field.options, this.fieldValue(field.id), this.language);\n }\n\n /**\n * Finds which tab — and, where the field lives one level down, which sub-tab — owns a\n * field. The walk used to check top-level `fields` only, so every field in a sub-tab was\n * simply not found and the jump did nothing at all.\n */\n\n /**\n * Switches to the tab holding `fieldId`, then scrolls it into view and moves focus to it.\n *\n * Delegated rather than implemented twice. The hosted form grew the same jump when a\n * refused save had to be able to take the user to the first invalid field, and the form is\n * where it belongs: it owns the tab state, the panel that renders the field, and the\n * element the jump is looking for. This is kept as the record editor's public entry point\n * because the summary panel's quick-jump calls it and a host may too.\n */\n jumpToField(fieldId: string): void {\n this.dynamicFormComp?.jumpToField(fieldId);\n }\n}\n","<div class=\"ngx-record-editor\">\n <!-- Record Header -->\n <div class=\"ngx-record-editor__header\">\n <div class=\"ngx-record-editor__title-group\">\n @if (profileImageUrl) {\n <img\n class=\"ngx-record-editor__avatar\"\n data-testid=\"header-profile-image\"\n [src]=\"profileImageUrl\"\n [alt]=\"recordHeading\"\n />\n } @else {\n <div class=\"ngx-record-editor__avatar\" data-testid=\"header-avatar-initial\">\n {{ avatarLetter }}\n </div>\n }\n <div>\n <!--\n The record's own name, with the entity underneath. These were the other way round —\n both showing the entity — so the header never said which record was open.\n -->\n <h2 class=\"ngx-record-editor__title\" data-testid=\"record-title\">\n {{ recordHeading }}\n </h2>\n <span class=\"ngx-record-editor__subtitle\">{{ ui.text('entityLabel', language, { entity: recordTitle }) }}</span>\n </div>\n </div>\n\n <!-- Record-level status switch, outside section editing -->\n @if (headerToggleField; as toggleField) {\n <label class=\"ngx-record-editor__header-toggle\">\n <span>{{ formatFieldLabel(toggleField) }}</span>\n <input\n type=\"checkbox\"\n role=\"switch\"\n data-testid=\"header-toggle\"\n [checked]=\"headerToggleValue\"\n [disabled]=\"recordReadOnly\"\n [attr.aria-checked]=\"headerToggleValue\"\n (change)=\"toggleHeaderStatus()\"\n />\n <span class=\"ngx-record-editor__header-toggle-text\">{{ ui.text(headerToggleValue ? 'yes' : 'no', language) }}</span>\n </label>\n }\n </div>\n\n <!-- Dismissible info banners (rules `info` action) -->\n @for (banner of infoBanners; track banner.fieldId) {\n <div\n class=\"ngx-record-editor__banner ngx-record-editor__banner--info\"\n role=\"status\"\n [attr.data-testid]=\"'info-banner-' + banner.fieldId\"\n >\n <span>ℹ️ {{ banner.message }}</span>\n <button\n type=\"button\"\n class=\"ngx-record-editor__banner-dismiss\"\n [attr.data-testid]=\"'dismiss-' + banner.fieldId\"\n [attr.aria-label]=\"ui.text('dismissBanner', language, { message: banner.message })\"\n (click)=\"dismissInfoBanner(banner.fieldId)\"\n >\n ✕\n </button>\n </div>\n }\n\n <!-- Modification baseline banner -->\n @if (isModified()) {\n <div class=\"ngx-record-editor__banner ngx-record-editor__banner--warning\">\n {{ ui.text('recordModified', language) }}\n </div>\n }\n\n <!-- Summary Panel (showOnMinimize fields with interactive jump) -->\n @if (summaryFields().length > 0) {\n <div class=\"ngx-record-editor__summary-panel\" data-testid=\"summary-panel\">\n @for (sf of summaryFields(); track sf.id) {\n <div\n class=\"ngx-record-editor__summary-item\"\n [attr.data-testid]=\"'summary-' + sf.id\"\n (click)=\"jumpToField(sf.id)\"\n [title]=\"ui.text('jumpToField', language, { field: formatFieldLabel(sf) })\"\n >\n <span class=\"ngx-record-editor__summary-label\">{{ formatFieldLabel(sf) }}</span>\n <span class=\"ngx-record-editor__summary-val\">{{ formatFieldValue(sf) }}</span>\n </div>\n }\n </div>\n }\n\n <!-- Section edit bar: one tab is edited at a time, and validated on its own -->\n @if (viewMode && !recordReadOnly) {\n <div class=\"ngx-record-editor__section-bar\">\n @if (isEditingActiveTab) {\n <span class=\"ngx-record-editor__section-hint\">{{ ui.text('editingSection', language) }}</span>\n <button type=\"button\" class=\"ngx-form__reset\" data-testid=\"cancel-section\" (click)=\"cancelSection()\">\n {{ ui.text('cancel', language) }}\n </button>\n <button type=\"button\" class=\"ngx-form__submit\" data-testid=\"save-section\" (click)=\"saveSection()\">\n {{ ui.text('saveSection', language) }}\n </button>\n } @else {\n <button type=\"button\" class=\"ngx-form__reset\" data-testid=\"edit-section\" (click)=\"editSection()\">\n {{ ui.text('editSection', language) }}\n </button>\n }\n </div>\n }\n\n @if (Object.keys(sectionErrors()).length > 0) {\n <div class=\"ngx-record-editor__banner ngx-record-editor__banner--error\" role=\"alert\" data-testid=\"section-errors\">\n @for (key of Object.keys(sectionErrors()); track key) {\n <div>⚠️ {{ sectionErrors()[key] }}</div>\n }\n </div>\n }\n\n <!-- Array rows: listed here, edited in the drawer below -->\n @for (arrayField of arrayFieldsForActiveTab; track arrayField.id) {\n <div class=\"ngx-record-editor__rows\" [attr.data-testid]=\"'rows-' + arrayField.id\">\n <div class=\"ngx-record-editor__rows-head\">\n <span class=\"ngx-record-editor__summary-label\">{{ formatFieldLabel(arrayField) }}</span>\n @if (!sectionReadOnly) {\n <button\n type=\"button\"\n class=\"ngx-form__reset\"\n [attr.data-testid]=\"'add-row-' + arrayField.id\"\n (click)=\"openAddRow(arrayField)\"\n >\n {{ ui.text('addRow', language) }}\n </button>\n }\n </div>\n\n @for (row of rowsOf(arrayField); track $index) {\n <div class=\"ngx-record-editor__row\" [attr.data-testid]=\"'row-' + arrayField.id + '-' + $index\">\n <span class=\"ngx-record-editor__row-text\">{{ rowSummary(arrayField, row) }}</span>\n @if (!sectionReadOnly) {\n <button\n type=\"button\"\n class=\"ngx-record-editor__row-btn\"\n [attr.data-testid]=\"'edit-row-' + arrayField.id + '-' + $index\"\n (click)=\"openEditRow(arrayField, $index)\"\n >\n {{ ui.text('edit', language) }}\n </button>\n <button\n type=\"button\"\n class=\"ngx-record-editor__row-btn\"\n [attr.data-testid]=\"'delete-row-' + arrayField.id + '-' + $index\"\n (click)=\"deleteRow(arrayField, $index)\"\n >\n {{ ui.text('delete', language) }}\n </button>\n }\n </div>\n } @empty {\n <p class=\"ngx-record-editor__row-empty\">{{ ui.text('noRows', language) }}</p>\n }\n </div>\n }\n\n <!--\n Row drawer. Deliberately outside the tab panel: building a row's FormGroup inside the\n tab view races the tab's own initialisation (the reference hit this with FormArray).\n -->\n @if (inlineRowField(); as rowField) {\n <div class=\"ngx-record-editor__drawer\" data-testid=\"row-drawer\" [formGroup]=\"inlineRowForm!\">\n <div class=\"ngx-record-editor__rows-head\">\n <strong>{{ rowDrawerTitle(rowField) }}</strong>\n </div>\n\n <div class=\"ngx-form__panel\">\n @for (child of rowField.children ?? []; track child.id) {\n <ngx-dynamic-field\n [field]=\"child\"\n [control]=\"inlineRowForm!.get(child.id)!\"\n [config]=\"config\"\n [language]=\"language\"\n [readonly]=\"false\"\n [userRoles]=\"userRoles\"\n [style.gridColumn]=\"'span 12'\"\n />\n }\n </div>\n\n <div class=\"ngx-record-editor__section-bar\">\n <button type=\"button\" class=\"ngx-form__reset\" data-testid=\"cancel-row\" (click)=\"cancelRow()\">\n {{ ui.text('cancel', language) }}\n </button>\n <button type=\"button\" class=\"ngx-form__submit\" data-testid=\"save-row\" (click)=\"saveRow()\">\n {{ ui.text('saveRow', language) }}\n </button>\n </div>\n </div>\n }\n\n <!-- Main Dynamic Form -->\n <ngx-dynamic-form\n [config]=\"config\"\n [rules]=\"rules\"\n [initialData]=\"initialData\"\n [originalData]=\"originalBaseline()\"\n [userRoles]=\"userRoles\"\n [language]=\"language\"\n [readonly]=\"sectionReadOnly\"\n [readOnlyFields]=\"readOnlyFields\"\n [layout]=\"layout\"\n [showInfoBanners]=\"false\"\n [loading]=\"loading\"\n [error]=\"error\"\n (formChange)=\"onFormChange($event)\"\n (formSubmit)=\"onFormSubmit($event)\"\n (saveRejected)=\"saveRejected.emit($event)\"\n (formReset)=\"onFormReset()\"\n (activeTabChange)=\"onActiveTabChange($event)\"\n />\n</div>\n","/**\n * import-contracts.ts — the two seams the import wizard hangs on.\n *\n * Both follow the pattern the rest of this package already uses for anything the library\n * cannot decide for a consumer — `FileUploadHandler`, `EntityReferenceLoader`,\n * `LookupListLoader`: a function type here, a token to register it against, and a default\n * that works without registering anything.\n *\n * **Why two rather than one.** Reading a file and deciding where the work happens are\n * different questions with different answers. A consumer may want `.xlsx` support in a\n * wizard that still runs entirely in the browser, or plain CSV that is nonetheless processed\n * on a server because their files have fifty thousand rows. Collapsing them into one option\n * would make each answer imply the other.\n */\n\nimport type {\n EntityFormConfig,\n FormRule,\n ImportLookups,\n ImportResult,\n MappingPlan,\n SheetData,\n TemplateSpec,\n} from '@dynamic-entity/core';\n\n/**\n * Reads an uploaded file into headers and positional rows.\n *\n * Positional (`string[][]`), not keyed by header, because a real sheet carries duplicate\n * headers and blank ones — and because a mapping entry addresses a column by index for\n * exactly that reason. A parser that returned objects keyed by header would silently lose\n * the second of two columns both called \"Notes\".\n *\n * The library ships a CSV implementation and no more. Registering one that understands\n * `.xlsx` is how a consumer adds it, and which spreadsheet library they use stays their\n * choice — this package has no runtime dependency and gains none here.\n *\n * @example\n * provideNgxDynamicEntity({\n * sheetParser: async file => {\n * const workbook = XLSX.read(await file.arrayBuffer());\n * const rows = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]], {\n * header: 1, raw: false, defval: '',\n * }) as string[][];\n * return { headers: rows[0] ?? [], rows: rows.slice(1) };\n * },\n * })\n */\nexport type SheetParser = (file: File) => SheetData | Promise<SheetData>;\n\n/** The formats a generated template can be written in. CSV needs no dependency. */\nexport type TemplateFormat = 'csv' | 'xlsx';\n\n/** What the wizard needs to know about the entity it is importing into. */\nexport interface ImportContext {\n config: EntityFormConfig;\n /**\n * Rules that apply to this entity.\n *\n * Without them an import checks field validators only, which is **not** what the form\n * enforces: a rule can attach an error, and a rule can hide a field, which must relax\n * `required`. Pass the same rules the form is rendered with or the two disagree.\n */\n rules?: readonly FormRule[];\n /** Values for any `listName` field, already resolved — core cannot reach `LOOKUP_REGISTRY`. */\n lookups?: ImportLookups;\n lang?: string;\n}\n\n/** What a first look at an uploaded file yields. */\nexport interface ImportPreview {\n headers: string[];\n /** The first few rows, for the mapping screen to show under each column. */\n sample: string[][];\n /** Where the suggester got to. Every inferred match is tagged `guess`. */\n suggestion: MappingPlan;\n /** Total data rows in the file, which may be far more than `sample` holds. */\n rowCount: number;\n}\n\n/**\n * Where the work happens.\n *\n * The default implementation does everything in the browser with `@dynamic-entity/core` and\n * never touches the network, so the wizard is fully usable with no backend at all. Register\n * an implementation that posts to a server and the same components drive it instead — the\n * engine underneath is the same code either way, which is the point of it being pure.\n *\n * This is the real answer to \"should parsing happen on the client or the server?\": both,\n * chosen at registration, without a second implementation of the mapping rules.\n */\nexport interface ImportTransport {\n /** Headers, a sample, and a suggested mapping for a freshly chosen file. */\n preview(file: File, context: ImportContext): Promise<ImportPreview>;\n /** Apply a plan to the whole file. */\n commit(file: File, plan: MappingPlan, context: ImportContext): Promise<ImportResult>;\n /**\n * Render a template for download.\n *\n * `fields` is the selection the user actually made — refs with row numbers stripped, one per\n * choice — and `spec` is that selection already expanded against the config. A transport that\n * renders locally wants the spec; one that asks a server wants the selection, because the\n * server has the config and only the choice needs to cross the wire. Passing both means\n * neither has to reconstruct the other: the HTTP transport used to recover the selection from\n * the expanded spec, which worked only because `stripIndices` happens to be exactly the\n * inverse of the expansion. Optional, so an existing implementation keeps compiling.\n */\n template(\n spec: TemplateSpec,\n format: TemplateFormat,\n context: ImportContext,\n fields?: readonly string[],\n ): Promise<Blob>;\n}\n","/**\n * sheet-parser.ts — the built-in CSV reader, and the reason it is the only one.\n *\n * CSV is what every spreadsheet tool exports and what a text editor can produce, and\n * `@dynamic-entity/core` parses it with no dependency. Shipping that as the default means the\n * import wizard works on a fresh `npm install` with nothing registered — `SHEET_PARSER` then\n * exists for the consumer who *also* wants `.xlsx`, rather than for the consumer who wants\n * the feature to work at all.\n *\n * The alternative was a hard dependency on a spreadsheet library in a package that currently\n * has none, for a file format many consumers will never see.\n */\n\nimport { parseCsv, type SheetData } from '@dynamic-entity/core';\nimport type { SheetParser } from './import-contracts';\n\n/** Extensions the built-in parser will attempt. */\nconst TEXT_EXTENSIONS = /\\.(csv|tsv|txt)$/i;\n\n/**\n * Read a text file as CSV.\n *\n * A binary workbook is refused by name rather than attempted: `.xlsx` is a zip, so reading it\n * as text yields a header row of mojibake and a mapping screen full of nonsense, which is a\n * much harder thing to diagnose than being told the format is not supported.\n */\nexport const defaultSheetParser: SheetParser = async (file: File): Promise<SheetData> => {\n if (file?.name && !TEXT_EXTENSIONS.test(file.name)) {\n throw new Error(\n `Cannot read \"${file.name}\". The built-in parser handles CSV only — register a ` +\n 'sheetParser with provideNgxDynamicEntity({ sheetParser }) to accept other formats.',\n );\n }\n return parseCsv(await file.text());\n};\n","/**\n * local-import-transport.ts — the whole import, in the browser, with no server.\n *\n * This is the default `IMPORT_TRANSPORT`, and it is a thin arrangement of pure functions\n * from `@dynamic-entity/core` rather than an implementation of anything. That matters: a\n * consumer who later registers a server transport is not switching to a second set of\n * mapping rules, they are moving the same ones to a different machine.\n *\n * Its limit is the one every browser has — the file is read into memory whole. That is fine\n * for the sizes a person assembles by hand and wrong for a fifty-thousand-row export, which\n * is what a streaming server transport is for.\n */\n\nimport { Injectable, inject } from '@angular/core';\nimport {\n applyMapping,\n deriveImportColumns,\n suggestMapping,\n toCsv,\n type ImportResult,\n type MappingPlan,\n type SheetData,\n type TemplateSpec,\n} from '@dynamic-entity/core';\nimport { SHEET_PARSER } from '../tokens/injection-tokens';\nimport { defaultSheetParser } from './sheet-parser';\nimport type {\n ImportContext,\n ImportPreview,\n ImportTransport,\n TemplateFormat,\n} from './import-contracts';\n\n/** How many rows the mapping screen shows under each column. */\nconst SAMPLE_ROWS = 5;\n\n@Injectable({ providedIn: 'root' })\nexport class LocalImportTransport implements ImportTransport {\n private readonly registered = inject(SHEET_PARSER, { optional: true });\n\n /**\n * One parse per file, not one per call.\n *\n * A wizard run reads the same file twice — once to show its headers, once to import it —\n * and this is the transport whose stated limit is that it holds the file in memory. Doing\n * the work twice doubled both the parse and the peak memory of the one implementation that\n * can least afford it.\n *\n * A `WeakMap` keyed on the `File` itself: the entry lives exactly as long as something\n * still holds the file, so choosing a different file drops the old sheet without anything\n * having to remember to. Keying on a name or a size would collide between two files a user\n * picked in sequence.\n */\n private readonly parsed = new WeakMap<File, Promise<SheetData>>();\n\n /** The registered parser, or the built-in CSV one. */\n private read(file: File): Promise<SheetData> {\n const cached = this.parsed.get(file);\n if (cached) return cached;\n\n // The *promise* is cached, not its result, so two calls that overlap share one parse\n // rather than starting a second before the first resolves.\n const pending = Promise.resolve((this.registered ?? defaultSheetParser)(file));\n this.parsed.set(file, pending);\n // A failed parse must not be remembered: the user may fix the file and pick it again.\n pending.catch(() => this.parsed.delete(file));\n return pending;\n }\n\n async preview(file: File, context: ImportContext): Promise<ImportPreview> {\n const sheet = await this.read(file);\n const { columns } = deriveImportColumns(context.config, { lang: context.lang });\n\n return {\n headers: sheet.headers,\n sample: sheet.rows.slice(0, SAMPLE_ROWS),\n rowCount: sheet.rows.length,\n suggestion: suggestMapping(sheet.headers, columns, context.config?.entity ?? ''),\n };\n }\n\n async commit(file: File, plan: MappingPlan, context: ImportContext): Promise<ImportResult> {\n const sheet = await this.read(file);\n return applyMapping(sheet.rows, plan, context.config, {\n lang: context.lang,\n rules: context.rules,\n lookups: context.lookups,\n });\n }\n\n async template(spec: TemplateSpec, format: TemplateFormat): Promise<Blob> {\n if (format === 'xlsx') {\n // Deliberately not a silent fallback to CSV. A file named `.xlsx` that is really CSV\n // opens with a warning in Excel and imports wrongly elsewhere, and the consumer would\n // have no idea why — where this message says exactly which seam to fill.\n throw new Error(\n 'This build can only write CSV templates. Register an IMPORT_TRANSPORT that writes ' +\n 'xlsx — see provideNgxDynamicEntity({ importTransport }) — or request csv.',\n );\n }\n\n // Headers only, and `spec.notes` deliberately left out of the file.\n //\n // A guidance row under the headers reads well and breaks the round trip: CSV has one\n // header row and no concept of a second, so re-importing the template the user filled in\n // would treat the guidance as a record and report a failed row 2 on every single import.\n // The notes are shown beside each column in the picker instead, where they can be read\n // without being parsed. A format with somewhere to put them — an xlsx cell comment, a\n // second sheet — can carry them; CSV has nowhere that is not data.\n const csv = toCsv(spec.columns.map(column => column.header));\n return new Blob([csv], { type: 'text/csv;charset=utf-8' });\n }\n}\n\n","/**\n * http-import-transport.ts — the same wizard, with the work happening on a server.\n *\n * The components do not change at all: they already talk to an `ImportTransport`, which was\n * the point of the seam. Registering this one moves the mapping, coercion and validation from\n * the tab to a server that runs the *same* `@dynamic-entity/core` functions — so the reason to\n * do it is size, not behaviour.\n *\n * **Built on `fetch`, not `HttpClient`.** This package has no `@angular/common/http` dependency\n * today, and four requests is not the reason to acquire one — a consumer who wants interceptors\n * passes their own `fetch`, which is a smaller seam than a dependency.\n */\n\nimport {\n CORE_VERSION,\n deriveImportColumns,\n stripIndices,\n type ImportCommitResponse,\n type ImportErrorResponse,\n type ImportPreviewResponse,\n type ImportResult,\n type MappingPlan,\n type TemplateSpec,\n} from '@dynamic-entity/core';\nimport type { Provider } from '@angular/core';\nimport { IMPORT_TRANSPORT } from '../tokens/injection-tokens';\nimport type {\n ImportContext,\n ImportPreview,\n ImportTransport,\n TemplateFormat,\n} from './import-contracts';\n\nexport interface HttpImportTransportOptions {\n /** Where the router is mounted, e.g. `/api/import`. A trailing slash is ignored. */\n baseUrl: string;\n /** Supply one to add interceptors, retries, or credentials. Defaults to the global `fetch`. */\n fetch?: typeof fetch;\n /** Headers on every request — an `Authorization`, a tenant id. Never a `Content-Type`. */\n headers?: Record<string, string> | (() => Record<string, string>);\n /**\n * Where a warning goes. Defaults to `console.warn`.\n *\n * There is exactly one warning, and it is the engine-version mismatch below — which is a\n * developer's problem, not a user's, so it does not belong in the wizard's error banner.\n */\n warn?: (message: string) => void;\n}\n\n/** `Content-Type` is deliberately not settable: `fetch` must set the multipart boundary. */\nfunction resolveHeaders(options: HttpImportTransportOptions): Record<string, string> {\n const headers = typeof options.headers === 'function' ? options.headers() : options.headers ?? {};\n const out: Record<string, string> = {};\n for (const [name, value] of Object.entries(headers)) {\n if (name.toLowerCase() === 'content-type') continue;\n out[name] = value;\n }\n return out;\n}\n\nconst trimSlash = (url: string): string => String(url ?? '').replace(/\\/+$/, '');\n\n/** Same major and minor. Two engines a patch apart are the same engine. */\nfunction sameLine(a: string, b: string): boolean {\n const line = (version: string): string => version.split('.').slice(0, 2).join('.');\n return line(a) === line(b);\n}\n\n/**\n * Turn a failed response into an `Error` the wizard can show.\n *\n * The server's envelope carries a code and a message it wrote itself; anything else — a proxy's\n * HTML error page, a network failure — has no message worth showing, so a status line is what\n * the user gets rather than a page of markup.\n */\nasync function failureOf(response: Response): Promise<Error> {\n let body: ImportErrorResponse | undefined;\n try {\n body = (await response.json()) as ImportErrorResponse;\n } catch {\n /* not our envelope */\n }\n const message = body?.error?.message;\n return new Error(message || `The import server answered ${response.status}.`);\n}\n\n/**\n * The field selection, as short as it can be said without changing what it means.\n *\n * Two reductions, and both are exact rather than approximate:\n *\n * - **Row numbers come off.** `buildTemplateSpec` matches a column by its ref *or* by its ref\n * with indices stripped, and the picker that produced this selection worked in stripped refs\n * to begin with — so `contacts.0.email, contacts.1.email, contacts.2.email` is the expansion\n * of one choice, and collapsing it back recovers exactly what the user ticked.\n * - **A full selection is sent as no selection at all**, because omitting `fields` already\n * means every column.\n *\n * Without them a wide config produced a query string of ten kilobytes or more — past the eight\n * nginx and Node default to — and the request most likely to hit it is \"give me a template with\n * everything\", which is the one this now sends as a bare `?format=`.\n */\nfunction selectionOf(\n spec: TemplateSpec,\n context: ImportContext,\n fields?: readonly string[],\n): string {\n // The caller's own selection when it gave one — the wizard does — and the expanded spec\n // reduced back to it otherwise, for a host calling `template` directly.\n const chosen = new Set(fields ?? spec.columns.map(column => stripIndices(column.ref)));\n const all = new Set(\n deriveImportColumns(context?.config, { lang: context?.lang }).columns.map(column =>\n stripIndices(column.ref),\n ),\n );\n\n if (all.size && chosen.size === all.size && [...all].every(ref => chosen.has(ref))) return '';\n return [...chosen].join(',');\n}\n\n/**\n * Not `@Injectable`, and registered by value rather than by class.\n *\n * Its constructor takes options rather than dependencies, so there is nothing for an injector\n * to resolve — and a consumer who wants two of them, pointed at two backends, gets that for\n * free.\n */\nclass HttpImportTransport implements ImportTransport {\n constructor(private readonly options: HttpImportTransportOptions) {}\n\n private get base(): string {\n return trimSlash(this.options.baseUrl);\n }\n\n private get send(): typeof fetch {\n // Bound rather than referenced: a bare `globalThis.fetch` passed around as a value throws\n // \"Illegal invocation\" in a browser, because it needs `window` as its receiver.\n return this.options.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n private entityOf(context: ImportContext): string {\n return encodeURIComponent(context?.config?.entity ?? '');\n }\n\n /**\n * Warn when the server's engine is not the one this bundle was built against.\n *\n * The two halves are separately deployed and may differ. `MappingPlan.configVersion` catches\n * *config* drift and says nothing about *engine* drift, so \"one engine, both sides\" is only\n * true if something checks — and this is the something. A warning rather than a refusal: a\n * patch release is not a reason to stop somebody importing.\n */\n private checkEngine(version: string | undefined): void {\n // Compared at major.minor. A patch difference between two deploys is the normal state of\n // a rolling release and says nothing about whether the engines agree; warning on it puts a\n // line in the console on every preview and every commit, which is how people learn to\n // scroll past the warning that does matter.\n if (!version || sameLine(version, CORE_VERSION)) return;\n const warn = this.options.warn ?? ((message: string) => console.warn(message));\n warn(\n `[ngx-dynamic-entity] The import server runs @dynamic-entity/core ${version}; this app ` +\n `was built against ${CORE_VERSION}. The two halves of an import are supposed to be the ` +\n 'same engine — bring them into step before trusting a difference in what they produce.',\n );\n }\n\n async preview(file: File, context: ImportContext): Promise<ImportPreview> {\n const body = new FormData();\n body.append('file', file, file.name || 'upload');\n\n const response = await this.send(`${this.base}/${this.entityOf(context)}/preview`, {\n method: 'POST',\n headers: resolveHeaders(this.options),\n body,\n });\n if (!response.ok) throw await failureOf(response);\n\n const preview = (await response.json()) as ImportPreviewResponse;\n this.checkEngine(preview.engineVersion);\n\n return {\n headers: preview.headers ?? [],\n sample: preview.sample ?? [],\n suggestion: preview.suggestion,\n rowCount: preview.rowCount ?? 0,\n };\n }\n\n async commit(file: File, plan: MappingPlan, context: ImportContext): Promise<ImportResult> {\n const body = new FormData();\n // **The plan first, and the file second.** The server starts importing while the file is\n // still arriving — that is the whole reason it exists — so the plan has to have arrived\n // already. `FormData` preserves append order, so this ordering is the contract.\n body.append('plan', JSON.stringify(plan));\n body.append('file', file, file.name || 'upload');\n\n const response = await this.send(`${this.base}/${this.entityOf(context)}/import`, {\n method: 'POST',\n headers: resolveHeaders(this.options),\n body,\n });\n if (!response.ok) throw await failureOf(response);\n\n const result = (await response.json()) as ImportCommitResponse;\n this.checkEngine(result.engineVersion);\n\n return {\n // Empty, and not because nothing was imported. The server streamed the file precisely so\n // that fifty thousand records never had to exist at once; sending them back would undo\n // that on the way out. `imported` is the count, and the records are in the consumer's\n // database.\n records: [],\n imported: result.imported ?? 0,\n skipped: result.skipped ?? 0,\n failed: result.failed ?? 0,\n errors: result.errors ?? [],\n errorCount: result.errorCount ?? result.errors?.length ?? 0,\n truncated: result.truncated ?? false,\n planProblems: result.planProblems ?? [],\n };\n }\n\n async template(\n spec: TemplateSpec,\n format: TemplateFormat,\n context: ImportContext,\n fields?: readonly string[],\n ): Promise<Blob> {\n // The server rebuilds the spec from its own config; only the selection crosses the wire.\n // Posting a whole spec would let a client choose the headers of a file the server signs\n // its name to, and the server has the config anyway.\n const query = new URLSearchParams({ format });\n const selection = selectionOf(spec, context, fields);\n if (selection) query.set('fields', selection);\n\n const response = await this.send(\n `${this.base}/${this.entityOf(context)}/template?${query.toString()}`,\n { method: 'GET', headers: resolveHeaders(this.options) },\n );\n if (!response.ok) throw await failureOf(response);\n return response.blob();\n }\n}\n\n/**\n * Register the HTTP transport.\n *\n * ```ts\n * provideNgxDynamicEntity({}),\n * provideHttpImportTransport({ baseUrl: '/api/import' }),\n * ```\n *\n * A plain `Provider` rather than `EnvironmentProviders`, so it composes inside a component's\n * or a route's `providers` array as well as at the root — which is how a consumer points one\n * part of an app at a different backend.\n */\nexport function provideHttpImportTransport(options: HttpImportTransportOptions): Provider {\n return { provide: IMPORT_TRANSPORT, useValue: new HttpImportTransport(options) };\n}\n\n/** Exported for a consumer who wants to subclass or wrap it; most should use the provider. */\nexport { HttpImportTransport };\n","import { ChangeDetectionStrategy, Component, Input, inject } from '@angular/core';\nimport type { ImportRowError } from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\n\n/**\n * The rows an import could not take, and why.\n *\n * Grouped by row rather than listed flat: a row with four problems is one row to go and fix,\n * and four separate lines invite the reader to think there are four. The row number is the\n * one the spreadsheet shows in its gutter — header counted as row 1 — because that is the\n * number they will scroll to.\n */\n@Component({\n selector: 'ngx-import-errors',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [],\n template: `\n @if (errors.length) {\n <section class=\"ngx-import-errors\" data-testid=\"import-errors\">\n <h4 class=\"ngx-import-errors__heading\">{{ ui.text('importErrorsHeading', language) }}</h4>\n <table class=\"ngx-import-errors__table\">\n <thead>\n <tr>\n <th scope=\"col\">{{ ui.text('importErrorRow', language, { row: '#' }) }}</th>\n <th scope=\"col\">{{ ui.text('importErrorField', language) }}</th>\n <th scope=\"col\">{{ ui.text('importErrorReason', language) }}</th>\n </tr>\n </thead>\n <tbody>\n @for (group of grouped(); track group.row) {\n @for (problem of group.problems; track $index) {\n <tr [attr.data-testid]=\"'import-error-row-' + group.row\">\n @if ($first) {\n <th scope=\"row\" [attr.rowspan]=\"group.problems.length\">\n {{ ui.text('importErrorRow', language, { row: group.row }) }}\n </th>\n }\n <td>{{ problem.ref }}</td>\n <td>{{ problem.message }}</td>\n </tr>\n }\n }\n </tbody>\n </table>\n </section>\n }\n `,\n styles: [\n `\n .ngx-import-errors__heading {\n margin: 0 0 8px;\n font-size: var(--ngx-font-size, 14px);\n color: var(--ngx-color-error, #b91c1c);\n }\n .ngx-import-errors__table {\n width: 100%;\n border-collapse: collapse;\n }\n .ngx-import-errors__table th,\n .ngx-import-errors__table td {\n text-align: left;\n padding: 6px 10px;\n border-bottom: 1px solid var(--ngx-color-border, #e5e7eb);\n vertical-align: top;\n }\n .ngx-import-errors__table thead th {\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-import-errors__table tbody th {\n white-space: nowrap;\n color: var(--ngx-color-error, #b91c1c);\n }\n `,\n ],\n})\nexport class ImportErrorsComponent {\n @Input() errors: readonly ImportRowError[] = [];\n @Input() language = 'en';\n\n protected readonly ui = inject(UiTextService);\n\n /** Row number → its problems, in the order the rows appear in the file. */\n protected grouped(): { row: number; problems: ImportRowError[] }[] {\n const byRow = new Map<number, ImportRowError[]>();\n for (const error of this.errors) {\n const list = byRow.get(error.row) ?? [];\n list.push(error);\n byRow.set(error.row, list);\n }\n return [...byRow.entries()]\n .sort((a, b) => a[0] - b[0])\n .map(([row, problems]) => ({ row, problems }));\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n OnChanges,\n Output,\n inject,\n signal,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n deriveImportColumns,\n type EntityFormConfig,\n type ImportColumn,\n type MappingEntry,\n type MappingPlan,\n} from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\n\n/** One target field, and which of the sheet's columns feeds it. */\ninterface MappingRow {\n column: ImportColumn;\n /** Index into the sheet's headers, or `null` for \"not imported\". */\n source: number | null;\n guessed: boolean;\n}\n\n/**\n * Match the sheet's columns to the config's fields.\n *\n * The table is driven by the **target fields**, not by the sheet's columns, which is the\n * choice that decides how the screen reads. A user is answering \"where does Start Date come\n * from?\", which they can do; column-first would ask \"what is column G?\", which they often\n * cannot, and would make a sheet with forty irrelevant columns forty questions long.\n *\n * A selection is a **column index**, never header text. Two columns headed \"Notes\" are two\n * different answers, and text cannot tell them apart.\n */\n@Component({\n selector: 'ngx-import-mapper',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FormsModule],\n template: `\n <section class=\"ngx-import-mapper\" data-testid=\"import-mapper\">\n <p class=\"ngx-import-mapper__summary\" data-testid=\"import-mapped-count\">\n {{ ui.text('importMappedCount', language, { mapped: mappedCount(), total: rows().length }) }}\n </p>\n @if (missingRequired() > 0) {\n <p class=\"ngx-import-mapper__warning\" data-testid=\"import-required-unmapped\" role=\"status\">\n {{ ui.text('importRequiredUnmapped', language, { count: missingRequired() }) }}\n </p>\n }\n @if (unsupported() > 0) {\n <p class=\"ngx-import-mapper__note\" data-testid=\"import-mapper-unsupported\">\n {{ ui.text('importTemplateUnsupported', language, { count: unsupported() }) }}\n </p>\n }\n\n <table class=\"ngx-import-mapper__table\">\n <thead>\n <tr>\n <th scope=\"col\">{{ ui.text('importTargetField', language) }}</th>\n <th scope=\"col\">{{ ui.text('importColumnInFile', language) }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.column.ref) {\n <tr [attr.data-testid]=\"'import-map-' + row.column.ref\">\n <th scope=\"row\">\n {{ row.column.header }}\n @if (row.column.required) {\n <span class=\"ngx-import-mapper__required\" aria-hidden=\"true\">*</span>\n }\n </th>\n <td>\n <select\n class=\"ngx-import-mapper__select\"\n [attr.data-testid]=\"'import-select-' + row.column.ref\"\n [attr.aria-label]=\"row.column.header\"\n [ngModel]=\"row.source\"\n (ngModelChange)=\"choose(row, $event)\"\n >\n <option [ngValue]=\"null\">{{ ui.text('importUnmapped', language) }}</option>\n @for (header of headers; track $index) {\n <option [ngValue]=\"$index\">{{ header || '—' }}</option>\n }\n </select>\n @if (row.guessed && row.source !== null) {\n <span class=\"ngx-import-mapper__guess\" [attr.data-testid]=\"'import-guess-' + row.column.ref\">\n {{ ui.text('importGuessed', language) }}\n </span>\n }\n </td>\n </tr>\n }\n </tbody>\n </table>\n </section>\n `,\n styles: [\n `\n .ngx-import-mapper__summary,\n .ngx-import-mapper__warning,\n .ngx-import-mapper__note {\n margin: 0 0 10px;\n }\n .ngx-import-mapper__warning {\n color: var(--ngx-color-warning, #b45309);\n background: var(--ngx-color-warning-soft, #fffbeb);\n border: 1px solid var(--ngx-color-border, #fef3c7);\n border-radius: var(--ngx-radius-sm, 6px);\n padding: 8px 12px;\n }\n .ngx-import-mapper__note {\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-import-mapper__table {\n width: 100%;\n border-collapse: collapse;\n }\n .ngx-import-mapper__table th,\n .ngx-import-mapper__table td {\n text-align: left;\n padding: 8px 10px;\n border-bottom: 1px solid var(--ngx-color-border, #e5e7eb);\n vertical-align: middle;\n }\n .ngx-import-mapper__table thead th {\n color: var(--ngx-color-muted, #6b7280);\n font-size: var(--ngx-font-size, 13px);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n }\n .ngx-import-mapper__required {\n color: var(--ngx-color-error, #b91c1c);\n margin-left: 2px;\n }\n .ngx-import-mapper__select {\n min-width: 220px;\n max-width: 100%;\n padding: 6px 8px;\n border: 1px solid var(--ngx-color-border, #d1d5db);\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-surface, #ffffff);\n color: inherit;\n font: inherit;\n }\n .ngx-import-mapper__guess {\n margin-left: 8px;\n padding: 2px 8px;\n border-radius: 999px;\n font-size: 12px;\n color: var(--ngx-color-info, #1d4ed8);\n background: var(--ngx-color-info-soft, #eff6ff);\n }\n @media (max-width: 640px) {\n .ngx-import-mapper__select {\n min-width: 0;\n width: 100%;\n }\n }\n `,\n ],\n})\nexport class ImportMapperComponent implements OnChanges {\n @Input({ required: true }) config!: EntityFormConfig;\n @Input() headers: readonly string[] = [];\n /** The starting point, normally `suggestMapping`'s output. */\n @Input() plan: MappingPlan | null = null;\n @Input() language = 'en';\n\n /** Emitted whenever the user changes a selection. */\n @Output() readonly planChange = new EventEmitter<MappingPlan>();\n\n protected readonly ui = inject(UiTextService);\n protected readonly rows = signal<MappingRow[]>([]);\n /**\n * How many fields a spreadsheet cannot carry at all.\n *\n * Shown here as well as in the template picker, because a user who already had a sheet\n * skipped that screen — and this is the only place they would otherwise find out that an\n * attachment column was never going to arrive.\n */\n protected readonly unsupported = signal(0);\n\n ngOnChanges(): void {\n const { columns, unsupported } = deriveImportColumns(this.config, { lang: this.language });\n this.unsupported.set(unsupported.length);\n const byRef = new Map((this.plan?.entries ?? []).map(entry => [entry.ref, entry]));\n\n this.rows.set(\n columns.map(column => {\n const entry = byRef.get(column.ref);\n return {\n column,\n source: entry?.column ?? null,\n guessed: entry?.confidence === 'guess',\n };\n }),\n );\n }\n\n protected mappedCount(): number {\n return this.rows().filter(row => row.source !== null).length;\n }\n\n protected missingRequired(): number {\n return this.rows().filter(row => row.column.required && row.source === null).length;\n }\n\n protected choose(row: MappingRow, source: number | null): void {\n this.rows.update(rows =>\n rows.map(candidate =>\n candidate.column.ref === row.column.ref\n ? // A hand-made choice is not a guess any more, so the badge goes.\n { ...candidate, source, guessed: false }\n : candidate,\n ),\n );\n this.planChange.emit(this.toPlan());\n }\n\n /** The current selections as the plan that will be applied. */\n private toPlan(): MappingPlan {\n const entries: MappingEntry[] = this.rows()\n .filter(row => row.source !== null)\n .map(row => ({\n ref: row.column.ref,\n column: row.source as number,\n header: this.headers[row.source as number],\n confidence: row.guessed ? ('guess' as const) : ('exact' as const),\n }));\n\n return {\n entity: this.config?.entity ?? '',\n configVersion: this.config?.version,\n sourceHeaders: [...this.headers],\n entries,\n };\n }\n}\n","import { ChangeDetectionStrategy, Component, Input, OnChanges, inject, signal } from '@angular/core';\nimport {\n applyMapping,\n coerceCell,\n deriveImportColumns,\n formatDisplayValue,\n type EntityFormConfig,\n type FormRule,\n type ImportColumn,\n type ImportLookups,\n type MappingPlan,\n} from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\n\n/** One cell, already turned into the text the record will show. */\ninterface PreviewCell {\n text: string;\n failed: boolean;\n}\n\n/** A row of cells, plus why the import will refuse it — if it will. */\ninterface PreviewRow {\n cells: PreviewCell[];\n /** Empty when the row will be imported. */\n rejections: string[];\n}\n\n/**\n * The first few rows as the record will hold them, not as the sheet holds them.\n *\n * Every cell goes through the same `coerceCell` the import will use and then through\n * `formatDisplayValue`, which is what the renderer uses to show a stored value. So a\n * `dropdown` cell reading `Aktiv` shows as `Active` here if that is the option it resolved\n * to, and a cell that will fail shows its reason before anyone commits to anything.\n *\n * Showing the raw text instead would be easier and would preview the wrong thing: the point\n * of this screen is to catch a mapping that is subtly wrong, and a column of unchanged text\n * looks correct whatever field it was pointed at.\n *\n * **The rows are also run through the real import**, not just through coercion. `coerceCell`\n * alone catches a cell that will not parse and says nothing about a row that will be rejected\n * — a missing required field, a rule that forbids the combination — so a heading promising\n * \"as they will be saved\" was showing rows that would never be saved at all, looking exactly\n * like the ones that would. `applyMapping` over the sample answers that with the same engine\n * the commit uses, rather than a second opinion about what counts as valid.\n *\n * The whole grid is built once per input change rather than from template method calls.\n * Deriving the config's columns inside a `@for` means re-walking the entire schema for every\n * cell on every change-detection pass, which is a lot of work to produce five rows.\n */\n@Component({\n selector: 'ngx-import-preview',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [],\n template: `\n <section class=\"ngx-import-preview\" data-testid=\"import-preview\">\n <h4 class=\"ngx-import-preview__heading\">\n {{ ui.text('importPreviewHeading', language, { count: rows.length }) }}\n </h4>\n <div class=\"ngx-import-preview__scroll\">\n <table class=\"ngx-import-preview__table\">\n <thead>\n <tr>\n @for (column of columns(); track column.ref) {\n <th scope=\"col\">{{ column.header }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of grid(); track $index) {\n <tr\n [attr.data-testid]=\"'import-preview-row-' + $index\"\n [class.ngx-import-preview__row--rejected]=\"row.rejections.length\"\n >\n @for (cell of row.cells; track $index) {\n <td [class.ngx-import-preview__cell--error]=\"cell.failed\">{{ cell.text }}</td>\n }\n </tr>\n @if (row.rejections.length) {\n <tr class=\"ngx-import-preview__reason\">\n <td [attr.colspan]=\"columns().length\" [attr.data-testid]=\"'import-preview-rejected-' + $index\">\n {{ ui.text('importRowRejected', language, { reason: row.rejections.join('; ') }) }}\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n </section>\n `,\n styles: [\n `\n .ngx-import-preview__heading {\n margin: 0 0 8px;\n font-size: var(--ngx-font-size, 14px);\n }\n /* The one place a horizontal scrollbar belongs: a sheet can have forty columns. */\n .ngx-import-preview__scroll {\n overflow-x: auto;\n border: 1px solid var(--ngx-color-border, #e5e7eb);\n border-radius: var(--ngx-radius-sm, 6px);\n }\n .ngx-import-preview__table {\n width: 100%;\n border-collapse: collapse;\n white-space: nowrap;\n }\n .ngx-import-preview__table th,\n .ngx-import-preview__table td {\n text-align: left;\n padding: 6px 10px;\n border-bottom: 1px solid var(--ngx-color-border, #f3f4f6);\n }\n .ngx-import-preview__table thead th {\n background: var(--ngx-color-surface-alt, #f9fafb);\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-import-preview__cell--error {\n color: var(--ngx-color-error, #b91c1c);\n background: var(--ngx-color-error-soft, #fef2f2);\n }\n /* A row that will be refused is dimmed, and says why on the line beneath it. */\n .ngx-import-preview__row--rejected td {\n opacity: 0.65;\n }\n .ngx-import-preview__reason td {\n white-space: normal;\n color: var(--ngx-color-error, #b91c1c);\n background: var(--ngx-color-error-soft, #fef2f2);\n }\n `,\n ],\n})\nexport class ImportPreviewComponent implements OnChanges {\n @Input({ required: true }) config!: EntityFormConfig;\n @Input({ required: true }) plan!: MappingPlan;\n @Input() rows: readonly (readonly string[])[] = [];\n @Input() lookups?: ImportLookups;\n /** The same rules the commit will apply; without them a rule-driven rejection is invisible. */\n @Input() rules?: readonly FormRule[];\n @Input() language = 'en';\n\n protected readonly ui = inject(UiTextService);\n\n /** The columns this plan fills, in the plan's own order. */\n protected readonly columns = signal<ImportColumn[]>([]);\n protected readonly grid = signal<PreviewRow[]>([]);\n\n ngOnChanges(): void {\n const byRef = new Map(\n deriveImportColumns(this.config, { lang: this.language }).columns.map(c => [c.ref, c]),\n );\n\n const entries = (this.plan?.entries ?? []).filter(entry => byRef.has(entry.ref));\n this.columns.set(entries.map(entry => byRef.get(entry.ref)!));\n\n // The same engine the commit runs, over the sample only. Row 0 of the sample is numbered\n // 0 here rather than 2, because these row numbers index the preview, not the file.\n const dryRun = applyMapping(this.rows, this.plan, this.config, {\n lang: this.language,\n lookups: this.lookups,\n rules: this.rules,\n stamp: false,\n firstRowNumber: 0,\n });\n const rejectionsByRow = new Map<number, string[]>();\n for (const error of dryRun.errors) {\n rejectionsByRow.set(error.row, [...(rejectionsByRow.get(error.row) ?? []), error.message]);\n }\n\n this.grid.set(\n this.rows.map((row, index) => ({\n rejections: rejectionsByRow.get(index) ?? [],\n cells: entries.map(entry => {\n const field = byRef.get(entry.ref)!.field;\n const raw = entry.column === undefined ? entry.constant : row[entry.column];\n const outcome = coerceCell(field, raw, {\n lang: this.language,\n lookups: this.lookups,\n });\n\n if ('error' in outcome) return { text: outcome.error, failed: true };\n return {\n text: formatDisplayValue(field.type, field.options, outcome.value, this.language),\n failed: false,\n };\n }),\n })),\n );\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n OnChanges,\n Output,\n inject,\n signal,\n} from '@angular/core';\nimport {\n buildTemplateSpec,\n deriveImportColumns,\n stripIndices,\n type EntityFormConfig,\n type UnsupportedColumn,\n} from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\n\n/** One field offered for the template, with the guidance that belongs to it. */\ninterface TemplateChoice {\n /** The ref with any row number removed, so a repeating field is offered once. */\n ref: string;\n header: string;\n note: string;\n selected: boolean;\n}\n\n/**\n * Pick the fields a template should carry, then download it.\n *\n * The guidance for each field is shown **here**, beside the checkbox, rather than written\n * into the file as a second header row. CSV has one header row and no concept of a second,\n * so a guidance row inside the file would come back as a record on re-import and fail row 2\n * of every import the user ever ran.\n *\n * A repeating field is offered once, not once per row number: \"Contacts / Name\" is a decision,\n * and \"Contacts / Name 1\", \"Contacts / Name 2\", \"Contacts / Name 3\" is the same decision\n * asked three times.\n */\n@Component({\n selector: 'ngx-import-template',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [],\n template: `\n <section class=\"ngx-import-template\" data-testid=\"import-template\">\n <h4 class=\"ngx-import-template__heading\">{{ ui.text('importTemplateHeading', language) }}</h4>\n <p class=\"ngx-import-template__explain\">{{ ui.text('importTemplateExplain', language) }}</p>\n\n <div class=\"ngx-import-template__bulk\">\n <button type=\"button\" (click)=\"selectAll(true)\" data-testid=\"import-template-all\">\n {{ ui.text('importTemplateSelectAll', language) }}\n </button>\n <button type=\"button\" (click)=\"selectAll(false)\" data-testid=\"import-template-none\">\n {{ ui.text('importTemplateSelectNone', language) }}\n </button>\n </div>\n\n <ul class=\"ngx-import-template__list\">\n @for (choice of choices(); track choice.ref) {\n <li class=\"ngx-import-template__item\">\n <label>\n <input\n type=\"checkbox\"\n [checked]=\"choice.selected\"\n (change)=\"toggle(choice.ref)\"\n [attr.data-testid]=\"'import-template-field-' + choice.ref\"\n />\n <span class=\"ngx-import-template__label\">{{ choice.header }}</span>\n </label>\n @if (choice.note) {\n <span class=\"ngx-import-template__note\">{{ choice.note }}</span>\n }\n </li>\n }\n </ul>\n\n @if (unsupported().length) {\n <p class=\"ngx-import-template__unsupported\" data-testid=\"import-template-unsupported\">\n {{ ui.text('importTemplateUnsupported', language, { count: unsupported().length }) }}\n </p>\n }\n\n <button\n type=\"button\"\n class=\"ngx-import-template__download\"\n data-testid=\"import-template-download\"\n [disabled]=\"!selectedCount()\"\n (click)=\"download.emit(selectedRefs())\"\n >\n {{ ui.text('importTemplateDownload', language) }}\n </button>\n </section>\n `,\n styles: [\n `\n .ngx-import-template {\n padding: 14px;\n border: 1px solid var(--ngx-color-border, #e5e7eb);\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-surface-alt, #f9fafb);\n }\n .ngx-import-template__heading {\n margin: 0 0 4px;\n font-size: var(--ngx-font-size, 14px);\n }\n .ngx-import-template__explain {\n margin: 0 0 10px;\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-import-template__bulk {\n display: flex;\n gap: 8px;\n margin-bottom: 10px;\n }\n .ngx-import-template__list {\n list-style: none;\n margin: 0 0 10px;\n padding: 0;\n max-height: 240px;\n overflow-y: auto;\n display: grid;\n gap: 4px;\n }\n .ngx-import-template__item {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 8px;\n }\n .ngx-import-template__item label {\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n }\n .ngx-import-template__note {\n color: var(--ngx-color-muted, #6b7280);\n font-size: 12px;\n }\n .ngx-import-template__unsupported {\n margin: 0 0 10px;\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-import-template button {\n padding: 6px 12px;\n border: 1px solid var(--ngx-color-border, #d1d5db);\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-surface, #ffffff);\n color: inherit;\n font: inherit;\n cursor: pointer;\n }\n .ngx-import-template button:disabled {\n opacity: 0.55;\n cursor: not-allowed;\n }\n `,\n ],\n})\nexport class ImportTemplateComponent implements OnChanges {\n @Input({ required: true }) config!: EntityFormConfig;\n @Input() language = 'en';\n\n /** The refs to include, with row numbers stripped — the caller builds the spec. */\n @Output() readonly download = new EventEmitter<string[]>();\n\n protected readonly ui = inject(UiTextService);\n protected readonly choices = signal<TemplateChoice[]>([]);\n protected readonly unsupported = signal<UnsupportedColumn[]>([]);\n\n ngOnChanges(): void {\n const spec = buildTemplateSpec(this.config, { lang: this.language });\n const derived = deriveImportColumns(this.config, { lang: this.language });\n\n // One entry per field, keyed on the ref with its row number removed, so a repeating\n // field collapses back into the single choice it is.\n const seen = new Map<string, TemplateChoice>();\n spec.columns.forEach((column, i) => {\n const ref = stripIndices(column.ref);\n if (seen.has(ref)) return;\n seen.set(ref, {\n ref,\n header: column.arrayIndex === undefined ? column.header : stripRowNumber(column.header),\n note: spec.notes[i] ?? '',\n selected: true,\n });\n });\n\n this.choices.set([...seen.values()]);\n this.unsupported.set(derived.unsupported);\n }\n\n protected selectedCount(): number {\n return this.choices().filter(choice => choice.selected).length;\n }\n\n protected selectedRefs(): string[] {\n return this.choices()\n .filter(choice => choice.selected)\n .map(choice => choice.ref);\n }\n\n protected toggle(ref: string): void {\n this.choices.update(choices =>\n choices.map(choice =>\n choice.ref === ref ? { ...choice, selected: !choice.selected } : choice,\n ),\n );\n }\n\n protected selectAll(selected: boolean): void {\n this.choices.update(choices => choices.map(choice => ({ ...choice, selected })));\n }\n}\n\n/** \"Contacts / Name 1\" → \"Contacts / Name\", for the collapsed choice. */\nfunction stripRowNumber(header: string): string {\n return header.replace(/ \\d+$/, '');\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n Output,\n inject,\n signal,\n} from '@angular/core';\nimport {\n buildTemplateSpec,\n collectLeafTargets,\n formatConfigProblems,\n type EntityFormConfig,\n type FormRule,\n type ImportLookups,\n type ImportResult,\n type MappingPlan,\n} from '@dynamic-entity/core';\nimport { IMPORT_TRANSPORT } from '../tokens/injection-tokens';\nimport { UiTextService } from '../services/ui-text.service';\nimport { LookupRegistryService } from '../services/lookup-registry.service';\nimport { LocalImportTransport } from './local-import-transport';\nimport { ImportErrorsComponent } from './import-errors.component';\nimport { ImportMapperComponent } from './import-mapper.component';\nimport { ImportPreviewComponent } from './import-preview.component';\nimport { ImportTemplateComponent } from './import-template.component';\nimport type { ImportContext, ImportTransport, TemplateFormat } from './import-contracts';\n\ntype Step = 'upload' | 'map' | 'review' | 'done';\n\n/**\n * The import wizard: choose a file, match its columns, look at what that produced, commit.\n *\n * It holds no import logic of its own. Everything it does goes through an `ImportTransport`,\n * which by default is the in-browser one built on `@dynamic-entity/core` — so the wizard\n * works with no backend, and a consumer who registers a server transport gets the same\n * screens over the same mapping rules rather than a second implementation of them.\n *\n * The review step exists because the expensive mistake here is not a file that fails to\n * import, it is one that imports *successfully into the wrong fields*. That is invisible in a\n * summary and obvious in five rendered rows.\n */\n@Component({\n selector: 'ngx-entity-import',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ImportTemplateComponent,\n ImportMapperComponent,\n ImportPreviewComponent,\n ImportErrorsComponent,\n ],\n template: `\n <div class=\"ngx-import\" data-testid=\"entity-import\">\n <ol class=\"ngx-import__steps\" data-testid=\"import-steps\">\n @for (name of steps; track name) {\n <li\n class=\"ngx-import__step\"\n [class.ngx-import__step--current]=\"step() === name\"\n [attr.aria-current]=\"step() === name ? 'step' : null\"\n [attr.data-testid]=\"'import-step-' + name\"\n >\n {{ stepLabel(name) }}\n </li>\n }\n </ol>\n\n @if (problem(); as text) {\n <p class=\"ngx-import__problem\" role=\"alert\" data-testid=\"import-problem\">{{ text }}</p>\n }\n\n @switch (step()) {\n @case ('upload') {\n <ngx-import-template\n [config]=\"config\"\n [language]=\"language\"\n (download)=\"downloadTemplate($event)\"\n />\n\n <label class=\"ngx-import__file\">\n <span>{{ ui.text('importChooseFile', language) }}</span>\n <input type=\"file\" data-testid=\"import-file\" (change)=\"chooseFile($event)\" />\n </label>\n\n @if (busy()) {\n <p data-testid=\"import-reading\">{{ ui.text('importReading', language) }}</p>\n }\n @if (fileName()) {\n <p data-testid=\"import-file-chosen\">\n {{ ui.text('importFileChosen', language, { name: fileName(), rows: rowCount() }) }}\n </p>\n }\n }\n\n @case ('map') {\n <ngx-import-mapper\n [config]=\"config\"\n [headers]=\"headers()\"\n [plan]=\"plan()\"\n [language]=\"language\"\n (planChange)=\"plan.set($event)\"\n />\n <button type=\"button\" data-testid=\"import-to-review\" (click)=\"step.set('review')\">\n {{ ui.text('importReview', language) }}\n </button>\n }\n\n @case ('review') {\n @if (plan(); as current) {\n <ngx-import-preview\n [config]=\"config\"\n [plan]=\"current\"\n [rows]=\"sample()\"\n [lookups]=\"resolvedLookups()\"\n [rules]=\"rules\"\n [language]=\"language\"\n />\n }\n <button\n type=\"button\"\n data-testid=\"import-commit\"\n [disabled]=\"busy()\"\n (click)=\"commit()\"\n >\n {{\n busy()\n ? ui.text('importImporting', language)\n : ui.text('importRunImport', language, { count: rowCount() })\n }}\n </button>\n <button type=\"button\" data-testid=\"import-back\" (click)=\"step.set('map')\">\n {{ ui.text('importMap', language) }}\n </button>\n }\n\n @case ('done') {\n @if (result(); as done) {\n <p data-testid=\"import-succeeded\">\n {{ ui.text('importSucceeded', language, { count: importedCount(done) }) }}\n </p>\n @if (done.skipped) {\n <p data-testid=\"import-skipped\">\n {{ ui.text('importSkippedRows', language, { count: done.skipped }) }}\n </p>\n }\n @if (failedRowCount(done)) {\n <p data-testid=\"import-failed\">\n {{ ui.text('importFailedRows', language, { count: failedRowCount(done) }) }}\n </p>\n }\n @if (done.truncated) {\n <p data-testid=\"import-errors-truncated\">\n {{\n ui.text('importErrorsTruncated', language, {\n shown: done.errors.length,\n count: done.errorCount ?? done.errors.length,\n })\n }}\n </p>\n }\n <ngx-import-errors [errors]=\"done.errors\" [language]=\"language\" />\n }\n <button type=\"button\" data-testid=\"import-restart\" (click)=\"restart()\">\n {{ ui.text('importStartOver', language) }}\n </button>\n }\n }\n </div>\n `,\n styles: [\n `\n .ngx-import {\n display: flex;\n flex-direction: column;\n gap: var(--ngx-gap, 16px);\n color: var(--ngx-color-text, #1f2937);\n font-size: var(--ngx-font-size, 14px);\n }\n .ngx-import__steps {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n list-style: none;\n margin: 0;\n padding: 0;\n }\n .ngx-import__step {\n padding: 4px 12px;\n border: 1px solid var(--ngx-color-border, #e5e7eb);\n border-radius: var(--ngx-radius-sm, 6px);\n color: var(--ngx-color-muted, #6b7280);\n background: var(--ngx-color-surface-alt, #f9fafb);\n }\n .ngx-import__step--current {\n color: var(--ngx-color-accent, #4f46e5);\n border-color: var(--ngx-color-accent, #4f46e5);\n background: var(--ngx-color-accent-soft, #e0e7ff);\n font-weight: 600;\n }\n .ngx-import__problem {\n margin: 0;\n padding: 10px 12px;\n border: 1px solid var(--ngx-color-border, #fecaca);\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-error-soft, #fef2f2);\n color: var(--ngx-color-error, #b91c1c);\n /* A parser message can be a whole sentence with a filename in it. */\n overflow-wrap: anywhere;\n }\n .ngx-import__file {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 14px;\n border: 1px dashed var(--ngx-color-border, #d1d5db);\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-surface, #ffffff);\n }\n .ngx-import button {\n align-self: flex-start;\n padding: 8px 16px;\n border: 1px solid var(--ngx-color-border, #d1d5db);\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-surface, #ffffff);\n color: inherit;\n font: inherit;\n cursor: pointer;\n }\n .ngx-import button:hover:not(:disabled) {\n border-color: var(--ngx-color-accent, #4f46e5);\n background: var(--ngx-color-accent-soft, #e0e7ff);\n }\n .ngx-import button:disabled {\n opacity: 0.55;\n cursor: not-allowed;\n }\n `,\n ],\n})\nexport class EntityImportComponent {\n @Input({ required: true }) config!: EntityFormConfig;\n /**\n * The rules the form is rendered with.\n *\n * Pass them, or the import checks field validators only — which is not what the form\n * enforces, and a required field hidden by a rule will fail every row.\n */\n @Input() rules?: readonly FormRule[];\n /**\n * Named lists, overriding what the wizard already resolves from `LOOKUP_REGISTRY`.\n *\n * Not something a host has to supply: every `listName` a config mentions is loaded from the\n * registry the renderer is already holding. Pass this only to override one.\n */\n @Input() lookups?: ImportLookups;\n @Input() language = 'en';\n /** Format asked of the transport when a template is downloaded. */\n @Input() templateFormat: TemplateFormat = 'csv';\n\n /** The finished import, once it has run. */\n @Output() readonly importComplete = new EventEmitter<ImportResult>();\n /** A template the transport produced, for a host that would rather save it its own way. */\n @Output() readonly templateReady = new EventEmitter<Blob>();\n\n protected readonly ui = inject(UiTextService);\n protected readonly steps: Step[] = ['upload', 'map', 'review', 'done'];\n\n protected readonly step = signal<Step>('upload');\n protected readonly busy = signal(false);\n protected readonly problem = signal<string | null>(null);\n protected readonly headers = signal<string[]>([]);\n protected readonly sample = signal<string[][]>([]);\n protected readonly rowCount = signal(0);\n protected readonly fileName = signal('');\n protected readonly plan = signal<MappingPlan | null>(null);\n protected readonly result = signal<ImportResult | null>(null);\n\n private readonly registered = inject(IMPORT_TRANSPORT, { optional: true });\n private readonly local = inject(LocalImportTransport);\n private readonly lookupRegistry = inject(LookupRegistryService);\n private file: File | null = null;\n\n /** Named lists resolved from `LOOKUP_REGISTRY`, merged under the `lookups` input. */\n protected readonly resolvedLookups = signal<ImportLookups>({});\n\n private get transport(): ImportTransport {\n return this.registered ?? this.local;\n }\n\n private context(): ImportContext {\n return {\n config: this.config,\n rules: this.rules,\n lookups: this.resolvedLookups(),\n lang: this.language,\n };\n }\n\n /**\n * Load every named list this config's fields refer to.\n *\n * `@dynamic-entity/core` is framework-agnostic and cannot reach `LOOKUP_REGISTRY`, so\n * `coerceCell` takes the values as an argument. That is a reason for *core* to ask, not a\n * reason for the host to be asked — this package is holding the registry, and making the\n * consumer re-supply what the library already has is how a `listName` column ends up\n * storing the raw text `\"Gold\"` instead of the option object. Such a record renders\n * correctly and then matches no rule, which is the exact failure the option-shape contract\n * exists to prevent.\n *\n * The `lookups` input still wins where it names a list, so a host can override one without\n * having to provide all of them.\n */\n private async loadLookups(): Promise<void> {\n const fromRegistry: ImportLookups = {};\n\n const names = new Set<string>();\n for (const target of collectLeafTargets(this.config)) {\n if (target.field.listName) names.add(target.field.listName);\n }\n\n for (const listName of names) {\n // A list that fails to load is not a reason to refuse the import: the field falls back\n // to passing its text through, which is what happens today for an unregistered list.\n try {\n const options = await this.lookupRegistry.resolveOptions(\n { id: listName, type: 'dropdown', label: {}, listName },\n this.language,\n );\n if (options.length) fromRegistry[listName] = options;\n } catch {\n /* left out, so the field passes its text through */\n }\n }\n\n this.resolvedLookups.set({ ...fromRegistry, ...(this.lookups ?? {}) });\n }\n\n protected stepLabel(step: Step): string {\n // One key per step rather than an index, so a translator sees words and not positions.\n const keys = {\n upload: 'importUpload',\n map: 'importMap',\n review: 'importReview',\n done: 'importDone',\n } as const;\n return this.ui.text(keys[step], this.language);\n }\n\n protected async chooseFile(event: Event): Promise<void> {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0] ?? null;\n if (!file) {\n this.problem.set(this.ui.text('importNeedFile', this.language));\n return;\n }\n\n this.problem.set(null);\n this.busy.set(true);\n\n try {\n await this.loadLookups();\n const preview = await this.transport.preview(file, this.context());\n // Assigned only once the file has been read: holding a file whose headers describe the\n // previous one is an invariant worth not having to reason about.\n this.file = file;\n this.fileName.set(file.name);\n this.headers.set(preview.headers);\n this.sample.set(preview.sample);\n this.rowCount.set(preview.rowCount);\n this.plan.set(preview.suggestion);\n this.step.set('map');\n } catch (error) {\n // A parser refusing a format, or a file that is not what it claims, is ordinary user\n // input rather than a defect — it is reported where the user is looking.\n this.problem.set(messageOf(error));\n } finally {\n this.busy.set(false);\n }\n }\n\n protected async commit(): Promise<void> {\n const plan = this.plan();\n if (!this.file || !plan) {\n this.problem.set(this.ui.text('importNeedFile', this.language));\n return;\n }\n\n this.busy.set(true);\n this.problem.set(null);\n\n try {\n const result = await this.transport.commit(this.file, plan, this.context());\n\n // A plan-level error means nothing was imported, and saying \"imported 0 records\" would\n // describe that as a successful run of an empty file.\n const fatal = result.planProblems?.filter(p => p.level === 'error') ?? [];\n if (fatal.length) {\n this.problem.set(\n this.ui.text('importPlanProblem', this.language, {\n message: formatConfigProblems(fatal),\n }),\n );\n this.step.set('map');\n return;\n }\n\n this.result.set(result);\n this.step.set('done');\n this.importComplete.emit(result);\n } catch (error) {\n this.problem.set(messageOf(error));\n } finally {\n this.busy.set(false);\n }\n }\n\n protected async downloadTemplate(fields: string[]): Promise<void> {\n this.problem.set(null);\n try {\n const spec = buildTemplateSpec(this.config, { lang: this.language, fields });\n // The selection as well as the spec. A server transport needs the choice, not the\n // expansion of it — and recovering one from the other is a round trip that only works\n // while the expansion stays exactly invertible.\n const blob = await this.transport.template(spec, this.templateFormat, this.context(), fields);\n this.templateReady.emit(blob);\n saveBlob(blob, `${this.config?.entity || 'import'}-template.${this.templateFormat}`);\n } catch (error) {\n this.problem.set(messageOf(error));\n }\n }\n\n /**\n * How many records were written.\n *\n * `records.length` for the in-browser transport, which returns every record it built, and\n * `imported` for a server one, which streamed the file precisely so that fifty thousand\n * records never had to exist at once and therefore has a number rather than a list. Reading\n * `records.length` alone would report a successful import of nothing.\n */\n protected importedCount(result: ImportResult): number {\n return result.imported ?? result.records.length;\n }\n\n /**\n * How many distinct rows failed, not how many problems they had between them.\n *\n * `failed` when the transport reports it, and the distinct rows in `errors` only when it does\n * not. Counting the errors alone was wrong the moment a transport started capping them: a run\n * of a thousand rows where two hundred failed said **seven**, because seven was how many\n * distinct rows fitted inside the first twenty retained problems. This is the number a user\n * acts on — which rows do I go and fix — so a confident wrong answer is the worst of the\n * available ones. The in-browser transport returns every error, so counting them there is\n * exact and `failed` is absent.\n */\n protected failedRowCount(result: ImportResult): number {\n return result.failed ?? new Set(result.errors.map(error => error.row)).size;\n }\n\n protected restart(): void {\n this.file = null;\n this.fileName.set('');\n this.headers.set([]);\n this.sample.set([]);\n this.rowCount.set(0);\n this.plan.set(null);\n this.result.set(null);\n this.problem.set(null);\n this.step.set('upload');\n }\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Hand a generated file to the browser.\n *\n * The object URL is revoked on the next turn rather than immediately: revoking it in the same\n * task can cancel the download that was just started, and the leak of waiting one tick is a\n * single URL.\n */\nfunction saveBlob(blob: Blob, filename: string): void {\n if (typeof document === 'undefined') return;\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = filename;\n anchor.style.display = 'none';\n document.body.appendChild(anchor);\n anchor.click();\n document.body.removeChild(anchor);\n setTimeout(() => URL.revokeObjectURL(url));\n}\n","// Tokens\nexport * from './lib/tokens/injection-tokens';\n\n// Providers\nexport * from './lib/providers/provide-ngx-dynamic-entity';\nexport * from './lib/providers/provide-field-types';\n\n// Services\nexport * from './lib/services/field-registry.service';\nexport * from './lib/services/hook-registry.service';\nexport * from './lib/services/validator-registry.service';\nexport * from './lib/services/entity-ref-registry.service';\nexport * from './lib/services/entity-ref-selection.service';\nexport * from './lib/services/cascade-data.service';\nexport * from './lib/services/entity-reference.service';\nexport * from './lib/services/entity-ref-cache';\nexport * from './lib/services/lookup-registry.service';\nexport * from './lib/services/rbac.service';\nexport * from './lib/services/rules-evaluation.service';\nexport * from './lib/services/config-source.service';\nexport * from './lib/services/validation-messages.service';\nexport * from './lib/services/ui-text.service';\n\n// Components — the library ships form UI only; rendering a data table is the consumer's choice.\nexport * from './lib/form/dynamic-form.component';\nexport * from './lib/form/dynamic-record-form.component';\nexport * from './lib/form/dynamic-field/dynamic-field.component';\n\n// Import wizard — the shell, and each screen individually, same reusability rule as above.\nexport * from './lib/import/import-contracts';\nexport * from './lib/import/sheet-parser';\nexport * from './lib/import/local-import-transport';\nexport * from './lib/import/http-import-transport';\nexport * from './lib/import/entity-import.component';\nexport * from './lib/import/import-mapper.component';\nexport * from './lib/import/import-preview.component';\nexport * from './lib/import/import-template.component';\nexport * from './lib/import/import-errors.component';\n\n// The contract a field component must satisfy to be registered with provideFieldTypes.\n// Previously this existed only as a code comment and an ADR that is gitignored, so a\n// consumer had no interface to implement against.\nexport * from './lib/field-types/field-component.contract';\n// Unique DOM ids, for a custom field type that renders a `<label for>` — see the contract.\nexport * from './lib/field-types/field-dom-id';\n\n// Field type components — every one, individually importable.\n//\n// The tree-shaking seam is `provideFieldTypes({ image: ImageFieldComponent })`: register\n// only what you use and the rest never enters the bundle. That only works for components a\n// consumer can name, and ten of these were unreachable — so wanting eleven of the twenty\n// meant calling provideBuiltInFieldTypes() and bundling all of them, which is exactly what\n// the seam exists to avoid.\nexport * from './lib/field-types/text-field.component';\nexport * from './lib/field-types/textarea-field.component';\nexport * from './lib/field-types/markdown-field.component';\nexport * from './lib/field-types/number-field.component';\nexport * from './lib/field-types/currency-field.component';\nexport * from './lib/field-types/email-field.component';\nexport * from './lib/field-types/password-field.component';\nexport * from './lib/field-types/checkbox-field.component';\nexport * from './lib/field-types/boolean-field.component';\nexport * from './lib/field-types/date-field.component';\nexport * from './lib/field-types/date-time-field.component';\nexport * from './lib/field-types/time-field.component';\nexport * from './lib/field-types/month-year-field.component';\nexport * from './lib/field-types/dropdown-field.component';\nexport * from './lib/field-types/radio-field.component';\nexport * from './lib/field-types/multi-select-field.component';\nexport * from './lib/field-types/entity-ref-field.component';\nexport * from './lib/field-types/group-field.component';\nexport * from './lib/field-types/array-field.component';\nexport * from './lib/field-types/image-field.component';\nexport * from './lib/field-types/file-field.component';\n\n// Value helpers — a dropdown value is now a language-keyed object, so a consumer rendering\n// record values needs these. Re-exported so they don't have to depend on core directly.\nexport {\n resolveLabel,\n resolveOptionLabel,\n resolveOptionValue,\n formatDisplayValue,\n valuesMatch,\n normalizeOption,\n normalizeConfig,\n} from '@dynamic-entity/core';\n\n// Re-export core types so consumers need only one import\nexport type {\n EntityFormConfig,\n NestedTabConfig,\n NestedFieldConfig,\n FieldTableConfig,\n RichFieldType,\n LocalizedText,\n DropdownOption,\n VersionedRecord,\n EntityPermissions,\n RbacContext,\n FieldValidators,\n EntityReferenceConfig,\n EntityReferenceLoader,\n ReferenceOption,\n ReferenceLoaderContext,\n AutoPatchConfig,\n PatchOnTrueMapping,\n FileRef,\n FormRule,\n RuleCondition,\n RuleAction,\n RuleEvaluationResult,\n CommonModuleEntry,\n ComponentClass,\n} from '@dynamic-entity/core';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["coreResolveEffectiveMask","coreShouldMaskField"],"mappings":"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"}
1
+ {"version":3,"file":"ngx-dynamic-entity.mjs","sources":["../../src/lib/services/entity-ref-cache.ts","../../src/lib/tokens/injection-tokens.ts","../../src/lib/providers/provide-ngx-dynamic-entity.ts","../../src/lib/services/validation-messages.service.ts","../../src/lib/field-types/field-dom-id.ts","../../src/lib/field-types/text-field.component.ts","../../src/lib/field-types/textarea-field.component.ts","../../src/lib/services/ui-text.service.ts","../../src/lib/field-types/markdown-field.component.ts","../../src/lib/field-types/number-field.component.ts","../../src/lib/field-types/currency-field.component.ts","../../src/lib/field-types/email-field.component.ts","../../src/lib/field-types/password-field.component.ts","../../src/lib/field-types/checkbox-field.component.ts","../../src/lib/field-types/boolean-field.component.ts","../../src/lib/field-types/date-field.component.ts","../../src/lib/field-types/date-time-field.component.ts","../../src/lib/field-types/time-field.component.ts","../../src/lib/field-types/month-year-field.component.ts","../../src/lib/services/lookup-registry.service.ts","../../src/lib/field-types/dropdown-field.component.ts","../../src/lib/field-types/radio-field.component.ts","../../src/lib/field-types/multi-select-field.component.ts","../../src/lib/services/entity-ref-registry.service.ts","../../src/lib/services/entity-reference.service.ts","../../src/lib/services/cascade-data.service.ts","../../src/lib/services/entity-ref-selection.service.ts","../../src/lib/field-types/entity-ref-field.component.ts","../../src/lib/services/field-registry.service.ts","../../src/lib/services/rbac.service.ts","../../src/lib/form/dynamic-field/dynamic-field.component.ts","../../src/lib/field-types/group-field.component.ts","../../src/lib/services/validator-registry.service.ts","../../src/lib/field-types/array-field.component.ts","../../src/lib/services/file-upload.service.ts","../../src/lib/field-types/image-field.component.ts","../../src/lib/field-types/file-field.component.ts","../../src/lib/providers/provide-field-types.ts","../../src/lib/services/hook-registry.service.ts","../../src/lib/services/rules-evaluation.service.ts","../../src/lib/services/config-source.service.ts","../../src/lib/form/form-structure.service.ts","../../src/lib/form/dynamic-form.component.ts","../../src/lib/form/dynamic-form.component.html","../../src/lib/form/dynamic-record-form.component.ts","../../src/lib/form/dynamic-record-form.component.html","../../src/lib/import/import-contracts.ts","../../src/lib/import/sheet-parser.ts","../../src/lib/import/local-import-transport.ts","../../src/lib/import/http-import-transport.ts","../../src/lib/import/import-errors.component.ts","../../src/lib/import/import-mapper.component.ts","../../src/lib/import/import-preview.component.ts","../../src/lib/import/import-template.component.ts","../../src/lib/import/entity-import.component.ts","../../src/public-api.ts","../../src/ngx-dynamic-entity.ts"],"sourcesContent":["import type { ReferenceOption } from '@dynamic-entity/core';\n\n/**\n * Backing store for cached reference options.\n *\n * Pluggable on purpose. The reference implementation kept its cache in a service instance,\n * so every entity label was re-fetched on a browser refresh (issue #22 in the architecture\n * doc). A consumer that wants the cache to survive a reload can back this with\n * sessionStorage; the default keeps it in memory, which is the right call for a library\n * that must not silently persist a tenant's data.\n */\nexport interface EntityRefCacheStore {\n get(key: string): ReferenceOption[] | undefined;\n set(key: string, value: ReferenceOption[]): void;\n delete(key: string): void;\n /** Every key currently held — used for prefix invalidation of one entity. */\n keys(): string[];\n clear(): void;\n}\n\n/** Default in-memory store. Lives as long as the injector that created it. */\nexport class InMemoryEntityRefCacheStore implements EntityRefCacheStore {\n private readonly map = new Map<string, ReferenceOption[]>();\n\n get(key: string): ReferenceOption[] | undefined {\n return this.map.get(key);\n }\n\n set(key: string, value: ReferenceOption[]): void {\n this.map.set(key, value);\n }\n\n delete(key: string): void {\n this.map.delete(key);\n }\n\n keys(): string[] {\n return [...this.map.keys()];\n }\n\n clear(): void {\n this.map.clear();\n }\n}\n","import { InjectionToken } from '@angular/core';\nimport type { Type } from '@angular/core';\nimport type {\n CommonModuleEntry,\n EntityReferenceLoader,\n FileUploadHandler,\n LookupListSource,\n RecordMigration,\n} from '@dynamic-entity/core';\nimport { InMemoryEntityRefCacheStore, type EntityRefCacheStore } from '../services/entity-ref-cache';\nimport type { UiTextOverrides } from '../services/ui-text.service';\nimport type { ImportTransport, SheetParser } from '../import/import-contracts';\n\n/** Roles that see XXXXXXXXX for masked fields. Presentational only — enforce authz server-side. */\nexport const MASKED_ROLES = new InjectionToken<string[]>('MASKED_ROLES');\n\n/**\n * Consumer **overrides**: fieldType string → Angular component class.\n * Highest priority — beats anything registered through `provideFieldTypes()`.\n */\nexport const FIELD_TYPE_REGISTRY = new InjectionToken<Map<string, Type<any>>>('FIELD_TYPE_REGISTRY');\n\n/**\n * Multi-provider of field-type sets, contributed by `provideFieldTypes()` /\n * `provideBuiltInFieldTypes()`. Multi so several calls compose instead of clobbering;\n * later sets win on key collision. This is the seam that keeps unused field components\n * out of the bundle — nothing is imported until a set names it.\n */\nexport const FIELD_TYPE_SETS = new InjectionToken<Record<string, Type<any>>[]>('FIELD_TYPE_SETS');\n\n/**\n * Registry: entity key → option loader.\n *\n * A loader receives a `ReferenceLoaderContext` (`parentValue`, `filters`, `lang`) and may\n * return an array, a Promise, or an Observable of `ReferenceOption[]`. `ctx` is optional,\n * so a zero-arg loader (`() => svc.list()`) is still a valid registration.\n */\nexport const ENTITY_REF_REGISTRY = new InjectionToken<Map<string, EntityReferenceLoader>>('ENTITY_REF_REGISTRY');\n\n/**\n * Registry: list name → the values of a named master list (`field.listName`).\n *\n * A source may be the values themselves (array / Promise / Observable) or a **loader function**,\n * which is what you want for anything fetched: a bare Promise is created when the provider is\n * built, so every list would load whether or not a form uses it.\n *\n * Values are normalised by `normalizeLookupValues` — bare strings and `LocalizedText` are\n * accepted alongside the full `{ code, name, sortOrder }` shape.\n *\n * @example\n * provideNgxDynamicEntity({\n * lookups: {\n * employeeStatus: () => listService.getByName('employeeStatus'),\n * grades: ['Junior', 'Senior'],\n * },\n * })\n */\nexport const LOOKUP_REGISTRY = new InjectionToken<Map<string, LookupListSource>>('LOOKUP_REGISTRY');\n\n/**\n * Ordered steps that move a saved record forward when a config's `version` increases.\n *\n * Without these, `EntityFormConfig.version` and `VersionedRecord._configVersion` are\n * declarations nothing acts on: a schema can be edited freely while records keep their old\n * shape, and nothing reconciles the two. Registering migrations makes the version numbers\n * mean something.\n *\n * @example\n * provideNgxDynamicEntity({\n * migrations: [\n * { from: 1, to: 2, description: 'split name', migrate: r => ({ ...r, firstName: r['name'] }) },\n * ],\n * })\n */\nexport const RECORD_MIGRATIONS = new InjectionToken<RecordMigration[]>('RECORD_MIGRATIONS');\n\n/**\n * Overrides for the messages shown under an invalid field, keyed by Angular error key\n * (`required`, `minlength`, `pattern`, …) plus a few field-specific keys.\n *\n * The built-in messages are English literals. Registering here is what makes a non-English\n * form possible without re-implementing every field component; unlisted keys keep their\n * default, so overriding one does not mean supplying them all.\n */\nexport const VALIDATION_MESSAGES = new InjectionToken<Record<string, any>>('VALIDATION_MESSAGES');\n\n/** Registry: validator key → ValidatorFn */\nexport const VALIDATOR_REGISTRY = new InjectionToken<Map<string, any>>('VALIDATOR_REGISTRY');\n\n/**\n * Registry: validator key → AsyncValidatorFn.\n *\n * Kept separate from VALIDATOR_REGISTRY because Angular applies the two differently: an async\n * validator runs only once the synchronous ones pass, and puts the control into `pending`\n * while it does. Name them from a schema with `validators: { customAsync: ['uniqueEmail'] }`.\n */\nexport const ASYNC_VALIDATOR_REGISTRY = new InjectionToken<Map<string, any>>('ASYNC_VALIDATOR_REGISTRY');\n\n/**\n * A registered hook: receives the payload, returns it (or a replacement), sync or async.\n *\n * Spelled out rather than typed as `Function`, which accepts class declarations and any\n * arity and gives a consumer no signature to write against.\n */\nexport type HookFn = (data: any, context?: unknown) => unknown | Promise<unknown>;\n\n/** Registry: hook key → async (data, context) => data */\nexport const HOOK_REGISTRY = new InjectionToken<Map<string, HookFn>>('HOOK_REGISTRY');\n\n/**\n * Consumer-registered list of common module tabs (documents, audit, tasks, etc.).\n * The library ships no built-in implementations. Consumers provide their own list\n * so the builder's module-picker and the renderer's tab switcher know what's available.\n *\n * `component` must be the component **class**: it is mounted through `ngComponentOutlet`,\n * which takes a type, not a selector. An entry naming a selector string renders nothing and\n * warns — `COMMON_MODULES` in core is a catalogue of names for the builder's picker, and\n * offering a module the renderer cannot mount is the one way to get this wrong.\n *\n * @example\n * providers: [\n * {\n * provide: COMMON_MODULES_REGISTRY,\n * useValue: [\n * { id: 'documents', label: { en: 'Documents' }, component: DocumentsViewComponent },\n * { id: 'audit', label: { en: 'Audit Log' }, component: AuditLogComponent },\n * ] satisfies CommonModuleEntry[]\n * }\n * ]\n */\nexport const COMMON_MODULES_REGISTRY = new InjectionToken<CommonModuleEntry[]>('COMMON_MODULES_REGISTRY');\n\n/**\n * Consumer-provided file/image upload handler.\n * When supplied, image-field and file-field call it to persist the File and receive a stable\n * URL back. Without it the field stores `{ file, name, size, mimeType }` for the consumer to\n * upload on submit. May return the result directly, as a Promise, or as an Observable.\n *\n * @example\n * { provide: UPLOAD_HANDLER, useFactory: () => (file: File) => myUploadService.upload(file) }\n */\nexport const UPLOAD_HANDLER = new InjectionToken<FileUploadHandler>('UPLOAD_HANDLER');\n\n/**\n * Reads an uploaded spreadsheet into headers and positional rows, for the import wizard.\n *\n * Unregistered, the wizard reads CSV with the dependency-free parser in\n * `@dynamic-entity/core`, so it works with nothing provided. Register one to accept `.xlsx`\n * — which spreadsheet library that uses stays the consumer's choice, and this package keeps\n * having no runtime dependency.\n *\n * Rows come back **positional** (`string[][]`) rather than keyed by header, because a real\n * sheet has duplicate headers and blank ones; a header-keyed row silently loses the second\n * of two columns both called \"Notes\".\n *\n * @example\n * provideNgxDynamicEntity({\n * sheetParser: async file => {\n * const wb = XLSX.read(await file.arrayBuffer());\n * const rows = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], {\n * header: 1, raw: false, defval: '',\n * }) as string[][];\n * return { headers: rows[0] ?? [], rows: rows.slice(1) };\n * },\n * })\n */\nexport const SHEET_PARSER = new InjectionToken<SheetParser>('SHEET_PARSER');\n\n/**\n * Where an import's work happens.\n *\n * Unregistered, everything runs in the browser through `@dynamic-entity/core` and nothing\n * touches the network — the wizard is fully usable with no backend. Register one that posts\n * to a server and the same components drive that instead, over the same pure mapping engine,\n * which is what keeps a client-side import and a server-side one from disagreeing about what\n * they produced.\n *\n * The reason to register one is size: the default reads the whole file into memory, which is\n * right for a sheet somebody assembled and wrong for a fifty-thousand-row export.\n *\n * @example\n * { provide: IMPORT_TRANSPORT, useClass: HttpImportTransport }\n */\nexport const IMPORT_TRANSPORT = new InjectionToken<ImportTransport>('IMPORT_TRANSPORT');\n\n/**\n * Backing store for the entity-reference options cache. Defaults to in-memory.\n * Provide your own to make the cache outlive a page refresh.\n *\n * @example\n * { provide: ENTITY_REF_CACHE_STORE, useClass: SessionStorageRefCache }\n */\nexport const ENTITY_REF_CACHE_STORE = new InjectionToken<EntityRefCacheStore>('ENTITY_REF_CACHE_STORE', {\n providedIn: 'root',\n factory: () => new InMemoryEntityRefCacheStore(),\n});\n\n/**\n * Consumer-provided predicate function to check whether user roles can edit system default tabs or fields.\n * Defaults to allowing edits if not provided.\n */\nexport const SYSTEM_DEFAULT_CAN_EDIT = new InjectionToken<(roles: string[]) => boolean>('SYSTEM_DEFAULT_CAN_EDIT');\n\nexport type ConfigSourceHandler = (entityKey: string) => any;\n\n/**\n * Registry/Resolver for resolving an EntityFormConfig by entity key across entities (Phase 8).\n * Enables cross-entity field referencing (`isReferenced`, `referencedEntityKey`, `referencedFieldId`, `hasDrift`).\n */\nexport const CONFIG_SOURCE = new InjectionToken<ConfigSourceHandler>('CONFIG_SOURCE');\n\n/**\n * Turns the markdown a `markdown` field stores into HTML for display.\n *\n * Optional, and deliberately not bundled: these packages declare no runtime dependencies\n * beyond `tslib`, and a markdown parser is a large one to force on every consumer. Without\n * a renderer the field still works — it stores and shows the source text, with line breaks\n * preserved and nothing interpreted.\n *\n * The returned HTML is bound through `[innerHTML]`, so Angular's sanitizer strips scripts\n * and event handlers before it reaches the DOM. That is a backstop, not a licence: a\n * renderer should still be configured to escape raw HTML in its input, because sanitizing\n * removes the dangerous parts silently rather than telling the author their content was\n * altered.\n *\n * @example\n * import { marked } from 'marked';\n * { provide: MARKDOWN_RENDERER, useValue: (src: string) => marked.parse(src) as string }\n */\nexport const MARKDOWN_RENDERER = new InjectionToken<(source: string) => string>('MARKDOWN_RENDERER');\n\n/**\n * The text a masked field shows in place of its value. Defaults to `XXXXXXXXX`.\n *\n * Masking is presentational — see SECURITY.md — and what it prints is a product decision:\n * `••••••••` reads as a redaction, \"Hidden\" reads as a permission, and a localized string\n * reads as neither in English. It was a literal repeated across every field component, so\n * there was no way to choose.\n *\n * @example\n * { provide: MASKED_PLACEHOLDER, useValue: '••••••••' }\n */\nexport const MASKED_PLACEHOLDER = new InjectionToken<string>('MASKED_PLACEHOLDER');\n\n/**\n * Overrides for the library's own chrome — Save, Reset, \"No rows yet.\", and the rest.\n *\n * Field labels and options come from the config as `LocalizedText` and already follow the\n * form's `language`. This is the text *around* them, which was English literals in the\n * templates: an application in German rendered German labels around English buttons.\n *\n * The library does no translating — it publishes the keys it renders and resolves whatever\n * a host hands back. `DEFAULT_UI_TEXT` is the full list of keys with their English source\n * strings, so a translation file can be generated from it rather than transcribed. Anything\n * left out keeps its English default.\n *\n * @example The config's own shape — `LocalizedText` per key, resolved against `language`\n * {\n * provide: UI_TEXT,\n * useValue: {\n * save: { en: 'Save', de: 'Speichern' },\n * reset: { en: 'Reset', de: 'Zurücksetzen' },\n * },\n * }\n *\n * @example One language, or a host that re-provides on switch\n * { provide: UI_TEXT, useValue: { save: 'Speichern', reset: 'Zurücksetzen' } }\n *\n * @example An existing i18n layer (ngx-translate, Transloco, $localize)\n * {\n * provide: UI_TEXT,\n * useFactory: () => {\n * const translate = inject(TranslateService);\n * return (key, defaultText) => translate.instant(`dynamicEntity.${key}`) || defaultText;\n * },\n * }\n *\n * A resolver is read during change detection, so it must be synchronous and cheap.\n */\nexport const UI_TEXT = new InjectionToken<UiTextOverrides>('UI_TEXT');\n","import { EnvironmentProviders, makeEnvironmentProviders, Type } from '@angular/core';\nimport type { EntityReferenceLoader, LookupListSource, RecordMigration } from '@dynamic-entity/core';\nimport {\n ENTITY_REF_REGISTRY,\n FIELD_TYPE_REGISTRY,\n HOOK_REGISTRY,\n type HookFn,\n ASYNC_VALIDATOR_REGISTRY,\n RECORD_MIGRATIONS,\n VALIDATION_MESSAGES,\n LOOKUP_REGISTRY,\n MASKED_ROLES,\n UI_TEXT,\n VALIDATOR_REGISTRY,\n SHEET_PARSER,\n IMPORT_TRANSPORT,\n} from '../tokens/injection-tokens';\nimport type { UiTextOverrides } from '../services/ui-text.service';\nimport type { ImportTransport, SheetParser } from '../import/import-contracts';\n\nexport interface NgxDynamicEntityConfig {\n /** Roles that see masked field values as XXXXXXXXX */\n maskedRoles?: string[];\n /** Custom field type components keyed by type string */\n fieldTypes?: Record<string, Type<any>>;\n /**\n * Entity-ref option loaders keyed by entity key.\n * Each receives `{ parentValue, filters, lang }` and may return an array, Promise, or Observable.\n */\n entityRefs?: Record<string, EntityReferenceLoader>;\n /**\n * Named master lists keyed by list name, for fields that set `listName`.\n * Each may be the values themselves (array/Promise/Observable) or a loader function — prefer\n * a loader for anything fetched, so an unused list is never loaded.\n */\n lookups?: Record<string, LookupListSource>;\n /**\n * Override the messages shown under invalid fields, keyed by Angular error key. A value is\n * a string, or a function receiving `(language, error)` when it needs the error's detail.\n * Unlisted keys keep their English default.\n */\n validationMessages?: Record<string, string | ((language: string, error: any) => string)>;\n /**\n * Override the library's own chrome — Save, Reset, \"No rows yet.\". Either a partial map\n * keyed by `UiTextKey`, whose values are strings or the same `LocalizedText` a field label\n * uses (`{ en, de }`, resolved against the form's `language`), or a resolver\n * `(key, defaultText, language) => string` that hands the key to an existing i18n layer.\n * `DEFAULT_UI_TEXT` lists every key with its English source string; unlisted keys keep it.\n */\n uiText?: UiTextOverrides;\n /**\n * Async validator functions keyed by name, for checks that need a server — uniqueness,\n * availability, a remote rule. Name them from a schema with\n * `validators: { customAsync: ['uniqueEmail'] }`.\n *\n * Each is an Angular `AsyncValidatorFn`: it receives the control and returns a Promise or\n * Observable of `ValidationErrors | null`. The control is `pending` while it runs, and the\n * form cannot be submitted until every pending check settles.\n */\n asyncValidators?: Record<string, any>;\n /** Custom validator functions keyed by validator name */\n validators?: Record<string, any>;\n /** Hook functions keyed by hook name */\n hooks?: Record<string, HookFn>;\n /**\n * Ordered steps that upgrade a saved record when `EntityFormConfig.version` moves ahead\n * of the record's `_configVersion`. Applied to `initialData` before the form is patched.\n */\n migrations?: RecordMigration[];\n /**\n * Reads an uploaded spreadsheet for the import wizard, as `{ headers, rows }` with rows\n * positional rather than keyed by header.\n *\n * Omit it and CSV is read by the dependency-free parser in `@dynamic-entity/core`; supply\n * one to accept `.xlsx`, using whichever spreadsheet library you already have.\n */\n sheetParser?: SheetParser;\n /**\n * Where an import's work happens. Omit it and the whole import runs in the browser with no\n * network at all; supply one that posts to a server for files too large to hold in memory.\n * Either way the mapping, coercion and validation are the same pure functions.\n */\n importTransport?: ImportTransport;\n}\n\n/**\n * Provider function for ngx-dynamic-entity.\n * All options are optional — consumers provide only what they use (ISP).\n *\n * Usage in app.config.ts:\n * provideNgxDynamicEntity({\n * maskedRoles: ['IT_SUPPORT'],\n * entityRefs: { clients: () => clientService.getOptions() },\n * })\n */\nexport const provideNgxDynamicEntity = (config: NgxDynamicEntityConfig = {}): EnvironmentProviders =>\n makeEnvironmentProviders([\n { provide: MASKED_ROLES, useValue: config.maskedRoles ?? [] },\n { provide: FIELD_TYPE_REGISTRY, useValue: new Map(Object.entries(config.fieldTypes ?? {})) },\n { provide: ENTITY_REF_REGISTRY, useValue: new Map(Object.entries(config.entityRefs ?? {})) },\n { provide: LOOKUP_REGISTRY, useValue: new Map(Object.entries(config.lookups ?? {})) },\n { provide: VALIDATOR_REGISTRY, useValue: new Map(Object.entries(config.validators ?? {})) },\n {\n provide: ASYNC_VALIDATOR_REGISTRY,\n useValue: new Map(Object.entries(config.asyncValidators ?? {})),\n },\n { provide: HOOK_REGISTRY, useValue: new Map(Object.entries(config.hooks ?? {})) },\n { provide: RECORD_MIGRATIONS, useValue: config.migrations ?? [] },\n { provide: VALIDATION_MESSAGES, useValue: config.validationMessages ?? {} },\n { provide: UI_TEXT, useValue: config.uiText ?? {} },\n // Both optional and both null when unset: the wizard falls back to the built-in CSV\n // parser and the in-browser transport, so it works with nothing registered.\n { provide: SHEET_PARSER, useValue: config.sheetParser ?? null },\n { provide: IMPORT_TRANSPORT, useValue: config.importTransport ?? null },\n ]);\n","import { Injectable, inject } from '@angular/core';\nimport type { ValidationErrors } from '@angular/forms';\nimport { VALIDATION_MESSAGES } from '../tokens/injection-tokens';\n\n/**\n * Resolves an Angular `ValidationErrors` object to the message shown under a field.\n *\n * These strings used to be hardcoded English literals inside each field component, so a\n * German form meant re-implementing every field type — the labels honoured `language` while\n * the errors underneath them did not.\n *\n * A message is a plain string, or a function when it needs the error's own detail\n * (`minlength.requiredLength`, `min.min`, and so on). The active `language` is passed\n * through, so one registration can serve every locale:\n *\n * ```typescript\n * provideNgxDynamicEntity({\n * validationMessages: {\n * required: lang => (lang === 'de' ? 'Pflichtfeld.' : 'This field is required.'),\n * minlength: (lang, err) => `Mindestens ${err['requiredLength']} Zeichen.`,\n * },\n * });\n * ```\n *\n * Unregistered keys fall back to the defaults below, so overriding one message does not\n * mean supplying them all.\n */\nexport type ValidationMessage = string | ((language: string, error: any) => string);\n\n/** The built-in English messages. Every key here can be overridden individually. */\nexport const DEFAULT_VALIDATION_MESSAGES: Record<string, ValidationMessage> = {\n required: 'This field is required.',\n requiredSelection: 'Please select an option.',\n email: 'Please enter a valid email address.',\n pattern: 'Invalid format.',\n minlength: (_lang, err) => `Minimum ${err?.requiredLength} characters required.`,\n maxlength: (_lang, err) => `Maximum ${err?.requiredLength} characters allowed.`,\n min: (_lang, err) => `Value must be at least ${err?.min}.`,\n max: (_lang, err) => `Value must not exceed ${err?.max}.`,\n invalid: 'Invalid value.',\n invalidNumber: 'Invalid number.',\n invalidSelection: 'Invalid selection.',\n};\n\n/** An error key, or a pair mapping one to a different message key. */\nexport type MessageOrderEntry = string | readonly [errorKey: string, messageKey: string];\n\n/**\n * The keys a plain input can raise, most specific first.\n *\n * A type that cannot raise one of these is unaffected by its presence — `resolve` returns the\n * first error actually on the control — so the shared list costs nothing and spares every\n * field component a near-identical copy of it.\n */\nconst COMMON_ORDER: readonly MessageOrderEntry[] = ['required', 'email', 'min', 'max', 'minlength', 'maxlength', 'pattern'];\n\n/**\n * Where a field type disagrees with the common list.\n *\n * Only three do, and each for a reason about how the control reads rather than what it can\n * raise: a select says \"Please select an option\" where an input says \"This field is\n * required\"; a number that is neither required nor out of range is not \"invalid\", it is not a\n * number; and a control with no text in it cannot fail a length or format rule.\n */\nconst ORDER_BY_FIELD_TYPE: Readonly<Record<string, { order: readonly MessageOrderEntry[]; fallback: string }>> = {\n dropdown: { order: [['required', 'requiredSelection']], fallback: 'invalidSelection' },\n number: { order: ['required', 'min', 'max'], fallback: 'invalidNumber' },\n boolean: { order: ['required', 'pattern'], fallback: 'invalid' },\n checkbox: { order: ['required', 'pattern'], fallback: 'invalid' },\n file: { order: ['required', 'pattern'], fallback: 'invalid' },\n image: { order: ['required', 'pattern'], fallback: 'invalid' },\n};\n\n@Injectable({ providedIn: 'root' })\nexport class ValidationMessagesService {\n private readonly overrides = inject(VALIDATION_MESSAGES, { optional: true }) ?? {};\n\n /**\n * The message for the first error present, in the order the caller lists.\n *\n * Order is the caller's because it is field-specific: a dropdown wants\n * `requiredSelection` where a text input wants `required`, and the first match wins so the\n * most specific message is the one shown.\n */\n resolve(\n errors: ValidationErrors | null | undefined,\n language: string,\n order: readonly (string | readonly [errorKey: string, messageKey: string])[],\n fallbackKey = 'invalid',\n ): string {\n if (!errors) return '';\n\n for (const entry of order) {\n // A tuple maps an Angular error key to a different message key: a dropdown raises the\n // standard `required` error but reads better as \"Please select an option\", and both\n // messages stay independently overridable.\n const [errorKey, messageKey] = typeof entry === 'string' ? [entry, entry] : entry;\n // `errors[errorKey]` is usually an object of detail, but `required` is simply `true`.\n if (errors[errorKey] === undefined) continue;\n return this.messageFor(messageKey, language, errors[errorKey]);\n }\n return this.messageFor(fallbackKey, language, null);\n }\n\n /**\n * The message for a field, chosen by its **type** rather than by a list the caller supplies.\n *\n * Every field component used to pass its own copy of the key order, and the copies were\n * near-identical — which was tolerable while the field itself was the only thing that\n * rendered a message. It stopped being tolerable when the error summary above the form\n * started naming what is wrong with each field: the summary has no field component to ask\n * (the offending field is usually on a tab that is not rendered), so it would have needed a\n * second copy of the same table, and a dropdown would have said \"This field is required\" in\n * the summary and \"Please select an option\" under the control.\n *\n * One table, read from both places, is what keeps those two sentences the same sentence.\n */\n resolveForField(errors: ValidationErrors | null | undefined, language: string, fieldType: string): string {\n const { order, fallback } = this.orderFor(fieldType);\n return this.resolve(errors, language, order, fallback);\n }\n\n /** A field type's key order. An unrecognised type — a consumer's own — gets the common list. */\n orderFor(fieldType: string): { order: readonly MessageOrderEntry[]; fallback: string } {\n return ORDER_BY_FIELD_TYPE[fieldType] ?? { order: COMMON_ORDER, fallback: 'invalid' };\n }\n\n /** One message by key, honouring an override before the default. */\n messageFor(key: string, language: string, error: unknown): string {\n const message = this.overrides[key] ?? DEFAULT_VALIDATION_MESSAGES[key];\n if (message === undefined) return '';\n return typeof message === 'function' ? message(language, error) : message;\n }\n}\n","/**\n * DOM ids that survive being rendered more than once.\n *\n * A field component used to derive its control's id straight from `field.id`. That is unique\n * in a config and *not* unique in a document: an `array` field renders the same child fields\n * once per row, so a two-row Contacts array put two `#name` inputs on the page. `<label for>`\n * resolves to the first match in document order, so clicking the second row's label focused\n * the first row's input, and a screen reader read the same association twice. Duplicate ids on\n * focusable elements are also a WCAG failure in their own right.\n *\n * The fix is a counter, which is what Angular Material does for the same reason: the id stays\n * readable — `email-de7` — and is unique for the lifetime of the page. It is deliberately not\n * derived from the row index, because a field component is given exactly five inputs and none\n * of them says where it is; adding a sixth would change the contract every custom field type\n * implements.\n *\n * Ids are not a public contract. Address a control in a test through its `data-testid`, which\n * is stable, or through its label, which is what a user sees.\n */\nlet sequence = 0;\n\n/** A token unique to one component instance, for the lifetime of the page. */\nexport function nextFieldInstanceId(): string {\n sequence += 1;\n return `de${sequence}`;\n}\n\n/**\n * `{fieldId}-{instance}{suffix}` — the field first, so the id still reads as the field it\n * belongs to when someone is looking at the DOM.\n *\n * `field` is undefined until the renderer assigns it, and a template can be checked once\n * before that happens.\n */\nexport function fieldDomId(field: { id?: string } | undefined, instance: string, suffix = ''): string {\n return `${field?.id ?? 'field'}-${instance}${suffix}`;\n}\n\n/**\n * The `aria-describedby` a control needs, given what is rendered beside it right now.\n *\n * A field can show two things under its control — the author's help text and, once touched, a\n * validation message — and a screen reader announces only what this attribute names. Three\n * field components named the error; the other sixteen named nothing at all, so their error\n * messages were on screen and silent. Help text would have inherited the same gap.\n *\n * Order matters: the hint describes the field and the error describes the attempt, so the hint\n * is read first. `null` rather than an empty string when there is nothing to describe — an\n * empty `aria-describedby` is a dangling reference, not an absent one.\n *\n * Shared rather than written into each of the twenty-one field components, because the rule is\n * the same everywhere and getting it wrong is invisible until somebody uses a screen reader.\n */\nexport function fieldDescribedBy(\n domId: (suffix?: string) => string,\n parts: { hint?: boolean; error?: boolean },\n): string | null {\n const ids: string[] = [];\n if (parts.hint) ids.push(domId('-hint'));\n if (parts.error) ids.push(domId('-error'));\n return ids.length ? ids.join(' ') : null;\n}\n","import { Component, Input, OnDestroy, inject, ChangeDetectionStrategy, signal } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport { Subscription } from 'rxjs';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-text-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--text\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n [class.ngx-field--invalid]=\"control && control.invalid && control.touched\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\"\n >{{ label }}\n @if (field.validators?.required) {\n <span class=\"ngx-field__req\">*</span>\n }\n </label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{ displayValue() ?? '—' }}</span>\n } @else {\n <input\n [id]=\"domId()\"\n type=\"text\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [formControl]=\"$any(control)\"\n [placeholder]=\"placeholder\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-invalid]=\"control.invalid && control.touched\"\n [attr.aria-describedby]=\"describedBy()\"\n />\n @if (errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class TextFieldComponent implements OnDestroy {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n private displaySub?: Subscription;\n\n @Input() field!: NestedFieldConfig;\n @Input()\n set control(value: AbstractControl) {\n this._control = value;\n this.displaySub?.unsubscribe();\n this.displayValue.set(value?.value ?? null);\n this.displaySub = value?.valueChanges.subscribe(v => this.displayValue.set(v));\n }\n get control(): AbstractControl {\n return this._control;\n }\n private _control!: AbstractControl;\n\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n /** Readonly markup reads this signal so an external patch (autoPatch) is visible under OnPush. */\n readonly displayValue = signal<unknown>(null);\n\n ngOnDestroy(): void {\n this.displaySub?.unsubscribe();\n }\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control || !this.control.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-textarea-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--textarea\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{ control.value }}</span>\n } @else {\n <textarea\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [placeholder]=\"placeholder\"\n [attr.disabled]=\"field.disabled ? true : null\"\n rows=\"3\"\n ></textarea>\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class TextareaFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport { resolveLabel, type LocalizedText } from '@dynamic-entity/core';\nimport { UI_TEXT } from '../tokens/injection-tokens';\n\n/** `{name}` — the slot a `UiTextParams` entry fills. */\nconst PLACEHOLDER = new RegExp('[{]([a-zA-Z0-9_]+)[}]', 'g');\n\n/**\n * Every word this library puts on screen that does not come from a config.\n *\n * Field labels, placeholders and options are `LocalizedText` and already follow the form's\n * `language`. The library's *own* chrome — Save, Reset, \"No rows yet.\" — was English\n * literals in twenty-odd templates, so an application in German rendered German labels\n * around English buttons. There was no way to change them short of forking a component.\n *\n * This map is the whole surface: the keys are what a host translates, and the values are\n * the English source strings to translate *from*. It is exported so a translation file can\n * be generated from it rather than transcribed by hand.\n *\n * Keys are grouped by where they appear rather than alphabetically, because a translator\n * works screen by screen and a list sorted by name hides which strings sit together.\n */\nexport const DEFAULT_UI_TEXT = {\n // Form actions\n save: 'Save',\n saving: 'Saving…',\n reset: 'Reset',\n saveShortcutHint: 'Shortcut: Ctrl+S',\n loading: 'Loading…',\n\n // Why a save was refused — the summary above the form, and the count on each tab\n errorSummaryTitle: '{count} field(s) need attention before this can be saved.',\n tabErrorCount: '{count} field(s) need attention on this tab',\n\n // Record view — the per-tab edit flow\n editSection: 'Edit section',\n saveSection: 'Save section',\n editingSection: 'Editing this section',\n cancel: 'Cancel',\n edit: 'Edit',\n delete: 'Delete',\n\n // Array rows\n addRow: '+ Row',\n addItem: '+ Add Item',\n itemNumber: 'Item #{number}',\n addRowTitle: 'Add {field} row',\n editRowTitle: 'Edit {field} row',\n saveRow: 'Save row',\n remove: 'Remove',\n noRows: 'No rows yet.',\n noItems: 'No items added yet.',\n\n // Choice fields\n selectPlaceholder: 'Select...',\n selectParentFirst: 'Select {field} first.',\n\n // Boolean and checkbox display\n yes: 'Yes',\n no: 'No',\n\n // Files and images\n uploading: 'Uploading…',\n chooseFile: 'Choose file',\n replaceFile: 'Replace file',\n removeFile: 'Remove file',\n downloadFile: 'Download file',\n noImage: 'No image',\n uploadImage: 'Upload',\n changeImage: 'Change',\n\n // Month / year pickers\n month: 'Month',\n year: 'Year',\n\n // Markdown editor\n write: 'Write',\n preview: 'Preview',\n markdownEditorMode: '{label} editor mode',\n\n // Accessible names for icon-only controls\n showPassword: 'Show password',\n hidePassword: 'Hide password',\n lockField: 'Lock {field}',\n unlockField: 'Unlock {field}',\n criticalFieldLockHint: 'Critical field — click to lock',\n criticalFieldUnlockHint: 'Critical field — click to unlock for editing',\n dismissBanner: 'Dismiss: {message}',\n jumpToField: 'Click to jump to {field}',\n\n // Import wizard — the steps, in order\n importUpload: 'Choose a file',\n importMap: 'Match columns',\n importReview: 'Review',\n importDone: 'Done',\n\n // Import wizard — choosing a file\n importChooseFile: 'Choose a spreadsheet',\n importFileChosen: '{name} — {rows} row(s)',\n importReading: 'Reading the file…',\n importNeedFile: 'Choose a file to continue.',\n\n // Import wizard — the template a user can start from\n importTemplateHeading: 'Start from a template',\n importTemplateExplain: 'Download a sheet with the right columns, fill it in, and upload it.',\n importTemplateDownload: 'Download template',\n importTemplateSelectAll: 'Select all',\n importTemplateSelectNone: 'Select none',\n importTemplateUnsupported: '{count} field(s) cannot be carried by a spreadsheet.',\n\n // Import wizard — matching columns\n importColumnInFile: 'Column in your file',\n importTargetField: 'Field',\n importUnmapped: 'Not imported',\n importGuessed: 'Guessed',\n importMappedCount: '{mapped} of {total} field(s) matched.',\n importRequiredUnmapped: '{count} required field(s) still need a column.',\n\n // Import wizard — review and result\n importPreviewHeading: 'First {count} row(s), as they will be saved',\n importRowRejected: 'This row will not be imported: {reason}',\n importRunImport: 'Import {count} row(s)',\n importImporting: 'Importing…',\n importSucceeded: 'Imported {count} record(s).',\n importSkippedRows: '{count} blank row(s) skipped.',\n importFailedRows: '{count} row(s) could not be imported.',\n // A streaming transport caps what it retains — fifty thousand error objects is the same\n // unbounded growth as holding the file — so the count and the sample are different numbers\n // and the user is told which they are looking at.\n importErrorsTruncated: 'Showing the first {shown} of {count} problem(s).',\n importStartOver: 'Import another file',\n\n // Import wizard — what went wrong\n importErrorsHeading: 'Rows that need attention',\n importErrorRow: 'Row {row}',\n importErrorField: 'Field',\n importErrorReason: 'Reason',\n importPlanProblem: 'This mapping cannot be used: {message}',\n\n // Banners and whole-record states\n entityLabel: 'Entity: {entity}',\n criticalFieldChanged: '🔒 Critical field changed: {fields} — this differs from the value at the start of this session.',\n recordModified: '🔒 Record modified from session baseline — unsaved changes pending.',\n accessDenied: 'You do not have permission to view this record.',\n};\n\n/**\n * The keys above, as a union. Templates are checked against it, so a mistyped key is an\n * AOT error rather than a blank button, and a host writing overrides gets completion.\n */\nexport type UiTextKey = keyof typeof DEFAULT_UI_TEXT;\n\n/**\n * One replacement: a plain string, or the same `LocalizedText` map a config uses for a\n * field label — `{ en: 'Save', de: 'Speichern' }`, resolved against the form's `language`\n * by the very function that resolves the labels beside it.\n */\nexport type UiTextValue = string | LocalizedText;\n\n/**\n * Asked for one key at render time, given the English default to fall back on and the\n * form's active language.\n *\n * This is the seam for an existing i18n setup — `$localize`, ngx-translate, Transloco —\n * whose catalogue is language-first (`de.json`) rather than key-first, and which already\n * holds its own idea of the current language. Take `language` or ignore it accordingly.\n */\nexport type UiTextResolverFor<K extends string> = (key: K, defaultText: string, language: string) => string;\n\n/** The resolver for this library's own keys. */\nexport type UiTextResolver = UiTextResolverFor<UiTextKey>;\n\n/**\n * Values substituted into a `{placeholder}` in the text.\n *\n * A sentence with a name in the middle has to travel as one string: word order moves\n * between languages, so splitting it into fragments around an interpolation produces\n * grammatical nonsense in the ones it was not written for.\n */\nexport type UiTextParams = Record<string, string | number>;\n\n/** Either a partial map of replacements, or a resolver that answers per key. */\nexport type UiTextOverridesFor<K extends string> = Partial<Record<K, UiTextValue>> | UiTextResolverFor<K>;\n\n/** The overrides for this library's own keys. */\nexport type UiTextOverrides = UiTextOverridesFor<UiTextKey>;\n\n/**\n * The resolution rule itself, over any key vocabulary.\n *\n * Exported because the builder package renders a second, disjoint set of words and needs\n * the same rule — overrides first, then the English default, per key, with `{placeholder}`\n * substitution. Sharing the function rather than the vocabulary is what keeps a renderer\n * consumer from seeing a hundred and fifty builder keys in completion.\n */\nexport function resolveUiText<K extends string>(\n overrides: UiTextOverridesFor<K> | null | undefined,\n defaults: Readonly<Record<K, string>>,\n key: K,\n language: string,\n params?: UiTextParams,\n): string {\n const fallback = ownString(defaults, key);\n const resolved = !overrides\n ? fallback\n : typeof overrides === 'function'\n ? askResolver(overrides, key, fallback, language)\n : // `resolveLabel` handles a bare string at runtime but does not say so in its\n // signature, so the branch is taken here rather than leaning on an undeclared one.\n resolveOne(own<UiTextValue | undefined>(overrides, key), language) || fallback;\n\n return interpolate(resolved, params);\n}\n\n/**\n * An **own** entry, or `undefined`.\n *\n * `map[key]` walks the prototype chain, so `toString` answers with `Function` and\n * `__proto__` with `Object.prototype` — neither of which is a string, and both of which\n * reach `interpolate` and then a template. The key type rules that out in TypeScript; a key\n * arriving from a translation catalogue at runtime, or from a host written in JavaScript,\n * does not.\n */\nfunction own<T>(map: Partial<Record<string, T>>, key: string): T | undefined {\n return Object.prototype.hasOwnProperty.call(map, key) ? map[key] : undefined;\n}\n\nfunction ownString<K extends string>(defaults: Readonly<Record<K, string>>, key: K): string {\n const value = own(defaults as Record<string, unknown>, key);\n return typeof value === 'string' ? value : '';\n}\n\n/**\n * A resolver runs inside change detection, once per label per pass, in someone else's code.\n *\n * If it throws, the exception surfaces from a template expression and the form does not\n * render at all — every form in the application, over one bad catalogue entry. Falling back\n * to English is the same answer this function already gives for a resolver that returns\n * nothing, and it keeps a translation fault a translation fault rather than an outage.\n */\nfunction askResolver<K extends string>(resolver: UiTextResolverFor<K>, key: K, fallback: string, language: string): string {\n try {\n const answer = resolver(key, fallback, language);\n return typeof answer === 'string' && answer ? answer : fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction resolveOne(value: UiTextValue | undefined, language: string): string {\n if (typeof value === 'string') return value;\n const resolved = resolveLabel(value, language);\n // `resolveLabel` is typed to return a string and does, for every shape it is documented\n // to take. A host handing it a number reaches `Object.values(42)`, which is empty.\n return typeof resolved === 'string' ? resolved : '';\n}\n\n/**\n * Resolves the library's own UI text, honouring `UI_TEXT` before the defaults.\n *\n * Resolution is per key, not all-or-nothing, so a host replacing three buttons does not\n * have to supply the other thirty — and an override that yields nothing for a key still\n * renders English rather than a gap, which is what a translation catalogue asked for a\n * missing entry typically hands back.\n */\n@Injectable({ providedIn: 'root' })\nexport class UiTextService {\n private readonly overrides = inject(UI_TEXT, { optional: true });\n\n /**\n * One label by key, in `language`; English if nothing overrides it. `params` fill the\n * `{placeholder}` slots, in whatever position the translation puts them.\n */\n text(key: UiTextKey, language = 'en', params?: UiTextParams): string {\n return resolveUiText(this.overrides, DEFAULT_UI_TEXT, key, language, params);\n }\n}\n\n/** A placeholder with no matching param is left as written, which is visible in review. */\nfunction interpolate(text: string, params?: UiTextParams): string {\n if (!params) return text;\n // `name in params` would answer for `toString` and `constructor` too, substituting a\n // function body into a sentence. Only what the caller actually passed counts.\n return text.replace(PLACEHOLDER, (match, name) => {\n const value = own(params as Record<string, unknown>, name);\n return value === undefined || value === null ? match : String(value);\n });\n}\n","import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n DestroyRef,\n Input,\n OnChanges,\n SimpleChanges,\n inject,\n signal,\n} from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { MARKDOWN_RENDERER, MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/**\n * Markdown field: a long-form input that stores **markdown source**, never HTML.\n *\n * Storing the source rather than rendered HTML is the whole design. The record stays plain\n * text — diffable, portable, safe to log, and impossible to turn into stored XSS by writing\n * it into a database. Rendering happens at display time and only when a consumer asks for\n * it, via `MARKDOWN_RENDERER`.\n *\n * Without a renderer this degrades to exactly what `textarea` does, plus preserved line\n * breaks: the source is shown as text with nothing interpreted. That is the default because\n * these packages declare no runtime dependencies beyond `tslib`, and a markdown parser is a\n * large thing to force on a consumer who wanted a form library.\n *\n * With a renderer, its HTML is bound through `[innerHTML]`, which Angular sanitizes — see\n * the token's own note on why that is a backstop rather than a licence.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-markdown-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--markdown\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n @if (rendered(); as html) {\n <div\n class=\"ngx-field__value ngx-field__markdown\"\n [attr.data-testid]=\"'field-' + field.id + '-value'\"\n [innerHTML]=\"html\"\n ></div>\n } @else {\n <!-- No renderer: the source is the display. The stylesheet keeps its line\n breaks with white-space: pre-wrap, and interpolation escapes it. -->\n <span class=\"ngx-field__value ngx-field__markdown--source\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n control.value\n }}</span>\n }\n } @else {\n <div class=\"ngx-field__markdown-editor\">\n @if (canPreview) {\n <div\n class=\"ngx-field__markdown-tabs\"\n role=\"group\"\n [attr.aria-label]=\"ui.text('markdownEditorMode', language, { label })\"\n >\n <button\n type=\"button\"\n class=\"ngx-field__markdown-tab\"\n [attr.data-testid]=\"'field-' + field.id + '-write'\"\n [attr.aria-pressed]=\"!previewing()\"\n (click)=\"previewing.set(false)\"\n >\n {{ ui.text('write', language) }}\n </button>\n <button\n type=\"button\"\n class=\"ngx-field__markdown-tab\"\n [attr.data-testid]=\"'field-' + field.id + '-preview'\"\n [attr.aria-pressed]=\"previewing()\"\n (click)=\"previewing.set(true)\"\n >\n {{ ui.text('preview', language) }}\n </button>\n </div>\n }\n\n @if (previewing()) {\n <div\n class=\"ngx-field__markdown ngx-field__markdown--preview\"\n [attr.data-testid]=\"'field-' + field.id + '-preview-body'\"\n [innerHTML]=\"rendered()\"\n ></div>\n } @else {\n <textarea\n [id]=\"domId()\"\n class=\"ngx-field__input ngx-field__input--markdown\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [placeholder]=\"placeholder\"\n [attr.disabled]=\"field.disabled ? true : null\"\n rows=\"6\"\n ></textarea>\n }\n </div>\n\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class MarkdownFieldComponent implements OnChanges {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n /** Optional — the field is fully usable without one. */\n private readonly render = inject(MARKDOWN_RENDERER, { optional: true });\n private readonly cdr = inject(ChangeDetectorRef);\n private readonly destroyRef = inject(DestroyRef);\n\n protected readonly previewing = signal(false);\n\n private valueSub?: { unsubscribe(): void };\n\n /**\n * Re-render when the value changes from outside this component.\n *\n * `rendered()` reads `control.value`, which under OnPush is neither an input nor a\n * template event: typing in the textarea updates through `formControl`, but a host\n * calling `patchValue`, a rule, or an `autoPatch` mapping does not mark this component\n * dirty. The preview and the read-only view would keep showing the previous document\n * while the record already held a different one.\n */\n ngOnChanges(changes: SimpleChanges): void {\n if (!changes['control']) return;\n this.valueSub?.unsubscribe();\n this.valueSub = this.control?.valueChanges?.subscribe(() => this.cdr.markForCheck());\n if (this.valueSub) this.destroyRef.onDestroy(() => this.valueSub?.unsubscribe());\n }\n\n /** A Preview tab that can only ever show the source back is worse than no tab. */\n protected get canPreview(): boolean {\n return !!this.render;\n }\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n /**\n * Rendered HTML, or null when there is no renderer or nothing to render.\n *\n * A renderer is consumer code and may throw on input it does not like. Letting that\n * escape would take down the whole form over one malformed field, so it falls back to the\n * source text — which is what the field would have shown with no renderer at all.\n *\n * Memoised on the source, because this is called from the template: without it the\n * consumer's markdown parser ran on every change-detection pass, for every markdown field\n * on screen, over the whole document — which on a form holding a few long ones is a parse\n * per keystroke *elsewhere* in the form. The cache is keyed by the exact source string,\n * so a value that comes back to something already rendered is free too.\n */\n private cached?: { source: string; html: string | null };\n\n protected rendered(): string | null {\n const source = this.control?.value;\n if (!this.render || typeof source !== 'string' || source === '') return null;\n if (this.cached?.source === source) return this.cached.html;\n\n let html: string | null;\n try {\n html = this.render(source);\n } catch {\n html = null;\n }\n this.cached = { source, html };\n return html;\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, inject, ChangeDetectionStrategy } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-number-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--number\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n [class.ngx-field--invalid]=\"control && control.invalid && control.touched\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">\n {{ label }}\n @if (field.validators?.required) {\n <span class=\"ngx-field__req\">*</span>\n }\n </label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{ control.value ?? '—' }}</span>\n } @else {\n <input\n [id]=\"domId()\"\n type=\"number\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [formControl]=\"$any(control)\"\n [placeholder]=\"placeholder\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-invalid]=\"control.invalid && control.touched\"\n [attr.aria-describedby]=\"describedBy()\"\n />\n @if (errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class NumberFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control || !this.control.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/** Currency field: number input with locale-aware currency symbol prefix. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-currency-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--currency\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\"\n >{{ symbol }}{{ control.value }}</span\n >\n } @else {\n <div class=\"ngx-field__currency-wrap\">\n <span class=\"ngx-field__currency-symbol\">{{ symbol }}</span>\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input ngx-field__input--currency\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n type=\"number\"\n step=\"0.01\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [placeholder]=\"placeholder || '0.00'\"\n [attr.disabled]=\"field.disabled ? true : null\"\n />\n </div>\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class CurrencyFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n /** Picks the currency symbol from the locale — defaults to '$'. */\n get symbol(): string {\n try {\n return (\n (0)\n .toLocaleString(this.language, { style: 'currency', currency: 'USD', minimumFractionDigits: 0 })\n .replace(/[\\d,.\\s]/g, '')\n .trim() || '$'\n );\n } catch {\n return '$';\n }\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/** Email field: type=\"email\" input with inline validation hint. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-email-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--email\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">\n @if (control.value) {\n <a [href]=\"'mailto:' + control.value\" class=\"ngx-field__email-link\">{{ control.value }}</a>\n } @else {\n —\n }\n </span>\n } @else {\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n type=\"email\"\n autocomplete=\"email\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [placeholder]=\"placeholder || 'you@example.com'\"\n [attr.disabled]=\"field.disabled ? true : null\"\n />\n @if (errorMessage) {\n <!-- One branch, resolved by the service. The template used to spell out \"Email is\n required\" and \"Enter a valid email address\" itself, so a host configuring\n validationMessages was overridden by markup it could not reach. The service\n defaults say the same thing. -->\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class EmailFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, signal, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/** Password field: masked input with show/hide eye toggle. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-password-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--password\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">••••••••</span>\n } @else {\n <div class=\"ngx-field__password-wrap\">\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [type]=\"visible() ? 'text' : 'password'\"\n autocomplete=\"current-password\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [placeholder]=\"placeholder || '••••••••'\"\n [attr.disabled]=\"field.disabled ? true : null\"\n />\n <button\n type=\"button\"\n class=\"ngx-field__eye-btn\"\n (click)=\"toggleVisibility()\"\n [attr.aria-label]=\"ui.text(visible() ? 'hidePassword' : 'showPassword', language)\"\n >\n {{ visible() ? '🙈' : '👁' }}\n </button>\n </div>\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class PasswordFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n readonly visible = signal(false);\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n toggleVisibility(): void {\n this.visible.update(v => !v);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-checkbox-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--checkbox\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n @if (masked) {\n <label class=\"ngx-field__label\">{{ label }}</label>\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <label class=\"ngx-field__label\">{{ label }}</label>\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n control.value ? ui.text('yes', language) : ui.text('no', language)\n }}</span>\n } @else {\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n type=\"checkbox\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.disabled]=\"field.disabled ? true : null\"\n />\n {{ label }}\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </label>\n @if (errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class CheckboxFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n /**\n * Configured messages reach this field too.\n *\n * It rendered no error element at all, so a required checkbox left unticked told the user\n * nothing — and `validationMessages` could not reach a field that never displayed one.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/**\n * Boolean field: a slide-toggle style switch (true/false).\n * Distinct from `checkbox` (which is a standalone bool) in that it renders as a\n * toggle switch with Yes/No labels for clearer binary state communication.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-boolean-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--boolean\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n @if (masked) {\n <label class=\"ngx-field__label\">{{ label }}</label>\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <label class=\"ngx-field__label\">{{ label }}</label>\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n control.value ? ui.text('yes', language) : ui.text('no', language)\n }}</span>\n } @else {\n <div class=\"ngx-field__toggle-wrap\">\n <label class=\"ngx-field__toggle-label\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n <label class=\"ngx-field__toggle-switch\" [class.ngx-field__toggle-switch--checked]=\"control.value\">\n <input\n class=\"ngx-field__toggle-input\"\n type=\"checkbox\"\n role=\"switch\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-checked]=\"control.value\"\n />\n <span class=\"ngx-field__toggle-track\">\n <span class=\"ngx-field__toggle-thumb\"></span>\n </span>\n <span class=\"ngx-field__toggle-text\">{{\n control.value ? ui.text('yes', language) : ui.text('no', language)\n }}</span>\n </label>\n </div>\n @if (errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class BooleanFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n /**\n * Configured messages reach this field too.\n *\n * It rendered no error element at all, so a required checkbox left unticked told the user\n * nothing — and `validationMessages` could not reach a field that never displayed one.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { formatDisplayValue, resolveLabel } from '@dynamic-entity/core';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-date-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--date\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n formatDate(control.value)\n }}</span>\n } @else {\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n type=\"date\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.disabled]=\"field.disabled ? true : null\"\n />\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class DateFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n /**\n * ISO 8601 date → display string, through the formatter the host configured.\n *\n * This used to call `toLocaleDateString()` directly, which meant `setDateFormatters` — the\n * one seam for choosing how a date is rendered — reached the record summary and the `time`\n * field but not this one. A host that configured formatters got them almost everywhere,\n * and silently did not get them on the field type most likely to be the reason they\n * configured formatters at all.\n *\n * The default formatter is `toLocaleDateString()` with no locale, so an application that\n * has not called `setDateFormatters` renders exactly what it rendered before.\n */\n formatDate(value: string | null): string {\n if (!value) return '—';\n // `new Date('nonsense')` does not throw and `toLocaleDateString()` returns the *string*\n // \"Invalid Date\", so the try/catch this replaced never fired and readers saw that text\n // instead of their data. Records outlive schemas — a field retyped from text to date can\n // hold anything — so an unparseable value is shown as stored, and never reaches the\n // formatter.\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) return value;\n return formatDisplayValue('date', undefined, value, this.language);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { formatDisplayValue, resolveLabel } from '@dynamic-entity/core';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n/**\n * Reads a stored value into a `Date`.\n *\n * A bare calendar date is pinned to *local* midnight. `new Date('2020-01-01')` reads a\n * date-only string as UTC midnight, which renders as the previous day anywhere west of\n * Greenwich — and every legacy `datetime` value has exactly that shape, because the type\n * used to render through `DateFieldComponent` and its `type=\"date\"` input.\n */\nfunction parseStored(value: unknown): Date | null {\n if (value === null || value === undefined || value === '') return null;\n if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;\n\n const raw = String(value);\n const dateOnly = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(raw);\n if (dateOnly) return new Date(+dateOnly[1], +dateOnly[2] - 1, +dateOnly[3]);\n\n const parsed = new Date(raw);\n return Number.isNaN(parsed.getTime()) ? null : parsed;\n}\n\nconst pad = (n: number): string => String(n).padStart(2, '0');\n\n/**\n * Date & Time field: a single `datetime-local` input.\n *\n * The type is stored as ISO 8601 UTC, per the same convention `date` follows, while the\n * input works in the viewer's local zone — `datetime-local` has no offset, so the two\n * conversions here are what keep a value stable across a round trip.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-date-time-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--datetime\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n formatDateTime(control.value)\n }}</span>\n } @else {\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n type=\"datetime-local\"\n [value]=\"inputValue\"\n (change)=\"onInput($any($event.target).value)\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n />\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class DateTimeFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n /** Stored ISO 8601 → the `YYYY-MM-DDTHH:mm` local form the input requires. */\n get inputValue(): string {\n const d = parseStored(this.control?.value);\n if (!d) return '';\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;\n }\n\n /** The input's local `YYYY-MM-DDTHH:mm` → stored ISO 8601 UTC. */\n onInput(value: string): void {\n if (!value) {\n this.control.setValue(null);\n this.control.markAsTouched();\n return;\n }\n const d = new Date(value);\n // An unparseable value is stored verbatim rather than silently discarded, so a validator\n // sees what the user actually entered.\n this.control.setValue(Number.isNaN(d.getTime()) ? value : d.toISOString());\n this.control.markAsTouched();\n }\n\n /**\n * Displays date *and* time, through the formatter the host configured.\n *\n * Two rounds of the same fault. First this called `toLocaleDateString()`, so a datetime\n * read back through the field showed no time while the record summary showed it. Then it\n * called `toLocaleString()` directly, which fixed the time but kept the field outside\n * `setDateFormatters` — so a host that configured formatters still saw them apply to the\n * summary and not to the field. Going through `formatDisplayValue` is what makes the two\n * paths agree by construction rather than by matching literals.\n *\n * `parseStored` accepts shapes `new Date(raw)` alone does not, so the *parsed* instant is\n * handed on as ISO rather than the raw value.\n */\n formatDateTime(value: unknown): string {\n const d = parseStored(value);\n if (!d) return '—';\n return formatDisplayValue('datetime', undefined, d.toISOString(), this.language);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { formatDisplayValue, resolveLabel } from '@dynamic-entity/core';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n/**\n * Time field: a bare time of day, with no date and no zone attached.\n *\n * Stored as `HH:mm` — exactly the value `<input type=\"time\">` reads and writes, so the\n * control binds straight through with no conversion. That is the whole reason this is a\n * separate type from `datetime`: a recurring 09:00 opening time is not a moment in time,\n * and converting it to UTC would move it whenever the offset changed.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-time-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--time\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n formatTime(control.value)\n }}</span>\n } @else {\n <input\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n type=\"time\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.disabled]=\"field.disabled ? true : null\"\n />\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class TimeFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n /**\n * Defers to core rather than parsing `HH:mm` locally. The other date-ish components each\n * grew their own formatter, and `datetime` ended up showing one thing in the field and\n * another in the record summary because the two drifted apart.\n */\n formatTime(value: unknown): string {\n return formatDisplayValue('time', undefined, value, this.language);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\nconst MONTH_NAMES = [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December',\n];\n\nconst CURRENT_YEAR = new Date().getFullYear();\nconst YEARS = Array.from({ length: 80 }, (_, i) => CURRENT_YEAR - i);\n\n/**\n * Month-Year field: two linked selects (Month + Year).\n * Value stored as ISO partial date string \"YYYY-MM\" for unambiguous storage.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-month-year-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--month-year\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <!--\n Points at the month select: one visible label stands in front of two controls, and a\n label pointing at neither of them announces as nothing and focuses nothing when\n clicked. Each select then carries its own name below, because \"Billing Cycle\" alone\n does not say which half of the pair the screen reader has landed on.\n -->\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId('-month')\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n formatValue(control.value)\n }}</span>\n } @else {\n <div class=\"ngx-field__month-year-wrap\">\n <select\n [id]=\"domId('-month')\"\n class=\"ngx-field__input ngx-field__input--month\"\n [attr.aria-label]=\"label + ' ' + ui.text('month', language)\"\n [attr.data-testid]=\"'field-' + field.id + '-month'\"\n [value]=\"selectedMonth\"\n (change)=\"onMonthChange($any($event.target).value)\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n >\n <option value=\"\">{{ ui.text('month', language) }}</option>\n @for (m of months; track m.value) {\n <option [value]=\"m.value\" [selected]=\"m.value === selectedMonth\">{{ m.label }}</option>\n }\n </select>\n <select\n [id]=\"domId('-year')\"\n class=\"ngx-field__input ngx-field__input--year\"\n [attr.aria-label]=\"label + ' ' + ui.text('year', language)\"\n [attr.data-testid]=\"'field-' + field.id + '-year'\"\n [value]=\"selectedYear\"\n (change)=\"onYearChange($any($event.target).value)\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n >\n <option value=\"\">{{ ui.text('year', language) }}</option>\n @for (y of years; track y) {\n <option [value]=\"y\" [selected]=\"y.toString() === selectedYear\">{{ y }}</option>\n }\n </select>\n </div>\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class MonthYearFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n readonly months = MONTH_NAMES.map((label, i) => ({ value: String(i + 1).padStart(2, '0'), label }));\n readonly years = YEARS;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n /** Parses \"YYYY-MM\" or \"YYYY-MM-DD\" stored value → month part. */\n get selectedMonth(): string {\n const v = String(this.control.value ?? '');\n return v.length >= 7 ? v.substring(5, 7) : '';\n }\n\n get selectedYear(): string {\n const v = String(this.control.value ?? '');\n return v.length >= 4 ? v.substring(0, 4) : '';\n }\n\n onMonthChange(month: string): void {\n const year = this.selectedYear || new Date().getFullYear().toString();\n this.control.setValue(month ? `${year}-${month}` : null);\n this.control.markAsTouched();\n }\n\n onYearChange(year: string): void {\n const month = this.selectedMonth || '01';\n this.control.setValue(year ? `${year}-${month}` : null);\n this.control.markAsTouched();\n }\n\n formatValue(value: unknown): string {\n if (!value) return '—';\n const [year, monthNum] = String(value).split('-');\n const monthName = MONTH_NAMES[parseInt(monthNum, 10) - 1];\n return monthName && year ? `${monthName} ${year}` : String(value);\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Injectable, inject, type WritableSignal } from '@angular/core';\nimport type {\n DropdownOption,\n LookupListLoader,\n LookupListResult,\n LookupListSource,\n LookupListValue,\n NestedFieldConfig,\n RawLookupListValue,\n Subscribable,\n} from '@dynamic-entity/core';\nimport { lookupValuesToOptions, normalizeLookupValues, resolveLabel } from '@dynamic-entity/core';\nimport { LOOKUP_REGISTRY } from '../tokens/injection-tokens';\n\n/** Cache-key field separator. Kept out of template literals so it stays visible in source. */\nconst SEP = '|';\n\n/**\n * LookupRegistryService — the cache in front of consumer-registered master lists.\n *\n * Three layers, deliberately the same shape as `EntityReferenceService`, because the problem is\n * the same: one list is typically used by many fields across many entities.\n * 1. **options** — resolved `DropdownOption[]` per (list name, lang).\n * 2. **in-flight** — the pending Promise, so N fields on one list trigger one load, not N.\n * 3. **labels** — synchronous value → text (parity plan §6.2). This is not a nicety: since\n * `viewMode` defaults to true a record opens read-only, so rendering a stored value as\n * text is the *first* thing a `listName` field has to do. An async-only registry would\n * paint the raw stored value and then flip, on every record open.\n *\n * A failed load rejects and caches nothing, so one transient error does not serve an empty\n * list forever — the same fix made for entity references in phase 5.\n */\n@Injectable({ providedIn: 'root' })\nexport class LookupRegistryService {\n private readonly registry =\n inject(LOOKUP_REGISTRY, { optional: true }) ?? new Map<string, LookupListSource>();\n\n /** `listName|lang` -> resolved options. */\n private readonly options = new Map<string, DropdownOption[]>();\n /** `listName|lang` -> normalised values, so a consumer can reach `code` / `isSystemDefined`. */\n private readonly values = new Map<string, LookupListValue[]>();\n /** Loads in progress, keyed as above. */\n private readonly inFlight = new Map<string, Promise<DropdownOption[]>>();\n /** `listName|lang|text` -> display text, for the synchronous read-only path. */\n private readonly labels = new Map<string, string>();\n\n has(listName: string): boolean {\n return this.registry.has(listName);\n }\n\n /**\n * Options for a named list, from cache when present.\n * Concurrent callers with the same key share one load.\n */\n async load(listName: string, lang = 'en'): Promise<DropdownOption[]> {\n const key = this.cacheKey(listName, lang);\n\n const cached = this.options.get(key);\n if (cached) return cached;\n\n const pending = this.inFlight.get(key);\n if (pending) return pending;\n\n const source = this.registry.get(listName);\n if (source === undefined) return [];\n\n const load = this.invoke(source, lang).then(raw => {\n const values = normalizeLookupValues(raw);\n const options = lookupValuesToOptions(values);\n this.values.set(key, values);\n this.options.set(key, options);\n this.rememberLabels(listName, lang, options);\n return options;\n });\n\n // Only the `.then` above writes to the cache, and a rejection skips it: the caller still\n // gets an empty list, but the next call retries instead of reading a poisoned entry.\n const guarded = load\n .catch(() => [] as DropdownOption[])\n .finally(() => this.inFlight.delete(key));\n\n this.inFlight.set(key, guarded);\n return guarded;\n }\n\n /** Cached options without triggering a load. `undefined` when not loaded. */\n peek(listName: string, lang = 'en'): DropdownOption[] | undefined {\n return this.options.get(this.cacheKey(listName, lang));\n }\n\n /**\n * Cached list values, carrying `_id`, `code`, `isSystemDefined` and `from`.\n * The library never reads those; this is the seam for a consumer that needs them.\n */\n valuesFor(listName: string, lang = 'en'): LookupListValue[] | undefined {\n return this.values.get(this.cacheKey(listName, lang));\n }\n\n /**\n * Display text for a stored value, synchronously. `undefined` when the list has not loaded\n * or holds no matching value — the caller keeps its own fallback, which is the stored text.\n *\n * Every language of an option is indexed, so a record saved under one language renders in\n * another: a value stored as `'Aktiv'` resolves to `'Active'` under `lang: 'en'`.\n */\n labelFor(listName: string | undefined, value: unknown, lang = 'en'): string | undefined {\n if (!listName || value === null || value === undefined || value === '') return undefined;\n for (const text of this.candidateTexts(value, lang)) {\n const hit = this.labels.get(this.labelKey(listName, lang, text));\n if (hit) return hit;\n }\n return undefined;\n }\n\n // ─── Field-level resolution — inline options win, else `listName` ────────────\n\n /** True when this field's options have to come from the registry. */\n needsResolve(field: NestedFieldConfig | undefined): boolean {\n return !!field?.listName && !field.options?.length;\n }\n\n /**\n * The options to render right now, without awaiting: inline options, else whatever the\n * registry already holds. Empty on a cold miss — pair with `resolveOptions`.\n */\n optionsFor(field: NestedFieldConfig | undefined, lang = 'en'): DropdownOption[] {\n if (!field) return [];\n if (field.options?.length) return field.options;\n if (!field.listName) return [];\n return this.peek(field.listName, lang) ?? [];\n }\n\n /** The options for a field, loading the named list if needed. */\n resolveOptions(field: NestedFieldConfig | undefined, lang = 'en'): Promise<DropdownOption[]> {\n if (!this.needsResolve(field)) return Promise.resolve(this.optionsFor(field, lang));\n return this.load(field!.listName!, lang);\n }\n\n /** Drop everything cached for one list, leaving other lists intact. */\n invalidate(listName: string): void {\n const prefix = `${listName}${SEP}`;\n for (const map of [this.options, this.values, this.inFlight]) {\n for (const key of [...map.keys()]) {\n if (key.startsWith(prefix)) map.delete(key);\n }\n }\n for (const key of [...this.labels.keys()]) {\n if (key.startsWith(prefix)) this.labels.delete(key);\n }\n }\n\n clear(): void {\n this.options.clear();\n this.values.clear();\n this.inFlight.clear();\n this.labels.clear();\n }\n\n // ─── Internals ──────────────────────────────────────────────────────────────\n\n private cacheKey(listName: string, lang: string): string {\n return [listName, lang].join(SEP);\n }\n\n private labelKey(listName: string, lang: string, text: string): string {\n return [listName, lang, text].join(SEP);\n }\n\n /** Index an option under every language it carries, so any stored spelling finds it. */\n private rememberLabels(listName: string, lang: string, options: DropdownOption[]): void {\n for (const option of options) {\n const display = resolveLabel(option, lang);\n if (!display) continue;\n for (const text of Object.values(option)) {\n if (typeof text === 'string' && text !== '') {\n this.labels.set(this.labelKey(listName, lang, text), display);\n }\n }\n }\n }\n\n /** The texts a stored value could have been indexed under. */\n private candidateTexts(value: unknown, lang: string): string[] {\n if (typeof value === 'object') {\n const texts = Object.values(value as Record<string, unknown>).filter(\n (v): v is string => typeof v === 'string' && v !== '',\n );\n const resolved = resolveLabel(value as Record<string, string>, lang);\n return resolved ? [resolved, ...texts] : texts;\n }\n return [String(value)];\n }\n\n // ─── Source coercion (values | loader, array | Promise | Observable) ─────────\n\n private invoke(source: LookupListSource, lang: string): Promise<RawLookupListValue[]> {\n let result: LookupListResult;\n try {\n result = typeof source === 'function' ? (source as LookupListLoader)({ lang }) : source;\n } catch (err) {\n // Reject rather than resolve empty: `load` must be able to tell failure from an empty\n // list, or it would cache the failure.\n return Promise.reject(err);\n }\n return this.toPromise(result);\n }\n\n private toPromise(result: LookupListResult): Promise<RawLookupListValue[]> {\n if (Array.isArray(result)) return Promise.resolve(result);\n if (this.isSubscribable(result)) {\n // First emission wins, so a stream that stays open still resolves the load.\n return new Promise<RawLookupListValue[]>((resolve, reject) => {\n let settled = false;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n fn();\n };\n result.subscribe({\n next: value => settle(() => resolve(value ?? [])),\n error: err => settle(() => reject(err)),\n // Completing without emitting is a legitimate empty list, and is cached.\n complete: () => settle(() => resolve([])),\n });\n });\n }\n return Promise.resolve(result as Promise<RawLookupListValue[]>);\n }\n\n private isSubscribable(value: unknown): value is Subscribable<RawLookupListValue[]> {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Subscribable<RawLookupListValue[]>).subscribe === 'function'\n );\n }\n}\n\n/** A choice field component, as far as option resolution is concerned. */\nexport interface ChoiceOptionHost {\n readonly field: NestedFieldConfig | undefined;\n readonly language: string;\n readonly options: WritableSignal<DropdownOption[]>;\n}\n\nconst hostLastConfig = new WeakMap<ChoiceOptionHost, { field?: NestedFieldConfig; lang?: string }>();\n\n/**\n * Point a choice component's `options` signal at the right source (parity plan §6.3).\n *\n * Called from the `field` / `language` input setters of `dropdown`, `radio` and `multiSelect` —\n * the wiring is theirs, the decision is the service's, which is what keeps the field\n * five-input contract intact: options are never pushed in as a sixth input.\n *\n * Setters rather than `ngOnChanges` on purpose. `ngOnChanges` only fires for inputs Angular\n * itself sets, so a component whose `field` is assigned directly — which the field specs do,\n * and any consumer holding a `ComponentRef` may do — would render no options at all.\n *\n * Paints synchronously first (inline options, or a warm list), then fills in when a cold list\n * lands. The late result is dropped if the field or language changed while it was in flight.\n */\nexport function refreshChoiceOptions(host: ChoiceOptionHost, lookups: LookupRegistryService): void {\n const last = hostLastConfig.get(host);\n if (last && last.field === host.field && last.lang === host.language) {\n return;\n }\n hostLastConfig.set(host, { field: host.field, lang: host.language });\n\n host.options.set(lookups.optionsFor(host.field, host.language));\n if (!lookups.needsResolve(host.field)) return;\n\n const listName = host.field?.listName;\n const lang = host.language;\n void lookups.resolveOptions(host.field, host.language).then(options => {\n if (host.field?.listName === listName && host.language === lang) host.options.set(options);\n });\n}\n","import { Component, Input, inject, signal, ChangeDetectionStrategy } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { DropdownOption, NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { resolveLabel, resolveOptionLabel, valuesMatch } from '@dynamic-entity/core';\nimport { LookupRegistryService, refreshChoiceOptions } from '../services/lookup-registry.service';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-dropdown-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--dropdown\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n [class.ngx-field--invalid]=\"control && control.invalid && control.touched\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">\n {{ label }}\n @if (field.validators?.required) {\n <span class=\"ngx-field__req\">*</span>\n }\n </label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n getLabel(control.value)\n }}</span>\n } @else {\n <select\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [formControl]=\"$any(control)\"\n [compareWith]=\"compareFn\"\n [attr.disabled]=\"field.disabled ? true : null\"\n [attr.aria-invalid]=\"control.invalid && control.touched\"\n [attr.aria-describedby]=\"describedBy()\"\n >\n <option [value]=\"''\">{{ placeholder || ui.text('selectPlaceholder', language) }}</option>\n @for (option of options(); track getOptLabel(option)) {\n @if (isObjectVal(option)) {\n <option [ngValue]=\"getOptStoredVal(option)\">{{ getOptLabel(option) }}</option>\n } @else {\n <option [value]=\"getOptStoredVal(option)\">{{ getOptLabel(option) }}</option>\n }\n }\n </select>\n @if (errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class DropdownFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly lookups = inject(LookupRegistryService);\n private readonly messages = inject(ValidationMessagesService);\n\n private _field!: NestedFieldConfig;\n private _language = 'en';\n\n /** Setter-based so options resolve however the input is set — see `refreshChoiceOptions`. */\n @Input() set field(value: NestedFieldConfig) {\n this._field = value;\n refreshChoiceOptions(this, this.lookups);\n }\n get field(): NestedFieldConfig {\n return this._field;\n }\n\n @Input() set language(value: string) {\n this._language = value || 'en';\n refreshChoiceOptions(this, this.lookups);\n }\n get language(): string {\n return this._language;\n }\n\n @Input() control!: AbstractControl;\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n /** Inline `options`, or the field's named list resolved through the registry (§6.3). */\n readonly options = signal<DropdownOption[]>([]);\n\n readonly compareFn = (o1: unknown, o2: unknown): boolean => valuesMatch(o1, o2, this.language);\n\n isObjectVal(option: DropdownOption): boolean {\n return typeof option === 'object' && option !== null;\n }\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n /**\n * The value this option stores — the option object itself.\n *\n * Kept as a method rather than binding `option` straight into the template, because it is\n * the one place that says *why* the two are the same thing. It used to delegate to\n * `getOptionStoredValue`, an exported identity function whose two branches returned their\n * argument unchanged; naming a transformation that does not happen is worse than naming\n * nothing, because a reader has to go and check.\n */\n getOptStoredVal(option: DropdownOption): unknown {\n return option;\n }\n\n getOptLabel(option: DropdownOption): string {\n return resolveOptionLabel(option, this.language);\n }\n\n /**\n * Read-only display. Never awaits (§6.2): a warm list resolves the label, a cold one falls\n * back to the stored text — which under the §2 contract *is* the display value, so it is\n * never wrong, only unlocalised.\n */\n getLabel(value: unknown): string {\n if (value == null || value === '') return '—';\n const option = this.options().find(o => valuesMatch(o, value, this.language));\n if (option) return this.getOptLabel(option);\n const cached = this.lookups.labelFor(this.field?.listName, value, this.language);\n if (cached) return cached;\n return typeof value === 'object' ? resolveLabel(value as Record<string, string>, this.language) : String(value ?? '—');\n }\n\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control || !this.control.errors || !this.control.touched) return '';\n // `requiredSelection` rather than `required`: \"Please select an option\" reads better on a\n // dropdown than \"This field is required\", and both stay independently overridable.\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, inject, signal, ChangeDetectionStrategy, ChangeDetectorRef, OnDestroy } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport { Subscription } from 'rxjs';\nimport type { DropdownOption, NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport {\n resolveLabel,\n resolveOptionLabel,\n resolveOptionValue,\n valuesMatch,\n} from '@dynamic-entity/core';\nimport { LookupRegistryService, refreshChoiceOptions } from '../services/lookup-registry.service';\n\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n/** Radio field: a group of radio buttons built from field.options. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-radio-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--radio\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <fieldset class=\"ngx-field__fieldset\">\n <legend class=\"ngx-field__label\">\n {{ label }}\n @if (hint) {\n <!--\n Inside the legend rather than beside it: a fieldset allows exactly one legend\n and it must be the first child, so a sibling row would be invalid here.\n -->\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </legend>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{ getSelectedLabel() }}</span>\n } @else {\n <div class=\"ngx-field__radio-group\">\n @for (option of options(); track getOptLabel(option)) {\n <label class=\"ngx-field__radio-option\" [attr.for]=\"getRadioId(option)\">\n <input\n [id]=\"getRadioId(option)\"\n [attr.data-testid]=\"'field-' + field.id + '-option-' + optionSlug(option)\"\n type=\"radio\"\n class=\"ngx-field__radio-input\"\n [name]=\"domId()\"\n [attr.aria-describedby]=\"describedBy()\"\n [value]=\"getOptStoredVal(option)\"\n [checked]=\"isChecked(option)\"\n [attr.disabled]=\"field.disabled ? true : null\"\n (change)=\"onSelect(option)\"\n />\n <span class=\"ngx-field__radio-label\">{{ getOptLabel(option) }}</span>\n </label>\n }\n </div>\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </fieldset>\n </div>\n `,\n})\nexport class RadioFieldComponent implements OnDestroy {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n private readonly lookups = inject(LookupRegistryService);\n private readonly cdr = inject(ChangeDetectorRef);\n\n private _field!: NestedFieldConfig;\n private _language = 'en';\n private _control!: AbstractControl;\n private _controlSub?: Subscription;\n\n ngOnDestroy(): void {\n this._controlSub?.unsubscribe();\n }\n\n /** Setter-based so options resolve however the input is set — see `refreshChoiceOptions`. */\n @Input() set field(value: NestedFieldConfig) {\n this._field = value;\n refreshChoiceOptions(this, this.lookups);\n }\n get field(): NestedFieldConfig {\n return this._field;\n }\n\n @Input() set language(value: string) {\n this._language = value || 'en';\n refreshChoiceOptions(this, this.lookups);\n }\n get language(): string {\n return this._language;\n }\n\n @Input() set control(value: AbstractControl) {\n this._control = value;\n this._controlSub?.unsubscribe();\n this._controlSub = this._control?.valueChanges?.subscribe(() => {\n this.cdr.markForCheck();\n });\n }\n get control(): AbstractControl {\n return this._control;\n }\n\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n /** Inline `options`, or the field's named list resolved through the registry (§6.3). */\n readonly options = signal<DropdownOption[]>([]);\n\n onSelect(option: DropdownOption): void {\n this.control?.setValue(option);\n this.control?.markAsTouched();\n this.control?.markAsDirty();\n }\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n /**\n * The value this option stores — the option object itself.\n *\n * Kept as a method rather than binding `option` straight into the template, because it is\n * the one place that says *why* the two are the same thing. It used to delegate to\n * `getOptionStoredValue`, an exported identity function whose two branches returned their\n * argument unchanged; naming a transformation that does not happen is worse than naming\n * nothing, because a reader has to go and check.\n */\n getOptStoredVal(option: DropdownOption): unknown {\n return option;\n }\n\n /**\n * Stable DOM id for one radio, so the <label for> association works.\n * Slugified because the option text is the value now — \"On Leave\" must not put a space\n * into an id attribute.\n */\n getRadioId(option: DropdownOption): string {\n return this.domId(`-${this.optionSlug(option)}`);\n }\n\n /**\n * The option's part of an id or a test hook.\n *\n * `??` cannot fire here: `resolveOptionValue` returns '' for an empty option, not null, so\n * every valueless option produced the same slug — and two radios sharing an id break the\n * `for` that ties each label to its input.\n */\n optionSlug(option: DropdownOption): string {\n const raw = String(this.getOptVal(option) ?? '').trim();\n const text = raw || 'opt';\n return text.trim().replace(/\\s+/g, '_').toLowerCase();\n }\n\n getOptVal(option: DropdownOption): string | number | boolean {\n return resolveOptionValue(option, this.language);\n }\n\n getOptLabel(option: DropdownOption): string {\n return resolveOptionLabel(option, this.language);\n }\n\n /** Whether the given option matches the control's current value. */\n isChecked(option: DropdownOption): boolean {\n return valuesMatch(this.control?.value, option, this.language);\n }\n\n /** Read-only display — synchronous, per §6.2. See `DropdownFieldComponent.getLabel`. */\n getSelectedLabel(): string {\n const value = this.control?.value;\n // `typeof null === 'object'`, so without this guard an empty value fell through to\n // `resolveLabel(null)` and rendered as blank — dropdown and multiSelect both show an em dash.\n if (value === null || value === undefined || value === '') return '—';\n const selected = this.options().find(o => valuesMatch(o, value, this.language));\n if (selected) return this.getOptLabel(selected);\n const cached = this.lookups.labelFor(this.field?.listName, value, this.language);\n if (cached) return cached;\n return typeof value === 'object' ? resolveLabel(value as Record<string, string>, this.language) : String(value ?? '—');\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, Input, inject, signal, ChangeDetectionStrategy } from '@angular/core';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { DropdownOption, NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel, resolveOptionLabel, valuesMatch } from '@dynamic-entity/core';\nimport { LookupRegistryService, refreshChoiceOptions } from '../services/lookup-registry.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-multi-select-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--multiSelect\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n getLabels(control.value)\n }}</span>\n } @else {\n <select\n [id]=\"domId()\"\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [compareWith]=\"compareFn\"\n [attr.disabled]=\"field.disabled ? true : null\"\n multiple\n size=\"4\"\n >\n @for (option of options(); track getOptLabel(option)) {\n @if (isObjectVal(option)) {\n <option [ngValue]=\"getOptStoredVal(option)\">{{ getOptLabel(option) }}</option>\n } @else {\n <option [value]=\"getOptStoredVal(option)\">{{ getOptLabel(option) }}</option>\n }\n }\n </select>\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class MultiSelectFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n private readonly lookups = inject(LookupRegistryService);\n\n private _field!: NestedFieldConfig;\n private _language = 'en';\n\n /** Setter-based so options resolve however the input is set — see `refreshChoiceOptions`. */\n @Input() set field(value: NestedFieldConfig) {\n this._field = value;\n refreshChoiceOptions(this, this.lookups);\n }\n get field(): NestedFieldConfig {\n return this._field;\n }\n\n @Input() set language(value: string) {\n this._language = value || 'en';\n refreshChoiceOptions(this, this.lookups);\n }\n get language(): string {\n return this._language;\n }\n\n @Input() control!: AbstractControl;\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n /** Inline `options`, or the field's named list resolved through the registry (§6.3). */\n readonly options = signal<DropdownOption[]>([]);\n\n readonly compareFn = (o1: unknown, o2: unknown): boolean => valuesMatch(o1, o2, this.language);\n\n isObjectVal(option: DropdownOption): boolean {\n return typeof option === 'object' && option !== null;\n }\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n /**\n * The value this option stores — the option object itself.\n *\n * Kept as a method rather than binding `option` straight into the template, because it is\n * the one place that says *why* the two are the same thing. It used to delegate to\n * `getOptionStoredValue`, an exported identity function whose two branches returned their\n * argument unchanged; naming a transformation that does not happen is worse than naming\n * nothing, because a reader has to go and check.\n */\n getOptStoredVal(option: DropdownOption): unknown {\n return option;\n }\n\n getOptLabel(option: DropdownOption): string {\n return resolveOptionLabel(option, this.language);\n }\n\n /** Read-only display — synchronous, per §6.2. See `DropdownFieldComponent.getLabel`. */\n getLabels(values: unknown): string {\n if (!Array.isArray(values) || !values.length) return '—';\n return values\n .map(v => {\n const opt = this.options().find(o => valuesMatch(o, v, this.language));\n if (opt) return this.getOptLabel(opt);\n const cached = this.lookups.labelFor(this.field?.listName, v, this.language);\n if (cached) return cached;\n return typeof v === 'object' && v !== null ? resolveLabel(v as Record<string, string>, this.language) : String(v);\n })\n .join(', ');\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport type { EntityReferenceLoader } from '@dynamic-entity/core';\nimport { ENTITY_REF_REGISTRY } from '../tokens/injection-tokens';\n\n/**\n * EntityRefRegistryService — resolves entity-ref option loader functions.\n * Entity-ref options come ONLY from this registry.\n * Never pass loaders via @Input() on field components.\n *\n * Consumers register loaders via provideNgxDynamicEntity({ entityRefs: { clients: () => [...] } }).\n * EntityRefFieldComponent injects this service and calls resolve(field.component ?? field.id).\n */\n@Injectable({ providedIn: 'root' })\nexport class EntityRefRegistryService {\n private readonly registry =\n inject(ENTITY_REF_REGISTRY, { optional: true }) ?? new Map<string, EntityReferenceLoader>();\n\n /**\n * Get the option loader for an entity key.\n * @returns The loader, or null if none is registered.\n */\n resolve(entityKey: string): EntityReferenceLoader | null {\n return this.registry.get(entityKey) ?? null;\n }\n\n has(entityKey: string): boolean {\n return this.registry.has(entityKey);\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport type {\n EntityReferenceLoader,\n RawReferenceItem,\n ReferenceLoaderContext,\n ReferenceLoaderResult,\n ReferenceOption,\n Subscribable,\n} from '@dynamic-entity/core';\nimport {\n buildReferenceCacheKey,\n entityKeyFromCacheKey,\n normalizeReferenceOptions,\n resolveLabel,\n valuesMatch,\n} from '@dynamic-entity/core';\nimport { ENTITY_REF_CACHE_STORE } from '../tokens/injection-tokens';\nimport { EntityRefRegistryService } from './entity-ref-registry.service';\n\n/** Label-cache field separator. Kept out of template literals so it stays visible in source. */\nconst LABEL_SEP = '|';\n\n/**\n * EntityReferenceService — the cache in front of consumer-registered option loaders.\n *\n * Three layers, matching the reference implementation:\n * 1. **options** — resolved `ReferenceOption[]` per (entity, lang, displayFields, filters).\n * 2. **in-flight** — the pending Promise, so N fields referencing one entity trigger one\n * load rather than N. This is the layer that actually removes duplicate HTTP calls;\n * an options cache alone does nothing for concurrent first loads.\n * 3. **labels** — synchronous value → text, for rendering a stored reference without\n * waiting on a load.\n *\n * Invalidation is per entity, not global. The reference could only `clearCache()` everything\n * (issue #16), so saving one record re-fetched every entity's options.\n */\n@Injectable({ providedIn: 'root' })\nexport class EntityReferenceService {\n private readonly registry = inject(EntityRefRegistryService);\n private readonly store = inject(ENTITY_REF_CACHE_STORE);\n\n /** Loads in progress, keyed the same way as the options cache. */\n private readonly inFlight = new Map<string, Promise<ReferenceOption[]>>();\n /** `entityKey|lang|canonicalValue` -> display text. */\n private readonly labels = new Map<string, string>();\n\n /**\n * Options for an entity, from cache when present.\n * Concurrent callers with the same key share one load.\n */\n async load(entityKey: string, ctx: ReferenceLoaderContext = {}): Promise<ReferenceOption[]> {\n const key = buildReferenceCacheKey(entityKey, {\n lang: ctx.lang,\n filters: ctx.filters,\n displayFields: ctx.displayFields,\n parentValue: ctx.parentValue,\n });\n\n const cached = this.store.get(key);\n if (cached) return cached;\n\n const pending = this.inFlight.get(key);\n if (pending) return pending;\n\n const loader = this.registry.resolve(entityKey);\n if (!loader) return [];\n\n const load = this.invoke(loader, ctx)\n .then(raw => {\n // displayFields drive label building, which is why they are part of the cache key.\n const options = normalizeReferenceOptions(\n raw as RawReferenceItem[],\n ctx.displayFields ? { enabled: true, displayFields: ctx.displayFields } : undefined,\n ctx.lang ?? 'en',\n );\n this.store.set(key, options);\n this.rememberLabels(entityKey, ctx.lang ?? 'en', options);\n return options;\n });\n\n // A failed load resolves to [] for the caller but is never written to the store, so a\n // transient error is retried on the next call instead of poisoning the cache. Only the\n // `.then` above caches, and a rejection skips it.\n const guarded = load\n .catch(() => [] as ReferenceOption[])\n .finally(() => this.inFlight.delete(key));\n\n this.inFlight.set(key, guarded);\n return guarded;\n }\n\n /** Cached options without triggering a load. `undefined` when not cached. */\n peek(entityKey: string, ctx: ReferenceLoaderContext = {}): ReferenceOption[] | undefined {\n return this.store.get(\n buildReferenceCacheKey(entityKey, {\n lang: ctx.lang,\n filters: ctx.filters,\n displayFields: ctx.displayFields,\n parentValue: ctx.parentValue,\n }),\n );\n }\n\n /**\n * Display text for a stored reference value, synchronously.\n * Returns `undefined` when the entity's options have never been loaded.\n */\n labelFor(entityKey: string, value: unknown, lang = 'en'): string | undefined {\n return this.labels.get(this.labelKey(entityKey, lang, value));\n }\n\n /** Drop everything cached for one entity, leaving other entities intact. */\n invalidate(entityKey: string): void {\n for (const key of this.store.keys()) {\n if (entityKeyFromCacheKey(key) === entityKey) this.store.delete(key);\n }\n for (const key of [...this.inFlight.keys()]) {\n if (entityKeyFromCacheKey(key) === entityKey) this.inFlight.delete(key);\n }\n const prefix = `${entityKey}${LABEL_SEP}`;\n for (const key of [...this.labels.keys()]) {\n if (key.startsWith(prefix)) this.labels.delete(key);\n }\n }\n\n clear(): void {\n this.store.clear();\n this.inFlight.clear();\n this.labels.clear();\n }\n\n private rememberLabels(entityKey: string, lang: string, options: ReferenceOption[]): void {\n for (const option of options) {\n this.labels.set(this.labelKey(entityKey, lang, option.value), option.label);\n }\n }\n\n /** Label-cache key. An object value collapses to its resolved text for the active language. */\n private labelKey(entityKey: string, lang: string, value: unknown): string {\n const canonical =\n value !== null && typeof value === 'object'\n ? resolveLabel(value as Record<string, string>, lang)\n : String(value ?? '');\n return [entityKey, lang, canonical].join(LABEL_SEP);\n }\n\n // ─── Loader result coercion (array | Promise | Observable) ──────────────────\n\n private invoke(\n loader: EntityReferenceLoader,\n ctx: ReferenceLoaderContext,\n ): Promise<ReferenceOption[]> {\n let result: ReferenceLoaderResult;\n try {\n result = loader(ctx);\n } catch (err) {\n // Reject rather than resolve empty: `load` must be able to tell failure from\n // \"no matches\", or it would cache the failure.\n return Promise.reject(err);\n }\n return this.toPromise(result);\n }\n\n private toPromise(result: ReferenceLoaderResult): Promise<ReferenceOption[]> {\n if (Array.isArray(result)) return Promise.resolve(result);\n if (this.isSubscribable(result)) {\n // First emission wins, so an Observable that stays open still resolves the load.\n return new Promise<ReferenceOption[]>((resolve, reject) => {\n let settled = false;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n fn();\n };\n result.subscribe({\n next: value => settle(() => resolve(value ?? [])),\n // An erroring stream is a failed load, not an empty one — see `invoke`.\n error: err => settle(() => reject(err)),\n // Completing without emitting is a legitimate empty result, and is cached.\n complete: () => settle(() => resolve([])),\n });\n });\n }\n return Promise.resolve(result as Promise<ReferenceOption[]>);\n }\n\n private isSubscribable(value: unknown): value is Subscribable<ReferenceOption[]> {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Subscribable<ReferenceOption[]>).subscribe === 'function'\n );\n }\n\n /** Exposed for cascade filtering, which matches a parent value against option values. */\n matches(a: unknown, b: unknown, lang = 'en'): boolean {\n return valuesMatch(a, b, lang);\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport type {\n EntityFormConfig,\n NestedFieldConfig,\n NestedTabConfig,\n ReferenceLoaderContext,\n ReferenceOption,\n} from '@dynamic-entity/core';\nimport { applyCascadeFilter } from '@dynamic-entity/core';\nimport { EntityRefRegistryService } from './entity-ref-registry.service';\nimport { EntityReferenceService } from './entity-reference.service';\n\n/**\n * CascadeDataService — loads entity-reference options and applies parent→child cascades.\n *\n * Loaders come from the registry only. This service owns the three things a\n * field component should not: resolving the loader, coercing whatever it returned\n * (array | Promise | Observable) into a Promise, and filtering by the parent's value.\n */\n@Injectable({ providedIn: 'root' })\nexport class CascadeDataService {\n private readonly registry = inject(EntityRefRegistryService);\n private readonly references = inject(EntityReferenceService);\n\n /** Preload runs by formConfigId, so a second call joins the first rather than re-fetching. */\n private readonly preloads = new Map<string, Promise<void>>();\n\n /** Registry key for a field: explicit `linkedEntityKey`, else the field id. */\n entityKeyFor(field: NestedFieldConfig): string {\n return field.entityReference?.linkedEntityKey ?? field.id;\n }\n\n /** Whether a loader is registered for this field. */\n canLoad(field: NestedFieldConfig): boolean {\n return this.registry.has(this.entityKeyFor(field));\n }\n\n /**\n * Load the options for a field, cascade-filtered against `parentValue`.\n * Returns `[]` when no loader is registered, or when a cascade child has no parent value yet.\n */\n async load(\n field: NestedFieldConfig,\n ctx: ReferenceLoaderContext = {},\n ): Promise<ReferenceOption[]> {\n const cfg = field.entityReference;\n if (!this.canLoad(field)) return [];\n\n // A cascade child with no parent selection must offer nothing.\n const hasParentValue =\n ctx.parentValue !== null && ctx.parentValue !== undefined && ctx.parentValue !== '';\n if (cfg?.parentField && !hasParentValue) return [];\n\n const lang = ctx.lang ?? 'en';\n\n // When the cascade can be resolved locally (`lookupFilter`/`lookupPath`), fetch the\n // unfiltered set once and filter per parent below — switching parent then costs nothing.\n // Otherwise the loader is the only thing that can narrow the list, so `parentValue` is\n // passed through and becomes part of the cache identity (one entry per parent).\n const filtersLocally = !!(cfg?.lookupFilter || cfg?.lookupPath);\n\n const options = await this.references.load(this.entityKeyFor(field), {\n ...ctx,\n parentValue: filtersLocally ? undefined : ctx.parentValue,\n filters: { ...(cfg?.filters ?? {}), ...(ctx.filters ?? {}) },\n displayFields: cfg?.displayFields,\n lang,\n });\n\n return applyCascadeFilter(options, ctx.parentValue, cfg, lang);\n }\n\n // ─── Preload ────────────────────────────────────────────────────────────────\n\n /**\n * Warm the cache for every entity a config's cascades depend on, so changing a parent\n * resolves from memory instead of a round-trip.\n *\n * Idempotent per `formConfigId`: calling it again returns the in-flight or completed run\n * rather than re-fetching.\n */\n initializeCascadeData(formConfigId: string, config: EntityFormConfig, lang = 'en'): Promise<void> {\n const existing = this.preloads.get(formConfigId);\n if (existing) return existing;\n\n const fields = this.cascadeFields(config);\n const run = Promise.all(\n fields.map(field =>\n this.references.load(this.entityKeyFor(field), {\n filters: field.entityReference?.filters,\n displayFields: field.entityReference?.displayFields,\n lang,\n }),\n ),\n ).then(() => undefined);\n\n this.preloads.set(formConfigId, run);\n return run;\n }\n\n /** Resolves true once `initializeCascadeData` for this config has finished. */\n async waitForData(formConfigId: string): Promise<boolean> {\n const run = this.preloads.get(formConfigId);\n if (!run) return false;\n await run;\n return true;\n }\n\n /**\n * Child options for a parent selection, from cache only — no load is triggered.\n * Returns `[]` when the entity has not been preloaded.\n */\n getCachedChildOptions(\n field: NestedFieldConfig,\n parentValue: unknown,\n lang = 'en',\n ): ReferenceOption[] {\n const cfg = field.entityReference;\n const cached = this.references.peek(this.entityKeyFor(field), {\n filters: cfg?.filters,\n displayFields: cfg?.displayFields,\n lang,\n });\n if (!cached) return [];\n return applyCascadeFilter(cached, parentValue, cfg, lang);\n }\n\n /** Forget the preload for one config. The option cache itself is untouched. */\n clearCache(formConfigId: string): void {\n this.preloads.delete(formConfigId);\n }\n\n /** Every entity-ref field in the config that participates in a cascade. */\n private cascadeFields(config: EntityFormConfig): NestedFieldConfig[] {\n const found: NestedFieldConfig[] = [];\n const walkFields = (fields: NestedFieldConfig[] | undefined) => {\n for (const field of fields ?? []) {\n const cfg = field.entityReference;\n if (cfg?.enabled && (cfg.parentField || cfg.lookupPath || cfg.lookupFilter)) {\n found.push(field);\n }\n walkFields(field.children);\n }\n };\n const walkTabs = (tabs: NestedTabConfig[] | undefined) => {\n for (const tab of tabs ?? []) {\n walkFields(tab.fields);\n walkTabs(tab.children);\n }\n };\n walkTabs(config?.tabs);\n return found;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport type { ReferenceOption } from '@dynamic-entity/core';\n\nexport interface EntityRefSelection {\n fieldId: string;\n /** The chosen option, or `null` when the selection was cleared. */\n option: ReferenceOption | null;\n}\n\n/**\n * EntityRefSelectionService — the channel an entity-ref field uses to publish *which record*\n * the user picked, so the owning form can run `autoPatch` against it.\n *\n * The control value alone is not enough: `autoPatch` copies fields out of the selected\n * record, which only the field component has after loading its options.\n *\n * Provided at `DynamicFormComponent` level so each form instance gets its own channel;\n * the `root` fallback keeps standalone field components injectable in isolation.\n */\n@Injectable({ providedIn: 'root' })\nexport class EntityRefSelectionService {\n private readonly subject = new Subject<EntityRefSelection>();\n\n readonly selection$ = this.subject.asObservable();\n\n emit(fieldId: string, option: ReferenceOption | null): void {\n this.subject.next({ fieldId, option });\n }\n}\n","import { Component, DestroyRef, Input, OnInit, inject, signal, ChangeDetectionStrategy } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { AbstractControl, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig, ReferenceOption } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { CascadeDataService } from '../services/cascade-data.service';\nimport { EntityRefSelectionService } from '../services/entity-ref-selection.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/**\n * EntityRefFieldComponent — a select populated from a consumer-registered loader.\n *\n * Cascades: when `entityReference.parentField` is set, the component watches that sibling\n * control (via `control.parent`) and reloads its own options on every parent change,\n * clearing a now-invalid selection. It publishes the picked record on\n * `EntityRefSelectionService` so the owning form can run `autoPatch`.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-entity-ref-field',\n standalone: true,\n imports: [ReactiveFormsModule],\n template: `\n <div\n class=\"ngx-field ngx-field--entity-ref\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">{{\n getLabel(control.value)\n }}</span>\n } @else {\n @if (loading()) {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-loading'\" role=\"status\">{{\n ui.text('loading', language)\n }}</span>\n } @else {\n <select\n class=\"ngx-field__input\"\n [attr.data-testid]=\"'field-' + field.id + '-input'\"\n [id]=\"domId()\"\n [formControl]=\"$any(control)\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.disabled]=\"field.disabled ? true : null\"\n >\n <option value=\"\">{{ placeholder || ui.text('selectPlaceholder', language) }}</option>\n @for (option of options(); track option.value) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </select>\n @if (awaitingParent()) {\n <span class=\"ngx-field__hint\" [attr.data-testid]=\"'field-' + field.id + '-hint'\">{{\n ui.text('selectParentFirst', language, { field: parentFieldId ?? '' })\n }}</span>\n }\n }\n @if (errorMessage) {\n <span class=\"ngx-field__error\" [attr.data-testid]=\"'field-' + field.id + '-error'\" [id]=\"domId('-error')\">{{\n errorMessage\n }}</span>\n }\n }\n </div>\n `,\n})\nexport class EntityRefFieldComponent implements OnInit {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n private readonly cascade = inject(CascadeDataService);\n private readonly selectionBus = inject(EntityRefSelectionService);\n private readonly destroyRef = inject(DestroyRef);\n\n readonly options = signal<ReferenceOption[]>([]);\n readonly loading = signal(false);\n /** True when this field cascades but its parent has no value yet. */\n readonly awaitingParent = signal(false);\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get placeholder(): string {\n return resolveLabel(this.field?.placeholder, this.language);\n }\n\n get parentFieldId(): string | undefined {\n return this.field?.entityReference?.parentField;\n }\n\n ngOnInit(): void {\n if (this.masked) return;\n void this.reload();\n this.watchParent();\n this.control?.valueChanges\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(value => this.publishSelection(String(value ?? '')));\n }\n\n /** Reload options against the parent's current value. */\n async reload(): Promise<void> {\n const parentValue = this.parentValue();\n this.awaitingParent.set(\n !!this.parentFieldId && (parentValue === null || parentValue === undefined || parentValue === ''),\n );\n\n if (!this.cascade.canLoad(this.field)) {\n this.options.set([]);\n return;\n }\n\n this.loading.set(true);\n try {\n this.options.set(await this.cascade.load(this.field, { parentValue, lang: this.language }));\n } finally {\n this.loading.set(false);\n }\n }\n\n /**\n * Publish the selected option so autoPatch can copy from its record.\n *\n * Driven from `valueChanges` rather than the select's `change` event: that event is the\n * same one the `formControl` directive listens to, so reading the control inside a\n * template `(change)` handler can see the previous value. `valueChanges` fires after the\n * model has updated — including Playwright `selectOption`, which updates the control\n * through the value accessor.\n */\n onSelectionChange(value?: string): void {\n this.publishSelection(value ?? String(this.control?.value ?? ''));\n }\n\n private publishSelection(current: string): void {\n const selected = this.options().find(o => String(o.value) === current);\n this.selectionBus.emit(this.field.id, selected ?? null);\n }\n\n getLabel(value: any): string {\n const option = this.options().find(o => String(o.value) === String(value));\n return option?.label ?? value ?? '—';\n }\n\n private parentValue(): unknown {\n const parentId = this.parentFieldId;\n if (!parentId) return undefined;\n return this.control?.parent?.get(parentId)?.value;\n }\n\n /** Reload (and drop a stale selection) whenever the parent control changes. */\n private watchParent(): void {\n const parentId = this.parentFieldId;\n if (!parentId) return;\n const parentControl = this.control?.parent?.get(parentId);\n if (!parentControl) return;\n\n parentControl.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {\n if (this.control.value) {\n this.control.setValue('', { emitEvent: false });\n this.selectionBus.emit(this.field.id, null);\n }\n void this.reload();\n });\n }\n /**\n * Resolved through `ValidationMessagesService`, so `provideNgxDynamicEntity({\n * validationMessages })` reaches this field. It used to render a fixed\n * \"This field has an error\", which made a documented, configurable feature work on three\n * of fifteen field types.\n */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Injectable, Type, inject } from '@angular/core';\nimport { FIELD_TYPE_REGISTRY, FIELD_TYPE_SETS } from '../tokens/injection-tokens';\n\n/**\n * FieldRegistryService — resolves field type strings to Angular component classes.\n *\n * **Tree-shaking contract:** this service holds *no* static imports of field components.\n * Nothing is bundled until something registers it, which is what makes the built-ins\n * opt-in. Register them with `provideBuiltInFieldTypes()` (all 21 keys) or a narrower\n * subset via `provideFieldTypes({ ... })` — see `providers/provide-field-types.ts`.\n *\n * Resolution order: consumer token registry → runtime registrations → nothing.\n */\n@Injectable({ providedIn: 'root' })\nexport class FieldRegistryService {\n private readonly consumerRegistry =\n inject(FIELD_TYPE_REGISTRY, { optional: true }) ?? new Map<string, Type<any>>();\n private readonly dynamicRegistry = new Map<string, Type<any>>();\n\n constructor() {\n // Sets contributed by provideFieldTypes()/provideBuiltInFieldTypes(), in declaration order.\n for (const set of inject(FIELD_TYPE_SETS, { optional: true }) ?? []) {\n this.registerAll(set);\n }\n }\n\n /** Register a field type component mapping at runtime. */\n register(type: string, component: Type<any>): void {\n this.dynamicRegistry.set(type, component);\n }\n\n /** Register multiple field type component mappings at runtime. */\n registerAll(map: Record<string, Type<any>>): void {\n for (const [type, comp] of Object.entries(map)) {\n this.dynamicRegistry.set(type, comp);\n }\n }\n\n /**\n * Resolve a field type string to a component class.\n * Consumer token registry takes priority over runtime registrations.\n */\n resolve(fieldType: string): Type<any> | null {\n return this.consumerRegistry.get(fieldType) ?? this.dynamicRegistry.get(fieldType) ?? null;\n }\n\n /** Check if a field type has a registered component. */\n has(fieldType: string): boolean {\n return this.consumerRegistry.has(fieldType) || this.dynamicRegistry.has(fieldType);\n }\n\n /** Every registered field type key. Consumer overrides and runtime registrations combined. */\n registeredTypes(): string[] {\n return [...new Set([...this.dynamicRegistry.keys(), ...this.consumerRegistry.keys()])].sort();\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport type { EntityFormConfig, NestedFieldConfig, NestedTabConfig } from '@dynamic-entity/core';\nimport { shouldMaskField as coreShouldMaskField, resolveEffectiveMask as coreResolveEffectiveMask } from '@dynamic-entity/core';\nimport { MASKED_ROLES } from '../tokens/injection-tokens';\n\n/**\n * RbacService — ALL permission checks and masking logic live here.\n */\n@Injectable({ providedIn: 'root' })\nexport class RbacService {\n private readonly maskedRoles = inject(MASKED_ROLES, { optional: true }) ?? [];\n\n /**\n * Check if any of the user's roles satisfy the required roles.\n * hasPermission(roles, undefined) → true (no restriction).\n */\n hasPermission(userRoles: string[], requiredRoles?: string[]): boolean {\n if (!requiredRoles?.length) return true;\n return userRoles.some(r => requiredRoles.includes(r));\n }\n\n /** 3-level OR resolution */\n resolveEffectiveMask(formMask?: boolean, tabMask?: boolean, fieldMask?: boolean): boolean {\n return coreResolveEffectiveMask(formMask, tabMask, fieldMask);\n }\n\n /** Check if the user's roles include any masked role */\n isUserMaskedRole(userRoles: string[]): boolean {\n return this.maskedRoles.some(r => userRoles.includes(r));\n }\n\n /** Determine if a specific field should be masked for this user */\n shouldMaskField(field: NestedFieldConfig, tab: NestedTabConfig | undefined, config: EntityFormConfig, userRoles: string[]): boolean {\n return coreShouldMaskField(field, tab, config, userRoles, this.maskedRoles);\n }\n\n /** Get view/edit/delete permissions for a config */\n getPermissions(config: EntityFormConfig, userRoles: string[]) {\n return {\n canView: this.hasPermission(userRoles, config.permissions?.view),\n canEdit: this.hasPermission(userRoles, config.permissions?.edit),\n canDelete: this.hasPermission(userRoles, config.permissions?.delete),\n };\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ComponentRef,\n Injector,\n Input,\n OnChanges, OnDestroy,\n SimpleChanges,\n ViewChild,\n ViewContainerRef,\n inject,\n isDevMode,\n} from '@angular/core';\nimport { AbstractControl } from '@angular/forms';\nimport { Subscription } from 'rxjs';\nimport type { NestedFieldConfig, EntityFormConfig, NestedTabConfig } from '@dynamic-entity/core';\nimport { findTab } from '@dynamic-entity/core';\nimport { FieldRegistryService } from '../../services/field-registry.service';\nimport { RbacService } from '../../services/rbac.service';\n\n/**\n * DynamicFieldComponent — mounts the correct field component for a given NestedFieldConfig.\n * Uses ViewContainerRef.createComponent() and passes inputs via setInput(); see\n * DynamicFieldComponentContract for the five inputs every field component receives.\n * Never add field-type-specific logic here — this component must remain generic.\n *\n * The 5 inputs (field, control, language, readonly, masked) are passed to every mounted\n * component uniformly — no special-casing per type.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-dynamic-field',\n standalone: true,\n template: `<ng-container #fieldHost></ng-container>`,\n styles: [\n `\n :host {\n display: block;\n width: 100%;\n min-width: 0;\n }\n `,\n ],\n})\nexport class DynamicFieldComponent implements OnChanges, OnDestroy {\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() config!: EntityFormConfig;\n @Input() currentTabId?: string;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() userRoles: string[] = [];\n\n @ViewChild('fieldHost', { read: ViewContainerRef, static: true })\n private readonly fieldHost!: ViewContainerRef;\n\n private readonly fieldRegistry = inject(FieldRegistryService);\n private readonly rbacService = inject(RbacService);\n /**\n * Passed into `createComponent` so a hosted field sees this host's injector — including\n * `DynamicFormComponent`'s scoped `EntityRefSelectionService`. Without it, a standalone\n * field resolves the root bus and `autoPatch` never runs.\n */\n private readonly injector = inject(Injector);\n\n private componentRef: ComponentRef<unknown> | null = null;\n\n ngOnChanges(_changes: SimpleChanges): void {\n this.mountField();\n }\n\n private mountField(): void {\n if (!this.field || !this.control) return;\n\n const ComponentClass = this.fieldRegistry.resolve(this.field.type);\n if (!ComponentClass) {\n this.warnUnresolved(this.field.type);\n return; // Unknown field type — render nothing\n }\n\n // Determine masking for this specific field\n const tab: NestedTabConfig | null = this.currentTabId ? findTab(this.config?.tabs, this.currentTabId) : null;\n const masked = this.rbacService.shouldMaskField(this.field, tab ?? undefined, this.config, this.userRoles);\n\n // Re-use existing component if same type, otherwise recreate\n if (this.componentRef && this.componentRef.instance instanceof ComponentClass) {\n this.setInputs(this.componentRef, masked);\n return;\n }\n\n this.fieldHost.clear();\n this.componentRef = this.fieldHost.createComponent(ComponentClass, {\n injector: this.injector,\n });\n this.setInputs(this.componentRef, masked);\n this.watchControl();\n this.componentRef.changeDetectorRef.detectChanges();\n }\n\n /**\n * Field types are opt-in (see `provideFieldTypes` / `provideBuiltInFieldTypes`), so an\n * unregistered type renders nothing. Say so once per type in dev builds rather than\n * leaving a silently blank slot.\n */\n private warnUnresolved(type: string): void {\n if (!isDevMode() || DynamicFieldComponent.warnedTypes.has(type)) return;\n DynamicFieldComponent.warnedTypes.add(type);\n console.warn(\n `[ngx-dynamic-entity] No component registered for field type \"${type}\" — the field was not rendered. ` +\n `Register it with provideFieldTypes({ '${type}': MyComponent }) or provideBuiltInFieldTypes().`,\n );\n }\n\n private static readonly warnedTypes = new Set<string>();\n\n /**\n * Re-check the hosted field component.\n *\n * The field components are OnPush, so they re-render on an input change, an event from\n * their own template, or a signal they read. `form.markAllAsTouched()` is none of those —\n * it flips `touched` from outside, and every field's error message depends on it. Without\n * this, a blocked submit would mark the form touched and no error would appear.\n */\n refresh(): void {\n this.componentRef?.changeDetectorRef.detectChanges();\n }\n\n /**\n * Re-check the hosted component whenever its control changes from outside.\n *\n * The field components are OnPush, so they re-render on an input change or an event from\n * their own template. A control mutated externally is neither — and that is not an edge\n * case: patchForm, reset, autoPatch and patchOnTrue all do exactly that. Without this, a\n * field patched from a record would keep rendering its previous value.\n *\n * `detectChanges()` rather than `markForCheck()`: a selection that arrives from a native\n * `change` event (or Playwright) may not be followed by another Angular tick, so a dirty\n * flag would never be flushed. Running CD on the hosted component now is the copy showing up.\n *\n * Done here rather than in each of the eighteen field components: the host owns the\n * component reference, so one subscription covers every type including custom ones.\n */\n private watchControl(): void {\n this.controlSub?.unsubscribe();\n if (!this.control) return;\n\n this.controlSub = this.control.valueChanges.subscribe(() => this.refresh());\n }\n\n private controlSub?: Subscription;\n\n ngOnDestroy(): void {\n this.controlSub?.unsubscribe();\n }\n\n /**\n * Pass all 5 contract inputs via ComponentRef.setInput() — uniform for all types.\n * The public shape is DynamicFieldComponentContract.\n * Must use setInput(), not property assignment: the field components declare inputs with\n * definite assignment and no initializer, and the lib compiles with\n * useDefineForClassFields:false, so `'field' in instance` is false until first set.\n */\n private setInputs(ref: ComponentRef<unknown>, masked: boolean): void {\n ref.setInput('field', this.field);\n ref.setInput('control', this.control);\n ref.setInput('language', this.language);\n ref.setInput('readonly', this.readonly || !!this.field.readonly);\n ref.setInput('masked', masked);\n }\n}\n","import { Component, Input, forwardRef, ChangeDetectionStrategy, inject } from '@angular/core';\nimport { AbstractControl, FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig, EntityFormConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { DynamicFieldComponent } from '../form/dynamic-field/dynamic-field.component';\n\n/** Renders a nested fieldset container for a group field's children. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-group-field',\n standalone: true,\n imports: [ReactiveFormsModule, forwardRef(() => DynamicFieldComponent)],\n template: `\n <fieldset\n class=\"ngx-field ngx-field--group\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <legend class=\"ngx-field__legend\">\n {{ label }}\n @if (hint) {\n <!-- A group's hint describes the whole section, so it hangs off the section's name. -->\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span class=\"ngx-field__hint\" role=\"tooltip\" [attr.data-testid]=\"'field-' + field.id + '-hint'\">{{ hint }}</span>\n </span>\n }\n </legend>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else {\n <div class=\"ngx-field__group-children\">\n @for (child of field.children ?? []; track child.id) {\n @if (child.visibility !== false) {\n <ngx-dynamic-field\n [field]=\"child\"\n [control]=\"getChildControl(child.id)\"\n [config]=\"config\"\n [language]=\"language\"\n [readonly]=\"readonly || !!child.readonly\"\n [userRoles]=\"userRoles\"\n />\n }\n }\n </div>\n }\n </fieldset>\n `,\n styles: [\n `\n .ngx-field--group {\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n padding: 16px;\n margin-bottom: 16px;\n background: #fafafa;\n }\n .ngx-field__legend {\n font-weight: 600;\n font-size: 14px;\n padding: 0 8px;\n color: #334155;\n }\n .ngx-field__group-children {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n `,\n ],\n})\nexport class GroupFieldComponent {\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() config!: EntityFormConfig;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n @Input() userRoles: string[] = [];\n\n /** Author help text for the section as a whole. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n getChildControl(childId: string): AbstractControl {\n const group = this.control as FormGroup;\n return group?.get(childId) as AbstractControl;\n }\n}\n","import { Injectable, inject, isDevMode } from '@angular/core';\nimport { AsyncValidatorFn, ValidatorFn, Validators } from '@angular/forms';\nimport type { FieldValidators } from '@dynamic-entity/core';\nimport { ASYNC_VALIDATOR_REGISTRY, VALIDATOR_REGISTRY } from '../tokens/injection-tokens';\n\n/**\n * ValidatorRegistryService — resolves validator configs / key strings to Angular ValidatorFns.\n */\n@Injectable({ providedIn: 'root' })\nexport class ValidatorRegistryService {\n private readonly consumerRegistry = inject(VALIDATOR_REGISTRY, { optional: true }) ?? new Map();\n private readonly asyncRegistry = inject(ASYNC_VALIDATOR_REGISTRY, { optional: true }) ?? new Map();\n\n /**\n * Resolve a validator key string to a ValidatorFn.\n * Supports parameterized built-ins like 'min:0', 'maxLength:255'.\n */\n resolve(validatorKey: string): ValidatorFn | null {\n if (this.consumerRegistry.has(validatorKey)) {\n return this.consumerRegistry.get(validatorKey);\n }\n\n if (validatorKey === 'required') return Validators.required;\n if (validatorKey === 'email') return Validators.email;\n\n const [name, param] = validatorKey.split(':');\n const value = parseFloat(param);\n\n if (name === 'min' && !isNaN(value)) return Validators.min(value);\n if (name === 'max' && !isNaN(value)) return Validators.max(value);\n if (name === 'minLength' && !isNaN(value)) return Validators.minLength(value);\n if (name === 'maxLength' && !isNaN(value)) return Validators.maxLength(value);\n\n return null;\n }\n\n /** Resolve multiple validator keys into a ValidatorFn[] */\n resolveAll(validatorKeys: string[] = []): ValidatorFn[] {\n return validatorKeys.map(k => this.resolve(k)).filter((v): v is ValidatorFn => v !== null);\n }\n\n /** Resolve a FieldValidators object or string[] into ValidatorFn[] */\n resolveFromConfig(config?: FieldValidators | string[]): ValidatorFn[] {\n if (!config) return [];\n if (Array.isArray(config)) return this.resolveAll(config);\n\n const fnList: ValidatorFn[] = [];\n if (config.required) fnList.push(Validators.required);\n if (config.min !== undefined) fnList.push(Validators.min(config.min));\n if (config.max !== undefined) fnList.push(Validators.max(config.max));\n if (config.minLength !== undefined) fnList.push(Validators.minLength(config.minLength));\n if (config.maxLength !== undefined) fnList.push(Validators.maxLength(config.maxLength));\n if (config.pattern) {\n // `Validators.pattern` compiles the string, so an unparseable one threw here — during\n // control construction, which takes the whole form down rather than one field's format\n // check. `validateConfig` reports it as an error; at runtime the field degrades to no\n // pattern validation, which is exactly what the server-side import path already does.\n try {\n fnList.push(Validators.pattern(config.pattern));\n } catch (err) {\n this.warnOnce(\n `pattern:${config.pattern}`,\n `The pattern \"${config.pattern}\" is not a valid regular expression ` +\n `(${err instanceof Error ? err.message : String(err)}), so no format check is ` +\n `applied to this field. Run \"dynamic-entity validate\" over the config to find it.`,\n );\n }\n }\n if (config.email) fnList.push(Validators.email);\n\n // Named validators from the consumer registry. This branch previously hardcoded the\n // built-ins and consulted the registry only for the `string[]` form of this config, so\n // a validator the consumer had registered could not be named from a typed schema\n // without casting it to `any`.\n for (const key of config.custom ?? []) {\n const fn = this.resolve(key);\n if (fn) fnList.push(fn);\n else this.warnUnresolved('custom', key);\n }\n\n return fnList;\n }\n\n /**\n * Resolve the async validators a field names, in `validators.customAsync`.\n *\n * Async validators are deliberately a separate registry and a separate config key: Angular\n * attaches them through `setAsyncValidators`, runs them only once the synchronous ones\n * pass, and holds the control in `pending` until they settle. Mixing them into the\n * synchronous list would silently never run them.\n *\n * An unknown name is skipped rather than throwing, matching the synchronous behaviour.\n */\n resolveAsyncFromConfig(config?: FieldValidators | string[]): AsyncValidatorFn[] {\n if (!config || Array.isArray(config)) return [];\n\n const out: AsyncValidatorFn[] = [];\n for (const key of config.customAsync ?? []) {\n const fn = this.asyncRegistry.get(key);\n if (fn) out.push(fn);\n else this.warnUnresolved('customAsync', key);\n }\n return out;\n }\n\n /**\n * Say when a named validator resolved to nothing.\n *\n * It used to be dropped in silence, which is the worst failure mode this library has: the\n * schema says the field is checked, the field is not checked, the form saves, and nothing\n * anywhere said so. For `customAsync` that is typically a uniqueness check, so the duplicate\n * lands in the database.\n *\n * Dev only, once per name — this runs while controls are built, which happens on every\n * config change. `validateConfig` with `knownValidators` is the build-time version of the\n * same check, and it fails CI rather than a console.\n */\n private warnUnresolved(kind: 'custom' | 'customAsync', key: string): void {\n this.warnOnce(\n `${kind}:${key}`,\n `No validator named \"${key}\" is registered, so validators.${kind} drops it and it never ` +\n `runs. Register it with provideNgxDynamicEntity({ ${\n kind === 'customAsync' ? 'asyncValidators' : 'validators'\n }: { '${key}': ... } }).`,\n );\n }\n\n /** Per service instance, which is per injector — so a test gets a clean slate. */\n private readonly warned = new Set<string>();\n\n private warnOnce(id: string, message: string): void {\n if (!isDevMode() || this.warned.has(id)) return;\n this.warned.add(id);\n console.warn(`[ngx-dynamic-entity] ${message}`);\n }\n}\n","import { Component, Input, inject, forwardRef, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';\nimport { AbstractControl, FormArray, FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport type { NestedFieldConfig, EntityFormConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { DynamicFieldComponent } from '../form/dynamic-field/dynamic-field.component';\nimport { ValidatorRegistryService } from '../services/validator-registry.service';\nimport { UiTextService } from '../services/ui-text.service';\n\n/** Renders repeating rows for a FormArray, with Add Item and Remove. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-array-field',\n standalone: true,\n imports: [ReactiveFormsModule, forwardRef(() => DynamicFieldComponent)],\n template: `\n <div\n class=\"ngx-field ngx-field--array\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__array-header\">\n <label class=\"ngx-field__label\">\n {{ label }}\n @if (hint) {\n <!-- Explains the set of rows, so it hangs off their name rather than any one row. -->\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span class=\"ngx-field__hint\" role=\"tooltip\" [attr.data-testid]=\"'field-' + field.id + '-hint'\">{{\n hint\n }}</span>\n </span>\n }\n </label>\n @if (!readonly && !masked) {\n <button\n type=\"button\"\n class=\"ngx-field__array-add-btn\"\n [attr.data-testid]=\"'field-' + field.id + '-add'\"\n (click)=\"addItem()\"\n >\n {{ ui.text('addItem', language) }}\n </button>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else {\n <div class=\"ngx-field__array-list\">\n @for (itemGroup of formArray.controls; track idx; let idx = $index) {\n <div class=\"ngx-field__array-item\" [attr.data-testid]=\"'field-' + field.id + '-row'\">\n <div class=\"ngx-field__array-item-header\">\n <span class=\"ngx-field__array-item-title\">{{ ui.text('itemNumber', language, { number: idx + 1 }) }}</span>\n @if (!readonly) {\n <button\n type=\"button\"\n class=\"ngx-field__array-remove-btn\"\n [attr.data-testid]=\"'field-' + field.id + '-remove-' + idx\"\n (click)=\"removeItem(idx)\"\n >\n {{ ui.text('remove', language) }}\n </button>\n }\n </div>\n <div class=\"ngx-field__array-item-fields\">\n @for (child of field.children ?? []; track child.id) {\n @if (child.visibility !== false) {\n <ngx-dynamic-field\n [field]=\"child\"\n [control]=\"getItemChildControl(itemGroup, child.id)\"\n [config]=\"config\"\n [language]=\"language\"\n [readonly]=\"readonly || !!child.readonly\"\n [userRoles]=\"userRoles\"\n />\n }\n }\n </div>\n </div>\n }\n @if (formArray.controls.length === 0) {\n <div class=\"ngx-field__array-empty\" [attr.data-testid]=\"'field-' + field.id + '-empty'\">\n {{ ui.text('noItems', language) }}\n </div>\n }\n </div>\n }\n </div>\n `,\n styles: [\n `\n .ngx-field--array {\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n padding: 16px;\n margin-bottom: 16px;\n background: #f8fafc;\n }\n .ngx-field__array-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 12px;\n }\n .ngx-field__array-add-btn {\n background: #2563eb;\n color: #fff;\n border: none;\n padding: 6px 12px;\n border-radius: 4px;\n font-weight: 500;\n cursor: pointer;\n }\n .ngx-field__array-add-btn:hover {\n background: #1d4ed8;\n }\n .ngx-field__array-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n .ngx-field__array-item {\n background: #fff;\n border: 1px solid #cbd5e1;\n border-radius: 6px;\n padding: 12px;\n }\n .ngx-field__array-item-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n border-bottom: 1px solid #f1f5f9;\n padding-bottom: 6px;\n }\n .ngx-field__array-item-title {\n font-weight: 600;\n font-size: 13px;\n color: #475569;\n }\n .ngx-field__array-remove-btn {\n background: #ef4444;\n color: #fff;\n border: none;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 12px;\n cursor: pointer;\n }\n .ngx-field__array-empty {\n color: #94a3b8;\n font-style: italic;\n font-size: 13px;\n }\n `,\n ],\n})\nexport class ArrayFieldComponent {\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n /**\n * addItem/removeItem are public and may be called from outside this component's template,\n * which under OnPush would not re-render. The host also watches the control, but this\n * keeps the component correct on its own.\n */\n private readonly cdr = inject(ChangeDetectorRef);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() config!: EntityFormConfig;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n @Input() userRoles: string[] = [];\n\n private readonly fb = inject(FormBuilder);\n private readonly validatorRegistry = inject(ValidatorRegistryService);\n\n /** Author help text for the section as a whole. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n get formArray(): FormArray {\n return this.control as FormArray;\n }\n\n getItemChildControl(itemGroup: AbstractControl, childId: string): AbstractControl {\n return (itemGroup as FormGroup).get(childId) as AbstractControl;\n }\n\n addItem(): void {\n const controls: Record<string, any> = {};\n for (const child of this.field.children ?? []) {\n const validators = this.validatorRegistry.resolveFromConfig(child.validators);\n controls[child.id] = [child.defaultValue ?? null, validators];\n }\n const group = this.fb.group(controls);\n this.formArray.push(group);\n this.cdr.markForCheck();\n }\n\n removeItem(index: number): void {\n this.formArray.removeAt(index);\n this.cdr.markForCheck();\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport type { FileRef, Subscribable, UploadResult } from '@dynamic-entity/core';\nimport { UPLOAD_HANDLER } from '../tokens/injection-tokens';\n\n/**\n * FileUploadService — the single place image-field and file-field agree on how a\n * selected `File` becomes a `FileRef`.\n *\n * With `UPLOAD_HANDLER` registered the file is persisted and stored as `{ url }`;\n * without one it is stored as `{ file }` for the consumer to upload at submit time.\n */\n@Injectable({ providedIn: 'root' })\nexport class FileUploadService {\n private readonly handler = inject(UPLOAD_HANDLER, { optional: true });\n\n get hasHandler(): boolean {\n return !!this.handler;\n }\n\n /** Metadata common to both persisted and unpersisted refs. */\n private describe(file: File): FileRef {\n return { name: file.name, size: file.size, mimeType: file.type };\n }\n\n /**\n * Turn a selected File into the value to store on the control.\n * @throws when a registered handler rejects — callers surface it as a field error.\n */\n async toFileRef(file: File): Promise<FileRef> {\n const meta = this.describe(file);\n if (!this.handler) return { ...meta, file };\n\n const result = await this.normalize(this.handler(file));\n return { ...meta, url: result.url, name: result.name ?? meta.name };\n }\n\n /** Object URL for previewing an unpersisted File. Callers must revoke it. */\n previewUrlFor(ref: FileRef | null | undefined): string | null {\n if (!ref) return null;\n if (ref.url) return ref.url;\n if (ref.file && typeof URL !== 'undefined' && typeof URL.createObjectURL === 'function') {\n return URL.createObjectURL(ref.file);\n }\n return null;\n }\n\n revokePreviewUrl(url: string | null): void {\n if (!url || !url.startsWith('blob:')) return;\n if (typeof URL !== 'undefined' && typeof URL.revokeObjectURL === 'function') {\n URL.revokeObjectURL(url);\n }\n }\n\n private normalize(\n result: UploadResult | Promise<UploadResult> | Subscribable<UploadResult>,\n ): Promise<UploadResult> {\n if (this.isSubscribable(result)) {\n return new Promise<UploadResult>((resolve, reject) => {\n let settled = false;\n result.subscribe({\n next: value => {\n if (settled) return;\n settled = true;\n resolve(value);\n },\n error: err => {\n if (settled) return;\n settled = true;\n reject(err);\n },\n complete: () => {\n if (settled) return;\n settled = true;\n reject(new Error('Upload handler completed without emitting a result.'));\n },\n });\n });\n }\n return Promise.resolve(result as UploadResult | Promise<UploadResult>);\n }\n\n private isSubscribable(value: unknown): value is Subscribable<UploadResult> {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Subscribable<UploadResult>).subscribe === 'function'\n );\n }\n}\n","import { Component, OnDestroy, inject, Input, signal, ChangeDetectionStrategy } from '@angular/core';\nimport { AbstractControl } from '@angular/forms';\nimport type { FileRef, NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { resolveLabel } from '@dynamic-entity/core';\nimport { FileUploadService } from '../services/file-upload.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/**\n * Image field: preview thumbnail + upload button.\n *\n * With `UPLOAD_HANDLER` registered the file is persisted and stored as `{ url }`; without one\n * it is stored as `{ file }` and previewed from an object URL (revoked when replaced/destroyed).\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-image-field',\n standalone: true,\n imports: [],\n template: `\n <div\n class=\"ngx-field ngx-field--image\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else {\n <div class=\"ngx-field__image-wrap\">\n @if (previewUrl()) {\n <img class=\"ngx-field__image-preview\" [src]=\"previewUrl()\" [alt]=\"label\" />\n } @else {\n <div class=\"ngx-field__image-placeholder\">\n <span>📷</span>\n <span>{{ ui.text('noImage', language) }}</span>\n </div>\n }\n @if (!readonly) {\n <div class=\"ngx-field__image-actions\">\n <label class=\"ngx-field__upload-btn\" [class.ngx-field__upload-btn--loading]=\"uploading()\">\n @if (uploading()) {\n <span>{{ ui.text('uploading', language) }}</span>\n } @else {\n <span>{{ ui.text(previewUrl() ? 'changeImage' : 'uploadImage', language) }}</span>\n <input\n type=\"file\"\n class=\"ngx-field__file-input\"\n [id]=\"domId()\"\n accept=\"image/*\"\n [disabled]=\"field.disabled || uploading()\"\n (change)=\"onFileSelect($any($event.target).files[0])\"\n [attr.aria-describedby]=\"describedBy()\"\n />\n }\n </label>\n @if (previewUrl()) {\n <button type=\"button\" class=\"ngx-field__remove-btn\" (click)=\"remove()\">\n {{ ui.text('remove', language) }}\n </button>\n }\n </div>\n }\n </div>\n <!-- An upload failure and an unmet validator are different problems, and this only\n ever showed the first. A required file left unchosen said nothing, and a\n configured required message had no element to appear in. -->\n @if (uploadError() || errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ uploadError() || errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class ImageFieldComponent implements OnDestroy {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n private readonly uploads = inject(FileUploadService);\n\n readonly uploading = signal(false);\n readonly uploadError = signal<string | null>(null);\n\n /** Cached so an object URL is minted once per File, not once per change-detection pass. */\n private previewSource: FileRef | null = null;\n private previewCache: string | null = null;\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n previewUrl(): string | null {\n const value = (this.control?.value as FileRef | null) ?? null;\n if (value === this.previewSource) return this.previewCache;\n\n this.uploads.revokePreviewUrl(this.previewCache);\n this.previewSource = value;\n this.previewCache = this.uploads.previewUrlFor(value);\n return this.previewCache;\n }\n\n async onFileSelect(file: File | undefined): Promise<void> {\n if (!file) return;\n this.uploadError.set(null);\n this.uploading.set(true);\n try {\n this.control.setValue(await this.uploads.toFileRef(file));\n this.control.markAsTouched();\n } catch {\n this.uploadError.set('Upload failed. Please try again.');\n } finally {\n this.uploading.set(false);\n }\n }\n\n remove(): void {\n this.control.setValue(null);\n this.control.markAsTouched();\n }\n\n ngOnDestroy(): void {\n this.uploads.revokePreviewUrl(this.previewCache);\n }\n /** Validation, as distinct from the upload failures this field already reported. */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { Component, inject, Input, signal, ChangeDetectionStrategy } from '@angular/core';\nimport { AbstractControl } from '@angular/forms';\nimport type { FileRef, NestedFieldConfig } from '@dynamic-entity/core';\nimport { MASKED_PLACEHOLDER } from '../tokens/injection-tokens';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\nimport { fileRefName, resolveLabel } from '@dynamic-entity/core';\nimport { FileUploadService } from '../services/file-upload.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { fieldDescribedBy, fieldDomId, nextFieldInstanceId } from './field-dom-id';\n\n/**\n * File field: file input with filename display and download link.\n * Shares the `FileRef` / `UPLOAD_HANDLER` contract with image-field via FileUploadService.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-file-field',\n standalone: true,\n imports: [],\n template: `\n <div\n class=\"ngx-field ngx-field--file\"\n [attr.data-testid]=\"'field-' + field.id\"\n [attr.data-field-type]=\"field.type\"\n [class.ngx-field--readonly]=\"readonly\"\n [class.ngx-field--masked]=\"masked\"\n >\n <div class=\"ngx-field__label-row\">\n <label class=\"ngx-field__label\" [attr.for]=\"domId()\">{{ label }}</label>\n @if (hint) {\n <span class=\"ngx-field__hint-wrap\">\n <span class=\"ngx-field__hint-icon\" aria-hidden=\"true\">i</span>\n <span\n class=\"ngx-field__hint\"\n role=\"tooltip\"\n [attr.data-testid]=\"'field-' + field.id + '-hint'\"\n [id]=\"domId('-hint')\"\n >{{ hint }}</span\n >\n </span>\n }\n </div>\n @if (masked) {\n <span class=\"ngx-field__value ngx-field__value--masked\" [attr.data-testid]=\"'field-' + field.id + '-masked'\">{{\n maskedText\n }}</span>\n } @else if (readonly) {\n @if (fileUrl()) {\n <a class=\"ngx-field__file-link\" [href]=\"fileUrl()!\" target=\"_blank\" rel=\"noopener\">\n 📎 {{ fileName() || ui.text('downloadFile', language) }}\n </a>\n } @else {\n <span class=\"ngx-field__value\" [attr.data-testid]=\"'field-' + field.id + '-value'\">—</span>\n }\n } @else {\n <div class=\"ngx-field__file-wrap\">\n @if (fileName()) {\n <div class=\"ngx-field__file-selected\">\n <span class=\"ngx-field__file-name\">📎 {{ fileName() }}</span>\n <button\n type=\"button\"\n class=\"ngx-field__remove-btn\"\n (click)=\"remove()\"\n [attr.aria-label]=\"ui.text('removeFile', language)\"\n >\n ✕\n </button>\n </div>\n }\n <label class=\"ngx-field__upload-btn\" [class.ngx-field__upload-btn--loading]=\"uploading()\">\n @if (uploading()) {\n <span>{{ ui.text('uploading', language) }}</span>\n } @else {\n <span>{{ fileName() ? ui.text('replaceFile', language) : ui.text('chooseFile', language) }}</span>\n <input\n type=\"file\"\n class=\"ngx-field__file-input\"\n [id]=\"domId()\"\n [disabled]=\"field.disabled || uploading()\"\n (change)=\"onFileSelect($any($event.target).files[0])\"\n [attr.aria-describedby]=\"describedBy()\"\n />\n }\n </label>\n </div>\n <!-- An upload failure and an unmet validator are different problems, and this only\n ever showed the first. A required file left unchosen said nothing, and a\n configured required message had no element to appear in. -->\n @if (uploadError() || errorMessage) {\n <span\n class=\"ngx-field__error\"\n [attr.data-testid]=\"'field-' + field.id + '-error'\"\n [id]=\"domId('-error')\"\n role=\"alert\"\n >{{ uploadError() || errorMessage }}</span\n >\n }\n }\n </div>\n `,\n})\nexport class FileFieldComponent {\n /**\n * Unique to this component instance: an `array` renders the same field once per row, and a\n * DOM id may not repeat. See `field-dom-id.ts`.\n */\n private readonly instanceId = nextFieldInstanceId();\n protected domId(suffix = ''): string {\n return fieldDomId(this.field, this.instanceId, suffix);\n }\n\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */\n protected readonly maskedText = inject(MASKED_PLACEHOLDER, { optional: true }) ?? 'XXXXXXXXX';\n private readonly messages = inject(ValidationMessagesService);\n @Input() field!: NestedFieldConfig;\n @Input() control!: AbstractControl;\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() masked: boolean = false;\n\n private readonly uploads = inject(FileUploadService);\n\n readonly uploading = signal(false);\n readonly uploadError = signal<string | null>(null);\n\n get label(): string {\n return resolveLabel(this.field?.label, this.language);\n }\n\n private get value(): FileRef | null {\n return (this.control?.value as FileRef | null) ?? null;\n }\n\n fileUrl(): string | null {\n return this.value?.url ?? null;\n }\n\n fileName(): string | null {\n return fileRefName(this.value) || null;\n }\n\n async onFileSelect(file: File | undefined): Promise<void> {\n if (!file) return;\n this.uploadError.set(null);\n this.uploading.set(true);\n try {\n this.control.setValue(await this.uploads.toFileRef(file));\n this.control.markAsTouched();\n } catch {\n this.uploadError.set('Upload failed. Please try again.');\n } finally {\n this.uploading.set(false);\n }\n }\n\n remove(): void {\n this.control.setValue(null);\n this.control.markAsTouched();\n }\n /** Validation, as distinct from the upload failures this field already reported. */\n /** Author help text, shown under the control and named by `aria-describedby`. */\n get hint(): string {\n return resolveLabel(this.field?.hint, this.language);\n }\n\n /** The ids of whatever is describing this control right now. */\n protected describedBy(): string | null {\n return fieldDescribedBy(s => this.domId(s), { hint: !!this.hint, error: !!this.errorMessage });\n }\n\n get errorMessage(): string {\n if (!this.control?.errors || !this.control.touched) return '';\n return this.messages.resolveForField(this.control.errors, this.language, this.field.type);\n }\n}\n","import { EnvironmentProviders, Type, makeEnvironmentProviders } from '@angular/core';\nimport { FIELD_TYPE_SETS } from '../tokens/injection-tokens';\n\nimport { TextFieldComponent } from '../field-types/text-field.component';\nimport { TextareaFieldComponent } from '../field-types/textarea-field.component';\nimport { MarkdownFieldComponent } from '../field-types/markdown-field.component';\nimport { NumberFieldComponent } from '../field-types/number-field.component';\nimport { CurrencyFieldComponent } from '../field-types/currency-field.component';\nimport { EmailFieldComponent } from '../field-types/email-field.component';\nimport { PasswordFieldComponent } from '../field-types/password-field.component';\nimport { CheckboxFieldComponent } from '../field-types/checkbox-field.component';\nimport { BooleanFieldComponent } from '../field-types/boolean-field.component';\nimport { DateFieldComponent } from '../field-types/date-field.component';\nimport { DateTimeFieldComponent } from '../field-types/date-time-field.component';\nimport { TimeFieldComponent } from '../field-types/time-field.component';\nimport { MonthYearFieldComponent } from '../field-types/month-year-field.component';\nimport { DropdownFieldComponent } from '../field-types/dropdown-field.component';\nimport { RadioFieldComponent } from '../field-types/radio-field.component';\nimport { MultiSelectFieldComponent } from '../field-types/multi-select-field.component';\nimport { EntityRefFieldComponent } from '../field-types/entity-ref-field.component';\nimport { GroupFieldComponent } from '../field-types/group-field.component';\nimport { ArrayFieldComponent } from '../field-types/array-field.component';\nimport { ImageFieldComponent } from '../field-types/image-field.component';\nimport { FileFieldComponent } from '../field-types/file-field.component';\n\n/**\n * Field-type registration — the tree-shaking seam.\n *\n * `FieldRegistryService` imports no components. Whatever you register here is what gets\n * bundled, so an app that only uses text/number/dropdown pays for three components and\n * their imports, not twenty-one.\n *\n * ```ts\n * // Everything (convenient; bundles all built-ins):\n * provideNgxDynamicEntity(), provideBuiltInFieldTypes()\n *\n * // Only what this app renders:\n * provideFieldTypes({ text: TextFieldComponent, number: NumberFieldComponent })\n * ```\n *\n * Both merge into `FIELD_TYPE_REGISTRY`; later registrations win on key collision.\n */\n\n/** Map of every built-in field type key → component. Referencing this pulls in all of them. */\nexport function builtInFieldTypes(): Record<string, Type<any>> {\n return {\n text: TextFieldComponent,\n textarea: TextareaFieldComponent,\n markdown: MarkdownFieldComponent,\n number: NumberFieldComponent,\n currency: CurrencyFieldComponent,\n email: EmailFieldComponent,\n password: PasswordFieldComponent,\n checkbox: CheckboxFieldComponent,\n boolean: BooleanFieldComponent,\n date: DateFieldComponent,\n datetime: DateTimeFieldComponent,\n time: TimeFieldComponent,\n monthYear: MonthYearFieldComponent,\n dropdown: DropdownFieldComponent,\n radio: RadioFieldComponent,\n multiSelect: MultiSelectFieldComponent,\n 'entity-ref': EntityRefFieldComponent,\n group: GroupFieldComponent,\n array: ArrayFieldComponent,\n image: ImageFieldComponent,\n file: FileFieldComponent,\n };\n}\n\n/** Register a specific set of field types. Only the components you name are bundled. */\nexport function provideFieldTypes(types: Record<string, Type<any>>): EnvironmentProviders {\n return makeEnvironmentProviders([\n { provide: FIELD_TYPE_SETS, useValue: types, multi: true },\n ]);\n}\n\n/** Register all 21 built-in field type keys. Convenience for apps that use most of them. */\nexport function provideBuiltInFieldTypes(): EnvironmentProviders {\n return provideFieldTypes(builtInFieldTypes());\n}\n","import { Injectable, inject } from '@angular/core';\nimport { HOOK_REGISTRY } from '../tokens/injection-tokens';\n\n/**\n * HookRegistryService — stores and runs Angular-side pre/post hooks.\n * Consumers register hooks via provideNgxDynamicEntity({ hooks: { 'clients:beforeSave': fn } }).\n */\n@Injectable({ providedIn: 'root' })\nexport class HookRegistryService {\n private readonly registry = inject(HOOK_REGISTRY, { optional: true }) ?? new Map();\n\n has(key: string): boolean {\n return this.registry.has(key);\n }\n\n async run(key: string, data: any, context: any = {}): Promise<any> {\n const hook = this.registry.get(key);\n if (!hook) return data;\n return hook(data, context);\n }\n}\n","import { Injectable } from '@angular/core';\nimport type {\n EntityFormConfig,\n EvaluateFormRulesOptions,\n FieldScopeEntry,\n FormRule,\n NestedFieldConfig,\n NestedTabConfig,\n RuleEvaluationResult,\n} from '@dynamic-entity/core';\nimport type { AbstractControl } from '@angular/forms';\nimport { evaluateFieldVisibility, evaluateFormRules, filterRulesForTab } from '@dynamic-entity/core';\n\n/** What `syncHiddenFieldState` needs from the form it is operating on. */\nexport interface RuleSyncContext {\n result: RuleEvaluationResult;\n /** The values `showWhen` is evaluated against — the flat map the rules engine reads. */\n values: Record<string, unknown>;\n /** Every name a field answers to: its bare id, and its bracketed path. */\n namesOf(field: NestedFieldConfig): readonly string[];\n /**\n * The field's dotted address, unbracketed — `personal.address.city`.\n *\n * Separate from `namesOf` because it is compared as a *prefix*: a container hides its\n * descendants, and `[personal.address]` is not a prefix of `[personal.address.city]` once\n * the brackets are in the way.\n */\n addressOf(field: NestedFieldConfig): string;\n /** The control a scope entry addresses, or `null` when it has no static path. */\n controlFor(entry: FieldScopeEntry): AbstractControl | null;\n}\n\n/**\n * RulesEvaluationService — evaluates rules, and owns what a result *means*.\n *\n * It used to be two passthrough methods, with the interpretation spread across the component:\n * the render filter decided one way what a rule result did to a field, and the validity sync\n * decided again forty lines further down. They disagreed about what \"every field\" meant, and\n * the consequence was a required field inside a `group` that a rule had hidden holding\n * `form.invalid` true forever with nothing on screen to explain it.\n *\n * Precedence lives here now, in one method that both callers go through. Still stateless —\n * every method takes the result it is interpreting, so there is nothing to go stale against a\n * rebuilt form and nothing to reset between configs.\n */\n@Injectable({ providedIn: 'root' })\nexport class RulesEvaluationService {\n /**\n * Evaluate rules against form values and optional original baseline values.\n */\n evaluate(\n rules: FormRule[] | undefined | null,\n values: Record<string, unknown>,\n originalValues?: Record<string, unknown>,\n options?: EvaluateFormRulesOptions,\n ): RuleEvaluationResult {\n return evaluateFormRules(rules, values, originalValues, options);\n }\n\n /**\n * Filter rules pertinent to a single tab.\n */\n filterForTab(rules: FormRule[] | undefined | null, tabId: string, config: EntityFormConfig): FormRule[] {\n return filterRulesForTab(rules, tabId, config);\n }\n\n /**\n * Whether a field renders, under the precedence documented on `RuleEvaluationResult`.\n *\n * An explicit hide beats everything. A show beats static hiding — `visibility: false`, or a\n * `showWhen` that does not currently hold — because a rule that could only hide what the\n * config already hides would have nothing to say, and `{ visibility: true }` was a\n * documented no-op until it did. Otherwise the config's own visibility decides.\n */\n isFieldVisible(\n result: RuleEvaluationResult,\n field: NestedFieldConfig,\n names: readonly string[],\n values: Record<string, unknown>,\n ): boolean {\n const sets = this.nameSets(result);\n if (names.some(name => sets.hidden.has(name))) return false;\n if (names.some(name => sets.shown.has(name))) return true;\n return evaluateFieldVisibility(field, values);\n }\n\n /** The same precedence for a tab. */\n isTabVisible(result: RuleEvaluationResult, tab: NestedTabConfig): boolean {\n if (result.hiddenTabs.includes(tab.id)) return false;\n return tab.visibility !== false || result.shownTabs.includes(tab.id);\n }\n\n /**\n * Keep a hidden field's control out of form validity.\n *\n * A field hidden by a rule or a `showWhen` is filtered out of the render, but its\n * validators stay attached — so a hidden *required* field holds `form.invalid` true\n * forever, permanently disabling Save with nothing on screen to explain why.\n *\n * Disabling is the fix rather than stripping validators: Angular excludes disabled controls\n * from validity, and the field's own validators survive intact for when it comes back.\n * Values are untouched — a disabled control still carries its value, so rule evaluation and\n * the emitted record see exactly what they saw before. That also keeps this from feeding\n * back on itself: hiding a field cannot change the values the rules are evaluated over.\n *\n * The predicate is `isFieldVisible`, the same one the render filter uses, so what is on\n * screen and what counts toward validity cannot drift apart.\n *\n * Entries must arrive parent-first, which is what `collectFieldScopes` yields: a container's\n * children are skipped once the container itself is hidden, because Angular's `disable()`\n * cascades to descendants and a child's `enable()` walks back up recalculating ancestors.\n * Toggling a child inside a hidden group would fight its parent.\n */\n syncHiddenFieldState(entries: readonly FieldScopeEntry[], ctx: RuleSyncContext): void {\n const hiddenContainers: string[] = [];\n\n for (const entry of entries) {\n const field = entry.field;\n if (!field?.id) continue;\n\n const address = ctx.addressOf(field);\n if (hiddenContainers.some(prefix => address.startsWith(`${prefix}.`))) continue;\n\n const hidden = !this.isFieldVisible(ctx.result, field, ctx.namesOf(field), ctx.values);\n if (hidden && (field.type === 'group' || field.type === 'array')) hiddenContainers.push(address);\n\n const ctrl = ctx.controlFor(entry);\n if (!ctrl) continue;\n\n if (hidden) {\n if (ctrl.enabled) ctrl.disable({ emitEvent: false });\n } else if (ctrl.disabled && !field.disabled) {\n ctrl.enable({ emitEvent: false });\n }\n }\n }\n\n /**\n * The hidden and shown names as sets, memoised against the result they came from.\n *\n * `isFieldVisible` runs once per field per change-detection pass; building two sets from\n * two arrays each time turns a rule result into allocation proportional to the form. A\n * `WeakMap` keyed by the result means it is built once per evaluation and collected with it.\n */\n private nameSets(result: RuleEvaluationResult): { hidden: Set<string>; shown: Set<string> } {\n let sets = this.nameSetCache.get(result);\n if (!sets) {\n sets = { hidden: new Set(result.hiddenFields), shown: new Set(result.shownFields) };\n this.nameSetCache.set(result, sets);\n }\n return sets;\n }\n\n private readonly nameSetCache = new WeakMap<\n RuleEvaluationResult,\n { hidden: Set<string>; shown: Set<string> }\n >();\n}\n","import { Injectable, Inject, Optional } from '@angular/core';\nimport type { EntityFormConfig } from '@dynamic-entity/core';\nimport { isObservable, firstValueFrom } from 'rxjs';\nimport { CONFIG_SOURCE, type ConfigSourceHandler } from '../tokens/injection-tokens';\n\n@Injectable({ providedIn: 'root' })\nexport class ConfigSourceService {\n private readonly cache = new Map<string, EntityFormConfig>();\n private readonly inFlight = new Map<string, Promise<EntityFormConfig | undefined>>();\n\n private readonly handler?: ConfigSourceHandler;\n\n constructor(@Optional() @Inject(CONFIG_SOURCE) handler?: any) {\n this.handler = handler;\n }\n\n /** Retrieve an entity config by key, with caching and in-flight deduplication. */\n async getConfig(entityKey: string): Promise<EntityFormConfig | undefined> {\n if (!entityKey || !this.handler) return undefined;\n if (this.cache.has(entityKey)) return this.cache.get(entityKey);\n if (this.inFlight.has(entityKey)) return this.inFlight.get(entityKey);\n\n const promise = (async () => {\n try {\n const raw = this.handler!(entityKey);\n let resolved: EntityFormConfig | undefined;\n\n if (isObservable(raw)) {\n resolved = await firstValueFrom(raw as any);\n } else {\n resolved = await Promise.resolve(raw as any);\n }\n\n if (resolved) {\n this.cache.set(entityKey, resolved);\n }\n return resolved;\n } catch (err) {\n console.warn(`ConfigSourceService failed to load config for entity \"${entityKey}\"`, err);\n return undefined;\n } finally {\n this.inFlight.delete(entityKey);\n }\n })();\n\n this.inFlight.set(entityKey, promise);\n return promise;\n }\n\n /** Clear cached configs (e.g. after a config edit in the builder). */\n clearCache(entityKey?: string): void {\n if (entityKey) {\n this.cache.delete(entityKey);\n } else {\n this.cache.clear();\n }\n }\n}\n","import { Injectable, inject, isDevMode } from '@angular/core';\nimport { AbstractControl, FormArray, FormBuilder, FormGroup } from '@angular/forms';\nimport type { EntityFormConfig, NestedFieldConfig, NestedTabConfig } from '@dynamic-entity/core';\nimport {\n getTabData,\n getTabPath,\n getValueByPath,\n normalizeArrayStructures,\n parseFieldRef,\n setTabData,\n setValueByPath,\n} from '@dynamic-entity/core';\nimport { ValidatorRegistryService } from '../services/validator-registry.service';\n\n/**\n * FormStructureService — config ⇄ `FormGroup`, and nothing else.\n *\n * The one question this answers is *where a value lives*: which control a field owns, how\n * the tab tree nests into groups, how a record is read out of the tree and patched back in.\n * It was half of `DynamicFormComponent`, mixed in with tab state, focus management, rule\n * evaluation and RBAC — and the cost of that was not length but ownership: the bug Phase 2\n * fixed was two methods forty lines apart disagreeing about what \"every field\" meant.\n *\n * Deliberately stateless. Every method takes the form and the config it is operating on, so\n * there is no cached `this.form` to go stale against a rebuilt one, and every method is\n * testable without a component or a TestBed.\n *\n * Provided at the component, not the root: `FormBuilder` and the validator registry are the\n * only things injected, but keeping the service per form leaves room for that to change\n * without turning into shared mutable state.\n */\n@Injectable()\nexport class FormStructureService {\n private readonly fb = inject(FormBuilder);\n private readonly validatorRegistry = inject(ValidatorRegistryService);\n\n /**\n * Build the control tree for a config.\n *\n * The tree mirrors the record's shape exactly: a tab opens a `FormGroup` under its id, a\n * `flatData` tab merges into its parent's, and a `group` field opens one for its children.\n * That correspondence is what lets a `[path]` ref resolve through `form.get()` and name\n * exactly one control — see `getControl`.\n */\n buildForm(config: EntityFormConfig): FormGroup {\n const group: Record<string, AbstractControl> = {};\n\n const buildTabControls = (tabs: NestedTabConfig[], parentGroup: Record<string, AbstractControl>) => {\n for (const tab of tabs) {\n if (tab.flatData) {\n for (const field of tab.fields || []) {\n this.buildFieldControl(field, parentGroup);\n }\n if (tab.children) buildTabControls(tab.children, parentGroup);\n } else {\n const tabGroup: Record<string, AbstractControl> = {};\n for (const field of tab.fields || []) {\n this.buildFieldControl(field, tabGroup);\n }\n if (tab.children) buildTabControls(tab.children, tabGroup);\n parentGroup[tab.id] = this.fb.group(tabGroup);\n }\n }\n };\n\n buildTabControls(config.tabs || [], group);\n return this.fb.group(group);\n }\n\n /** One field's control: a nested group, an empty array, or a leaf carrying its validators. */\n buildFieldControl(field: NestedFieldConfig, group: Record<string, AbstractControl>): void {\n if (field.type === 'group') {\n const subGroup: Record<string, AbstractControl> = {};\n for (const child of field.children || []) {\n this.buildFieldControl(child, subGroup);\n }\n group[field.id] = this.fb.group(subGroup);\n } else if (field.type === 'array') {\n group[field.id] = this.fb.array([]);\n } else {\n const validators = this.validatorRegistry.resolveFromConfig(field.validators);\n const asyncValidators = this.validatorRegistry.resolveAsyncFromConfig(field.validators);\n group[field.id] = this.fb.control(\n { value: field.defaultValue ?? null, disabled: field.disabled ?? false },\n validators,\n asyncValidators,\n );\n }\n }\n\n /** One row of an `array` field: a FormGroup when the field declares columns, else a bare control. */\n buildArrayRow(field: NestedFieldConfig | undefined, item: unknown): AbstractControl {\n if (!field?.children?.length) return this.fb.control(item);\n\n const rowGroup: Record<string, AbstractControl> = {};\n for (const child of field.children) {\n this.buildFieldControl(child, rowGroup);\n }\n const group = this.fb.group(rowGroup);\n if (item && typeof item === 'object') group.patchValue(item as Record<string, unknown>);\n return group;\n }\n\n /** The `FormGroup` a tab's fields live in, honouring `flatData`. */\n getTabGroup(form: FormGroup | null, config: EntityFormConfig | null | undefined, tabId: string): FormGroup | null {\n if (!form) return null;\n const path = getTabPath(config?.tabs, tabId);\n if (!path || path.length === 0) return form;\n\n let curr: AbstractControl | null = form;\n for (const p of path) {\n if (!curr || !(curr instanceof FormGroup)) return null;\n curr = curr.get(p);\n }\n return curr instanceof FormGroup ? curr : null;\n }\n\n /**\n * Find a control by reference: a bracketed path, or a bare field id.\n *\n * A bracketed path names exactly one control, because the tree nests exactly as the path\n * does — so `form.get('work.address.city')` walks straight to it. A bare id is what every\n * config written before paths existed uses: it is looked for on `currentTabId` first, then\n * at the root, then by a recursive search whose result is whichever the walk reaches first.\n * That last branch is the ambiguity refs exist to remove, and callers that can name a path\n * should.\n */\n getControl(\n form: FormGroup | null,\n config: EntityFormConfig | null | undefined,\n fieldId: string,\n currentTabId?: string,\n ): AbstractControl | null {\n if (!form) return null;\n\n const parsed = parseFieldRef(fieldId);\n if (parsed.kind === 'ref') return form.get(parsed.value);\n\n if (currentTabId) {\n const tabGrp = this.getTabGroup(form, config, currentTabId);\n const ctrl = tabGrp?.get(fieldId);\n if (ctrl) return ctrl;\n }\n\n const rootCtrl = form.get(fieldId);\n if (rootCtrl) return rootCtrl;\n\n const findInGroup = (group: FormGroup): AbstractControl | null => {\n for (const key of Object.keys(group.controls)) {\n const c = group.controls[key];\n if (key === fieldId) return c;\n if (c instanceof FormGroup) {\n const found = findInGroup(c);\n if (found) return found;\n }\n }\n return null;\n };\n\n return findInGroup(form);\n }\n\n /** Assemble the full nested record from per-tab groups, respecting flatData, refererField & arrays. */\n extractRecord(form: FormGroup | null, config: EntityFormConfig | null | undefined): Record<string, any> {\n if (!form || !config) return {};\n let record: Record<string, any> = {};\n\n const walkTabs = (tabs: NestedTabConfig[]) => {\n for (const tab of tabs) {\n const fieldValBag: Record<string, unknown> = {};\n for (const field of tab.fields || []) {\n const ctrl = this.getControl(form, config, field.id, tab.id);\n if (ctrl) fieldValBag[field.id] = ctrl.value;\n }\n\n setTabData(record, tab.id, fieldValBag, config);\n\n for (const field of tab.fields || []) {\n if (field.refererField) {\n const ctrl = this.getControl(form, config, field.id, tab.id);\n if (ctrl) setValueByPath(record, field.refererField, ctrl.value);\n }\n }\n\n if (tab.children) walkTabs(tab.children);\n }\n };\n\n walkTabs(config.tabs || []);\n record = normalizeArrayStructures(record, config);\n return record;\n }\n\n /**\n * Write a record into the control tree.\n *\n * Returns the top-level keys that named a known field and were *not* consumed, so the\n * caller can say so — see `DynamicFormComponent.warnUnconsumedInitialData`. Reporting\n * rather than logging keeps the \"warn once per form\" bookkeeping with the form, and keeps\n * this service free of console output.\n */\n patchForm(\n form: FormGroup | null,\n config: EntityFormConfig | null | undefined,\n data: Record<string, any>,\n fieldsById: Map<string, NestedFieldConfig>,\n ): string[] {\n if (!data || !form || !config) return [];\n const patchedFieldIds = new Set<string>();\n\n const walkTabs = (tabs: NestedTabConfig[]) => {\n for (const tab of tabs) {\n const tabData = getTabData(tab.id, data, config);\n for (const field of tab.fields || []) {\n let val = tabData && typeof tabData === 'object' ? tabData[field.id] : undefined;\n if (field.refererField) {\n const refVal = getValueByPath(data, field.refererField);\n if (refVal !== undefined) val = refVal;\n }\n if (val === undefined) continue;\n\n const ctrl = this.getControl(form, config, field.id, tab.id);\n if (!ctrl) continue;\n\n if (ctrl instanceof FormArray && Array.isArray(val)) {\n ctrl.clear();\n for (const item of val) {\n ctrl.push(this.buildArrayRow(fieldsById.get(field.id), item));\n }\n } else {\n ctrl.patchValue(val, { emitEvent: false });\n }\n patchedFieldIds.add(field.id);\n }\n if (tab.children) walkTabs(tab.children);\n }\n };\n\n walkTabs(config.tabs || []);\n return this.unconsumedKeys(config, data, fieldsById, patchedFieldIds);\n }\n\n /**\n * Top-level keys that name a field but reached no control.\n *\n * A record is nested by tab id (`{ tabId: { fieldId: value } }`) unless the tab sets\n * `flatData: true`. Handing a flat record to a nested tab finds nothing, so the fields stay\n * empty — with no error and no clue.\n *\n * Only keys matching a known field id count: anything else is the consumer's own record\n * metadata (ids, timestamps, `_configVersion`) and is not our business.\n */\n private unconsumedKeys(\n config: EntityFormConfig,\n data: Record<string, any>,\n fieldsById: Map<string, NestedFieldConfig>,\n patchedFieldIds: Set<string>,\n ): string[] {\n if (!isDevMode()) return [];\n\n const tabIds = new Set<string>();\n const collectTabIds = (tabs: NestedTabConfig[]) => {\n for (const tab of tabs) {\n tabIds.add(tab.id);\n if (tab.children) collectTabIds(tab.children);\n }\n };\n collectTabIds(config.tabs || []);\n\n return Object.keys(data).filter(\n key =>\n // A tab id at the root is the nested container, not a stray field.\n !tabIds.has(key) &&\n data[key] !== undefined &&\n fieldsById.has(key) &&\n !patchedFieldIds.has(key),\n );\n }\n}\n","import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n Injector,\n Input,\n Output,\n EventEmitter,\n OnChanges,\n OnDestroy,\n OnInit,\n SimpleChange,\n SimpleChanges,\n afterNextRender,\n signal,\n computed,\n inject,\n isDevMode,\n ElementRef,\n ViewChild,\n ViewChildren,\n QueryList,\n HostListener,\n} from '@angular/core';\nimport { NgComponentOutlet } from '@angular/common';\nimport { AbstractControl, FormArray, FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport { Subscription } from 'rxjs';\nimport { debounceTime } from 'rxjs/operators';\nimport type { AutoPatchConfig, EntityFormConfig, FormRule, NestedFieldConfig, NestedTabConfig } from '@dynamic-entity/core';\nimport type { FieldScopeEntry } from '@dynamic-entity/core';\nimport {\n ambiguousFieldIds,\n collectFieldScopes,\n fieldRefFor,\n parseFieldRef,\n refOf,\n toRefToken,\n valuesEqual,\n applyAutoPatch,\n applyPatchOnTrue,\n fieldsUnderTab,\n migrateRecord,\n findTab,\n normalizeConfigOptions,\n resolveLabel,\n} from '@dynamic-entity/core';\nimport { DynamicFieldComponent } from './dynamic-field/dynamic-field.component';\nimport { FormStructureService } from './form-structure.service';\nimport { COMMON_MODULES_REGISTRY, RECORD_MIGRATIONS } from '../tokens/injection-tokens';\nimport { ValidatorRegistryService } from '../services/validator-registry.service';\nimport { HookRegistryService } from '../services/hook-registry.service';\nimport { RbacService } from '../services/rbac.service';\nimport { RulesEvaluationService } from '../services/rules-evaluation.service';\nimport { EntityRefSelectionService } from '../services/entity-ref-selection.service';\nimport { UiTextService } from '../services/ui-text.service';\nimport { ValidationMessagesService } from '../services/validation-messages.service';\n\n/**\n * Grid width per field type, used only under `layout=\"auto\"` and only where the field itself\n * names no `colSpan`.\n *\n * The rule behind the numbers is how much *content* the control holds, not how much room it\n * would happily fill: a date is eight characters and a currency amount is rarely more, so\n * giving either a full row buys nothing but scrolling. Anything that holds a paragraph, a\n * picture, or a form of its own keeps all twelve.\n *\n * A type missing from this table falls back to twelve, which is what an unrecognised custom\n * field type should get: the layout is conservative about controls it knows nothing about.\n */\nconst AUTO_COL_SPAN: Readonly<Record<string, number>> = {\n text: 6,\n email: 6,\n password: 6,\n number: 4,\n currency: 4,\n date: 4,\n datetime: 4,\n time: 4,\n monthYear: 4,\n dropdown: 6,\n radio: 6,\n multiSelect: 6,\n boolean: 4,\n checkbox: 4,\n 'entity-ref': 6,\n // Left at the full width deliberately — textarea, markdown, image, file, group and array\n // each hold something a half-row would crop.\n};\n\n/** A field the form will not save, with what is wrong and where to find it. */\nexport interface InvalidField {\n field: NestedFieldConfig;\n /** The same message the field renders under itself. */\n message: string;\n tabId: string;\n subTabId?: string;\n}\n\n/**\n * DynamicFormComponent — the main form component.\n * Renders a reactive form from EntityFormConfig with tab support, responsive 12-col grid,\n * rules evaluation, conditional visibility, autoPatch/patchOnTrue, criticalField locking,\n * keyboard shortcuts (Ctrl+S, Esc), and RBAC-gated submission.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-dynamic-form',\n standalone: true,\n imports: [ReactiveFormsModule, DynamicFieldComponent, NgComponentOutlet],\n // Scoped per form instance: entity-ref selections must not leak between concurrent forms,\n // and the structure service is deliberately per form rather than shared.\n providers: [EntityRefSelectionService, FormStructureService],\n templateUrl: './dynamic-form.component.html',\n /*\n * The grid is structural, so it lives here rather than in the optional stylesheet.\n *\n * `getFieldSpan` writes `grid-column` inline on every slot, and a consumer who never\n * imports `ngx-dynamic-entity/styles.css` still has to get a laid-out form rather than a\n * column of unpositioned divs. That makes this the authoritative copy, and the reason the\n * stylesheet deliberately does not restate it: a component stylesheet is injected after a\n * global one and carries an attribute selector, so a duplicate there would lose every tie\n * and sit in the file looking authoritative while doing nothing.\n *\n * Every value that a design might want to move is read from the same tokens the stylesheet\n * sets, with a fallback for the consumer who imports nothing.\n */\n styles: [\n `\n .ngx-form__panel {\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n gap: var(--ngx-gap, 18px);\n align-items: start;\n }\n .ngx-form__field-slot {\n display: flex;\n align-items: flex-start;\n gap: 6px;\n min-width: 0;\n }\n .ngx-form__field-slot ngx-dynamic-field {\n flex: 1;\n min-width: 0;\n }\n .ngx-form__lock {\n flex: 0 0 auto;\n margin-top: 22px;\n background: none;\n border: 1px solid transparent;\n border-radius: var(--ngx-radius-sm, 6px);\n cursor: pointer;\n font-size: 14px;\n line-height: 1;\n padding: 4px 6px;\n }\n .ngx-form__lock:hover {\n border-color: var(--ngx-color-border, #d1d5db);\n background: var(--ngx-color-surface-alt, #f9fafb);\n }\n /* Matches the stylesheet's own breakpoint — a 12-column grid is unreadable below it. */\n @media (max-width: 640px) {\n .ngx-form__panel {\n grid-template-columns: minmax(0, 1fr);\n }\n .ngx-form__field-slot {\n grid-column: 1 / -1 !important;\n }\n }\n `,\n ],\n})\nexport class DynamicFormComponent implements OnInit, OnChanges, OnDestroy {\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n // ─── Inputs ───────────────────────────────────────────────────────────────\n /**\n * The schema to render.\n *\n * An accessor pair rather than a plain field: `ngOnChanges` normalises the option shape,\n * and that result is kept here instead of being written back over the input. Reassigning\n * an `@Input` works, but it mutates what the parent handed us — and a parent using OnPush\n * or signals would never observe the replacement anyway.\n *\n * Reads of `this.config` get the normalised copy once it exists, so every internal caller\n * is unaffected.\n */\n @Input()\n set config(value: EntityFormConfig) {\n this.rawConfig = value;\n this.normalizedConfig = undefined; // re-normalised in ngOnChanges\n }\n get config(): EntityFormConfig {\n return this.normalizedConfig ?? this.rawConfig;\n }\n private rawConfig!: EntityFormConfig;\n private normalizedConfig?: EntityFormConfig;\n @Input() rules?: FormRule[];\n @Input() initialData?: Record<string, any>;\n /** Session-original values for `VALUE_CHANGED` rules. Captured from the first build when omitted. */\n @Input() originalData?: Record<string, any>;\n @Input() userRoles: string[] = [];\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n /** Field ids forced read-only while the rest of the form stays editable. */\n @Input() readOnlyFields: string[] = [];\n /**\n * Render rule `info` banners inline. The record editor sets this false and renders its\n * own dismissible versions, so the two do not double up.\n */\n @Input() showInfoBanners: boolean = true;\n @Input() loading: boolean = false;\n @Input() error: string | null = null;\n /**\n * Milliseconds to debounce `formChange`. The reference debounces at 300ms so a consumer\n * re-rendering on every value change is not driven per keystroke. Zero emits\n * synchronously, which the record editor relies on for its own bookkeeping.\n */\n @Input() changeDebounceMs: number = 0;\n /**\n * Preview mode: seed one empty row per `array` field so the structure is visible, then\n * disable the form. Used by the builder's live preview.\n */\n @Input() preview: boolean = false;\n /**\n * How a field with no `colSpan` of its own is sized in the 12-column grid.\n *\n * `stack` — the historic behaviour — gives every such field the full twelve, so a form of\n * eight short text fields renders as an eight-row ladder with two thirds of its width\n * empty. `auto` sizes them by field type instead: a date or a number is half a row, a\n * textarea or a nested group still takes all twelve.\n *\n * An explicit `colSpan` always wins in both modes, so turning `auto` on cannot override a\n * layout somebody authored. The default stays `stack` because changing how existing configs\n * render is not this input's business — opting in is.\n */\n @Input() layout: 'stack' | 'auto' = 'stack';\n\n // ─── Outputs ──────────────────────────────────────────────────────────────\n @Output() formSubmit = new EventEmitter<Record<string, any>>();\n @Output() formChange = new EventEmitter<Record<string, any>>();\n @Output() formReset = new EventEmitter<void>();\n /** The visible tab changed. Lets a host track it without reaching into this component. */\n @Output() activeTabChange = new EventEmitter<string>();\n /**\n * Emitted when a `beforeSave` hook aborted the save — by returning false or throwing.\n * `formSubmit` does not fire in that case.\n */\n @Output() saveRejected = new EventEmitter<{ reason: string; error?: unknown }>();\n\n // ─── Services ─────────────────────────────────────────────────────────────\n private readonly cdr = inject(ChangeDetectorRef);\n private readonly fb = inject(FormBuilder);\n private readonly validatorRegistry = inject(ValidatorRegistryService);\n private readonly hookRegistry = inject(HookRegistryService);\n private readonly rbacService = inject(RbacService);\n private readonly rulesEvaluation = inject(RulesEvaluationService);\n /** config ⇄ FormGroup: where a value lives. See `FormStructureService`. */\n private readonly structure = inject(FormStructureService);\n /** Resolves what is wrong with a field, for the error summary — see `resolveForField`. */\n private readonly messages = inject(ValidationMessagesService);\n private readonly entityRefSelection = inject(EntityRefSelectionService);\n private readonly commonModulesRegistry = inject(COMMON_MODULES_REGISTRY, { optional: true });\n private readonly migrations = inject(RECORD_MIGRATIONS, { optional: true }) ?? [];\n /** Scopes the field-slot lookup a jump does, so the library never touches global `document`. */\n private readonly host = inject(ElementRef) as ElementRef<HTMLElement>;\n /** Ties `afterNextRender` to this component, so destroying it cancels a pending jump. */\n private readonly injector = inject(Injector);\n\n protected readonly Object = Object;\n\n // ─── Signals (local reactive state) ───────────────────────────────────────\n readonly activeTab = signal<string>('');\n readonly activeSubTab = signal<string>('');\n readonly isSaving = signal(false);\n readonly formValues = signal<Record<string, any>>({});\n /** Baseline captured at first build, used when `originalData` is not supplied. */\n readonly sessionBaseline = signal<Record<string, any>>({});\n /** Critical fields the user has explicitly unlocked for editing. */\n readonly unlockedFields = signal<ReadonlySet<string>>(new Set<string>());\n\n /** The active tab's field panel, focused after a tab switch. */\n @ViewChild('formPanel') private formPanel?: ElementRef<HTMLElement>;\n\n /** The hosted field components, so an external control-state change can reach them. */\n @ViewChildren(DynamicFieldComponent) private fieldHosts?: QueryList<DynamicFieldComponent>;\n\n // ─── Form ─────────────────────────────────────────────────────────────────\n form!: FormGroup;\n\n private valueSub?: Subscription;\n private statusSub?: Subscription;\n private selectionSub?: Subscription;\n /** Previous values, for detecting `patchOnTrue` false→true transitions. */\n private previousValues: Record<string, any> = {};\n\n // ─── Keyboard Shortcuts ───────────────────────────────────────────────────\n @HostListener('window:keydown', ['$event'])\n handleKeyboardEvent(event: KeyboardEvent): void {\n if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') {\n event.preventDefault();\n // No `form.valid` check: the shortcut is the Save button, and pressing Save on an\n // invalid form is what produces the error summary. Guarding here instead meant Ctrl+S\n // on an incomplete form did nothing at all — and unlike the button, a shortcut cannot\n // even look disabled.\n // `void`, not an `await`: a `@HostListener` cannot be async without changing what\n // Angular does with its return value, and `submit()` reports its own failures through\n // `saveRejected`. Nothing here would have anywhere to put a rejection.\n if (!this.readonly && this.canSubmit) void this.submit();\n }\n }\n\n // ─── Computed ─────────────────────────────────────────────────────────────\n readonly ruleResult = computed(() =>\n this.rulesEvaluation.evaluate(this.rules, this.formValues(), this.baseline(), {\n // The engine reports rather than logs, because it also runs on a server. This is the\n // client's answer: say it once per distinct problem, in dev only. A rule the author\n // half-finished used to throw out of change detection; now it is skipped, and a\n // silently skipped rule is exactly as hard to diagnose as a thrown one.\n onProblem: message => this.warnOnce(message),\n }),\n );\n\n /** Warned-about rule problems, per component instance — see `warnedAmbiguousIds`. */\n private readonly warnedProblems = new Set<string>();\n\n private warnOnce(message: string): void {\n if (!isDevMode() || this.warnedProblems.has(message)) return;\n this.warnedProblems.add(message);\n console.warn(`[ngx-dynamic-entity] ${message}`);\n }\n\n /**\n * Critical fields whose value differs from the session baseline.\n * These drive the deferred `VALUE_CHANGED` banner — a critical edit is announced once,\n * against the value the record had when the session started, not per keystroke.\n */\n readonly changedCriticalFields = computed<NestedFieldConfig[]>(() => {\n const baseline = this.baseline();\n if (!baseline || Object.keys(baseline).length === 0) return [];\n const values = this.formValues();\n return this.allFields().filter(f => f.criticalField && !this.sameValue(values[f.id], baseline[f.id]));\n });\n\n get tabs(): NestedTabConfig[] {\n return this.config?.tabs || [];\n }\n\n get visibleTabs(): NestedTabConfig[] {\n return this.tabs.filter(tab => this.isTabVisible(tab));\n }\n\n private isTabVisible(tab: NestedTabConfig): boolean {\n return this.rulesEvaluation.isTabVisible(this.ruleResult(), tab);\n }\n\n get activeTabConfig(): NestedTabConfig | null {\n const tabId = this.activeTab();\n if (!tabId) return this.visibleTabs[0] ?? null;\n return findTab(this.tabs, tabId);\n }\n\n get visibleSubTabs(): NestedTabConfig[] {\n const active = this.activeTabConfig;\n if (!active?.children || active.children.length === 0) return [];\n return active.children.filter(tab => this.isTabVisible(tab));\n }\n\n get activeSubTabConfig(): NestedTabConfig | null {\n const subTabs = this.visibleSubTabs;\n if (!subTabs.length) return null;\n const subId = this.activeSubTab();\n return subTabs.find(s => s.id === subId) ?? subTabs[0];\n }\n\n /**\n * The component to mount for the active tab, or `null` if there is nothing to mount.\n *\n * A registry entry may name its component with a **selector string** — `COMMON_MODULES`\n * is a catalogue of names for the builder's picker, and the token's own example showed\n * one. `ngComponentOutlet` mounts a component *type*, so a string reached it and Angular\n * threw an assertion the moment somebody opened that tab. Following the documented shape\n * broke the feature, which is worse than the feature not existing.\n *\n * A string now resolves to nothing renderable and says why, once per module.\n */\n get activeTabModuleComponent(): any | null {\n const active = this.activeSubTabConfig ?? this.activeTabConfig;\n if (!active?.moduleName || !this.commonModulesRegistry) return null;\n const entry = this.commonModulesRegistry.find(m => m.id === active.moduleName || m.component === active.moduleName);\n if (!entry) return null;\n if (typeof entry.component === 'string') {\n this.warnSelectorModule(entry.id, entry.component);\n return null;\n }\n return entry.component;\n }\n\n /** Warned once per module id, because a getter runs on every change-detection pass. */\n private readonly warnedSelectorModules = new Set<string>();\n\n private warnSelectorModule(id: string, selector: string): void {\n if (this.warnedSelectorModules.has(id)) return;\n this.warnedSelectorModules.add(id);\n console.warn(\n `[ngx-dynamic-entity] The common module '${id}' is registered with the selector ` +\n `'${selector}' rather than a component class, so there is nothing to mount for its ` +\n `tab. Register the component itself: ` +\n `{ id: '${id}', label: {...}, component: MyComponent }.`,\n );\n }\n\n get fieldsForActiveTab(): NestedFieldConfig[] {\n const active = this.activeSubTabConfig ?? this.activeTabConfig;\n if (active?.moduleName) return [];\n const rawFields = active ? active.fields || [] : (this.config?.tabs || []).flatMap(t => t.fields || []);\n const currentValues = this.formValues();\n\n return rawFields.filter(field => this.isFieldVisible(field, currentValues));\n }\n\n /**\n * Whether a field renders. Precedence lives in `RulesEvaluationService`, which is also\n * what `syncHiddenFieldState` asks — so what is on screen and what counts toward validity\n * cannot drift apart.\n */\n private isFieldVisible(field: NestedFieldConfig, values: Record<string, unknown>): boolean {\n return this.rulesEvaluation.isFieldVisible(this.ruleResult(), field, this.namesOf(field), values);\n }\n\n /**\n * Entity-level permissions for the current roles.\n *\n * Cached rather than recomputed: this is read from the template several times per change\n * detection pass, and a fresh object each time is both wasted allocation and a new\n * identity for anything comparing by reference. Invalidated in `ngOnChanges` when\n * `config` or `userRoles` change, which are its only inputs.\n */\n get permissions(): ReturnType<RbacService['getPermissions']> {\n return (this.permissionsCache ??= this.rbacService.getPermissions(this.config, this.userRoles));\n }\n\n private permissionsCache: ReturnType<RbacService['getPermissions']> | null = null;\n\n /**\n * Whether the current roles may see this record at all.\n *\n * `permissions.view` used to be computed and thrown away — a user whose roles failed it\n * still received the complete form with every value in the DOM. It is honoured now.\n *\n * As with masking, this is presentational: it stops the browser rendering data, it does\n * not stop the data reaching the browser. Authorize on the server.\n */\n get canView(): boolean {\n return this.permissions.canView;\n }\n\n /**\n * Whether the current roles may delete this record.\n *\n * The library ships no delete affordance, so this is surfaced for the consumer to gate\n * their own — exposed rather than dropped, because a permission the schema declares\n * should be answerable.\n */\n get canDelete(): boolean {\n return this.permissions.canDelete;\n }\n\n get canSubmit(): boolean {\n return this.canView && this.permissions.canEdit && !this.readonly;\n }\n\n /**\n * Errors raised by `validation` rules, keyed by the target they point at.\n *\n * A rule can declare the record invalid independently of Angular's validators, so form\n * validity alone is not the whole picture. `DynamicRecordFormComponent.saveSection()`\n * has always honoured these; `submit()` did not, which meant the same rule blocked one\n * save path and merely painted a banner on the other — and anything wiring\n * `(formSubmit)` to persistence wrote records the rules engine had already rejected.\n */\n get ruleValidationErrors(): Record<string, string> {\n return this.ruleResult().validationErrors;\n }\n\n /** True when a `validation` rule is currently blocking submission. */\n get hasRuleErrors(): boolean {\n return Object.keys(this.ruleValidationErrors).length > 0;\n }\n\n /**\n * True while an async validator is still running.\n *\n * Angular reports a control with an outstanding async check as `pending`, and `invalid` is\n * false until it settles — so without this a form could be submitted in the gap before a\n * uniqueness check came back.\n */\n get isValidating(): boolean {\n return this.form.pending;\n }\n\n /**\n * Whether a submit would be refused. The guard `submit()` checks — not the button's state.\n *\n * See `submitDisabled` for why those are no longer the same question.\n */\n get submitBlocked(): boolean {\n return this.form.invalid || this.form.pending || this.hasRuleErrors;\n }\n\n /**\n * Whether the Save button is unavailable.\n *\n * This used to be `submitBlocked`, so an invalid form greyed Save out — and a greyed button\n * is the worst possible answer to \"why can't I save?\". It cannot be clicked, so there is no\n * moment at which the form gets to say which field is at fault or which tab it is on; the\n * user is left comparing a disabled button against a form that looks, to them, filled in.\n * On a tabbed form the offending field is usually not even on screen.\n *\n * Save now stays available while the form is merely invalid. Clicking it still saves\n * nothing — `submit()` checks `submitBlocked` and refuses — but the refusal is where the\n * error summary, the tab badges and the jump to the first bad field come from, so pressing\n * Save produces an explanation instead of silence.\n *\n * What is still disabled is what a *retry cannot fix*: a save already in flight, and an\n * async validator whose answer has not come back. Those are moments where the right answer\n * is genuinely \"wait\", and a button that accepts a click would be lying.\n */\n get submitDisabled(): boolean {\n return this.isSaving() || this.loading || this.form.pending;\n }\n\n ngOnInit(): void {\n this.selectionSub = this.entityRefSelection.selection$.subscribe(({ fieldId, option }) => {\n this.runAutoPatch(fieldId, option?.record);\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['config'] || changes['userRoles']) {\n this.permissionsCache = null;\n }\n if (changes['config'] && this.rawConfig) {\n // Configs arrive as plain JSON from storage or an API, where TypeScript cannot enforce\n // the option shape. Normalise here, at the library boundary, so everything downstream\n // can rely on an option being a LocalizedText. Returns the same object when it already\n // is, so a well-formed config costs nothing.\n // Kept in a field of our own rather than written back to the @Input. Reassigning an\n // input works, but it surprises a parent that holds the same object — and a parent\n // using OnPush or signals would not see the replacement anyway.\n this.normalizedConfig = normalizeConfigOptions(this.config);\n }\n if (changes['config'] || changes['initialData']) {\n this.buildForm();\n\n // Clear *before* the guard below, not after it.\n //\n // The reset used to sit behind `if (visibleTabs.length === 0) return`, so a swap that\n // arrived while no tab was visible — a config still being applied, or every tab hidden\n // by a rule at that instant — skipped it entirely and the previous record's tab\n // survived into the next one. Clearing is unconditional and cheap, and safe on its own\n // because `activeTabConfig` already falls back to the first visible tab when nothing\n // is selected. Selecting the tab is what needs tabs to exist; forgetting the old one\n // does not.\n if (changes['config'] || this.isRecordSwap(changes['initialData'])) {\n this.activeTab.set('');\n this.activeSubTab.set('');\n }\n\n if (this.visibleTabs.length === 0) return;\n\n // The first tab used to be chosen only when no tab was active yet, and nothing ever\n // cleared `activeTab` — so a form that stays mounted while `initialData` is swapped\n // opened the next record on the tab the previous one was left on. The demo escaped it\n // by destroying the form between records; a host that keeps it mounted did not.\n //\n // Resetting here is consistent with what already happens: `buildForm` assigns a brand\n // new FormGroup, so a changed `initialData` has already discarded every control and\n // all validation state. The tab was the one thing pretending nothing had changed.\n if (!this.activeTab()) {\n // No focus steal: the panel gains focus when a *user* picks a tab, not when a host\n // swaps the record underneath them.\n this.setActiveTab(this.visibleTabs[0].id, { focusPanel: false });\n }\n }\n }\n\n /**\n * Whether an `initialData` change represents loading a different record.\n *\n * Not every change does. A template binding like `[initialData]=\"record() || {}\"` yields a\n * fresh object literal on each evaluation, so `ngOnChanges` fires with two empty objects\n * and nothing has actually been loaded — resetting there would drag someone back to the\n * first tab while they were filling in a new record on the third.\n */\n private isRecordSwap(change: SimpleChange | undefined): boolean {\n if (!change || change.isFirstChange()) return false;\n const empty = (v: unknown): boolean =>\n v === null || v === undefined || (typeof v === 'object' && Object.keys(v as object).length === 0);\n return !(empty(change.previousValue) && empty(change.currentValue));\n }\n\n ngOnDestroy(): void {\n this.valueSub?.unsubscribe();\n this.statusSub?.unsubscribe();\n this.selectionSub?.unsubscribe();\n }\n\n /**\n * `focusPanel: false` is for a caller that is about to focus something more specific.\n *\n * Activating a tab moves focus into its panel, which is right for a keyboard user pressing\n * a tab. A quick-jump also switches tabs, but then focuses the field it was aiming at — and\n * the panel focus runs on `requestAnimationFrame`, after `afterNextRender`, so it landed\n * second and took the focus back every time. Saying so is better than out-timing it.\n */\n setActiveTab(tabId: string, options?: { focusPanel?: boolean }): void {\n const changed = this.activeTab() !== tabId;\n if (changed) this.activeTabChange.emit(tabId);\n this.activeTab.set(tabId);\n if (changed && options?.focusPanel !== false) this.focusActivePanel();\n const parent = findTab(this.tabs, tabId);\n if (parent?.children?.length) {\n this.activeSubTab.set(parent.children[0].id);\n } else {\n this.activeSubTab.set('');\n }\n }\n\n setActiveSubTab(subTabId: string, options?: { focusPanel?: boolean }): void {\n const changed = this.activeSubTab() !== subTabId;\n this.activeSubTab.set(subTabId);\n if (changed && options?.focusPanel !== false) this.focusActivePanel();\n }\n\n getFieldSpan(field: NestedFieldConfig): string {\n const span = field.colSpan ?? (this.layout === 'auto' ? (AUTO_COL_SPAN[field.type] ?? 12) : 12);\n return `span ${Math.min(12, Math.max(1, span))}`;\n }\n\n // ─── Validation recovery ──────────────────────────────────────────────────\n\n /**\n * Set by a submit that validation refused, cleared by one that went through.\n *\n * Gates the error summary rather than `form.invalid` doing it: a form opened on an empty\n * required field is invalid from the first render, and leading with a block of red before\n * the user has typed anything is an accusation, not help. The summary is the answer to\n * \"why did Save do nothing\", so it appears when Save does nothing.\n */\n readonly submitAttempted = signal(false);\n\n /**\n * Every rendered field whose control is currently invalid, with the tab it lives on.\n *\n * Read by the tab badges, the error summary and the jump, so all three agree on what\n * counts. Hidden fields are excluded because `syncHiddenFieldState` disables them and a\n * disabled control is not part of validity — pointing the user at one would send them to a\n * field that is not on screen, or worse, switch tabs to show them nothing.\n *\n * Cached per change-detection pass. The walk calls `getControl` once per field and that\n * falls back to a recursive search of the whole form; the template reads this three times\n * for the summary and once per tab for the badges, so recomputing it each time turns one\n * traversal into a dozen on every keystroke. `form.statusChanges` is the only thing that\n * can alter the answer, and it already runs `markForCheck` — dropping the cache there keeps\n * it honest without a second subscription.\n */\n invalidFields(): InvalidField[] {\n if (this.invalidFieldsCache) return this.invalidFieldsCache;\n\n const out: InvalidField[] = [];\n\n /*\n * Descends into `group` children rather than stopping at the container.\n *\n * A `FormGroup` is invalid whenever any descendant is, so reporting the container said\n * \"Contacts is invalid\" and left the user to open it and hunt. The offending leaf is\n * both the useful answer and the one `jumpToField` can actually move focus to.\n *\n * An `array` is reported as itself: its rows are built and destroyed at runtime, so\n * there is no configured child to name and nothing stable to jump to.\n */\n const collectField = (field: NestedFieldConfig, tab: NestedTabConfig, parentId?: string) => {\n const control = this.getControl(field.id, tab.id);\n if (!control || control.disabled || control.valid || control.pending) return;\n\n if (field.type === 'group' && field.children?.length) {\n for (const child of field.children) collectField(child, tab, parentId);\n return;\n }\n\n // The same message the field renders under itself — see `resolveForField`. Saying\n // only *which* field is wrong leaves the user to go and look at each one; saying what\n // is wrong with it is usually enough to fix it without leaving the summary.\n const message = this.messages.resolveForField(control.errors, this.language, field.type);\n out.push(\n parentId\n ? { field, message, tabId: parentId, subTabId: tab.id }\n : { field, message, tabId: tab.id },\n );\n };\n\n const collect = (tab: NestedTabConfig, parentId?: string) => {\n for (const field of tab.fields ?? []) collectField(field, tab, parentId);\n for (const child of tab.children ?? []) collect(child, parentId ?? tab.id);\n };\n for (const tab of this.visibleTabs) collect(tab);\n\n return (this.invalidFieldsCache = out);\n }\n\n private invalidFieldsCache?: InvalidField[];\n\n /** How many invalid fields sit on a tab — its own and its sub-tabs'. */\n tabErrorCount(tab: NestedTabConfig): number {\n if (!this.submitAttempted()) return 0;\n return this.invalidFields().filter(entry => entry.tabId === tab.id).length;\n }\n\n /** The same count for a sub-tab, which is addressed by its own id rather than its parent's. */\n subTabErrorCount(subTab: NestedTabConfig): number {\n if (!this.submitAttempted()) return 0;\n return this.invalidFields().filter(entry => entry.subTabId === subTab.id).length;\n }\n\n /**\n * Switch to the tab holding `fieldId`, scroll it into view, and move focus onto it.\n *\n * `afterNextRender` rather than a timer: the panel the field lives in is rendered by the\n * change detection this call is part of, so the element does not exist yet — and a timeout\n * is both a guess at how long that takes and something that keeps running after the\n * component is destroyed. The query is scoped to this component's own element, so the\n * library never reaches for the global `document`.\n */\n jumpToField(fieldId: string): void {\n const location = this.invalidFields().find(entry => entry.field.id === fieldId) ?? this.locateField(fieldId);\n if (!location) return;\n\n // The panel must not take focus back — this jump is going to focus the field itself.\n this.setActiveTab(location.tabId, { focusPanel: false });\n // `setActiveTab` resets to a tab's first child, so the sub-tab is selected after it.\n if (location.subTabId) this.setActiveSubTab(location.subTabId, { focusPanel: false });\n\n afterNextRender(\n () => {\n // The id comes from config, so it never goes into a selector string: no escaping to\n // get wrong, and no need for `CSS.escape`, which jsdom does not provide.\n const wanted = `field-container-${fieldId}`;\n const el = Array.from(this.host.nativeElement.querySelectorAll<HTMLElement>('[id^=\"field-container-\"]')).find(\n slot => slot.id === wanted,\n );\n if (!el) return;\n el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n // The slot carries tabindex=\"-1\", so this actually moves focus rather than only\n // scrolling and leaving focus behind on the link that was clicked.\n el.focus();\n },\n { injector: this.injector },\n );\n }\n\n /**\n * Which tab (and sub-tab) holds a field.\n *\n * Descends into `group`/`array` children: this compared top-level fields only, so \"jump to\n * the first invalid field\" found nothing for a nested one and silently did nothing. Only\n * sub-tabs one level deep are named, because that is what the tab strip can select —\n * anything deeper resolves to the ancestor it renders under.\n */\n private locateField(fieldId: string): { tabId: string; subTabId?: string } | null {\n const holds = (fields: NestedFieldConfig[] | undefined): boolean =>\n (fields ?? []).some(f => f?.id === fieldId || holds(f?.children));\n\n const search = (tabs: NestedTabConfig[] | undefined, tabId?: string, subTabId?: string):\n | { tabId: string; subTabId?: string }\n | null => {\n for (const tab of tabs ?? []) {\n if (!tab?.id) continue;\n const at = tabId ?? tab.id;\n const sub = tabId ? (subTabId ?? tab.id) : undefined;\n if (holds(tab.fields)) return sub ? { tabId: at, subTabId: sub } : { tabId: at };\n const found = search(tab.children, at, sub);\n if (found) return found;\n }\n return null;\n };\n\n return search(this.tabs);\n }\n\n // ─── criticalField locking ────────────────────────────────────────────────\n\n /** A critical field stays read-only until the user deliberately unlocks it. */\n isFieldLocked(field: NestedFieldConfig): boolean {\n return !!field.criticalField && !this.unlockedFields().has(field.id);\n }\n\n /**\n * Whether this field renders read-only, from any of the four reasons: the whole form,\n * the field's own flag, a caller-supplied `readOnlyFields` entry, or a criticalField lock.\n */\n isFieldReadonly(field: NestedFieldConfig): boolean {\n return (\n this.readonly ||\n // `permissions.edit` gated the Save button and nothing else, so a role without edit\n // rights received a fully editable form: it could type into every field, and only\n // discovered the record was not theirs to change when no Save button appeared. The\n // permission means the record may not be edited, so the fields say so.\n !this.permissions.canEdit ||\n !!field.readonly ||\n this.readOnlyFields.includes(field.id) ||\n this.isFieldLocked(field)\n );\n }\n\n toggleFieldLock(field: NestedFieldConfig): void {\n // Unlocking is an edit. Without the permission check a viewer could open the lock on a\n // critical field, which is the one control that exists to make editing deliberate.\n if (!field.criticalField || this.readonly || !this.permissions.canEdit) return;\n const next = new Set(this.unlockedFields());\n if (next.has(field.id)) next.delete(field.id);\n else next.add(field.id);\n this.unlockedFields.set(next);\n }\n\n /**\n * A field's label in the form's language, falling back to its id.\n *\n * The fallback matters wherever the label stands alone rather than beside its control: an\n * error-summary chip or a critical-change banner naming a field with no label for this\n * language would otherwise be blank, and a blank chip is worse than a raw id.\n */\n resolveFieldLabel(field: NestedFieldConfig): string {\n return resolveLabel(field.label, this.language) || field.id;\n }\n\n /**\n * The changed critical fields as one comma-separated string.\n *\n * Joined here rather than looped in the template because the banner is a sentence with the\n * list inside it, and a sentence has to reach `UI_TEXT` whole — a translation moves the\n * list somewhere else in the clause.\n */\n changedCriticalFieldLabels(): string {\n return this.changedCriticalFields()\n .map(field => this.resolveFieldLabel(field))\n .join(', ');\n }\n\n // ─── Form construction ────────────────────────────────────────────────────\n\n private buildForm(): void {\n if (!this.config) return;\n this.form = this.structure.buildForm(this.config);\n // A rebuild replaces every control, and the scope index is keyed by config identity.\n this.scopeCache = undefined;\n this.warnAmbiguousRuleReferences();\n\n if (this.initialData) {\n this.patchForm(this.upgradeRecord(this.initialData));\n }\n\n const initialFlattened = this.flattenFormValues();\n this.formValues.set(initialFlattened);\n this.previousValues = { ...initialFlattened };\n this.sessionBaseline.set({ ...initialFlattened });\n this.unlockedFields.set(new Set<string>());\n this.syncHiddenFieldState(initialFlattened);\n\n if (this.preview) {\n // Show what an array field looks like rather than an empty slot, then freeze.\n for (const field of this.allFields()) {\n if (field.type !== 'array') continue;\n const array = this.getArrayControl(field.id);\n if (array && array.length === 0) array.push(this.buildArrayRow(field, undefined));\n }\n this.form.disable({ emitEvent: false });\n }\n\n // Rebuilding must not stack subscriptions on successive config/data changes.\n this.valueSub?.unsubscribe();\n const changes$ =\n this.changeDebounceMs > 0 ? this.form.valueChanges.pipe(debounceTime(this.changeDebounceMs)) : this.form.valueChanges;\n // Validity is not value: an async validator settling flips `pending` and then `invalid`\n // with no value change and no template event, so under OnPush the Save button would\n // never re-enable. submitBlocked reads form.pending and form.invalid, so this is what\n // keeps it honest.\n this.statusSub?.unsubscribe();\n // A rebuild replaces every control, so anything cached against the old ones is stale.\n this.invalidFieldsCache = undefined;\n this.statusSub = this.form.statusChanges.subscribe(() => {\n // The only thing that can change which fields are invalid — see `invalidFields`.\n this.invalidFieldsCache = undefined;\n this.cdr.markForCheck();\n });\n\n this.valueSub = changes$.subscribe(() => {\n const flattened = this.flattenFormValues();\n this.formValues.set(flattened);\n this.runPatchOnTrue(flattened);\n this.syncHiddenFieldState(flattened);\n this.previousValues = { ...flattened };\n this.formChange.emit(this.extractRecord());\n });\n }\n\n /**\n * The `FormArray` behind an `array` field, for callers that manage rows themselves —\n * the record editor's inline row drawer.\n */\n getArrayControl(fieldId: string, tabId?: string): FormArray | null {\n const ctrl = this.getControl(fieldId, tabId);\n return ctrl instanceof FormArray ? ctrl : null;\n }\n\n /**\n * Build one detached row for an `array` field, with the field's own validators applied.\n * Exposed so a row can be edited outside the form and pushed on save.\n */\n createArrayRow(field: NestedFieldConfig, value?: unknown): AbstractControl {\n return this.buildArrayRow(field, value);\n }\n\n private buildArrayRow(field: NestedFieldConfig | undefined, item: unknown): AbstractControl {\n return this.structure.buildArrayRow(field, item);\n }\n\n /**\n * Mark every control touched, then re-check the field components.\n *\n * They are OnPush and `touched` is flipped from outside their own template, so the second\n * half is what makes the error messages actually appear.\n */\n private markAllTouched(): void {\n this.form.markAllAsTouched();\n this.fieldHosts?.forEach(host => host.refresh());\n }\n\n /**\n * Bring a record up to the config's `version` before it reaches the form.\n *\n * Done here because this is the one place a record enters the renderer, so a consumer\n * cannot forget it. Migration is a no-op unless the consumer registered steps *and* the\n * record is behind — an unstamped record is deliberately left alone (see `migrateRecord`).\n *\n * A missing or broken step throws from core. That is not swallowed: rendering a\n * half-understood record would write it back in a shape matching neither schema.\n */\n private upgradeRecord(data: Record<string, any>): Record<string, any> {\n if (!this.migrations.length || !this.config) return data;\n\n const result = migrateRecord(data, this.config, this.migrations);\n if (result.applied.length && isDevMode()) {\n console.info(\n `[ngx-dynamic-entity] Migrated a \"${this.config.entity}\" record from config version ` +\n `${result.from} to ${result.to} (steps: ${result.applied.join(', ')}).`,\n );\n }\n return result.record;\n }\n\n private patchForm(data: Record<string, any>): void {\n if (!data || !this.form || !this.config) return;\n const fieldsById = new Map(this.allFields().map(f => [f.id, f]));\n const unconsumed = this.structure.patchForm(this.form, this.config, data, fieldsById);\n this.warnUnconsumedInitialData(unconsumed);\n }\n\n /**\n * A record is nested by tab id (`{ tabId: { fieldId: value } }`) unless the tab sets\n * `flatData: true`. Handing a flat record to a nested tab finds nothing, so the fields\n * stay empty — with no error and no clue. That silent miss is the most expensive way to\n * lose an hour with this library, so name it in dev builds.\n *\n * Which keys were missed is `FormStructureService`'s answer; warning once per key per form\n * is this component's, because it is the thing that lives as long as the form does.\n */\n private warnUnconsumedInitialData(keys: readonly string[]): void {\n const fresh = keys.filter(key => !this.warnedUnconsumedKeys.has(key));\n if (!fresh.length) return;\n\n for (const key of fresh) this.warnedUnconsumedKeys.add(key);\n\n const shown = fresh.slice(0, 5).join(', ');\n const more = fresh.length > 5 ? ` (+${fresh.length - 5} more)` : '';\n const plural = fresh.length === 1;\n console.warn(\n `[ngx-dynamic-entity] initialData has top-level ${plural ? 'key' : 'keys'} matching ` +\n `${plural ? 'a field that was' : 'fields that were'} not populated: ${shown}${more}. ` +\n `A record is nested by tab id ({ tabId: { fieldId: value } }) unless the tab sets ` +\n `flatData: true. Either nest the value under its tab id, or set flatData: true on ` +\n `the tab holding ${plural ? 'that field' : 'those fields'}.`,\n );\n }\n\n /** Warn once per key per form instance — patchForm re-runs on every initialData change. */\n private readonly warnedUnconsumedKeys = new Set<string>();\n\n /** Assemble full nested record from per-tab FormGroups, respecting flatData, refererField & arrays. */\n extractRecord(): Record<string, any> {\n return this.structure.extractRecord(this.form, this.config);\n }\n\n /**\n * Warns when a rule names a field id that two scopes define.\n *\n * Field ids are unique per scope, so `address` may exist on both Personal Details and Work\n * Details — but a rule carries a bare id and no scope, so it cannot say which one it means.\n * `flattenFormValues` keys by bare id, so one of the two silently wins and the rule reads\n * whichever landed there.\n *\n * `validateConfig({ rules })` catches this statically. The check here remains because\n * consumers that never call the validator still get a signal in development.\n */\n private warnAmbiguousRuleReferences(): void {\n if (!isDevMode() || !this.rules?.length || !this.config) return;\n\n const ambiguous = ambiguousFieldIds(this.config);\n if (ambiguous.size === 0) return;\n\n const referenced = new Set<string>();\n for (const rule of this.rules) {\n if (rule.fieldId) referenced.add(rule.fieldId);\n for (const condition of rule.conditions ?? []) {\n if (condition.compareToField) referenced.add(condition.compareToField);\n }\n for (const target of rule.targets ?? []) {\n if (target.type === 'field' && target.id) referenced.add(target.id);\n }\n }\n\n for (const raw of referenced) {\n const parsed = parseFieldRef(raw);\n if (parsed.kind === 'ref') continue;\n const id = parsed.value;\n const scopes = ambiguous.get(id);\n if (!scopes || this.warnedAmbiguousIds.has(id)) continue;\n this.warnedAmbiguousIds.add(id);\n console.warn(\n `[ngx-dynamic-entity] A rule references field \"${id}\", which is defined in ${scopes.join(' and ')}. ` +\n `A bare id cannot say which one is meant, so the rule will read whichever the form finds first. ` +\n `Name it by path instead, as [${scopes[0]}.${id}].`,\n );\n }\n }\n\n /**\n * Ids already warned about, per component instance.\n *\n * This was `private static`, so it was module-global mutable state that nothing ever\n * cleared: under SSR every render of every form in the process accumulated into one set\n * that lived as long as the server did, and the first request to render a config\n * suppressed the warning for every request after it. Per instance, the warning is once per\n * form — which is what \"warn once\" was meant to mean.\n */\n private readonly warnedAmbiguousIds = new Set<string>();\n\n /**\n * The value map rules and `showWhen` are evaluated against.\n *\n * Every field appears under two keys: its bare id, and its `refererField` path wrapped in brackets.\n * The bare id is what every config written so far uses and is kept exactly as it was — but\n * ids are unique per scope, so when two scopes define one the last field walked wins and\n * the rule reads whichever that is. `[personal.address]` names one field and cannot be\n * ambiguous, which is why a rule that has to distinguish them uses the ref.\n *\n * Both live in one flat map on purpose: `evaluateFormRules` takes a `Record<string,\n * unknown>` and needs no knowledge of refs at all — the extra keys simply resolve.\n */\n /**\n * Every name a rule may address this field by.\n *\n * A rule target is either a bare field id — how every config so far addresses a field — or\n * a bracketed path, which is the only way to name one of two fields that share an id. Both\n * have to match, or a rule written either way would fail to hide what it targeted.\n *\n * The path comes last, and `syncHiddenFieldState` relies on that: it uses the last entry\n * as the field's address when deciding whether a hidden container already covers it.\n */\n private namesOf(field: NestedFieldConfig): readonly string[] {\n const path = field.refererField ?? this.pathFor(field);\n return path ? [field.id, toRefToken(path)] : [field.id];\n }\n\n /**\n * The field's dotted address, unbracketed.\n *\n * The positional path rather than an authored `refererField`: this is compared as a prefix\n * to decide whether a hidden container already covers a field, and containment is a fact\n * about where the field *is*. A `refererField` is a binding override — it says where the\n * value goes, not which group renders it.\n */\n private addressOf(field: NestedFieldConfig): string {\n return this.pathFor(field) ?? field.id;\n }\n\n /** The field's declared path, or the one its position implies when it carries none. */\n private pathFor(field: NestedFieldConfig): string | null {\n const entry = this.scopeEntryFor(field);\n return entry ? fieldRefFor(entry.scope, field.id) : null;\n }\n\n /**\n * Every field in the config with the scope its value is stored under, cached per config.\n *\n * `collectFieldScopes` walks the whole tree. It was called once per field from `pathFor`,\n * which `namesField` calls, which the render filter calls for every field on the active\n * tab — a quadratic walk on every change-detection pass. Keyed by config identity, so a\n * new config invalidates it without an explicit lifecycle hook to forget.\n */\n private fieldScopes(): FieldScopeEntry[] {\n if (this.scopeCache?.config !== this.config) {\n const entries = collectFieldScopes(this.config);\n this.scopeCache = {\n config: this.config,\n entries,\n byField: new Map(entries.map(entry => [entry.field, entry])),\n };\n }\n return this.scopeCache.entries;\n }\n\n private scopeEntryFor(field: NestedFieldConfig): FieldScopeEntry | undefined {\n this.fieldScopes();\n return this.scopeCache?.byField.get(field);\n }\n\n private scopeCache?: {\n config: EntityFormConfig | null | undefined;\n entries: FieldScopeEntry[];\n byField: Map<NestedFieldConfig, FieldScopeEntry>;\n };\n\n /**\n * The control a scope entry addresses, named by path rather than by bare id.\n *\n * `getControl(field.id)` with no tab falls through to a first-match recursive search of the\n * whole form, so with `address` on two tabs, hiding one disabled the other. The control\n * tree mirrors the scope path exactly — `buildTabControls` nests by tab id and\n * `buildFieldControl` nests a `group` under its own id — so a `[path]` ref resolves through\n * `form.get()` on `getControl`'s first branch and names exactly one control.\n *\n * A field inside an `array` has no static path: its controls live in `FormArray` rows built\n * per row. `form.get()` returns null for those and they are left alone, which is correct —\n * a row's controls are created and destroyed with the row.\n */\n private controlForEntry(entry: FieldScopeEntry): AbstractControl | null {\n return this.getControl(toRefToken(fieldRefFor(entry.scope, entry.field.id)));\n }\n\n\n\n private flattenFormValues(): Record<string, any> {\n const out: Record<string, any> = {};\n for (const entry of collectFieldScopes(this.config)) {\n const field = entry.field;\n if (!field?.id) continue;\n const ctrl = this.getControl(field.id, entry.scope.split('.').pop());\n if (!ctrl) continue;\n out[field.id] = ctrl.value;\n out[toRefToken(refOf(field, entry.scope))] = ctrl.value;\n }\n return out;\n }\n\n // ─── autoPatch / patchOnTrue ──────────────────────────────────────────────\n\n /**\n * `autoPatch` — copy mapped fields out of the record the user just selected in an\n * entity-ref field into the configured target tab's controls.\n */\n private runAutoPatch(fieldId: string, record: Record<string, unknown> | undefined): void {\n if (!record) return;\n const field = this.allFields().find(f => f.id === fieldId);\n const autoPatch = field?.autoPatch;\n if (!autoPatch) return;\n\n const patch = applyAutoPatch(autoPatch, record);\n for (const [targetId, value] of Object.entries(patch)) {\n const control = this.resolveTargetControl(autoPatch, targetId);\n control?.patchValue(value);\n }\n // Readonly targets interpolate `control.value` under OnPush. `detectChanges` on the\n // hosted component flushes that write immediately — `markForCheck` waits for a later\n // tick that a Playwright selection never schedules.\n this.fieldHosts?.forEach(host => host.refresh());\n }\n\n /**\n * `patchOnTrue` — when a boolean/checkbox field transitions to `true`,\n * copy `from` → `to` within the current record.\n */\n private runPatchOnTrue(values: Record<string, any>): void {\n for (const field of this.allFields()) {\n const mappings = field.patchOnTrue;\n if (!mappings?.length) continue;\n\n const wasTrue = this.previousValues[field.id] === true;\n const isTrue = values[field.id] === true;\n if (!isTrue || wasTrue) continue;\n\n const patch = applyPatchOnTrue(mappings, values);\n for (const [targetId, value] of Object.entries(patch)) {\n this.getControl(targetId)?.patchValue(value, { emitEvent: false });\n }\n }\n }\n\n /**\n * Prefer a control declared on the configured target tab; fall back to a top-level control.\n *\n * \"Declared on the tab\" now means anywhere under it, sub-tabs and `group` children\n * included. It meant the tab's own top-level fields only, so an `autoPatch` mapping onto a\n * field inside a group resolved to `null` and copied nothing, silently.\n */\n private resolveTargetControl(autoPatch: AutoPatchConfig, targetId: string): AbstractControl | null {\n const tab = findTab(this.tabs, autoPatch.targetTab);\n if (!tab) return this.getControl(targetId, autoPatch.targetTab);\n\n const entry = fieldsUnderTab(this.config, autoPatch.targetTab).find(e => {\n if (!e.field?.id) return false;\n const parsed = parseFieldRef(targetId);\n return parsed.kind === 'ref'\n ? fieldRefFor(e.scope, e.field.id) === parsed.value\n : e.field.id === parsed.value;\n });\n if (!entry) return null;\n return this.controlForEntry(entry);\n }\n\n // ─── Helpers ──────────────────────────────────────────────────────────────\n\n /**\n * Keep a hidden field's control out of form validity — see\n * `RulesEvaluationService.syncHiddenFieldState`, which owns the rule and the reasoning.\n *\n * This supplies the three things it cannot know: which fields exist and in what order\n * (`collectFieldScopes`, parent-first), what each one is called, and which control each\n * one addresses.\n */\n private syncHiddenFieldState(values: Record<string, any>): void {\n if (this.preview) return; // preview freezes the whole form on purpose\n\n this.rulesEvaluation.syncHiddenFieldState(this.fieldScopes(), {\n result: this.ruleResult(),\n values,\n namesOf: field => this.namesOf(field),\n addressOf: field => this.addressOf(field),\n controlFor: entry => this.controlForEntry(entry),\n });\n }\n\n /** Every field in the config, including `group`/`array` children. */\n private allFields(): NestedFieldConfig[] {\n const out: NestedFieldConfig[] = [];\n const walkFields = (fields: NestedFieldConfig[] | undefined) => {\n for (const f of fields ?? []) {\n out.push(f);\n if (f.children?.length) walkFields(f.children);\n }\n };\n const walkTabs = (tabs: NestedTabConfig[] | undefined) => {\n for (const t of tabs ?? []) {\n walkFields(t.fields);\n walkTabs(t.children);\n }\n };\n walkTabs(this.config?.tabs);\n return out;\n }\n\n /** An empty `originalData` counts as \"not supplied\" — fall back to the captured baseline. */\n private baseline(): Record<string, any> {\n const supplied = this.originalData;\n if (supplied && Object.keys(supplied).length > 0) return supplied;\n return this.sessionBaseline();\n }\n\n /**\n * Whether a critical field still holds what it held when the session started.\n *\n * The same question `VALUE_CHANGED` asks, so it is answered by the same comparator rather\n * than by a third one. The local version compared objects through `JSON.stringify`, which\n * is key-order sensitive — two serialisers writing the same option in a different key\n * order made the field read as edited — and had its own idea of which values count as\n * empty. `valuesEqual` is order-independent and treats `null` and `undefined` as the same\n * absence; the empty-string case is kept here, because a cleared text input is not an edit.\n */\n private sameValue(a: unknown, b: unknown): boolean {\n const aEmpty = a === null || a === undefined || a === '';\n const bEmpty = b === null || b === undefined || b === '';\n if (aEmpty && bEmpty) return true;\n return valuesEqual(a, b);\n }\n\n /**\n * Find a control by a bracketed path or a bare field id.\n *\n * Public API, so it stays on the component and delegates — see `FormStructureService`,\n * which owns the resolution rule and is where the behaviour is documented.\n */\n getControl(fieldId: string, currentTabId?: string): AbstractControl | null {\n return this.structure.getControl(this.form, this.config, fieldId, currentTabId);\n }\n\n /**\n * Move focus into the newly shown panel.\n *\n * Activating a tab replaces everything below it while focus stays on the tab button, so a\n * screen-reader or keyboard user is given no indication that the content changed and must\n * tab back through the strip to reach it. Deferred a frame because the panel's contents\n * are rendered by the change detection this call is part of.\n */\n private focusActivePanel(): void {\n if (typeof requestAnimationFrame !== 'function') return;\n requestAnimationFrame(() =>\n // `preventScroll` because this focus exists to tell a screen reader the panel changed,\n // not to move the page. The default scrolls the panel into view, which on a short\n // viewport jumps the layout — enough that a Save button below it moves out from under\n // a tap. The panel sits directly beneath the tab strip and is already on screen.\n this.formPanel?.nativeElement?.focus?.({ preventScroll: true }),\n );\n }\n\n /** Accessible name for the field panel — it is the tabpanel for the active tab. */\n get activeTabLabel(): string {\n const tab = this.activeSubTabConfig ?? this.activeTabConfig;\n return tab ? this.resolveTabLabel(tab) : '';\n }\n\n /**\n * Why a referenced field is flagged.\n *\n * `hasDrift` was written by the builder and read by nothing at runtime, so a field whose\n * source definition had changed since it was linked looked entirely normal to the person\n * filling the form in.\n */\n driftHint(field: NestedFieldConfig): string {\n const source = field.referencedEntityKey ? `\"${field.referencedEntityKey}\"` : 'its source entity';\n return `This field is linked to ${source} and its definition there has changed since it was linked.`;\n }\n\n resolveTabLabel(tab: NestedTabConfig): string {\n return resolveLabel(tab.label, this.language);\n }\n\n async submit(): Promise<void> {\n if (!this.canSubmit || this.submitBlocked) {\n /*\n * A refused save used to mark every control touched and stop there.\n *\n * On a tabbed form that is indistinguishable from a broken button: the errors appear on\n * whichever tabs hold them, the user is looking at a different one, and nothing on\n * screen changes. Three things fix it, and all three are needed — the summary says how\n * many and which, the tab badges say where, and this jump takes the user to the first.\n */\n this.markAllTouched();\n this.submitAttempted.set(true);\n const first = this.invalidFields()[0];\n if (first) this.jumpToField(first.field.id);\n return;\n }\n\n // Whatever the last attempt complained about is settled, so the summary goes away.\n this.submitAttempted.set(false);\n\n const rawData = this.extractRecord();\n let processedData = rawData;\n\n this.isSaving.set(true);\n try {\n // beforeSave can now abort the save: returning false, or throwing, stops it. Previously\n // its return value simply replaced the payload and the submit proceeded regardless, so\n // a hook that wanted to veto — a server-side check, a confirmation — had no way to.\n const hookKey = `${this.config?.entity}:beforeSave`;\n if (this.hookRegistry.has(hookKey)) {\n const result = await this.hookRegistry.run(hookKey, processedData);\n if (result === false) {\n this.saveRejected.emit({ reason: 'beforeSave returned false' });\n return;\n }\n // Anything else is the payload to submit; `undefined` means \"unchanged\".\n if (result !== undefined && result !== true) processedData = result;\n }\n\n this.formSubmit.emit(processedData);\n } catch (err) {\n // A hook that throws aborts the save and reports why, rather than the error escaping\n // into an unhandled rejection with the form left looking as though it saved.\n this.saveRejected.emit({ reason: err instanceof Error ? err.message : String(err), error: err });\n } finally {\n this.isSaving.set(false);\n }\n }\n\n reset(): void {\n this.form.reset();\n if (this.initialData) this.patchForm(this.initialData);\n const values = this.flattenFormValues();\n this.formValues.set(values);\n this.previousValues = { ...values };\n this.unlockedFields.set(new Set<string>());\n // Nothing has been attempted against the restored values, so the old complaint is stale.\n this.submitAttempted.set(false);\n this.formReset.emit();\n }\n}\n","@if (canView) {\n <form [formGroup]=\"form\" (ngSubmit)=\"submit()\" class=\"ngx-form\" [class.ngx-form--readonly]=\"readonly\" novalidate>\n <!-- Error message banner -->\n @if (error) {\n <div class=\"ngx-form__error-banner\" role=\"alert\" data-testid=\"form-error\">{{ error }}</div>\n }\n\n <!--\n Why the last Save did nothing.\n Only after a refused submit — see `submitAttempted`. Each entry jumps to its field,\n switching tabs on the way, because the field is usually not the one on screen.\n -->\n @if (submitAttempted() && invalidFields().length > 0) {\n <div class=\"ngx-form__error-summary\" role=\"alert\" data-testid=\"error-summary\" tabindex=\"-1\">\n <!--\n `error-summary-heading`, not `-title`: the links below are `error-summary-<fieldId>`,\n and a field whose id happens to be `title` would then share a test id with this line.\n The `extensions` entity has exactly such a field.\n -->\n <p class=\"ngx-form__error-summary-title\" data-testid=\"error-summary-heading\">\n {{ ui.text('errorSummaryTitle', language, { count: invalidFields().length }) }}\n </p>\n <ul class=\"ngx-form__error-summary-list\">\n @for (entry of invalidFields(); track entry.field.id) {\n <li>\n <!--\n The field, and what is wrong with it — the same sentence the field renders\n under itself, so the summary is not a second opinion. Naming only the field\n left the user to visit each one to find out what it wanted.\n -->\n <button\n type=\"button\"\n class=\"ngx-form__error-summary-link\"\n [attr.data-testid]=\"'error-summary-' + entry.field.id\"\n (click)=\"jumpToField(entry.field.id)\"\n >\n <span class=\"ngx-form__error-summary-field\">{{ resolveFieldLabel(entry.field) }}</span>\n @if (entry.message) {\n <span class=\"ngx-form__error-summary-reason\">{{ entry.message }}</span>\n }\n </button>\n </li>\n }\n </ul>\n </div>\n }\n\n <!-- Rules Info Banners -->\n @for (infoKey of showInfoBanners ? Object.keys(ruleResult().infoBanners) : []; track infoKey) {\n <div class=\"ngx-form__info-banner\" role=\"status\" [attr.data-testid]=\"'info-banner-' + infoKey\">\n ℹ️ {{ ruleResult().infoBanners[infoKey] }}\n </div>\n }\n\n <!-- Rules Validation Errors & Warnings -->\n @for (errKey of Object.keys(ruleResult().validationErrors); track errKey) {\n <div class=\"ngx-form__error-banner\" role=\"alert\" [attr.data-testid]=\"'rule-error-' + errKey\">\n ⚠️ {{ ruleResult().validationErrors[errKey] }}\n </div>\n }\n @for (warnKey of Object.keys(ruleResult().validationWarnings); track warnKey) {\n <div class=\"ngx-form__warning-banner\" role=\"status\" [attr.data-testid]=\"'rule-warning-' + warnKey\">\n ⚡ {{ ruleResult().validationWarnings[warnKey] }}\n </div>\n }\n\n <!-- Deferred VALUE_CHANGED notice for criticalField edits (vs session baseline) -->\n @if (changedCriticalFields().length > 0) {\n <div class=\"ngx-form__warning-banner\" role=\"status\" data-testid=\"critical-change-banner\">\n {{ ui.text('criticalFieldChanged', language, { fields: changedCriticalFieldLabels() }) }}\n </div>\n }\n\n <!-- Primary Tab bar — only if visible tabs defined -->\n @if (visibleTabs.length > 0) {\n <div class=\"ngx-form__tabs\" role=\"tablist\" data-testid=\"tab-strip\">\n @for (tab of visibleTabs; track tab.id) {\n <button\n type=\"button\"\n class=\"ngx-form__tab\"\n [attr.data-testid]=\"'tab-' + tab.id\"\n [class.ngx-form__tab--active]=\"activeTab() === tab.id\"\n (click)=\"setActiveTab(tab.id)\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab() === tab.id\"\n >\n {{ resolveTabLabel(tab) }}\n <!--\n How many fields on this tab are stopping the save.\n The count is in the accessible name rather than the badge, because \"3\" read out\n after a tab name says nothing about what it counts.\n -->\n @if (tabErrorCount(tab); as errors) {\n <span\n class=\"ngx-form__tab-badge\"\n [attr.data-testid]=\"'tab-errors-' + tab.id\"\n [attr.aria-label]=\"ui.text('tabErrorCount', language, { count: errors })\"\n >{{ errors }}</span\n >\n }\n </button>\n }\n </div>\n }\n\n <!-- Sub-tab bar — only if active tab has sub-tabs -->\n @if (visibleSubTabs.length > 0) {\n <div\n class=\"ngx-form__tabs ngx-form__tabs--sub\"\n role=\"tablist\"\n data-testid=\"subtab-strip\"\n style=\"margin-top: -12px; margin-bottom: 12px; font-size: 13px\"\n >\n @for (subTab of visibleSubTabs; track subTab.id) {\n <button\n type=\"button\"\n class=\"ngx-form__tab ngx-form__tab--sub\"\n [attr.data-testid]=\"'subtab-' + subTab.id\"\n [class.ngx-form__tab--active]=\"activeSubTabConfig?.id === subTab.id\"\n (click)=\"setActiveSubTab(subTab.id)\"\n role=\"tab\"\n [attr.aria-selected]=\"activeSubTabConfig?.id === subTab.id\"\n >\n {{ resolveTabLabel(subTab) }}\n @if (subTabErrorCount(subTab); as errors) {\n <span\n class=\"ngx-form__tab-badge\"\n [attr.data-testid]=\"'subtab-errors-' + subTab.id\"\n [attr.aria-label]=\"ui.text('tabErrorCount', language, { count: errors })\"\n >{{ errors }}</span\n >\n }\n </button>\n }\n </div>\n }\n\n <!--\n One tabpanel per tab, wrapping both branches. Focus moves here on a tab switch, and a\n module tab is still a tab — putting the panel semantics on only the fields branch left\n a module tab with nowhere for focus to land.\n -->\n <div role=\"tabpanel\" tabindex=\"-1\" #formPanel class=\"ngx-form__tabpanel\" [attr.aria-label]=\"activeTabLabel\">\n @if (activeTabModuleComponent) {\n <div class=\"ngx-form__module-panel\" data-testid=\"module-panel\">\n <ng-container\n *ngComponentOutlet=\"activeTabModuleComponent; inputs: (activeSubTabConfig || activeTabConfig)?.moduleInputs\"\n ></ng-container>\n </div>\n } @else {\n <!-- Fields for active tab (Responsive 12-column grid) -->\n <div class=\"ngx-form__panel\" data-testid=\"form-panel\">\n @for (field of fieldsForActiveTab; track field.id) {\n <div\n class=\"ngx-form__field-slot\"\n [style.gridColumn]=\"getFieldSpan(field)\"\n [attr.id]=\"'field-container-' + field.id\"\n tabindex=\"-1\"\n >\n <ngx-dynamic-field\n [field]=\"field\"\n [control]=\"getControl(field.id, (activeSubTabConfig || activeTabConfig)?.id)!\"\n [config]=\"config\"\n [currentTabId]=\"(activeSubTabConfig || activeTabConfig)?.id\"\n [language]=\"language\"\n [readonly]=\"isFieldReadonly(field)\"\n [userRoles]=\"userRoles\"\n />\n @if (field.hasDrift) {\n <!--\n Drift was previously visible only in the builder, so a referenced field whose\n source had changed looked completely normal to the person filling the form in.\n role=\"status\" rather than \"alert\": it is information, not an error.\n -->\n <span\n class=\"ngx-field__drift\"\n role=\"status\"\n [attr.data-testid]=\"'field-' + field.id + '-drift'\"\n [title]=\"driftHint(field)\"\n >⚠ {{ driftHint(field) }}</span\n >\n }\n @if (field.criticalField && !readonly) {\n <button\n type=\"button\"\n class=\"ngx-form__lock\"\n [attr.data-testid]=\"'lock-' + field.id\"\n [attr.aria-pressed]=\"!isFieldLocked(field)\"\n [attr.aria-label]=\"\n ui.text(isFieldLocked(field) ? 'unlockField' : 'lockField', language, {\n field: resolveFieldLabel(field),\n })\n \"\n [title]=\"ui.text(isFieldLocked(field) ? 'criticalFieldUnlockHint' : 'criticalFieldLockHint', language)\"\n (click)=\"toggleFieldLock(field)\"\n >\n {{ isFieldLocked(field) ? '🔒' : '🔓' }}\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Submit button — gated by RBAC and isSaving lock -->\n @if (!readonly && permissions.canEdit) {\n <div class=\"ngx-form__actions\" data-testid=\"form-actions\">\n <button type=\"button\" class=\"ngx-form__reset\" data-testid=\"form-reset\" (click)=\"reset()\" [disabled]=\"isSaving()\">\n {{ ui.text('reset', language) }}\n </button>\n <!--\n Two different \"unavailable\" states, and they are not the same thing.\n\n `disabled` is for what a retry cannot fix — a save in flight, an async check still\n outstanding. `data-blocked` is for validation: the button stays fully operable,\n because pressing it is how the user gets the error summary, but it should not look\n ready either. The stylesheet mutes it without taking the click away.\n\n Deliberately not `aria-disabled`. That announces a control as present-but-inoperable,\n and this one is operable and useful — pressing it raises a `role=\"alert\"` naming\n every field at fault, which is more than a disabled button could ever say. Tooling\n agrees: Playwright refuses to click through `aria-disabled`, and it would be right\n to, because the attribute would be claiming something untrue.\n -->\n <button\n type=\"submit\"\n class=\"ngx-form__submit\"\n data-testid=\"form-submit\"\n [disabled]=\"submitDisabled\"\n [attr.data-blocked]=\"submitBlocked ? '' : null\"\n [title]=\"ui.text('saveShortcutHint', language)\"\n >\n @if (isSaving() || loading) {\n {{ ui.text('saving', language) }}\n } @else {\n {{ ui.text('save', language) }}\n }\n </button>\n </div>\n }\n </form>\n} @else {\n <!-- permissions.view denied: render nothing of the record.\n Presentational only — the server must not send data this user may not see. -->\n <div class=\"ngx-form__denied\" role=\"status\" data-testid=\"form-access-denied\">\n {{ ui.text('accessDenied', language) }}\n </div>\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n Input,\n Output,\n EventEmitter,\n OnChanges,\n SimpleChanges,\n signal,\n computed,\n inject,\n ViewChild,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { AbstractControl, FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport type { EntityFormConfig, FormRule, NestedFieldConfig, NestedTabConfig } from '@dynamic-entity/core';\nimport { findTab, formatDisplayValue, getTabData, resolveLabel } from '@dynamic-entity/core';\nimport { DynamicFormComponent } from './dynamic-form.component';\nimport { DynamicFieldComponent } from './dynamic-field/dynamic-field.component';\nimport { HookRegistryService } from '../services/hook-registry.service';\nimport { RulesEvaluationService } from '../services/rules-evaluation.service';\nimport { RbacService } from '../services/rbac.service';\nimport { UiTextService } from '../services/ui-text.service';\n\n/**\n * Distinguishes \"no tab holds this field\" from \"the field holds undefined\", so the tab walk\n * can keep searching in the first case and stop in the second.\n */\nconst FIELD_NOT_FOUND = Symbol('field-not-found');\n\n/**\n * DynamicRecordFormComponent — comprehensive tabbed record view & edit component.\n * Supports cross-tab rule evaluation, profile header, summary drawer (showOnMinimize),\n * interactive quick-jump links, and baseline modification tracking.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-dynamic-record-form',\n standalone: true,\n imports: [CommonModule, ReactiveFormsModule, DynamicFormComponent, DynamicFieldComponent],\n templateUrl: './dynamic-record-form.component.html',\n /*\n * The record editor's own baseline, for a consumer who imports no stylesheet.\n *\n * Every value reads the token `ngx-dynamic-entity/styles.css` sets, with the previous\n * hard-coded literal as its fallback — so importing that file re-skins this component\n * instead of fighting it. It used to be literals all the way down, and because a component\n * stylesheet is injected after a global one and carries an attribute selector, the\n * stylesheet's whole `.ngx-record-editor__*` section lost every tie and did nothing at all.\n */\n styles: [\n `\n .ngx-record-editor {\n display: flex;\n flex-direction: column;\n gap: var(--ngx-gap, 16px);\n background: var(--ngx-color-surface, #ffffff);\n border: 1px solid var(--ngx-color-border, #e5e7eb);\n border-radius: var(--ngx-radius, 12px);\n padding: 20px;\n }\n .ngx-record-editor__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 14px;\n padding-bottom: var(--ngx-gap-sm, 16px);\n border-bottom: 1px solid var(--ngx-color-border, #f3f4f6);\n }\n .ngx-record-editor__title-group {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n }\n .ngx-record-editor__avatar {\n width: 44px;\n height: 44px;\n border-radius: 50%;\n object-fit: cover;\n background: var(--ngx-color-accent-soft, #e0e7ff);\n color: var(--ngx-color-accent, #4f46e5);\n border: 1px solid var(--ngx-color-border, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n font-size: 17px;\n flex: none;\n }\n .ngx-record-editor__title {\n font-size: 19px;\n font-weight: 700;\n color: var(--ngx-color-text, #111827);\n margin: 0;\n letter-spacing: -0.01em;\n }\n .ngx-record-editor__subtitle {\n font-size: var(--ngx-hint-size, 13px);\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-record-editor__header-toggle {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: var(--ngx-label-size, 13px);\n font-weight: var(--ngx-label-weight, 600);\n color: var(--ngx-color-text, #374151);\n }\n .ngx-record-editor__header-toggle-text {\n font-weight: 600;\n }\n .ngx-record-editor__banner {\n padding: 11px 14px;\n border-radius: var(--ngx-radius-sm, 8px);\n font-size: var(--ngx-font-size, 13px);\n border: 1px solid transparent;\n border-left-width: 3px;\n }\n .ngx-record-editor__banner--info {\n background: var(--ngx-color-info-soft, #eff6ff);\n border-color: var(--ngx-color-border, #dbeafe);\n border-left-color: var(--ngx-color-info, #1d4ed8);\n color: var(--ngx-color-info, #1d4ed8);\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n }\n .ngx-record-editor__banner--error {\n background: var(--ngx-color-error-soft, #fef2f2);\n border-color: var(--ngx-color-border, #fecaca);\n border-left-color: var(--ngx-color-error, #b91c1c);\n color: var(--ngx-color-error, #b91c1c);\n }\n .ngx-record-editor__banner--warning {\n background: var(--ngx-color-warning-soft, #fffbeb);\n border-color: var(--ngx-color-border, #fef3c7);\n border-left-color: var(--ngx-color-warning, #b45309);\n color: var(--ngx-color-warning, #b45309);\n }\n .ngx-record-editor__banner-dismiss {\n background: none;\n border: none;\n cursor: pointer;\n color: inherit;\n font-size: 14px;\n line-height: 1;\n padding: 2px 6px;\n border-radius: 4px;\n }\n .ngx-record-editor__banner-dismiss:hover {\n background: rgba(0, 0, 0, 0.06);\n }\n .ngx-record-editor__section-bar {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n flex-wrap: wrap;\n gap: 8px;\n }\n .ngx-record-editor__section-hint {\n margin-right: auto;\n font-size: var(--ngx-hint-size, 12px);\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-record-editor__rows {\n border: 1px solid var(--ngx-color-border, #f3f4f6);\n border-radius: var(--ngx-radius-sm, 8px);\n padding: 12px 14px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .ngx-record-editor__rows-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n .ngx-record-editor__row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-surface-alt, #f9fafb);\n }\n .ngx-record-editor__row-text {\n flex: 1;\n font-size: var(--ngx-font-size, 13px);\n overflow-wrap: anywhere;\n }\n .ngx-record-editor__row-btn {\n background: var(--ngx-color-surface, none);\n border: 1px solid var(--ngx-color-border, #e5e7eb);\n border-radius: var(--ngx-radius-sm, 6px);\n cursor: pointer;\n font: inherit;\n font-size: var(--ngx-hint-size, 12px);\n font-weight: var(--ngx-label-weight, 600);\n color: inherit;\n padding: 4px 10px;\n }\n .ngx-record-editor__row-btn:hover {\n border-color: var(--ngx-color-accent, #e5e7eb);\n color: var(--ngx-color-accent, inherit);\n }\n .ngx-record-editor__row-empty {\n font-size: var(--ngx-hint-size, 12px);\n color: var(--ngx-color-muted, #6b7280);\n margin: 0;\n }\n .ngx-record-editor__drawer {\n border: 1px solid var(--ngx-color-border, #dbeafe);\n background: var(--ngx-color-surface-alt, #f8fafc);\n border-radius: var(--ngx-radius, 8px);\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n /*\n * Label/value pairs, laid out as pairs. Stacked one per row this cost a full screen to\n * show six values that fit comfortably in two; auto-fit is what packs them, at whatever\n * width the panel happens to have.\n */\n .ngx-record-editor__summary-panel {\n background: var(--ngx-color-surface-alt, #f9fafb);\n border: 1px solid var(--ngx-color-border, #f3f4f6);\n border-radius: var(--ngx-radius, 8px);\n padding: 12px 16px;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));\n gap: 4px var(--ngx-gap, 12px);\n }\n .ngx-record-editor__summary-item {\n display: flex;\n flex-direction: column;\n cursor: pointer;\n padding: 6px 10px;\n border-radius: var(--ngx-radius-sm, 6px);\n min-width: 0;\n transition: background 0.15s;\n }\n .ngx-record-editor__summary-item:hover {\n background: var(--ngx-color-accent-soft, #eff6ff);\n }\n .ngx-record-editor__summary-label {\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--ngx-color-muted, #6b7280);\n font-weight: 600;\n }\n .ngx-record-editor__summary-val {\n font-size: var(--ngx-font-size, 14px);\n font-weight: 600;\n color: var(--ngx-color-text, #1f2937);\n overflow-wrap: anywhere;\n }\n @media (prefers-reduced-motion: reduce) {\n .ngx-record-editor__summary-item {\n transition: none;\n }\n }\n `,\n ],\n})\nexport class DynamicRecordFormComponent implements OnChanges {\n /** Library chrome, overridable via UI_TEXT. */\n protected readonly ui = inject(UiTextService);\n @Input() config!: EntityFormConfig;\n @Input() rules?: FormRule[];\n @Input() initialData?: Record<string, any>;\n @Input() userRoles: string[] = [];\n @Input() language: string = 'en';\n @Input() readonly: boolean = false;\n @Input() loading: boolean = false;\n @Input() error: string | null = null;\n /** Whole record read-only, regardless of RBAC. Equivalent to the reference's `isReadOnly`. */\n @Input() isReadOnly: boolean = false;\n /** Specific field ids forced read-only while the rest of the record stays editable. */\n @Input() readOnlyFields: string[] = [];\n /** Forwarded verbatim to the hosted form — see `DynamicFormComponent.layout`. */\n @Input() layout: 'stack' | 'auto' = 'stack';\n /**\n * Open the record read-only, with a per-tab \"Edit section\" flow — one tab is edited and\n * validated at a time. This is the framework's `EntityRecordComponent` model and the\n * default here.\n *\n * Set false for a directly editable record with no view/edit distinction.\n */\n @Input() viewMode: boolean = true;\n\n @Output() formSubmit = new EventEmitter<Record<string, any>>();\n @Output() formChange = new EventEmitter<Record<string, any>>();\n @Output() formReset = new EventEmitter<void>();\n /** One tab section was saved. Carries the whole record, plus which tab was edited. */\n @Output() sectionSave = new EventEmitter<{ tabId: string; record: Record<string, any> }>();\n /**\n * A `beforeSave` hook aborted the save — by returning false or throwing.\n *\n * Re-exposed from the embedded `ngx-dynamic-form`, and emitted by `saveSection` too. The\n * inner form already ran the hook and already refused the save, but nothing carried that\n * out to a host binding this component: the veto worked and looked exactly like a Save\n * button that did nothing, which is the failure `saveRejected` exists to prevent.\n */\n @Output() saveRejected = new EventEmitter<{ reason: string; error?: unknown }>();\n\n @ViewChild(DynamicFormComponent) dynamicFormComp?: DynamicFormComponent;\n\n private readonly rulesEvaluation = inject(RulesEvaluationService);\n private readonly rbacService = inject(RbacService);\n private readonly hookRegistry = inject(HookRegistryService);\n\n readonly currentData = signal<Record<string, any>>({});\n readonly originalBaseline = signal<Record<string, any>>({});\n\n /**\n * Info banners the user has dismissed, by field id.\n *\n * The reference's contract: an info banner persists until dismissed, **not** until the\n * value changes. Dismissal is keyed by field so re-triggering a different field's rule\n * still shows. Re-armed when a different record is loaded.\n */\n private readonly dismissed = signal<ReadonlySet<string>>(new Set<string>());\n\n /**\n * Info banners from the rules engine that are still showing.\n *\n * A getter, not a `computed`: the source is `dynamicFormComp`, a ViewChild. A computed\n * evaluated before the view initialises would capture no dependency on the child's\n * `ruleResult` signal and then never recompute. Read per change-detection pass instead.\n */\n get infoBanners(): { fieldId: string; message: string }[] {\n const result = this.dynamicFormComp?.ruleResult();\n const gone = this.dismissed();\n return Object.entries(result?.infoBanners ?? {})\n .filter(([fieldId]) => !gone.has(fieldId))\n .map(([fieldId, message]) => ({ fieldId, message: String(message) }));\n }\n\n dismissInfoBanner(fieldId: string): void {\n this.dismissed.set(new Set(this.dismissed()).add(fieldId));\n }\n\n /**\n * Whether the current roles may edit this record.\n *\n * `userRoles` was declared as an input here and then read by nothing at all — this\n * component computed no permissions of any kind, so the record view was fully editable\n * for every role while the plain form at least hid its Save button. Cached on the same\n * terms as the sibling component: it depends only on `config` and `userRoles`.\n */\n private permissionsCache: ReturnType<RbacService['getPermissions']> | null = null;\n\n get permissions(): ReturnType<RbacService['getPermissions']> {\n return (this.permissionsCache ??= this.rbacService.getPermissions(this.config, this.userRoles));\n }\n\n /** True when nothing in the record may be edited. */\n get recordReadOnly(): boolean {\n return this.readonly || this.isReadOnly || !this.permissions.canEdit;\n }\n\n // ─── Inline array-row editing ───────────────────────────────────────────────\n\n /**\n * A row of an `array` field is edited in a drawer, not inline in the tab panel.\n *\n * The drawer is rendered outside the tab container on purpose: the reference found that\n * building a row's FormGroup inside the tab view races the tab's own initialisation, so\n * the row form is kept detached and only pushed into the FormArray on save.\n */\n readonly inlineRowField = signal<NestedFieldConfig | null>(null);\n readonly inlineRowIndex = signal<number | null>(null);\n inlineRowForm: FormGroup | null = null;\n\n /** `array` fields on the tab currently shown, so the template can list their rows. */\n get arrayFieldsForActiveTab(): NestedFieldConfig[] {\n const tabId = this.activeTabId;\n const tab = tabId ? findTab(this.config?.tabs, tabId) : null;\n return (tab?.fields ?? []).filter(f => f.type === 'array');\n }\n\n /**\n * Rows currently held by an `array` field, read from the record value.\n *\n * Deliberately not read off the child's FormArray: that control only exists once the\n * child has initialised, so rendering from it changed value mid-pass. `currentData` is a\n * signal seeded from `initialData` and kept current by the child's `formChange`.\n */\n rowsOf(field: NestedFieldConfig): Record<string, unknown>[] {\n const tabId = this.activeTabId;\n const tabData = tabId ? getTabData(tabId, this.currentData(), this.config) : null;\n const rows = (tabData as Record<string, unknown> | null)?.[field.id];\n return Array.isArray(rows) ? (rows as Record<string, unknown>[]) : [];\n }\n\n /** One row rendered as text, so the list is readable without opening the drawer. */\n rowSummary(field: NestedFieldConfig, row: Record<string, unknown>): string {\n const value = row ?? {};\n const parts = (field.children ?? [])\n .map(child => value[child.id])\n .filter(v => v !== null && v !== undefined && v !== '')\n .map(v => (typeof v === 'object' ? JSON.stringify(v) : String(v)));\n return parts.length ? parts.join(' · ') : '(empty)';\n }\n\n openAddRow(field: NestedFieldConfig): void {\n if (this.sectionReadOnly) return;\n this.inlineRowField.set(field);\n this.inlineRowIndex.set(null);\n this.inlineRowForm = this.dynamicFormComp?.createArrayRow(field) as FormGroup;\n }\n\n openEditRow(field: NestedFieldConfig, index: number): void {\n if (this.sectionReadOnly) return;\n this.inlineRowField.set(field);\n this.inlineRowIndex.set(index);\n this.inlineRowForm = this.dynamicFormComp?.createArrayRow(field, this.rowsOf(field)[index]) as FormGroup;\n }\n\n cancelRow(): void {\n this.inlineRowField.set(null);\n this.inlineRowIndex.set(null);\n this.inlineRowForm = null;\n }\n\n /** Commit the drawer into the FormArray. Rules re-evaluate off the resulting value change. */\n saveRow(): void {\n const field = this.inlineRowField();\n const form = this.dynamicFormComp;\n if (!field || !form || !this.inlineRowForm) return;\n\n if (this.inlineRowForm.invalid) {\n this.inlineRowForm.markAllAsTouched();\n return;\n }\n\n const array = form.getArrayControl(field.id, this.activeTabId ?? undefined);\n if (!array) return;\n\n const index = this.inlineRowIndex();\n if (index === null) array.push(form.createArrayRow(field, this.inlineRowForm.value));\n else array.at(index).patchValue(this.inlineRowForm.value);\n\n array.updateValueAndValidity();\n this.currentData.set(form.extractRecord());\n this.cancelRow();\n }\n\n deleteRow(field: NestedFieldConfig, index: number): void {\n if (this.sectionReadOnly) return;\n const array = this.dynamicFormComp?.getArrayControl(field.id, this.activeTabId ?? undefined);\n array?.removeAt(index);\n array?.updateValueAndValidity();\n if (this.dynamicFormComp) this.currentData.set(this.dynamicFormComp.extractRecord());\n if (this.inlineRowIndex() === index) this.cancelRow();\n }\n\n // ─── Per-tab section editing ────────────────────────────────────────────────\n\n /**\n * The tab currently open for editing, or null when the record is being viewed.\n *\n * The reference edits one tab section at a time rather than the whole record, and\n * validates only that section on save — a required field on an untouched tab must not\n * block saving the tab you are actually working on.\n */\n readonly editingTabId = signal<string | null>(null);\n\n /**\n * The tab the inner form is showing.\n *\n * Tracked here rather than read off the ViewChild. The child resolves its first tab as\n * part of its own initialisation, so reading it during this component's render changed\n * value mid-pass — an ExpressionChangedAfterItHasBeenChecked error. Seeded from the\n * config and kept in step by the child's `activeTabChange` output.\n */\n private readonly activeTabIdSig = signal<string | null>(null);\n\n get activeTabId(): string | null {\n return this.activeTabIdSig();\n }\n\n onActiveTabChange(tabId: string): void {\n if (this.activeTabIdSig() === tabId) return;\n this.activeTabIdSig.set(tabId);\n // Editing does not follow the user to another tab.\n this.editingTabId.set(null);\n this.cancelRow();\n }\n\n /** First tab a user can see, used to seed the active tab before the child reports one. */\n private firstVisibleTabId(): string | null {\n return this.config?.tabs?.find(t => t.visibility !== false)?.id ?? null;\n }\n\n /** Errors from the last save attempt, by field id. */\n readonly sectionErrors = signal<Record<string, string>>({});\n\n /** Template access to `Object.keys` for iterating the error map. */\n protected readonly Object = Object;\n\n get isEditingActiveTab(): boolean {\n // Without view mode there is no view/edit distinction — everything is always editable.\n if (!this.viewMode) return true;\n return !!this.activeTabId && this.editingTabId() === this.activeTabId;\n }\n\n /** Fields render read-only unless their own tab is the one being edited. */\n get sectionReadOnly(): boolean {\n return this.recordReadOnly || !this.isEditingActiveTab;\n }\n\n editSection(): void {\n if (!this.viewMode || this.recordReadOnly || !this.activeTabId) return;\n this.sectionErrors.set({});\n this.editingTabId.set(this.activeTabId);\n }\n\n /** Discard this section's edits, restoring each field from the session baseline. */\n cancelSection(): void {\n const tabId = this.editingTabId();\n const form = this.dynamicFormComp;\n if (tabId && form) {\n const tab = findTab(this.config?.tabs, tabId);\n const baselineTab = (getTabData(tabId, this.originalBaseline(), this.config) ?? {}) as Record<string, unknown>;\n for (const field of tab?.fields ?? []) {\n const baselineValue = baselineTab[field.id];\n\n // A FormArray cannot be restored with setValue — that demands a value shaped exactly\n // like the current rows. Rebuild it from the baseline rows instead.\n const array = form.getArrayControl(field.id, tabId);\n if (array) {\n array.clear();\n for (const row of Array.isArray(baselineValue) ? baselineValue : []) {\n array.push(form.createArrayRow(field, row));\n }\n array.updateValueAndValidity();\n continue;\n }\n\n form.getControl(field.id, tabId)?.setValue(baselineValue ?? null);\n }\n this.currentData.set(form.extractRecord());\n }\n this.sectionErrors.set({});\n this.editingTabId.set(null);\n }\n\n /**\n * Validate this section only, then emit it. Validation is scoped two ways: Angular\n * validity of the tab's own controls, and rules filtered to this tab — a rule targeting\n * a hidden tab must not block the save (the reference's OV0-968 fix).\n */\n async saveSection(): Promise<void> {\n const tabId = this.editingTabId();\n const form = this.dynamicFormComp;\n if (!tabId || !form) return;\n\n const tab = findTab(this.config?.tabs, tabId);\n const errors: Record<string, string> = {};\n\n for (const field of tab?.fields ?? []) {\n const ctrl = form.getControl(field.id, tabId);\n if (ctrl?.invalid) {\n ctrl.markAsTouched();\n errors[field.id] = `${resolveLabel(field.label, this.language)} is invalid.`;\n }\n }\n\n const scoped = this.rulesEvaluation.filterForTab(this.rules, tabId, this.config);\n const ruleErrors = this.rulesEvaluation.evaluate(scoped, form.formValues(), this.originalBaseline()).validationErrors;\n Object.assign(errors, ruleErrors);\n\n if (Object.keys(errors).length > 0) {\n this.sectionErrors.set(errors);\n return;\n }\n\n this.sectionErrors.set({});\n\n const record = form.extractRecord();\n\n // Only await when there is something to await. An async function runs synchronously up\n // to its first `await`, so this keeps `sectionSave` firing in the same tick for the\n // hosts that register no hook — which is how it has always behaved, and which a host\n // may well depend on. Awaiting an already-resolved promise would defer the emit by a\n // microtask for everybody, to no purpose.\n const hookKey = `${this.config?.entity}:beforeSave`;\n const reviewed = this.hookRegistry.has(hookKey) ? await this.runBeforeSave(record) : record;\n // Vetoed: the section stays open, exactly as the whole-record form stays open, so the\n // user is looking at the values the hook refused rather than at a closed section.\n if (reviewed === null) return;\n\n this.editingTabId.set(null);\n this.currentData.set(reviewed);\n this.sectionSave.emit({ tabId, record: reviewed });\n }\n\n /**\n * Put a record to the entity's `beforeSave` hook.\n *\n * `sectionSave` carries the *whole* record — `extractRecord()`, not the tab's slice — so\n * the same payload reached persistence through two buttons, one of which asked the hook\n * and one of which did not. A hook registered to veto a save is a data-integrity\n * mechanism; having a second route around it made it advisory.\n *\n * @returns the record to emit, or `null` when the hook aborted (already reported).\n */\n private async runBeforeSave(record: Record<string, any>): Promise<Record<string, any> | null> {\n const hookKey = `${this.config?.entity}:beforeSave`;\n // Defensive: `saveSection` checks this before awaiting, but a later caller may not.\n if (!this.hookRegistry.has(hookKey)) return record;\n\n try {\n const result = await this.hookRegistry.run(hookKey, record);\n if (result === false) {\n this.saveRejected.emit({ reason: 'beforeSave returned false' });\n return null;\n }\n // Anything else is the payload to save; `undefined`/`true` mean \"unchanged\".\n return result === undefined || result === true ? record : (result as Record<string, any>);\n } catch (err) {\n this.saveRejected.emit({ reason: err instanceof Error ? err.message : String(err), error: err });\n return null;\n }\n }\n\n /**\n * Seed the session baseline from the loaded record so `VALUE_CHANGED` rules and the\n * modification banner compare against the record as it was opened — not as it was\n * after the first keystroke.\n */\n ngOnChanges(changes: SimpleChanges): void {\n // Permissions depend on these two and nothing else; a stale cache would keep a record\n // editable after a role switch.\n if (changes['config'] || changes['userRoles']) {\n this.permissionsCache = null;\n }\n if (changes['initialData'] || changes['config']) {\n this.originalBaseline.set({ ...(this.initialData ?? {}) });\n this.currentData.set({ ...(this.initialData ?? {}) });\n this.activeTabIdSig.set(this.firstVisibleTabId());\n // A different record is a different set of banners — re-arm them.\n this.dismissed.set(new Set<string>());\n }\n }\n\n get recordTitle(): string {\n if (!this.config) return 'Record';\n return this.config.name ? resolveLabel(this.config.name, this.language) : this.config.entity;\n }\n\n /**\n * What this record is called, as opposed to what kind of thing it is.\n *\n * The header used to show the entity's name twice — \"clients\", with \"Entity: clients\"\n * underneath — so the one question a record header exists to answer, *which* record am I\n * looking at, was the one thing it did not say. The entity keeps the subtitle; this takes\n * the heading.\n *\n * The order is deliberate. `showOnMinimize` is the author saying \"this is what identifies a\n * record\" — it is what the summary panel and the collapsed view already show — so it is\n * asked first. A text or email field is the fallback because those are what a name is\n * stored in; a number or a date is a property of the record, not its identity, and would\n * give a header reading \"42\". When neither exists there is nothing to name it with and the\n * entity label stands in, which is the behaviour this replaced.\n *\n * A masked field is never a candidate. Masking is presentational (see SECURITY.md), but\n * that is exactly why: the whole point is that this role does not get to read the value, and\n * promoting it into the page heading would print in full what every field renders as\n * `XXXXXXXXX`. A record whose only text field is masked keeps the entity label.\n *\n * One pass rather than two filtered ones: this is a getter the header reads on every change\n * detection, and the preferred candidate is usually the first field it meets.\n */\n get recordHeading(): string {\n const named = (field: NestedFieldConfig): string | null => {\n const value = this.fieldValue(field.id);\n if (typeof value !== 'string' && typeof value !== 'number') return null;\n const text = String(value).trim();\n return text.length ? text : null;\n };\n\n let fallback: string | null = null;\n for (const field of this.allFields()) {\n if (field.visibility === false) continue;\n if (this.rbacService.shouldMaskField(field, undefined, this.config, this.userRoles)) continue;\n\n if (field.showOnMinimize) {\n const preferred = named(field);\n if (preferred) return preferred;\n } else if (!fallback && (field.type === 'text' || field.type === 'email')) {\n fallback = named(field);\n }\n }\n return fallback ?? this.recordTitle;\n }\n\n get avatarLetter(): string {\n return (this.recordHeading || 'R').charAt(0).toUpperCase();\n }\n\n // ─── Header fields (isProfileImage / isHeaderToggle) ────────────────────────\n\n /** Every field in the config, at any depth. */\n private allFields(): NestedFieldConfig[] {\n const out: NestedFieldConfig[] = [];\n const walkFields = (fields: NestedFieldConfig[] | undefined) => {\n for (const f of fields ?? []) {\n out.push(f);\n walkFields(f.children);\n }\n };\n const walkTabs = (tabs: NestedTabConfig[] | undefined) => {\n for (const t of tabs ?? []) {\n walkFields(t.fields);\n walkTabs(t.children);\n }\n };\n walkTabs(this.config?.tabs);\n return out;\n }\n\n /** The field flagged `isProfileImage`, rendered as the record avatar. */\n get headerProfileField(): NestedFieldConfig | null {\n return this.allFields().find(f => f.isProfileImage) ?? null;\n }\n\n /** The field flagged `isHeaderToggle`, rendered as a status switch in the header. */\n get headerToggleField(): NestedFieldConfig | null {\n return this.allFields().find(f => f.isHeaderToggle) ?? null;\n }\n\n /** Avatar image URL, when the profile field holds a persisted FileRef. */\n get profileImageUrl(): string | null {\n const field = this.headerProfileField;\n if (!field) return null;\n const value = this.fieldValue(field.id) as { url?: string } | null;\n return value?.url ?? null;\n }\n\n get headerToggleValue(): boolean {\n const field = this.headerToggleField;\n return field ? this.fieldValue(field.id) === true : false;\n }\n\n /**\n * Flip the header toggle. It writes straight to the control rather than going through\n * section editing — the reference treats it as a record-level status switch, not part of\n * any one tab's section.\n */\n toggleHeaderStatus(): void {\n const field = this.headerToggleField;\n if (!field || this.recordReadOnly) return;\n const ctrl = this.controlFor(field.id);\n if (!ctrl) return;\n ctrl.setValue(!this.headerToggleValue);\n if (this.dynamicFormComp) this.currentData.set(this.dynamicFormComp.extractRecord());\n }\n\n /** Locate a field's control wherever it lives, since header fields may be on any tab. */\n private controlFor(fieldId: string): AbstractControl | null {\n return this.dynamicFormComp?.getControl(fieldId) ?? null;\n }\n\n /**\n * A field's current value, read from the record so it is stable during render.\n *\n * Resolved through `getTabData` so it honours exactly the nesting contract the form\n * patches with — `{ tabId: { fieldId } }`, or the record root when the tab sets\n * `flatData`. Reading the record flat instead is not a shortcut: it makes the summary\n * display values the form never loaded, which reads as \"the data is there\" while every\n * control behind it is empty.\n *\n * Walks sub-tabs as well: a summary, header, or profile field may sit on any tab at any\n * depth.\n */\n private fieldValue(fieldId: string): unknown {\n const visit = (tabs: NestedTabConfig[] = []): unknown => {\n for (const tab of tabs) {\n const data = getTabData(tab.id, this.currentData(), this.config) as Record<string, unknown> | null;\n if (data && fieldId in data) return data[fieldId];\n if (tab.children) {\n const found = visit(tab.children);\n if (found !== FIELD_NOT_FOUND) return found;\n }\n }\n return FIELD_NOT_FOUND;\n };\n\n const result = visit(this.config?.tabs);\n return result === FIELD_NOT_FOUND ? undefined : result;\n }\n\n readonly isModified = computed(() => {\n const orig = this.originalBaseline();\n const curr = this.currentData();\n if (!orig || !curr || Object.keys(orig).length === 0) return false;\n return JSON.stringify(orig) !== JSON.stringify(curr);\n });\n\n readonly summaryFields = computed<NestedFieldConfig[]>(() => {\n const fields: NestedFieldConfig[] = [];\n const walkTabs = (tabs: NestedTabConfig[] = []) => {\n for (const t of tabs) {\n for (const f of t.fields ?? []) {\n if (f.showOnMinimize) fields.push(f);\n }\n if (t.children) walkTabs(t.children);\n }\n };\n walkTabs(this.config?.tabs);\n return fields;\n });\n\n onFormChange(data: Record<string, any>): void {\n // Baseline is seeded from `initialData` in ngOnChanges; only fill it here when the\n // record was opened empty (create flow), so the first emitted shape becomes the baseline.\n if (Object.keys(this.originalBaseline()).length === 0) {\n this.originalBaseline.set({ ...data });\n }\n this.currentData.set(data);\n this.formChange.emit(data);\n }\n\n onFormSubmit(data: Record<string, any>): void {\n this.formSubmit.emit(data);\n }\n\n onFormReset(): void {\n this.formReset.emit();\n }\n\n formatFieldLabel(field: NestedFieldConfig): string {\n return resolveLabel(field.label, this.language);\n }\n\n /** \"Add <field> row\" / \"Edit <field> row\" — one key each, because word order moves. */\n rowDrawerTitle(field: NestedFieldConfig): string {\n const key = this.inlineRowIndex() === null ? 'addRowTitle' : 'editRowTitle';\n return this.ui.text(key, this.language, { field: this.formatFieldLabel(field) });\n }\n\n /** Summary values render through the shared core formatter, not a local stringifier. */\n formatFieldValue(field: NestedFieldConfig): string {\n return formatDisplayValue(field.type, field.options, this.fieldValue(field.id), this.language);\n }\n\n /**\n * Finds which tab — and, where the field lives one level down, which sub-tab — owns a\n * field. The walk used to check top-level `fields` only, so every field in a sub-tab was\n * simply not found and the jump did nothing at all.\n */\n\n /**\n * Switches to the tab holding `fieldId`, then scrolls it into view and moves focus to it.\n *\n * Delegated rather than implemented twice. The hosted form grew the same jump when a\n * refused save had to be able to take the user to the first invalid field, and the form is\n * where it belongs: it owns the tab state, the panel that renders the field, and the\n * element the jump is looking for. This is kept as the record editor's public entry point\n * because the summary panel's quick-jump calls it and a host may too.\n */\n jumpToField(fieldId: string): void {\n this.dynamicFormComp?.jumpToField(fieldId);\n }\n}\n","<div class=\"ngx-record-editor\">\n <!-- Record Header -->\n <div class=\"ngx-record-editor__header\">\n <div class=\"ngx-record-editor__title-group\">\n @if (profileImageUrl) {\n <img\n class=\"ngx-record-editor__avatar\"\n data-testid=\"header-profile-image\"\n [src]=\"profileImageUrl\"\n [alt]=\"recordHeading\"\n />\n } @else {\n <div class=\"ngx-record-editor__avatar\" data-testid=\"header-avatar-initial\">\n {{ avatarLetter }}\n </div>\n }\n <div>\n <!--\n The record's own name, with the entity underneath. These were the other way round —\n both showing the entity — so the header never said which record was open.\n -->\n <h2 class=\"ngx-record-editor__title\" data-testid=\"record-title\">\n {{ recordHeading }}\n </h2>\n <span class=\"ngx-record-editor__subtitle\">{{ ui.text('entityLabel', language, { entity: recordTitle }) }}</span>\n </div>\n </div>\n\n <!-- Record-level status switch, outside section editing -->\n @if (headerToggleField; as toggleField) {\n <label class=\"ngx-record-editor__header-toggle\">\n <span>{{ formatFieldLabel(toggleField) }}</span>\n <input\n type=\"checkbox\"\n role=\"switch\"\n data-testid=\"header-toggle\"\n [checked]=\"headerToggleValue\"\n [disabled]=\"recordReadOnly\"\n [attr.aria-checked]=\"headerToggleValue\"\n (change)=\"toggleHeaderStatus()\"\n />\n <span class=\"ngx-record-editor__header-toggle-text\">{{ ui.text(headerToggleValue ? 'yes' : 'no', language) }}</span>\n </label>\n }\n </div>\n\n <!-- Dismissible info banners (rules `info` action) -->\n @for (banner of infoBanners; track banner.fieldId) {\n <div\n class=\"ngx-record-editor__banner ngx-record-editor__banner--info\"\n role=\"status\"\n [attr.data-testid]=\"'info-banner-' + banner.fieldId\"\n >\n <span>ℹ️ {{ banner.message }}</span>\n <button\n type=\"button\"\n class=\"ngx-record-editor__banner-dismiss\"\n [attr.data-testid]=\"'dismiss-' + banner.fieldId\"\n [attr.aria-label]=\"ui.text('dismissBanner', language, { message: banner.message })\"\n (click)=\"dismissInfoBanner(banner.fieldId)\"\n >\n ✕\n </button>\n </div>\n }\n\n <!-- Modification baseline banner -->\n @if (isModified()) {\n <div class=\"ngx-record-editor__banner ngx-record-editor__banner--warning\">\n {{ ui.text('recordModified', language) }}\n </div>\n }\n\n <!-- Summary Panel (showOnMinimize fields with interactive jump) -->\n @if (summaryFields().length > 0) {\n <div class=\"ngx-record-editor__summary-panel\" data-testid=\"summary-panel\">\n @for (sf of summaryFields(); track sf.id) {\n <div\n class=\"ngx-record-editor__summary-item\"\n [attr.data-testid]=\"'summary-' + sf.id\"\n (click)=\"jumpToField(sf.id)\"\n [title]=\"ui.text('jumpToField', language, { field: formatFieldLabel(sf) })\"\n >\n <span class=\"ngx-record-editor__summary-label\">{{ formatFieldLabel(sf) }}</span>\n <span class=\"ngx-record-editor__summary-val\">{{ formatFieldValue(sf) }}</span>\n </div>\n }\n </div>\n }\n\n <!-- Section edit bar: one tab is edited at a time, and validated on its own -->\n @if (viewMode && !recordReadOnly) {\n <div class=\"ngx-record-editor__section-bar\">\n @if (isEditingActiveTab) {\n <span class=\"ngx-record-editor__section-hint\">{{ ui.text('editingSection', language) }}</span>\n <button type=\"button\" class=\"ngx-form__reset\" data-testid=\"cancel-section\" (click)=\"cancelSection()\">\n {{ ui.text('cancel', language) }}\n </button>\n <button type=\"button\" class=\"ngx-form__submit\" data-testid=\"save-section\" (click)=\"saveSection()\">\n {{ ui.text('saveSection', language) }}\n </button>\n } @else {\n <button type=\"button\" class=\"ngx-form__reset\" data-testid=\"edit-section\" (click)=\"editSection()\">\n {{ ui.text('editSection', language) }}\n </button>\n }\n </div>\n }\n\n @if (Object.keys(sectionErrors()).length > 0) {\n <div class=\"ngx-record-editor__banner ngx-record-editor__banner--error\" role=\"alert\" data-testid=\"section-errors\">\n @for (key of Object.keys(sectionErrors()); track key) {\n <div>⚠️ {{ sectionErrors()[key] }}</div>\n }\n </div>\n }\n\n <!-- Array rows: listed here, edited in the drawer below -->\n @for (arrayField of arrayFieldsForActiveTab; track arrayField.id) {\n <div class=\"ngx-record-editor__rows\" [attr.data-testid]=\"'rows-' + arrayField.id\">\n <div class=\"ngx-record-editor__rows-head\">\n <span class=\"ngx-record-editor__summary-label\">{{ formatFieldLabel(arrayField) }}</span>\n @if (!sectionReadOnly) {\n <button\n type=\"button\"\n class=\"ngx-form__reset\"\n [attr.data-testid]=\"'add-row-' + arrayField.id\"\n (click)=\"openAddRow(arrayField)\"\n >\n {{ ui.text('addRow', language) }}\n </button>\n }\n </div>\n\n @for (row of rowsOf(arrayField); track $index) {\n <div class=\"ngx-record-editor__row\" [attr.data-testid]=\"'row-' + arrayField.id + '-' + $index\">\n <span class=\"ngx-record-editor__row-text\">{{ rowSummary(arrayField, row) }}</span>\n @if (!sectionReadOnly) {\n <button\n type=\"button\"\n class=\"ngx-record-editor__row-btn\"\n [attr.data-testid]=\"'edit-row-' + arrayField.id + '-' + $index\"\n (click)=\"openEditRow(arrayField, $index)\"\n >\n {{ ui.text('edit', language) }}\n </button>\n <button\n type=\"button\"\n class=\"ngx-record-editor__row-btn\"\n [attr.data-testid]=\"'delete-row-' + arrayField.id + '-' + $index\"\n (click)=\"deleteRow(arrayField, $index)\"\n >\n {{ ui.text('delete', language) }}\n </button>\n }\n </div>\n } @empty {\n <p class=\"ngx-record-editor__row-empty\">{{ ui.text('noRows', language) }}</p>\n }\n </div>\n }\n\n <!--\n Row drawer. Deliberately outside the tab panel: building a row's FormGroup inside the\n tab view races the tab's own initialisation (the reference hit this with FormArray).\n -->\n @if (inlineRowField(); as rowField) {\n <div class=\"ngx-record-editor__drawer\" data-testid=\"row-drawer\" [formGroup]=\"inlineRowForm!\">\n <div class=\"ngx-record-editor__rows-head\">\n <strong>{{ rowDrawerTitle(rowField) }}</strong>\n </div>\n\n <div class=\"ngx-form__panel\">\n @for (child of rowField.children ?? []; track child.id) {\n <ngx-dynamic-field\n [field]=\"child\"\n [control]=\"inlineRowForm!.get(child.id)!\"\n [config]=\"config\"\n [language]=\"language\"\n [readonly]=\"false\"\n [userRoles]=\"userRoles\"\n [style.gridColumn]=\"'span 12'\"\n />\n }\n </div>\n\n <div class=\"ngx-record-editor__section-bar\">\n <button type=\"button\" class=\"ngx-form__reset\" data-testid=\"cancel-row\" (click)=\"cancelRow()\">\n {{ ui.text('cancel', language) }}\n </button>\n <button type=\"button\" class=\"ngx-form__submit\" data-testid=\"save-row\" (click)=\"saveRow()\">\n {{ ui.text('saveRow', language) }}\n </button>\n </div>\n </div>\n }\n\n <!-- Main Dynamic Form -->\n <ngx-dynamic-form\n [config]=\"config\"\n [rules]=\"rules\"\n [initialData]=\"initialData\"\n [originalData]=\"originalBaseline()\"\n [userRoles]=\"userRoles\"\n [language]=\"language\"\n [readonly]=\"sectionReadOnly\"\n [readOnlyFields]=\"readOnlyFields\"\n [layout]=\"layout\"\n [showInfoBanners]=\"false\"\n [loading]=\"loading\"\n [error]=\"error\"\n (formChange)=\"onFormChange($event)\"\n (formSubmit)=\"onFormSubmit($event)\"\n (saveRejected)=\"saveRejected.emit($event)\"\n (formReset)=\"onFormReset()\"\n (activeTabChange)=\"onActiveTabChange($event)\"\n />\n</div>\n","/**\n * import-contracts.ts — the two seams the import wizard hangs on.\n *\n * Both follow the pattern the rest of this package already uses for anything the library\n * cannot decide for a consumer — `FileUploadHandler`, `EntityReferenceLoader`,\n * `LookupListLoader`: a function type here, a token to register it against, and a default\n * that works without registering anything.\n *\n * **Why two rather than one.** Reading a file and deciding where the work happens are\n * different questions with different answers. A consumer may want `.xlsx` support in a\n * wizard that still runs entirely in the browser, or plain CSV that is nonetheless processed\n * on a server because their files have fifty thousand rows. Collapsing them into one option\n * would make each answer imply the other.\n */\n\nimport type {\n EntityFormConfig,\n FormRule,\n ImportLookups,\n ImportResult,\n MappingPlan,\n SheetData,\n TemplateSpec,\n} from '@dynamic-entity/core';\n\n/**\n * Reads an uploaded file into headers and positional rows.\n *\n * Positional (`string[][]`), not keyed by header, because a real sheet carries duplicate\n * headers and blank ones — and because a mapping entry addresses a column by index for\n * exactly that reason. A parser that returned objects keyed by header would silently lose\n * the second of two columns both called \"Notes\".\n *\n * The library ships a CSV implementation and no more. Registering one that understands\n * `.xlsx` is how a consumer adds it, and which spreadsheet library they use stays their\n * choice — this package has no runtime dependency and gains none here.\n *\n * @example\n * provideNgxDynamicEntity({\n * sheetParser: async file => {\n * const workbook = XLSX.read(await file.arrayBuffer());\n * const rows = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]], {\n * header: 1, raw: false, defval: '',\n * }) as string[][];\n * return { headers: rows[0] ?? [], rows: rows.slice(1) };\n * },\n * })\n */\nexport type SheetParser = (file: File) => SheetData | Promise<SheetData>;\n\n/** The formats a generated template can be written in. CSV needs no dependency. */\nexport type TemplateFormat = 'csv' | 'xlsx';\n\n/** What the wizard needs to know about the entity it is importing into. */\nexport interface ImportContext {\n config: EntityFormConfig;\n /**\n * Rules that apply to this entity.\n *\n * Without them an import checks field validators only, which is **not** what the form\n * enforces: a rule can attach an error, and a rule can hide a field, which must relax\n * `required`. Pass the same rules the form is rendered with or the two disagree.\n */\n rules?: readonly FormRule[];\n /** Values for any `listName` field, already resolved — core cannot reach `LOOKUP_REGISTRY`. */\n lookups?: ImportLookups;\n lang?: string;\n}\n\n/** What a first look at an uploaded file yields. */\nexport interface ImportPreview {\n headers: string[];\n /** The first few rows, for the mapping screen to show under each column. */\n sample: string[][];\n /** Where the suggester got to. Every inferred match is tagged `guess`. */\n suggestion: MappingPlan;\n /** Total data rows in the file, which may be far more than `sample` holds. */\n rowCount: number;\n}\n\n/**\n * Where the work happens.\n *\n * The default implementation does everything in the browser with `@dynamic-entity/core` and\n * never touches the network, so the wizard is fully usable with no backend at all. Register\n * an implementation that posts to a server and the same components drive it instead — the\n * engine underneath is the same code either way, which is the point of it being pure.\n *\n * This is the real answer to \"should parsing happen on the client or the server?\": both,\n * chosen at registration, without a second implementation of the mapping rules.\n */\nexport interface ImportTransport {\n /** Headers, a sample, and a suggested mapping for a freshly chosen file. */\n preview(file: File, context: ImportContext): Promise<ImportPreview>;\n /** Apply a plan to the whole file. */\n commit(file: File, plan: MappingPlan, context: ImportContext): Promise<ImportResult>;\n /**\n * Render a template for download.\n *\n * `fields` is the selection the user actually made — refs with row numbers stripped, one per\n * choice — and `spec` is that selection already expanded against the config. A transport that\n * renders locally wants the spec; one that asks a server wants the selection, because the\n * server has the config and only the choice needs to cross the wire. Passing both means\n * neither has to reconstruct the other: the HTTP transport used to recover the selection from\n * the expanded spec, which worked only because `stripIndices` happens to be exactly the\n * inverse of the expansion. Optional, so an existing implementation keeps compiling.\n */\n template(\n spec: TemplateSpec,\n format: TemplateFormat,\n context: ImportContext,\n fields?: readonly string[],\n ): Promise<Blob>;\n}\n","/**\n * sheet-parser.ts — the built-in CSV reader, and the reason it is the only one.\n *\n * CSV is what every spreadsheet tool exports and what a text editor can produce, and\n * `@dynamic-entity/core` parses it with no dependency. Shipping that as the default means the\n * import wizard works on a fresh `npm install` with nothing registered — `SHEET_PARSER` then\n * exists for the consumer who *also* wants `.xlsx`, rather than for the consumer who wants\n * the feature to work at all.\n *\n * The alternative was a hard dependency on a spreadsheet library in a package that currently\n * has none, for a file format many consumers will never see.\n */\n\nimport { parseCsv, type SheetData } from '@dynamic-entity/core';\nimport type { SheetParser } from './import-contracts';\n\n/** Extensions the built-in parser will attempt. */\nconst TEXT_EXTENSIONS = /\\.(csv|tsv|txt)$/i;\n\n/**\n * Read a text file as CSV.\n *\n * A binary workbook is refused by name rather than attempted: `.xlsx` is a zip, so reading it\n * as text yields a header row of mojibake and a mapping screen full of nonsense, which is a\n * much harder thing to diagnose than being told the format is not supported.\n */\nexport const defaultSheetParser: SheetParser = async (file: File): Promise<SheetData> => {\n if (file?.name && !TEXT_EXTENSIONS.test(file.name)) {\n throw new Error(\n `Cannot read \"${file.name}\". The built-in parser handles CSV only — register a ` +\n 'sheetParser with provideNgxDynamicEntity({ sheetParser }) to accept other formats.',\n );\n }\n return parseCsv(await file.text());\n};\n","/**\n * local-import-transport.ts — the whole import, in the browser, with no server.\n *\n * This is the default `IMPORT_TRANSPORT`, and it is a thin arrangement of pure functions\n * from `@dynamic-entity/core` rather than an implementation of anything. That matters: a\n * consumer who later registers a server transport is not switching to a second set of\n * mapping rules, they are moving the same ones to a different machine.\n *\n * Its limit is the one every browser has — the file is read into memory whole. That is fine\n * for the sizes a person assembles by hand and wrong for a fifty-thousand-row export, which\n * is what a streaming server transport is for.\n */\n\nimport { Injectable, inject } from '@angular/core';\nimport {\n applyMapping,\n deriveImportColumns,\n suggestMapping,\n toCsv,\n type ImportResult,\n type MappingPlan,\n type SheetData,\n type TemplateSpec,\n} from '@dynamic-entity/core';\nimport { SHEET_PARSER } from '../tokens/injection-tokens';\nimport { defaultSheetParser } from './sheet-parser';\nimport type {\n ImportContext,\n ImportPreview,\n ImportTransport,\n TemplateFormat,\n} from './import-contracts';\n\n/** How many rows the mapping screen shows under each column. */\nconst SAMPLE_ROWS = 5;\n\n@Injectable({ providedIn: 'root' })\nexport class LocalImportTransport implements ImportTransport {\n private readonly registered = inject(SHEET_PARSER, { optional: true });\n\n /**\n * One parse per file, not one per call.\n *\n * A wizard run reads the same file twice — once to show its headers, once to import it —\n * and this is the transport whose stated limit is that it holds the file in memory. Doing\n * the work twice doubled both the parse and the peak memory of the one implementation that\n * can least afford it.\n *\n * A `WeakMap` keyed on the `File` itself: the entry lives exactly as long as something\n * still holds the file, so choosing a different file drops the old sheet without anything\n * having to remember to. Keying on a name or a size would collide between two files a user\n * picked in sequence.\n */\n private readonly parsed = new WeakMap<File, Promise<SheetData>>();\n\n /** The registered parser, or the built-in CSV one. */\n private read(file: File): Promise<SheetData> {\n const cached = this.parsed.get(file);\n if (cached) return cached;\n\n // The *promise* is cached, not its result, so two calls that overlap share one parse\n // rather than starting a second before the first resolves.\n const pending = Promise.resolve((this.registered ?? defaultSheetParser)(file));\n this.parsed.set(file, pending);\n // A failed parse must not be remembered: the user may fix the file and pick it again.\n pending.catch(() => this.parsed.delete(file));\n return pending;\n }\n\n async preview(file: File, context: ImportContext): Promise<ImportPreview> {\n const sheet = await this.read(file);\n const { columns } = deriveImportColumns(context.config, { lang: context.lang });\n\n return {\n headers: sheet.headers,\n sample: sheet.rows.slice(0, SAMPLE_ROWS),\n rowCount: sheet.rows.length,\n suggestion: suggestMapping(sheet.headers, columns, context.config?.entity ?? ''),\n };\n }\n\n async commit(file: File, plan: MappingPlan, context: ImportContext): Promise<ImportResult> {\n const sheet = await this.read(file);\n return applyMapping(sheet.rows, plan, context.config, {\n lang: context.lang,\n rules: context.rules,\n lookups: context.lookups,\n });\n }\n\n async template(spec: TemplateSpec, format: TemplateFormat): Promise<Blob> {\n if (format === 'xlsx') {\n // Deliberately not a silent fallback to CSV. A file named `.xlsx` that is really CSV\n // opens with a warning in Excel and imports wrongly elsewhere, and the consumer would\n // have no idea why — where this message says exactly which seam to fill.\n throw new Error(\n 'This build can only write CSV templates. Register an IMPORT_TRANSPORT that writes ' +\n 'xlsx — see provideNgxDynamicEntity({ importTransport }) — or request csv.',\n );\n }\n\n // Headers only, and `spec.notes` deliberately left out of the file.\n //\n // A guidance row under the headers reads well and breaks the round trip: CSV has one\n // header row and no concept of a second, so re-importing the template the user filled in\n // would treat the guidance as a record and report a failed row 2 on every single import.\n // The notes are shown beside each column in the picker instead, where they can be read\n // without being parsed. A format with somewhere to put them — an xlsx cell comment, a\n // second sheet — can carry them; CSV has nowhere that is not data.\n const csv = toCsv(spec.columns.map(column => column.header));\n return new Blob([csv], { type: 'text/csv;charset=utf-8' });\n }\n}\n\n","/**\n * http-import-transport.ts — the same wizard, with the work happening on a server.\n *\n * The components do not change at all: they already talk to an `ImportTransport`, which was\n * the point of the seam. Registering this one moves the mapping, coercion and validation from\n * the tab to a server that runs the *same* `@dynamic-entity/core` functions — so the reason to\n * do it is size, not behaviour.\n *\n * **Built on `fetch`, not `HttpClient`.** This package has no `@angular/common/http` dependency\n * today, and four requests is not the reason to acquire one — a consumer who wants interceptors\n * passes their own `fetch`, which is a smaller seam than a dependency.\n */\n\nimport {\n CORE_VERSION,\n deriveImportColumns,\n stripIndices,\n type ImportCommitResponse,\n type ImportErrorResponse,\n type ImportPreviewResponse,\n type ImportResult,\n type MappingPlan,\n type TemplateSpec,\n} from '@dynamic-entity/core';\nimport type { Provider } from '@angular/core';\nimport { IMPORT_TRANSPORT } from '../tokens/injection-tokens';\nimport type {\n ImportContext,\n ImportPreview,\n ImportTransport,\n TemplateFormat,\n} from './import-contracts';\n\nexport interface HttpImportTransportOptions {\n /** Where the router is mounted, e.g. `/api/import`. A trailing slash is ignored. */\n baseUrl: string;\n /** Supply one to add interceptors, retries, or credentials. Defaults to the global `fetch`. */\n fetch?: typeof fetch;\n /** Headers on every request — an `Authorization`, a tenant id. Never a `Content-Type`. */\n headers?: Record<string, string> | (() => Record<string, string>);\n /**\n * Where a warning goes. Defaults to `console.warn`.\n *\n * There is exactly one warning, and it is the engine-version mismatch below — which is a\n * developer's problem, not a user's, so it does not belong in the wizard's error banner.\n */\n warn?: (message: string) => void;\n}\n\n/** `Content-Type` is deliberately not settable: `fetch` must set the multipart boundary. */\nfunction resolveHeaders(options: HttpImportTransportOptions): Record<string, string> {\n const headers = typeof options.headers === 'function' ? options.headers() : options.headers ?? {};\n const out: Record<string, string> = {};\n for (const [name, value] of Object.entries(headers)) {\n if (name.toLowerCase() === 'content-type') continue;\n out[name] = value;\n }\n return out;\n}\n\nconst trimSlash = (url: string): string => String(url ?? '').replace(/\\/+$/, '');\n\n/** Same major and minor. Two engines a patch apart are the same engine. */\nfunction sameLine(a: string, b: string): boolean {\n const line = (version: string): string => version.split('.').slice(0, 2).join('.');\n return line(a) === line(b);\n}\n\n/**\n * Turn a failed response into an `Error` the wizard can show.\n *\n * The server's envelope carries a code and a message it wrote itself; anything else — a proxy's\n * HTML error page, a network failure — has no message worth showing, so a status line is what\n * the user gets rather than a page of markup.\n */\nasync function failureOf(response: Response): Promise<Error> {\n let body: ImportErrorResponse | undefined;\n try {\n body = (await response.json()) as ImportErrorResponse;\n } catch {\n /* not our envelope */\n }\n const message = body?.error?.message;\n return new Error(message || `The import server answered ${response.status}.`);\n}\n\n/**\n * The field selection, as short as it can be said without changing what it means.\n *\n * Two reductions, and both are exact rather than approximate:\n *\n * - **Row numbers come off.** `buildTemplateSpec` matches a column by its ref *or* by its ref\n * with indices stripped, and the picker that produced this selection worked in stripped refs\n * to begin with — so `contacts.0.email, contacts.1.email, contacts.2.email` is the expansion\n * of one choice, and collapsing it back recovers exactly what the user ticked.\n * - **A full selection is sent as no selection at all**, because omitting `fields` already\n * means every column.\n *\n * Without them a wide config produced a query string of ten kilobytes or more — past the eight\n * nginx and Node default to — and the request most likely to hit it is \"give me a template with\n * everything\", which is the one this now sends as a bare `?format=`.\n */\nfunction selectionOf(\n spec: TemplateSpec,\n context: ImportContext,\n fields?: readonly string[],\n): string {\n // The caller's own selection when it gave one — the wizard does — and the expanded spec\n // reduced back to it otherwise, for a host calling `template` directly.\n const chosen = new Set(fields ?? spec.columns.map(column => stripIndices(column.ref)));\n const all = new Set(\n deriveImportColumns(context?.config, { lang: context?.lang }).columns.map(column =>\n stripIndices(column.ref),\n ),\n );\n\n if (all.size && chosen.size === all.size && [...all].every(ref => chosen.has(ref))) return '';\n return [...chosen].join(',');\n}\n\n/**\n * Not `@Injectable`, and registered by value rather than by class.\n *\n * Its constructor takes options rather than dependencies, so there is nothing for an injector\n * to resolve — and a consumer who wants two of them, pointed at two backends, gets that for\n * free.\n */\nclass HttpImportTransport implements ImportTransport {\n constructor(private readonly options: HttpImportTransportOptions) {}\n\n private get base(): string {\n return trimSlash(this.options.baseUrl);\n }\n\n private get send(): typeof fetch {\n // Bound rather than referenced: a bare `globalThis.fetch` passed around as a value throws\n // \"Illegal invocation\" in a browser, because it needs `window` as its receiver.\n return this.options.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n private entityOf(context: ImportContext): string {\n return encodeURIComponent(context?.config?.entity ?? '');\n }\n\n /**\n * Warn when the server's engine is not the one this bundle was built against.\n *\n * The two halves are separately deployed and may differ. `MappingPlan.configVersion` catches\n * *config* drift and says nothing about *engine* drift, so \"one engine, both sides\" is only\n * true if something checks — and this is the something. A warning rather than a refusal: a\n * patch release is not a reason to stop somebody importing.\n */\n private checkEngine(version: string | undefined): void {\n // Compared at major.minor. A patch difference between two deploys is the normal state of\n // a rolling release and says nothing about whether the engines agree; warning on it puts a\n // line in the console on every preview and every commit, which is how people learn to\n // scroll past the warning that does matter.\n if (!version || sameLine(version, CORE_VERSION)) return;\n const warn = this.options.warn ?? ((message: string) => console.warn(message));\n warn(\n `[ngx-dynamic-entity] The import server runs @dynamic-entity/core ${version}; this app ` +\n `was built against ${CORE_VERSION}. The two halves of an import are supposed to be the ` +\n 'same engine — bring them into step before trusting a difference in what they produce.',\n );\n }\n\n async preview(file: File, context: ImportContext): Promise<ImportPreview> {\n const body = new FormData();\n body.append('file', file, file.name || 'upload');\n\n const response = await this.send(`${this.base}/${this.entityOf(context)}/preview`, {\n method: 'POST',\n headers: resolveHeaders(this.options),\n body,\n });\n if (!response.ok) throw await failureOf(response);\n\n const preview = (await response.json()) as ImportPreviewResponse;\n this.checkEngine(preview.engineVersion);\n\n return {\n headers: preview.headers ?? [],\n sample: preview.sample ?? [],\n suggestion: preview.suggestion,\n rowCount: preview.rowCount ?? 0,\n };\n }\n\n async commit(file: File, plan: MappingPlan, context: ImportContext): Promise<ImportResult> {\n const body = new FormData();\n // **The plan first, and the file second.** The server starts importing while the file is\n // still arriving — that is the whole reason it exists — so the plan has to have arrived\n // already. `FormData` preserves append order, so this ordering is the contract.\n body.append('plan', JSON.stringify(plan));\n body.append('file', file, file.name || 'upload');\n\n const response = await this.send(`${this.base}/${this.entityOf(context)}/import`, {\n method: 'POST',\n headers: resolveHeaders(this.options),\n body,\n });\n if (!response.ok) throw await failureOf(response);\n\n const result = (await response.json()) as ImportCommitResponse;\n this.checkEngine(result.engineVersion);\n\n return {\n // Empty, and not because nothing was imported. The server streamed the file precisely so\n // that fifty thousand records never had to exist at once; sending them back would undo\n // that on the way out. `imported` is the count, and the records are in the consumer's\n // database.\n records: [],\n imported: result.imported ?? 0,\n skipped: result.skipped ?? 0,\n failed: result.failed ?? 0,\n errors: result.errors ?? [],\n errorCount: result.errorCount ?? result.errors?.length ?? 0,\n truncated: result.truncated ?? false,\n planProblems: result.planProblems ?? [],\n };\n }\n\n async template(\n spec: TemplateSpec,\n format: TemplateFormat,\n context: ImportContext,\n fields?: readonly string[],\n ): Promise<Blob> {\n // The server rebuilds the spec from its own config; only the selection crosses the wire.\n // Posting a whole spec would let a client choose the headers of a file the server signs\n // its name to, and the server has the config anyway.\n const query = new URLSearchParams({ format });\n const selection = selectionOf(spec, context, fields);\n if (selection) query.set('fields', selection);\n\n const response = await this.send(\n `${this.base}/${this.entityOf(context)}/template?${query.toString()}`,\n { method: 'GET', headers: resolveHeaders(this.options) },\n );\n if (!response.ok) throw await failureOf(response);\n return response.blob();\n }\n}\n\n/**\n * Register the HTTP transport.\n *\n * ```ts\n * provideNgxDynamicEntity({}),\n * provideHttpImportTransport({ baseUrl: '/api/import' }),\n * ```\n *\n * A plain `Provider` rather than `EnvironmentProviders`, so it composes inside a component's\n * or a route's `providers` array as well as at the root — which is how a consumer points one\n * part of an app at a different backend.\n */\nexport function provideHttpImportTransport(options: HttpImportTransportOptions): Provider {\n return { provide: IMPORT_TRANSPORT, useValue: new HttpImportTransport(options) };\n}\n\n/** Exported for a consumer who wants to subclass or wrap it; most should use the provider. */\nexport { HttpImportTransport };\n","import { ChangeDetectionStrategy, Component, Input, inject } from '@angular/core';\nimport type { ImportRowError } from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\n\n/**\n * The rows an import could not take, and why.\n *\n * Grouped by row rather than listed flat: a row with four problems is one row to go and fix,\n * and four separate lines invite the reader to think there are four. The row number is the\n * one the spreadsheet shows in its gutter — header counted as row 1 — because that is the\n * number they will scroll to.\n */\n@Component({\n selector: 'ngx-import-errors',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [],\n template: `\n @if (errors.length) {\n <section class=\"ngx-import-errors\" data-testid=\"import-errors\">\n <h4 class=\"ngx-import-errors__heading\">{{ ui.text('importErrorsHeading', language) }}</h4>\n <table class=\"ngx-import-errors__table\">\n <thead>\n <tr>\n <th scope=\"col\">{{ ui.text('importErrorRow', language, { row: '#' }) }}</th>\n <th scope=\"col\">{{ ui.text('importErrorField', language) }}</th>\n <th scope=\"col\">{{ ui.text('importErrorReason', language) }}</th>\n </tr>\n </thead>\n <tbody>\n @for (group of grouped(); track group.row) {\n @for (problem of group.problems; track $index) {\n <tr [attr.data-testid]=\"'import-error-row-' + group.row\">\n @if ($first) {\n <th scope=\"row\" [attr.rowspan]=\"group.problems.length\">\n {{ ui.text('importErrorRow', language, { row: group.row }) }}\n </th>\n }\n <td>{{ problem.ref }}</td>\n <td>{{ problem.message }}</td>\n </tr>\n }\n }\n </tbody>\n </table>\n </section>\n }\n `,\n styles: [\n `\n .ngx-import-errors__heading {\n margin: 0 0 8px;\n font-size: var(--ngx-font-size, 14px);\n color: var(--ngx-color-error, #b91c1c);\n }\n .ngx-import-errors__table {\n width: 100%;\n border-collapse: collapse;\n }\n .ngx-import-errors__table th,\n .ngx-import-errors__table td {\n text-align: left;\n padding: 6px 10px;\n border-bottom: 1px solid var(--ngx-color-border, #e5e7eb);\n vertical-align: top;\n }\n .ngx-import-errors__table thead th {\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-import-errors__table tbody th {\n white-space: nowrap;\n color: var(--ngx-color-error, #b91c1c);\n }\n `,\n ],\n})\nexport class ImportErrorsComponent {\n @Input() errors: readonly ImportRowError[] = [];\n @Input() language = 'en';\n\n protected readonly ui = inject(UiTextService);\n\n /** Row number → its problems, in the order the rows appear in the file. */\n protected grouped(): { row: number; problems: ImportRowError[] }[] {\n const byRow = new Map<number, ImportRowError[]>();\n for (const error of this.errors) {\n const list = byRow.get(error.row) ?? [];\n list.push(error);\n byRow.set(error.row, list);\n }\n return [...byRow.entries()]\n .sort((a, b) => a[0] - b[0])\n .map(([row, problems]) => ({ row, problems }));\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n OnChanges,\n Output,\n inject,\n signal,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n deriveImportColumns,\n type EntityFormConfig,\n type ImportColumn,\n type MappingEntry,\n type MappingPlan,\n} from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\n\n/** One target field, and which of the sheet's columns feeds it. */\ninterface MappingRow {\n column: ImportColumn;\n /** Index into the sheet's headers, or `null` for \"not imported\". */\n source: number | null;\n guessed: boolean;\n}\n\n/**\n * Match the sheet's columns to the config's fields.\n *\n * The table is driven by the **target fields**, not by the sheet's columns, which is the\n * choice that decides how the screen reads. A user is answering \"where does Start Date come\n * from?\", which they can do; column-first would ask \"what is column G?\", which they often\n * cannot, and would make a sheet with forty irrelevant columns forty questions long.\n *\n * A selection is a **column index**, never header text. Two columns headed \"Notes\" are two\n * different answers, and text cannot tell them apart.\n */\n@Component({\n selector: 'ngx-import-mapper',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FormsModule],\n template: `\n <section class=\"ngx-import-mapper\" data-testid=\"import-mapper\">\n <p class=\"ngx-import-mapper__summary\" data-testid=\"import-mapped-count\">\n {{ ui.text('importMappedCount', language, { mapped: mappedCount(), total: rows().length }) }}\n </p>\n @if (missingRequired() > 0) {\n <p class=\"ngx-import-mapper__warning\" data-testid=\"import-required-unmapped\" role=\"status\">\n {{ ui.text('importRequiredUnmapped', language, { count: missingRequired() }) }}\n </p>\n }\n @if (unsupported() > 0) {\n <p class=\"ngx-import-mapper__note\" data-testid=\"import-mapper-unsupported\">\n {{ ui.text('importTemplateUnsupported', language, { count: unsupported() }) }}\n </p>\n }\n\n <table class=\"ngx-import-mapper__table\">\n <thead>\n <tr>\n <th scope=\"col\">{{ ui.text('importTargetField', language) }}</th>\n <th scope=\"col\">{{ ui.text('importColumnInFile', language) }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.column.ref) {\n <tr [attr.data-testid]=\"'import-map-' + row.column.ref\">\n <th scope=\"row\">\n {{ row.column.header }}\n @if (row.column.required) {\n <span class=\"ngx-import-mapper__required\" aria-hidden=\"true\">*</span>\n }\n </th>\n <td>\n <select\n class=\"ngx-import-mapper__select\"\n [attr.data-testid]=\"'import-select-' + row.column.ref\"\n [attr.aria-label]=\"row.column.header\"\n [ngModel]=\"row.source\"\n (ngModelChange)=\"choose(row, $event)\"\n >\n <option [ngValue]=\"null\">{{ ui.text('importUnmapped', language) }}</option>\n @for (header of headers; track $index) {\n <option [ngValue]=\"$index\">{{ header || '—' }}</option>\n }\n </select>\n @if (row.guessed && row.source !== null) {\n <span class=\"ngx-import-mapper__guess\" [attr.data-testid]=\"'import-guess-' + row.column.ref\">\n {{ ui.text('importGuessed', language) }}\n </span>\n }\n </td>\n </tr>\n }\n </tbody>\n </table>\n </section>\n `,\n styles: [\n `\n .ngx-import-mapper__summary,\n .ngx-import-mapper__warning,\n .ngx-import-mapper__note {\n margin: 0 0 10px;\n }\n .ngx-import-mapper__warning {\n color: var(--ngx-color-warning, #b45309);\n background: var(--ngx-color-warning-soft, #fffbeb);\n border: 1px solid var(--ngx-color-border, #fef3c7);\n border-radius: var(--ngx-radius-sm, 6px);\n padding: 8px 12px;\n }\n .ngx-import-mapper__note {\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-import-mapper__table {\n width: 100%;\n border-collapse: collapse;\n }\n .ngx-import-mapper__table th,\n .ngx-import-mapper__table td {\n text-align: left;\n padding: 8px 10px;\n border-bottom: 1px solid var(--ngx-color-border, #e5e7eb);\n vertical-align: middle;\n }\n .ngx-import-mapper__table thead th {\n color: var(--ngx-color-muted, #6b7280);\n font-size: var(--ngx-font-size, 13px);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n }\n .ngx-import-mapper__required {\n color: var(--ngx-color-error, #b91c1c);\n margin-left: 2px;\n }\n .ngx-import-mapper__select {\n min-width: 220px;\n max-width: 100%;\n padding: 6px 8px;\n border: 1px solid var(--ngx-color-border, #d1d5db);\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-surface, #ffffff);\n color: inherit;\n font: inherit;\n }\n .ngx-import-mapper__guess {\n margin-left: 8px;\n padding: 2px 8px;\n border-radius: 999px;\n font-size: 12px;\n color: var(--ngx-color-info, #1d4ed8);\n background: var(--ngx-color-info-soft, #eff6ff);\n }\n @media (max-width: 640px) {\n .ngx-import-mapper__select {\n min-width: 0;\n width: 100%;\n }\n }\n `,\n ],\n})\nexport class ImportMapperComponent implements OnChanges {\n @Input({ required: true }) config!: EntityFormConfig;\n @Input() headers: readonly string[] = [];\n /** The starting point, normally `suggestMapping`'s output. */\n @Input() plan: MappingPlan | null = null;\n @Input() language = 'en';\n\n /** Emitted whenever the user changes a selection. */\n @Output() readonly planChange = new EventEmitter<MappingPlan>();\n\n protected readonly ui = inject(UiTextService);\n protected readonly rows = signal<MappingRow[]>([]);\n /**\n * How many fields a spreadsheet cannot carry at all.\n *\n * Shown here as well as in the template picker, because a user who already had a sheet\n * skipped that screen — and this is the only place they would otherwise find out that an\n * attachment column was never going to arrive.\n */\n protected readonly unsupported = signal(0);\n\n ngOnChanges(): void {\n const { columns, unsupported } = deriveImportColumns(this.config, { lang: this.language });\n this.unsupported.set(unsupported.length);\n const byRef = new Map((this.plan?.entries ?? []).map(entry => [entry.ref, entry]));\n\n this.rows.set(\n columns.map(column => {\n const entry = byRef.get(column.ref);\n return {\n column,\n source: entry?.column ?? null,\n guessed: entry?.confidence === 'guess',\n };\n }),\n );\n }\n\n protected mappedCount(): number {\n return this.rows().filter(row => row.source !== null).length;\n }\n\n protected missingRequired(): number {\n return this.rows().filter(row => row.column.required && row.source === null).length;\n }\n\n protected choose(row: MappingRow, source: number | null): void {\n this.rows.update(rows =>\n rows.map(candidate =>\n candidate.column.ref === row.column.ref\n ? // A hand-made choice is not a guess any more, so the badge goes.\n { ...candidate, source, guessed: false }\n : candidate,\n ),\n );\n this.planChange.emit(this.toPlan());\n }\n\n /** The current selections as the plan that will be applied. */\n private toPlan(): MappingPlan {\n const entries: MappingEntry[] = this.rows()\n .filter(row => row.source !== null)\n .map(row => ({\n ref: row.column.ref,\n column: row.source as number,\n header: this.headers[row.source as number],\n confidence: row.guessed ? ('guess' as const) : ('exact' as const),\n }));\n\n return {\n entity: this.config?.entity ?? '',\n configVersion: this.config?.version,\n sourceHeaders: [...this.headers],\n entries,\n };\n }\n}\n","import { ChangeDetectionStrategy, Component, Input, OnChanges, inject, signal } from '@angular/core';\nimport {\n applyMapping,\n coerceCell,\n deriveImportColumns,\n formatDisplayValue,\n type EntityFormConfig,\n type FormRule,\n type ImportColumn,\n type ImportLookups,\n type MappingPlan,\n} from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\n\n/** One cell, already turned into the text the record will show. */\ninterface PreviewCell {\n text: string;\n failed: boolean;\n}\n\n/** A row of cells, plus why the import will refuse it — if it will. */\ninterface PreviewRow {\n cells: PreviewCell[];\n /** Empty when the row will be imported. */\n rejections: string[];\n}\n\n/**\n * The first few rows as the record will hold them, not as the sheet holds them.\n *\n * Every cell goes through the same `coerceCell` the import will use and then through\n * `formatDisplayValue`, which is what the renderer uses to show a stored value. So a\n * `dropdown` cell reading `Aktiv` shows as `Active` here if that is the option it resolved\n * to, and a cell that will fail shows its reason before anyone commits to anything.\n *\n * Showing the raw text instead would be easier and would preview the wrong thing: the point\n * of this screen is to catch a mapping that is subtly wrong, and a column of unchanged text\n * looks correct whatever field it was pointed at.\n *\n * **The rows are also run through the real import**, not just through coercion. `coerceCell`\n * alone catches a cell that will not parse and says nothing about a row that will be rejected\n * — a missing required field, a rule that forbids the combination — so a heading promising\n * \"as they will be saved\" was showing rows that would never be saved at all, looking exactly\n * like the ones that would. `applyMapping` over the sample answers that with the same engine\n * the commit uses, rather than a second opinion about what counts as valid.\n *\n * The whole grid is built once per input change rather than from template method calls.\n * Deriving the config's columns inside a `@for` means re-walking the entire schema for every\n * cell on every change-detection pass, which is a lot of work to produce five rows.\n */\n@Component({\n selector: 'ngx-import-preview',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [],\n template: `\n <section class=\"ngx-import-preview\" data-testid=\"import-preview\">\n <h4 class=\"ngx-import-preview__heading\">\n {{ ui.text('importPreviewHeading', language, { count: rows.length }) }}\n </h4>\n <div class=\"ngx-import-preview__scroll\">\n <table class=\"ngx-import-preview__table\">\n <thead>\n <tr>\n @for (column of columns(); track column.ref) {\n <th scope=\"col\">{{ column.header }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of grid(); track $index) {\n <tr\n [attr.data-testid]=\"'import-preview-row-' + $index\"\n [class.ngx-import-preview__row--rejected]=\"row.rejections.length\"\n >\n @for (cell of row.cells; track $index) {\n <td [class.ngx-import-preview__cell--error]=\"cell.failed\">{{ cell.text }}</td>\n }\n </tr>\n @if (row.rejections.length) {\n <tr class=\"ngx-import-preview__reason\">\n <td [attr.colspan]=\"columns().length\" [attr.data-testid]=\"'import-preview-rejected-' + $index\">\n {{ ui.text('importRowRejected', language, { reason: row.rejections.join('; ') }) }}\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n </section>\n `,\n styles: [\n `\n .ngx-import-preview__heading {\n margin: 0 0 8px;\n font-size: var(--ngx-font-size, 14px);\n }\n /* The one place a horizontal scrollbar belongs: a sheet can have forty columns. */\n .ngx-import-preview__scroll {\n overflow-x: auto;\n border: 1px solid var(--ngx-color-border, #e5e7eb);\n border-radius: var(--ngx-radius-sm, 6px);\n }\n .ngx-import-preview__table {\n width: 100%;\n border-collapse: collapse;\n white-space: nowrap;\n }\n .ngx-import-preview__table th,\n .ngx-import-preview__table td {\n text-align: left;\n padding: 6px 10px;\n border-bottom: 1px solid var(--ngx-color-border, #f3f4f6);\n }\n .ngx-import-preview__table thead th {\n background: var(--ngx-color-surface-alt, #f9fafb);\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-import-preview__cell--error {\n color: var(--ngx-color-error, #b91c1c);\n background: var(--ngx-color-error-soft, #fef2f2);\n }\n /* A row that will be refused is dimmed, and says why on the line beneath it. */\n .ngx-import-preview__row--rejected td {\n opacity: 0.65;\n }\n .ngx-import-preview__reason td {\n white-space: normal;\n color: var(--ngx-color-error, #b91c1c);\n background: var(--ngx-color-error-soft, #fef2f2);\n }\n `,\n ],\n})\nexport class ImportPreviewComponent implements OnChanges {\n @Input({ required: true }) config!: EntityFormConfig;\n @Input({ required: true }) plan!: MappingPlan;\n @Input() rows: readonly (readonly string[])[] = [];\n @Input() lookups?: ImportLookups;\n /** The same rules the commit will apply; without them a rule-driven rejection is invisible. */\n @Input() rules?: readonly FormRule[];\n @Input() language = 'en';\n\n protected readonly ui = inject(UiTextService);\n\n /** The columns this plan fills, in the plan's own order. */\n protected readonly columns = signal<ImportColumn[]>([]);\n protected readonly grid = signal<PreviewRow[]>([]);\n\n ngOnChanges(): void {\n const byRef = new Map(\n deriveImportColumns(this.config, { lang: this.language }).columns.map(c => [c.ref, c]),\n );\n\n const entries = (this.plan?.entries ?? []).filter(entry => byRef.has(entry.ref));\n this.columns.set(entries.map(entry => byRef.get(entry.ref)!));\n\n // The same engine the commit runs, over the sample only. Row 0 of the sample is numbered\n // 0 here rather than 2, because these row numbers index the preview, not the file.\n const dryRun = applyMapping(this.rows, this.plan, this.config, {\n lang: this.language,\n lookups: this.lookups,\n rules: this.rules,\n stamp: false,\n firstRowNumber: 0,\n });\n const rejectionsByRow = new Map<number, string[]>();\n for (const error of dryRun.errors) {\n rejectionsByRow.set(error.row, [...(rejectionsByRow.get(error.row) ?? []), error.message]);\n }\n\n this.grid.set(\n this.rows.map((row, index) => ({\n rejections: rejectionsByRow.get(index) ?? [],\n cells: entries.map(entry => {\n const field = byRef.get(entry.ref)!.field;\n const raw = entry.column === undefined ? entry.constant : row[entry.column];\n const outcome = coerceCell(field, raw, {\n lang: this.language,\n lookups: this.lookups,\n });\n\n if ('error' in outcome) return { text: outcome.error, failed: true };\n return {\n text: formatDisplayValue(field.type, field.options, outcome.value, this.language),\n failed: false,\n };\n }),\n })),\n );\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n OnChanges,\n Output,\n inject,\n signal,\n} from '@angular/core';\nimport {\n buildTemplateSpec,\n deriveImportColumns,\n stripIndices,\n type EntityFormConfig,\n type UnsupportedColumn,\n} from '@dynamic-entity/core';\nimport { UiTextService } from '../services/ui-text.service';\n\n/** One field offered for the template, with the guidance that belongs to it. */\ninterface TemplateChoice {\n /** The ref with any row number removed, so a repeating field is offered once. */\n ref: string;\n header: string;\n note: string;\n selected: boolean;\n}\n\n/**\n * Pick the fields a template should carry, then download it.\n *\n * The guidance for each field is shown **here**, beside the checkbox, rather than written\n * into the file as a second header row. CSV has one header row and no concept of a second,\n * so a guidance row inside the file would come back as a record on re-import and fail row 2\n * of every import the user ever ran.\n *\n * A repeating field is offered once, not once per row number: \"Contacts / Name\" is a decision,\n * and \"Contacts / Name 1\", \"Contacts / Name 2\", \"Contacts / Name 3\" is the same decision\n * asked three times.\n */\n@Component({\n selector: 'ngx-import-template',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [],\n template: `\n <section class=\"ngx-import-template\" data-testid=\"import-template\">\n <h4 class=\"ngx-import-template__heading\">{{ ui.text('importTemplateHeading', language) }}</h4>\n <p class=\"ngx-import-template__explain\">{{ ui.text('importTemplateExplain', language) }}</p>\n\n <div class=\"ngx-import-template__bulk\">\n <button type=\"button\" (click)=\"selectAll(true)\" data-testid=\"import-template-all\">\n {{ ui.text('importTemplateSelectAll', language) }}\n </button>\n <button type=\"button\" (click)=\"selectAll(false)\" data-testid=\"import-template-none\">\n {{ ui.text('importTemplateSelectNone', language) }}\n </button>\n </div>\n\n <ul class=\"ngx-import-template__list\">\n @for (choice of choices(); track choice.ref) {\n <li class=\"ngx-import-template__item\">\n <label>\n <input\n type=\"checkbox\"\n [checked]=\"choice.selected\"\n (change)=\"toggle(choice.ref)\"\n [attr.data-testid]=\"'import-template-field-' + choice.ref\"\n />\n <span class=\"ngx-import-template__label\">{{ choice.header }}</span>\n </label>\n @if (choice.note) {\n <span class=\"ngx-import-template__note\">{{ choice.note }}</span>\n }\n </li>\n }\n </ul>\n\n @if (unsupported().length) {\n <p class=\"ngx-import-template__unsupported\" data-testid=\"import-template-unsupported\">\n {{ ui.text('importTemplateUnsupported', language, { count: unsupported().length }) }}\n </p>\n }\n\n <button\n type=\"button\"\n class=\"ngx-import-template__download\"\n data-testid=\"import-template-download\"\n [disabled]=\"!selectedCount()\"\n (click)=\"download.emit(selectedRefs())\"\n >\n {{ ui.text('importTemplateDownload', language) }}\n </button>\n </section>\n `,\n styles: [\n `\n .ngx-import-template {\n padding: 14px;\n border: 1px solid var(--ngx-color-border, #e5e7eb);\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-surface-alt, #f9fafb);\n }\n .ngx-import-template__heading {\n margin: 0 0 4px;\n font-size: var(--ngx-font-size, 14px);\n }\n .ngx-import-template__explain {\n margin: 0 0 10px;\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-import-template__bulk {\n display: flex;\n gap: 8px;\n margin-bottom: 10px;\n }\n .ngx-import-template__list {\n list-style: none;\n margin: 0 0 10px;\n padding: 0;\n max-height: 240px;\n overflow-y: auto;\n display: grid;\n gap: 4px;\n }\n .ngx-import-template__item {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 8px;\n }\n .ngx-import-template__item label {\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n }\n .ngx-import-template__note {\n color: var(--ngx-color-muted, #6b7280);\n font-size: 12px;\n }\n .ngx-import-template__unsupported {\n margin: 0 0 10px;\n color: var(--ngx-color-muted, #6b7280);\n }\n .ngx-import-template button {\n padding: 6px 12px;\n border: 1px solid var(--ngx-color-border, #d1d5db);\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-surface, #ffffff);\n color: inherit;\n font: inherit;\n cursor: pointer;\n }\n .ngx-import-template button:disabled {\n opacity: 0.55;\n cursor: not-allowed;\n }\n `,\n ],\n})\nexport class ImportTemplateComponent implements OnChanges {\n @Input({ required: true }) config!: EntityFormConfig;\n @Input() language = 'en';\n\n /** The refs to include, with row numbers stripped — the caller builds the spec. */\n @Output() readonly download = new EventEmitter<string[]>();\n\n protected readonly ui = inject(UiTextService);\n protected readonly choices = signal<TemplateChoice[]>([]);\n protected readonly unsupported = signal<UnsupportedColumn[]>([]);\n\n ngOnChanges(): void {\n const spec = buildTemplateSpec(this.config, { lang: this.language });\n const derived = deriveImportColumns(this.config, { lang: this.language });\n\n // One entry per field, keyed on the ref with its row number removed, so a repeating\n // field collapses back into the single choice it is.\n const seen = new Map<string, TemplateChoice>();\n spec.columns.forEach((column, i) => {\n const ref = stripIndices(column.ref);\n if (seen.has(ref)) return;\n seen.set(ref, {\n ref,\n header: column.arrayIndex === undefined ? column.header : stripRowNumber(column.header),\n note: spec.notes[i] ?? '',\n selected: true,\n });\n });\n\n this.choices.set([...seen.values()]);\n this.unsupported.set(derived.unsupported);\n }\n\n protected selectedCount(): number {\n return this.choices().filter(choice => choice.selected).length;\n }\n\n protected selectedRefs(): string[] {\n return this.choices()\n .filter(choice => choice.selected)\n .map(choice => choice.ref);\n }\n\n protected toggle(ref: string): void {\n this.choices.update(choices =>\n choices.map(choice =>\n choice.ref === ref ? { ...choice, selected: !choice.selected } : choice,\n ),\n );\n }\n\n protected selectAll(selected: boolean): void {\n this.choices.update(choices => choices.map(choice => ({ ...choice, selected })));\n }\n}\n\n/** \"Contacts / Name 1\" → \"Contacts / Name\", for the collapsed choice. */\nfunction stripRowNumber(header: string): string {\n return header.replace(/ \\d+$/, '');\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n Output,\n inject,\n signal,\n} from '@angular/core';\nimport {\n buildTemplateSpec,\n collectLeafTargets,\n formatConfigProblems,\n type EntityFormConfig,\n type FormRule,\n type ImportLookups,\n type ImportResult,\n type MappingPlan,\n} from '@dynamic-entity/core';\nimport { IMPORT_TRANSPORT } from '../tokens/injection-tokens';\nimport { UiTextService } from '../services/ui-text.service';\nimport { LookupRegistryService } from '../services/lookup-registry.service';\nimport { LocalImportTransport } from './local-import-transport';\nimport { ImportErrorsComponent } from './import-errors.component';\nimport { ImportMapperComponent } from './import-mapper.component';\nimport { ImportPreviewComponent } from './import-preview.component';\nimport { ImportTemplateComponent } from './import-template.component';\nimport type { ImportContext, ImportTransport, TemplateFormat } from './import-contracts';\n\ntype Step = 'upload' | 'map' | 'review' | 'done';\n\n/**\n * The import wizard: choose a file, match its columns, look at what that produced, commit.\n *\n * It holds no import logic of its own. Everything it does goes through an `ImportTransport`,\n * which by default is the in-browser one built on `@dynamic-entity/core` — so the wizard\n * works with no backend, and a consumer who registers a server transport gets the same\n * screens over the same mapping rules rather than a second implementation of them.\n *\n * The review step exists because the expensive mistake here is not a file that fails to\n * import, it is one that imports *successfully into the wrong fields*. That is invisible in a\n * summary and obvious in five rendered rows.\n */\n@Component({\n selector: 'ngx-entity-import',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ImportTemplateComponent,\n ImportMapperComponent,\n ImportPreviewComponent,\n ImportErrorsComponent,\n ],\n template: `\n <div class=\"ngx-import\" data-testid=\"entity-import\">\n <ol class=\"ngx-import__steps\" data-testid=\"import-steps\">\n @for (name of steps; track name) {\n <li\n class=\"ngx-import__step\"\n [class.ngx-import__step--current]=\"step() === name\"\n [attr.aria-current]=\"step() === name ? 'step' : null\"\n [attr.data-testid]=\"'import-step-' + name\"\n >\n {{ stepLabel(name) }}\n </li>\n }\n </ol>\n\n @if (problem(); as text) {\n <p class=\"ngx-import__problem\" role=\"alert\" data-testid=\"import-problem\">{{ text }}</p>\n }\n\n @switch (step()) {\n @case ('upload') {\n <ngx-import-template\n [config]=\"config\"\n [language]=\"language\"\n (download)=\"downloadTemplate($event)\"\n />\n\n <label class=\"ngx-import__file\">\n <span>{{ ui.text('importChooseFile', language) }}</span>\n <input type=\"file\" data-testid=\"import-file\" (change)=\"chooseFile($event)\" />\n </label>\n\n @if (busy()) {\n <p data-testid=\"import-reading\">{{ ui.text('importReading', language) }}</p>\n }\n @if (fileName()) {\n <p data-testid=\"import-file-chosen\">\n {{ ui.text('importFileChosen', language, { name: fileName(), rows: rowCount() }) }}\n </p>\n }\n }\n\n @case ('map') {\n <ngx-import-mapper\n [config]=\"config\"\n [headers]=\"headers()\"\n [plan]=\"plan()\"\n [language]=\"language\"\n (planChange)=\"plan.set($event)\"\n />\n <button type=\"button\" data-testid=\"import-to-review\" (click)=\"step.set('review')\">\n {{ ui.text('importReview', language) }}\n </button>\n }\n\n @case ('review') {\n @if (plan(); as current) {\n <ngx-import-preview\n [config]=\"config\"\n [plan]=\"current\"\n [rows]=\"sample()\"\n [lookups]=\"resolvedLookups()\"\n [rules]=\"rules\"\n [language]=\"language\"\n />\n }\n <button\n type=\"button\"\n data-testid=\"import-commit\"\n [disabled]=\"busy()\"\n (click)=\"commit()\"\n >\n {{\n busy()\n ? ui.text('importImporting', language)\n : ui.text('importRunImport', language, { count: rowCount() })\n }}\n </button>\n <button type=\"button\" data-testid=\"import-back\" (click)=\"step.set('map')\">\n {{ ui.text('importMap', language) }}\n </button>\n }\n\n @case ('done') {\n @if (result(); as done) {\n <p data-testid=\"import-succeeded\">\n {{ ui.text('importSucceeded', language, { count: importedCount(done) }) }}\n </p>\n @if (done.skipped) {\n <p data-testid=\"import-skipped\">\n {{ ui.text('importSkippedRows', language, { count: done.skipped }) }}\n </p>\n }\n @if (failedRowCount(done)) {\n <p data-testid=\"import-failed\">\n {{ ui.text('importFailedRows', language, { count: failedRowCount(done) }) }}\n </p>\n }\n @if (done.truncated) {\n <p data-testid=\"import-errors-truncated\">\n {{\n ui.text('importErrorsTruncated', language, {\n shown: done.errors.length,\n count: done.errorCount ?? done.errors.length,\n })\n }}\n </p>\n }\n <ngx-import-errors [errors]=\"done.errors\" [language]=\"language\" />\n }\n <button type=\"button\" data-testid=\"import-restart\" (click)=\"restart()\">\n {{ ui.text('importStartOver', language) }}\n </button>\n }\n }\n </div>\n `,\n styles: [\n `\n .ngx-import {\n display: flex;\n flex-direction: column;\n gap: var(--ngx-gap, 16px);\n color: var(--ngx-color-text, #1f2937);\n font-size: var(--ngx-font-size, 14px);\n }\n .ngx-import__steps {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n list-style: none;\n margin: 0;\n padding: 0;\n }\n .ngx-import__step {\n padding: 4px 12px;\n border: 1px solid var(--ngx-color-border, #e5e7eb);\n border-radius: var(--ngx-radius-sm, 6px);\n color: var(--ngx-color-muted, #6b7280);\n background: var(--ngx-color-surface-alt, #f9fafb);\n }\n .ngx-import__step--current {\n color: var(--ngx-color-accent, #4f46e5);\n border-color: var(--ngx-color-accent, #4f46e5);\n background: var(--ngx-color-accent-soft, #e0e7ff);\n font-weight: 600;\n }\n .ngx-import__problem {\n margin: 0;\n padding: 10px 12px;\n border: 1px solid var(--ngx-color-border, #fecaca);\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-error-soft, #fef2f2);\n color: var(--ngx-color-error, #b91c1c);\n /* A parser message can be a whole sentence with a filename in it. */\n overflow-wrap: anywhere;\n }\n .ngx-import__file {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 14px;\n border: 1px dashed var(--ngx-color-border, #d1d5db);\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-surface, #ffffff);\n }\n .ngx-import button {\n align-self: flex-start;\n padding: 8px 16px;\n border: 1px solid var(--ngx-color-border, #d1d5db);\n border-radius: var(--ngx-radius-sm, 6px);\n background: var(--ngx-color-surface, #ffffff);\n color: inherit;\n font: inherit;\n cursor: pointer;\n }\n .ngx-import button:hover:not(:disabled) {\n border-color: var(--ngx-color-accent, #4f46e5);\n background: var(--ngx-color-accent-soft, #e0e7ff);\n }\n .ngx-import button:disabled {\n opacity: 0.55;\n cursor: not-allowed;\n }\n `,\n ],\n})\nexport class EntityImportComponent {\n @Input({ required: true }) config!: EntityFormConfig;\n /**\n * The rules the form is rendered with.\n *\n * Pass them, or the import checks field validators only — which is not what the form\n * enforces, and a required field hidden by a rule will fail every row.\n */\n @Input() rules?: readonly FormRule[];\n /**\n * Named lists, overriding what the wizard already resolves from `LOOKUP_REGISTRY`.\n *\n * Not something a host has to supply: every `listName` a config mentions is loaded from the\n * registry the renderer is already holding. Pass this only to override one.\n */\n @Input() lookups?: ImportLookups;\n @Input() language = 'en';\n /** Format asked of the transport when a template is downloaded. */\n @Input() templateFormat: TemplateFormat = 'csv';\n\n /** The finished import, once it has run. */\n @Output() readonly importComplete = new EventEmitter<ImportResult>();\n /** A template the transport produced, for a host that would rather save it its own way. */\n @Output() readonly templateReady = new EventEmitter<Blob>();\n\n protected readonly ui = inject(UiTextService);\n protected readonly steps: Step[] = ['upload', 'map', 'review', 'done'];\n\n protected readonly step = signal<Step>('upload');\n protected readonly busy = signal(false);\n protected readonly problem = signal<string | null>(null);\n protected readonly headers = signal<string[]>([]);\n protected readonly sample = signal<string[][]>([]);\n protected readonly rowCount = signal(0);\n protected readonly fileName = signal('');\n protected readonly plan = signal<MappingPlan | null>(null);\n protected readonly result = signal<ImportResult | null>(null);\n\n private readonly registered = inject(IMPORT_TRANSPORT, { optional: true });\n private readonly local = inject(LocalImportTransport);\n private readonly lookupRegistry = inject(LookupRegistryService);\n private file: File | null = null;\n\n /** Named lists resolved from `LOOKUP_REGISTRY`, merged under the `lookups` input. */\n protected readonly resolvedLookups = signal<ImportLookups>({});\n\n private get transport(): ImportTransport {\n return this.registered ?? this.local;\n }\n\n private context(): ImportContext {\n return {\n config: this.config,\n rules: this.rules,\n lookups: this.resolvedLookups(),\n lang: this.language,\n };\n }\n\n /**\n * Load every named list this config's fields refer to.\n *\n * `@dynamic-entity/core` is framework-agnostic and cannot reach `LOOKUP_REGISTRY`, so\n * `coerceCell` takes the values as an argument. That is a reason for *core* to ask, not a\n * reason for the host to be asked — this package is holding the registry, and making the\n * consumer re-supply what the library already has is how a `listName` column ends up\n * storing the raw text `\"Gold\"` instead of the option object. Such a record renders\n * correctly and then matches no rule, which is the exact failure the option-shape contract\n * exists to prevent.\n *\n * The `lookups` input still wins where it names a list, so a host can override one without\n * having to provide all of them.\n */\n private async loadLookups(): Promise<void> {\n const fromRegistry: ImportLookups = {};\n\n const names = new Set<string>();\n for (const target of collectLeafTargets(this.config)) {\n if (target.field.listName) names.add(target.field.listName);\n }\n\n for (const listName of names) {\n // A list that fails to load is not a reason to refuse the import: the field falls back\n // to passing its text through, which is what happens today for an unregistered list.\n try {\n const options = await this.lookupRegistry.resolveOptions(\n { id: listName, type: 'dropdown', label: {}, listName },\n this.language,\n );\n if (options.length) fromRegistry[listName] = options;\n } catch {\n /* left out, so the field passes its text through */\n }\n }\n\n this.resolvedLookups.set({ ...fromRegistry, ...(this.lookups ?? {}) });\n }\n\n protected stepLabel(step: Step): string {\n // One key per step rather than an index, so a translator sees words and not positions.\n const keys = {\n upload: 'importUpload',\n map: 'importMap',\n review: 'importReview',\n done: 'importDone',\n } as const;\n return this.ui.text(keys[step], this.language);\n }\n\n protected async chooseFile(event: Event): Promise<void> {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0] ?? null;\n if (!file) {\n this.problem.set(this.ui.text('importNeedFile', this.language));\n return;\n }\n\n this.problem.set(null);\n this.busy.set(true);\n\n try {\n await this.loadLookups();\n const preview = await this.transport.preview(file, this.context());\n // Assigned only once the file has been read: holding a file whose headers describe the\n // previous one is an invariant worth not having to reason about.\n this.file = file;\n this.fileName.set(file.name);\n this.headers.set(preview.headers);\n this.sample.set(preview.sample);\n this.rowCount.set(preview.rowCount);\n this.plan.set(preview.suggestion);\n this.step.set('map');\n } catch (error) {\n // A parser refusing a format, or a file that is not what it claims, is ordinary user\n // input rather than a defect — it is reported where the user is looking.\n this.problem.set(messageOf(error));\n } finally {\n this.busy.set(false);\n }\n }\n\n protected async commit(): Promise<void> {\n const plan = this.plan();\n if (!this.file || !plan) {\n this.problem.set(this.ui.text('importNeedFile', this.language));\n return;\n }\n\n this.busy.set(true);\n this.problem.set(null);\n\n try {\n const result = await this.transport.commit(this.file, plan, this.context());\n\n // A plan-level error means nothing was imported, and saying \"imported 0 records\" would\n // describe that as a successful run of an empty file.\n const fatal = result.planProblems?.filter(p => p.level === 'error') ?? [];\n if (fatal.length) {\n this.problem.set(\n this.ui.text('importPlanProblem', this.language, {\n message: formatConfigProblems(fatal),\n }),\n );\n this.step.set('map');\n return;\n }\n\n this.result.set(result);\n this.step.set('done');\n this.importComplete.emit(result);\n } catch (error) {\n this.problem.set(messageOf(error));\n } finally {\n this.busy.set(false);\n }\n }\n\n protected async downloadTemplate(fields: string[]): Promise<void> {\n this.problem.set(null);\n try {\n const spec = buildTemplateSpec(this.config, { lang: this.language, fields });\n // The selection as well as the spec. A server transport needs the choice, not the\n // expansion of it — and recovering one from the other is a round trip that only works\n // while the expansion stays exactly invertible.\n const blob = await this.transport.template(spec, this.templateFormat, this.context(), fields);\n this.templateReady.emit(blob);\n saveBlob(blob, `${this.config?.entity || 'import'}-template.${this.templateFormat}`);\n } catch (error) {\n this.problem.set(messageOf(error));\n }\n }\n\n /**\n * How many records were written.\n *\n * `records.length` for the in-browser transport, which returns every record it built, and\n * `imported` for a server one, which streamed the file precisely so that fifty thousand\n * records never had to exist at once and therefore has a number rather than a list. Reading\n * `records.length` alone would report a successful import of nothing.\n */\n protected importedCount(result: ImportResult): number {\n return result.imported ?? result.records.length;\n }\n\n /**\n * How many distinct rows failed, not how many problems they had between them.\n *\n * `failed` when the transport reports it, and the distinct rows in `errors` only when it does\n * not. Counting the errors alone was wrong the moment a transport started capping them: a run\n * of a thousand rows where two hundred failed said **seven**, because seven was how many\n * distinct rows fitted inside the first twenty retained problems. This is the number a user\n * acts on — which rows do I go and fix — so a confident wrong answer is the worst of the\n * available ones. The in-browser transport returns every error, so counting them there is\n * exact and `failed` is absent.\n */\n protected failedRowCount(result: ImportResult): number {\n return result.failed ?? new Set(result.errors.map(error => error.row)).size;\n }\n\n protected restart(): void {\n this.file = null;\n this.fileName.set('');\n this.headers.set([]);\n this.sample.set([]);\n this.rowCount.set(0);\n this.plan.set(null);\n this.result.set(null);\n this.problem.set(null);\n this.step.set('upload');\n }\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Hand a generated file to the browser.\n *\n * The object URL is revoked on the next turn rather than immediately: revoking it in the same\n * task can cancel the download that was just started, and the leak of waiting one tick is a\n * single URL.\n */\nfunction saveBlob(blob: Blob, filename: string): void {\n if (typeof document === 'undefined') return;\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = filename;\n anchor.style.display = 'none';\n document.body.appendChild(anchor);\n anchor.click();\n document.body.removeChild(anchor);\n setTimeout(() => URL.revokeObjectURL(url));\n}\n","// Tokens\nexport * from './lib/tokens/injection-tokens';\n\n// Providers\nexport * from './lib/providers/provide-ngx-dynamic-entity';\nexport * from './lib/providers/provide-field-types';\n\n// Services\nexport * from './lib/services/field-registry.service';\nexport * from './lib/services/hook-registry.service';\nexport * from './lib/services/validator-registry.service';\nexport * from './lib/services/entity-ref-registry.service';\nexport * from './lib/services/entity-ref-selection.service';\nexport * from './lib/services/cascade-data.service';\nexport * from './lib/services/entity-reference.service';\nexport * from './lib/services/entity-ref-cache';\nexport * from './lib/services/lookup-registry.service';\nexport * from './lib/services/rbac.service';\nexport * from './lib/services/rules-evaluation.service';\nexport * from './lib/services/config-source.service';\nexport * from './lib/services/validation-messages.service';\nexport * from './lib/services/ui-text.service';\n\n// Components — the library ships form UI only; rendering a data table is the consumer's choice.\nexport * from './lib/form/dynamic-form.component';\nexport * from './lib/form/dynamic-record-form.component';\nexport * from './lib/form/dynamic-field/dynamic-field.component';\n\n// Import wizard — the shell, and each screen individually, same reusability rule as above.\nexport * from './lib/import/import-contracts';\nexport * from './lib/import/sheet-parser';\nexport * from './lib/import/local-import-transport';\nexport * from './lib/import/http-import-transport';\nexport * from './lib/import/entity-import.component';\nexport * from './lib/import/import-mapper.component';\nexport * from './lib/import/import-preview.component';\nexport * from './lib/import/import-template.component';\nexport * from './lib/import/import-errors.component';\n\n// The contract a field component must satisfy to be registered with provideFieldTypes.\n// Previously this existed only as a code comment and an ADR that is gitignored, so a\n// consumer had no interface to implement against.\nexport * from './lib/field-types/field-component.contract';\n// Unique DOM ids, for a custom field type that renders a `<label for>` — see the contract.\nexport * from './lib/field-types/field-dom-id';\n\n// Field type components — every one, individually importable.\n//\n// The tree-shaking seam is `provideFieldTypes({ image: ImageFieldComponent })`: register\n// only what you use and the rest never enters the bundle. That only works for components a\n// consumer can name, and ten of these were unreachable — so wanting eleven of the twenty\n// meant calling provideBuiltInFieldTypes() and bundling all of them, which is exactly what\n// the seam exists to avoid.\nexport * from './lib/field-types/text-field.component';\nexport * from './lib/field-types/textarea-field.component';\nexport * from './lib/field-types/markdown-field.component';\nexport * from './lib/field-types/number-field.component';\nexport * from './lib/field-types/currency-field.component';\nexport * from './lib/field-types/email-field.component';\nexport * from './lib/field-types/password-field.component';\nexport * from './lib/field-types/checkbox-field.component';\nexport * from './lib/field-types/boolean-field.component';\nexport * from './lib/field-types/date-field.component';\nexport * from './lib/field-types/date-time-field.component';\nexport * from './lib/field-types/time-field.component';\nexport * from './lib/field-types/month-year-field.component';\nexport * from './lib/field-types/dropdown-field.component';\nexport * from './lib/field-types/radio-field.component';\nexport * from './lib/field-types/multi-select-field.component';\nexport * from './lib/field-types/entity-ref-field.component';\nexport * from './lib/field-types/group-field.component';\nexport * from './lib/field-types/array-field.component';\nexport * from './lib/field-types/image-field.component';\nexport * from './lib/field-types/file-field.component';\n\n// Value helpers — a dropdown value is now a language-keyed object, so a consumer rendering\n// record values needs these. Re-exported so they don't have to depend on core directly.\nexport {\n resolveLabel,\n resolveOptionLabel,\n resolveOptionValue,\n formatDisplayValue,\n valuesMatch,\n normalizeOption,\n normalizeConfig,\n} from '@dynamic-entity/core';\n\n// Re-export core types so consumers need only one import\nexport type {\n EntityFormConfig,\n NestedTabConfig,\n NestedFieldConfig,\n FieldTableConfig,\n RichFieldType,\n LocalizedText,\n DropdownOption,\n VersionedRecord,\n EntityPermissions,\n RbacContext,\n FieldValidators,\n EntityReferenceConfig,\n EntityReferenceLoader,\n ReferenceOption,\n ReferenceLoaderContext,\n AutoPatchConfig,\n PatchOnTrueMapping,\n FileRef,\n FormRule,\n RuleCondition,\n RuleAction,\n RuleEvaluationResult,\n CommonModuleEntry,\n ComponentClass,\n} from '@dynamic-entity/core';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["coreResolveEffectiveMask","coreShouldMaskField"],"mappings":";;;;;;;;;;;AAoBA;MACa,2BAA2B,CAAA;AACrB,IAAA,GAAG,GAAG,IAAI,GAAG,EAA6B;AAE3D,IAAA,GAAG,CAAC,GAAW,EAAA;QACb,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;IAC1B;IAEA,GAAG,CAAC,GAAW,EAAE,KAAwB,EAAA;QACvC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC;IAC1B;AAEA,IAAA,MAAM,CAAC,GAAW,EAAA;AAChB,QAAA,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;IACtB;IAEA,IAAI,GAAA;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IAC7B;IAEA,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE;IAClB;AACD;;AC9BD;MACa,YAAY,GAAG,IAAI,cAAc,CAAW,cAAc;AAEvE;;;AAGG;MACU,mBAAmB,GAAG,IAAI,cAAc,CAAyB,qBAAqB;AAEnG;;;;;AAKG;MACU,eAAe,GAAG,IAAI,cAAc,CAA8B,iBAAiB;AAEhG;;;;;;AAMG;MACU,mBAAmB,GAAG,IAAI,cAAc,CAAqC,qBAAqB;AAE/G;;;;;;;;;;;;;;;;;AAiBG;MACU,eAAe,GAAG,IAAI,cAAc,CAAgC,iBAAiB;AAElG;;;;;;;;;;;;;;AAcG;MACU,iBAAiB,GAAG,IAAI,cAAc,CAAoB,mBAAmB;AAE1F;;;;;;;AAOG;MACU,mBAAmB,GAAG,IAAI,cAAc,CAAsB,qBAAqB;AAEhG;MACa,kBAAkB,GAAG,IAAI,cAAc,CAAmB,oBAAoB;AAE3F;;;;;;AAMG;MACU,wBAAwB,GAAG,IAAI,cAAc,CAAmB,0BAA0B;AAUvG;MACa,aAAa,GAAG,IAAI,cAAc,CAAsB,eAAe;AAEpF;;;;;;;;;;;;;;;;;;;;AAoBG;MACU,uBAAuB,GAAG,IAAI,cAAc,CAAsB,yBAAyB;AAExG;;;;;;;;AAQG;MACU,cAAc,GAAG,IAAI,cAAc,CAAoB,gBAAgB;AAEpF;;;;;;;;;;;;;;;;;;;;;;AAsBG;MACU,YAAY,GAAG,IAAI,cAAc,CAAc,cAAc;AAE1E;;;;;;;;;;;;;;AAcG;MACU,gBAAgB,GAAG,IAAI,cAAc,CAAkB,kBAAkB;AAEtF;;;;;;AAMG;MACU,sBAAsB,GAAG,IAAI,cAAc,CAAsB,wBAAwB,EAAE;AACtG,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,MAAM,IAAI,2BAA2B,EAAE;AACjD,CAAA;AAED;;;AAGG;MACU,uBAAuB,GAAG,IAAI,cAAc,CAA+B,yBAAyB;AAIjH;;;AAGG;MACU,aAAa,GAAG,IAAI,cAAc,CAAsB,eAAe;AAEpF;;;;;;;;;;;;;;;;;AAiBG;MACU,iBAAiB,GAAG,IAAI,cAAc,CAA6B,mBAAmB;AAEnG;;;;;;;;;;AAUG;MACU,kBAAkB,GAAG,IAAI,cAAc,CAAS,oBAAoB;AAEjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCG;MACU,OAAO,GAAG,IAAI,cAAc,CAAkB,SAAS;;AClMpE;;;;;;;;;AASG;AACI,MAAM,uBAAuB,GAAG,CAAC,MAAA,GAAiC,EAAE,KACzE,wBAAwB,CAAC;IACvB,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE,EAAE;IAC7D,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,EAAE;IAC5F,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,EAAE;IAC5F,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,EAAE;IACrF,EAAE,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,EAAE;AAC3F,IAAA;AACE,QAAA,OAAO,EAAE,wBAAwB;AACjC,QAAA,QAAQ,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;AAChE,KAAA;IACD,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE;IACjF,EAAE,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,CAAC,UAAU,IAAI,EAAE,EAAE;IACjE,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,CAAC,kBAAkB,IAAI,EAAE,EAAE;IAC3E,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE;;;IAGnD,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI,EAAE;IAC/D,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,CAAC,eAAe,IAAI,IAAI,EAAE;AACxE,CAAA;;ACrFH;AACO,MAAM,2BAA2B,GAAsC;AAC5E,IAAA,QAAQ,EAAE,yBAAyB;AACnC,IAAA,iBAAiB,EAAE,0BAA0B;AAC7C,IAAA,KAAK,EAAE,qCAAqC;AAC5C,IAAA,OAAO,EAAE,iBAAiB;AAC1B,IAAA,SAAS,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,CAAA,QAAA,EAAW,GAAG,EAAE,cAAc,CAAA,qBAAA,CAAuB;AAChF,IAAA,SAAS,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,CAAA,QAAA,EAAW,GAAG,EAAE,cAAc,CAAA,oBAAA,CAAsB;AAC/E,IAAA,GAAG,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,CAAA,uBAAA,EAA0B,GAAG,EAAE,GAAG,CAAA,CAAA,CAAG;AAC1D,IAAA,GAAG,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,CAAA,sBAAA,EAAyB,GAAG,EAAE,GAAG,CAAA,CAAA,CAAG;AACzD,IAAA,OAAO,EAAE,gBAAgB;AACzB,IAAA,aAAa,EAAE,iBAAiB;AAChC,IAAA,gBAAgB,EAAE,oBAAoB;;AAMxC;;;;;;AAMG;AACH,MAAM,YAAY,GAAiC,CAAC,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC;AAE3H;;;;;;;AAOG;AACH,MAAM,mBAAmB,GAAwF;AAC/G,IAAA,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC,EAAE,QAAQ,EAAE,kBAAkB,EAAE;AACtF,IAAA,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE;AACxE,IAAA,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE;AAChE,IAAA,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE;AACjE,IAAA,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE;AAC7D,IAAA,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE;CAC/D;MAGY,yBAAyB,CAAA;AACnB,IAAA,SAAS,GAAG,MAAM,CAAC,mBAAmB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE;AAElF;;;;;;AAMG;IACH,OAAO,CACL,MAA2C,EAC3C,QAAgB,EAChB,KAA4E,EAC5E,WAAW,GAAG,SAAS,EAAA;AAEvB,QAAA,IAAI,CAAC,MAAM;AAAE,YAAA,OAAO,EAAE;AAEtB,QAAA,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE;;;;YAIzB,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,GAAG,OAAO,KAAK,KAAK,QAAQ,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,KAAK;;AAEjF,YAAA,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,SAAS;gBAAE;AACpC,YAAA,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChE;QACA,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,CAAC;IACrD;AAEA;;;;;;;;;;;;AAYG;AACH,IAAA,eAAe,CAAC,MAA2C,EAAE,QAAgB,EAAE,SAAiB,EAAA;AAC9F,QAAA,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;AACpD,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC;IACxD;;AAGA,IAAA,QAAQ,CAAC,SAAiB,EAAA;AACxB,QAAA,OAAO,mBAAmB,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE;IACvF;;AAGA,IAAA,UAAU,CAAC,GAAW,EAAE,QAAgB,EAAE,KAAc,EAAA;AACtD,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,2BAA2B,CAAC,GAAG,CAAC;QACvE,IAAI,OAAO,KAAK,SAAS;AAAE,YAAA,OAAO,EAAE;AACpC,QAAA,OAAO,OAAO,OAAO,KAAK,UAAU,GAAG,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,OAAO;IAC3E;wGA1DW,yBAAyB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAzB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,yBAAyB,cADZ,MAAM,EAAA,CAAA;;4FACnB,yBAAyB,EAAA,UAAA,EAAA,CAAA;kBADrC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACzElC;;;;;;;;;;;;;;;;;;AAkBG;AACH,IAAI,QAAQ,GAAG,CAAC;AAEhB;SACgB,mBAAmB,GAAA;IACjC,QAAQ,IAAI,CAAC;IACb,OAAO,CAAA,EAAA,EAAK,QAAQ,CAAA,CAAE;AACxB;AAEA;;;;;;AAMG;AACG,SAAU,UAAU,CAAC,KAAkC,EAAE,QAAgB,EAAE,MAAM,GAAG,EAAE,EAAA;IAC1F,OAAO,CAAA,EAAG,KAAK,EAAE,EAAE,IAAI,OAAO,CAAA,CAAA,EAAI,QAAQ,CAAA,EAAG,MAAM,CAAA,CAAE;AACvD;AAEA;;;;;;;;;;;;;;AAcG;AACG,SAAU,gBAAgB,CAC9B,KAAkC,EAClC,KAA0C,EAAA;IAE1C,MAAM,GAAG,GAAa,EAAE;IACxB,IAAI,KAAK,CAAC,IAAI;QAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,KAAK,CAAC,KAAK;QAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AAC1C,IAAA,OAAO,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI;AAC1C;;MCaa,kBAAkB,CAAA;AAC7B;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AACrD,IAAA,UAAU;AAET,IAAA,KAAK;IACd,IACI,OAAO,CAAC,KAAsB,EAAA;AAChC,QAAA,IAAI,CAAC,QAAQ,GAAG,KAAK;AACrB,QAAA,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE;QAC9B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC;QAC3C,IAAI,CAAC,UAAU,GAAG,KAAK,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAChF;AACA,IAAA,IAAI,OAAO,GAAA;QACT,OAAO,IAAI,CAAC,QAAQ;IACtB;AACQ,IAAA,QAAQ;IAEP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;;AAGvB,IAAA,YAAY,GAAG,MAAM,CAAU,IAAI,mFAAC;IAE7C,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE;IAChC;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC;IAC7D;;AAGA,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7E,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGA5DW,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA5DnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA3DS,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FA6DlB,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAjE9B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,gBAAgB;AAC1B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DT,EAAA,CAAA;AACF,iBAAA;;sBAgBE;;sBACA;;sBAYA;;sBACA;;sBACA;;;MC1CU,sBAAsB,CAAA;AACjC;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AACpD,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEhC,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC;IAC7D;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGA7CW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAjDvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAhDS,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAkDlB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAtDlC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,oBAAoB;AAC9B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CT,EAAA,CAAA;AACF,iBAAA;;sBAcE;;sBACA;;sBACA;;sBACA;;sBACA;;;AC3EH;AACA,MAAM,WAAW,GAAG,IAAI,MAAM,CAAC,uBAAuB,EAAE,GAAG,CAAC;AAE5D;;;;;;;;;;;;;;AAcG;AACI,MAAM,eAAe,GAAG;;AAE7B,IAAA,IAAI,EAAE,MAAM;AACZ,IAAA,MAAM,EAAE,SAAS;AACjB,IAAA,KAAK,EAAE,OAAO;AACd,IAAA,gBAAgB,EAAE,kBAAkB;AACpC,IAAA,OAAO,EAAE,UAAU;;AAGnB,IAAA,iBAAiB,EAAE,2DAA2D;AAC9E,IAAA,aAAa,EAAE,6CAA6C;;AAG5D,IAAA,WAAW,EAAE,cAAc;AAC3B,IAAA,WAAW,EAAE,cAAc;AAC3B,IAAA,cAAc,EAAE,sBAAsB;AACtC,IAAA,MAAM,EAAE,QAAQ;AAChB,IAAA,IAAI,EAAE,MAAM;AACZ,IAAA,MAAM,EAAE,QAAQ;;AAGhB,IAAA,MAAM,EAAE,OAAO;AACf,IAAA,OAAO,EAAE,YAAY;AACrB,IAAA,UAAU,EAAE,gBAAgB;AAC5B,IAAA,WAAW,EAAE,iBAAiB;AAC9B,IAAA,YAAY,EAAE,kBAAkB;AAChC,IAAA,OAAO,EAAE,UAAU;AACnB,IAAA,MAAM,EAAE,QAAQ;AAChB,IAAA,MAAM,EAAE,cAAc;AACtB,IAAA,OAAO,EAAE,qBAAqB;;AAG9B,IAAA,iBAAiB,EAAE,WAAW;AAC9B,IAAA,iBAAiB,EAAE,uBAAuB;;AAG1C,IAAA,GAAG,EAAE,KAAK;AACV,IAAA,EAAE,EAAE,IAAI;;AAGR,IAAA,SAAS,EAAE,YAAY;AACvB,IAAA,UAAU,EAAE,aAAa;AACzB,IAAA,WAAW,EAAE,cAAc;AAC3B,IAAA,UAAU,EAAE,aAAa;AACzB,IAAA,YAAY,EAAE,eAAe;AAC7B,IAAA,OAAO,EAAE,UAAU;AACnB,IAAA,WAAW,EAAE,QAAQ;AACrB,IAAA,WAAW,EAAE,QAAQ;;AAGrB,IAAA,KAAK,EAAE,OAAO;AACd,IAAA,IAAI,EAAE,MAAM;;AAGZ,IAAA,KAAK,EAAE,OAAO;AACd,IAAA,OAAO,EAAE,SAAS;AAClB,IAAA,kBAAkB,EAAE,qBAAqB;;AAGzC,IAAA,YAAY,EAAE,eAAe;AAC7B,IAAA,YAAY,EAAE,eAAe;AAC7B,IAAA,SAAS,EAAE,cAAc;AACzB,IAAA,WAAW,EAAE,gBAAgB;AAC7B,IAAA,qBAAqB,EAAE,gCAAgC;AACvD,IAAA,uBAAuB,EAAE,8CAA8C;AACvE,IAAA,aAAa,EAAE,oBAAoB;AACnC,IAAA,WAAW,EAAE,0BAA0B;;AAGvC,IAAA,YAAY,EAAE,eAAe;AAC7B,IAAA,SAAS,EAAE,eAAe;AAC1B,IAAA,YAAY,EAAE,QAAQ;AACtB,IAAA,UAAU,EAAE,MAAM;;AAGlB,IAAA,gBAAgB,EAAE,sBAAsB;AACxC,IAAA,gBAAgB,EAAE,wBAAwB;AAC1C,IAAA,aAAa,EAAE,mBAAmB;AAClC,IAAA,cAAc,EAAE,4BAA4B;;AAG5C,IAAA,qBAAqB,EAAE,uBAAuB;AAC9C,IAAA,qBAAqB,EAAE,qEAAqE;AAC5F,IAAA,sBAAsB,EAAE,mBAAmB;AAC3C,IAAA,uBAAuB,EAAE,YAAY;AACrC,IAAA,wBAAwB,EAAE,aAAa;AACvC,IAAA,yBAAyB,EAAE,sDAAsD;;AAGjF,IAAA,kBAAkB,EAAE,qBAAqB;AACzC,IAAA,iBAAiB,EAAE,OAAO;AAC1B,IAAA,cAAc,EAAE,cAAc;AAC9B,IAAA,aAAa,EAAE,SAAS;AACxB,IAAA,iBAAiB,EAAE,uCAAuC;AAC1D,IAAA,sBAAsB,EAAE,gDAAgD;;AAGxE,IAAA,oBAAoB,EAAE,6CAA6C;AACnE,IAAA,iBAAiB,EAAE,yCAAyC;AAC5D,IAAA,eAAe,EAAE,uBAAuB;AACxC,IAAA,eAAe,EAAE,YAAY;AAC7B,IAAA,eAAe,EAAE,6BAA6B;AAC9C,IAAA,iBAAiB,EAAE,+BAA+B;AAClD,IAAA,gBAAgB,EAAE,uCAAuC;;;;AAIzD,IAAA,qBAAqB,EAAE,kDAAkD;AACzE,IAAA,eAAe,EAAE,qBAAqB;;AAGtC,IAAA,mBAAmB,EAAE,0BAA0B;AAC/C,IAAA,cAAc,EAAE,WAAW;AAC3B,IAAA,gBAAgB,EAAE,OAAO;AACzB,IAAA,iBAAiB,EAAE,QAAQ;AAC3B,IAAA,iBAAiB,EAAE,wCAAwC;;AAG3D,IAAA,WAAW,EAAE,kBAAkB;AAC/B,IAAA,oBAAoB,EAAE,iGAAiG;AACvH,IAAA,cAAc,EAAE,qEAAqE;AACrF,IAAA,YAAY,EAAE,iDAAiD;;AA4CjE;;;;;;;AAOG;AACG,SAAU,aAAa,CAC3B,SAAmD,EACnD,QAAqC,EACrC,GAAM,EACN,QAAgB,EAChB,MAAqB,EAAA;IAErB,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC;IACzC,MAAM,QAAQ,GAAG,CAAC;AAChB,UAAE;AACF,UAAE,OAAO,SAAS,KAAK;cACnB,WAAW,CAAC,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ;AAChD;;AAEE,gBAAA,UAAU,CAAC,GAAG,CAA0B,SAAS,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,IAAI,QAAQ;AAEpF,IAAA,OAAO,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC;AACtC;AAEA;;;;;;;;AAQG;AACH,SAAS,GAAG,CAAI,GAA+B,EAAE,GAAW,EAAA;IAC1D,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS;AAC9E;AAEA,SAAS,SAAS,CAAmB,QAAqC,EAAE,GAAM,EAAA;IAChF,MAAM,KAAK,GAAG,GAAG,CAAC,QAAmC,EAAE,GAAG,CAAC;AAC3D,IAAA,OAAO,OAAO,KAAK,KAAK,QAAQ,GAAG,KAAK,GAAG,EAAE;AAC/C;AAEA;;;;;;;AAOG;AACH,SAAS,WAAW,CAAmB,QAA8B,EAAE,GAAM,EAAE,QAAgB,EAAE,QAAgB,EAAA;AAC/G,IAAA,IAAI;QACF,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC;AAChD,QAAA,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,GAAG,MAAM,GAAG,QAAQ;IACjE;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,QAAQ;IACjB;AACF;AAEA,SAAS,UAAU,CAAC,KAA8B,EAAE,QAAgB,EAAA;IAClE,IAAI,OAAO,KAAK,KAAK,QAAQ;AAAE,QAAA,OAAO,KAAK;IAC3C,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC;;;AAG9C,IAAA,OAAO,OAAO,QAAQ,KAAK,QAAQ,GAAG,QAAQ,GAAG,EAAE;AACrD;AAEA;;;;;;;AAOG;MAEU,aAAa,CAAA;IACP,SAAS,GAAG,MAAM,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAEhE;;;AAGG;AACH,IAAA,IAAI,CAAC,GAAc,EAAE,QAAQ,GAAG,IAAI,EAAE,MAAqB,EAAA;AACzD,QAAA,OAAO,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC;IAC9E;wGATW,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAb,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,aAAa,cADA,MAAM,EAAA,CAAA;;4FACnB,aAAa,EAAA,UAAA,EAAA,CAAA;kBADzB,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;AAalC;AACA,SAAS,WAAW,CAAC,IAAY,EAAE,MAAqB,EAAA;AACtD,IAAA,IAAI,CAAC,MAAM;AAAE,QAAA,OAAO,IAAI;;;IAGxB,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,IAAI,KAAI;QAC/C,MAAM,KAAK,GAAG,GAAG,CAAC,MAAiC,EAAE,IAAI,CAAC;AAC1D,QAAA,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;AACtE,IAAA,CAAC,CAAC;AACJ;;AC5QA;;;;;;;;;;;;;;;AAeG;MA0GU,sBAAsB,CAAA;AACjC;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;;AAE1C,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;AACpC,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;;IAGf,MAAM,GAAG,MAAM,CAAC,iBAAiB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACtD,IAAA,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC;AAC/B,IAAA,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AAE7B,IAAA,UAAU,GAAG,MAAM,CAAC,KAAK,iFAAC;AAErC,IAAA,QAAQ;AAEhB;;;;;;;;AAQG;AACH,IAAA,WAAW,CAAC,OAAsB,EAAA;AAChC,QAAA,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YAAE;AACzB,QAAA,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE;QAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACpF,IAAI,IAAI,CAAC,QAAQ;AAAE,YAAA,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC;IAClF;;AAGA,IAAA,IAAc,UAAU,GAAA;AACtB,QAAA,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM;IACtB;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC;IAC7D;AAEA;;;;;;;;;;;;AAYG;AACK,IAAA,MAAM;IAEJ,QAAQ,GAAA;AAChB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK;AAClC,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,EAAE;AAAE,YAAA,OAAO,IAAI;AAC5E,QAAA,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM;AAAE,YAAA,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI;AAE3D,QAAA,IAAI,IAAmB;AACvB,QAAA,IAAI;AACF,YAAA,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QAC5B;AAAE,QAAA,MAAM;YACN,IAAI,GAAG,IAAI;QACb;QACA,IAAI,CAAC,MAAM,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;AAC9B,QAAA,OAAO,IAAI;IACb;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGA3GW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,aAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EApGvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkGT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAnGS,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAqGlB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAzGlC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,oBAAoB;AAC9B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkGT,EAAA,CAAA;AACF,iBAAA;;sBAgBE;;sBACA;;sBACA;;sBACA;;sBACA;;;MCtFU,oBAAoB,CAAA;AAC/B;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AAEpD,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEhC,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC;IAC7D;;AAGA,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7E,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGAzCW,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,oBAAoB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA5DrB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA3DS,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,mBAAA,EAAA,QAAA,EAAA,iGAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FA6DlB,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAjEhC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,kBAAkB;AAC5B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DT,EAAA,CAAA;AACF,iBAAA;;sBAeE;;sBACA;;sBACA;;sBACA;;sBACA;;;ACnFH;MA6Da,sBAAsB,CAAA;AACjC;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AACpD,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEhC,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC;IAC7D;;AAGA,IAAA,IAAI,MAAM,GAAA;AACR,QAAA,IAAI;YACF,QACE,CAAC,CAAC;AACC,iBAAA,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,EAAE;AAC9F,iBAAA,OAAO,CAAC,WAAW,EAAE,EAAE;AACvB,iBAAA,IAAI,EAAE,IAAI,GAAG;QAEpB;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,GAAG;QACZ;IACF;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGA3DW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAvDvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAtDS,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,mBAAA,EAAA,QAAA,EAAA,iGAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAwDlB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBA5DlC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,oBAAoB;AAC9B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDT,EAAA,CAAA;AACF,iBAAA;;sBAcE;;sBACA;;sBACA;;sBACA;;sBACA;;;AC9EH;MAkEa,mBAAmB,CAAA;AAC9B;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AACpD,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEhC,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC;IAC7D;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGA7CW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,mBAAmB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA5DpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA3DS,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FA6DlB,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAjE/B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,iBAAiB;AAC3B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DT,EAAA,CAAA;AACF,iBAAA;;sBAcE;;sBACA;;sBACA;;sBACA;;sBACA;;;AClFH;MAkEa,sBAAsB,CAAA;AACjC;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;;AAE1C,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;AACpC,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEvB,IAAA,OAAO,GAAG,MAAM,CAAC,KAAK,8EAAC;AAEhC,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC;IAC7D;IAEA,gBAAgB,GAAA;AACd,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9B;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGArDW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA5DvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA3DS,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FA6DlB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAjElC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,oBAAoB;AAC9B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DT,EAAA,CAAA;AACF,iBAAA;;sBAgBE;;sBACA;;sBACA;;sBACA;;sBACA;;;MCxBU,sBAAsB,CAAA;AACjC;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;;AAE1B,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AACpD,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEhC,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGA3CW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAxDvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAvDS,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,4BAAA,EAAA,QAAA,EAAA,uGAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAyDlB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBA7DlC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,oBAAoB;AAC9B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDT,EAAA,CAAA;AACF,iBAAA;;sBAgBE;;sBACA;;sBACA;;sBACA;;sBACA;;;AChFH;;;;AAIG;MAsEU,qBAAqB,CAAA;AAChC;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;;AAE1B,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AACpD,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEhC,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGA3CW,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAArB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAhEtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA/DS,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,4BAAA,EAAA,QAAA,EAAA,uGAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAiElB,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBArEjC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,mBAAmB;AAC7B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DT,EAAA,CAAA;AACF,iBAAA;;sBAgBE;;sBACA;;sBACA;;sBACA;;sBACA;;;MCvCU,kBAAkB,CAAA;AAC7B;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AACpD,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEhC,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA;;;;;;;;;;;AAWG;AACH,IAAA,UAAU,CAAC,KAAoB,EAAA;AAC7B,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,GAAG;;;;;;AAMtB,QAAA,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC;QAC9B,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;AAAE,YAAA,OAAO,KAAK;AAChD,QAAA,OAAO,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACpE;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGAjEW,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlDnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAjDS,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAmDlB,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAvD9B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,gBAAgB;AAC1B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDT,EAAA,CAAA;AACF,iBAAA;;sBAcE;;sBACA;;sBACA;;sBACA;;sBACA;;;ACxEH;;;;;;;AAOG;AACH,SAAS,WAAW,CAAC,KAAc,EAAA;IACjC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;AAAE,QAAA,OAAO,IAAI;IACtE,IAAI,KAAK,YAAY,IAAI;AAAE,QAAA,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,GAAG,KAAK;AAE9E,IAAA,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC;IACzB,MAAM,QAAQ,GAAG,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC;AACtD,IAAA,IAAI,QAAQ;QAAE,OAAO,IAAI,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAE3E,IAAA,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;AAC5B,IAAA,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,GAAG,MAAM;AACvD;AAEA,MAAM,GAAG,GAAG,CAAC,CAAS,KAAa,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC;AAE7D;;;;;;AAMG;MAyDU,sBAAsB,CAAA;AACjC;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AACpD,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEhC,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;;AAGA,IAAA,IAAI,UAAU,GAAA;QACZ,MAAM,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC;AAC1C,QAAA,IAAI,CAAC,CAAC;AAAE,YAAA,OAAO,EAAE;AACjB,QAAA,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA,CAAA,EAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAA,CAAA,EAAI,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA,CAAA,EAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA,CAAA,EAAI,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,EAAE;IACtH;;AAGA,IAAA,OAAO,CAAC,KAAa,EAAA;QACnB,IAAI,CAAC,KAAK,EAAE;AACV,YAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC3B,YAAA,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE;YAC5B;QACF;AACA,QAAA,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC;;;QAGzB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;AAC1E,QAAA,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE;IAC9B;AAEA;;;;;;;;;;;;AAYG;AACH,IAAA,cAAc,CAAC,KAAc,EAAA;AAC3B,QAAA,MAAM,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC;AAC5B,QAAA,IAAI,CAAC,CAAC;AAAE,YAAA,OAAO,GAAG;AAClB,QAAA,OAAO,kBAAkB,CAAC,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC;IAClF;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGAjFW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAnDvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAlDS,mBAAmB,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAoDlB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAxDlC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,qBAAqB;AAC/B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDT,EAAA,CAAA;AACF,iBAAA;;sBAcE;;sBACA;;sBACA;;sBACA;;sBACA;;;ACtGH;;;;;;;AAOG;MAwDU,kBAAkB,CAAA;AAC7B;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AACpD,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEhC,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA;;;;AAIG;AACH,IAAA,UAAU,CAAC,KAAc,EAAA;AACvB,QAAA,OAAO,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACpE;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGAlDW,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlDnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAjDS,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAmDlB,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAvD9B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,gBAAgB;AAC1B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDT,EAAA,CAAA;AACF,iBAAA;;sBAcE;;sBACA;;sBACA;;sBACA;;sBACA;;;AC/EH,MAAM,WAAW,GAAG;IAClB,SAAS;IACT,UAAU;IACV,OAAO;IACP,OAAO;IACP,KAAK;IACL,MAAM;IACN,MAAM;IACN,QAAQ;IACR,WAAW;IACX,SAAS;IACT,UAAU;IACV,UAAU;CACX;AAED,MAAM,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,YAAY,GAAG,CAAC,CAAC;AAEpE;;;AAGG;MAqFU,uBAAuB,CAAA;AAClC;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;;AAE1B,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AACpD,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEvB,IAAA,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1F,KAAK,GAAG,KAAK;AAEtB,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;;AAGA,IAAA,IAAI,aAAa,GAAA;AACf,QAAA,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE;IAC/C;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE;IAC/C;AAEA,IAAA,aAAa,CAAC,KAAa,EAAA;AACzB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;AACrE,QAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,GAAG,GAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,CAAE,GAAG,IAAI,CAAC;AACxD,QAAA,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE;IAC9B;AAEA,IAAA,YAAY,CAAC,IAAY,EAAA;AACvB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI;AACxC,QAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,CAAE,GAAG,IAAI,CAAC;AACvD,QAAA,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE;IAC9B;AAEA,IAAA,WAAW,CAAC,KAAc,EAAA;AACxB,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,GAAG;AACtB,QAAA,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;AACjD,QAAA,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;AACzD,QAAA,OAAO,SAAS,IAAI,IAAI,GAAG,GAAG,SAAS,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE,GAAG,MAAM,CAAC,KAAK,CAAC;IACnE;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGA5EW,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAvB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,uBAAuB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA/ExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6ET,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA9ES,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,cAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,uBAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,OAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAgFlB,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBApFnC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,sBAAsB;AAChC,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6ET,EAAA,CAAA;AACF,iBAAA;;sBAgBE;;sBACA;;sBACA;;sBACA;;sBACA;;;ACxHH;AACA,MAAM,GAAG,GAAG,GAAG;AAEf;;;;;;;;;;;;;;AAcG;MAEU,qBAAqB,CAAA;AACf,IAAA,QAAQ,GACvB,MAAM,CAAC,eAAe,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI,GAAG,EAA4B;;AAGnE,IAAA,OAAO,GAAG,IAAI,GAAG,EAA4B;;AAE7C,IAAA,MAAM,GAAG,IAAI,GAAG,EAA6B;;AAE7C,IAAA,QAAQ,GAAG,IAAI,GAAG,EAAqC;;AAEvD,IAAA,MAAM,GAAG,IAAI,GAAG,EAAkB;AAEnD,IAAA,GAAG,CAAC,QAAgB,EAAA;QAClB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;IACpC;AAEA;;;AAGG;AACH,IAAA,MAAM,IAAI,CAAC,QAAgB,EAAE,IAAI,GAAG,IAAI,EAAA;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;QAEzC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;AACpC,QAAA,IAAI,MAAM;AAAE,YAAA,OAAO,MAAM;QAEzB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;AACtC,QAAA,IAAI,OAAO;AAAE,YAAA,OAAO,OAAO;QAE3B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1C,IAAI,MAAM,KAAK,SAAS;AAAE,YAAA,OAAO,EAAE;AAEnC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,IAAG;AAChD,YAAA,MAAM,MAAM,GAAG,qBAAqB,CAAC,GAAG,CAAC;AACzC,YAAA,MAAM,OAAO,GAAG,qBAAqB,CAAC,MAAM,CAAC;YAC7C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC;YAC5B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC;YAC9B,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC;AAC5C,YAAA,OAAO,OAAO;AAChB,QAAA,CAAC,CAAC;;;QAIF,MAAM,OAAO,GAAG;AACb,aAAA,KAAK,CAAC,MAAM,EAAsB;AAClC,aAAA,OAAO,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAE3C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC;AAC/B,QAAA,OAAO,OAAO;IAChB;;AAGA,IAAA,IAAI,CAAC,QAAgB,EAAE,IAAI,GAAG,IAAI,EAAA;AAChC,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACxD;AAEA;;;AAGG;AACH,IAAA,SAAS,CAAC,QAAgB,EAAE,IAAI,GAAG,IAAI,EAAA;AACrC,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACvD;AAEA;;;;;;AAMG;AACH,IAAA,QAAQ,CAAC,QAA4B,EAAE,KAAc,EAAE,IAAI,GAAG,IAAI,EAAA;AAChE,QAAA,IAAI,CAAC,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;AAAE,YAAA,OAAO,SAAS;AACxF,QAAA,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE;AACnD,YAAA,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAChE,YAAA,IAAI,GAAG;AAAE,gBAAA,OAAO,GAAG;QACrB;AACA,QAAA,OAAO,SAAS;IAClB;;;AAKA,IAAA,YAAY,CAAC,KAAoC,EAAA;AAC/C,QAAA,OAAO,CAAC,CAAC,KAAK,EAAE,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM;IACpD;AAEA;;;AAGG;AACH,IAAA,UAAU,CAAC,KAAoC,EAAE,IAAI,GAAG,IAAI,EAAA;AAC1D,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,EAAE;AACrB,QAAA,IAAI,KAAK,CAAC,OAAO,EAAE,MAAM;YAAE,OAAO,KAAK,CAAC,OAAO;QAC/C,IAAI,CAAC,KAAK,CAAC,QAAQ;AAAE,YAAA,OAAO,EAAE;AAC9B,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE;IAC9C;;AAGA,IAAA,cAAc,CAAC,KAAoC,EAAE,IAAI,GAAG,IAAI,EAAA;AAC9D,QAAA,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;AAAE,YAAA,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACnF,OAAO,IAAI,CAAC,IAAI,CAAC,KAAM,CAAC,QAAS,EAAE,IAAI,CAAC;IAC1C;;AAGA,IAAA,UAAU,CAAC,QAAgB,EAAA;AACzB,QAAA,MAAM,MAAM,GAAG,CAAA,EAAG,QAAQ,CAAA,EAAG,GAAG,EAAE;AAClC,QAAA,KAAK,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YAC5D,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE;AACjC,gBAAA,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC;AAAE,oBAAA,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;YAC7C;QACF;AACA,QAAA,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE;AACzC,YAAA,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC;AAAE,gBAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;QACrD;IACF;IAEA,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;AACpB,QAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;AACnB,QAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE;AACrB,QAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;IACrB;;IAIQ,QAAQ,CAAC,QAAgB,EAAE,IAAY,EAAA;QAC7C,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;IACnC;AAEQ,IAAA,QAAQ,CAAC,QAAgB,EAAE,IAAY,EAAE,IAAY,EAAA;AAC3D,QAAA,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;IACzC;;AAGQ,IAAA,cAAc,CAAC,QAAgB,EAAE,IAAY,EAAE,OAAyB,EAAA;AAC9E,QAAA,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;YAC5B,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC;AAC1C,YAAA,IAAI,CAAC,OAAO;gBAAE;YACd,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;gBACxC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,EAAE,EAAE;AAC3C,oBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC;gBAC/D;YACF;QACF;IACF;;IAGQ,cAAc,CAAC,KAAc,EAAE,IAAY,EAAA;AACjD,QAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAgC,CAAC,CAAC,MAAM,CAClE,CAAC,CAAC,KAAkB,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE,CACtD;YACD,MAAM,QAAQ,GAAG,YAAY,CAAC,KAA+B,EAAE,IAAI,CAAC;AACpE,YAAA,OAAO,QAAQ,GAAG,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,GAAG,KAAK;QAChD;AACA,QAAA,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxB;;IAIQ,MAAM,CAAC,MAAwB,EAAE,IAAY,EAAA;AACnD,QAAA,IAAI,MAAwB;AAC5B,QAAA,IAAI;AACF,YAAA,MAAM,GAAG,OAAO,MAAM,KAAK,UAAU,GAAI,MAA2B,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM;QACzF;QAAE,OAAO,GAAG,EAAE;;;AAGZ,YAAA,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC;QAC5B;AACA,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;IAC/B;AAEQ,IAAA,SAAS,CAAC,MAAwB,EAAA;AACxC,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;AAAE,YAAA,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;AACzD,QAAA,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE;;YAE/B,OAAO,IAAI,OAAO,CAAuB,CAAC,OAAO,EAAE,MAAM,KAAI;gBAC3D,IAAI,OAAO,GAAG,KAAK;AACnB,gBAAA,MAAM,MAAM,GAAG,CAAC,EAAc,KAAI;AAChC,oBAAA,IAAI,OAAO;wBAAE;oBACb,OAAO,GAAG,IAAI;AACd,oBAAA,EAAE,EAAE;AACN,gBAAA,CAAC;gBACD,MAAM,CAAC,SAAS,CAAC;AACf,oBAAA,IAAI,EAAE,KAAK,IAAI,MAAM,CAAC,MAAM,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;AACjD,oBAAA,KAAK,EAAE,GAAG,IAAI,MAAM,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC;;AAEvC,oBAAA,QAAQ,EAAE,MAAM,MAAM,CAAC,MAAM,OAAO,CAAC,EAAE,CAAC,CAAC;AAC1C,iBAAA,CAAC;AACJ,YAAA,CAAC,CAAC;QACJ;AACA,QAAA,OAAO,OAAO,CAAC,OAAO,CAAC,MAAuC,CAAC;IACjE;AAEQ,IAAA,cAAc,CAAC,KAAc,EAAA;AACnC,QAAA,QACE,OAAO,KAAK,KAAK,QAAQ;AACzB,YAAA,KAAK,KAAK,IAAI;AACd,YAAA,OAAQ,KAA4C,CAAC,SAAS,KAAK,UAAU;IAEjF;wGA1MW,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAArB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,qBAAqB,cADR,MAAM,EAAA,CAAA;;4FACnB,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBADjC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;AAqNlC,MAAM,cAAc,GAAG,IAAI,OAAO,EAAkE;AAEpG;;;;;;;;;;;;;AAaG;AACG,SAAU,oBAAoB,CAAC,IAAsB,EAAE,OAA8B,EAAA;IACzF,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;AACrC,IAAA,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ,EAAE;QACpE;IACF;AACA,IAAA,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;AAEpE,IAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/D,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE;AAEvC,IAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,EAAE,QAAQ;AACrC,IAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ;AAC1B,IAAA,KAAK,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,IAAG;AACpE,QAAA,IAAI,IAAI,CAAC,KAAK,EAAE,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;AAAE,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;AAC5F,IAAA,CAAC,CAAC;AACJ;;MC/La,sBAAsB,CAAA;AACjC;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;;AAE1B,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,OAAO,GAAG,MAAM,CAAC,qBAAqB,CAAC;AACvC,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AAErD,IAAA,MAAM;IACN,SAAS,GAAG,IAAI;;IAGxB,IAAa,KAAK,CAAC,KAAwB,EAAA;AACzC,QAAA,IAAI,CAAC,MAAM,GAAG,KAAK;AACnB,QAAA,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC;IAC1C;AACA,IAAA,IAAI,KAAK,GAAA;QACP,OAAO,IAAI,CAAC,MAAM;IACpB;IAEA,IAAa,QAAQ,CAAC,KAAa,EAAA;AACjC,QAAA,IAAI,CAAC,SAAS,GAAG,KAAK,IAAI,IAAI;AAC9B,QAAA,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC;IAC1C;AACA,IAAA,IAAI,QAAQ,GAAA;QACV,OAAO,IAAI,CAAC,SAAS;IACvB;AAES,IAAA,OAAO;IACP,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;;AAGvB,IAAA,OAAO,GAAG,MAAM,CAAmB,EAAE,8EAAC;AAEtC,IAAA,SAAS,GAAG,CAAC,EAAW,EAAE,EAAW,KAAc,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC;AAE9F,IAAA,WAAW,CAAC,MAAsB,EAAA;QAChC,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;IACtD;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC;IAC7D;AAEA;;;;;;;;AAQG;AACH,IAAA,eAAe,CAAC,MAAsB,EAAA;AACpC,QAAA,OAAO,MAAM;IACf;AAEA,IAAA,WAAW,CAAC,MAAsB,EAAA;QAChC,OAAO,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC;IAClD;AAEA;;;;AAIG;AACH,IAAA,QAAQ,CAAC,KAAc,EAAA;AACrB,QAAA,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE;AAAE,YAAA,OAAO,GAAG;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC7E,QAAA,IAAI,MAAM;AAAE,YAAA,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;AAChF,QAAA,IAAI,MAAM;AAAE,YAAA,OAAO,MAAM;QACzB,OAAO,OAAO,KAAK,KAAK,QAAQ,GAAG,YAAY,CAAC,KAA+B,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,KAAK,IAAI,GAAG,CAAC;IACxH;;AAGA,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;;;QAG7E,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGAxGW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,QAAA,EAAA,UAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAtEvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoET,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EArES,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,cAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,uBAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,0BAAA,EAAA,QAAA,EAAA,6GAAA,EAAA,MAAA,EAAA,CAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAuElB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBA3ElC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,oBAAoB;AAC9B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoET,EAAA,CAAA;AACF,iBAAA;;sBAsBE;;sBAQA;;sBAQA;;sBACA;;sBACA;;;AC7GH;MAsEa,mBAAmB,CAAA;AAC9B;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AAC5C,IAAA,OAAO,GAAG,MAAM,CAAC,qBAAqB,CAAC;AACvC,IAAA,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC;AAExC,IAAA,MAAM;IACN,SAAS,GAAG,IAAI;AAChB,IAAA,QAAQ;AACR,IAAA,WAAW;IAEnB,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE;IACjC;;IAGA,IAAa,KAAK,CAAC,KAAwB,EAAA;AACzC,QAAA,IAAI,CAAC,MAAM,GAAG,KAAK;AACnB,QAAA,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC;IAC1C;AACA,IAAA,IAAI,KAAK,GAAA;QACP,OAAO,IAAI,CAAC,MAAM;IACpB;IAEA,IAAa,QAAQ,CAAC,KAAa,EAAA;AACjC,QAAA,IAAI,CAAC,SAAS,GAAG,KAAK,IAAI,IAAI;AAC9B,QAAA,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC;IAC1C;AACA,IAAA,IAAI,QAAQ,GAAA;QACV,OAAO,IAAI,CAAC,SAAS;IACvB;IAEA,IAAa,OAAO,CAAC,KAAsB,EAAA;AACzC,QAAA,IAAI,CAAC,QAAQ,GAAG,KAAK;AACrB,QAAA,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE;AAC/B,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,SAAS,CAAC,MAAK;AAC7D,YAAA,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE;AACzB,QAAA,CAAC,CAAC;IACJ;AACA,IAAA,IAAI,OAAO,GAAA;QACT,OAAO,IAAI,CAAC,QAAQ;IACtB;IAES,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;;AAGvB,IAAA,OAAO,GAAG,MAAM,CAAmB,EAAE,8EAAC;AAE/C,IAAA,QAAQ,CAAC,MAAsB,EAAA;AAC7B,QAAA,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC;AAC9B,QAAA,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE;AAC7B,QAAA,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE;IAC7B;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA;;;;;;;;AAQG;AACH,IAAA,eAAe,CAAC,MAAsB,EAAA;AACpC,QAAA,OAAO,MAAM;IACf;AAEA;;;;AAIG;AACH,IAAA,UAAU,CAAC,MAAsB,EAAA;AAC/B,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,CAAA,CAAA,EAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA,CAAE,CAAC;IAClD;AAEA;;;;;;AAMG;AACH,IAAA,UAAU,CAAC,MAAsB,EAAA;AAC/B,QAAA,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;AACvD,QAAA,MAAM,IAAI,GAAG,GAAG,IAAI,KAAK;AACzB,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE;IACvD;AAEA,IAAA,SAAS,CAAC,MAAsB,EAAA;QAC9B,OAAO,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC;IAClD;AAEA,IAAA,WAAW,CAAC,MAAsB,EAAA;QAChC,OAAO,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC;IAClD;;AAGA,IAAA,SAAS,CAAC,MAAsB,EAAA;AAC9B,QAAA,OAAO,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC;IAChE;;IAGA,gBAAgB,GAAA;AACd,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK;;;QAGjC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;AAAE,YAAA,OAAO,GAAG;QACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC/E,QAAA,IAAI,QAAQ;AAAE,YAAA,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;AAChF,QAAA,IAAI,MAAM;AAAE,YAAA,OAAO,MAAM;QACzB,OAAO,OAAO,KAAK,KAAK,QAAQ,GAAG,YAAY,CAAC,KAA+B,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,KAAK,IAAI,GAAG,CAAC;IACxH;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGApJW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,mBAAmB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,QAAA,EAAA,UAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAhEpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA/DS,mBAAmB,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAiElB,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBArE/B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,iBAAiB;AAC3B,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DT,EAAA,CAAA;AACF,iBAAA;;sBA2BE;;sBAQA;;sBAQA;;sBAWA;;sBACA;;;MCjEU,yBAAyB,CAAA;AACpC;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AAC5C,IAAA,OAAO,GAAG,MAAM,CAAC,qBAAqB,CAAC;AAEhD,IAAA,MAAM;IACN,SAAS,GAAG,IAAI;;IAGxB,IAAa,KAAK,CAAC,KAAwB,EAAA;AACzC,QAAA,IAAI,CAAC,MAAM,GAAG,KAAK;AACnB,QAAA,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC;IAC1C;AACA,IAAA,IAAI,KAAK,GAAA;QACP,OAAO,IAAI,CAAC,MAAM;IACpB;IAEA,IAAa,QAAQ,CAAC,KAAa,EAAA;AACjC,QAAA,IAAI,CAAC,SAAS,GAAG,KAAK,IAAI,IAAI;AAC9B,QAAA,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC;IAC1C;AACA,IAAA,IAAI,QAAQ,GAAA;QACV,OAAO,IAAI,CAAC,SAAS;IACvB;AAES,IAAA,OAAO;IACP,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;;AAGvB,IAAA,OAAO,GAAG,MAAM,CAAmB,EAAE,8EAAC;AAEtC,IAAA,SAAS,GAAG,CAAC,EAAW,EAAE,EAAW,KAAc,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC;AAE9F,IAAA,WAAW,CAAC,MAAsB,EAAA;QAChC,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;IACtD;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA;;;;;;;;AAQG;AACH,IAAA,eAAe,CAAC,MAAsB,EAAA;AACpC,QAAA,OAAO,MAAM;IACf;AAEA,IAAA,WAAW,CAAC,MAAsB,EAAA;QAChC,OAAO,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC;IAClD;;AAGA,IAAA,SAAS,CAAC,MAAe,EAAA;QACvB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM;AAAE,YAAA,OAAO,GAAG;AACxD,QAAA,OAAO;aACJ,GAAG,CAAC,CAAC,IAAG;YACP,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AACtE,YAAA,IAAI,GAAG;AAAE,gBAAA,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;YACrC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC;AAC5E,YAAA,IAAI,MAAM;AAAE,gBAAA,OAAO,MAAM;YACzB,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,GAAG,YAAY,CAAC,CAA2B,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;AACnH,QAAA,CAAC;aACA,IAAI,CAAC,IAAI,CAAC;IACf;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGArGW,yBAAyB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAzB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,yBAAyB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,wBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,QAAA,EAAA,UAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA5D1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA3DS,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,cAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,uBAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,kCAAA,EAAA,QAAA,EAAA,2FAAA,EAAA,MAAA,EAAA,CAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FA6DlB,yBAAyB,EAAA,UAAA,EAAA,CAAA;kBAjErC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,wBAAwB;AAClC,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DT,EAAA,CAAA;AACF,iBAAA;;sBAoBE;;sBAQA;;sBAQA;;sBACA;;sBACA;;;AC3GH;;;;;;;AAOG;MAEU,wBAAwB,CAAA;AAClB,IAAA,QAAQ,GACvB,MAAM,CAAC,mBAAmB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI,GAAG,EAAiC;AAE7F;;;AAGG;AACH,IAAA,OAAO,CAAC,SAAiB,EAAA;QACvB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI;IAC7C;AAEA,IAAA,GAAG,CAAC,SAAiB,EAAA;QACnB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC;IACrC;wGAdW,wBAAwB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAxB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,wBAAwB,cADX,MAAM,EAAA,CAAA;;4FACnB,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBADpC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACOlC;AACA,MAAM,SAAS,GAAG,GAAG;AAErB;;;;;;;;;;;;;AAaG;MAEU,sBAAsB,CAAA;AAChB,IAAA,QAAQ,GAAG,MAAM,CAAC,wBAAwB,CAAC;AAC3C,IAAA,KAAK,GAAG,MAAM,CAAC,sBAAsB,CAAC;;AAGtC,IAAA,QAAQ,GAAG,IAAI,GAAG,EAAsC;;AAExD,IAAA,MAAM,GAAG,IAAI,GAAG,EAAkB;AAEnD;;;AAGG;AACH,IAAA,MAAM,IAAI,CAAC,SAAiB,EAAE,MAA8B,EAAE,EAAA;AAC5D,QAAA,MAAM,GAAG,GAAG,sBAAsB,CAAC,SAAS,EAAE;YAC5C,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,aAAa,EAAE,GAAG,CAAC,aAAa;YAChC,WAAW,EAAE,GAAG,CAAC,WAAW;AAC7B,SAAA,CAAC;QAEF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;AAClC,QAAA,IAAI,MAAM;AAAE,YAAA,OAAO,MAAM;QAEzB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;AACtC,QAAA,IAAI,OAAO;AAAE,YAAA,OAAO,OAAO;QAE3B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC;AAC/C,QAAA,IAAI,CAAC,MAAM;AAAE,YAAA,OAAO,EAAE;QAEtB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG;aACjC,IAAI,CAAC,GAAG,IAAG;;AAEV,YAAA,MAAM,OAAO,GAAG,yBAAyB,CACvC,GAAyB,EACzB,GAAG,CAAC,aAAa,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,EAAE,GAAG,SAAS,EACnF,GAAG,CAAC,IAAI,IAAI,IAAI,CACjB;YACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC;AAC5B,YAAA,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,OAAO,CAAC;AACzD,YAAA,OAAO,OAAO;AAChB,QAAA,CAAC,CAAC;;;;QAKJ,MAAM,OAAO,GAAG;AACb,aAAA,KAAK,CAAC,MAAM,EAAuB;AACnC,aAAA,OAAO,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAE3C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC;AAC/B,QAAA,OAAO,OAAO;IAChB;;AAGA,IAAA,IAAI,CAAC,SAAiB,EAAE,GAAA,GAA8B,EAAE,EAAA;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,sBAAsB,CAAC,SAAS,EAAE;YAChC,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,aAAa,EAAE,GAAG,CAAC,aAAa;YAChC,WAAW,EAAE,GAAG,CAAC,WAAW;AAC7B,SAAA,CAAC,CACH;IACH;AAEA;;;AAGG;AACH,IAAA,QAAQ,CAAC,SAAiB,EAAE,KAAc,EAAE,IAAI,GAAG,IAAI,EAAA;AACrD,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/D;;AAGA,IAAA,UAAU,CAAC,SAAiB,EAAA;QAC1B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE;AACnC,YAAA,IAAI,qBAAqB,CAAC,GAAG,CAAC,KAAK,SAAS;AAAE,gBAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;QACtE;AACA,QAAA,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE;AAC3C,YAAA,IAAI,qBAAqB,CAAC,GAAG,CAAC,KAAK,SAAS;AAAE,gBAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC;QACzE;AACA,QAAA,MAAM,MAAM,GAAG,CAAA,EAAG,SAAS,CAAA,EAAG,SAAS,EAAE;AACzC,QAAA,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE;AACzC,YAAA,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC;AAAE,gBAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;QACrD;IACF;IAEA,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;AAClB,QAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE;AACrB,QAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;IACrB;AAEQ,IAAA,cAAc,CAAC,SAAiB,EAAE,IAAY,EAAE,OAA0B,EAAA;AAChF,QAAA,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;YAC5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC;QAC7E;IACF;;AAGQ,IAAA,QAAQ,CAAC,SAAiB,EAAE,IAAY,EAAE,KAAc,EAAA;QAC9D,MAAM,SAAS,GACb,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK;AACjC,cAAE,YAAY,CAAC,KAA+B,EAAE,IAAI;AACpD,cAAE,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;AACzB,QAAA,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;IACrD;;IAIQ,MAAM,CACZ,MAA6B,EAC7B,GAA2B,EAAA;AAE3B,QAAA,IAAI,MAA6B;AACjC,QAAA,IAAI;AACF,YAAA,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC;QACtB;QAAE,OAAO,GAAG,EAAE;;;AAGZ,YAAA,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC;QAC5B;AACA,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;IAC/B;AAEQ,IAAA,SAAS,CAAC,MAA6B,EAAA;AAC7C,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;AAAE,YAAA,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;AACzD,QAAA,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE;;YAE/B,OAAO,IAAI,OAAO,CAAoB,CAAC,OAAO,EAAE,MAAM,KAAI;gBACxD,IAAI,OAAO,GAAG,KAAK;AACnB,gBAAA,MAAM,MAAM,GAAG,CAAC,EAAc,KAAI;AAChC,oBAAA,IAAI,OAAO;wBAAE;oBACb,OAAO,GAAG,IAAI;AACd,oBAAA,EAAE,EAAE;AACN,gBAAA,CAAC;gBACD,MAAM,CAAC,SAAS,CAAC;AACf,oBAAA,IAAI,EAAE,KAAK,IAAI,MAAM,CAAC,MAAM,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;;AAEjD,oBAAA,KAAK,EAAE,GAAG,IAAI,MAAM,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC;;AAEvC,oBAAA,QAAQ,EAAE,MAAM,MAAM,CAAC,MAAM,OAAO,CAAC,EAAE,CAAC,CAAC;AAC1C,iBAAA,CAAC;AACJ,YAAA,CAAC,CAAC;QACJ;AACA,QAAA,OAAO,OAAO,CAAC,OAAO,CAAC,MAAoC,CAAC;IAC9D;AAEQ,IAAA,cAAc,CAAC,KAAc,EAAA;AACnC,QAAA,QACE,OAAO,KAAK,KAAK,QAAQ;AACzB,YAAA,KAAK,KAAK,IAAI;AACd,YAAA,OAAQ,KAAyC,CAAC,SAAS,KAAK,UAAU;IAE9E;;AAGA,IAAA,OAAO,CAAC,CAAU,EAAE,CAAU,EAAE,IAAI,GAAG,IAAI,EAAA;QACzC,OAAO,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC;IAChC;wGAhKW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,sBAAsB,cADT,MAAM,EAAA,CAAA;;4FACnB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBADlC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACxBlC;;;;;;AAMG;MAEU,kBAAkB,CAAA;AACZ,IAAA,QAAQ,GAAG,MAAM,CAAC,wBAAwB,CAAC;AAC3C,IAAA,UAAU,GAAG,MAAM,CAAC,sBAAsB,CAAC;;AAG3C,IAAA,QAAQ,GAAG,IAAI,GAAG,EAAyB;;AAG5D,IAAA,YAAY,CAAC,KAAwB,EAAA;QACnC,OAAO,KAAK,CAAC,eAAe,EAAE,eAAe,IAAI,KAAK,CAAC,EAAE;IAC3D;;AAGA,IAAA,OAAO,CAAC,KAAwB,EAAA;AAC9B,QAAA,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACpD;AAEA;;;AAGG;AACH,IAAA,MAAM,IAAI,CACR,KAAwB,EACxB,MAA8B,EAAE,EAAA;AAEhC,QAAA,MAAM,GAAG,GAAG,KAAK,CAAC,eAAe;AACjC,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;AAAE,YAAA,OAAO,EAAE;;AAGnC,QAAA,MAAM,cAAc,GAClB,GAAG,CAAC,WAAW,KAAK,IAAI,IAAI,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,GAAG,CAAC,WAAW,KAAK,EAAE;AACrF,QAAA,IAAI,GAAG,EAAE,WAAW,IAAI,CAAC,cAAc;AAAE,YAAA,OAAO,EAAE;AAElD,QAAA,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,IAAI;;;;;AAM7B,QAAA,MAAM,cAAc,GAAG,CAAC,EAAE,GAAG,EAAE,YAAY,IAAI,GAAG,EAAE,UAAU,CAAC;AAE/D,QAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE;AACnE,YAAA,GAAG,GAAG;YACN,WAAW,EAAE,cAAc,GAAG,SAAS,GAAG,GAAG,CAAC,WAAW;AACzD,YAAA,OAAO,EAAE,EAAE,IAAI,GAAG,EAAE,OAAO,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE;YAC5D,aAAa,EAAE,GAAG,EAAE,aAAa;YACjC,IAAI;AACL,SAAA,CAAC;AAEF,QAAA,OAAO,kBAAkB,CAAC,OAAO,EAAE,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,CAAC;IAChE;;AAIA;;;;;;AAMG;AACH,IAAA,qBAAqB,CAAC,YAAoB,EAAE,MAAwB,EAAE,IAAI,GAAG,IAAI,EAAA;QAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC;AAChD,QAAA,IAAI,QAAQ;AAAE,YAAA,OAAO,QAAQ;QAE7B,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QACzC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CACrB,MAAM,CAAC,GAAG,CAAC,KAAK,IACd,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE;AAC7C,YAAA,OAAO,EAAE,KAAK,CAAC,eAAe,EAAE,OAAO;AACvC,YAAA,aAAa,EAAE,KAAK,CAAC,eAAe,EAAE,aAAa;YACnD,IAAI;SACL,CAAC,CACH,CACF,CAAC,IAAI,CAAC,MAAM,SAAS,CAAC;QAEvB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC;AACpC,QAAA,OAAO,GAAG;IACZ;;IAGA,MAAM,WAAW,CAAC,YAAoB,EAAA;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC;AAC3C,QAAA,IAAI,CAAC,GAAG;AAAE,YAAA,OAAO,KAAK;AACtB,QAAA,MAAM,GAAG;AACT,QAAA,OAAO,IAAI;IACb;AAEA;;;AAGG;AACH,IAAA,qBAAqB,CACnB,KAAwB,EACxB,WAAoB,EACpB,IAAI,GAAG,IAAI,EAAA;AAEX,QAAA,MAAM,GAAG,GAAG,KAAK,CAAC,eAAe;AACjC,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE;YAC5D,OAAO,EAAE,GAAG,EAAE,OAAO;YACrB,aAAa,EAAE,GAAG,EAAE,aAAa;YACjC,IAAI;AACL,SAAA,CAAC;AACF,QAAA,IAAI,CAAC,MAAM;AAAE,YAAA,OAAO,EAAE;QACtB,OAAO,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,IAAI,CAAC;IAC3D;;AAGA,IAAA,UAAU,CAAC,YAAoB,EAAA;AAC7B,QAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC;IACpC;;AAGQ,IAAA,aAAa,CAAC,MAAwB,EAAA;QAC5C,MAAM,KAAK,GAAwB,EAAE;AACrC,QAAA,MAAM,UAAU,GAAG,CAAC,MAAuC,KAAI;AAC7D,YAAA,KAAK,MAAM,KAAK,IAAI,MAAM,IAAI,EAAE,EAAE;AAChC,gBAAA,MAAM,GAAG,GAAG,KAAK,CAAC,eAAe;AACjC,gBAAA,IAAI,GAAG,EAAE,OAAO,KAAK,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,YAAY,CAAC,EAAE;AAC3E,oBAAA,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;gBACnB;AACA,gBAAA,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC;YAC5B;AACF,QAAA,CAAC;AACD,QAAA,MAAM,QAAQ,GAAG,CAAC,IAAmC,KAAI;AACvD,YAAA,KAAK,MAAM,GAAG,IAAI,IAAI,IAAI,EAAE,EAAE;AAC5B,gBAAA,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC;AACtB,gBAAA,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;YACxB;AACF,QAAA,CAAC;AACD,QAAA,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;AACtB,QAAA,OAAO,KAAK;IACd;wGApIW,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,kBAAkB,cADL,MAAM,EAAA,CAAA;;4FACnB,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAD9B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACTlC;;;;;;;;;AASG;MAEU,yBAAyB,CAAA;AACnB,IAAA,OAAO,GAAG,IAAI,OAAO,EAAsB;AAEnD,IAAA,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE;IAEjD,IAAI,CAAC,OAAe,EAAE,MAA8B,EAAA;QAClD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IACxC;wGAPW,yBAAyB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAzB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,yBAAyB,cADZ,MAAM,EAAA,CAAA;;4FACnB,yBAAyB,EAAA,UAAA,EAAA,CAAA;kBADrC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACRlC;;;;;;;AAOG;MAuEU,uBAAuB,CAAA;AAClC;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;;AAE1B,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AACpD,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEf,IAAA,OAAO,GAAG,MAAM,CAAC,kBAAkB,CAAC;AACpC,IAAA,YAAY,GAAG,MAAM,CAAC,yBAAyB,CAAC;AAChD,IAAA,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AAEvC,IAAA,OAAO,GAAG,MAAM,CAAoB,EAAE,8EAAC;AACvC,IAAA,OAAO,GAAG,MAAM,CAAC,KAAK,8EAAC;;AAEvB,IAAA,cAAc,GAAG,MAAM,CAAC,KAAK,qFAAC;AAEvC,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC;IAC7D;AAEA,IAAA,IAAI,aAAa,GAAA;AACf,QAAA,OAAO,IAAI,CAAC,KAAK,EAAE,eAAe,EAAE,WAAW;IACjD;IAEA,QAAQ,GAAA;QACN,IAAI,IAAI,CAAC,MAAM;YAAE;AACjB,QAAA,KAAK,IAAI,CAAC,MAAM,EAAE;QAClB,IAAI,CAAC,WAAW,EAAE;QAClB,IAAI,CAAC,OAAO,EAAE;AACX,aAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC;AACxC,aAAA,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;IACnE;;AAGA,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE;QACtC,IAAI,CAAC,cAAc,CAAC,GAAG,CACrB,CAAC,CAAC,IAAI,CAAC,aAAa,KAAK,WAAW,KAAK,IAAI,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,EAAE,CAAC,CAClG;AAED,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACrC,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB;QACF;AAEA,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;AACtB,QAAA,IAAI;YACF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC7F;gBAAU;AACR,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;QACzB;IACF;AAEA;;;;;;;;AAQG;AACH,IAAA,iBAAiB,CAAC,KAAc,EAAA;AAC9B,QAAA,IAAI,CAAC,gBAAgB,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IACnE;AAEQ,IAAA,gBAAgB,CAAC,OAAe,EAAA;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC;AACtE,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,IAAI,IAAI,CAAC;IACzD;AAEA,IAAA,QAAQ,CAAC,KAAU,EAAA;QACjB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1E,QAAA,OAAO,MAAM,EAAE,KAAK,IAAI,KAAK,IAAI,GAAG;IACtC;IAEQ,WAAW,GAAA;AACjB,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa;AACnC,QAAA,IAAI,CAAC,QAAQ;AAAE,YAAA,OAAO,SAAS;AAC/B,QAAA,OAAO,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,KAAK;IACnD;;IAGQ,WAAW,GAAA;AACjB,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa;AACnC,QAAA,IAAI,CAAC,QAAQ;YAAE;AACf,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC;AACzD,QAAA,IAAI,CAAC,aAAa;YAAE;AAEpB,QAAA,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,MAAK;AAClF,YAAA,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;AACtB,gBAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAC/C,gBAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC;YAC7C;AACA,YAAA,KAAK,IAAI,CAAC,MAAM,EAAE;AACpB,QAAA,CAAC,CAAC;IACJ;AACA;;;;;AAKG;;AAEH,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGAtIW,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAvB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,uBAAuB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAjExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAhES,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,cAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,uBAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,0BAAA,EAAA,QAAA,EAAA,6GAAA,EAAA,MAAA,EAAA,CAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAkElB,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBAtEnC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,sBAAsB;AAChC,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,mBAAmB,CAAC;AAC9B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DT,EAAA,CAAA;AACF,iBAAA;;sBAgBE;;sBACA;;sBACA;;sBACA;;sBACA;;;AC1GH;;;;;;;;;AASG;MAEU,oBAAoB,CAAA;AACd,IAAA,gBAAgB,GAC/B,MAAM,CAAC,mBAAmB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI,GAAG,EAAqB;AAChE,IAAA,eAAe,GAAG,IAAI,GAAG,EAAqB;AAE/D,IAAA,WAAA,GAAA;;AAEE,QAAA,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,eAAe,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;AACnE,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;QACvB;IACF;;IAGA,QAAQ,CAAC,IAAY,EAAE,SAAoB,EAAA;QACzC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC;IAC3C;;AAGA,IAAA,WAAW,CAAC,GAA8B,EAAA;AACxC,QAAA,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YAC9C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC;QACtC;IACF;AAEA;;;AAGG;AACH,IAAA,OAAO,CAAC,SAAiB,EAAA;AACvB,QAAA,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI;IAC5F;;AAGA,IAAA,GAAG,CAAC,SAAiB,EAAA;AACnB,QAAA,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC;IACpF;;IAGA,eAAe,GAAA;QACb,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;IAC/F;wGAxCW,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAApB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,oBAAoB,cADP,MAAM,EAAA,CAAA;;4FACnB,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBADhC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACRlC;;AAEG;MAEU,WAAW,CAAA;AACL,IAAA,WAAW,GAAG,MAAM,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE;AAE7E;;;AAGG;IACH,aAAa,CAAC,SAAmB,EAAE,aAAwB,EAAA;QACzD,IAAI,CAAC,aAAa,EAAE,MAAM;AAAE,YAAA,OAAO,IAAI;AACvC,QAAA,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACvD;;AAGA,IAAA,oBAAoB,CAAC,QAAkB,EAAE,OAAiB,EAAE,SAAmB,EAAA;QAC7E,OAAOA,oBAAwB,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC;IAC/D;;AAGA,IAAA,gBAAgB,CAAC,SAAmB,EAAA;AAClC,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC1D;;AAGA,IAAA,eAAe,CAAC,KAAwB,EAAE,GAAgC,EAAE,MAAwB,EAAE,SAAmB,EAAA;AACvH,QAAA,OAAOC,eAAmB,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC;IAC7E;;IAGA,cAAc,CAAC,MAAwB,EAAE,SAAmB,EAAA;QAC1D,OAAO;AACL,YAAA,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC;AAChE,YAAA,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC;AAChE,YAAA,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC;SACrE;IACH;wGAlCW,WAAW,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAX,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAW,cADE,MAAM,EAAA,CAAA;;4FACnB,WAAW,EAAA,UAAA,EAAA,CAAA;kBADvB,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACYlC;;;;;;;;AAQG;MAgBU,qBAAqB,CAAA;AACvB,IAAA,KAAK;AACL,IAAA,OAAO;AACP,IAAA,MAAM;AACN,IAAA,YAAY;IACZ,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,SAAS,GAAa,EAAE;AAGhB,IAAA,SAAS;AAET,IAAA,aAAa,GAAG,MAAM,CAAC,oBAAoB,CAAC;AAC5C,IAAA,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;AAClD;;;;AAIG;AACc,IAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAEpC,YAAY,GAAiC,IAAI;AAEzD,IAAA,WAAW,CAAC,QAAuB,EAAA;QACjC,IAAI,CAAC,UAAU,EAAE;IACnB;IAEQ,UAAU,GAAA;QAChB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE;AAElC,QAAA,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;QAClE,IAAI,CAAC,cAAc,EAAE;YACnB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;AACpC,YAAA,OAAO;QACT;;QAGA,MAAM,GAAG,GAA2B,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,GAAG,IAAI;QAC5G,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;;AAG1G,QAAA,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,YAAY,cAAc,EAAE;YAC7E,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC;YACzC;QACF;AAEA,QAAA,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE;QACtB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,cAAc,EAAE;YACjE,QAAQ,EAAE,IAAI,CAAC,QAAQ;AACxB,SAAA,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC;QACzC,IAAI,CAAC,YAAY,EAAE;AACnB,QAAA,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,aAAa,EAAE;IACrD;AAEA;;;;AAIG;AACK,IAAA,cAAc,CAAC,IAAY,EAAA;QACjC,IAAI,CAAC,SAAS,EAAE,IAAI,qBAAqB,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE;AACjE,QAAA,qBAAqB,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;AAC3C,QAAA,OAAO,CAAC,IAAI,CACV,CAAA,6DAAA,EAAgE,IAAI,CAAA,gCAAA,CAAkC;YACpG,CAAA,sCAAA,EAAyC,IAAI,CAAA,gDAAA,CAAkD,CAClG;IACH;AAEQ,IAAA,OAAgB,WAAW,GAAG,IAAI,GAAG,EAAU;AAEvD;;;;;;;AAOG;IACH,OAAO,GAAA;AACL,QAAA,IAAI,CAAC,YAAY,EAAE,iBAAiB,CAAC,aAAa,EAAE;IACtD;AAEA;;;;;;;;;;;;;;AAcG;IACK,YAAY,GAAA;AAClB,QAAA,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE;QAC9B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE;AAEnB,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IAC7E;AAEQ,IAAA,UAAU;IAElB,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE;IAChC;AAEA;;;;;;AAMG;IACK,SAAS,CAAC,GAA0B,EAAE,MAAe,EAAA;QAC3D,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC;QACjC,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC;QACrC,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC;AACvC,QAAA,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;AAChE,QAAA,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAChC;wGA5HW,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAArB,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,MAAA,EAAA,QAAA,EAAA,YAAA,EAAA,cAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,WAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,WAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,IAAA,EASA,gBAAgB,EAAA,MAAA,EAAA,IAAA,EAAA,CAAA,EAAA,aAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EApBtC,CAAA,wCAAA,CAA0C,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,+CAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAWzC,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBAfjC,SAAS;AACS,YAAA,IAAA,EAAA,CAAA,EAAA,eAAA,EAAA,uBAAuB,CAAC,MAAM,EAAA,QAAA,EACrC,mBAAmB,EAAA,UAAA,EACjB,IAAI,YACN,CAAA,wCAAA,CAA0C,EAAA,MAAA,EAAA,CAAA,+CAAA,CAAA,EAAA;;sBAYnD;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBAEA,SAAS;uBAAC,WAAW,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,EAAE;;;AC9ClE;MAqEa,mBAAmB,CAAA;;AAEX,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AACpF,IAAA,KAAK;AACL,IAAA,OAAO;AACP,IAAA,MAAM;IACN,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;IACvB,SAAS,GAAa,EAAE;;AAGjC,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA,IAAA,eAAe,CAAC,OAAe,EAAA;AAC7B,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,OAAoB;AACvC,QAAA,OAAO,KAAK,EAAE,GAAG,CAAC,OAAO,CAAoB;IAC/C;wGAvBW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,mBAAmB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,MAAA,EAAA,QAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA/DpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,yQAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,EAAA,CAAA,UAAA,CAAA,MAxCS,mBAAmB,oDAAmB,qBAAqB,CAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,cAAA,EAAA,UAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAgE1D,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBApE/B,SAAS;AACS,YAAA,IAAA,EAAA,CAAA,EAAA,eAAA,EAAA,uBAAuB,CAAC,MAAM,EAAA,QAAA,EACrC,iBAAiB,EAAA,UAAA,EACf,IAAI,WACP,CAAC,mBAAmB,EAAE,UAAU,CAAC,MAAM,qBAAqB,CAAC,CAAC,EAAA,QAAA,EAC7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,yQAAA,CAAA,EAAA;;sBA2BA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;;AChFH;;AAEG;MAEU,wBAAwB,CAAA;AAClB,IAAA,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI,GAAG,EAAE;AAC9E,IAAA,aAAa,GAAG,MAAM,CAAC,wBAAwB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI,GAAG,EAAE;AAElG;;;AAGG;AACH,IAAA,OAAO,CAAC,YAAoB,EAAA;QAC1B,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE;YAC3C,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,YAAY,CAAC;QAChD;QAEA,IAAI,YAAY,KAAK,UAAU;YAAE,OAAO,UAAU,CAAC,QAAQ;QAC3D,IAAI,YAAY,KAAK,OAAO;YAAE,OAAO,UAAU,CAAC,KAAK;AAErD,QAAA,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC;AAC7C,QAAA,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC;QAE/B,IAAI,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;AAAE,YAAA,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;QACjE,IAAI,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;AAAE,YAAA,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;QACjE,IAAI,IAAI,KAAK,WAAW,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;AAAE,YAAA,OAAO,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC;QAC7E,IAAI,IAAI,KAAK,WAAW,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;AAAE,YAAA,OAAO,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC;AAE7E,QAAA,OAAO,IAAI;IACb;;IAGA,UAAU,CAAC,gBAA0B,EAAE,EAAA;QACrC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAuB,CAAC,KAAK,IAAI,CAAC;IAC5F;;AAGA,IAAA,iBAAiB,CAAC,MAAmC,EAAA;AACnD,QAAA,IAAI,CAAC,MAAM;AAAE,YAAA,OAAO,EAAE;AACtB,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;AAAE,YAAA,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAEzD,MAAM,MAAM,GAAkB,EAAE;QAChC,IAAI,MAAM,CAAC,QAAQ;AAAE,YAAA,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;AACrD,QAAA,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS;AAAE,YAAA,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACrE,QAAA,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS;AAAE,YAAA,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACrE,QAAA,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS;AAAE,YAAA,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AACvF,QAAA,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS;AAAE,YAAA,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AACvF,QAAA,IAAI,MAAM,CAAC,OAAO,EAAE;;;;;AAKlB,YAAA,IAAI;AACF,gBAAA,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACjD;YAAE,OAAO,GAAG,EAAE;AACZ,gBAAA,IAAI,CAAC,QAAQ,CACX,CAAA,QAAA,EAAW,MAAM,CAAC,OAAO,CAAA,CAAE,EAC3B,CAAA,aAAA,EAAgB,MAAM,CAAC,OAAO,CAAA,oCAAA,CAAsC;AAClE,oBAAA,CAAA,CAAA,EAAI,GAAG,YAAY,KAAK,GAAG,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA,yBAAA,CAA2B;AAC/E,oBAAA,CAAA,gFAAA,CAAkF,CACrF;YACH;QACF;QACA,IAAI,MAAM,CAAC,KAAK;AAAE,YAAA,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;;;;;QAM/C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE;YACrC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;AAC5B,YAAA,IAAI,EAAE;AAAE,gBAAA,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;;AAClB,gBAAA,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,GAAG,CAAC;QACzC;AAEA,QAAA,OAAO,MAAM;IACf;AAEA;;;;;;;;;AASG;AACH,IAAA,sBAAsB,CAAC,MAAmC,EAAA;QACxD,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;AAAE,YAAA,OAAO,EAAE;QAE/C,MAAM,GAAG,GAAuB,EAAE;QAClC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,WAAW,IAAI,EAAE,EAAE;YAC1C,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC;AACtC,YAAA,IAAI,EAAE;AAAE,gBAAA,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;;AACf,gBAAA,IAAI,CAAC,cAAc,CAAC,aAAa,EAAE,GAAG,CAAC;QAC9C;AACA,QAAA,OAAO,GAAG;IACZ;AAEA;;;;;;;;;;;AAWG;IACK,cAAc,CAAC,IAA8B,EAAE,GAAW,EAAA;AAChE,QAAA,IAAI,CAAC,QAAQ,CACX,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,EAChB,CAAA,oBAAA,EAAuB,GAAG,CAAA,+BAAA,EAAkC,IAAI,CAAA,uBAAA,CAAyB;AACvF,YAAA,CAAA,iDAAA,EACE,IAAI,KAAK,aAAa,GAAG,iBAAiB,GAAG,YAC/C,CAAA,KAAA,EAAQ,GAAG,CAAA,YAAA,CAAc,CAC5B;IACH;;AAGiB,IAAA,MAAM,GAAG,IAAI,GAAG,EAAU;IAEnC,QAAQ,CAAC,EAAU,EAAE,OAAe,EAAA;QAC1C,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE;AACzC,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AACnB,QAAA,OAAO,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAA,CAAE,CAAC;IACjD;wGA7HW,wBAAwB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAxB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,wBAAwB,cADX,MAAM,EAAA,CAAA;;4FACnB,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBADpC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACClC;MAwJa,mBAAmB,CAAA;;AAEX,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;;AAE1B,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC7F;;;;AAIG;AACc,IAAA,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC;AACvC,IAAA,KAAK;AACL,IAAA,OAAO;AACP,IAAA,MAAM;IACN,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;IACvB,SAAS,GAAa,EAAE;AAEhB,IAAA,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC;AACxB,IAAA,iBAAiB,GAAG,MAAM,CAAC,wBAAwB,CAAC;;AAGrE,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA,IAAA,IAAI,SAAS,GAAA;QACX,OAAO,IAAI,CAAC,OAAoB;IAClC;IAEA,mBAAmB,CAAC,SAA0B,EAAE,OAAe,EAAA;AAC7D,QAAA,OAAQ,SAAuB,CAAC,GAAG,CAAC,OAAO,CAAoB;IACjE;IAEA,OAAO,GAAA;QACL,MAAM,QAAQ,GAAwB,EAAE;QACxC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,EAAE;AAC7C,YAAA,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAC;AAC7E,YAAA,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,IAAI,EAAE,UAAU,CAAC;QAC/D;QACA,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;AACrC,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;AAC1B,QAAA,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE;IACzB;AAEA,IAAA,UAAU,CAAC,KAAa,EAAA;AACtB,QAAA,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC;AAC9B,QAAA,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE;IACzB;wGArDW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,mBAAmB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,MAAA,EAAA,QAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlJpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6ET,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,k/BAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,EAAA,CAAA,UAAA,CAAA,MA9ES,mBAAmB,oDAAmB,qBAAqB,CAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,cAAA,EAAA,UAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAmJ1D,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAvJ/B,SAAS;AACS,YAAA,IAAA,EAAA,CAAA,EAAA,eAAA,EAAA,uBAAuB,CAAC,MAAM,EAAA,QAAA,EACrC,iBAAiB,EAAA,UAAA,EACf,IAAI,WACP,CAAC,mBAAmB,EAAE,UAAU,CAAC,MAAM,qBAAqB,CAAC,CAAC,EAAA,QAAA,EAC7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6ET,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,k/BAAA,CAAA,EAAA;;sBAgFA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;;AC9KH;;;;;;AAMG;MAEU,iBAAiB,CAAA;IACX,OAAO,GAAG,MAAM,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAErE,IAAA,IAAI,UAAU,GAAA;AACZ,QAAA,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO;IACvB;;AAGQ,IAAA,QAAQ,CAAC,IAAU,EAAA;AACzB,QAAA,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE;IAClE;AAEA;;;AAGG;IACH,MAAM,SAAS,CAAC,IAAU,EAAA;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE;AAE3C,QAAA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvD,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE;IACrE;;AAGA,IAAA,aAAa,CAAC,GAA+B,EAAA;AAC3C,QAAA,IAAI,CAAC,GAAG;AAAE,YAAA,OAAO,IAAI;QACrB,IAAI,GAAG,CAAC,GAAG;YAAE,OAAO,GAAG,CAAC,GAAG;AAC3B,QAAA,IAAI,GAAG,CAAC,IAAI,IAAI,OAAO,GAAG,KAAK,WAAW,IAAI,OAAO,GAAG,CAAC,eAAe,KAAK,UAAU,EAAE;YACvF,OAAO,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;QACtC;AACA,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,gBAAgB,CAAC,GAAkB,EAAA;QACjC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE;AACtC,QAAA,IAAI,OAAO,GAAG,KAAK,WAAW,IAAI,OAAO,GAAG,CAAC,eAAe,KAAK,UAAU,EAAE;AAC3E,YAAA,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC;QAC1B;IACF;AAEQ,IAAA,SAAS,CACf,MAAyE,EAAA;AAEzE,QAAA,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE;YAC/B,OAAO,IAAI,OAAO,CAAe,CAAC,OAAO,EAAE,MAAM,KAAI;gBACnD,IAAI,OAAO,GAAG,KAAK;gBACnB,MAAM,CAAC,SAAS,CAAC;oBACf,IAAI,EAAE,KAAK,IAAG;AACZ,wBAAA,IAAI,OAAO;4BAAE;wBACb,OAAO,GAAG,IAAI;wBACd,OAAO,CAAC,KAAK,CAAC;oBAChB,CAAC;oBACD,KAAK,EAAE,GAAG,IAAG;AACX,wBAAA,IAAI,OAAO;4BAAE;wBACb,OAAO,GAAG,IAAI;wBACd,MAAM,CAAC,GAAG,CAAC;oBACb,CAAC;oBACD,QAAQ,EAAE,MAAK;AACb,wBAAA,IAAI,OAAO;4BAAE;wBACb,OAAO,GAAG,IAAI;AACd,wBAAA,MAAM,CAAC,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;oBAC1E,CAAC;AACF,iBAAA,CAAC;AACJ,YAAA,CAAC,CAAC;QACJ;AACA,QAAA,OAAO,OAAO,CAAC,OAAO,CAAC,MAA8C,CAAC;IACxE;AAEQ,IAAA,cAAc,CAAC,KAAc,EAAA;AACnC,QAAA,QACE,OAAO,KAAK,KAAK,QAAQ;AACzB,YAAA,KAAK,KAAK,IAAI;AACd,YAAA,OAAQ,KAAoC,CAAC,SAAS,KAAK,UAAU;IAEzE;wGA3EW,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAjB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,iBAAiB,cADJ,MAAM,EAAA,CAAA;;4FACnB,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAD7B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACDlC;;;;;AAKG;MAqFU,mBAAmB,CAAA;AAC9B;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;;AAE1B,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AACpD,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEf,IAAA,OAAO,GAAG,MAAM,CAAC,iBAAiB,CAAC;AAE3C,IAAA,SAAS,GAAG,MAAM,CAAC,KAAK,gFAAC;AACzB,IAAA,WAAW,GAAG,MAAM,CAAgB,IAAI,kFAAC;;IAG1C,aAAa,GAAmB,IAAI;IACpC,YAAY,GAAkB,IAAI;AAE1C,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;IAEA,UAAU,GAAA;QACR,MAAM,KAAK,GAAI,IAAI,CAAC,OAAO,EAAE,KAAwB,IAAI,IAAI;AAC7D,QAAA,IAAI,KAAK,KAAK,IAAI,CAAC,aAAa;YAAE,OAAO,IAAI,CAAC,YAAY;QAE1D,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC;AAChD,QAAA,IAAI,CAAC,aAAa,GAAG,KAAK;QAC1B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC;QACrD,OAAO,IAAI,CAAC,YAAY;IAC1B;IAEA,MAAM,YAAY,CAAC,IAAsB,EAAA;AACvC,QAAA,IAAI,CAAC,IAAI;YAAE;AACX,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;AAC1B,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AACxB,QAAA,IAAI;AACF,YAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACzD,YAAA,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE;QAC9B;AAAE,QAAA,MAAM;AACN,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,kCAAkC,CAAC;QAC1D;gBAAU;AACR,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QAC3B;IACF;IAEA,MAAM,GAAA;AACJ,QAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC3B,QAAA,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE;IAC9B;IAEA,WAAW,GAAA;QACT,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC;IAClD;;;AAGA,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGAhFW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,mBAAmB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA/EpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6ET,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAEU,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBApF/B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,iBAAiB;AAC3B,oBAAA,UAAU,EAAE,IAAI;AAChB,oBAAA,OAAO,EAAE,EAAE;AACX,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6ET,EAAA,CAAA;AACF,iBAAA;;sBAgBE;;sBACA;;sBACA;;sBACA;;sBACA;;;AC7GH;;;AAGG;MAwFU,kBAAkB,CAAA;AAC7B;;;AAGG;IACc,UAAU,GAAG,mBAAmB,EAAE;IACzC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAA;AACzB,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;IACxD;;AAGmB,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;;AAE1B,IAAA,UAAU,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,WAAW;AAC5E,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AACpD,IAAA,KAAK;AACL,IAAA,OAAO;IACP,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,MAAM,GAAY,KAAK;AAEf,IAAA,OAAO,GAAG,MAAM,CAAC,iBAAiB,CAAC;AAE3C,IAAA,SAAS,GAAG,MAAM,CAAC,KAAK,gFAAC;AACzB,IAAA,WAAW,GAAG,MAAM,CAAgB,IAAI,kFAAC;AAElD,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACvD;AAEA,IAAA,IAAY,KAAK,GAAA;AACf,QAAA,OAAQ,IAAI,CAAC,OAAO,EAAE,KAAwB,IAAI,IAAI;IACxD;IAEA,OAAO,GAAA;AACL,QAAA,OAAO,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,IAAI;IAChC;IAEA,QAAQ,GAAA;QACN,OAAO,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI;IACxC;IAEA,MAAM,YAAY,CAAC,IAAsB,EAAA;AACvC,QAAA,IAAI,CAAC,IAAI;YAAE;AACX,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;AAC1B,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AACxB,QAAA,IAAI;AACF,YAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACzD,YAAA,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE;QAC9B;AAAE,QAAA,MAAM;AACN,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,kCAAkC,CAAC;QAC1D;gBAAU;AACR,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QAC3B;IACF;IAEA,MAAM,GAAA;AACJ,QAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC3B,QAAA,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE;IAC9B;;;AAGA,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtD;;IAGU,WAAW,GAAA;AACnB,QAAA,OAAO,gBAAgB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAChG;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AAAE,YAAA,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IAC3F;wGA1EW,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlFnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgFT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAEU,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAvF9B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;oBACT,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE,gBAAgB;AAC1B,oBAAA,UAAU,EAAE,IAAI;AAChB,oBAAA,OAAO,EAAE,EAAE;AACX,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgFT,EAAA,CAAA;AACF,iBAAA;;sBAgBE;;sBACA;;sBACA;;sBACA;;sBACA;;;AC/FH;;;;;;;;;;;;;;;;AAgBG;AAEH;SACgB,iBAAiB,GAAA;IAC/B,OAAO;AACL,QAAA,IAAI,EAAE,kBAAkB;AACxB,QAAA,QAAQ,EAAE,sBAAsB;AAChC,QAAA,QAAQ,EAAE,sBAAsB;AAChC,QAAA,MAAM,EAAE,oBAAoB;AAC5B,QAAA,QAAQ,EAAE,sBAAsB;AAChC,QAAA,KAAK,EAAE,mBAAmB;AAC1B,QAAA,QAAQ,EAAE,sBAAsB;AAChC,QAAA,QAAQ,EAAE,sBAAsB;AAChC,QAAA,OAAO,EAAE,qBAAqB;AAC9B,QAAA,IAAI,EAAE,kBAAkB;AACxB,QAAA,QAAQ,EAAE,sBAAsB;AAChC,QAAA,IAAI,EAAE,kBAAkB;AACxB,QAAA,SAAS,EAAE,uBAAuB;AAClC,QAAA,QAAQ,EAAE,sBAAsB;AAChC,QAAA,KAAK,EAAE,mBAAmB;AAC1B,QAAA,WAAW,EAAE,yBAAyB;AACtC,QAAA,YAAY,EAAE,uBAAuB;AACrC,QAAA,KAAK,EAAE,mBAAmB;AAC1B,QAAA,KAAK,EAAE,mBAAmB;AAC1B,QAAA,KAAK,EAAE,mBAAmB;AAC1B,QAAA,IAAI,EAAE,kBAAkB;KACzB;AACH;AAEA;AACM,SAAU,iBAAiB,CAAC,KAAgC,EAAA;AAChE,IAAA,OAAO,wBAAwB,CAAC;QAC9B,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE;AAC3D,KAAA,CAAC;AACJ;AAEA;SACgB,wBAAwB,GAAA;AACtC,IAAA,OAAO,iBAAiB,CAAC,iBAAiB,EAAE,CAAC;AAC/C;;AC7EA;;;AAGG;MAEU,mBAAmB,CAAA;AACb,IAAA,QAAQ,GAAG,MAAM,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI,GAAG,EAAE;AAElF,IAAA,GAAG,CAAC,GAAW,EAAA;QACb,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;IAC/B;IAEA,MAAM,GAAG,CAAC,GAAW,EAAE,IAAS,EAAE,UAAe,EAAE,EAAA;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;AACnC,QAAA,IAAI,CAAC,IAAI;AAAE,YAAA,OAAO,IAAI;AACtB,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;IAC5B;wGAXW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,mBAAmB,cADN,MAAM,EAAA,CAAA;;4FACnB,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAD/B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACyBlC;;;;;;;;;;;;AAYG;MAEU,sBAAsB,CAAA;AACjC;;AAEG;AACH,IAAA,QAAQ,CACN,KAAoC,EACpC,MAA+B,EAC/B,cAAwC,EACxC,OAAkC,EAAA;QAElC,OAAO,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,CAAC;IAClE;AAEA;;AAEG;AACH,IAAA,YAAY,CAAC,KAAoC,EAAE,KAAa,EAAE,MAAwB,EAAA;QACxF,OAAO,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC;IAChD;AAEA;;;;;;;AAOG;AACH,IAAA,cAAc,CACZ,MAA4B,EAC5B,KAAwB,EACxB,KAAwB,EACxB,MAA+B,EAAA;QAE/B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;AAClC,QAAA,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAAE,YAAA,OAAO,KAAK;AAC3D,QAAA,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAAE,YAAA,OAAO,IAAI;AACzD,QAAA,OAAO,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC;IAC/C;;IAGA,YAAY,CAAC,MAA4B,EAAE,GAAoB,EAAA;QAC7D,IAAI,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;AAAE,YAAA,OAAO,KAAK;AACpD,QAAA,OAAO,GAAG,CAAC,UAAU,KAAK,KAAK,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;IACtE;AAEA;;;;;;;;;;;;;;;;;;;;AAoBG;IACH,oBAAoB,CAAC,OAAmC,EAAE,GAAoB,EAAA;QAC5E,MAAM,gBAAgB,GAAa,EAAE;AAErC,QAAA,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;AAC3B,YAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK;YACzB,IAAI,CAAC,KAAK,EAAE,EAAE;gBAAE;YAEhB,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC;AACpC,YAAA,IAAI,gBAAgB,CAAC,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,UAAU,CAAC,CAAA,EAAG,MAAM,CAAA,CAAA,CAAG,CAAC,CAAC;gBAAE;YAEvE,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC;AACtF,YAAA,IAAI,MAAM,KAAK,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;AAAE,gBAAA,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC;YAEhG,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC;AAClC,YAAA,IAAI,CAAC,IAAI;gBAAE;YAEX,IAAI,MAAM,EAAE;gBACV,IAAI,IAAI,CAAC,OAAO;oBAAE,IAAI,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;YACtD;iBAAO,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;gBAC3C,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;YACnC;QACF;IACF;AAEA;;;;;;AAMG;AACK,IAAA,QAAQ,CAAC,MAA4B,EAAA;QAC3C,IAAI,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC;QACxC,IAAI,CAAC,IAAI,EAAE;YACT,IAAI,GAAG,EAAE,MAAM,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE;YACnF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;QACrC;AACA,QAAA,OAAO,IAAI;IACb;AAEiB,IAAA,YAAY,GAAG,IAAI,OAAO,EAGxC;wGA9GQ,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,sBAAsB,cADT,MAAM,EAAA,CAAA;;4FACnB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBADlC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;MCvCrB,mBAAmB,CAAA;AACb,IAAA,KAAK,GAAG,IAAI,GAAG,EAA4B;AAC3C,IAAA,QAAQ,GAAG,IAAI,GAAG,EAAiD;AAEnE,IAAA,OAAO;AAExB,IAAA,WAAA,CAA+C,OAAa,EAAA;AAC1D,QAAA,IAAI,CAAC,OAAO,GAAG,OAAO;IACxB;;IAGA,MAAM,SAAS,CAAC,SAAiB,EAAA;AAC/B,QAAA,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,OAAO;AAAE,YAAA,OAAO,SAAS;AACjD,QAAA,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;AAC/D,QAAA,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC;AAErE,QAAA,MAAM,OAAO,GAAG,CAAC,YAAW;AAC1B,YAAA,IAAI;gBACF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAQ,CAAC,SAAS,CAAC;AACpC,gBAAA,IAAI,QAAsC;AAE1C,gBAAA,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE;AACrB,oBAAA,QAAQ,GAAG,MAAM,cAAc,CAAC,GAAU,CAAC;gBAC7C;qBAAO;oBACL,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,GAAU,CAAC;gBAC9C;gBAEA,IAAI,QAAQ,EAAE;oBACZ,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC;gBACrC;AACA,gBAAA,OAAO,QAAQ;YACjB;YAAE,OAAO,GAAG,EAAE;gBACZ,OAAO,CAAC,IAAI,CAAC,CAAA,sDAAA,EAAyD,SAAS,CAAA,CAAA,CAAG,EAAE,GAAG,CAAC;AACxF,gBAAA,OAAO,SAAS;YAClB;oBAAU;AACR,gBAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;YACjC;QACF,CAAC,GAAG;QAEJ,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC;AACrC,QAAA,OAAO,OAAO;IAChB;;AAGA,IAAA,UAAU,CAAC,SAAkB,EAAA;QAC3B,IAAI,SAAS,EAAE;AACb,YAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC;QAC9B;aAAO;AACL,YAAA,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;QACpB;IACF;AAlDW,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,kBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,mBAAmB,kBAME,aAAa,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AANlC,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,mBAAmB,cADN,MAAM,EAAA,CAAA;;4FACnB,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAD/B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;0BAOnB;;0BAAY,MAAM;2BAAC,aAAa;;;ACE/C;;;;;;;;;;;;;;;;AAgBG;MAEU,oBAAoB,CAAA;AACd,IAAA,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC;AACxB,IAAA,iBAAiB,GAAG,MAAM,CAAC,wBAAwB,CAAC;AAErE;;;;;;;AAOG;AACH,IAAA,SAAS,CAAC,MAAwB,EAAA;QAChC,MAAM,KAAK,GAAoC,EAAE;AAEjD,QAAA,MAAM,gBAAgB,GAAG,CAAC,IAAuB,EAAE,WAA4C,KAAI;AACjG,YAAA,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;AACtB,gBAAA,IAAI,GAAG,CAAC,QAAQ,EAAE;oBAChB,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE,EAAE;AACpC,wBAAA,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW,CAAC;oBAC5C;oBACA,IAAI,GAAG,CAAC,QAAQ;AAAE,wBAAA,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC;gBAC/D;qBAAO;oBACL,MAAM,QAAQ,GAAoC,EAAE;oBACpD,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE,EAAE;AACpC,wBAAA,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC;oBACzC;oBACA,IAAI,GAAG,CAAC,QAAQ;AAAE,wBAAA,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC;AAC1D,oBAAA,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;gBAC/C;YACF;AACF,QAAA,CAAC;QAED,gBAAgB,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,KAAK,CAAC;QAC1C,OAAO,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC;IAC7B;;IAGA,iBAAiB,CAAC,KAAwB,EAAE,KAAsC,EAAA;AAChF,QAAA,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE;YAC1B,MAAM,QAAQ,GAAoC,EAAE;YACpD,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,QAAQ,IAAI,EAAE,EAAE;AACxC,gBAAA,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC;YACzC;AACA,YAAA,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC3C;AAAO,aAAA,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE;AACjC,YAAA,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC;aAAO;AACL,YAAA,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAC;AAC7E,YAAA,MAAM,eAAe,GAAG,IAAI,CAAC,iBAAiB,CAAC,sBAAsB,CAAC,KAAK,CAAC,UAAU,CAAC;AACvF,YAAA,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC/B,EAAE,KAAK,EAAE,KAAK,CAAC,YAAY,IAAI,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,EAAE,EACxE,UAAU,EACV,eAAe,CAChB;QACH;IACF;;IAGA,aAAa,CAAC,KAAoC,EAAE,IAAa,EAAA;AAC/D,QAAA,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM;YAAE,OAAO,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QAE1D,MAAM,QAAQ,GAAoC,EAAE;AACpD,QAAA,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,QAAQ,EAAE;AAClC,YAAA,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC;QACzC;QACA,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;AACrC,QAAA,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;AAAE,YAAA,KAAK,CAAC,UAAU,CAAC,IAA+B,CAAC;AACvF,QAAA,OAAO,KAAK;IACd;;AAGA,IAAA,WAAW,CAAC,IAAsB,EAAE,MAA2C,EAAE,KAAa,EAAA;AAC5F,QAAA,IAAI,CAAC,IAAI;AAAE,YAAA,OAAO,IAAI;QACtB,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC;AAC5C,QAAA,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,IAAI;QAE3C,IAAI,IAAI,GAA2B,IAAI;AACvC,QAAA,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE;YACpB,IAAI,CAAC,IAAI,IAAI,EAAE,IAAI,YAAY,SAAS,CAAC;AAAE,gBAAA,OAAO,IAAI;AACtD,YAAA,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACpB;QACA,OAAO,IAAI,YAAY,SAAS,GAAG,IAAI,GAAG,IAAI;IAChD;AAEA;;;;;;;;;AASG;AACH,IAAA,UAAU,CACR,IAAsB,EACtB,MAA2C,EAC3C,OAAe,EACf,YAAqB,EAAA;AAErB,QAAA,IAAI,CAAC,IAAI;AAAE,YAAA,OAAO,IAAI;AAEtB,QAAA,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC;AACrC,QAAA,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;QAExD,IAAI,YAAY,EAAE;AAChB,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC;YAC3D,MAAM,IAAI,GAAG,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC;AACjC,YAAA,IAAI,IAAI;AAAE,gBAAA,OAAO,IAAI;QACvB;QAEA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;AAClC,QAAA,IAAI,QAAQ;AAAE,YAAA,OAAO,QAAQ;AAE7B,QAAA,MAAM,WAAW,GAAG,CAAC,KAAgB,KAA4B;AAC/D,YAAA,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE;gBAC7C,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAC7B,IAAI,GAAG,KAAK,OAAO;AAAE,oBAAA,OAAO,CAAC;AAC7B,gBAAA,IAAI,CAAC,YAAY,SAAS,EAAE;AAC1B,oBAAA,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC;AAC5B,oBAAA,IAAI,KAAK;AAAE,wBAAA,OAAO,KAAK;gBACzB;YACF;AACA,YAAA,OAAO,IAAI;AACb,QAAA,CAAC;AAED,QAAA,OAAO,WAAW,CAAC,IAAI,CAAC;IAC1B;;IAGA,aAAa,CAAC,IAAsB,EAAE,MAA2C,EAAA;AAC/E,QAAA,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM;AAAE,YAAA,OAAO,EAAE;QAC/B,IAAI,MAAM,GAAwB,EAAE;AAEpC,QAAA,MAAM,QAAQ,GAAG,CAAC,IAAuB,KAAI;AAC3C,YAAA,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;gBACtB,MAAM,WAAW,GAA4B,EAAE;gBAC/C,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE,EAAE;AACpC,oBAAA,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;AAC5D,oBAAA,IAAI,IAAI;wBAAE,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK;gBAC9C;gBAEA,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC;gBAE/C,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE,EAAE;AACpC,oBAAA,IAAI,KAAK,CAAC,YAAY,EAAE;AACtB,wBAAA,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;AAC5D,wBAAA,IAAI,IAAI;4BAAE,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC;oBAClE;gBACF;gBAEA,IAAI,GAAG,CAAC,QAAQ;AAAE,oBAAA,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC1C;AACF,QAAA,CAAC;AAED,QAAA,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;AAC3B,QAAA,MAAM,GAAG,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC;AACjD,QAAA,OAAO,MAAM;IACf;AAEA;;;;;;;AAOG;AACH,IAAA,SAAS,CACP,IAAsB,EACtB,MAA2C,EAC3C,IAAyB,EACzB,UAA0C,EAAA;AAE1C,QAAA,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM;AAAE,YAAA,OAAO,EAAE;AACxC,QAAA,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU;AAEzC,QAAA,MAAM,QAAQ,GAAG,CAAC,IAAuB,KAAI;AAC3C,YAAA,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;AACtB,gBAAA,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC;gBAChD,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE,EAAE;oBACpC,IAAI,GAAG,GAAG,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,SAAS;AAChF,oBAAA,IAAI,KAAK,CAAC,YAAY,EAAE;wBACtB,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC;wBACvD,IAAI,MAAM,KAAK,SAAS;4BAAE,GAAG,GAAG,MAAM;oBACxC;oBACA,IAAI,GAAG,KAAK,SAAS;wBAAE;AAEvB,oBAAA,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;AAC5D,oBAAA,IAAI,CAAC,IAAI;wBAAE;oBAEX,IAAI,IAAI,YAAY,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;wBACnD,IAAI,CAAC,KAAK,EAAE;AACZ,wBAAA,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE;AACtB,4BAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;wBAC/D;oBACF;yBAAO;wBACL,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;oBAC5C;AACA,oBAAA,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/B;gBACA,IAAI,GAAG,CAAC,QAAQ;AAAE,oBAAA,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC1C;AACF,QAAA,CAAC;AAED,QAAA,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;AAC3B,QAAA,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,eAAe,CAAC;IACvE;AAEA;;;;;;;;;AASG;AACK,IAAA,cAAc,CACpB,MAAwB,EACxB,IAAyB,EACzB,UAA0C,EAC1C,eAA4B,EAAA;QAE5B,IAAI,CAAC,SAAS,EAAE;AAAE,YAAA,OAAO,EAAE;AAE3B,QAAA,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU;AAChC,QAAA,MAAM,aAAa,GAAG,CAAC,IAAuB,KAAI;AAChD,YAAA,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;AACtB,gBAAA,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClB,IAAI,GAAG,CAAC,QAAQ;AAAE,oBAAA,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC/C;AACF,QAAA,CAAC;AACD,QAAA,aAAa,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QAEhC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAC7B,GAAG;;AAED,QAAA,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;AAChB,YAAA,IAAI,CAAC,GAAG,CAAC,KAAK,SAAS;AACvB,YAAA,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC;AACnB,YAAA,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAC5B;IACH;wGArPW,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;4GAApB,oBAAoB,EAAA,CAAA;;4FAApB,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBADhC;;;AC0BD;;;;;;;;;;;AAWG;AACH,MAAM,aAAa,GAAqC;AACtD,IAAA,IAAI,EAAE,CAAC;AACP,IAAA,KAAK,EAAE,CAAC;AACR,IAAA,QAAQ,EAAE,CAAC;AACX,IAAA,MAAM,EAAE,CAAC;AACT,IAAA,QAAQ,EAAE,CAAC;AACX,IAAA,IAAI,EAAE,CAAC;AACP,IAAA,QAAQ,EAAE,CAAC;AACX,IAAA,IAAI,EAAE,CAAC;AACP,IAAA,SAAS,EAAE,CAAC;AACZ,IAAA,QAAQ,EAAE,CAAC;AACX,IAAA,KAAK,EAAE,CAAC;AACR,IAAA,WAAW,EAAE,CAAC;AACd,IAAA,OAAO,EAAE,CAAC;AACV,IAAA,QAAQ,EAAE,CAAC;AACX,IAAA,YAAY,EAAE,CAAC;;;CAGhB;AAWD;;;;;AAKG;MAoEU,oBAAoB,CAAA;;AAEZ,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;;AAE7C;;;;;;;;;;AAUG;IACH,IACI,MAAM,CAAC,KAAuB,EAAA;AAChC,QAAA,IAAI,CAAC,SAAS,GAAG,KAAK;AACtB,QAAA,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;IACpC;AACA,IAAA,IAAI,MAAM,GAAA;AACR,QAAA,OAAO,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,SAAS;IAChD;AACQ,IAAA,SAAS;AACT,IAAA,gBAAgB;AACf,IAAA,KAAK;AACL,IAAA,WAAW;;AAEX,IAAA,YAAY;IACZ,SAAS,GAAa,EAAE;IACxB,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;;IAEzB,cAAc,GAAa,EAAE;AACtC;;;AAGG;IACM,eAAe,GAAY,IAAI;IAC/B,OAAO,GAAY,KAAK;IACxB,KAAK,GAAkB,IAAI;AACpC;;;;AAIG;IACM,gBAAgB,GAAW,CAAC;AACrC;;;AAGG;IACM,OAAO,GAAY,KAAK;AACjC;;;;;;;;;;;AAWG;IACM,MAAM,GAAqB,OAAO;;AAGjC,IAAA,UAAU,GAAG,IAAI,YAAY,EAAuB;AACpD,IAAA,UAAU,GAAG,IAAI,YAAY,EAAuB;AACpD,IAAA,SAAS,GAAG,IAAI,YAAY,EAAQ;;AAEpC,IAAA,eAAe,GAAG,IAAI,YAAY,EAAU;AACtD;;;AAGG;AACO,IAAA,YAAY,GAAG,IAAI,YAAY,EAAuC;;AAG/D,IAAA,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC;AAC/B,IAAA,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC;AACxB,IAAA,iBAAiB,GAAG,MAAM,CAAC,wBAAwB,CAAC;AACpD,IAAA,YAAY,GAAG,MAAM,CAAC,mBAAmB,CAAC;AAC1C,IAAA,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;AACjC,IAAA,eAAe,GAAG,MAAM,CAAC,sBAAsB,CAAC;;AAEhD,IAAA,SAAS,GAAG,MAAM,CAAC,oBAAoB,CAAC;;AAExC,IAAA,QAAQ,GAAG,MAAM,CAAC,yBAAyB,CAAC;AAC5C,IAAA,kBAAkB,GAAG,MAAM,CAAC,yBAAyB,CAAC;IACtD,qBAAqB,GAAG,MAAM,CAAC,uBAAuB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC3E,IAAA,UAAU,GAAG,MAAM,CAAC,iBAAiB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE;;AAEhE,IAAA,IAAI,GAAG,MAAM,CAAC,UAAU,CAA4B;;AAEpD,IAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAEzB,MAAM,GAAG,MAAM;;AAGzB,IAAA,SAAS,GAAG,MAAM,CAAS,EAAE,gFAAC;AAC9B,IAAA,YAAY,GAAG,MAAM,CAAS,EAAE,mFAAC;AACjC,IAAA,QAAQ,GAAG,MAAM,CAAC,KAAK,+EAAC;AACxB,IAAA,UAAU,GAAG,MAAM,CAAsB,EAAE,iFAAC;;AAE5C,IAAA,eAAe,GAAG,MAAM,CAAsB,EAAE,sFAAC;;AAEjD,IAAA,cAAc,GAAG,MAAM,CAAsB,IAAI,GAAG,EAAU,qFAAC;;AAGxC,IAAA,SAAS;;AAGI,IAAA,UAAU;;AAGvD,IAAA,IAAI;AAEI,IAAA,QAAQ;AACR,IAAA,SAAS;AACT,IAAA,YAAY;;IAEZ,cAAc,GAAwB,EAAE;;AAIhD,IAAA,mBAAmB,CAAC,KAAoB,EAAA;AACtC,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,KAAK,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE;YACvE,KAAK,CAAC,cAAc,EAAE;;;;;;;;AAQtB,YAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS;AAAE,gBAAA,KAAK,IAAI,CAAC,MAAM,EAAE;QAC1D;IACF;;IAGS,UAAU,GAAG,QAAQ,CAAC,MAC7B,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE;;;;;QAK5E,SAAS,EAAE,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;AAC7C,KAAA,CAAC,iFACH;;AAGgB,IAAA,cAAc,GAAG,IAAI,GAAG,EAAU;AAE3C,IAAA,QAAQ,CAAC,OAAe,EAAA;QAC9B,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE;AACtD,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC;AAChC,QAAA,OAAO,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAA,CAAE,CAAC;IACjD;AAEA;;;;AAIG;AACM,IAAA,qBAAqB,GAAG,QAAQ,CAAsB,MAAK;AAClE,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE;AAChC,QAAA,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,EAAE;AAC9D,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE;AAChC,QAAA,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACvG,IAAA,CAAC,4FAAC;AAEF,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE;IAChC;AAEA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACxD;AAEQ,IAAA,YAAY,CAAC,GAAoB,EAAA;AACvC,QAAA,OAAO,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,GAAG,CAAC;IAClE;AAEA,IAAA,IAAI,eAAe,GAAA;AACjB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE;AAC9B,QAAA,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,IAAI;QAC9C,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;IAClC;AAEA,IAAA,IAAI,cAAc,GAAA;AAChB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe;QACnC,IAAI,CAAC,MAAM,EAAE,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,EAAE;AAChE,QAAA,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAC9D;AAEA,IAAA,IAAI,kBAAkB,GAAA;AACpB,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc;QACnC,IAAI,CAAC,OAAO,CAAC,MAAM;AAAE,YAAA,OAAO,IAAI;AAChC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE;AACjC,QAAA,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC;IACxD;AAEA;;;;;;;;;;AAUG;AACH,IAAA,IAAI,wBAAwB,GAAA;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,eAAe;QAC9D,IAAI,CAAC,MAAM,EAAE,UAAU,IAAI,CAAC,IAAI,CAAC,qBAAqB;AAAE,YAAA,OAAO,IAAI;AACnE,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC,SAAS,KAAK,MAAM,CAAC,UAAU,CAAC;AACnH,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,IAAI;AACvB,QAAA,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,EAAE;YACvC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC;AAClD,YAAA,OAAO,IAAI;QACb;QACA,OAAO,KAAK,CAAC,SAAS;IACxB;;AAGiB,IAAA,qBAAqB,GAAG,IAAI,GAAG,EAAU;IAElD,kBAAkB,CAAC,EAAU,EAAE,QAAgB,EAAA;AACrD,QAAA,IAAI,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE;AACxC,QAAA,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,CAAC;AAClC,QAAA,OAAO,CAAC,IAAI,CACV,CAAA,wCAAA,EAA2C,EAAE,CAAA,kCAAA,CAAoC;AAC/E,YAAA,CAAA,CAAA,EAAI,QAAQ,CAAA,sEAAA,CAAwE;YACpF,CAAA,oCAAA,CAAsC;YACtC,CAAA,OAAA,EAAU,EAAE,CAAA,0CAAA,CAA4C,CAC3D;IACH;AAEA,IAAA,IAAI,kBAAkB,GAAA;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,eAAe;QAC9D,IAAI,MAAM,EAAE,UAAU;AAAE,YAAA,OAAO,EAAE;AACjC,QAAA,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC;AACvG,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,EAAE;AAEvC,QAAA,OAAO,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IAC7E;AAEA;;;;AAIG;IACK,cAAc,CAAC,KAAwB,EAAE,MAA+B,EAAA;QAC9E,OAAO,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACnG;AAEA;;;;;;;AAOG;AACH,IAAA,IAAI,WAAW,GAAA;QACb,QAAQ,IAAI,CAAC,gBAAgB,KAAK,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;IAChG;IAEQ,gBAAgB,GAAqD,IAAI;AAEjF;;;;;;;;AAQG;AACH,IAAA,IAAI,OAAO,GAAA;AACT,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO;IACjC;AAEA;;;;;;AAMG;AACH,IAAA,IAAI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS;IACnC;AAEA,IAAA,IAAI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ;IACnE;AAEA;;;;;;;;AAQG;AACH,IAAA,IAAI,oBAAoB,GAAA;AACtB,QAAA,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,gBAAgB;IAC3C;;AAGA,IAAA,IAAI,aAAa,GAAA;AACf,QAAA,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,MAAM,GAAG,CAAC;IAC1D;AAEA;;;;;;AAMG;AACH,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO;IAC1B;AAEA;;;;AAIG;AACH,IAAA,IAAI,aAAa,GAAA;AACf,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,aAAa;IACrE;AAEA;;;;;;;;;;;;;;;;;AAiBG;AACH,IAAA,IAAI,cAAc,GAAA;AAChB,QAAA,OAAO,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO;IAC7D;IAEA,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAI;YACvF,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC;AAC5C,QAAA,CAAC,CAAC;IACJ;AAEA,IAAA,WAAW,CAAC,OAAsB,EAAA;QAChC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC,EAAE;AAC7C,YAAA,IAAI,CAAC,gBAAgB,GAAG,IAAI;QAC9B;QACA,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE;;;;;;;;YAQvC,IAAI,CAAC,gBAAgB,GAAG,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC7D;QACA,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,aAAa,CAAC,EAAE;YAC/C,IAAI,CAAC,SAAS,EAAE;;;;;;;;;;AAWhB,YAAA,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE;AAClE,gBAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;AACtB,gBAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B;AAEA,YAAA,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;gBAAE;;;;;;;;;AAUnC,YAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE;;;AAGrB,gBAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;YAClE;QACF;IACF;AAEA;;;;;;;AAOG;AACK,IAAA,YAAY,CAAC,MAAgC,EAAA;AACnD,QAAA,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,aAAa,EAAE;AAAE,YAAA,OAAO,KAAK;AACnD,QAAA,MAAM,KAAK,GAAG,CAAC,CAAU,KACvB,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,KAAK,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,CAAW,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AACnG,QAAA,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACrE;IAEA,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE;AAC5B,QAAA,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE;AAC7B,QAAA,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE;IAClC;AAEA;;;;;;;AAOG;IACH,YAAY,CAAC,KAAa,EAAE,OAAkC,EAAA;QAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,KAAK;AAC1C,QAAA,IAAI,OAAO;AAAE,YAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC;AAC7C,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACzB,QAAA,IAAI,OAAO,IAAI,OAAO,EAAE,UAAU,KAAK,KAAK;YAAE,IAAI,CAAC,gBAAgB,EAAE;QACrE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;AACxC,QAAA,IAAI,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE;AAC5B,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9C;aAAO;AACL,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B;IACF;IAEA,eAAe,CAAC,QAAgB,EAAE,OAAkC,EAAA;QAClE,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE,KAAK,QAAQ;AAChD,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC;AAC/B,QAAA,IAAI,OAAO,IAAI,OAAO,EAAE,UAAU,KAAK,KAAK;YAAE,IAAI,CAAC,gBAAgB,EAAE;IACvE;AAEA,IAAA,YAAY,CAAC,KAAwB,EAAA;AACnC,QAAA,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;AAC/F,QAAA,OAAO,QAAQ,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE;IAClD;;AAIA;;;;;;;AAOG;AACM,IAAA,eAAe,GAAG,MAAM,CAAC,KAAK,sFAAC;AAExC;;;;;;;;;;;;;;AAcG;IACH,aAAa,GAAA;QACX,IAAI,IAAI,CAAC,kBAAkB;YAAE,OAAO,IAAI,CAAC,kBAAkB;QAE3D,MAAM,GAAG,GAAmB,EAAE;AAE9B;;;;;;;;;AASG;QACH,MAAM,YAAY,GAAG,CAAC,KAAwB,EAAE,GAAoB,EAAE,QAAiB,KAAI;AACzF,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;AACjD,YAAA,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,OAAO;gBAAE;AAEtE,YAAA,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE;AACpD,gBAAA,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,QAAQ;AAAE,oBAAA,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,CAAC;gBACtE;YACF;;;;YAKA,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC;YACxF,GAAG,CAAC,IAAI,CACN;AACE,kBAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE;AACrD,kBAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,CACtC;AACH,QAAA,CAAC;AAED,QAAA,MAAM,OAAO,GAAG,CAAC,GAAoB,EAAE,QAAiB,KAAI;AAC1D,YAAA,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE;AAAE,gBAAA,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,CAAC;AACxE,YAAA,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,QAAQ,IAAI,EAAE;gBAAE,OAAO,CAAC,KAAK,EAAE,QAAQ,IAAI,GAAG,CAAC,EAAE,CAAC;AAC5E,QAAA,CAAC;AACD,QAAA,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO,CAAC,GAAG,CAAC;AAEhD,QAAA,QAAQ,IAAI,CAAC,kBAAkB,GAAG,GAAG;IACvC;AAEQ,IAAA,kBAAkB;;AAG1B,IAAA,aAAa,CAAC,GAAoB,EAAA;AAChC,QAAA,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE;AAAE,YAAA,OAAO,CAAC;QACrC,OAAO,IAAI,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,MAAM;IAC5E;;AAGA,IAAA,gBAAgB,CAAC,MAAuB,EAAA;AACtC,QAAA,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE;AAAE,YAAA,OAAO,CAAC;QACrC,OAAO,IAAI,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM;IAClF;AAEA;;;;;;;;AAQG;AACH,IAAA,WAAW,CAAC,OAAe,EAAA;AACzB,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;AAC5G,QAAA,IAAI,CAAC,QAAQ;YAAE;;AAGf,QAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;;QAExD,IAAI,QAAQ,CAAC,QAAQ;AAAE,YAAA,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QAErF,eAAe,CACb,MAAK;;;AAGH,YAAA,MAAM,MAAM,GAAG,CAAA,gBAAA,EAAmB,OAAO,EAAE;AAC3C,YAAA,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAc,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAC3G,IAAI,IAAI,IAAI,CAAC,EAAE,KAAK,MAAM,CAC3B;AACD,YAAA,IAAI,CAAC,EAAE;gBAAE;AACT,YAAA,EAAE,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;;;YAG1D,EAAE,CAAC,KAAK,EAAE;QACZ,CAAC,EACD,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAC5B;IACH;AAEA;;;;;;;AAOG;AACK,IAAA,WAAW,CAAC,OAAe,EAAA;AACjC,QAAA,MAAM,KAAK,GAAG,CAAC,MAAuC,KACpD,CAAC,MAAM,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,OAAO,IAAI,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAEnE,MAAM,MAAM,GAAG,CAAC,IAAmC,EAAE,KAAc,EAAE,QAAiB,KAE3E;AACT,YAAA,KAAK,MAAM,GAAG,IAAI,IAAI,IAAI,EAAE,EAAE;gBAC5B,IAAI,CAAC,GAAG,EAAE,EAAE;oBAAE;AACd,gBAAA,MAAM,EAAE,GAAG,KAAK,IAAI,GAAG,CAAC,EAAE;AAC1B,gBAAA,MAAM,GAAG,GAAG,KAAK,IAAI,QAAQ,IAAI,GAAG,CAAC,EAAE,IAAI,SAAS;AACpD,gBAAA,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;oBAAE,OAAO,GAAG,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;AAChF,gBAAA,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,GAAG,CAAC;AAC3C,gBAAA,IAAI,KAAK;AAAE,oBAAA,OAAO,KAAK;YACzB;AACA,YAAA,OAAO,IAAI;AACb,QAAA,CAAC;AAED,QAAA,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;IAC1B;;;AAKA,IAAA,aAAa,CAAC,KAAwB,EAAA;AACpC,QAAA,OAAO,CAAC,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;IACtE;AAEA;;;AAGG;AACH,IAAA,eAAe,CAAC,KAAwB,EAAA;QACtC,QACE,IAAI,CAAC,QAAQ;;;;;AAKb,YAAA,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO;YACzB,CAAC,CAAC,KAAK,CAAC,QAAQ;YAChB,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AACtC,YAAA,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;IAE7B;AAEA,IAAA,eAAe,CAAC,KAAwB,EAAA;;;AAGtC,QAAA,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO;YAAE;QACxE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;AAC3C,QAAA,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;AAAE,YAAA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;;AACxC,YAAA,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;AACvB,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;IAC/B;AAEA;;;;;;AAMG;AACH,IAAA,iBAAiB,CAAC,KAAwB,EAAA;AACxC,QAAA,OAAO,YAAY,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,EAAE;IAC7D;AAEA;;;;;;AAMG;IACH,0BAA0B,GAAA;QACxB,OAAO,IAAI,CAAC,qBAAqB;aAC9B,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC;aAC1C,IAAI,CAAC,IAAI,CAAC;IACf;;IAIQ,SAAS,GAAA;QACf,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE;AAClB,QAAA,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;;AAEjD,QAAA,IAAI,CAAC,UAAU,GAAG,SAAS;QAC3B,IAAI,CAAC,2BAA2B,EAAE;AAElC,QAAA,IAAI,IAAI,CAAC,WAAW,EAAE;AACpB,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACtD;AAEA,QAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,EAAE;AACjD,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC;AACrC,QAAA,IAAI,CAAC,cAAc,GAAG,EAAE,GAAG,gBAAgB,EAAE;QAC7C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,GAAG,gBAAgB,EAAE,CAAC;QACjD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,GAAG,EAAU,CAAC;AAC1C,QAAA,IAAI,CAAC,oBAAoB,CAAC,gBAAgB,CAAC;AAE3C,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE;;YAEhB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;AACpC,gBAAA,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;oBAAE;gBAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;AAC5C,gBAAA,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;AAAE,oBAAA,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YACnF;YACA,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACzC;;AAGA,QAAA,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE;AAC5B,QAAA,MAAM,QAAQ,GACZ,IAAI,CAAC,gBAAgB,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY;;;;;AAKvH,QAAA,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE;;AAE7B,QAAA,IAAI,CAAC,kBAAkB,GAAG,SAAS;AACnC,QAAA,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,MAAK;;AAEtD,YAAA,IAAI,CAAC,kBAAkB,GAAG,SAAS;AACnC,YAAA,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE;AACzB,QAAA,CAAC,CAAC;QAEF,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAK;AACtC,YAAA,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,EAAE;AAC1C,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC;AAC9B,YAAA,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC;AAC9B,YAAA,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC;AACpC,YAAA,IAAI,CAAC,cAAc,GAAG,EAAE,GAAG,SAAS,EAAE;YACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;AAC5C,QAAA,CAAC,CAAC;IACJ;AAEA;;;AAGG;IACH,eAAe,CAAC,OAAe,EAAE,KAAc,EAAA;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC;QAC5C,OAAO,IAAI,YAAY,SAAS,GAAG,IAAI,GAAG,IAAI;IAChD;AAEA;;;AAGG;IACH,cAAc,CAAC,KAAwB,EAAE,KAAe,EAAA;QACtD,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC;IACzC;IAEQ,aAAa,CAAC,KAAoC,EAAE,IAAa,EAAA;QACvE,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC;IAClD;AAEA;;;;;AAKG;IACK,cAAc,GAAA;AACpB,QAAA,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;AAC5B,QAAA,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;IAClD;AAEA;;;;;;;;;AASG;AACK,IAAA,aAAa,CAAC,IAAyB,EAAA;QAC7C,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM;AAAE,YAAA,OAAO,IAAI;AAExD,QAAA,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC;QAChE,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,SAAS,EAAE,EAAE;YACxC,OAAO,CAAC,IAAI,CACV,CAAA,iCAAA,EAAoC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA,6BAAA,CAA+B;AACnF,gBAAA,CAAA,EAAG,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,EAAE,CAAA,SAAA,EAAY,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA,EAAA,CAAI,CAC1E;QACH;QACA,OAAO,MAAM,CAAC,MAAM;IACtB;AAEQ,IAAA,SAAS,CAAC,IAAyB,EAAA;QACzC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE;QACzC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QAChE,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC;AACrF,QAAA,IAAI,CAAC,yBAAyB,CAAC,UAAU,CAAC;IAC5C;AAEA;;;;;;;;AAQG;AACK,IAAA,yBAAyB,CAAC,IAAuB,EAAA;QACvD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrE,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE;QAEnB,KAAK,MAAM,GAAG,IAAI,KAAK;AAAE,YAAA,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC;AAE3D,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,GAAG,MAAM,KAAK,CAAC,MAAM,GAAG,CAAC,QAAQ,GAAG,EAAE;AACnE,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC;AACjC,QAAA,OAAO,CAAC,IAAI,CACV,CAAA,+CAAA,EAAkD,MAAM,GAAG,KAAK,GAAG,MAAM,CAAA,UAAA,CAAY;AACnF,YAAA,CAAA,EAAG,MAAM,GAAG,kBAAkB,GAAG,kBAAkB,CAAA,gBAAA,EAAmB,KAAK,CAAA,EAAG,IAAI,CAAA,EAAA,CAAI;YACtF,CAAA,iFAAA,CAAmF;YACnF,CAAA,iFAAA,CAAmF;YACnF,CAAA,gBAAA,EAAmB,MAAM,GAAG,YAAY,GAAG,cAAc,CAAA,CAAA,CAAG,CAC/D;IACH;;AAGiB,IAAA,oBAAoB,GAAG,IAAI,GAAG,EAAU;;IAGzD,aAAa,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;IAC7D;AAEA;;;;;;;;;;AAUG;IACK,2BAA2B,GAAA;AACjC,QAAA,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE;QAEzD,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC;AAChD,QAAA,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC;YAAE;AAE1B,QAAA,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU;AACpC,QAAA,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE;YAC7B,IAAI,IAAI,CAAC,OAAO;AAAE,gBAAA,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;YAC9C,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,IAAI,EAAE,EAAE;gBAC7C,IAAI,SAAS,CAAC,cAAc;AAAE,oBAAA,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,cAAc,CAAC;YACxE;YACA,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE;gBACvC,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,EAAE;AAAE,oBAAA,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACrE;QACF;AAEA,QAAA,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;AAC5B,YAAA,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC;AACjC,YAAA,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK;gBAAE;AAC3B,YAAA,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK;YACvB,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE;AAChD,YAAA,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;AAC/B,YAAA,OAAO,CAAC,IAAI,CACV,CAAA,8CAAA,EAAiD,EAAE,CAAA,uBAAA,EAA0B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA,EAAA,CAAI;gBACnG,CAAA,+FAAA,CAAiG;gBACjG,CAAA,6BAAA,EAAgC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA,EAAA,CAAI,CACtD;QACH;IACF;AAEA;;;;;;;;AAQG;AACc,IAAA,kBAAkB,GAAG,IAAI,GAAG,EAAU;AAEvD;;;;;;;;;;;AAWG;AACH;;;;;;;;;AASG;AACK,IAAA,OAAO,CAAC,KAAwB,EAAA;AACtC,QAAA,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;QACtD,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;IACzD;AAEA;;;;;;;AAOG;AACK,IAAA,SAAS,CAAC,KAAwB,EAAA;QACxC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE;IACxC;;AAGQ,IAAA,OAAO,CAAC,KAAwB,EAAA;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;AACvC,QAAA,OAAO,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI;IAC1D;AAEA;;;;;;;AAOG;IACK,WAAW,GAAA;QACjB,IAAI,IAAI,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE;YAC3C,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;YAC/C,IAAI,CAAC,UAAU,GAAG;gBAChB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,OAAO;gBACP,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;aAC7D;QACH;AACA,QAAA,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO;IAChC;AAEQ,IAAA,aAAa,CAAC,KAAwB,EAAA;QAC5C,IAAI,CAAC,WAAW,EAAE;QAClB,OAAO,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;IAC5C;AAEQ,IAAA,UAAU;AAMlB;;;;;;;;;;;;AAYG;AACK,IAAA,eAAe,CAAC,KAAsB,EAAA;QAC5C,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9E;IAIQ,iBAAiB,GAAA;QACvB,MAAM,GAAG,GAAwB,EAAE;QACnC,KAAK,MAAM,KAAK,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;AACnD,YAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK;YACzB,IAAI,CAAC,KAAK,EAAE,EAAE;gBAAE;YAChB,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;AACpE,YAAA,IAAI,CAAC,IAAI;gBAAE;YACX,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK;AAC1B,YAAA,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK;QACzD;AACA,QAAA,OAAO,GAAG;IACZ;;AAIA;;;AAGG;IACK,YAAY,CAAC,OAAe,EAAE,MAA2C,EAAA;AAC/E,QAAA,IAAI,CAAC,MAAM;YAAE;AACb,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC;AAC1D,QAAA,MAAM,SAAS,GAAG,KAAK,EAAE,SAAS;AAClC,QAAA,IAAI,CAAC,SAAS;YAAE;QAEhB,MAAM,KAAK,GAAG,cAAc,CAAC,SAAS,EAAE,MAAM,CAAC;AAC/C,QAAA,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACrD,MAAM,OAAO,GAAG,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,QAAQ,CAAC;AAC9D,YAAA,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC;QAC5B;;;;AAIA,QAAA,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;IAClD;AAEA;;;AAGG;AACK,IAAA,cAAc,CAAC,MAA2B,EAAA;QAChD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;AACpC,YAAA,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW;YAClC,IAAI,CAAC,QAAQ,EAAE,MAAM;gBAAE;AAEvB,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI;YACtD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI;YACxC,IAAI,CAAC,MAAM,IAAI,OAAO;gBAAE;YAExB,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC;AAChD,YAAA,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACrD,gBAAA,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;YACpE;QACF;IACF;AAEA;;;;;;AAMG;IACK,oBAAoB,CAAC,SAA0B,EAAE,QAAgB,EAAA;AACvE,QAAA,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,SAAS,CAAC;AACnD,QAAA,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,SAAS,CAAC;AAE/D,QAAA,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,IAAG;AACtE,YAAA,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE;AAAE,gBAAA,OAAO,KAAK;AAC9B,YAAA,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC;AACtC,YAAA,OAAO,MAAM,CAAC,IAAI,KAAK;AACrB,kBAAE,WAAW,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC;kBAC5C,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC,KAAK;AACjC,QAAA,CAAC,CAAC;AACF,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,IAAI;AACvB,QAAA,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;IACpC;;AAIA;;;;;;;AAOG;AACK,IAAA,oBAAoB,CAAC,MAA2B,EAAA;QACtD,IAAI,IAAI,CAAC,OAAO;AAAE,YAAA,OAAO;QAEzB,IAAI,CAAC,eAAe,CAAC,oBAAoB,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE;AAC5D,YAAA,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE;YACzB,MAAM;YACN,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YACrC,SAAS,EAAE,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YACzC,UAAU,EAAE,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;AACjD,SAAA,CAAC;IACJ;;IAGQ,SAAS,GAAA;QACf,MAAM,GAAG,GAAwB,EAAE;AACnC,QAAA,MAAM,UAAU,GAAG,CAAC,MAAuC,KAAI;AAC7D,YAAA,KAAK,MAAM,CAAC,IAAI,MAAM,IAAI,EAAE,EAAE;AAC5B,gBAAA,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AACX,gBAAA,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM;AAAE,oBAAA,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChD;AACF,QAAA,CAAC;AACD,QAAA,MAAM,QAAQ,GAAG,CAAC,IAAmC,KAAI;AACvD,YAAA,KAAK,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,EAAE;AAC1B,gBAAA,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC;AACpB,gBAAA,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;YACtB;AACF,QAAA,CAAC;AACD,QAAA,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC3B,QAAA,OAAO,GAAG;IACZ;;IAGQ,QAAQ,GAAA;AACd,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY;QAClC,IAAI,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC;AAAE,YAAA,OAAO,QAAQ;AACjE,QAAA,OAAO,IAAI,CAAC,eAAe,EAAE;IAC/B;AAEA;;;;;;;;;AASG;IACK,SAAS,CAAC,CAAU,EAAE,CAAU,EAAA;AACtC,QAAA,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE;AACxD,QAAA,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE;QACxD,IAAI,MAAM,IAAI,MAAM;AAAE,YAAA,OAAO,IAAI;AACjC,QAAA,OAAO,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1B;AAEA;;;;;AAKG;IACH,UAAU,CAAC,OAAe,EAAE,YAAqB,EAAA;AAC/C,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC;IACjF;AAEA;;;;;;;AAOG;IACK,gBAAgB,GAAA;QACtB,IAAI,OAAO,qBAAqB,KAAK,UAAU;YAAE;QACjD,qBAAqB,CAAC;;;;;AAKpB,QAAA,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAChE;IACH;;AAGA,IAAA,IAAI,cAAc,GAAA;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,eAAe;AAC3D,QAAA,OAAO,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE;IAC7C;AAEA;;;;;;AAMG;AACH,IAAA,SAAS,CAAC,KAAwB,EAAA;AAChC,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,mBAAmB,GAAG,CAAA,CAAA,EAAI,KAAK,CAAC,mBAAmB,CAAA,CAAA,CAAG,GAAG,mBAAmB;QACjG,OAAO,CAAA,wBAAA,EAA2B,MAAM,CAAA,0DAAA,CAA4D;IACtG;AAEA,IAAA,eAAe,CAAC,GAAoB,EAAA;QAClC,OAAO,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IAC/C;AAEA,IAAA,MAAM,MAAM,GAAA;QACV,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE;AACzC;;;;;;;AAOG;YACH,IAAI,CAAC,cAAc,EAAE;AACrB,YAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;YAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;AACrC,YAAA,IAAI,KAAK;gBAAE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3C;QACF;;AAGA,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC;AAE/B,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,EAAE;QACpC,IAAI,aAAa,GAAG,OAAO;AAE3B,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;AACvB,QAAA,IAAI;;;;YAIF,MAAM,OAAO,GAAG,CAAA,EAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAA,WAAA,CAAa;YACnD,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;AAClC,gBAAA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC;AAClE,gBAAA,IAAI,MAAM,KAAK,KAAK,EAAE;oBACpB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC;oBAC/D;gBACF;;AAEA,gBAAA,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI;oBAAE,aAAa,GAAG,MAAM;YACrE;AAEA,YAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC;QACrC;QAAE,OAAO,GAAG,EAAE;;;AAGZ,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,YAAY,KAAK,GAAG,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QAClG;gBAAU;AACR,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;QAC1B;IACF;IAEA,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;QACjB,IAAI,IAAI,CAAC,WAAW;AAAE,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC;AACtD,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,EAAE;AACvC,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC;AAC3B,QAAA,IAAI,CAAC,cAAc,GAAG,EAAE,GAAG,MAAM,EAAE;QACnC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,GAAG,EAAU,CAAC;;AAE1C,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC;AAC/B,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;wGAjtCW,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,oBAAoB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,KAAA,EAAA,OAAA,EAAA,WAAA,EAAA,aAAA,EAAA,YAAA,EAAA,cAAA,EAAA,SAAA,EAAA,WAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,SAAA,EAAA,KAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,kBAAA,EAAA,OAAA,EAAA,SAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,OAAA,EAAA,EAAA,UAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,SAAA,EAAA,WAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,gBAAA,EAAA,6BAAA,EAAA,EAAA,EAAA,SAAA,EA5DpB,CAAC,yBAAyB,EAAE,oBAAoB,CAAC,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,WAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,WAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,EAAA,YAAA,EAAA,YAAA,EAAA,SAAA,EA6K9C,qBAAqB,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,aAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EC5RrC,qoWAyPA,EAAA,MAAA,EAAA,CAAA,0rBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,ED7IY,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,aAAA,EAAA,QAAA,EAAA,8CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,sGAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,kBAAA,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,qBAAqB,2JAAE,iBAAiB,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,mBAAA,EAAA,yBAAA,EAAA,2BAAA,EAAA,sCAAA,EAAA,0BAAA,EAAA,2BAAA,CAAA,EAAA,QAAA,EAAA,CAAA,mBAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FA+D5D,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAnEhC,SAAS;AACS,YAAA,IAAA,EAAA,CAAA,EAAA,eAAA,EAAA,uBAAuB,CAAC,MAAM,EAAA,QAAA,EACrC,kBAAkB,EAAA,UAAA,EAChB,IAAI,WACP,CAAC,mBAAmB,EAAE,qBAAqB,EAAE,iBAAiB,CAAC,EAAA,SAAA,EAG7D,CAAC,yBAAyB,EAAE,oBAAoB,CAAC,EAAA,QAAA,EAAA,qoWAAA,EAAA,MAAA,EAAA,CAAA,0rBAAA,CAAA,EAAA;;sBA2E3D;;sBAUA;;sBACA;;sBAEA;;sBACA;;sBACA;;sBACA;;sBAEA;;sBAKA;;sBACA;;sBACA;;sBAMA;;sBAKA;;sBAaA;;sBAGA;;sBACA;;sBACA;;sBAEA;;sBAKA;;sBAkCA,SAAS;uBAAC,WAAW;;sBAGrB,YAAY;uBAAC,qBAAqB;;sBAYlC,YAAY;uBAAC,gBAAgB,EAAE,CAAC,QAAQ,CAAC;;;AEhR5C;;;AAGG;AACH,MAAM,eAAe,GAAG,MAAM,CAAC,iBAAiB,CAAC;AAEjD;;;;AAIG;MA2OU,0BAA0B,CAAA;;AAElB,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;AACpC,IAAA,MAAM;AACN,IAAA,KAAK;AACL,IAAA,WAAW;IACX,SAAS,GAAa,EAAE;IACxB,QAAQ,GAAW,IAAI;IACvB,QAAQ,GAAY,KAAK;IACzB,OAAO,GAAY,KAAK;IACxB,KAAK,GAAkB,IAAI;;IAE3B,UAAU,GAAY,KAAK;;IAE3B,cAAc,GAAa,EAAE;;IAE7B,MAAM,GAAqB,OAAO;AAC3C;;;;;;AAMG;IACM,QAAQ,GAAY,IAAI;AAEvB,IAAA,UAAU,GAAG,IAAI,YAAY,EAAuB;AACpD,IAAA,UAAU,GAAG,IAAI,YAAY,EAAuB;AACpD,IAAA,SAAS,GAAG,IAAI,YAAY,EAAQ;;AAEpC,IAAA,WAAW,GAAG,IAAI,YAAY,EAAkD;AAC1F;;;;;;;AAOG;AACO,IAAA,YAAY,GAAG,IAAI,YAAY,EAAuC;AAE/C,IAAA,eAAe;AAE/B,IAAA,eAAe,GAAG,MAAM,CAAC,sBAAsB,CAAC;AAChD,IAAA,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;AACjC,IAAA,YAAY,GAAG,MAAM,CAAC,mBAAmB,CAAC;AAElD,IAAA,WAAW,GAAG,MAAM,CAAsB,EAAE,kFAAC;AAC7C,IAAA,gBAAgB,GAAG,MAAM,CAAsB,EAAE,uFAAC;AAE3D;;;;;;AAMG;AACc,IAAA,SAAS,GAAG,MAAM,CAAsB,IAAI,GAAG,EAAU,gFAAC;AAE3E;;;;;;AAMG;AACH,IAAA,IAAI,WAAW,GAAA;QACb,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,UAAU,EAAE;AACjD,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE;QAC7B,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,IAAI,EAAE;AAC5C,aAAA,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;aACxC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACzE;AAEA,IAAA,iBAAiB,CAAC,OAAe,EAAA;AAC/B,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC5D;AAEA;;;;;;;AAOG;IACK,gBAAgB,GAAqD,IAAI;AAEjF,IAAA,IAAI,WAAW,GAAA;QACb,QAAQ,IAAI,CAAC,gBAAgB,KAAK,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;IAChG;;AAGA,IAAA,IAAI,cAAc,GAAA;AAChB,QAAA,OAAO,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO;IACtE;;AAIA;;;;;;AAMG;AACM,IAAA,cAAc,GAAG,MAAM,CAA2B,IAAI,qFAAC;AACvD,IAAA,cAAc,GAAG,MAAM,CAAgB,IAAI,qFAAC;IACrD,aAAa,GAAqB,IAAI;;AAGtC,IAAA,IAAI,uBAAuB,GAAA;AACzB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW;QAC9B,MAAM,GAAG,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,IAAI;QAC5D,OAAO,CAAC,GAAG,EAAE,MAAM,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC;IAC5D;AAEA;;;;;;AAMG;AACH,IAAA,MAAM,CAAC,KAAwB,EAAA;AAC7B,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW;QAC9B,MAAM,OAAO,GAAG,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI;QACjF,MAAM,IAAI,GAAI,OAA0C,GAAG,KAAK,CAAC,EAAE,CAAC;AACpE,QAAA,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAI,IAAkC,GAAG,EAAE;IACvE;;IAGA,UAAU,CAAC,KAAwB,EAAE,GAA4B,EAAA;AAC/D,QAAA,MAAM,KAAK,GAAG,GAAG,IAAI,EAAE;QACvB,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE;aAChC,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;AAC5B,aAAA,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE;AACrD,aAAA,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACpE,QAAA,OAAO,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,SAAS;IACrD;AAEA,IAAA,UAAU,CAAC,KAAwB,EAAA;QACjC,IAAI,IAAI,CAAC,eAAe;YAAE;AAC1B,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;AAC9B,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,KAAK,CAAc;IAC/E;IAEA,WAAW,CAAC,KAAwB,EAAE,KAAa,EAAA;QACjD,IAAI,IAAI,CAAC,eAAe;YAAE;AAC1B,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;AAC9B,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;QAC9B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAc;IAC1G;IAEA,SAAS,GAAA;AACP,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;AAC7B,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;AAC7B,QAAA,IAAI,CAAC,aAAa,GAAG,IAAI;IAC3B;;IAGA,OAAO,GAAA;AACL,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE;AACnC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe;QACjC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE;AAE5C,QAAA,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE;AAC9B,YAAA,IAAI,CAAC,aAAa,CAAC,gBAAgB,EAAE;YACrC;QACF;AAEA,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,IAAI,SAAS,CAAC;AAC3E,QAAA,IAAI,CAAC,KAAK;YAAE;AAEZ,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE;QACnC,IAAI,KAAK,KAAK,IAAI;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;;AAC/E,YAAA,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;QAEzD,KAAK,CAAC,sBAAsB,EAAE;QAC9B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QAC1C,IAAI,CAAC,SAAS,EAAE;IAClB;IAEA,SAAS,CAAC,KAAwB,EAAE,KAAa,EAAA;QAC/C,IAAI,IAAI,CAAC,eAAe;YAAE;AAC1B,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,IAAI,SAAS,CAAC;AAC5F,QAAA,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC;QACtB,KAAK,EAAE,sBAAsB,EAAE;QAC/B,IAAI,IAAI,CAAC,eAAe;AAAE,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,CAAC;AACpF,QAAA,IAAI,IAAI,CAAC,cAAc,EAAE,KAAK,KAAK;YAAE,IAAI,CAAC,SAAS,EAAE;IACvD;;AAIA;;;;;;AAMG;AACM,IAAA,YAAY,GAAG,MAAM,CAAgB,IAAI,mFAAC;AAEnD;;;;;;;AAOG;AACc,IAAA,cAAc,GAAG,MAAM,CAAgB,IAAI,qFAAC;AAE7D,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,IAAI,CAAC,cAAc,EAAE;IAC9B;AAEA,IAAA,iBAAiB,CAAC,KAAa,EAAA;AAC7B,QAAA,IAAI,IAAI,CAAC,cAAc,EAAE,KAAK,KAAK;YAAE;AACrC,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;;AAE9B,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;QAC3B,IAAI,CAAC,SAAS,EAAE;IAClB;;IAGQ,iBAAiB,GAAA;QACvB,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,KAAK,KAAK,CAAC,EAAE,EAAE,IAAI,IAAI;IACzE;;AAGS,IAAA,aAAa,GAAG,MAAM,CAAyB,EAAE,oFAAC;;IAGxC,MAAM,GAAG,MAAM;AAElC,IAAA,IAAI,kBAAkB,GAAA;;QAEpB,IAAI,CAAC,IAAI,CAAC,QAAQ;AAAE,YAAA,OAAO,IAAI;AAC/B,QAAA,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,YAAY,EAAE,KAAK,IAAI,CAAC,WAAW;IACvE;;AAGA,IAAA,IAAI,eAAe,GAAA;QACjB,OAAO,IAAI,CAAC,cAAc,IAAI,CAAC,IAAI,CAAC,kBAAkB;IACxD;IAEA,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,cAAc,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE;AAChE,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;IACzC;;IAGA,aAAa,GAAA;AACX,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE;AACjC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe;AACjC,QAAA,IAAI,KAAK,IAAI,IAAI,EAAE;AACjB,YAAA,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC;AAC7C,YAAA,MAAM,WAAW,IAAI,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,gBAAgB,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAA4B;YAC9G,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,MAAM,IAAI,EAAE,EAAE;gBACrC,MAAM,aAAa,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;;;AAI3C,gBAAA,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC;gBACnD,IAAI,KAAK,EAAE;oBACT,KAAK,CAAC,KAAK,EAAE;AACb,oBAAA,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,GAAG,EAAE,EAAE;AACnE,wBAAA,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;oBAC7C;oBACA,KAAK,CAAC,sBAAsB,EAAE;oBAC9B;gBACF;AAEA,gBAAA,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,aAAa,IAAI,IAAI,CAAC;YACnE;YACA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QAC5C;AACA,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;AAC1B,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;IAC7B;AAEA;;;;AAIG;AACH,IAAA,MAAM,WAAW,GAAA;AACf,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE;AACjC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe;AACjC,QAAA,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI;YAAE;AAErB,QAAA,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC;QAC7C,MAAM,MAAM,GAA2B,EAAE;QAEzC,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,MAAM,IAAI,EAAE,EAAE;AACrC,YAAA,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC;AAC7C,YAAA,IAAI,IAAI,EAAE,OAAO,EAAE;gBACjB,IAAI,CAAC,aAAa,EAAE;AACpB,gBAAA,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,cAAc;YAC9E;QACF;AAEA,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC;QAChF,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,gBAAgB;AACrH,QAAA,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC;QAEjC,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;AAClC,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC;YAC9B;QACF;AAEA,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;AAE1B,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE;;;;;;QAOnC,MAAM,OAAO,GAAG,CAAA,EAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAA,WAAA,CAAa;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM;;;QAG3F,IAAI,QAAQ,KAAK,IAAI;YAAE;AAEvB,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;AAC3B,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC;AAC9B,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACpD;AAEA;;;;;;;;;AASG;IACK,MAAM,aAAa,CAAC,MAA2B,EAAA;QACrD,MAAM,OAAO,GAAG,CAAA,EAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAA,WAAA,CAAa;;QAEnD,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC;AAAE,YAAA,OAAO,MAAM;AAElD,QAAA,IAAI;AACF,YAAA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC;AAC3D,YAAA,IAAI,MAAM,KAAK,KAAK,EAAE;gBACpB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC;AAC/D,gBAAA,OAAO,IAAI;YACb;;AAEA,YAAA,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,GAAG,MAAM,GAAI,MAA8B;QAC3F;QAAE,OAAO,GAAG,EAAE;AACZ,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,YAAY,KAAK,GAAG,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAChG,YAAA,OAAO,IAAI;QACb;IACF;AAEA;;;;AAIG;AACH,IAAA,WAAW,CAAC,OAAsB,EAAA;;;QAGhC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC,EAAE;AAC7C,YAAA,IAAI,CAAC,gBAAgB,GAAG,IAAI;QAC9B;QACA,IAAI,OAAO,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,EAAE;AAC/C,YAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,CAAC;AAC1D,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,CAAC;YACrD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;;YAEjD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,EAAU,CAAC;QACvC;IACF;AAEA,IAAA,IAAI,WAAW,GAAA;QACb,IAAI,CAAC,IAAI,CAAC,MAAM;AAAE,YAAA,OAAO,QAAQ;AACjC,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM;IAC9F;AAEA;;;;;;;;;;;;;;;;;;;;;;AAsBG;AACH,IAAA,IAAI,aAAa,GAAA;AACf,QAAA,MAAM,KAAK,GAAG,CAAC,KAAwB,KAAmB;YACxD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACvC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ;AAAE,gBAAA,OAAO,IAAI;YACvE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE;YACjC,OAAO,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,IAAI;AAClC,QAAA,CAAC;QAED,IAAI,QAAQ,GAAkB,IAAI;QAClC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;AACpC,YAAA,IAAI,KAAK,CAAC,UAAU,KAAK,KAAK;gBAAE;AAChC,YAAA,IAAI,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;gBAAE;AAErF,YAAA,IAAI,KAAK,CAAC,cAAc,EAAE;AACxB,gBAAA,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC;AAC9B,gBAAA,IAAI,SAAS;AAAE,oBAAA,OAAO,SAAS;YACjC;AAAO,iBAAA,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE;AACzE,gBAAA,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;YACzB;QACF;AACA,QAAA,OAAO,QAAQ,IAAI,IAAI,CAAC,WAAW;IACrC;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,OAAO,CAAC,IAAI,CAAC,aAAa,IAAI,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;IAC5D;;;IAKQ,SAAS,GAAA;QACf,MAAM,GAAG,GAAwB,EAAE;AACnC,QAAA,MAAM,UAAU,GAAG,CAAC,MAAuC,KAAI;AAC7D,YAAA,KAAK,MAAM,CAAC,IAAI,MAAM,IAAI,EAAE,EAAE;AAC5B,gBAAA,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AACX,gBAAA,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;YACxB;AACF,QAAA,CAAC;AACD,QAAA,MAAM,QAAQ,GAAG,CAAC,IAAmC,KAAI;AACvD,YAAA,KAAK,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,EAAE;AAC1B,gBAAA,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC;AACpB,gBAAA,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;YACtB;AACF,QAAA,CAAC;AACD,QAAA,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC3B,QAAA,OAAO,GAAG;IACZ;;AAGA,IAAA,IAAI,kBAAkB,GAAA;AACpB,QAAA,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,IAAI,IAAI;IAC7D;;AAGA,IAAA,IAAI,iBAAiB,GAAA;AACnB,QAAA,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,IAAI,IAAI;IAC7D;;AAGA,IAAA,IAAI,eAAe,GAAA;AACjB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB;AACrC,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,IAAI;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAA4B;AAClE,QAAA,OAAO,KAAK,EAAE,GAAG,IAAI,IAAI;IAC3B;AAEA,IAAA,IAAI,iBAAiB,GAAA;AACnB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB;AACpC,QAAA,OAAO,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,GAAG,KAAK;IAC3D;AAEA;;;;AAIG;IACH,kBAAkB,GAAA;AAChB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB;AACpC,QAAA,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,cAAc;YAAE;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;AACtC,QAAA,IAAI,CAAC,IAAI;YAAE;QACX,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC;QACtC,IAAI,IAAI,CAAC,eAAe;AAAE,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,CAAC;IACtF;;AAGQ,IAAA,UAAU,CAAC,OAAe,EAAA;QAChC,OAAO,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,OAAO,CAAC,IAAI,IAAI;IAC1D;AAEA;;;;;;;;;;;AAWG;AACK,IAAA,UAAU,CAAC,OAAe,EAAA;AAChC,QAAA,MAAM,KAAK,GAAG,CAAC,IAAA,GAA0B,EAAE,KAAa;AACtD,YAAA,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;AACtB,gBAAA,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,MAAM,CAAmC;AAClG,gBAAA,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI;AAAE,oBAAA,OAAO,IAAI,CAAC,OAAO,CAAC;AACjD,gBAAA,IAAI,GAAG,CAAC,QAAQ,EAAE;oBAChB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;oBACjC,IAAI,KAAK,KAAK,eAAe;AAAE,wBAAA,OAAO,KAAK;gBAC7C;YACF;AACA,YAAA,OAAO,eAAe;AACxB,QAAA,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;QACvC,OAAO,MAAM,KAAK,eAAe,GAAG,SAAS,GAAG,MAAM;IACxD;AAES,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAK;AAClC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,EAAE;AACpC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE;AAC/B,QAAA,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,KAAK;AAClE,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AACtD,IAAA,CAAC,iFAAC;AAEO,IAAA,aAAa,GAAG,QAAQ,CAAsB,MAAK;QAC1D,MAAM,MAAM,GAAwB,EAAE;AACtC,QAAA,MAAM,QAAQ,GAAG,CAAC,IAAA,GAA0B,EAAE,KAAI;AAChD,YAAA,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE;gBACpB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE;oBAC9B,IAAI,CAAC,CAAC,cAAc;AAAE,wBAAA,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;gBACtC;gBACA,IAAI,CAAC,CAAC,QAAQ;AAAE,oBAAA,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;YACtC;AACF,QAAA,CAAC;AACD,QAAA,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC3B,QAAA,OAAO,MAAM;AACf,IAAA,CAAC,oFAAC;AAEF,IAAA,YAAY,CAAC,IAAyB,EAAA;;;AAGpC,QAAA,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;YACrD,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC;QACxC;AACA,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;AAC1B,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;IAC5B;AAEA,IAAA,YAAY,CAAC,IAAyB,EAAA;AACpC,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;IAC5B;IAEA,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;IACvB;AAEA,IAAA,gBAAgB,CAAC,KAAwB,EAAA;QACvC,OAAO,YAAY,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACjD;;AAGA,IAAA,cAAc,CAAC,KAAwB,EAAA;AACrC,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,EAAE,KAAK,IAAI,GAAG,aAAa,GAAG,cAAc;QAC3E,OAAO,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;IAClF;;AAGA,IAAA,gBAAgB,CAAC,KAAwB,EAAA;QACvC,OAAO,kBAAkB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC;IAChG;AAEA;;;;AAIG;AAEH;;;;;;;;AAQG;AACH,IAAA,WAAW,CAAC,OAAe,EAAA;AACzB,QAAA,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,OAAO,CAAC;IAC5C;wGAzlBW,0BAA0B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAA1B,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,yBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,KAAA,EAAA,OAAA,EAAA,WAAA,EAAA,aAAA,EAAA,SAAA,EAAA,WAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,OAAA,EAAA,SAAA,EAAA,KAAA,EAAA,OAAA,EAAA,UAAA,EAAA,YAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,QAAA,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,EAAA,UAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,SAAA,EAAA,WAAA,EAAA,WAAA,EAAA,aAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,iBAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAyC1B,oBAAoB,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,aAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECtTjC,4zQA0NA,EAAA,MAAA,EAAA,CAAA,oxJAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EDnLY,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,sGAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,kBAAA,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,oBAAoB,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,OAAA,EAAA,aAAA,EAAA,cAAA,EAAA,WAAA,EAAA,UAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,OAAA,EAAA,kBAAA,EAAA,SAAA,EAAA,QAAA,CAAA,EAAA,OAAA,EAAA,CAAA,YAAA,EAAA,YAAA,EAAA,WAAA,EAAA,iBAAA,EAAA,cAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,qBAAqB,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,cAAA,EAAA,UAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAsO7E,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBA1OtC,SAAS;AACS,YAAA,IAAA,EAAA,CAAA,EAAA,eAAA,EAAA,uBAAuB,CAAC,MAAM,EAAA,QAAA,EACrC,yBAAyB,cACvB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,qBAAqB,CAAC,EAAA,QAAA,EAAA,4zQAAA,EAAA,MAAA,EAAA,CAAA,oxJAAA,CAAA,EAAA;;sBAyOxF;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBAEA;;sBAEA;;sBAEA;;sBAQA;;sBAEA;;sBACA;;sBACA;;sBAEA;;sBASA;;sBAEA,SAAS;uBAAC,oBAAoB;;;AEtTjC;;;;;;;;;;;;;AAaG;;ACbH;;;;;;;;;;;AAWG;AAKH;AACA,MAAM,eAAe,GAAG,mBAAmB;AAE3C;;;;;;AAMG;MACU,kBAAkB,GAAgB,OAAO,IAAU,KAAwB;AACtF,IAAA,IAAI,IAAI,EAAE,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;AAClD,QAAA,MAAM,IAAI,KAAK,CACb,gBAAgB,IAAI,CAAC,IAAI,CAAA,qDAAA,CAAuD;AAC9E,YAAA,oFAAoF,CACvF;IACH;IACA,OAAO,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;AACpC;;AClCA;;;;;;;;;;;AAWG;AAsBH;AACA,MAAM,WAAW,GAAG,CAAC;MAGR,oBAAoB,CAAA;IACd,UAAU,GAAG,MAAM,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAEtE;;;;;;;;;;;;AAYG;AACc,IAAA,MAAM,GAAG,IAAI,OAAO,EAA4B;;AAGzD,IAAA,IAAI,CAAC,IAAU,EAAA;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;AACpC,QAAA,IAAI,MAAM;AAAE,YAAA,OAAO,MAAM;;;AAIzB,QAAA,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,UAAU,IAAI,kBAAkB,EAAE,IAAI,CAAC,CAAC;QAC9E,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC;;AAE9B,QAAA,OAAO,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC7C,QAAA,OAAO,OAAO;IAChB;AAEA,IAAA,MAAM,OAAO,CAAC,IAAU,EAAE,OAAsB,EAAA;QAC9C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACnC,QAAA,MAAM,EAAE,OAAO,EAAE,GAAG,mBAAmB,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;QAE/E,OAAO;YACL,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC;AACxC,YAAA,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM;AAC3B,YAAA,UAAU,EAAE,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE,CAAC;SACjF;IACH;AAEA,IAAA,MAAM,MAAM,CAAC,IAAU,EAAE,IAAiB,EAAE,OAAsB,EAAA;QAChE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QACnC,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE;YACpD,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,OAAO,EAAE,OAAO,CAAC,OAAO;AACzB,SAAA,CAAC;IACJ;AAEA,IAAA,MAAM,QAAQ,CAAC,IAAkB,EAAE,MAAsB,EAAA;AACvD,QAAA,IAAI,MAAM,KAAK,MAAM,EAAE;;;;YAIrB,MAAM,IAAI,KAAK,CACb,oFAAoF;AAClF,gBAAA,2EAA2E,CAC9E;QACH;;;;;;;;;AAUA,QAAA,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;AAC5D,QAAA,OAAO,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,wBAAwB,EAAE,CAAC;IAC5D;wGA1EW,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAApB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,oBAAoB,cADP,MAAM,EAAA,CAAA;;4FACnB,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBADhC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACpClC;;;;;;;;;;;AAWG;AAsCH;AACA,SAAS,cAAc,CAAC,OAAmC,EAAA;IACzD,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,OAAO,KAAK,UAAU,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE;IACjG,MAAM,GAAG,GAA2B,EAAE;AACtC,IAAA,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;AACnD,QAAA,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,cAAc;YAAE;AAC3C,QAAA,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK;IACnB;AACA,IAAA,OAAO,GAAG;AACZ;AAEA,MAAM,SAAS,GAAG,CAAC,GAAW,KAAa,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;AAEhF;AACA,SAAS,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAA;IACpC,MAAM,IAAI,GAAG,CAAC,OAAe,KAAa,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;IAClF,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;AAC5B;AAEA;;;;;;AAMG;AACH,eAAe,SAAS,CAAC,QAAkB,EAAA;AACzC,IAAA,IAAI,IAAqC;AACzC,IAAA,IAAI;QACF,IAAI,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwB;IACvD;AAAE,IAAA,MAAM;;IAER;AACA,IAAA,MAAM,OAAO,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO;IACpC,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,CAAA,2BAAA,EAA8B,QAAQ,CAAC,MAAM,CAAA,CAAA,CAAG,CAAC;AAC/E;AAEA;;;;;;;;;;;;;;;AAeG;AACH,SAAS,WAAW,CAClB,IAAkB,EAClB,OAAsB,EACtB,MAA0B,EAAA;;;IAI1B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AACtF,IAAA,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,IAC9E,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CACzB,CACF;AAED,IAAA,IAAI,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAAE,QAAA,OAAO,EAAE;IAC7F,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;AAC9B;AAEA;;;;;;AAMG;AACH,MAAM,mBAAmB,CAAA;AACM,IAAA,OAAA;AAA7B,IAAA,WAAA,CAA6B,OAAmC,EAAA;QAAnC,IAAA,CAAA,OAAO,GAAP,OAAO;IAA+B;AAEnE,IAAA,IAAY,IAAI,GAAA;QACd,OAAO,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;IACxC;AAEA,IAAA,IAAY,IAAI,GAAA;;;AAGd,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;IAChE;AAEQ,IAAA,QAAQ,CAAC,OAAsB,EAAA;QACrC,OAAO,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,CAAC;IAC1D;AAEA;;;;;;;AAOG;AACK,IAAA,WAAW,CAAC,OAA2B,EAAA;;;;;QAK7C,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;YAAE;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAe,KAAK,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9E,IAAI,CACF,CAAA,iEAAA,EAAoE,OAAO,CAAA,WAAA,CAAa;AACtF,YAAA,CAAA,kBAAA,EAAqB,YAAY,CAAA,qDAAA,CAAuD;AACxF,YAAA,uFAAuF,CAC1F;IACH;AAEA,IAAA,MAAM,OAAO,CAAC,IAAU,EAAE,OAAsB,EAAA;AAC9C,QAAA,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE;AAC3B,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC;AAEhD,QAAA,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAA,EAAG,IAAI,CAAC,IAAI,CAAA,CAAA,EAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE;AACjF,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC;YACrC,IAAI;AACL,SAAA,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,EAAE;AAAE,YAAA,MAAM,MAAM,SAAS,CAAC,QAAQ,CAAC;QAEjD,MAAM,OAAO,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA0B;AAChE,QAAA,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC;QAEvC,OAAO;AACL,YAAA,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;AAC9B,YAAA,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;YAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;AAC9B,YAAA,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC;SAChC;IACH;AAEA,IAAA,MAAM,MAAM,CAAC,IAAU,EAAE,IAAiB,EAAE,OAAsB,EAAA;AAChE,QAAA,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE;;;;AAI3B,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACzC,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC;AAEhD,QAAA,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAA,EAAG,IAAI,CAAC,IAAI,CAAA,CAAA,EAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE;AAChF,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC;YACrC,IAAI;AACL,SAAA,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,EAAE;AAAE,YAAA,MAAM,MAAM,SAAS,CAAC,QAAQ,CAAC;QAEjD,MAAM,MAAM,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAyB;AAC9D,QAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC;QAEtC,OAAO;;;;;AAKL,YAAA,OAAO,EAAE,EAAE;AACX,YAAA,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,CAAC;AAC9B,YAAA,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,CAAC;AAC5B,YAAA,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC;AAC1B,YAAA,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;YAC3B,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;AAC3D,YAAA,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,KAAK;AACpC,YAAA,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,EAAE;SACxC;IACH;IAEA,MAAM,QAAQ,CACZ,IAAkB,EAClB,MAAsB,EACtB,OAAsB,EACtB,MAA0B,EAAA;;;;QAK1B,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAC7C,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC;AACpD,QAAA,IAAI,SAAS;AAAE,YAAA,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC;AAE7C,QAAA,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAC9B,CAAA,EAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA,UAAA,EAAa,KAAK,CAAC,QAAQ,EAAE,CAAA,CAAE,EACrE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CACzD;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE;AAAE,YAAA,MAAM,MAAM,SAAS,CAAC,QAAQ,CAAC;AACjD,QAAA,OAAO,QAAQ,CAAC,IAAI,EAAE;IACxB;AACD;AAED;;;;;;;;;;;AAWG;AACG,SAAU,0BAA0B,CAAC,OAAmC,EAAA;AAC5E,IAAA,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,IAAI,mBAAmB,CAAC,OAAO,CAAC,EAAE;AAClF;;AC9PA;;;;;;;AAOG;MAiEU,qBAAqB,CAAA;IACvB,MAAM,GAA8B,EAAE;IACtC,QAAQ,GAAG,IAAI;AAEL,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;;IAGnC,OAAO,GAAA;AACf,QAAA,MAAM,KAAK,GAAG,IAAI,GAAG,EAA4B;AACjD,QAAA,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE;AAC/B,YAAA,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE;AACvC,YAAA,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;YAChB,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC;QAC5B;AACA,QAAA,OAAO,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE;AACvB,aAAA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC1B,aAAA,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClD;wGAjBW,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAArB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA3DtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,ogBAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FA6BU,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBAhEjC,SAAS;+BACE,mBAAmB,EAAA,UAAA,EACjB,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,OAAA,EACtC,EAAE,EAAA,QAAA,EACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,ogBAAA,CAAA,EAAA;;sBA8BA;;sBACA;;;AClDH;;;;;;;;;;AAUG;MAgIU,qBAAqB,CAAA;AACL,IAAA,MAAM;IACxB,OAAO,GAAsB,EAAE;;IAE/B,IAAI,GAAuB,IAAI;IAC/B,QAAQ,GAAG,IAAI;;AAGL,IAAA,UAAU,GAAG,IAAI,YAAY,EAAe;AAE5C,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;AAC1B,IAAA,IAAI,GAAG,MAAM,CAAe,EAAE,2EAAC;AAClD;;;;;;AAMG;AACgB,IAAA,WAAW,GAAG,MAAM,CAAC,CAAC,kFAAC;IAE1C,WAAW,GAAA;QACT,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC1F,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC;AACxC,QAAA,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;QAElF,IAAI,CAAC,IAAI,CAAC,GAAG,CACX,OAAO,CAAC,GAAG,CAAC,MAAM,IAAG;YACnB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;YACnC,OAAO;gBACL,MAAM;AACN,gBAAA,MAAM,EAAE,KAAK,EAAE,MAAM,IAAI,IAAI;AAC7B,gBAAA,OAAO,EAAE,KAAK,EAAE,UAAU,KAAK,OAAO;aACvC;QACH,CAAC,CAAC,CACH;IACH;IAEU,WAAW,GAAA;AACnB,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,MAAM;IAC9D;IAEU,eAAe,GAAA;QACvB,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,MAAM;IACrF;IAEU,MAAM,CAAC,GAAe,EAAE,MAAqB,EAAA;QACrD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IACnB,IAAI,CAAC,GAAG,CAAC,SAAS,IAChB,SAAS,CAAC,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,MAAM,CAAC;AAClC;gBACE,EAAE,GAAG,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK;AACxC,cAAE,SAAS,CACd,CACF;QACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IACrC;;IAGQ,MAAM,GAAA;AACZ,QAAA,MAAM,OAAO,GAAmB,IAAI,CAAC,IAAI;aACtC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI;AACjC,aAAA,GAAG,CAAC,GAAG,KAAK;AACX,YAAA,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG;YACnB,MAAM,EAAE,GAAG,CAAC,MAAgB;YAC5B,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAgB,CAAC;YAC1C,UAAU,EAAE,GAAG,CAAC,OAAO,GAAI,OAAiB,GAAI,OAAiB;AAClE,SAAA,CAAC,CAAC;QAEL,OAAO;AACL,YAAA,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE;AACjC,YAAA,aAAa,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO;AACnC,YAAA,aAAa,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;YAChC,OAAO;SACR;IACH;wGA3EW,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAArB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,MAAA,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,EAAA,UAAA,EAAA,YAAA,EAAA,EAAA,aAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA1HtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,o0CAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAzDS,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,cAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,uBAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,0BAAA,EAAA,QAAA,EAAA,6GAAA,EAAA,MAAA,EAAA,CAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FA2HV,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBA/HjC,SAAS;+BACE,mBAAmB,EAAA,UAAA,EACjB,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,OAAA,EACtC,CAAC,WAAW,CAAC,EAAA,QAAA,EACZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,o0CAAA,CAAA,EAAA;;sBAmEA,KAAK;uBAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;;sBACxB;;sBAEA;;sBACA;;sBAGA;;;ACnJH;;;;;;;;;;;;;;;;;;;;;;AAsBG;MAsFU,sBAAsB,CAAA;AACN,IAAA,MAAM;AACN,IAAA,IAAI;IACtB,IAAI,GAAmC,EAAE;AACzC,IAAA,OAAO;;AAEP,IAAA,KAAK;IACL,QAAQ,GAAG,IAAI;AAEL,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;;AAG1B,IAAA,OAAO,GAAG,MAAM,CAAiB,EAAE,8EAAC;AACpC,IAAA,IAAI,GAAG,MAAM,CAAe,EAAE,2EAAC;IAElD,WAAW,GAAA;AACT,QAAA,MAAM,KAAK,GAAG,IAAI,GAAG,CACnB,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CACvF;QAED,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,EAAE,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAChF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAE,CAAC,CAAC;;;AAI7D,QAAA,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE;YAC7D,IAAI,EAAE,IAAI,CAAC,QAAQ;YACnB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK,EAAE,IAAI,CAAC,KAAK;AACjB,YAAA,KAAK,EAAE,KAAK;AACZ,YAAA,cAAc,EAAE,CAAC;AAClB,SAAA,CAAC;AACF,QAAA,MAAM,eAAe,GAAG,IAAI,GAAG,EAAoB;AACnD,QAAA,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE;YACjC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5F;AAEA,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CACX,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,MAAM;YAC7B,UAAU,EAAE,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;AAC5C,YAAA,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,IAAG;AACzB,gBAAA,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAE,CAAC,KAAK;gBACzC,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,KAAK,SAAS,GAAG,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;AAC3E,gBAAA,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE;oBACrC,IAAI,EAAE,IAAI,CAAC,QAAQ;oBACnB,OAAO,EAAE,IAAI,CAAC,OAAO;AACtB,iBAAA,CAAC;gBAEF,IAAI,OAAO,IAAI,OAAO;oBAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE;gBACpE,OAAO;AACL,oBAAA,IAAI,EAAE,kBAAkB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;AACjF,oBAAA,MAAM,EAAE,KAAK;iBACd;AACH,YAAA,CAAC,CAAC;SACH,CAAC,CAAC,CACJ;IACH;wGAxDW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA,SAAA,EAAA,KAAA,EAAA,OAAA,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,aAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAhFvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,+2BAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FA4CU,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBArFlC,SAAS;+BACE,oBAAoB,EAAA,UAAA,EAClB,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,OAAA,EACtC,EAAE,EAAA,QAAA,EACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,+2BAAA,CAAA,EAAA;;sBA6CA,KAAK;uBAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;;sBACxB,KAAK;uBAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;;sBACxB;;sBACA;;sBAEA;;sBACA;;;AClHH;;;;;;;;;;;AAWG;MA0HU,uBAAuB,CAAA;AACP,IAAA,MAAM;IACxB,QAAQ,GAAG,IAAI;;AAGL,IAAA,QAAQ,GAAG,IAAI,YAAY,EAAY;AAEvC,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;AAC1B,IAAA,OAAO,GAAG,MAAM,CAAmB,EAAE,8EAAC;AACtC,IAAA,WAAW,GAAG,MAAM,CAAsB,EAAE,kFAAC;IAEhE,WAAW,GAAA;AACT,QAAA,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;AACpE,QAAA,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;;;AAIzE,QAAA,MAAM,IAAI,GAAG,IAAI,GAAG,EAA0B;QAC9C,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,KAAI;YACjC,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC;AACpC,YAAA,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE;AACnB,YAAA,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE;gBACZ,GAAG;gBACH,MAAM,EAAE,MAAM,CAAC,UAAU,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC;gBACvF,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;AACzB,gBAAA,QAAQ,EAAE,IAAI;AACf,aAAA,CAAC;AACJ,QAAA,CAAC,CAAC;AAEF,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC;IAC3C;IAEU,aAAa,GAAA;AACrB,QAAA,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM;IAChE;IAEU,YAAY,GAAA;QACpB,OAAO,IAAI,CAAC,OAAO;aAChB,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ;aAChC,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC;IAC9B;AAEU,IAAA,MAAM,CAAC,GAAW,EAAA;AAC1B,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,IACzB,OAAO,CAAC,GAAG,CAAC,MAAM,IAChB,MAAM,CAAC,GAAG,KAAK,GAAG,GAAG,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,MAAM,CACxE,CACF;IACH;AAEU,IAAA,SAAS,CAAC,QAAiB,EAAA;QACnC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,KAAK,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IAClF;wGArDW,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAvB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,uBAAuB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,aAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EApHxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,2oCAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAmEU,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBAzHnC,SAAS;+BACE,qBAAqB,EAAA,UAAA,EACnB,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,OAAA,EACtC,EAAE,EAAA,QAAA,EACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,2oCAAA,CAAA,EAAA;;sBAoEA,KAAK;uBAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;;sBACxB;;sBAGA;;AAmDH;AACA,SAAS,cAAc,CAAC,MAAc,EAAA;IACpC,OAAO,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;AACpC;;AC7LA;;;;;;;;;;;AAWG;MAsMU,qBAAqB,CAAA;AACL,IAAA,MAAM;AACjC;;;;;AAKG;AACM,IAAA,KAAK;AACd;;;;;AAKG;AACM,IAAA,OAAO;IACP,QAAQ,GAAG,IAAI;;IAEf,cAAc,GAAmB,KAAK;;AAG5B,IAAA,cAAc,GAAG,IAAI,YAAY,EAAgB;;AAEjD,IAAA,aAAa,GAAG,IAAI,YAAY,EAAQ;AAExC,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;IAC1B,KAAK,GAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC;AAEnD,IAAA,IAAI,GAAG,MAAM,CAAO,QAAQ,2EAAC;AAC7B,IAAA,IAAI,GAAG,MAAM,CAAC,KAAK,2EAAC;AACpB,IAAA,OAAO,GAAG,MAAM,CAAgB,IAAI,8EAAC;AACrC,IAAA,OAAO,GAAG,MAAM,CAAW,EAAE,8EAAC;AAC9B,IAAA,MAAM,GAAG,MAAM,CAAa,EAAE,6EAAC;AAC/B,IAAA,QAAQ,GAAG,MAAM,CAAC,CAAC,+EAAC;AACpB,IAAA,QAAQ,GAAG,MAAM,CAAC,EAAE,+EAAC;AACrB,IAAA,IAAI,GAAG,MAAM,CAAqB,IAAI,2EAAC;AACvC,IAAA,MAAM,GAAG,MAAM,CAAsB,IAAI,6EAAC;IAE5C,UAAU,GAAG,MAAM,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACzD,IAAA,KAAK,GAAG,MAAM,CAAC,oBAAoB,CAAC;AACpC,IAAA,cAAc,GAAG,MAAM,CAAC,qBAAqB,CAAC;IACvD,IAAI,GAAgB,IAAI;;AAGb,IAAA,eAAe,GAAG,MAAM,CAAgB,EAAE,sFAAC;AAE9D,IAAA,IAAY,SAAS,GAAA;AACnB,QAAA,OAAO,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK;IACtC;IAEQ,OAAO,GAAA;QACb,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK,EAAE,IAAI,CAAC,KAAK;AACjB,YAAA,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE;YAC/B,IAAI,EAAE,IAAI,CAAC,QAAQ;SACpB;IACH;AAEA;;;;;;;;;;;;;AAaG;AACK,IAAA,MAAM,WAAW,GAAA;QACvB,MAAM,YAAY,GAAkB,EAAE;AAEtC,QAAA,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU;QAC/B,KAAK,MAAM,MAAM,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;AACpD,YAAA,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ;gBAAE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC7D;AAEA,QAAA,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE;;;AAG5B,YAAA,IAAI;AACF,gBAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,cAAc,CACtD,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,EACvD,IAAI,CAAC,QAAQ,CACd;gBACD,IAAI,OAAO,CAAC,MAAM;AAAE,oBAAA,YAAY,CAAC,QAAQ,CAAC,GAAG,OAAO;YACtD;AAAE,YAAA,MAAM;;YAER;QACF;AAEA,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,GAAG,YAAY,EAAE,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;IACxE;AAEU,IAAA,SAAS,CAAC,IAAU,EAAA;;AAE5B,QAAA,MAAM,IAAI,GAAG;AACX,YAAA,MAAM,EAAE,cAAc;AACtB,YAAA,GAAG,EAAE,WAAW;AAChB,YAAA,MAAM,EAAE,cAAc;AACtB,YAAA,IAAI,EAAE,YAAY;SACV;AACV,QAAA,OAAO,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC;IAChD;IAEU,MAAM,UAAU,CAAC,KAAY,EAAA;AACrC,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B;QAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,IAAI;QACrC,IAAI,CAAC,IAAI,EAAE;AACT,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/D;QACF;AAEA,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;AACtB,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;AAEnB,QAAA,IAAI;AACF,YAAA,MAAM,IAAI,CAAC,WAAW,EAAE;AACxB,YAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;;;AAGlE,YAAA,IAAI,CAAC,IAAI,GAAG,IAAI;YAChB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;YAC5B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;YACjC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;YAC/B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC;AACjC,YAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;QACtB;QAAE,OAAO,KAAK,EAAE;;;YAGd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACpC;gBAAU;AACR,YAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;QACtB;IACF;AAEU,IAAA,MAAM,MAAM,GAAA;AACpB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE;QACxB,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE;AACvB,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/D;QACF;AAEA,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;AACnB,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;AAEtB,QAAA,IAAI;YACF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;;;YAI3E,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,IAAI,EAAE;AACzE,YAAA,IAAI,KAAK,CAAC,MAAM,EAAE;AAChB,gBAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CACd,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,QAAQ,EAAE;AAC/C,oBAAA,OAAO,EAAE,oBAAoB,CAAC,KAAK,CAAC;AACrC,iBAAA,CAAC,CACH;AACD,gBAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;gBACpB;YACF;AAEA,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;AACvB,YAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;AACrB,YAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;QAClC;QAAE,OAAO,KAAK,EAAE;YACd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACpC;gBAAU;AACR,YAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;QACtB;IACF;IAEU,MAAM,gBAAgB,CAAC,MAAgB,EAAA;AAC/C,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;AACtB,QAAA,IAAI;AACF,YAAA,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;;;;YAI5E,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC;AAC7F,YAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;AAC7B,YAAA,QAAQ,CAAC,IAAI,EAAE,CAAA,EAAG,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,QAAQ,CAAA,UAAA,EAAa,IAAI,CAAC,cAAc,CAAA,CAAE,CAAC;QACtF;QAAE,OAAO,KAAK,EAAE;YACd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACpC;IACF;AAEA;;;;;;;AAOG;AACO,IAAA,aAAa,CAAC,MAAoB,EAAA;QAC1C,OAAO,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM;IACjD;AAEA;;;;;;;;;;AAUG;AACO,IAAA,cAAc,CAAC,MAAoB,EAAA;QAC3C,OAAO,MAAM,CAAC,MAAM,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI;IAC7E;IAEU,OAAO,GAAA;AACf,QAAA,IAAI,CAAC,IAAI,GAAG,IAAI;AAChB,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;AACrB,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;AACpB,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AACnB,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AACpB,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;AACnB,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;AACrB,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;AACtB,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;IACzB;wGArOW,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAArB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,EAAA,OAAA,EAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,aAAA,EAAA,eAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA3LtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoHT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,2+CAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAzHC,uBAAuB,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACvB,qBAAqB,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACrB,sBAAsB,mIACtB,qBAAqB,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,UAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FA6LZ,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBArMjC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,mBAAmB,cACjB,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,OAAA,EACtC;wBACP,uBAAuB;wBACvB,qBAAqB;wBACrB,sBAAsB;wBACtB,qBAAqB;qBACtB,EAAA,QAAA,EACS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoHT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,2+CAAA,CAAA,EAAA;;sBAwEA,KAAK;uBAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;;sBAOxB;;sBAOA;;sBACA;;sBAEA;;sBAGA;;sBAEA;;AAiNH,SAAS,SAAS,CAAC,KAAc,EAAA;AAC/B,IAAA,OAAO,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;AAC/D;AAEA;;;;;;AAMG;AACH,SAAS,QAAQ,CAAC,IAAU,EAAE,QAAgB,EAAA;IAC5C,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE;IACrC,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC;IACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC;AAC1C,IAAA,MAAM,CAAC,IAAI,GAAG,GAAG;AACjB,IAAA,MAAM,CAAC,QAAQ,GAAG,QAAQ;AAC1B,IAAA,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;AAC7B,IAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;IACjC,MAAM,CAAC,KAAK,EAAE;AACd,IAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;IACjC,UAAU,CAAC,MAAM,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;AAC5C;;AC9eA;;ACAA;;AAEG;;;;"}