@forgeroute/ui 0.3.0 → 0.3.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.
@@ -45,7 +45,8 @@ export interface ToolbarAction {
45
45
  badge?: number;
46
46
  /** Hide this action entirely */
47
47
  hidden?: boolean;
48
- /** Only shown when the table's `permission` is 'full' (e.g. "Add …", bulk mutations). */
48
+ /** Documentation of intent: marks a mutating action ("Add …", bulk mutations). It does not change behavior - the table hides
49
+ * EVERY page-defined toolbar action for any `permission` other than 'full', with or without this flag. */
49
50
  requiresFull?: boolean;
50
51
  /**
51
52
  * Keep this action when the table is empty and unfiltered. By default only `variant: 'primary'` buttons survive that
@@ -87,9 +88,13 @@ export interface RowAction {
87
88
  opens?: 'modal' | 'panel';
88
89
  /** Required when opens === 'modal'. Drives the confirm dialog shown by the table. */
89
90
  modal?: ConfirmConfig;
90
- /** Only shown when the table's `permission` is 'full' (edit, delete, any mutation).
91
- * The built-in `type: 'delete'` action is always treated as requiring full permission. */
91
+ /** Documentation of intent: marks a mutating action (edit, delete, ...). It does not change behavior - for any `permission`
92
+ * other than 'full' the table offers only View and actions marked `allowReadOnly`, with or without this flag.
93
+ * The built-in `type: 'delete'` action is never offered to read-only users. */
92
94
  requiresFull?: boolean;
95
+ /** Keep this action for read-only users too (download, preview: reads that change nothing). Without it a read-only table offers only
96
+ * View. Never applies to the built-in delete, and the table still drops the Actions column when no row has any visible action. */
97
+ allowReadOnly?: boolean;
93
98
  }
94
99
  /** Page-level permission passed to `<ui-data-table [permission]>`. Anything other than 'full' is read-only
95
100
  * (apps use values like 'read-only' / 'hidden'). */
