ngx-dynamic-entity 1.10.0 → 1.11.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.
@@ -53,6 +53,8 @@ declare const DEFAULT_UI_TEXT: {
53
53
  reset: string;
54
54
  saveShortcutHint: string;
55
55
  loading: string;
56
+ errorSummaryTitle: string;
57
+ tabErrorCount: string;
56
58
  editSection: string;
57
59
  saveSection: string;
58
60
  editingSection: string;
@@ -831,6 +833,8 @@ declare class ConfigSourceService {
831
833
  type ValidationMessage = string | ((language: string, error: any) => string);
832
834
  /** The built-in English messages. Every key here can be overridden individually. */
833
835
  declare const DEFAULT_VALIDATION_MESSAGES: Record<string, ValidationMessage>;
836
+ /** An error key, or a pair mapping one to a different message key. */
837
+ type MessageOrderEntry = string | readonly [errorKey: string, messageKey: string];
834
838
  declare class ValidationMessagesService {
835
839
  private readonly overrides;
836
840
  /**
@@ -841,12 +845,39 @@ declare class ValidationMessagesService {
841
845
  * most specific message is the one shown.
842
846
  */
843
847
  resolve(errors: ValidationErrors | null | undefined, language: string, order: readonly (string | readonly [errorKey: string, messageKey: string])[], fallbackKey?: string): string;
848
+ /**
849
+ * The message for a field, chosen by its **type** rather than by a list the caller supplies.
850
+ *
851
+ * Every field component used to pass its own copy of the key order, and the copies were
852
+ * near-identical — which was tolerable while the field itself was the only thing that
853
+ * rendered a message. It stopped being tolerable when the error summary above the form
854
+ * started naming what is wrong with each field: the summary has no field component to ask
855
+ * (the offending field is usually on a tab that is not rendered), so it would have needed a
856
+ * second copy of the same table, and a dropdown would have said "This field is required" in
857
+ * the summary and "Please select an option" under the control.
858
+ *
859
+ * One table, read from both places, is what keeps those two sentences the same sentence.
860
+ */
861
+ resolveForField(errors: ValidationErrors | null | undefined, language: string, fieldType: string): string;
862
+ /** A field type's key order. An unrecognised type — a consumer's own — gets the common list. */
863
+ orderFor(fieldType: string): {
864
+ order: readonly MessageOrderEntry[];
865
+ fallback: string;
866
+ };
844
867
  /** One message by key, honouring an override before the default. */
845
868
  messageFor(key: string, language: string, error: unknown): string;
846
869
  static ɵfac: i0.ɵɵFactoryDeclaration<ValidationMessagesService, never>;
847
870
  static ɵprov: i0.ɵɵInjectableDeclaration<ValidationMessagesService>;
848
871
  }
849
872
 
873
+ /** A field the form will not save, with what is wrong and where to find it. */
874
+ interface InvalidField {
875
+ field: NestedFieldConfig;
876
+ /** The same message the field renders under itself. */
877
+ message: string;
878
+ tabId: string;
879
+ subTabId?: string;
880
+ }
850
881
  /**
851
882
  * DynamicFormComponent — the main form component.
852
883
  * Renders a reactive form from EntityFormConfig with tab support, responsive 12-col grid,
@@ -898,6 +929,19 @@ declare class DynamicFormComponent implements OnInit, OnChanges, OnDestroy {
898
929
  * disable the form. Used by the builder's live preview.
899
930
  */
900
931
  preview: boolean;
932
+ /**
933
+ * How a field with no `colSpan` of its own is sized in the 12-column grid.
934
+ *
935
+ * `stack` — the historic behaviour — gives every such field the full twelve, so a form of
936
+ * eight short text fields renders as an eight-row ladder with two thirds of its width
937
+ * empty. `auto` sizes them by field type instead: a date or a number is half a row, a
938
+ * textarea or a nested group still takes all twelve.
939
+ *
940
+ * An explicit `colSpan` always wins in both modes, so turning `auto` on cannot override a
941
+ * layout somebody authored. The default stays `stack` because changing how existing configs
942
+ * render is not this input's business — opting in is.
943
+ */
944
+ layout: 'stack' | 'auto';
901
945
  formSubmit: EventEmitter<Record<string, any>>;
902
946
  formChange: EventEmitter<Record<string, any>>;
903
947
  formReset: EventEmitter<void>;
@@ -917,9 +961,15 @@ declare class DynamicFormComponent implements OnInit, OnChanges, OnDestroy {
917
961
  private readonly hookRegistry;
918
962
  private readonly rbacService;
919
963
  private readonly rulesEvaluation;
964
+ /** Resolves what is wrong with a field, for the error summary — see `resolveForField`. */
965
+ private readonly messages;
920
966
  private readonly entityRefSelection;
921
967
  private readonly commonModulesRegistry;
922
968
  private readonly migrations;
969
+ /** Scopes the field-slot lookup a jump does, so the library never touches global `document`. */
970
+ private readonly host;
971
+ /** Ties `afterNextRender` to this component, so destroying it cancels a pending jump. */
972
+ private readonly injector;
923
973
  protected readonly Object: ObjectConstructor;
924
974
  readonly activeTab: i0.WritableSignal<string>;
925
975
  readonly activeSubTab: i0.WritableSignal<string>;
@@ -1017,8 +1067,31 @@ declare class DynamicFormComponent implements OnInit, OnChanges, OnDestroy {
1017
1067
  * uniqueness check came back.
1018
1068
  */
1019
1069
  get isValidating(): boolean;
1020
- /** Single source of truth for both the submit guard and the button's disabled state. */
1070
+ /**
1071
+ * Whether a submit would be refused. The guard `submit()` checks — not the button's state.
1072
+ *
1073
+ * See `submitDisabled` for why those are no longer the same question.
1074
+ */
1021
1075
  get submitBlocked(): boolean;
1076
+ /**
1077
+ * Whether the Save button is unavailable.
1078
+ *
1079
+ * This used to be `submitBlocked`, so an invalid form greyed Save out — and a greyed button
1080
+ * is the worst possible answer to "why can't I save?". It cannot be clicked, so there is no
1081
+ * moment at which the form gets to say which field is at fault or which tab it is on; the
1082
+ * user is left comparing a disabled button against a form that looks, to them, filled in.
1083
+ * On a tabbed form the offending field is usually not even on screen.
1084
+ *
1085
+ * Save now stays available while the form is merely invalid. Clicking it still saves
1086
+ * nothing — `submit()` checks `submitBlocked` and refuses — but the refusal is where the
1087
+ * error summary, the tab badges and the jump to the first bad field come from, so pressing
1088
+ * Save produces an explanation instead of silence.
1089
+ *
1090
+ * What is still disabled is what a *retry cannot fix*: a save already in flight, and an
1091
+ * async validator whose answer has not come back. Those are moments where the right answer
1092
+ * is genuinely "wait", and a button that accepts a click would be lying.
1093
+ */
1094
+ get submitDisabled(): boolean;
1022
1095
  ngOnInit(): void;
1023
1096
  ngOnChanges(changes: SimpleChanges): void;
1024
1097
  /**
@@ -1046,6 +1119,47 @@ declare class DynamicFormComponent implements OnInit, OnChanges, OnDestroy {
1046
1119
  focusPanel?: boolean;
1047
1120
  }): void;
1048
1121
  getFieldSpan(field: NestedFieldConfig): string;
1122
+ /**
1123
+ * Set by a submit that validation refused, cleared by one that went through.
1124
+ *
1125
+ * Gates the error summary rather than `form.invalid` doing it: a form opened on an empty
1126
+ * required field is invalid from the first render, and leading with a block of red before
1127
+ * the user has typed anything is an accusation, not help. The summary is the answer to
1128
+ * "why did Save do nothing", so it appears when Save does nothing.
1129
+ */
1130
+ readonly submitAttempted: i0.WritableSignal<boolean>;
1131
+ /**
1132
+ * Every rendered field whose control is currently invalid, with the tab it lives on.
1133
+ *
1134
+ * Read by the tab badges, the error summary and the jump, so all three agree on what
1135
+ * counts. Hidden fields are excluded because `syncHiddenFieldState` disables them and a
1136
+ * disabled control is not part of validity — pointing the user at one would send them to a
1137
+ * field that is not on screen, or worse, switch tabs to show them nothing.
1138
+ *
1139
+ * Cached per change-detection pass. The walk calls `getControl` once per field and that
1140
+ * falls back to a recursive search of the whole form; the template reads this three times
1141
+ * for the summary and once per tab for the badges, so recomputing it each time turns one
1142
+ * traversal into a dozen on every keystroke. `form.statusChanges` is the only thing that
1143
+ * can alter the answer, and it already runs `markForCheck` — dropping the cache there keeps
1144
+ * it honest without a second subscription.
1145
+ */
1146
+ invalidFields(): InvalidField[];
1147
+ private invalidFieldsCache?;
1148
+ /** How many invalid fields sit on a tab — its own and its sub-tabs'. */
1149
+ tabErrorCount(tab: NestedTabConfig): number;
1150
+ /** The same count for a sub-tab, which is addressed by its own id rather than its parent's. */
1151
+ subTabErrorCount(subTab: NestedTabConfig): number;
1152
+ /**
1153
+ * Switch to the tab holding `fieldId`, scroll it into view, and move focus onto it.
1154
+ *
1155
+ * `afterNextRender` rather than a timer: the panel the field lives in is rendered by the
1156
+ * change detection this call is part of, so the element does not exist yet — and a timeout
1157
+ * is both a guess at how long that takes and something that keeps running after the
1158
+ * component is destroyed. The query is scoped to this component's own element, so the
1159
+ * library never reaches for the global `document`.
1160
+ */
1161
+ jumpToField(fieldId: string): void;
1162
+ private locateField;
1049
1163
  /** A critical field stays read-only until the user deliberately unlocks it. */
1050
1164
  isFieldLocked(field: NestedFieldConfig): boolean;
1051
1165
  /**
@@ -1054,6 +1168,13 @@ declare class DynamicFormComponent implements OnInit, OnChanges, OnDestroy {
1054
1168
  */
1055
1169
  isFieldReadonly(field: NestedFieldConfig): boolean;
1056
1170
  toggleFieldLock(field: NestedFieldConfig): void;
1171
+ /**
1172
+ * A field's label in the form's language, falling back to its id.
1173
+ *
1174
+ * The fallback matters wherever the label stands alone rather than beside its control: an
1175
+ * error-summary chip or a critical-change banner naming a field with no label for this
1176
+ * language would otherwise be blank, and a blank chip is worse than a raw id.
1177
+ */
1057
1178
  resolveFieldLabel(field: NestedFieldConfig): string;
1058
1179
  /**
1059
1180
  * The changed critical fields as one comma-separated string.
@@ -1213,7 +1334,7 @@ declare class DynamicFormComponent implements OnInit, OnChanges, OnDestroy {
1213
1334
  submit(): Promise<void>;
1214
1335
  reset(): void;
1215
1336
  static ɵfac: i0.ɵɵFactoryDeclaration<DynamicFormComponent, never>;
1216
- static ɵcmp: i0.ɵɵComponentDeclaration<DynamicFormComponent, "ngx-dynamic-form", never, { "config": { "alias": "config"; "required": false; }; "rules": { "alias": "rules"; "required": false; }; "initialData": { "alias": "initialData"; "required": false; }; "originalData": { "alias": "originalData"; "required": false; }; "userRoles": { "alias": "userRoles"; "required": false; }; "language": { "alias": "language"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "readOnlyFields": { "alias": "readOnlyFields"; "required": false; }; "showInfoBanners": { "alias": "showInfoBanners"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "error": { "alias": "error"; "required": false; }; "changeDebounceMs": { "alias": "changeDebounceMs"; "required": false; }; "preview": { "alias": "preview"; "required": false; }; }, { "formSubmit": "formSubmit"; "formChange": "formChange"; "formReset": "formReset"; "activeTabChange": "activeTabChange"; "saveRejected": "saveRejected"; }, never, never, true, never>;
1337
+ static ɵcmp: i0.ɵɵComponentDeclaration<DynamicFormComponent, "ngx-dynamic-form", never, { "config": { "alias": "config"; "required": false; }; "rules": { "alias": "rules"; "required": false; }; "initialData": { "alias": "initialData"; "required": false; }; "originalData": { "alias": "originalData"; "required": false; }; "userRoles": { "alias": "userRoles"; "required": false; }; "language": { "alias": "language"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "readOnlyFields": { "alias": "readOnlyFields"; "required": false; }; "showInfoBanners": { "alias": "showInfoBanners"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "error": { "alias": "error"; "required": false; }; "changeDebounceMs": { "alias": "changeDebounceMs"; "required": false; }; "preview": { "alias": "preview"; "required": false; }; "layout": { "alias": "layout"; "required": false; }; }, { "formSubmit": "formSubmit"; "formChange": "formChange"; "formReset": "formReset"; "activeTabChange": "activeTabChange"; "saveRejected": "saveRejected"; }, never, never, true, never>;
1217
1338
  }
1218
1339
 
1219
1340
  /**
@@ -1236,6 +1357,8 @@ declare class DynamicRecordFormComponent implements OnChanges {
1236
1357
  isReadOnly: boolean;
1237
1358
  /** Specific field ids forced read-only while the rest of the record stays editable. */
1238
1359
  readOnlyFields: string[];
1360
+ /** Forwarded verbatim to the hosted form — see `DynamicFormComponent.layout`. */
1361
+ layout: 'stack' | 'auto';
1239
1362
  /**
1240
1363
  * Open the record read-only, with a per-tab "Edit section" flow — one tab is edited and
1241
1364
  * validated at a time. This is the framework's `EntityRecordComponent` model and the
@@ -1268,8 +1391,6 @@ declare class DynamicRecordFormComponent implements OnChanges {
1268
1391
  private readonly rulesEvaluation;
1269
1392
  private readonly rbacService;
1270
1393
  private readonly hookRegistry;
1271
- private readonly host;
1272
- private readonly injector;
1273
1394
  readonly currentData: i0.WritableSignal<Record<string, any>>;
1274
1395
  readonly originalBaseline: i0.WritableSignal<Record<string, any>>;
1275
1396
  /**
@@ -1387,6 +1508,30 @@ declare class DynamicRecordFormComponent implements OnChanges {
1387
1508
  */
1388
1509
  ngOnChanges(changes: SimpleChanges): void;
1389
1510
  get recordTitle(): string;
1511
+ /**
1512
+ * What this record is called, as opposed to what kind of thing it is.
1513
+ *
1514
+ * The header used to show the entity's name twice — "clients", with "Entity: clients"
1515
+ * underneath — so the one question a record header exists to answer, *which* record am I
1516
+ * looking at, was the one thing it did not say. The entity keeps the subtitle; this takes
1517
+ * the heading.
1518
+ *
1519
+ * The order is deliberate. `showOnMinimize` is the author saying "this is what identifies a
1520
+ * record" — it is what the summary panel and the collapsed view already show — so it is
1521
+ * asked first. A text or email field is the fallback because those are what a name is
1522
+ * stored in; a number or a date is a property of the record, not its identity, and would
1523
+ * give a header reading "42". When neither exists there is nothing to name it with and the
1524
+ * entity label stands in, which is the behaviour this replaced.
1525
+ *
1526
+ * A masked field is never a candidate. Masking is presentational (see SECURITY.md), but
1527
+ * that is exactly why: the whole point is that this role does not get to read the value, and
1528
+ * promoting it into the page heading would print in full what every field renders as
1529
+ * `XXXXXXXXX`. A record whose only text field is masked keeps the entity label.
1530
+ *
1531
+ * One pass rather than two filtered ones: this is a getter the header reads on every change
1532
+ * detection, and the preferred candidate is usually the first field it meets.
1533
+ */
1534
+ get recordHeading(): string;
1390
1535
  get avatarLetter(): string;
1391
1536
  /** Every field in the config, at any depth. */
1392
1537
  private allFields;
@@ -1433,21 +1578,18 @@ declare class DynamicRecordFormComponent implements OnChanges {
1433
1578
  * field. The walk used to check top-level `fields` only, so every field in a sub-tab was
1434
1579
  * simply not found and the jump did nothing at all.
1435
1580
  */
1436
- private locateField;
1437
1581
  /**
1438
1582
  * Switches to the tab holding `fieldId`, then scrolls it into view and moves focus to it.
1439
1583
  *
1440
- * The wait for the new tab to render used to be a 50 ms `setTimeout`, which was wrong three
1441
- * ways: `document` is undefined on a server render, 50 ms is a guess that a large tab can
1442
- * outrun, and nothing cancelled the timer if the component went away first.
1443
- * `afterNextRender` fixes all three — it never runs on the server, it runs when the panel
1444
- * has actually rendered rather than when a guess expires, and it is tied to the injector so
1445
- * destroying the component cancels it. The query is scoped to this component's own element,
1446
- * so the library no longer reaches for the global `document` at all.
1584
+ * Delegated rather than implemented twice. The hosted form grew the same jump when a
1585
+ * refused save had to be able to take the user to the first invalid field, and the form is
1586
+ * where it belongs: it owns the tab state, the panel that renders the field, and the
1587
+ * element the jump is looking for. This is kept as the record editor's public entry point
1588
+ * because the summary panel's quick-jump calls it and a host may too.
1447
1589
  */
1448
1590
  jumpToField(fieldId: string): void;
1449
1591
  static ɵfac: i0.ɵɵFactoryDeclaration<DynamicRecordFormComponent, never>;
1450
- static ɵcmp: i0.ɵɵComponentDeclaration<DynamicRecordFormComponent, "ngx-dynamic-record-form", never, { "config": { "alias": "config"; "required": false; }; "rules": { "alias": "rules"; "required": false; }; "initialData": { "alias": "initialData"; "required": false; }; "userRoles": { "alias": "userRoles"; "required": false; }; "language": { "alias": "language"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "error": { "alias": "error"; "required": false; }; "isReadOnly": { "alias": "isReadOnly"; "required": false; }; "readOnlyFields": { "alias": "readOnlyFields"; "required": false; }; "viewMode": { "alias": "viewMode"; "required": false; }; }, { "formSubmit": "formSubmit"; "formChange": "formChange"; "formReset": "formReset"; "sectionSave": "sectionSave"; "saveRejected": "saveRejected"; }, never, never, true, never>;
1592
+ static ɵcmp: i0.ɵɵComponentDeclaration<DynamicRecordFormComponent, "ngx-dynamic-record-form", never, { "config": { "alias": "config"; "required": false; }; "rules": { "alias": "rules"; "required": false; }; "initialData": { "alias": "initialData"; "required": false; }; "userRoles": { "alias": "userRoles"; "required": false; }; "language": { "alias": "language"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "error": { "alias": "error"; "required": false; }; "isReadOnly": { "alias": "isReadOnly"; "required": false; }; "readOnlyFields": { "alias": "readOnlyFields"; "required": false; }; "layout": { "alias": "layout"; "required": false; }; "viewMode": { "alias": "viewMode"; "required": false; }; }, { "formSubmit": "formSubmit"; "formChange": "formChange"; "formReset": "formReset"; "sectionSave": "sectionSave"; "saveRejected": "saveRejected"; }, never, never, true, never>;
1451
1593
  }
1452
1594
 
1453
1595
  /**
@@ -1591,6 +1733,25 @@ declare function nextFieldInstanceId(): string;
1591
1733
  declare function fieldDomId(field: {
1592
1734
  id?: string;
1593
1735
  } | undefined, instance: string, suffix?: string): string;
1736
+ /**
1737
+ * The `aria-describedby` a control needs, given what is rendered beside it right now.
1738
+ *
1739
+ * A field can show two things under its control — the author's help text and, once touched, a
1740
+ * validation message — and a screen reader announces only what this attribute names. Three
1741
+ * field components named the error; the other sixteen named nothing at all, so their error
1742
+ * messages were on screen and silent. Help text would have inherited the same gap.
1743
+ *
1744
+ * Order matters: the hint describes the field and the error describes the attempt, so the hint
1745
+ * is read first. `null` rather than an empty string when there is nothing to describe — an
1746
+ * empty `aria-describedby` is a dangling reference, not an absent one.
1747
+ *
1748
+ * Shared rather than written into each of the nineteen field components, because the rule is
1749
+ * the same everywhere and getting it wrong is invisible until somebody uses a screen reader.
1750
+ */
1751
+ declare function fieldDescribedBy(domId: (suffix?: string) => string, parts: {
1752
+ hint?: boolean;
1753
+ error?: boolean;
1754
+ }): string | null;
1594
1755
 
1595
1756
  declare class TextFieldComponent implements OnDestroy {
1596
1757
  /**
@@ -1615,6 +1776,10 @@ declare class TextFieldComponent implements OnDestroy {
1615
1776
  ngOnDestroy(): void;
1616
1777
  get label(): string;
1617
1778
  get placeholder(): string;
1779
+ /** Author help text, shown under the control and named by `aria-describedby`. */
1780
+ get hint(): string;
1781
+ /** The ids of whatever is describing this control right now. */
1782
+ protected describedBy(): string | null;
1618
1783
  get errorMessage(): string;
1619
1784
  static ɵfac: i0.ɵɵFactoryDeclaration<TextFieldComponent, never>;
1620
1785
  static ɵcmp: i0.ɵɵComponentDeclaration<TextFieldComponent, "ngx-text-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>;
@@ -1643,6 +1808,10 @@ declare class TextareaFieldComponent {
1643
1808
  * "This field has an error", which made a documented, configurable feature work on three
1644
1809
  * of fifteen field types.
1645
1810
  */
1811
+ /** Author help text, shown under the control and named by `aria-describedby`. */
1812
+ get hint(): string;
1813
+ /** The ids of whatever is describing this control right now. */
1814
+ protected describedBy(): string | null;
1646
1815
  get errorMessage(): string;
1647
1816
  static ɵfac: i0.ɵɵFactoryDeclaration<TextareaFieldComponent, never>;
1648
1817
  static ɵcmp: i0.ɵɵComponentDeclaration<TextareaFieldComponent, "ngx-textarea-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>;
@@ -1715,6 +1884,10 @@ declare class MarkdownFieldComponent implements OnChanges {
1715
1884
  * "This field has an error", which made a documented, configurable feature work on three
1716
1885
  * of fifteen field types.
1717
1886
  */
1887
+ /** Author help text, shown under the control and named by `aria-describedby`. */
1888
+ get hint(): string;
1889
+ /** The ids of whatever is describing this control right now. */
1890
+ protected describedBy(): string | null;
1718
1891
  get errorMessage(): string;
1719
1892
  static ɵfac: i0.ɵɵFactoryDeclaration<MarkdownFieldComponent, never>;
1720
1893
  static ɵcmp: i0.ɵɵComponentDeclaration<MarkdownFieldComponent, "ngx-markdown-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>;
@@ -1737,6 +1910,10 @@ declare class NumberFieldComponent {
1737
1910
  masked: boolean;
1738
1911
  get label(): string;
1739
1912
  get placeholder(): string;
1913
+ /** Author help text, shown under the control and named by `aria-describedby`. */
1914
+ get hint(): string;
1915
+ /** The ids of whatever is describing this control right now. */
1916
+ protected describedBy(): string | null;
1740
1917
  get errorMessage(): string;
1741
1918
  static ɵfac: i0.ɵɵFactoryDeclaration<NumberFieldComponent, never>;
1742
1919
  static ɵcmp: i0.ɵɵComponentDeclaration<NumberFieldComponent, "ngx-number-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>;
@@ -1768,6 +1945,10 @@ declare class CurrencyFieldComponent {
1768
1945
  * "This field has an error", which made a documented, configurable feature work on three
1769
1946
  * of fifteen field types.
1770
1947
  */
1948
+ /** Author help text, shown under the control and named by `aria-describedby`. */
1949
+ get hint(): string;
1950
+ /** The ids of whatever is describing this control right now. */
1951
+ protected describedBy(): string | null;
1771
1952
  get errorMessage(): string;
1772
1953
  static ɵfac: i0.ɵɵFactoryDeclaration<CurrencyFieldComponent, never>;
1773
1954
  static ɵcmp: i0.ɵɵComponentDeclaration<CurrencyFieldComponent, "ngx-currency-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>;
@@ -1797,6 +1978,10 @@ declare class EmailFieldComponent {
1797
1978
  * "This field has an error", which made a documented, configurable feature work on three
1798
1979
  * of fifteen field types.
1799
1980
  */
1981
+ /** Author help text, shown under the control and named by `aria-describedby`. */
1982
+ get hint(): string;
1983
+ /** The ids of whatever is describing this control right now. */
1984
+ protected describedBy(): string | null;
1800
1985
  get errorMessage(): string;
1801
1986
  static ɵfac: i0.ɵɵFactoryDeclaration<EmailFieldComponent, never>;
1802
1987
  static ɵcmp: i0.ɵɵComponentDeclaration<EmailFieldComponent, "ngx-email-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>;
@@ -1830,6 +2015,10 @@ declare class PasswordFieldComponent {
1830
2015
  * "This field has an error", which made a documented, configurable feature work on three
1831
2016
  * of fifteen field types.
1832
2017
  */
2018
+ /** Author help text, shown under the control and named by `aria-describedby`. */
2019
+ get hint(): string;
2020
+ /** The ids of whatever is describing this control right now. */
2021
+ protected describedBy(): string | null;
1833
2022
  get errorMessage(): string;
1834
2023
  static ɵfac: i0.ɵɵFactoryDeclaration<PasswordFieldComponent, never>;
1835
2024
  static ɵcmp: i0.ɵɵComponentDeclaration<PasswordFieldComponent, "ngx-password-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>;
@@ -1859,6 +2048,10 @@ declare class CheckboxFieldComponent {
1859
2048
  * It rendered no error element at all, so a required checkbox left unticked told the user
1860
2049
  * nothing — and `validationMessages` could not reach a field that never displayed one.
1861
2050
  */
2051
+ /** Author help text, shown under the control and named by `aria-describedby`. */
2052
+ get hint(): string;
2053
+ /** The ids of whatever is describing this control right now. */
2054
+ protected describedBy(): string | null;
1862
2055
  get errorMessage(): string;
1863
2056
  static ɵfac: i0.ɵɵFactoryDeclaration<CheckboxFieldComponent, never>;
1864
2057
  static ɵcmp: i0.ɵɵComponentDeclaration<CheckboxFieldComponent, "ngx-checkbox-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>;
@@ -1870,6 +2063,12 @@ declare class CheckboxFieldComponent {
1870
2063
  * toggle switch with Yes/No labels for clearer binary state communication.
1871
2064
  */
1872
2065
  declare class BooleanFieldComponent {
2066
+ /**
2067
+ * Unique to this component instance: an `array` renders the same field once per row, and a
2068
+ * DOM id may not repeat. See `field-dom-id.ts`.
2069
+ */
2070
+ private readonly instanceId;
2071
+ protected domId(suffix?: string): string;
1873
2072
  /** Library chrome, overridable via UI_TEXT. */
1874
2073
  protected readonly ui: UiTextService;
1875
2074
  /** Overridable via MASKED_PLACEHOLDER; the default is the historic literal. */
@@ -1887,6 +2086,10 @@ declare class BooleanFieldComponent {
1887
2086
  * It rendered no error element at all, so a required checkbox left unticked told the user
1888
2087
  * nothing — and `validationMessages` could not reach a field that never displayed one.
1889
2088
  */
2089
+ /** Author help text, shown under the control and named by `aria-describedby`. */
2090
+ get hint(): string;
2091
+ /** The ids of whatever is describing this control right now. */
2092
+ protected describedBy(): string | null;
1890
2093
  get errorMessage(): string;
1891
2094
  static ɵfac: i0.ɵɵFactoryDeclaration<BooleanFieldComponent, never>;
1892
2095
  static ɵcmp: i0.ɵɵComponentDeclaration<BooleanFieldComponent, "ngx-boolean-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>;
@@ -1927,6 +2130,10 @@ declare class DateFieldComponent {
1927
2130
  * "This field has an error", which made a documented, configurable feature work on three
1928
2131
  * of fifteen field types.
1929
2132
  */
2133
+ /** Author help text, shown under the control and named by `aria-describedby`. */
2134
+ get hint(): string;
2135
+ /** The ids of whatever is describing this control right now. */
2136
+ protected describedBy(): string | null;
1930
2137
  get errorMessage(): string;
1931
2138
  static ɵfac: i0.ɵɵFactoryDeclaration<DateFieldComponent, never>;
1932
2139
  static ɵcmp: i0.ɵɵComponentDeclaration<DateFieldComponent, "ngx-date-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>;
@@ -1979,6 +2186,10 @@ declare class DateTimeFieldComponent {
1979
2186
  * "This field has an error", which made a documented, configurable feature work on three
1980
2187
  * of fifteen field types.
1981
2188
  */
2189
+ /** Author help text, shown under the control and named by `aria-describedby`. */
2190
+ get hint(): string;
2191
+ /** The ids of whatever is describing this control right now. */
2192
+ protected describedBy(): string | null;
1982
2193
  get errorMessage(): string;
1983
2194
  static ɵfac: i0.ɵɵFactoryDeclaration<DateTimeFieldComponent, never>;
1984
2195
  static ɵcmp: i0.ɵɵComponentDeclaration<DateTimeFieldComponent, "ngx-date-time-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>;
@@ -2020,6 +2231,10 @@ declare class TimeFieldComponent {
2020
2231
  * "This field has an error", which made a documented, configurable feature work on three
2021
2232
  * of fifteen field types.
2022
2233
  */
2234
+ /** Author help text, shown under the control and named by `aria-describedby`. */
2235
+ get hint(): string;
2236
+ /** The ids of whatever is describing this control right now. */
2237
+ protected describedBy(): string | null;
2023
2238
  get errorMessage(): string;
2024
2239
  static ɵfac: i0.ɵɵFactoryDeclaration<TimeFieldComponent, never>;
2025
2240
  static ɵcmp: i0.ɵɵComponentDeclaration<TimeFieldComponent, "ngx-time-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>;
@@ -2064,6 +2279,10 @@ declare class MonthYearFieldComponent {
2064
2279
  * "This field has an error", which made a documented, configurable feature work on three
2065
2280
  * of fifteen field types.
2066
2281
  */
2282
+ /** Author help text, shown under the control and named by `aria-describedby`. */
2283
+ get hint(): string;
2284
+ /** The ids of whatever is describing this control right now. */
2285
+ protected describedBy(): string | null;
2067
2286
  get errorMessage(): string;
2068
2287
  static ɵfac: i0.ɵɵFactoryDeclaration<MonthYearFieldComponent, never>;
2069
2288
  static ɵcmp: i0.ɵɵComponentDeclaration<MonthYearFieldComponent, "ngx-month-year-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>;
@@ -2106,6 +2325,10 @@ declare class DropdownFieldComponent {
2106
2325
  * never wrong, only unlocalised.
2107
2326
  */
2108
2327
  getLabel(value: unknown): string;
2328
+ /** Author help text, shown under the control and named by `aria-describedby`. */
2329
+ get hint(): string;
2330
+ /** The ids of whatever is describing this control right now. */
2331
+ protected describedBy(): string | null;
2109
2332
  get errorMessage(): string;
2110
2333
  static ɵfac: i0.ɵɵFactoryDeclaration<DropdownFieldComponent, never>;
2111
2334
  static ɵcmp: i0.ɵɵComponentDeclaration<DropdownFieldComponent, "ngx-dropdown-field", never, { "field": { "alias": "field"; "required": false; }; "language": { "alias": "language"; "required": false; }; "control": { "alias": "control"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "masked": { "alias": "masked"; "required": false; }; }, {}, never, never, true, never>;
@@ -2161,6 +2384,10 @@ declare class RadioFieldComponent {
2161
2384
  * "This field has an error", which made a documented, configurable feature work on three
2162
2385
  * of fifteen field types.
2163
2386
  */
2387
+ /** Author help text, shown under the control and named by `aria-describedby`. */
2388
+ get hint(): string;
2389
+ /** The ids of whatever is describing this control right now. */
2390
+ protected describedBy(): string | null;
2164
2391
  get errorMessage(): string;
2165
2392
  static ɵfac: i0.ɵɵFactoryDeclaration<RadioFieldComponent, never>;
2166
2393
  static ɵcmp: i0.ɵɵComponentDeclaration<RadioFieldComponent, "ngx-radio-field", never, { "field": { "alias": "field"; "required": false; }; "language": { "alias": "language"; "required": false; }; "control": { "alias": "control"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "masked": { "alias": "masked"; "required": false; }; }, {}, never, never, true, never>;
@@ -2202,6 +2429,10 @@ declare class MultiSelectFieldComponent {
2202
2429
  * "This field has an error", which made a documented, configurable feature work on three
2203
2430
  * of fifteen field types.
2204
2431
  */
2432
+ /** Author help text, shown under the control and named by `aria-describedby`. */
2433
+ get hint(): string;
2434
+ /** The ids of whatever is describing this control right now. */
2435
+ protected describedBy(): string | null;
2205
2436
  get errorMessage(): string;
2206
2437
  static ɵfac: i0.ɵɵFactoryDeclaration<MultiSelectFieldComponent, never>;
2207
2438
  static ɵcmp: i0.ɵɵComponentDeclaration<MultiSelectFieldComponent, "ngx-multi-select-field", never, { "field": { "alias": "field"; "required": false; }; "language": { "alias": "language"; "required": false; }; "control": { "alias": "control"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "masked": { "alias": "masked"; "required": false; }; }, {}, never, never, true, never>;
@@ -2266,6 +2497,10 @@ declare class EntityRefFieldComponent implements OnInit {
2266
2497
  * "This field has an error", which made a documented, configurable feature work on three
2267
2498
  * of fifteen field types.
2268
2499
  */
2500
+ /** Author help text, shown under the control and named by `aria-describedby`. */
2501
+ get hint(): string;
2502
+ /** The ids of whatever is describing this control right now. */
2503
+ protected describedBy(): string | null;
2269
2504
  get errorMessage(): string;
2270
2505
  static ɵfac: i0.ɵɵFactoryDeclaration<EntityRefFieldComponent, never>;
2271
2506
  static ɵcmp: i0.ɵɵComponentDeclaration<EntityRefFieldComponent, "ngx-entity-ref-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>;
@@ -2282,6 +2517,8 @@ declare class GroupFieldComponent {
2282
2517
  readonly: boolean;
2283
2518
  masked: boolean;
2284
2519
  userRoles: string[];
2520
+ /** Author help text for the section as a whole. */
2521
+ get hint(): string;
2285
2522
  get label(): string;
2286
2523
  getChildControl(childId: string): AbstractControl;
2287
2524
  static ɵfac: i0.ɵɵFactoryDeclaration<GroupFieldComponent, never>;
@@ -2309,6 +2546,8 @@ declare class ArrayFieldComponent {
2309
2546
  userRoles: string[];
2310
2547
  private readonly fb;
2311
2548
  private readonly validatorRegistry;
2549
+ /** Author help text for the section as a whole. */
2550
+ get hint(): string;
2312
2551
  get label(): string;
2313
2552
  get formArray(): FormArray;
2314
2553
  getItemChildControl(itemGroup: AbstractControl, childId: string): AbstractControl;
@@ -2353,6 +2592,10 @@ declare class ImageFieldComponent implements OnDestroy {
2353
2592
  remove(): void;
2354
2593
  ngOnDestroy(): void;
2355
2594
  /** Validation, as distinct from the upload failures this field already reported. */
2595
+ /** Author help text, shown under the control and named by `aria-describedby`. */
2596
+ get hint(): string;
2597
+ /** The ids of whatever is describing this control right now. */
2598
+ protected describedBy(): string | null;
2356
2599
  get errorMessage(): string;
2357
2600
  static ɵfac: i0.ɵɵFactoryDeclaration<ImageFieldComponent, never>;
2358
2601
  static ɵcmp: i0.ɵɵComponentDeclaration<ImageFieldComponent, "ngx-image-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>;
@@ -2389,10 +2632,14 @@ declare class FileFieldComponent {
2389
2632
  onFileSelect(file: File | undefined): Promise<void>;
2390
2633
  remove(): void;
2391
2634
  /** Validation, as distinct from the upload failures this field already reported. */
2635
+ /** Author help text, shown under the control and named by `aria-describedby`. */
2636
+ get hint(): string;
2637
+ /** The ids of whatever is describing this control right now. */
2638
+ protected describedBy(): string | null;
2392
2639
  get errorMessage(): string;
2393
2640
  static ɵfac: i0.ɵɵFactoryDeclaration<FileFieldComponent, never>;
2394
2641
  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>;
2395
2642
  }
2396
2643
 
2397
- 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, EntityRefFieldComponent, EntityRefRegistryService, EntityRefSelectionService, EntityReferenceService, FIELD_TYPE_REGISTRY, FIELD_TYPE_SETS, FieldRegistryService, FileFieldComponent, GroupFieldComponent, HOOK_REGISTRY, HookRegistryService, ImageFieldComponent, InMemoryEntityRefCacheStore, LOOKUP_REGISTRY, LookupRegistryService, MARKDOWN_RENDERER, MASKED_PLACEHOLDER, MASKED_ROLES, MarkdownFieldComponent, MonthYearFieldComponent, MultiSelectFieldComponent, NumberFieldComponent, PasswordFieldComponent, RECORD_MIGRATIONS, RadioFieldComponent, RbacService, RulesEvaluationService, SYSTEM_DEFAULT_CAN_EDIT, TextFieldComponent, TextareaFieldComponent, TimeFieldComponent, UI_TEXT, UPLOAD_HANDLER, UiTextService, VALIDATION_MESSAGES, VALIDATOR_REGISTRY, ValidationMessagesService, ValidatorRegistryService, builtInFieldTypes, fieldDomId, nextFieldInstanceId, provideBuiltInFieldTypes, provideFieldTypes, provideNgxDynamicEntity, refreshChoiceOptions, resolveUiText };
2398
- export type { ChoiceOptionHost, ConfigSourceHandler, DynamicFieldComponentContract, EntityRefCacheStore, EntityRefSelection, HookFn, NgxDynamicEntityConfig, UiTextKey, UiTextOverrides, UiTextOverridesFor, UiTextParams, UiTextResolver, UiTextResolverFor, UiTextValue, ValidationMessage };
2644
+ 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, EntityRefFieldComponent, EntityRefRegistryService, EntityRefSelectionService, EntityReferenceService, FIELD_TYPE_REGISTRY, FIELD_TYPE_SETS, FieldRegistryService, FileFieldComponent, GroupFieldComponent, HOOK_REGISTRY, HookRegistryService, ImageFieldComponent, InMemoryEntityRefCacheStore, LOOKUP_REGISTRY, LookupRegistryService, MARKDOWN_RENDERER, MASKED_PLACEHOLDER, MASKED_ROLES, MarkdownFieldComponent, MonthYearFieldComponent, MultiSelectFieldComponent, NumberFieldComponent, PasswordFieldComponent, RECORD_MIGRATIONS, RadioFieldComponent, RbacService, RulesEvaluationService, SYSTEM_DEFAULT_CAN_EDIT, TextFieldComponent, TextareaFieldComponent, TimeFieldComponent, UI_TEXT, UPLOAD_HANDLER, UiTextService, VALIDATION_MESSAGES, VALIDATOR_REGISTRY, ValidationMessagesService, ValidatorRegistryService, builtInFieldTypes, fieldDescribedBy, fieldDomId, nextFieldInstanceId, provideBuiltInFieldTypes, provideFieldTypes, provideNgxDynamicEntity, refreshChoiceOptions, resolveUiText };
2645
+ export type { ChoiceOptionHost, ConfigSourceHandler, DynamicFieldComponentContract, EntityRefCacheStore, EntityRefSelection, HookFn, InvalidField, MessageOrderEntry, NgxDynamicEntityConfig, UiTextKey, UiTextOverrides, UiTextOverridesFor, UiTextParams, UiTextResolver, UiTextResolverFor, UiTextValue, ValidationMessage };