ngx-dynamic-entity 2.1.1 → 2.3.0

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,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, Type, EnvironmentProviders, WritableSignal, OnInit, OnChanges, OnDestroy, EventEmitter, SimpleChanges, Provider } from '@angular/core';
3
- import { ReferenceOption, LocalizedText, EntityFormConfig, FormRule, ImportLookups, MappingPlan, ImportResult, TemplateSpec, SheetData, CommonModuleEntry, EntityReferenceLoader, LookupListSource, RecordMigration, FileUploadHandler, FieldValidators, NestedFieldConfig, ReferenceLoaderContext, DropdownOption, LookupListValue, NestedTabConfig, RuleEvaluationResult, FieldScopeEntry, EvaluateFormRulesOptions, ImportColumn, UnsupportedColumn, ImportRowError } from '@dynamic-entity/core';
3
+ import { ReferenceOption, LocalizedText, EntityFormConfig, FormRule, ImportLookups, MappingPlan, CsvDelimiter, ImportResult, TemplateSpec, SheetGrid, CommonModuleEntry, EntityReferenceLoader, LookupListSource, RecordMigration, FileUploadHandler, FieldValidators, NestedFieldConfig, ReferenceLoaderContext, DropdownOption, LookupListValue, NestedTabConfig, RuleEvaluationResult, FieldScopeEntry, EvaluateFormRulesOptions, ImportColumn, MappingEntry, UnsupportedColumn, ImportRowError, SliderBounds } from '@dynamic-entity/core';
4
4
  export { AutoPatchConfig, CommonModuleEntry, ComponentClass, DropdownOption, EntityFormConfig, EntityPermissions, EntityReferenceConfig, EntityReferenceLoader, FieldTableConfig, FieldValidators, FileRef, FormRule, LocalizedText, NestedFieldConfig, NestedTabConfig, PatchOnTrueMapping, RbacContext, ReferenceLoaderContext, ReferenceOption, RichFieldType, RuleAction, RuleCondition, RuleEvaluationResult, VersionedRecord, formatDisplayValue, normalizeConfig, normalizeOption, resolveLabel, resolveOptionLabel, resolveOptionValue, valuesMatch } from '@dynamic-entity/core';
5
5
  import { ValidatorFn, AsyncValidatorFn, AbstractControl, ValidationErrors, FormGroup, FormArray } from '@angular/forms';
6
6
  import * as rxjs from 'rxjs';