@@ -105,6 +110,9 @@ export interface ColumnDef {
105
110
  /** Values a bulk "Change <label>" may set. When omitted the options come from /filter-counts.
106
111
  * Use it when only some values are user-settable or when a valid value may currently have no rows. */
107
112
  bulkOptions?: string[];
113
+ /** Fixed column width (any CSS length, e.g. '140px'). Applied as width, min-width and max-width; cell text longer than
114
+ * it is cut with an ellipsis. Omit for an automatic width. Not applied to the Actions column's cell clipping. */
115
+ width?: string;
108
116
  align?: 'left' | 'right' | 'center';
109
117
  headerAlign?: 'left' | 'right' | 'center';
110
118
  /** How to render cell content. Defaults to 'text'. */
@@ -133,14 +141,24 @@ export interface ColumnDef {
133
141
  value: number;
134
142
  max: number;
135
143
  label?: string;
136
- variant?: 'blue' | 'green' | 'amber' | 'red' | 'slate';
144
+ variant?: 'blue' | 'green' | 'amber' | 'red' | 'slate' | 'lime';
137
145
  tooltip?: string;
146
+ autoColor?: boolean;
147
+ thresholds?: {
148
+ at: number;
149
+ variant: 'blue' | 'green' | 'amber' | 'red' | 'slate' | 'lime';
150
+ }[];
138
151
  } | null;
139
152
  /** Key in item holding the tags array. Defaults to col.key.
140
153
  * Expected shape: { name: string; variant?: BadgeVariant }[] */
141
154
  tagsKey?: string;
142
155
  /** Returns the image URL for the row. A falsy value (null / undefined / '') shows the placeholder icon. */
143
156
  imageFn?: (item: any) => string | null | undefined;
157
+ /** Focal point (percent, 50/50 = centered) of the cropped image, applied as CSS object-position. */
158
+ imagePositionFn?: (item: any) => {
159
+ x: number | null | undefined;
160
+ y: number | null | undefined;
161
+ } | null | undefined;
144
162
  /** Alt text for the row's image. When omitted the image is decorative (`alt=""`). */
145
163
  imageAlt?: (item: any) => string;
146
164
  /** 'circle' (default) or 'rounded' (3:2 rounded rectangle). */
@@ -231,6 +249,17 @@ export type BulkUpdateOption<T = any> = string | {
231
249
  * { field: 'delete', deletable: (row: Invoice) => row.status === 'DRAFT' }
232
250
  */
233
251
  deletable?: (row: T) => boolean;
252
+ /**
253
+ * Field changes (`{ field, canChange }`): true when the server will accept moving THIS row to `target` (a value the select offers).
254
+ * For rules the field values alone can't express, e.g. a draft can only be sent when it has a document and a recipient. Keep it
255
+ * identical to the backend rule. Rows it refuses are skipped like rows `allowedFrom` refuses ("N selected rows can't be changed to X
256
+ * and will be skipped." / `ctx.skippedBlocked` + `ctx.skippedRows` for host `confirm` copy), are never sent, and a target is offered
257
+ * only while some selected row can move to it. It runs after `allowedFrom` and only sees rows on the loaded page. Omit it and
258
+ * nothing changes.
259
+ *
260
+ * { field: 'status', allowedFrom: { SENT: ['DRAFT'] }, canChange: (row, target) => target !== 'SENT' || canSend(row) }
261
+ */
262
+ canChange?: (row: T, target: string) => boolean;
234
263
  };
235
264
  /** What a bulk confirm function receives. For bulk Delete: `targetValue`/`targetLabel` are '', `columnLabel` is 'Delete', skipped counts are 0. */
236
265
  export interface BulkConfirmContext<T = any> {
@@ -285,6 +314,8 @@ export interface BulkActionDef {
285
314
  confirm?: BulkConfirmFn | Record<string, BulkConfirmFn>;
286
315
  /** Bulk Delete only: which rows the server will delete (from `{ field: 'delete', deletable }`). */
287
316
  deletable?: (row: any) => boolean;
317
+ /** Field changes: per-row check that the server will accept the move to a target (from `{ field, canChange }`). */
318
+ canChange?: (row: any, target: string) => boolean;
288
319
  /**
289
320
  * The item field this action targets (e.g. 'status', 'type').
290
321
  * When set the table shows an inline select populated from the column's option sources.
@@ -767,7 +798,7 @@ export declare function createFieldReveal(showErrors: Signal<boolean>): {
767
798
  revealed: Signal<boolean>;
768
799
  };
769
800
  /** Splits `YYYY-MM-DD` (optionally followed by `Thh:mm[:ss]`) and rejects impossible dates (2026-02-31) and times (25:00). */
770
- export declare function parseIso(value: string, withTime: boolean): {
801
+ export declare function parseIso(value: string | null | undefined, withTime: boolean): {
771
802
  y: number;
772
803
  mo: number;
773
804
  d: number;
@@ -775,9 +806,9 @@ export declare function parseIso(value: string, withTime: boolean): {
775
806
  mi: number;
776
807
  } | null;
777
808
  /** "Oct 20, 2026" from an ISO date (never shifted by the time zone). */
778
- export declare function formatIsoDate(value: string): string;
809
+ export declare function formatIsoDate(value: string | null | undefined): string;
779
810
  /** "Oct 20, 2026, 3:30 PM" from an ISO local date-time. */
780
- export declare function formatIsoDateTime(value: string): string;
811
+ export declare function formatIsoDateTime(value: string | null | undefined): string;
781
812
  /** Sortable key `YYYYMMDDHHmm` of a parsed ISO value. */
782
813
  export declare function isoKey(p: {
783
814
  y: number;
@@ -786,6 +817,10 @@ export declare function isoKey(p: {
786
817
  h: number;
787
818
  mi: number;
788
819
  }): number;
820
+ /** Parses `HH:mm` (optionally `HH:mm:ss`) into minutes since midnight; null for anything else (25:00, 9:5, 09:30:99, text, null/undefined). */
821
+ export declare function parseTime(value: string | null | undefined): number | null;
822
+ /** "9:00 AM" / "12:30 PM" from an `HH:mm` value (returned unchanged when it cannot be parsed; '' for null/undefined/non-strings). */
823
+ export declare function formatTime(value: string | null | undefined): string;
789
824
  export interface SelectOption {
790
825
  value: string;
791
826
  label: string;
@@ -1135,6 +1170,8 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1135
1170
  private _columnBadgeLabel;
1136
1171
  protected readonly _error: import("@angular/core").WritableSignal<string | null>;
1137
1172
  protected readonly _search: import("@angular/core").WritableSignal<string>;
1173
+ /** The search text as sent to the API: lower-cased, so every search is case-insensitive whatever the backend does. The input still shows what the user typed. */
1174
+ protected readonly _searchParam: Signal<string>;
1138
1175
  protected readonly _page: import("@angular/core").WritableSignal<number>;
1139
1176
  protected readonly _sortField: import("@angular/core").WritableSignal<string | null>;
1140
1177
  protected readonly _sortDir: import("@angular/core").WritableSignal<SortDir>;
@@ -1147,6 +1184,8 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1147
1184
  protected readonly _effectiveSavedViews: Signal<SavedView[]>;
1148
1185
  /** Empty = show all defaultVisible; non-empty = show exactly these keys */
1149
1186
  protected readonly _visibleColumns: import("@angular/core").WritableSignal<string[]>;
1187
+ /** Drops the key of every `cellType: 'actions'` column — Actions is never part of a configured/saved column list. */
1188
+ protected _configurableKeys(keys: string[] | null | undefined): string[];
1150
1189
  protected readonly _ieRef: Signal<ImportExportComponent | undefined>;
1151
1190
  /** Tag overflow tooltip — fixed position to escape table's overflow:auto */
1152
1191
  protected readonly _tagTooltip: import("@angular/core").WritableSignal<{
@@ -1233,12 +1272,19 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1233
1272
  * through the column's own `nameFn` / `render` so it reads exactly like the cell. '' when there is none.
1234
1273
  */
1235
1274
  protected rowName(item: T): string;
1236
- /** "Select Acme Electric" — a row's selection checkbox name. */
1275
+ /**
1276
+ * Rows of the loaded page whose name repeats get a position suffix (" (1 of 2)", " (2 of 2)"), so a screen-reader user never hears two rows
1277
+ * announced identically ("Select Jane Cooper" twice). Names that are unique on the page — and rows with no name — are left exactly as they are.
1278
+ */
1279
+ private readonly _rowNameSuffix;
1280
+ /** A row's accessible name: its name, plus the position among rows of the same name when that name repeats on the page. */
1281
+ private rowAccessibleName;
1282
+ /** "Select Acme Electric" — a row's selection checkbox name ("Select Acme Electric (2 of 3)" when the name repeats on the page). */
1237
1283
  protected selectRowLabel(item: T): string;
1238
1284
  /**
1239
1285
  * "Row actions for Acme Electric" — a row's actions-menu trigger name. It still contains the generic "Row actions"
1240
1286
  * text, so lookups by that accessible name (substring) keep finding the button, while a screen-reader user now
1241
- * hears which row it belongs to.
1287
+ * hears which row it belongs to ("Row actions for Acme Electric (2 of 3)" when the name repeats on the page).
1242
1288
  */
1243
1289
  protected rowActionsLabel(item: T): string;
1244
1290
  protected toggleSelectAll(): void;
@@ -1355,7 +1401,8 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1355
1401
  protected onRowKeydown(e: KeyboardEvent, item: T): void;
1356
1402
  protected onInternalButtonClick(type: string): void;
1357
1403
  protected onImported(): void;
1358
- /** Row actions visible for the current permission: everything for 'full', only View (`type: 'view'`) otherwise. */
1404
+ /** Row actions visible for the current permission: everything for 'full'; otherwise only View (`type: 'view'`) and actions marked
1405
+ * `allowReadOnly` (never the built-in delete). The Actions column itself is shown only while some row has a visible action. */
1359
1406
  protected _rowActions(col: ColumnDef, item: T): RowAction[];
1360
1407
  protected onTableRowAction(type: string, col: ColumnDef, item: T): Promise<void>;
1361
1408
  private isNumericCol;
@@ -1367,6 +1414,8 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1367
1414
  protected imageUrl(col: ColumnDef, item: T): string | null;
1368
1415
  /** Always a string so the <img> keeps an `alt` attribute ('' = decorative). */
1369
1416
  protected imageAlt(col: ColumnDef, item: T): string;
1417
+ /** CSS object-position from `imagePositionFn` (percent); centered when there is none or it throws. */
1418
+ protected imagePosition(col: ColumnDef, item: T): string;
1370
1419
  protected imageClass(col: ColumnDef, small: boolean): string;
1371
1420
  protected onImageError(url: string): void;
1372
1421
  protected phoneCell(value: any): string;
@@ -1525,6 +1574,27 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1525
1574
  "rowDeleted": "rowDeleted";
1526
1575
  }, never, never, true, never>;
1527
1576
  }
1577
+ /**
1578
+ * Column-filter values travel as ONE comma-joined request parameter (`?section=Roofing,Siding`). A value that itself contains a comma
1579
+ * ("Roofing, Inc.") would be read as two. These helpers keep the wire format backward compatible and make such values unambiguous:
1580
+ *
1581
+ * - a value is sent AS IS unless joining it would be ambiguous: it contains a comma, a doubled backslash, or ends with a backslash;
1582
+ * - such a value is escaped: `\` becomes `\\` and `,` becomes `\,`;
1583
+ * - the reader splits on commas that are not escaped and unescapes `\,` and `\\`; any other backslash is an ordinary character.
1584
+ *
1585
+ * So every value that worked before (no comma, no doubled / trailing backslash) is byte-for-byte unchanged, and a backend that does not know the
1586
+ * escaping keeps working for them. Backends that parse filter values should split with the same rules (`splitFilterList` in the contractor
1587
+ * backend, `decodeFilterValues` here).
1588
+ */
1589
+ /** One value as it is written into the comma-joined parameter. */
1590
+ export declare function encodeFilterValue(value: string): string;
1591
+ /** The comma-joined parameter for a list of filter values (`['Roofing, Inc.', 'Siding']` -> `Roofing\, Inc.,Siding`). */
1592
+ export declare function encodeFilterValues(values: readonly string[]): string;
1593
+ /**
1594
+ * The values of a comma-joined parameter, the inverse of {@link encodeFilterValues}: split on unescaped commas, unescape `\,` and `\\`,
1595
+ * trim each value and drop the empty ones (the same as the plain split it replaces).
1596
+ */
1597
+ export declare function decodeFilterValues(raw: string): string[];
1528
1598
  export declare class SidePanelComponent implements OnDestroy {
1529
1599
  readonly open: import("@angular/core").InputSignal<boolean>;
1530
1600
  readonly title: import("@angular/core").InputSignal<string>;
@@ -1694,7 +1764,14 @@ export declare class ToastComponent {
1694
1764
  static ɵfac: i0.ɵɵFactoryDeclaration<ToastComponent, never>;
1695
1765
  static ɵcmp: i0.ɵɵComponentDeclaration<ToastComponent, "ui-toast", never, {}, {}, never, never, true, never>;
1696
1766
  }
1697
- export type ProgressBarVariant = 'blue' | 'green' | 'amber' | 'red' | 'slate';
1767
+ export type ProgressBarVariant = 'blue' | 'green' | 'amber' | 'red' | 'slate' | 'lime';
1768
+ /** Switch the fill to `variant` once completion reaches `at` percent (0-100). */
1769
+ export interface ProgressThreshold {
1770
+ at: number;
1771
+ variant: ProgressBarVariant;
1772
+ }
1773
+ /** Standard completion colors: red under 25%, amber 25%, blue 50%, lime 75%, green at 100%. */
1774
+ export declare const PROGRESS_STEP_THRESHOLDS: ProgressThreshold[];
1698
1775
  /**
1699
1776
  * Horizontal progress bar with an optional trailing label (e.g. "3/5").
1700
1777
  * Pass `value` and `max`; the fill width is clamped to 0–100%.
@@ -1706,12 +1783,22 @@ export declare class ProgressBarComponent {
1706
1783
  readonly max: import("@angular/core").InputSignal<number>;
1707
1784
  /** Text shown to the right of the bar, e.g. "3/5". */
1708
1785
  readonly label: import("@angular/core").InputSignal<string>;
1786
+ /** Fixed color; with `autoColor` it is the color below the first step (use `red`). */
1709
1787
  readonly variant: import("@angular/core").InputSignal<ProgressBarVariant>;
1710
- /** Native hover tooltip. */
1788
+ /**
1789
+ * Optional automatic color: the fill uses the variant of the highest threshold whose `at` is
1790
+ * <= the exact completion percent (not the rounded one), else `variant`.
1791
+ * e.g. `[{ at: 50, variant: 'amber' }, { at: 100, variant: 'green' }]`. Omit to keep `variant` fixed.
1792
+ */
1793
+ readonly thresholds: import("@angular/core").InputSignal<ProgressThreshold[] | null>;
1794
+ /** Shortcut for the standard steps (`PROGRESS_STEP_THRESHOLDS`): red <25%, amber 25%, blue 50%, lime 75%, green 100%. Explicit `thresholds` win. */
1795
+ readonly autoColor: import("@angular/core").InputSignal<boolean>;
1796
+ /** Hover / focus tooltip (library `uiTooltip`); `\n` starts a new line. */
1711
1797
  readonly tooltip: import("@angular/core").InputSignal<string>;
1712
1798
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
1713
1799
  protected readonly clampedValue: import("@angular/core").Signal<number>;
1714
1800
  protected readonly percent: import("@angular/core").Signal<number>;
1801
+ protected readonly effectiveVariant: import("@angular/core").Signal<ProgressBarVariant>;
1715
1802
  static ɵfac: i0.ɵɵFactoryDeclaration<ProgressBarComponent, never>;
1716
1803
  static ɵcmp: i0.ɵɵComponentDeclaration<ProgressBarComponent, "ui-progress-bar", never, {
1717
1804
  "value": {
@@ -1734,6 +1821,16 @@ export declare class ProgressBarComponent {
1734
1821
  "required": false;
1735
1822
  "isSignal": true;
1736
1823
  };
1824
+ "thresholds": {
1825
+ "alias": "thresholds";
1826
+ "required": false;
1827
+ "isSignal": true;
1828
+ };
1829
+ "autoColor": {
1830
+ "alias": "autoColor";
1831
+ "required": false;
1832
+ "isSignal": true;
1833
+ };
1737
1834
  "tooltip": {
1738
1835
  "alias": "tooltip";
1739
1836
  "required": false;
@@ -1775,12 +1872,141 @@ export declare class SkeletonComponent {
1775
1872
  };
1776
1873
  }, {}, never, never, true, never>;
1777
1874
  }
1778
- export declare class CheckboxComponent implements ControlValueAccessor {
1875
+ /**
1876
+ * Hover / focus tooltip for any element: `<span uiTooltip="Saved">`.
1877
+ * Empty text shows nothing. Line breaks (`\n`) are kept. Escape or leaving the element closes it.
1878
+ * The bubble is rendered on `document.body` (position: fixed) so table/panel overflow never clips it.
1879
+ */
1880
+ export declare class TooltipDirective {
1881
+ /** Tooltip text; empty or null disables the tooltip. */
1882
+ readonly uiTooltip: import("@angular/core").InputSignal<string | null | undefined>;
1883
+ /** Preferred side; flips to the other side when there is no room. */
1884
+ readonly tooltipPosition: import("@angular/core").InputSignal<"top" | "bottom">;
1885
+ private readonly host;
1886
+ private readonly doc;
1887
+ private bubble;
1888
+ private readonly id;
1889
+ constructor();
1890
+ protected show(): void;
1891
+ protected hide(): void;
1892
+ static ɵfac: i0.ɵɵFactoryDeclaration<TooltipDirective, never>;
1893
+ static ɵdir: i0.ɵɵDirectiveDeclaration<TooltipDirective, "[uiTooltip]", never, {
1894
+ "uiTooltip": {
1895
+ "alias": "uiTooltip";
1896
+ "required": false;
1897
+ "isSignal": true;
1898
+ };
1899
+ "tooltipPosition": {
1900
+ "alias": "tooltipPosition";
1901
+ "required": false;
1902
+ "isSignal": true;
1903
+ };
1904
+ }, {}, never, never, true, never>;
1905
+ }
1906
+ export type ImageRepositionShape = 'circle' | 'rounded';
1907
+ /**
1908
+ * Drag-to-center photo frame. The image fills the frame (`object-fit: cover`) and the user drags it, or uses the arrow
1909
+ * keys, to choose which part stays visible. The result is a focal point in percent (`x`, `y`, 0-100, 50/50 = centered)
1910
+ * to apply as CSS `object-position` wherever the image is shown (`ui-image-preview` / the data table image cell take it).
1911
+ *
1912
+ * <ui-image-reposition [src]="url" [(x)]="posX" [(y)]="posY" label="Photo position" />
1913
+ *
1914
+ * Only the axis that overflows the frame can move (a landscape photo moves sideways, a portrait one up and down).
1915
+ * Arrow keys nudge by 2% (Shift: 10%). The frame is a labelled group with a hint for assistive tech.
1916
+ */
1917
+ export declare class ImageRepositionComponent {
1918
+ private static nextId;
1919
+ protected readonly hintId: string;
1920
+ private readonly host;
1921
+ /** Image URL (or data URL). Without one the frame is empty and cannot be moved. */
1922
+ readonly src: import("@angular/core").InputSignal<string | null | undefined>;
1923
+ readonly alt: import("@angular/core").InputSignal<string>;
1924
+ readonly shape: import("@angular/core").InputSignal<ImageRepositionShape>;
1925
+ /** Accessible name of the frame. */
1926
+ readonly label: import("@angular/core").InputSignal<string>;
1927
+ /** Focal point, percent from the left (0-100). Two-way: `[(x)]`. */
1928
+ readonly x: import("@angular/core").ModelSignal<number>;
1929
+ /** Focal point, percent from the top (0-100). Two-way: `[(y)]`. */
1930
+ readonly y: import("@angular/core").ModelSignal<number>;
1931
+ protected readonly dragging: import("@angular/core").WritableSignal<boolean>;
1932
+ private natural;
1933
+ private start;
1934
+ protected onLoad(e: Event): void;
1935
+ /** How many px the cover-scaled image overflows the frame on each axis (0 = that axis cannot move). */
1936
+ private overflow;
1937
+ protected onPointerDown(e: PointerEvent): void;
1938
+ protected onPointerMove(e: PointerEvent): void;
1939
+ protected endDrag(e: PointerEvent): void;
1940
+ protected onKeydown(e: KeyboardEvent): void;
1941
+ static ɵfac: i0.ɵɵFactoryDeclaration<ImageRepositionComponent, never>;
1942
+ static ɵcmp: i0.ɵɵComponentDeclaration<ImageRepositionComponent, "ui-image-reposition", never, {
1943
+ "src": {
1944
+ "alias": "src";
1945
+ "required": false;
1946
+ "isSignal": true;
1947
+ };
1948
+ "alt": {
1949
+ "alias": "alt";
1950
+ "required": false;
1951
+ "isSignal": true;
1952
+ };
1953
+ "shape": {
1954
+ "alias": "shape";
1955
+ "required": false;
1956
+ "isSignal": true;
1957
+ };
1958
+ "label": {
1959
+ "alias": "label";
1960
+ "required": false;
1961
+ "isSignal": true;
1962
+ };
1963
+ "x": {
1964
+ "alias": "x";
1965
+ "required": false;
1966
+ "isSignal": true;
1967
+ };
1968
+ "y": {
1969
+ "alias": "y";
1970
+ "required": false;
1971
+ "isSignal": true;
1972
+ };
1973
+ }, {
1974
+ "x": "xChange";
1975
+ "y": "yChange";
1976
+ }, never, never, true, never>;
1977
+ }
1978
+ export declare class CheckboxComponent implements ControlValueAccessor, Validator, UiFieldValidity {
1779
1979
  readonly label: import("@angular/core").InputSignal<string>;
1780
1980
  /** Accessible name for the native checkbox when there is no visible `label` (e.g. a table row's selector). */
1781
1981
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
1782
1982
  readonly indeterminate: import("@angular/core").InputSignal<boolean>;
1783
1983
  readonly checked: import("@angular/core").ModelSignal<boolean>;
1984
+ /** The box must be ticked. */
1985
+ readonly required: import("@angular/core").InputSignal<boolean>;
1986
+ /** Replaces the built-in "<label> is required." message. */
1987
+ readonly requiredMessage: import("@angular/core").InputSignal<string>;
1988
+ readonly hint: import("@angular/core").InputSignal<string>;
1989
+ /** Host-provided error message (wins over the built-in one). */
1990
+ readonly error: import("@angular/core").InputSignal<string>;
1991
+ /** Reveal the built-in error message now (e.g. after a failed Save click), without waiting for a toggle. */
1992
+ readonly showErrors: import("@angular/core").InputSignal<boolean>;
1993
+ protected readonly _descId: string;
1994
+ private readonly _reveal;
1995
+ private readonly _issue;
1996
+ /** True while a required box is unticked or the host passed an `[error]`. */
1997
+ readonly invalid: import("@angular/core").Signal<boolean>;
1998
+ /** Message of the broken built-in rule ('' when valid), shown or not. */
1999
+ readonly errorMessage: import("@angular/core").Signal<string>;
2000
+ /** Emits whenever the field becomes invalid / valid. */
2001
+ readonly invalidChange: import("@angular/core").OutputEmitterRef<boolean>;
2002
+ protected readonly _activeError: import("@angular/core").Signal<string>;
2003
+ private _onValidatorChange;
2004
+ constructor();
2005
+ /** Re-run the form control's validation when a rule input (`required`, `requiredMessage`, `label`) changes. */
2006
+ ngOnChanges(): void;
2007
+ validate(control: AbstractControl): ValidationErrors | null;
2008
+ registerOnValidatorChange(fn: () => void): void;
2009
+ private _check;
1784
2010
  /** Public so a host template can bind `[disabled]` (a protected input fails strict template type-checking, TS2445). */
1785
2011
  readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
1786
2012
  private readonly _cvaDisabled;
@@ -1814,6 +2040,31 @@ export declare class CheckboxComponent implements ControlValueAccessor {
1814
2040
  "required": false;
1815
2041
  "isSignal": true;
1816
2042
  };
2043
+ "required": {
2044
+ "alias": "required";
2045
+ "required": false;
2046
+ "isSignal": true;
2047
+ };
2048
+ "requiredMessage": {
2049
+ "alias": "requiredMessage";
2050
+ "required": false;
2051
+ "isSignal": true;
2052
+ };
2053
+ "hint": {
2054
+ "alias": "hint";
2055
+ "required": false;
2056
+ "isSignal": true;
2057
+ };
2058
+ "error": {
2059
+ "alias": "error";
2060
+ "required": false;
2061
+ "isSignal": true;
2062
+ };
2063
+ "showErrors": {
2064
+ "alias": "showErrors";
2065
+ "required": false;
2066
+ "isSignal": true;
2067
+ };
1817
2068
  "_disabledInput": {
1818
2069
  "alias": "disabled";
1819
2070
  "required": false;
@@ -1821,6 +2072,7 @@ export declare class CheckboxComponent implements ControlValueAccessor {
1821
2072
  };
1822
2073
  }, {
1823
2074
  "checked": "checkedChange";
2075
+ "invalidChange": "invalidChange";
1824
2076
  }, never, ["*"], true, never>;
1825
2077
  }
1826
2078
  export declare class ButtonComponent {
@@ -2919,6 +3171,15 @@ declare class SendEmailComponent implements OnInit {
2919
3171
  docsRemovedNote: string;
2920
3172
  onDocumentsChange(v: DocumentSendValue): void;
2921
3173
  onDocumentsInvalid(bad: boolean): void;
3174
+ /** Server limits (400 "Subject must be 255 characters or fewer." / "Body must be 10000 characters or fewer."). */
3175
+ readonly MAX_SUBJECT = 255;
3176
+ readonly MAX_BODY = 10000;
3177
+ /** Inline error when the message, as it will be sent, is over the server limit ('' when fine). */
3178
+ get bodyLengthError(): string;
3179
+ /** Inline error when the subject, as it will be sent, is over the server limit ('' when fine). */
3180
+ get subjectLengthError(): string;
3181
+ /** The length problem shown under the form in every mode; compose mode shows the message one on the editor instead. */
3182
+ get sendLengthError(): string;
2922
3183
  get canSend(): boolean;
2923
3184
  get minScheduleTime(): string;
2924
3185
  /**
@@ -3826,6 +4087,8 @@ export declare class TextareaInputComponent implements ControlValueAccessor, Val
3826
4087
  private readonly _cvaDisabled;
3827
4088
  protected readonly disabled: import("@angular/core").Signal<boolean>;
3828
4089
  protected readonly _value: import("@angular/core").WritableSignal<string>;
4090
+ /** The hint is shown inline after the label; with no label there is nothing to hang it on, so it renders under the field. */
4091
+ protected readonly _unlabelledHint: import("@angular/core").Signal<boolean>;
3829
4092
  private readonly _reveal;
3830
4093
  private readonly _issue;
3831
4094
  /** True while the value breaks a built-in rule or the host passed an `[error]`. */
@@ -4182,18 +4445,37 @@ export declare class DatetimeInputComponent implements ControlValueAccessor, Val
4182
4445
  "invalidChange": "invalidChange";
4183
4446
  }, never, never, true, never>;
4184
4447
  }
4185
- export declare class TimeInputComponent implements ControlValueAccessor {
4448
+ export declare class TimeInputComponent implements ControlValueAccessor, Validator, UiFieldValidity {
4186
4449
  readonly label: import("@angular/core").InputSignal<string>;
4450
+ /** Accessible name when there is no visible `label` (falls back to `label`). */
4451
+ readonly ariaLabel: import("@angular/core").InputSignal<string>;
4187
4452
  readonly required: import("@angular/core").InputSignal<boolean>;
4188
4453
  readonly min: import("@angular/core").InputSignal<string>;
4189
4454
  readonly max: import("@angular/core").InputSignal<string>;
4190
4455
  readonly hint: import("@angular/core").InputSignal<string>;
4191
4456
  readonly error: import("@angular/core").InputSignal<string>;
4457
+ /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
4458
+ readonly showErrors: import("@angular/core").InputSignal<boolean>;
4192
4459
  protected readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
4193
4460
  private readonly _cvaDisabled;
4194
4461
  protected readonly disabled: import("@angular/core").Signal<boolean>;
4195
4462
  protected readonly _value: import("@angular/core").WritableSignal<string>;
4196
4463
  protected readonly _inputId: string;
4464
+ private readonly _reveal;
4465
+ private readonly _issue;
4466
+ /** True while the value breaks a built-in rule or the host passed an `[error]`. */
4467
+ readonly invalid: import("@angular/core").Signal<boolean>;
4468
+ /** Message of the first broken built-in rule ('' when valid), shown or not. */
4469
+ readonly errorMessage: import("@angular/core").Signal<string>;
4470
+ /** Emits whenever the field becomes invalid / valid. */
4471
+ readonly invalidChange: import("@angular/core").OutputEmitterRef<boolean>;
4472
+ protected readonly _activeError: import("@angular/core").Signal<string>;
4473
+ private _onValidatorChange;
4474
+ constructor();
4475
+ /** Re-run the form control's validation when a rule input (required, min, max) changes. */
4476
+ ngOnChanges(): void;
4477
+ validate(control: AbstractControl): ValidationErrors | null;
4478
+ registerOnValidatorChange(fn: () => void): void;
4197
4479
  private _onChange;
4198
4480
  private _onTouched;
4199
4481
  writeValue(val: string): void;
@@ -4202,6 +4484,7 @@ export declare class TimeInputComponent implements ControlValueAccessor {
4202
4484
  setDisabledState(d: boolean): void;
4203
4485
  protected onChange(event: Event): void;
4204
4486
  protected onBlur(): void;
4487
+ private _check;
4205
4488
  static ɵfac: i0.ɵɵFactoryDeclaration<TimeInputComponent, never>;
4206
4489
  static ɵcmp: i0.ɵɵComponentDeclaration<TimeInputComponent, "ui-time-input", never, {
4207
4490
  "label": {
@@ -4209,6 +4492,11 @@ export declare class TimeInputComponent implements ControlValueAccessor {
4209
4492
  "required": false;
4210
4493
  "isSignal": true;
4211
4494
  };
4495
+ "ariaLabel": {
4496
+ "alias": "ariaLabel";
4497
+ "required": false;
4498
+ "isSignal": true;
4499
+ };
4212
4500
  "required": {
4213
4501
  "alias": "required";
4214
4502
  "required": false;
@@ -4234,12 +4522,19 @@ export declare class TimeInputComponent implements ControlValueAccessor {
4234
4522
  "required": false;
4235
4523
  "isSignal": true;
4236
4524
  };
4525
+ "showErrors": {
4526
+ "alias": "showErrors";
4527
+ "required": false;
4528
+ "isSignal": true;
4529
+ };
4237
4530
  "_disabledInput": {
4238
4531
  "alias": "disabled";
4239
4532
  "required": false;
4240
4533
  "isSignal": true;
4241
4534
  };
4242
- }, {}, never, never, true, never>;
4535
+ }, {
4536
+ "invalidChange": "invalidChange";
4537
+ }, never, never, true, never>;
4243
4538
  }
4244
4539
  /**
4245
4540
  * Searchable multi-value dropdown. Selected values render as dismissible chips above the trigger.
@@ -5070,6 +5365,9 @@ export declare class ImagePreviewComponent {
5070
5365
  readonly size: import("@angular/core").InputSignal<ImagePreviewSize>;
5071
5366
  readonly placeholder: import("@angular/core").InputSignal<ImagePreviewPlaceholder>;
5072
5367
  readonly loading: import("@angular/core").InputSignal<"lazy" | "eager">;
5368
+ /** Focal point in percent (0-100, default centered) — which part of a cropped image stays visible (CSS object-position). */
5369
+ readonly positionX: import("@angular/core").InputSignal<number | null | undefined>;
5370
+ readonly positionY: import("@angular/core").InputSignal<number | null | undefined>;
5073
5371
  /**
5074
5372
  * Optional retry trigger: whenever its value changes, a failed image is attempted again (signal inputs cannot see
5075
5373
  * the same `src` being set twice, so a host bumps this, e.g. a counter, to retry the same URL).
@@ -5078,6 +5376,7 @@ export declare class ImagePreviewComponent {
5078
5376
  protected readonly _failed: import("@angular/core").WritableSignal<boolean>;
5079
5377
  /** Trimmed src; blank / whitespace-only is treated as no image. */
5080
5378
  protected readonly _url: import("@angular/core").Signal<string | null>;
5379
+ protected readonly _objectPosition: import("@angular/core").Signal<string>;
5081
5380
  protected readonly _cls: import("@angular/core").Signal<string>;
5082
5381
  constructor();
5083
5382
  /** Clears the failed state so the current `src` is attempted again (call via viewChild). */
@@ -5115,6 +5414,16 @@ export declare class ImagePreviewComponent {
5115
5414
  "required": false;
5116
5415
  "isSignal": true;
5117
5416
  };
5417
+ "positionX": {
5418
+ "alias": "positionX";
5419
+ "required": false;
5420
+ "isSignal": true;
5421
+ };
5422
+ "positionY": {
5423
+ "alias": "positionY";
5424
+ "required": false;
5425
+ "isSignal": true;
5426
+ };
5118
5427
  "retryKey": {
5119
5428
  "alias": "retryKey";
5120
5429
  "required": false;
@@ -5439,4 +5748,331 @@ export declare class RichTextEditorComponent implements ControlValueAccessor {
5439
5748
  * raw status text, "null"). Callers fall back to their own generated wording on `null`.
5440
5749
  */
5441
5750
  export declare function humanReadableMessage(value: unknown): string | null;
5751
+ /**
5752
+ * Single native radio button (visual tokens of `ui-checkbox`). Normally rendered by `ui-radio-group`; usable standalone
5753
+ * when the host manages the shared `name` and the `checked` state itself.
5754
+ */
5755
+ export declare class RadioComponent {
5756
+ readonly label: import("@angular/core").InputSignal<string>;
5757
+ readonly description: import("@angular/core").InputSignal<string>;
5758
+ /** Accessible name when there is no visible `label`. */
5759
+ readonly ariaLabel: import("@angular/core").InputSignal<string>;
5760
+ readonly value: import("@angular/core").InputSignal<string>;
5761
+ /** Radios with the same `name` form one keyboard (arrow key) group. */
5762
+ readonly name: import("@angular/core").InputSignal<string>;
5763
+ readonly checked: import("@angular/core").InputSignal<boolean>;
5764
+ readonly invalid: import("@angular/core").InputSignal<boolean>;
5765
+ /** Id(s) of the element(s) describing the group (hint / error). */
5766
+ readonly describedBy: import("@angular/core").InputSignal<string>;
5767
+ /** Public so a host template can bind `[disabled]` (a protected input fails strict template type-checking). */
5768
+ readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
5769
+ protected readonly disabled: import("@angular/core").InputSignal<boolean>;
5770
+ protected readonly _labelId: string;
5771
+ /** With a description inside the <label>, the accessible name would read "Email We send a message": name the input by the label text only. */
5772
+ protected readonly _labelledBy: import("@angular/core").Signal<string | null>;
5773
+ protected readonly _descriptionId: string;
5774
+ /** Group hint/error id plus the option's own description (kept out of the label so the accessible name is label-only). */
5775
+ protected readonly _describedByIds: import("@angular/core").Signal<string | null>;
5776
+ /** Emits the radio's `value` when the user selects it. */
5777
+ readonly selected: import("@angular/core").OutputEmitterRef<string>;
5778
+ protected onChange(event: Event): void;
5779
+ static ɵfac: i0.ɵɵFactoryDeclaration<RadioComponent, never>;
5780
+ static ɵcmp: i0.ɵɵComponentDeclaration<RadioComponent, "ui-radio", never, {
5781
+ "label": {
5782
+ "alias": "label";
5783
+ "required": false;
5784
+ "isSignal": true;
5785
+ };
5786
+ "description": {
5787
+ "alias": "description";
5788
+ "required": false;
5789
+ "isSignal": true;
5790
+ };
5791
+ "ariaLabel": {
5792
+ "alias": "ariaLabel";
5793
+ "required": false;
5794
+ "isSignal": true;
5795
+ };
5796
+ "value": {
5797
+ "alias": "value";
5798
+ "required": false;
5799
+ "isSignal": true;
5800
+ };
5801
+ "name": {
5802
+ "alias": "name";
5803
+ "required": false;
5804
+ "isSignal": true;
5805
+ };
5806
+ "checked": {
5807
+ "alias": "checked";
5808
+ "required": false;
5809
+ "isSignal": true;
5810
+ };
5811
+ "invalid": {
5812
+ "alias": "invalid";
5813
+ "required": false;
5814
+ "isSignal": true;
5815
+ };
5816
+ "describedBy": {
5817
+ "alias": "describedBy";
5818
+ "required": false;
5819
+ "isSignal": true;
5820
+ };
5821
+ "_disabledInput": {
5822
+ "alias": "disabled";
5823
+ "required": false;
5824
+ "isSignal": true;
5825
+ };
5826
+ }, {
5827
+ "selected": "selected";
5828
+ }, never, ["*"], true, never>;
5829
+ }
5830
+ export interface RadioOption {
5831
+ value: string;
5832
+ label: string;
5833
+ description?: string;
5834
+ disabled?: boolean;
5835
+ }
5836
+ /**
5837
+ * Group of native radio buttons inside a `<fieldset>` (+ `<legend>` = `label`), a ControlValueAccessor (string value, `''`
5838
+ * = nothing selected). Arrow keys move and select natively because all radios share one `name`.
5839
+ * Built-in validation: `required` -> "<label> is required."; a non-empty value that is not one of the `options` ->
5840
+ * "Select a valid option." (not checked while `options` is empty). Disabled groups are never invalid.
5841
+ *
5842
+ * Validity API (same on every ui input): Angular `Validator`, signals `invalid` + `errorMessage`, `invalidChange` output,
5843
+ * provides `UiFieldValidity`. Messages show after the group lost focus or while `[showErrors]="true"`; a host `[error]` wins.
5844
+ */
5845
+ export declare class RadioGroupComponent implements ControlValueAccessor, Validator, UiFieldValidity {
5846
+ readonly label: import("@angular/core").InputSignal<string>;
5847
+ readonly options: import("@angular/core").InputSignal<RadioOption[]>;
5848
+ readonly required: import("@angular/core").InputSignal<boolean>;
5849
+ readonly hint: import("@angular/core").InputSignal<string>;
5850
+ readonly error: import("@angular/core").InputSignal<string>;
5851
+ /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
5852
+ readonly showErrors: import("@angular/core").InputSignal<boolean>;
5853
+ readonly orientation: import("@angular/core").InputSignal<"vertical" | "horizontal">;
5854
+ /** Native `name` shared by the radios; a unique one is generated when omitted. */
5855
+ readonly name: import("@angular/core").InputSignal<string>;
5856
+ protected readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
5857
+ private readonly _cvaDisabled;
5858
+ protected readonly disabled: import("@angular/core").Signal<boolean>;
5859
+ private readonly _generatedName;
5860
+ protected get _name(): string;
5861
+ protected readonly _descId: string;
5862
+ protected readonly _value: import("@angular/core").WritableSignal<string>;
5863
+ private readonly _reveal;
5864
+ private readonly _issue;
5865
+ /** True while the value breaks a built-in rule or the host passed an `[error]`. */
5866
+ readonly invalid: import("@angular/core").Signal<boolean>;
5867
+ /** Message of the first broken built-in rule ('' when valid), shown or not. */
5868
+ readonly errorMessage: import("@angular/core").Signal<string>;
5869
+ /** Emits whenever the field becomes invalid / valid. */
5870
+ readonly invalidChange: import("@angular/core").OutputEmitterRef<boolean>;
5871
+ protected readonly _activeError: import("@angular/core").Signal<string>;
5872
+ private _onValidatorChange;
5873
+ constructor();
5874
+ /** Re-run the form control's validation when a rule input (required, options) changes. */
5875
+ ngOnChanges(): void;
5876
+ validate(control: AbstractControl): ValidationErrors | null;
5877
+ registerOnValidatorChange(fn: () => void): void;
5878
+ private _onChange;
5879
+ private _onTouched;
5880
+ writeValue(val: string): void;
5881
+ registerOnChange(fn: (v: string) => void): void;
5882
+ registerOnTouched(fn: () => void): void;
5883
+ setDisabledState(d: boolean): void;
5884
+ protected onSelect(value: string): void;
5885
+ /** Touched once focus leaves the whole group (moving between its radios does not count). */
5886
+ protected onFocusOut(event: FocusEvent): void;
5887
+ private _check;
5888
+ static ɵfac: i0.ɵɵFactoryDeclaration<RadioGroupComponent, never>;
5889
+ static ɵcmp: i0.ɵɵComponentDeclaration<RadioGroupComponent, "ui-radio-group", never, {
5890
+ "label": {
5891
+ "alias": "label";
5892
+ "required": false;
5893
+ "isSignal": true;
5894
+ };
5895
+ "options": {
5896
+ "alias": "options";
5897
+ "required": false;
5898
+ "isSignal": true;
5899
+ };
5900
+ "required": {
5901
+ "alias": "required";
5902
+ "required": false;
5903
+ "isSignal": true;
5904
+ };
5905
+ "hint": {
5906
+ "alias": "hint";
5907
+ "required": false;
5908
+ "isSignal": true;
5909
+ };
5910
+ "error": {
5911
+ "alias": "error";
5912
+ "required": false;
5913
+ "isSignal": true;
5914
+ };
5915
+ "showErrors": {
5916
+ "alias": "showErrors";
5917
+ "required": false;
5918
+ "isSignal": true;
5919
+ };
5920
+ "orientation": {
5921
+ "alias": "orientation";
5922
+ "required": false;
5923
+ "isSignal": true;
5924
+ };
5925
+ "name": {
5926
+ "alias": "name";
5927
+ "required": false;
5928
+ "isSignal": true;
5929
+ };
5930
+ "_disabledInput": {
5931
+ "alias": "disabled";
5932
+ "required": false;
5933
+ "isSignal": true;
5934
+ };
5935
+ }, {
5936
+ "invalidChange": "invalidChange";
5937
+ }, never, never, true, never>;
5938
+ }
5939
+ /**
5940
+ * Card for detail pages: an optional header and a body, both filled by the page that uses it.
5941
+ *
5942
+ * Header (all optional - set `[showHeader]="false"` and the card is just the body):
5943
+ * - `title` / `subtitle`: the bold uppercase title and the grey line under it.
5944
+ * - `titleId`: an id for the title text, which also names the card for assistive tech (aria-labelledby).
5945
+ * - `<div card-header-leading>`: something before the title block, such as a logo or an icon.
5946
+ * - `<ng-container card-header>`: your own header content, shown under the title (or instead of it when no title is set).
5947
+ * - `<ng-container card-header-action>`: buttons or links on the right side of the header.
5948
+ * - `showEdit` + `editLabel` + `(editClick)`: the built-in Edit button.
5949
+ * - `collapsible` (default true): a chevron toggle and a clickable header; `[(expanded)]` is two-way.
5950
+ * Without a header, or with `collapsible` false, the body is always open.
5951
+ *
5952
+ * The title is always shown in capitals; the subtitle keeps the case you give it. The body is the default content slot. A collapsed body is removed from the tab order and from assistive tech.
5953
+ *
5954
+ * <ui-detail-card title="COMMUNICATIONS" subtitle="All calls, texts, and emails"> ...body... </ui-detail-card>
5955
+ * <ui-detail-card title="CONTACT INFO" [showEdit]="true" (editClick)="openEdit()"> ... </ui-detail-card>
5956
+ * <ui-detail-card [showHeader]="false"> ...body only... </ui-detail-card>
5957
+ * <ui-detail-card [collapsible]="false">
5958
+ * <div card-header>Any markup</div>
5959
+ * <ui-button card-header-action size="xs" variant="secondary">Add</ui-button>
5960
+ * ...body...
5961
+ * </ui-detail-card>
5962
+ */
5963
+ export declare class DetailCardComponent {
5964
+ /** Bold uppercase title. Empty = no title text. */
5965
+ readonly title: import("@angular/core").InputSignal<string>;
5966
+ /** 1-6 makes the title a real heading for screen readers (role=heading, aria-level); null keeps it plain text. */
5967
+ readonly headingLevel: import("@angular/core").InputSignal<1 | 2 | 3 | 4 | 5 | 6 | null>;
5968
+ /** Optional id for the title text; the card is then labelled by it. Without it the title is the card's aria-label. */
5969
+ readonly titleId: import("@angular/core").InputSignal<string>;
5970
+ /** Grey line under the title. */
5971
+ readonly subtitle: import("@angular/core").InputSignal<string>;
5972
+ /** false = no header at all (no title, edit button, toggle or divider): the card is only the body, always open. */
5973
+ readonly showHeader: import("@angular/core").InputSignal<boolean>;
5974
+ /** Chevron toggle + clickable header. false = the body is always open. */
5975
+ readonly collapsible: import("@angular/core").InputSignal<boolean>;
5976
+ /** Two-way: whether the body is open. */
5977
+ readonly expanded: import("@angular/core").ModelSignal<boolean>;
5978
+ /** Show the built-in Edit button in the header. */
5979
+ readonly showEdit: import("@angular/core").InputSignal<boolean>;
5980
+ readonly editLabel: import("@angular/core").InputSignal<string>;
5981
+ readonly editClick: import("@angular/core").OutputEmitterRef<void>;
5982
+ /** The body is open unless the card has a header that is collapsible and was collapsed. */
5983
+ isOpen(): boolean;
5984
+ toggle(): void;
5985
+ /** A click on the header toggles, except on a control inside it (Edit, your own header actions, links, inputs). */
5986
+ onHeaderClick(event: Event): void;
5987
+ static ɵfac: i0.ɵɵFactoryDeclaration<DetailCardComponent, never>;
5988
+ static ɵcmp: i0.ɵɵComponentDeclaration<DetailCardComponent, "ui-detail-card", never, {
5989
+ "title": {
5990
+ "alias": "title";
5991
+ "required": false;
5992
+ "isSignal": true;
5993
+ };
5994
+ "headingLevel": {
5995
+ "alias": "headingLevel";
5996
+ "required": false;
5997
+ "isSignal": true;
5998
+ };
5999
+ "titleId": {
6000
+ "alias": "titleId";
6001
+ "required": false;
6002
+ "isSignal": true;
6003
+ };
6004
+ "subtitle": {
6005
+ "alias": "subtitle";
6006
+ "required": false;
6007
+ "isSignal": true;
6008
+ };
6009
+ "showHeader": {
6010
+ "alias": "showHeader";
6011
+ "required": false;
6012
+ "isSignal": true;
6013
+ };
6014
+ "collapsible": {
6015
+ "alias": "collapsible";
6016
+ "required": false;
6017
+ "isSignal": true;
6018
+ };
6019
+ "expanded": {
6020
+ "alias": "expanded";
6021
+ "required": false;
6022
+ "isSignal": true;
6023
+ };
6024
+ "showEdit": {
6025
+ "alias": "showEdit";
6026
+ "required": false;
6027
+ "isSignal": true;
6028
+ };
6029
+ "editLabel": {
6030
+ "alias": "editLabel";
6031
+ "required": false;
6032
+ "isSignal": true;
6033
+ };
6034
+ }, {
6035
+ "expanded": "expandedChange";
6036
+ "editClick": "editClick";
6037
+ }, never, ["[card-header-leading]", "[card-header]", "[card-header-action]", "*"], true, never>;
6038
+ }
6039
+ export type DividerSpace = 'none' | 'sm' | 'md' | 'lg';
6040
+ /**
6041
+ * Horizontal divider line (an `<hr>`) with the app's standard colour and optional space above / below.
6042
+ * It is a real separator for assistive tech by default; set `decorative` when it only adds visual rhythm and the
6043
+ * content around it already reads as separate (the line is then hidden from screen readers).
6044
+ *
6045
+ * <section class="kpi-grid"> ... </section>
6046
+ * <ui-divider /> // line with 16px below
6047
+ * <ui-divider spaceAbove="md" spaceBelow="lg" />
6048
+ * <ui-divider [decorative]="true" />
6049
+ */
6050
+ export declare class DividerComponent {
6051
+ /** Space above the line: none (0), sm (8px), md (16px), lg (24px). */
6052
+ readonly spaceAbove: import("@angular/core").InputSignal<DividerSpace>;
6053
+ /** Space below the line: none (0), sm (8px), md (16px), lg (24px). */
6054
+ readonly spaceBelow: import("@angular/core").InputSignal<DividerSpace>;
6055
+ /** true = purely visual: hidden from assistive tech. */
6056
+ readonly decorative: import("@angular/core").InputSignal<boolean>;
6057
+ protected readonly above: import("@angular/core").Signal<number>;
6058
+ protected readonly below: import("@angular/core").Signal<number>;
6059
+ static ɵfac: i0.ɵɵFactoryDeclaration<DividerComponent, never>;
6060
+ static ɵcmp: i0.ɵɵComponentDeclaration<DividerComponent, "ui-divider", never, {
6061
+ "spaceAbove": {
6062
+ "alias": "spaceAbove";
6063
+ "required": false;
6064
+ "isSignal": true;
6065
+ };
6066
+ "spaceBelow": {
6067
+ "alias": "spaceBelow";
6068
+ "required": false;
6069
+ "isSignal": true;
6070
+ };
6071
+ "decorative": {
6072
+ "alias": "decorative";
6073
+ "required": false;
6074
+ "isSignal": true;
6075
+ };
6076
+ }, {}, never, never, true, never>;
6077
+ }
5442
6078
  export type { SendDocumentsPayload, SendEmailPayload, SendTextPayload };