@@ -83,6 +83,10 @@ declare const DEFAULT_UI_TEXT: {
83
83
  noImage: string;
84
84
  uploadImage: string;
85
85
  changeImage: string;
86
+ ratingValue: string;
87
+ clearValue: string;
88
+ addTagPlaceholder: string;
89
+ removeTag: string;
86
90
  month: string;
87
91
  year: string;
88
92
  write: string;
@@ -116,7 +120,15 @@ declare const DEFAULT_UI_TEXT: {
116
120
  importGuessed: string;
117
121
  importMappedCount: string;
118
122
  importRequiredUnmapped: string;
123
+ importConstant: string;
124
+ importAddSlot: string;
125
+ importStaleHeading: string;
126
+ importStaleExplain: string;
127
+ importRemoveEntry: string;
119
128
  importPreviewHeading: string;
129
+ importDelimiterComma: string;
130
+ importDelimiterSemicolon: string;
131
+ importDelimiterTab: string;
120
132
  importRowRejected: string;
121
133
  importRunImport: string;
122
134
  importImporting: string;
@@ -215,27 +227,35 @@ declare class UiTextService {
215
227
  /**
216
228
  * Reads an uploaded file into headers and positional rows.
217
229
  *
218
- * Positional (`string[][]`), not keyed by header, because a real sheet carries duplicate
219
- * headers and blank ones — and because a mapping entry addresses a column by index for
220
- * exactly that reason. A parser that returned objects keyed by header would silently lose
221
- * the second of two columns both called "Notes".
230
+ * Positional, not keyed by header, because a real sheet carries duplicate headers and blank
231
+ * ones — and because a mapping entry addresses a column by index for exactly that reason. A
232
+ * parser that returned objects keyed by header would silently lose the second of two columns
233
+ * both called "Notes".
222
234
  *
223
- * The library ships a CSV implementation and no more. Registering one that understands
235
+ * Cells may keep their types (`SheetGrid`): a date cell handed over as a `Date` at UTC midnight
236
+ * is imported as that calendar date, exactly as the server reads the same workbook, where its
237
+ * text is whatever a library's formatter printed. A parser returning text (`SheetData`, as 2.2's
238
+ * did) still fits.
239
+ *
240
+ * The library ships a delimited-text reader and no more. Registering one that understands
224
241
  * `.xlsx` is how a consumer adds it, and which spreadsheet library they use stays their
225
242
  * choice — this package has no runtime dependency and gains none here.
226
243
  *
227
244
  * @example
245
+ * // SheetJS 0.20.3+ from https://cdn.sheetjs.com — the npm `xlsx` package stopped at 0.18.5,
246
+ * // which has known vulnerabilities. `UTC: true` matters: without it a date cell arrives at
247
+ * // *local* midnight, which is the previous day in UTC for anyone east of Greenwich.
228
248
  * provideNgxDynamicEntity({
229
249
  * sheetParser: async file => {
230
- * const workbook = XLSX.read(await file.arrayBuffer());
250
+ * const workbook = XLSX.read(await file.arrayBuffer(), { cellDates: true });
231
251
  * const rows = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]], {
232
- * header: 1, raw: false, defval: '',
233
- * }) as string[][];
234
- * return { headers: rows[0] ?? [], rows: rows.slice(1) };
252
+ * header: 1, raw: true, defval: '', UTC: true,
253
+ * }) as unknown[][];
254
+ * return { headers: (rows[0] ?? []).map(cellText), rows: rows.slice(1) };
235
255
  * },
236
256
  * })
237
257
  */
238
- type SheetParser = (file: File) => SheetData | Promise<SheetData>;
258
+ type SheetParser = (file: File) => SheetGrid | Promise<SheetGrid>;
239
259
  /** The formats a generated template can be written in. CSV needs no dependency. */
240
260
  type TemplateFormat = 'csv' | 'xlsx';
241
261
  /** What the wizard needs to know about the entity it is importing into. */
@@ -262,6 +282,13 @@ interface ImportPreview {
262
282
  suggestion: MappingPlan;
263
283
  /** Total data rows in the file, which may be far more than `sample` holds. */
264
284
  rowCount: number;
285
+ /**
286
+ * Rows of each repeating field the suggestion was sized for (`arrayBoundFor`). Optional so a
287
+ * transport written for 2.2 keeps compiling; the mapper sizes itself the same way regardless.
288
+ */
289
+ arrayBound?: number;
290
+ /** The field separator a delimited-text file used. Absent for a workbook. */
291
+ delimiter?: CsvDelimiter;
265
292
  }
266
293
  /**
267
294
  * Where the work happens.
@@ -616,7 +643,7 @@ declare const provideNgxDynamicEntity: (config?: NgxDynamicEntityConfig) => Envi
616
643
  *
617
644
  * `FieldRegistryService` imports no components. Whatever you register here is what gets
618
645
  * bundled, so an app that only uses text/number/dropdown pays for three components and
619
- * their imports, not twenty-one.
646
+ * their imports, not twenty-seven.
620
647
  *
621
648
  * ```ts
622
649
  * // Everything (convenient; bundles all built-ins):
@@ -632,7 +659,7 @@ declare const provideNgxDynamicEntity: (config?: NgxDynamicEntityConfig) => Envi
632
659
  declare function builtInFieldTypes(): Record<string, Type<any>>;
633
660
  /** Register a specific set of field types. Only the components you name are bundled. */
634
661
  declare function provideFieldTypes(types: Record<string, Type<any>>): EnvironmentProviders;
635
- /** Register all 21 built-in field type keys. Convenience for apps that use most of them. */
662
+ /** Register all 27 built-in field type keys. Convenience for apps that use most of them. */
636
663
  declare function provideBuiltInFieldTypes(): EnvironmentProviders;
637
664
 
638
665
  /**
@@ -678,6 +705,10 @@ declare class HookRegistryService {
678
705
  static ɵprov: i0.ɵɵInjectableDeclaration<HookRegistryService>;
679
706
  }
680
707
 
708
+ /** The built-in web address check. The rule itself is in core, so an import applies the same one. */
709
+ declare const urlValidator: ValidatorFn;
710
+ /** The built-in phone number check. The rule itself is in core, so an import applies the same one. */
711
+ declare const phoneValidator: ValidatorFn;
681
712
  /**
682
713
  * ValidatorRegistryService — resolves validator configs / key strings to Angular ValidatorFns.
683
714
  */
@@ -993,6 +1024,11 @@ interface RuleSyncContext {
993
1024
  addressOf(field: NestedFieldConfig): string;
994
1025
  /** The control a scope entry addresses, or `null` when it has no static path. */
995
1026
  controlFor(entry: FieldScopeEntry): AbstractControl | null;
1027
+ /**
1028
+ * The config the entries came from. Needed to know which tab owns each field: a tab that is
1029
+ * not rendered hides every field it owns. Omitted, only field-level visibility applies.
1030
+ */
1031
+ config?: EntityFormConfig | null;
996
1032
  }
997
1033
  /**
998
1034
  * RulesEvaluationService — evaluates rules, and owns what a result *means*.
@@ -1038,12 +1074,25 @@ declare class RulesEvaluationService {
1038
1074
  * The predicate is `isFieldVisible`, the same one the render filter uses, so what is on
1039
1075
  * screen and what counts toward validity cannot drift apart.
1040
1076
  *
1077
+ * A tab that is not rendered — hidden by a rule, or `visibility: false` with no rule showing
1078
+ * it — hides everything it owns, sub-tabs and container children included. Only fields were
1079
+ * checked here, so a rule hiding a tab with a required field on it left the form invalid
1080
+ * with the field out of sight and out of the error summary: Save did nothing, silently.
1081
+ * Import already relaxed a hidden tab's fields, so the form refused rows import accepted.
1082
+ *
1041
1083
  * Entries must arrive parent-first, which is what `collectFieldScopes` yields: a container's
1042
1084
  * children are skipped once the container itself is hidden, because Angular's `disable()`
1043
1085
  * cascades to descendants and a child's `enable()` walks back up recalculating ancestors.
1044
1086
  * Toggling a child inside a hidden group would fight its parent.
1045
1087
  */
1046
1088
  syncHiddenFieldState(entries: readonly FieldScopeEntry[], ctx: RuleSyncContext): void;
1089
+ /**
1090
+ * Every field owned by a tab that does not render, under `isTabVisible`'s precedence.
1091
+ *
1092
+ * Stops descending at the first hidden tab: `fieldsUnderTab` already covers its sub-tabs,
1093
+ * and a sub-tab of a hidden tab is not rendered whatever its own visibility says.
1094
+ */
1095
+ private fieldsOnHiddenTabs;
1047
1096
  /**
1048
1097
  * The hidden and shown names as sets, memoised against the result they came from.
1049
1098
  *
@@ -2127,6 +2176,8 @@ declare class EntityImportComponent {
2127
2176
  protected readonly headers: i0.WritableSignal<string[]>;
2128
2177
  protected readonly sample: i0.WritableSignal<string[][]>;
2129
2178
  protected readonly rowCount: i0.WritableSignal<number>;
2179
+ /** The separator a delimited file turned out to use, so the user can see how it was read. */
2180
+ protected readonly delimiter: i0.WritableSignal<CsvDelimiter>;
2130
2181
  protected readonly fileName: i0.WritableSignal<string>;
2131
2182
  protected readonly plan: i0.WritableSignal<MappingPlan>;
2132
2183
  protected readonly result: i0.WritableSignal<ImportResult>;
@@ -2178,6 +2229,10 @@ declare class EntityImportComponent {
2178
2229
  * exact and `failed` is absent.
2179
2230
  */
2180
2231
  protected failedRowCount(result: ImportResult): number;
2232
+ /** The decimal mark the commit will read numbers with, so the preview reads them the same. */
2233
+ protected decimal(): '.' | ',';
2234
+ /** How the file's columns were split, in words — or nothing for a workbook. */
2235
+ protected delimiterText(): string | null;
2181
2236
  protected restart(): void;
2182
2237
  static ɵfac: i0.ɵɵFactoryDeclaration<EntityImportComponent, never>;
2183
2238
  static ɵcmp: i0.ɵɵComponentDeclaration<EntityImportComponent, "ngx-entity-import", never, { "config": { "alias": "config"; "required": true; }; "rules": { "alias": "rules"; "required": false; }; "lookups": { "alias": "lookups"; "required": false; }; "language": { "alias": "language"; "required": false; }; "templateFormat": { "alias": "templateFormat"; "required": false; }; }, { "importComplete": "importComplete"; "templateReady": "templateReady"; }, never, never, true, never>;
@@ -2186,9 +2241,18 @@ declare class EntityImportComponent {
2186
2241
  /** One target field, and which of the sheet's columns feeds it. */
2187
2242
  interface MappingRow {
2188
2243
  column: ImportColumn;
2189
- /** Index into the sheet's headers, or `null` for "not imported". */
2244
+ /** Index into the sheet's headers, `CONSTANT` for a fixed value, or `null` for "not imported". */
2190
2245
  source: number | null;
2191
2246
  guessed: boolean;
2247
+ /** The incoming plan's entry for this field, emitted untouched until the user changes it. */
2248
+ entry?: MappingEntry;
2249
+ /** The user changed this row, so `entry` no longer describes it. */
2250
+ dirty: boolean;
2251
+ }
2252
+ /** A repeating field, for its "Add a row" button. */
2253
+ interface ArraySlots {
2254
+ arrayRef: string;
2255
+ label: string;
2192
2256
  }
2193
2257
  /**
2194
2258
  * Match the sheet's columns to the config's fields.
@@ -2219,11 +2283,39 @@ declare class ImportMapperComponent implements OnChanges {
2219
2283
  * attachment column was never going to arrive.
2220
2284
  */
2221
2285
  protected readonly unsupported: i0.WritableSignal<number>;
2286
+ /** A plan entry whose field this config no longer has. Kept, and emitted, until removed. */
2287
+ protected readonly stale: i0.WritableSignal<MappingEntry[]>;
2288
+ /** Repeating fields the user can add a row to. */
2289
+ protected readonly arrays: i0.WritableSignal<ArraySlots[]>;
2290
+ protected readonly constant = -1;
2291
+ /** Rows added by hand per repeating field, on top of what the sheet and plan imply. */
2292
+ private readonly extraSlots;
2293
+ /** The incoming plan, read through the 2.2 alias. Every entry in it survives `toPlan`. */
2294
+ private incoming;
2222
2295
  ngOnChanges(): void;
2296
+ /**
2297
+ * Rows for every field, sized so nothing the plan or the sheet names is out of reach.
2298
+ *
2299
+ * Sizing from the default three meant a sheet with `Phone 4` could not be mapped at all,
2300
+ * and a stored plan reaching further lost those entries on the next change — `toPlan` only
2301
+ * ever emitted rows, and there were none for them.
2302
+ */
2303
+ private rebuild;
2223
2304
  protected mappedCount(): number;
2224
2305
  protected missingRequired(): number;
2306
+ protected hasConstant(row: MappingRow): boolean;
2307
+ protected constantText(entry: MappingEntry): string;
2225
2308
  protected choose(row: MappingRow, source: number | null): void;
2226
- /** The current selections as the plan that will be applied. */
2309
+ /** One more row for one repeating field, for this session. */
2310
+ protected addSlot(arrayRef: string): void;
2311
+ protected removeStale(entry: MappingEntry): void;
2312
+ /**
2313
+ * The current selections as the plan that will be applied.
2314
+ *
2315
+ * Every entry of the incoming plan survives in its own position — a fixed value, a ref the
2316
+ * config no longer has — unless the user changed or removed it, and an untouched entry is
2317
+ * emitted exactly as it arrived. New selections follow, in field order.
2318
+ */
2227
2319
  private toPlan;
2228
2320
  static ɵfac: i0.ɵɵFactoryDeclaration<ImportMapperComponent, never>;
2229
2321
  static ɵcmp: i0.ɵɵComponentDeclaration<ImportMapperComponent, "ngx-import-mapper", never, { "config": { "alias": "config"; "required": true; }; "headers": { "alias": "headers"; "required": false; }; "plan": { "alias": "plan"; "required": false; }; "language": { "alias": "language"; "required": false; }; }, { "planChange": "planChange"; }, never, never, true, never>;
@@ -2271,13 +2363,15 @@ declare class ImportPreviewComponent implements OnChanges {
2271
2363
  /** The same rules the commit will apply; without them a rule-driven rejection is invisible. */
2272
2364
  rules?: readonly FormRule[];
2273
2365
  language: string;
2366
+ /** The decimal mark number cells use — the one the commit will read them with. */
2367
+ decimal: '.' | ',';
2274
2368
  protected readonly ui: UiTextService;
2275
2369
  /** The columns this plan fills, in the plan's own order. */
2276
2370
  protected readonly columns: i0.WritableSignal<ImportColumn[]>;
2277
2371
  protected readonly grid: i0.WritableSignal<PreviewRow[]>;
2278
2372
  ngOnChanges(): void;
2279
2373
  static ɵfac: i0.ɵɵFactoryDeclaration<ImportPreviewComponent, never>;
2280
- static ɵcmp: i0.ɵɵComponentDeclaration<ImportPreviewComponent, "ngx-import-preview", never, { "config": { "alias": "config"; "required": true; }; "plan": { "alias": "plan"; "required": true; }; "rows": { "alias": "rows"; "required": false; }; "lookups": { "alias": "lookups"; "required": false; }; "rules": { "alias": "rules"; "required": false; }; "language": { "alias": "language"; "required": false; }; }, {}, never, never, true, never>;
2374
+ static ɵcmp: i0.ɵɵComponentDeclaration<ImportPreviewComponent, "ngx-import-preview", never, { "config": { "alias": "config"; "required": true; }; "plan": { "alias": "plan"; "required": true; }; "rows": { "alias": "rows"; "required": false; }; "lookups": { "alias": "lookups"; "required": false; }; "rules": { "alias": "rules"; "required": false; }; "language": { "alias": "language"; "required": false; }; "decimal": { "alias": "decimal"; "required": false; }; }, {}, never, never, true, never>;
2281
2375
  }
2282
2376
 
2283
2377
  /** One field offered for the template, with the guidance that belongs to it. */
@@ -3257,5 +3351,261 @@ declare class FileFieldComponent {
3257
3351
  static ɵcmp: i0.ɵɵComponentDeclaration<FileFieldComponent, "ngx-file-field", never, { "field": { "alias": "field"; "required": false; }; "control": { "alias": "control"; "required": false; }; "language": { "alias": "language"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "masked": { "alias": "masked"; "required": false; }; }, {}, never, never, true, never>;
3258
3352
  }
3259
3353
 
3260
- export { ASYNC_VALIDATOR_REGISTRY, ArrayFieldComponent, BooleanFieldComponent, COMMON_MODULES_REGISTRY, CONFIG_SOURCE, CascadeDataService, CheckboxFieldComponent, ConfigSourceService, CurrencyFieldComponent, DEFAULT_UI_TEXT, DEFAULT_VALIDATION_MESSAGES, DateFieldComponent, DateTimeFieldComponent, DropdownFieldComponent, DynamicFieldComponent, DynamicFormComponent, DynamicRecordFormComponent, ENTITY_REF_CACHE_STORE, ENTITY_REF_REGISTRY, EmailFieldComponent, EntityImportComponent, EntityRefFieldComponent, EntityRefRegistryService, EntityRefSelectionService, EntityReferenceService, FIELD_TYPE_REGISTRY, FIELD_TYPE_SETS, FieldRegistryService, FileFieldComponent, GroupFieldComponent, HOOK_REGISTRY, HookRegistryService, HttpImportTransport, IMPORT_TRANSPORT, ImageFieldComponent, ImportErrorsComponent, ImportMapperComponent, ImportPreviewComponent, ImportTemplateComponent, InMemoryEntityRefCacheStore, LOOKUP_REGISTRY, LocalImportTransport, LookupRegistryService, MARKDOWN_RENDERER, MASKED_PLACEHOLDER, MASKED_ROLES, MarkdownFieldComponent, MonthYearFieldComponent, MultiSelectFieldComponent, NumberFieldComponent, PasswordFieldComponent, RECORD_MIGRATIONS, RadioFieldComponent, RbacService, RulesEvaluationService, SHEET_PARSER, SYSTEM_DEFAULT_CAN_EDIT, TextFieldComponent, TextareaFieldComponent, TimeFieldComponent, UI_TEXT, UPLOAD_HANDLER, UiTextService, VALIDATION_MESSAGES, VALIDATOR_REGISTRY, ValidationMessagesService, ValidatorRegistryService, builtInFieldTypes, defaultSheetParser, fieldDescribedBy, fieldDomId, nextFieldInstanceId, provideBuiltInFieldTypes, provideFieldTypes, provideHttpImportTransport, provideNgxDynamicEntity, refreshChoiceOptions, resolveUiText };
3354
+ /**
3355
+ * URL field: a `type="url"` input, and a link when read-only.
3356
+ *
3357
+ * The read-only link is rendered only for a value that passes `isValidUrl`, meaning an http or
3358
+ * https address. A record can hold anything, including `javascript:`, and a field whose job is
3359
+ * to show an address must not turn a stored script into something to click. Anything else is
3360
+ * shown as plain text.
3361
+ */
3362
+ declare class UrlFieldComponent {
3363
+ /**
3364
+ * Unique to this component instance: an `array` renders the same field once per row, and a
3365
+ * DOM id may not repeat. See `field-dom-id.ts`.
3366
+ */
3367
+ private readonly instanceId;
3368
+ protected domId(suffix?: string): string;
3369
+ /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */
3370
+ protected readonly maskedText: string;
3371
+ private readonly messages;
3372
+ field: NestedFieldConfig;
3373
+ control: AbstractControl;
3374
+ language: string;
3375
+ readonly: boolean;
3376
+ masked: boolean;
3377
+ get label(): string;
3378
+ get placeholder(): string;
3379
+ /** Author help text, shown under the control and named by `aria-describedby`. */
3380
+ get hint(): string;
3381
+ /** Whether the stored value is an http(s) address, and so safe to render as a link. */
3382
+ get linkable(): boolean;
3383
+ /** The ids of whatever is describing this control right now. */
3384
+ protected describedBy(): string | null;
3385
+ get errorMessage(): string;
3386
+ static ɵfac: i0.ɵɵFactoryDeclaration<UrlFieldComponent, never>;
3387
+ static ɵcmp: i0.ɵɵComponentDeclaration<UrlFieldComponent, "ngx-url-field", never, { "field": { "alias": "field"; "required": false; }; "control": { "alias": "control"; "required": false; }; "language": { "alias": "language"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "masked": { "alias": "masked"; "required": false; }; }, {}, never, never, true, never>;
3388
+ }
3389
+
3390
+ /**
3391
+ * Phone field: a `type="tel"` input, and a `tel:` link when read-only.
3392
+ *
3393
+ * The value is stored exactly as typed, spaces and brackets included. The number is shown back
3394
+ * to people far more often than it is dialled, and `+44 20 7946 0958` is easier to read than
3395
+ * its digits run together. Only the link target is stripped down to what a dialler needs.
3396
+ */
3397
+ declare class PhoneFieldComponent {
3398
+ /**
3399
+ * Unique to this component instance: an `array` renders the same field once per row, and a
3400
+ * DOM id may not repeat. See `field-dom-id.ts`.
3401
+ */
3402
+ private readonly instanceId;
3403
+ protected domId(suffix?: string): string;
3404
+ /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */
3405
+ protected readonly maskedText: string;
3406
+ private readonly messages;
3407
+ field: NestedFieldConfig;
3408
+ control: AbstractControl;
3409
+ language: string;
3410
+ readonly: boolean;
3411
+ masked: boolean;
3412
+ get label(): string;
3413
+ get placeholder(): string;
3414
+ /** Author help text, shown under the control and named by `aria-describedby`. */
3415
+ get hint(): string;
3416
+ /** `tel:` plus the digits and a leading `+`, or null for a value that is not a phone number. */
3417
+ get dialHref(): string | null;
3418
+ /** The ids of whatever is describing this control right now. */
3419
+ protected describedBy(): string | null;
3420
+ get errorMessage(): string;
3421
+ static ɵfac: i0.ɵɵFactoryDeclaration<PhoneFieldComponent, never>;
3422
+ static ɵcmp: i0.ɵɵComponentDeclaration<PhoneFieldComponent, "ngx-phone-field", never, { "field": { "alias": "field"; "required": false; }; "control": { "alias": "control"; "required": false; }; "language": { "alias": "language"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "masked": { "alias": "masked"; "required": false; }; }, {}, never, never, true, never>;
3423
+ }
3424
+
3425
+ /**
3426
+ * Slider field: a range input over `validators.min`–`validators.max` in steps of `field.step`.
3427
+ *
3428
+ * A range input cannot show that it is empty. With no value it puts the thumb at the midpoint,
3429
+ * which looks exactly like a chosen value. The readout beside it is therefore the value itself,
3430
+ * and shows a dash until someone moves the thumb. Without it, a required slider nobody touched
3431
+ * would look answered and still fail at save.
3432
+ */
3433
+ declare class SliderFieldComponent {
3434
+ /**
3435
+ * Unique to this component instance: an `array` renders the same field once per row, and a
3436
+ * DOM id may not repeat. See `field-dom-id.ts`.
3437
+ */
3438
+ private readonly instanceId;
3439
+ protected domId(suffix?: string): string;
3440
+ /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */
3441
+ protected readonly maskedText: string;
3442
+ private readonly messages;
3443
+ field: NestedFieldConfig;
3444
+ control: AbstractControl;
3445
+ language: string;
3446
+ readonly: boolean;
3447
+ masked: boolean;
3448
+ get label(): string;
3449
+ /** Author help text, shown under the control and named by `aria-describedby`. */
3450
+ get hint(): string;
3451
+ get bounds(): SliderBounds;
3452
+ /** Whether the control holds a number. The thumb's position cannot say. */
3453
+ get hasValue(): boolean;
3454
+ get display(): string;
3455
+ /** The ids of whatever is describing this control right now. */
3456
+ protected describedBy(): string | null;
3457
+ get errorMessage(): string;
3458
+ static ɵfac: i0.ɵɵFactoryDeclaration<SliderFieldComponent, never>;
3459
+ static ɵcmp: i0.ɵɵComponentDeclaration<SliderFieldComponent, "ngx-slider-field", never, { "field": { "alias": "field"; "required": false; }; "control": { "alias": "control"; "required": false; }; "language": { "alias": "language"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "masked": { "alias": "masked"; "required": false; }; }, {}, never, never, true, never>;
3460
+ }
3461
+
3462
+ /**
3463
+ * Rating field: 1 to `validators.max` stars (default 5), stored as a number.
3464
+ *
3465
+ * Built from native radio inputs in a fieldset, not clickable spans. That gives it the
3466
+ * behaviour a radio group already has: arrow keys move the choice, Tab enters and leaves the
3467
+ * group once, and a screen reader announces "3 of 5, radio button, 3 of 5". Each star's
3468
+ * label is text a host can translate (`ratingValue`), because a star glyph read aloud is
3469
+ * "black star".
3470
+ */
3471
+ declare class RatingFieldComponent implements OnDestroy {
3472
+ /**
3473
+ * Unique to this component instance: an `array` renders the same field once per row, and a
3474
+ * DOM id may not repeat. See `field-dom-id.ts`.
3475
+ */
3476
+ private readonly instanceId;
3477
+ protected domId(suffix?: string): string;
3478
+ /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */
3479
+ protected readonly maskedText: string;
3480
+ private readonly messages;
3481
+ private readonly cdr;
3482
+ protected readonly ui: UiTextService;
3483
+ field: NestedFieldConfig;
3484
+ language: string;
3485
+ readonly: boolean;
3486
+ masked: boolean;
3487
+ private _control;
3488
+ private _controlSub?;
3489
+ /**
3490
+ * Subscribed because the radios are not bound through a form directive. A value patched in
3491
+ * from outside (a reset, an autoPatch) would otherwise leave an OnPush view showing the old
3492
+ * stars.
3493
+ */
3494
+ set control(value: AbstractControl);
3495
+ get control(): AbstractControl;
3496
+ ngOnDestroy(): void;
3497
+ get label(): string;
3498
+ /** Author help text, shown under the control and named by `aria-describedby`. */
3499
+ get hint(): string;
3500
+ get scale(): number;
3501
+ get stars(): number[];
3502
+ /** The stored rating, or null when there is none or it is not a star on this scale. */
3503
+ get current(): number | null;
3504
+ select(star: number): void;
3505
+ clear(): void;
3506
+ /** The ids of whatever is describing this control right now. */
3507
+ protected describedBy(): string | null;
3508
+ get errorMessage(): string;
3509
+ static ɵfac: i0.ɵɵFactoryDeclaration<RatingFieldComponent, never>;
3510
+ static ɵcmp: i0.ɵɵComponentDeclaration<RatingFieldComponent, "ngx-rating-field", never, { "field": { "alias": "field"; "required": false; }; "language": { "alias": "language"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "masked": { "alias": "masked"; "required": false; }; "control": { "alias": "control"; "required": false; }; }, {}, never, never, true, never>;
3511
+ }
3512
+
3513
+ /**
3514
+ * Colour field: a native colour picker, storing `#rrggbb`.
3515
+ *
3516
+ * Like a range input, a colour input has no empty state and shows black. The code beside it is
3517
+ * therefore the real value, a dash until a colour is chosen, and a clear button sets the value
3518
+ * back to nothing. Without them, "no colour" and "black" would look the same.
3519
+ *
3520
+ * Only a value that passes `normalizeHexColor` reaches a `style` binding. A record can hold
3521
+ * any string, and a colour swatch is no place to interpret one.
3522
+ */
3523
+ declare class ColorFieldComponent {
3524
+ /**
3525
+ * Unique to this component instance: an `array` renders the same field once per row, and a
3526
+ * DOM id may not repeat. See `field-dom-id.ts`.
3527
+ */
3528
+ private readonly instanceId;
3529
+ protected domId(suffix?: string): string;
3530
+ /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */
3531
+ protected readonly maskedText: string;
3532
+ private readonly messages;
3533
+ protected readonly ui: UiTextService;
3534
+ field: NestedFieldConfig;
3535
+ control: AbstractControl;
3536
+ language: string;
3537
+ readonly: boolean;
3538
+ masked: boolean;
3539
+ get label(): string;
3540
+ /** Author help text, shown under the control and named by `aria-describedby`. */
3541
+ get hint(): string;
3542
+ /** The stored colour as `#rrggbb`, or null when there is none or it is not a colour. */
3543
+ get hex(): string | null;
3544
+ clear(): void;
3545
+ /** The ids of whatever is describing this control right now. */
3546
+ protected describedBy(): string | null;
3547
+ get errorMessage(): string;
3548
+ static ɵfac: i0.ɵɵFactoryDeclaration<ColorFieldComponent, never>;
3549
+ static ɵcmp: i0.ɵɵComponentDeclaration<ColorFieldComponent, "ngx-color-field", never, { "field": { "alias": "field"; "required": false; }; "control": { "alias": "control"; "required": false; }; "language": { "alias": "language"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "masked": { "alias": "masked"; "required": false; }; }, {}, never, never, true, never>;
3550
+ }
3551
+
3552
+ /**
3553
+ * Tags field: free text entered as a list of chips, stored as `string[]`.
3554
+ *
3555
+ * Unlike `multiSelect`, the values are whatever the user types, so there is no option list to
3556
+ * keep in step. Enter or a comma ends a tag, Backspace in an empty box removes the last one,
3557
+ * and pasted text is split on commas, semicolons and line breaks. Leaving the box commits
3558
+ * what is in it, so a tag someone typed and then tabbed away from is not silently lost.
3559
+ *
3560
+ * The control holds the array. The text box is only a draft, which is why it is not bound
3561
+ * with a form directive.
3562
+ */
3563
+ declare class TagsFieldComponent implements OnDestroy {
3564
+ /**
3565
+ * Unique to this component instance: an `array` renders the same field once per row, and a
3566
+ * DOM id may not repeat. See `field-dom-id.ts`.
3567
+ */
3568
+ private readonly instanceId;
3569
+ protected domId(suffix?: string): string;
3570
+ /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */
3571
+ protected readonly maskedText: string;
3572
+ private readonly messages;
3573
+ private readonly cdr;
3574
+ protected readonly ui: UiTextService;
3575
+ field: NestedFieldConfig;
3576
+ language: string;
3577
+ readonly: boolean;
3578
+ masked: boolean;
3579
+ private _control;
3580
+ private _controlSub?;
3581
+ /** Subscribed for the same reason as the rating field: nothing here is a form directive. */
3582
+ set control(value: AbstractControl);
3583
+ get control(): AbstractControl;
3584
+ ngOnDestroy(): void;
3585
+ get label(): string;
3586
+ get placeholder(): string;
3587
+ /** Author help text, shown under the control and named by `aria-describedby`. */
3588
+ get hint(): string;
3589
+ /** The stored tags, read leniently. A record may hold a single string or anything else. */
3590
+ get tags(): string[];
3591
+ onKeydown(event: KeyboardEvent, entry: HTMLInputElement): void;
3592
+ onPaste(event: ClipboardEvent, entry: HTMLInputElement): void;
3593
+ onBlur(entry: HTMLInputElement): void;
3594
+ /** Add whatever is in the draft box, split on separators, and empty it. */
3595
+ commit(entry: HTMLInputElement): void;
3596
+ private add;
3597
+ remove(tag: string): void;
3598
+ /**
3599
+ * An empty list is stored as `[]`, not `null`. `required` treats both as empty, and `[]`
3600
+ * stays the same shape as every other value this field holds.
3601
+ */
3602
+ private write;
3603
+ /** The ids of whatever is describing this control right now. */
3604
+ protected describedBy(): string | null;
3605
+ get errorMessage(): string;
3606
+ static ɵfac: i0.ɵɵFactoryDeclaration<TagsFieldComponent, never>;
3607
+ static ɵcmp: i0.ɵɵComponentDeclaration<TagsFieldComponent, "ngx-tags-field", never, { "field": { "alias": "field"; "required": false; }; "language": { "alias": "language"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "masked": { "alias": "masked"; "required": false; }; "control": { "alias": "control"; "required": false; }; }, {}, never, never, true, never>;
3608
+ }
3609
+
3610
+ export { ASYNC_VALIDATOR_REGISTRY, ArrayFieldComponent, BooleanFieldComponent, COMMON_MODULES_REGISTRY, CONFIG_SOURCE, CascadeDataService, CheckboxFieldComponent, ColorFieldComponent, ConfigSourceService, CurrencyFieldComponent, DEFAULT_UI_TEXT, DEFAULT_VALIDATION_MESSAGES, DateFieldComponent, DateTimeFieldComponent, DropdownFieldComponent, DynamicFieldComponent, DynamicFormComponent, DynamicRecordFormComponent, ENTITY_REF_CACHE_STORE, ENTITY_REF_REGISTRY, EmailFieldComponent, EntityImportComponent, EntityRefFieldComponent, EntityRefRegistryService, EntityRefSelectionService, EntityReferenceService, FIELD_TYPE_REGISTRY, FIELD_TYPE_SETS, FieldRegistryService, FileFieldComponent, GroupFieldComponent, HOOK_REGISTRY, HookRegistryService, HttpImportTransport, IMPORT_TRANSPORT, ImageFieldComponent, ImportErrorsComponent, ImportMapperComponent, ImportPreviewComponent, ImportTemplateComponent, InMemoryEntityRefCacheStore, LOOKUP_REGISTRY, LocalImportTransport, LookupRegistryService, MARKDOWN_RENDERER, MASKED_PLACEHOLDER, MASKED_ROLES, MarkdownFieldComponent, MonthYearFieldComponent, MultiSelectFieldComponent, NumberFieldComponent, PasswordFieldComponent, PhoneFieldComponent, RECORD_MIGRATIONS, RadioFieldComponent, RatingFieldComponent, RbacService, RulesEvaluationService, SHEET_PARSER, SYSTEM_DEFAULT_CAN_EDIT, SliderFieldComponent, TagsFieldComponent, TextFieldComponent, TextareaFieldComponent, TimeFieldComponent, UI_TEXT, UPLOAD_HANDLER, UiTextService, UrlFieldComponent, VALIDATION_MESSAGES, VALIDATOR_REGISTRY, ValidationMessagesService, ValidatorRegistryService, builtInFieldTypes, defaultSheetParser, fieldDescribedBy, fieldDomId, nextFieldInstanceId, phoneValidator, provideBuiltInFieldTypes, provideFieldTypes, provideHttpImportTransport, provideNgxDynamicEntity, refreshChoiceOptions, resolveUiText, urlValidator };
3261
3611
  export type { ChoiceOptionHost, ConfigSourceHandler, DynamicFieldComponentContract, EntityRefCacheStore, EntityRefSelection, HookFn, HttpImportTransportOptions, ImportContext, ImportPreview, ImportTransport, InvalidField, MessageOrderEntry, NgxDynamicEntityConfig, RuleSyncContext, SheetParser, TemplateFormat, UiTextKey, UiTextOverrides, UiTextOverridesFor, UiTextParams, UiTextResolver, UiTextResolverFor, UiTextValue, ValidationMessage };