@area8975/ui 0.1.1-dev.12 → 0.1.1-dev.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from "@angular/core";
2
- import { ElementRef, OnDestroy, OnInit, Signal, TemplateRef, WritableSignal } from "@angular/core";
2
+ import { ElementRef, EnvironmentProviders, InjectionToken, OnDestroy, OnInit, Provider, Signal, TemplateRef, WritableSignal } from "@angular/core";
3
3
  import ApexCharts$1 from "apexcharts";
4
4
  import { Placement } from "@floating-ui/dom";
5
5
  import { Observable } from "rxjs";
@@ -9,6 +9,8 @@ export interface ChartLegendItem {
9
9
  colour: string;
10
10
  /** Shows the key as a dashed line, for series told apart by line style. */
11
11
  dashed?: boolean;
12
+ /** Text to show instead of `name`. `name` still ties the item to its series. */
13
+ label?: string;
12
14
  }
13
15
  /** Anything a legend can be linked to with `for`, every chart is one. */
14
16
  export interface ChartLegendSource {
@@ -26,30 +28,40 @@ export type ChartLegendPosition = 'auto' | 'none';
26
28
  * colour blindness (adjacent pairs stay apart for protan, deutan and tritan).
27
29
  * Keep the order, a series takes the next slot, never a generated colour.
28
30
  */
29
- declare const CHART_PALETTE: readonly ["#2a78d6", "#eb6834", "#1baf7a", "#eda100", "#e87ba4", "#008300", "#4a3aa7", "#e34948"];
31
+ export declare const CHART_PALETTE: readonly ["#2a78d6", "#eb6834", "#1baf7a", "#eda100", "#e87ba4", "#008300", "#4a3aa7", "#e34948"];
32
+ /**
33
+ * The palette for dark mode. Violet and green are lightened so every slot
34
+ * keeps 3:1 contrast on a dark card, the rest already do.
35
+ */
36
+ export declare const CHART_PALETTE_DARK: readonly ["#2a78d6", "#eb6834", "#1baf7a", "#eda100", "#e87ba4", "#2e9e2e", "#8a7cf0", "#e34948"];
30
37
  /** Past eight series, fold the rest into "Other" instead of reusing a colour. */
31
- declare const CHART_MAX_SERIES: 8;
38
+ export declare const CHART_MAX_SERIES: 8;
32
39
  /** Lines can go to sixteen, the second eight reuse the colours dashed. */
33
- declare const CHART_MAX_LINE_SERIES: number;
34
- declare const CHART_INK: {
35
- readonly text: "#1e2939";
36
- readonly muted: "#6a7282";
37
- readonly grid: "#e5e7eb";
38
- readonly surface: "#ffffff";
39
- readonly context: "#d1d5dc";
40
- };
41
- interface ChartSeriesStyle {
40
+ export declare const CHART_MAX_LINE_SERIES: number;
41
+ /** Chart chrome, apex needs real colours so these can't be CSS variables. */
42
+ export interface ChartInk {
43
+ text: string;
44
+ muted: string;
45
+ grid: string;
46
+ surface: string;
47
+ /** Series that are there for context. */
48
+ context: string;
49
+ }
50
+ export declare const CHART_INK: ChartInk;
51
+ export declare const CHART_INK_DARK: ChartInk;
52
+ export declare function chartInk(dark: boolean): ChartInk;
53
+ export interface ChartSeriesStyle {
42
54
  colour: string;
43
55
  dashed: boolean;
44
56
  }
45
57
  /** Past the eighth slot a series goes grey, reusing a colour would make two series look the same. */
46
- declare function chartColour(index: number): string;
58
+ export declare function chartColour(index: number, dark?: boolean): string;
47
59
  /**
48
60
  * Colour plus line style for a slot. With `dashes` the ninth to sixteenth
49
61
  * slots reuse the colours as dashed lines, colour and dash together keep
50
62
  * them apart. Anything past that is grey.
51
63
  */
52
- declare function chartSeriesStyle(index: number, dashes: boolean): ChartSeriesStyle;
64
+ export declare function chartSeriesStyle(index: number, dashes: boolean, dark?: boolean): ChartSeriesStyle;
53
65
  export type ChartOptions = ApexCharts$1.ApexOptions;
54
66
  /** One named set of values, one per category. */
55
67
  export interface ChartSeries {
@@ -57,16 +69,27 @@ export interface ChartSeries {
57
69
  data: (number | null)[];
58
70
  /** Overrides the palette slot, keep it for when a series must match something else. */
59
71
  colour?: string;
72
+ /** Draws the line dashed, e.g. to set projected figures apart from actual ones. Bars ignore it. */
73
+ dashed?: boolean;
60
74
  }
75
+ /**
76
+ * Pixels, or `fill` to take the height of the chart's host, which then has to
77
+ * get its height from layout (a grid row, a flex parent, `h-full` under a sized
78
+ * parent). Clamp it with `min-h-*` and `max-h-*` on the host.
79
+ */
80
+ export type ChartHeight = number | 'fill';
61
81
  /** Turns a raw value into what the axis, tooltip and table show, e.g. money. */
62
82
  export type ChartValueFormatter = (value: number) => string;
63
83
  /** Inputs every chart with categories along one axis and values up the other shares. */
64
84
  declare abstract class UiAxisChartBase implements ChartLegendSource {
85
+ protected readonly uiFormat: import("@area8975/ui").UiFormat;
86
+ protected readonly dark: import("@angular/core").WritableSignal<boolean>;
87
+ protected readonly ink: import("@angular/core").Signal<import("@area8975/ui").ChartInk>;
65
88
  readonly series: import("@angular/core").InputSignal<ChartSeries[]>;
66
89
  readonly categories: import("@angular/core").InputSignal<string[]>;
67
90
  /** Says what the chart shows, e.g. "Spending by month". */
68
91
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
69
- readonly height: import("@angular/core").InputSignal<number>;
92
+ readonly height: import("@angular/core").InputSignal<ChartHeight>;
70
93
  /** Used on the value axis, the tooltip and the table, e.g. to show money. */
71
94
  readonly valueFormatter: import("@angular/core").InputSignal<ChartValueFormatter>;
72
95
  /** Heading for the category column in the data table. */
@@ -82,6 +105,11 @@ declare abstract class UiAxisChartBase implements ChartLegendSource {
82
105
  * matter stand out. The way to show more series than there are colours.
83
106
  */
84
107
  readonly highlight: import("@angular/core").InputSignal<string[] | null>;
108
+ /**
109
+ * Highlighted series keep the colour they'd have with nothing highlighted,
110
+ * so picking one out of many doesn't change what colour it is.
111
+ */
112
+ readonly highlightKeepsColours: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
85
113
  /** `none` leaves the legend out, for when a `ui-chart-legend` is linked with `for`. */
86
114
  readonly legend: import("@angular/core").InputSignal<ChartLegendPosition>;
87
115
  /** Series switched off in the legend. */
@@ -90,8 +118,10 @@ declare abstract class UiAxisChartBase implements ChartLegendSource {
90
118
  readonly emphasis: import("@angular/core").WritableSignal<string | null>;
91
119
  /** Charts that draw lines can tell series apart by dashes too, bars can't. */
92
120
  protected readonly supportsDashes: boolean;
121
+ protected readonly apexHeight: import("@angular/core").Signal<number | "100%">;
93
122
  protected readonly isEmpty: import("@angular/core").Signal<boolean>;
94
123
  protected readonly isMuted: import("@angular/core").Signal<boolean[]>;
124
+ private readonly colourOrder;
95
125
  protected readonly styles: import("@angular/core").Signal<ChartSeriesStyle[]>;
96
126
  protected readonly colours: import("@angular/core").Signal<string[]>;
97
127
  protected readonly dashed: import("@angular/core").Signal<boolean[]>;
@@ -156,6 +186,11 @@ declare abstract class UiAxisChartBase implements ChartLegendSource {
156
186
  "required": false;
157
187
  "isSignal": true;
158
188
  };
189
+ "highlightKeepsColours": {
190
+ "alias": "highlightKeepsColours";
191
+ "required": false;
192
+ "isSignal": true;
193
+ };
159
194
  "legend": {
160
195
  "alias": "legend";
161
196
  "required": false;
@@ -170,6 +205,8 @@ declare abstract class UiAxisChartBase implements ChartLegendSource {
170
205
  export declare class UiBarChartComponent extends UiAxisChartBase {
171
206
  readonly orientation: import("@angular/core").InputSignal<"vertical" | "horizontal">;
172
207
  readonly stacked: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
208
+ /** Picks out one category, e.g. the month a page is showing, and fades the rest. */
209
+ readonly highlightCategory: import("@angular/core").InputSignal<string | null>;
173
210
  protected readonly chartOptions: import("@angular/core").Signal<ApexCharts.ApexOptions>;
174
211
  static ɵfac: i0.ɵɵFactoryDeclaration<UiBarChartComponent, never>;
175
212
  static ɵcmp: i0.ɵɵComponentDeclaration<UiBarChartComponent, "ui-bar-chart", never, {
@@ -183,6 +220,11 @@ export declare class UiBarChartComponent extends UiAxisChartBase {
183
220
  "required": false;
184
221
  "isSignal": true;
185
222
  };
223
+ "highlightCategory": {
224
+ "alias": "highlightCategory";
225
+ "required": false;
226
+ "isSignal": true;
227
+ };
186
228
  }, {}, never, never, true, never>;
187
229
  }
188
230
  /** vertical draws columns rising from the bottom, horizontal draws bars from the left. */
@@ -204,6 +246,7 @@ export declare class UiChartComponent {
204
246
  private readonly canvas;
205
247
  private readonly chart;
206
248
  private destroyed;
249
+ private drawnNames;
207
250
  constructor();
208
251
  private applyHidden;
209
252
  private applyEmphasis;
@@ -243,7 +286,7 @@ export declare class UiChartFrameComponent {
243
286
  readonly hiddenSeries: import("@angular/core").ModelSignal<string[]>;
244
287
  readonly valueFormatter: import("@angular/core").InputSignal<ChartValueFormatter>;
245
288
  readonly categoryLabel: import("@angular/core").InputSignal<string>;
246
- readonly height: import("@angular/core").InputSignal<number>;
289
+ readonly height: import("@angular/core").InputSignal<ChartHeight>;
247
290
  readonly emptyText: import("@angular/core").InputSignal<string>;
248
291
  readonly loading: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
249
292
  readonly empty: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
@@ -251,6 +294,8 @@ export declare class UiChartFrameComponent {
251
294
  readonly showLegend: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
252
295
  /** The series the legend is pointing at, the others fade while it's set. */
253
296
  readonly emphasis: import("@angular/core").ModelSignal<string | null>;
297
+ protected readonly fill: import("@angular/core").Signal<boolean>;
298
+ protected readonly fixedHeight: import("@angular/core").Signal<number | null>;
254
299
  static ɵfac: i0.ɵɵFactoryDeclaration<UiChartFrameComponent, never>;
255
300
  static ɵcmp: i0.ɵɵComponentDeclaration<UiChartFrameComponent, "ui-chart-frame", never, {
256
301
  "options": {
@@ -394,6 +439,11 @@ export declare class UiChartLegendComponent {
394
439
  readonly note: import("@angular/core").InputSignal<string>;
395
440
  /** A chart to take items from and hide or fade series on, set its `legend` to `none`. */
396
441
  readonly for: import("@angular/core").InputSignal<ChartLegendSource | null>;
442
+ /**
443
+ * Adjusts the items taken from `for`, e.g. to relabel or reorder them.
444
+ * Keep each item's `name`, toggling and fading find the series by it.
445
+ */
446
+ readonly itemsWith: import("@angular/core").InputSignal<((items: ChartLegendItem[]) => ChartLegendItem[]) | null>;
397
447
  /** Names of items switched off, bound two-way when `toggleable`. */
398
448
  readonly hidden: import("@angular/core").ModelSignal<string[]>;
399
449
  /** Lets each item be clicked to hide or show its series. */
@@ -430,6 +480,11 @@ export declare class UiChartLegendComponent {
430
480
  "required": false;
431
481
  "isSignal": true;
432
482
  };
483
+ "itemsWith": {
484
+ "alias": "itemsWith";
485
+ "required": false;
486
+ "isSignal": true;
487
+ };
433
488
  "hidden": {
434
489
  "alias": "hidden";
435
490
  "required": false;
@@ -454,6 +509,11 @@ export declare class UiLineChartComponent extends UiAxisChartBase {
454
509
  readonly curve: import("@angular/core").InputSignal<"straight" | "smooth" | "stepline">;
455
510
  /** Draws a dot on every point, not just the hovered one. Handy with few points. */
456
511
  readonly showPoints: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
512
+ /** Shades this category and everything after it as a forecast. */
513
+ readonly projectedFrom: import("@angular/core").InputSignal<string | null>;
514
+ /** Names the `projectedFrom` band. */
515
+ readonly projectedLabel: import("@angular/core").InputSignal<string>;
516
+ private readonly projectedAnnotations;
457
517
  protected readonly chartOptions: import("@angular/core").Signal<ApexCharts.ApexOptions>;
458
518
  private tooltipOrder;
459
519
  static ɵfac: i0.ɵɵFactoryDeclaration<UiLineChartComponent, never>;
@@ -468,6 +528,16 @@ export declare class UiLineChartComponent extends UiAxisChartBase {
468
528
  "required": false;
469
529
  "isSignal": true;
470
530
  };
531
+ "projectedFrom": {
532
+ "alias": "projectedFrom";
533
+ "required": false;
534
+ "isSignal": true;
535
+ };
536
+ "projectedLabel": {
537
+ "alias": "projectedLabel";
538
+ "required": false;
539
+ "isSignal": true;
540
+ };
471
541
  }, {}, never, never, true, never>;
472
542
  }
473
543
  /** How points are joined, straight segments, a smooth curve, or steps. */
@@ -481,6 +551,7 @@ export type LineChartCurve = typeof LineChartCurves[number];
481
551
  */
482
552
  export declare class UiPieChartComponent extends UiAxisChartBase {
483
553
  readonly variant: import("@angular/core").InputSignal<"pie" | "donut">;
554
+ private readonly percentFormatter;
484
555
  /** Shown above the total in the middle of a donut. */
485
556
  readonly totalLabel: import("@angular/core").InputSignal<string>;
486
557
  protected readonly values: import("@angular/core").Signal<(number | null)[]>;
@@ -512,6 +583,27 @@ export declare class UiPieChartComponent extends UiAxisChartBase {
512
583
  export declare const PieChartVariants: readonly ["pie", "donut"];
513
584
  /** @see {@link PieChartVariants} */
514
585
  export type PieChartVariant = typeof PieChartVariants[number];
586
+ /** Currency and locale shared by everything in the library that formats numbers. */
587
+ export interface UiFormat {
588
+ /** ISO 4217 code, e.g. "GBP". */
589
+ currency: string;
590
+ /** BCP 47 tag, e.g. "en-GB". */
591
+ locale: string;
592
+ }
593
+ /** What the library uses when nothing is provided. */
594
+ export declare const UI_FORMAT_DEFAULTS: UiFormat;
595
+ export declare const UI_FORMAT: InjectionToken<UiFormat>;
596
+ /**
597
+ * Sets the currency and locale once, in the app config or on a component for
598
+ * just its part of the page. Inputs on a component still win over it.
599
+ */
600
+ export declare function provideUiFormat(format: Partial<UiFormat>): Provider;
601
+ /**
602
+ * Formats money in the provided currency and locale, made for a chart's
603
+ * `valueFormatter`. Needs an injection context, e.g. a component field.
604
+ * `options` tweaks the output, e.g. `{ maximumFractionDigits: 0 }` for axes.
605
+ */
606
+ export declare function injectMoneyFormatter(options?: Intl.NumberFormatOptions): (value: number) => string;
515
607
  /** Native type values ui-input supports. File/checkbox/radio/range need their own components. */
516
608
  export declare const InputTypes: readonly ["text", "email", "tel", "url", "search", "password", "number", "date", "time", "datetime-local", "month", "week", "color"];
517
609
  /** @see {@link InputTypes} */
@@ -759,7 +851,7 @@ export declare class UiInputComponent<ValueType = string> {
759
851
  readonly name: import("@angular/core").InputSignal<string>;
760
852
  readonly placeholder: import("@angular/core").InputSignal<string>;
761
853
  readonly autocomplete: import("@angular/core").InputSignal<string>;
762
- readonly inputmode: import("@angular/core").InputSignal<"" | "none" | "text" | "search" | "numeric" | "decimal" | "email" | "tel" | "url">;
854
+ readonly inputmode: import("@angular/core").InputSignal<"" | "decimal" | "none" | "text" | "search" | "numeric" | "email" | "tel" | "url">;
763
855
  readonly required: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
764
856
  readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
765
857
  readonly readonly: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
@@ -773,6 +865,8 @@ export declare class UiInputComponent<ValueType = string> {
773
865
  readonly maxlength: import("@angular/core").InputSignal<number | null>;
774
866
  readonly autofocus: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
775
867
  readonly spellcheck: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
868
+ /** With `type="password"`, adds a button to show and hide what's been typed. */
869
+ readonly revealable: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
776
870
  readonly list: import("@angular/core").InputSignal<string>;
777
871
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
778
872
  readonly describedBy: import("@angular/core").InputSignal<string>;
@@ -786,6 +880,9 @@ export declare class UiInputComponent<ValueType = string> {
786
880
  readonly blurred: import("@angular/core").OutputEmitterRef<FocusEvent>;
787
881
  readonly leadingElement: import("@angular/core").Signal<TemplateRef<unknown> | undefined>;
788
882
  readonly trailingElement: import("@angular/core").Signal<TemplateRef<unknown> | undefined>;
883
+ protected readonly revealed: import("@angular/core").WritableSignal<boolean>;
884
+ protected readonly canReveal: import("@angular/core").Signal<boolean>;
885
+ protected readonly shownType: import("@angular/core").Signal<"number" | "color" | "text" | "search" | "time" | "email" | "tel" | "url" | "password" | "date" | "datetime-local" | "month" | "week">;
789
886
  readonly generatedClasses: import("@angular/core").Signal<string>;
790
887
  protected handleInput(event: Event): void;
791
888
  protected handleFocus(event: FocusEvent): void;
@@ -893,6 +990,11 @@ export declare class UiInputComponent<ValueType = string> {
893
990
  "required": false;
894
991
  "isSignal": true;
895
992
  };
993
+ "revealable": {
994
+ "alias": "revealable";
995
+ "required": false;
996
+ "isSignal": true;
997
+ };
896
998
  "list": {
897
999
  "alias": "list";
898
1000
  "required": false;
@@ -1114,7 +1216,7 @@ export declare class UiSelectComponent<Model = unknown> {
1114
1216
  readonly searchMode: import("@angular/core").InputSignal<SearchMode>;
1115
1217
  readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
1116
1218
  readonly validationState: import("@angular/core").ModelSignal<InputValidation>;
1117
- readonly clearable: import("@angular/core").InputSignal<boolean>;
1219
+ readonly clearable: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
1118
1220
  readonly clearLabel: import("@angular/core").InputSignal<string>;
1119
1221
  /**
1120
1222
  * Offers a "Create" row when a search matches nothing. Needs a
@@ -1445,7 +1547,6 @@ export declare class UiTextareaComponent {
1445
1547
  export declare class UiAlertComponent {
1446
1548
  readonly appearance: import("@angular/core").InputSignal<"soft" | "bordered">;
1447
1549
  readonly intent: import("@angular/core").InputSignal<string>;
1448
- readonly classes: import("@angular/core").InputSignal<string>;
1449
1550
  readonly icon: import("@angular/core").Signal<TemplateRef<unknown> | undefined>;
1450
1551
  readonly generatedClasses: import("@angular/core").Signal<string>;
1451
1552
  static ɵfac: i0.ɵɵFactoryDeclaration<UiAlertComponent, never>;
@@ -1460,22 +1561,53 @@ export declare class UiAlertComponent {
1460
1561
  "required": false;
1461
1562
  "isSignal": true;
1462
1563
  };
1463
- "classes": {
1464
- "alias": "classes";
1465
- "required": false;
1466
- "isSignal": true;
1467
- };
1468
1564
  }, {}, ["icon"], ["*"], true, never>;
1469
1565
  }
1470
1566
  export declare const AlertIntents: string[];
1471
1567
  export declare const AlertAppearances: readonly ["soft", "bordered"];
1472
1568
  export type AlertIntent = typeof AlertIntents[number];
1473
1569
  export type AlertAppearance = typeof AlertAppearances[number];
1570
+ /**
1571
+ * A small round picture of a person, their initials until `src` is set or
1572
+ * when the image fails to load. Screen readers hear the name, not the initials.
1573
+ */
1574
+ export declare class UiAvatarComponent {
1575
+ /** Who it shows, the initials come from it. */
1576
+ readonly name: import("@angular/core").InputSignal<string>;
1577
+ readonly src: import("@angular/core").InputSignal<string | null>;
1578
+ readonly size: import("@angular/core").InputSignal<"sm" | "md" | "lg">;
1579
+ private readonly failedSrc;
1580
+ protected readonly showImage: import("@angular/core").Signal<boolean>;
1581
+ protected readonly initials: import("@angular/core").Signal<string>;
1582
+ readonly generatedClasses: import("@angular/core").Signal<string>;
1583
+ protected imageFailed(): void;
1584
+ static ɵfac: i0.ɵɵFactoryDeclaration<UiAvatarComponent, never>;
1585
+ static ɵcmp: i0.ɵɵComponentDeclaration<UiAvatarComponent, "ui-avatar", never, {
1586
+ "name": {
1587
+ "alias": "name";
1588
+ "required": true;
1589
+ "isSignal": true;
1590
+ };
1591
+ "src": {
1592
+ "alias": "src";
1593
+ "required": false;
1594
+ "isSignal": true;
1595
+ };
1596
+ "size": {
1597
+ "alias": "size";
1598
+ "required": false;
1599
+ "isSignal": true;
1600
+ };
1601
+ }, {}, never, never, true, never>;
1602
+ }
1603
+ /** sm for dense rows, md for menus and lists, lg for a profile header. */
1604
+ export declare const AvatarSizes: readonly ["sm", "md", "lg"];
1605
+ /** @see {@link AvatarSizes} */
1606
+ export type AvatarSize = typeof AvatarSizes[number];
1474
1607
  export declare class UiBadgeComponent {
1475
1608
  readonly appearance: import("@angular/core").InputSignal<"solid" | "outline" | "soft">;
1476
1609
  readonly intent: import("@angular/core").InputSignal<"primary" | "secondary" | "success" | "warning" | "danger">;
1477
1610
  readonly size: import("@angular/core").InputSignal<"xs" | "sm" | "md" | "lg">;
1478
- readonly classes: import("@angular/core").InputSignal<string>;
1479
1611
  readonly generatedClasses: import("@angular/core").Signal<string>;
1480
1612
  static ɵfac: i0.ɵɵFactoryDeclaration<UiBadgeComponent, never>;
1481
1613
  static ɵcmp: i0.ɵɵComponentDeclaration<UiBadgeComponent, "ui-badge", never, {
@@ -1494,11 +1626,6 @@ export declare class UiBadgeComponent {
1494
1626
  "required": false;
1495
1627
  "isSignal": true;
1496
1628
  };
1497
- "classes": {
1498
- "alias": "classes";
1499
- "required": false;
1500
- "isSignal": true;
1501
- };
1502
1629
  }, {}, never, ["*"], true, never>;
1503
1630
  }
1504
1631
  export declare const BadgeIntents: readonly ["primary", "secondary", "success", "warning", "danger"];
@@ -1517,8 +1644,8 @@ export declare class UiButtonComponent {
1517
1644
  readonly classes: import("@angular/core").InputSignal<string>;
1518
1645
  readonly type: import("@angular/core").InputSignal<"button" | "reset" | "submit">;
1519
1646
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
1520
- readonly disabled: import("@angular/core").InputSignal<boolean>;
1521
- readonly loading: import("@angular/core").InputSignal<boolean>;
1647
+ readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
1648
+ readonly loading: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
1522
1649
  /**
1523
1650
  * Whether the underlying `<button>` element should be disabled - true when
1524
1651
  * `disabled` is set explicitly, or implicitly while `loading` is true.
@@ -1740,13 +1867,46 @@ export declare const CardRadii: readonly ["none", "sm", "md", "lg", "xl"];
1740
1867
  /** @see {@link CardRadii} */
1741
1868
  export type CardRadius = typeof CardRadii[number];
1742
1869
  export declare const radiusClasses: Record<CardRadius, string>;
1870
+ /**
1871
+ * The title row at the top of a card, with an optional muted subtitle.
1872
+ * Anything projected goes on the right as actions, e.g. buttons or a picker,
1873
+ * and wraps under the title when there isn't room.
1874
+ */
1875
+ export declare class UiCardHeaderComponent {
1876
+ readonly heading: import("@angular/core").InputSignal<string>;
1877
+ readonly subtitle: import("@angular/core").InputSignal<string>;
1878
+ /** Pick the level that fits the page's outline, it doesn't change the look. */
1879
+ readonly headingLevel: import("@angular/core").InputSignal<2 | 3 | 4>;
1880
+ static ɵfac: i0.ɵɵFactoryDeclaration<UiCardHeaderComponent, never>;
1881
+ static ɵcmp: i0.ɵɵComponentDeclaration<UiCardHeaderComponent, "ui-card-header", never, {
1882
+ "heading": {
1883
+ "alias": "heading";
1884
+ "required": true;
1885
+ "isSignal": true;
1886
+ };
1887
+ "subtitle": {
1888
+ "alias": "subtitle";
1889
+ "required": false;
1890
+ "isSignal": true;
1891
+ };
1892
+ "headingLevel": {
1893
+ "alias": "headingLevel";
1894
+ "required": false;
1895
+ "isSignal": true;
1896
+ };
1897
+ }, {}, never, ["*"], true, never>;
1898
+ }
1899
+ /** Heading levels a card title can use. */
1900
+ export declare const CardHeadingLevels: readonly [2, 3, 4];
1901
+ /** @see {@link CardHeadingLevels} */
1902
+ export type CardHeadingLevel = typeof CardHeadingLevels[number];
1743
1903
  export declare class UiContainerComponent {
1744
1904
  static ɵfac: i0.ɵɵFactoryDeclaration<UiContainerComponent, never>;
1745
1905
  static ɵcmp: i0.ɵɵComponentDeclaration<UiContainerComponent, "ui-container", never, {}, {}, never, ["*"], true, never>;
1746
1906
  }
1747
1907
  export declare class UiDrawerComponent {
1748
1908
  readonly isOpen: import("@angular/core").WritableSignal<boolean>;
1749
- readonly enableBackdrop: import("@angular/core").InputSignal<boolean>;
1909
+ readonly enableBackdrop: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
1750
1910
  readonly label: import("@angular/core").InputSignal<string>;
1751
1911
  readonly subLabel: import("@angular/core").InputSignal<string>;
1752
1912
  static ɵfac: i0.ɵɵFactoryDeclaration<UiDrawerComponent, never>;
@@ -1822,15 +1982,15 @@ export declare class UiDropdownComponent {
1822
1982
  }, {}, ["content"], ["*"], true, never>;
1823
1983
  }
1824
1984
  export declare class UiKpiComponent {
1825
- readonly title: import("@angular/core").InputSignal<string>;
1985
+ readonly label: import("@angular/core").InputSignal<string>;
1826
1986
  readonly value: import("@angular/core").InputSignal<string>;
1827
1987
  readonly hint: import("@angular/core").InputSignal<string>;
1828
1988
  readonly icon: import("@angular/core").InputSignal<string | undefined>;
1829
1989
  readonly iconPosition: import("@angular/core").InputSignal<"right" | "left">;
1830
1990
  static ɵfac: i0.ɵɵFactoryDeclaration<UiKpiComponent, never>;
1831
1991
  static ɵcmp: i0.ɵɵComponentDeclaration<UiKpiComponent, "ui-kpi", never, {
1832
- "title": {
1833
- "alias": "title";
1992
+ "label": {
1993
+ "alias": "label";
1834
1994
  "required": false;
1835
1995
  "isSignal": true;
1836
1996
  };
@@ -1917,17 +2077,21 @@ export declare class UiModalComponent {
1917
2077
  * Formats a money value, e.g. -42.1 as "-£42.10".
1918
2078
  */
1919
2079
  export declare class UiMoneyComponent {
2080
+ private readonly defaults;
1920
2081
  readonly value: import("@angular/core").InputSignal<number | null>;
2082
+ /** Defaults to the currency from `provideUiFormat`. */
1921
2083
  readonly currency: import("@angular/core").InputSignal<string>;
2084
+ /** Defaults to the locale from `provideUiFormat`. */
1922
2085
  readonly locale: import("@angular/core").InputSignal<string>;
1923
2086
  readonly signDisplay: import("@angular/core").InputSignal<"auto" | "always" | "exceptZero" | "never">;
1924
2087
  /** Green for money in, red for money out. */
1925
2088
  readonly colourBySign: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
2089
+ /** Rounds to whole units, e.g. "£2,235" for headline figures where pence are noise. */
2090
+ readonly wholeUnits: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
1926
2091
  /** Short form like "£12K", the full amount goes in the title. */
1927
2092
  readonly compact: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
1928
2093
  /** Shown when there's no value. */
1929
2094
  readonly placeholder: import("@angular/core").InputSignal<string>;
1930
- readonly classes: import("@angular/core").InputSignal<string>;
1931
2095
  private readonly amount;
1932
2096
  protected readonly formatted: import("@angular/core").Signal<string>;
1933
2097
  protected readonly title: import("@angular/core").Signal<string | null>;
@@ -1961,6 +2125,11 @@ export declare class UiMoneyComponent {
1961
2125
  "required": false;
1962
2126
  "isSignal": true;
1963
2127
  };
2128
+ "wholeUnits": {
2129
+ "alias": "wholeUnits";
2130
+ "required": false;
2131
+ "isSignal": true;
2132
+ };
1964
2133
  "compact": {
1965
2134
  "alias": "compact";
1966
2135
  "required": false;
@@ -1971,11 +2140,6 @@ export declare class UiMoneyComponent {
1971
2140
  "required": false;
1972
2141
  "isSignal": true;
1973
2142
  };
1974
- "classes": {
1975
- "alias": "classes";
1976
- "required": false;
1977
- "isSignal": true;
1978
- };
1979
2143
  }, {}, never, never, true, never>;
1980
2144
  }
1981
2145
  /** Intl signDisplay values, controls when a + or - is shown. */
@@ -1987,8 +2151,6 @@ export type PaginationItem = number | 'ellipsis';
1987
2151
  export declare class UiPaginationComponent {
1988
2152
  readonly page: import("@angular/core").ModelSignal<number>;
1989
2153
  readonly totalPages: import("@angular/core").InputSignal<number>;
1990
- readonly classes: import("@angular/core").InputSignal<string>;
1991
- readonly generatedClasses: import("@angular/core").Signal<string>;
1992
2154
  readonly isFirstPage: import("@angular/core").Signal<boolean>;
1993
2155
  readonly isLastPage: import("@angular/core").Signal<boolean>;
1994
2156
  readonly items: import("@angular/core").Signal<PaginationItem[]>;
@@ -2006,11 +2168,6 @@ export declare class UiPaginationComponent {
2006
2168
  "required": true;
2007
2169
  "isSignal": true;
2008
2170
  };
2009
- "classes": {
2010
- "alias": "classes";
2011
- "required": false;
2012
- "isSignal": true;
2013
- };
2014
2171
  }, {
2015
2172
  "page": "pageChange";
2016
2173
  }, never, never, true, never>;
@@ -2141,6 +2298,45 @@ export declare class UiProgressComponent {
2141
2298
  };
2142
2299
  }, {}, never, never, true, never>;
2143
2300
  }
2301
+ /** One choice in a segmented control. */
2302
+ export interface SegmentedOption<T> {
2303
+ value: T;
2304
+ label: string;
2305
+ /** Read out instead of `label`, for when the label is abbreviated, e.g. "6M". */
2306
+ ariaLabel?: string;
2307
+ }
2308
+ /**
2309
+ * A row of options where exactly one is picked, e.g. a time range or a view
2310
+ * toggle. Built on native radios, so arrow keys move between options and
2311
+ * screen readers hear a radio group.
2312
+ */
2313
+ export declare class UiSegmentedComponent<T> {
2314
+ readonly options: import("@angular/core").InputSignal<SegmentedOption<T>[]>;
2315
+ readonly value: import("@angular/core").ModelSignal<T>;
2316
+ /** What the options choose between, e.g. "How far back the charts go". */
2317
+ readonly ariaLabel: import("@angular/core").InputSignal<string>;
2318
+ protected readonly name: string;
2319
+ static ɵfac: i0.ɵɵFactoryDeclaration<UiSegmentedComponent<any>, never>;
2320
+ static ɵcmp: i0.ɵɵComponentDeclaration<UiSegmentedComponent<any>, "ui-segmented", never, {
2321
+ "options": {
2322
+ "alias": "options";
2323
+ "required": true;
2324
+ "isSignal": true;
2325
+ };
2326
+ "value": {
2327
+ "alias": "value";
2328
+ "required": true;
2329
+ "isSignal": true;
2330
+ };
2331
+ "ariaLabel": {
2332
+ "alias": "ariaLabel";
2333
+ "required": true;
2334
+ "isSignal": true;
2335
+ };
2336
+ }, {
2337
+ "value": "valueChange";
2338
+ }, never, never, true, never>;
2339
+ }
2144
2340
  /**
2145
2341
  * A placeholder shown while content loads. Size it with classes on the
2146
2342
  * element, e.g. `class="w-48"` for text or `class="size-12"` for a circle.
@@ -2150,7 +2346,6 @@ export declare class UiSkeletonComponent {
2150
2346
  readonly animated: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
2151
2347
  /** Text only, stacks this many lines with a shorter last one. */
2152
2348
  readonly lines: import("@angular/core").InputSignalWithTransform<number, unknown>;
2153
- readonly classes: import("@angular/core").InputSignal<string>;
2154
2349
  protected readonly lineIndexes: import("@angular/core").Signal<number[]>;
2155
2350
  readonly generatedClasses: import("@angular/core").Signal<string>;
2156
2351
  static ɵfac: i0.ɵɵFactoryDeclaration<UiSkeletonComponent, never>;
@@ -2170,20 +2365,33 @@ export declare class UiSkeletonComponent {
2170
2365
  "required": false;
2171
2366
  "isSignal": true;
2172
2367
  };
2173
- "classes": {
2174
- "alias": "classes";
2175
- "required": false;
2176
- "isSignal": true;
2177
- };
2178
2368
  }, {}, never, never, true, never>;
2179
2369
  }
2180
2370
  /** What a skeleton stands in for, lines of text, an avatar or a block. */
2181
2371
  export declare const SkeletonShapes: readonly ["text", "circle", "rect"];
2182
2372
  /** @see {@link SkeletonShapes} */
2183
2373
  export type SkeletonShape = typeof SkeletonShapes[number];
2374
+ /**
2375
+ * A muted label over a large figure, for the numbers inside a card. Project
2376
+ * the value, e.g. a `ui-money`, and optionally a change or badge beside it
2377
+ * with `stat-change` and a small line under it with `stat-note`.
2378
+ *
2379
+ * Each stat is its own `dl`, so put a row of them in a plain flex or grid wrapper.
2380
+ */
2381
+ export declare class UiStatComponent {
2382
+ readonly label: import("@angular/core").InputSignal<string>;
2383
+ static ɵfac: i0.ɵɵFactoryDeclaration<UiStatComponent, never>;
2384
+ static ɵcmp: i0.ɵɵComponentDeclaration<UiStatComponent, "ui-stat", never, {
2385
+ "label": {
2386
+ "alias": "label";
2387
+ "required": true;
2388
+ "isSignal": true;
2389
+ };
2390
+ }, {}, never, ["*", "[stat-change]", "[stat-note]"], true, never>;
2391
+ }
2184
2392
  export declare class UiTabDirective {
2185
2393
  label: import("@angular/core").InputSignal<string>;
2186
- disabled: import("@angular/core").InputSignal<boolean>;
2394
+ disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
2187
2395
  active: import("@angular/core").ModelSignal<boolean>;
2188
2396
  static ɵfac: i0.ɵɵFactoryDeclaration<UiTabDirective, never>;
2189
2397
  static ɵdir: i0.ɵɵDirectiveDeclaration<UiTabDirective, "[uiTab]", never, {
@@ -2710,6 +2918,12 @@ export declare class UiOverlayComponent implements UiOverlayStackEntry {
2710
2918
  }
2711
2919
  export declare class UiSidebarComponent {
2712
2920
  readonly isOpen: import("@angular/core").ModelSignal<boolean>;
2921
+ /**
2922
+ * True while the sidebar is narrow, so content projected into the footer can
2923
+ * shrink to an icon or avatar. Read it with `#sidebar="uiSidebar"` or by
2924
+ * injecting UiSidebarComponent.
2925
+ */
2926
+ readonly isCollapsed: import("@angular/core").Signal<boolean>;
2713
2927
  readonly toggle: () => void;
2714
2928
  static ɵfac: i0.ɵɵFactoryDeclaration<UiSidebarComponent, never>;
2715
2929
  static ɵcmp: i0.ɵɵComponentDeclaration<UiSidebarComponent, "ui-sidebar", ["uiSidebar"], {
@@ -2720,7 +2934,7 @@ export declare class UiSidebarComponent {
2720
2934
  };
2721
2935
  }, {
2722
2936
  "isOpen": "isOpenChange";
2723
- }, never, ["*"], true, never>;
2937
+ }, never, ["*", "[sidebar-footer]"], true, never>;
2724
2938
  }
2725
2939
  export declare class UiSidebarItemComponent {
2726
2940
  private readonly sidebar;
@@ -3250,4 +3464,44 @@ export declare class UiTimeSelectComponent {
3250
3464
  }, {
3251
3465
  "value": "valueChange";
3252
3466
  }, never, never, true, never>;
3253
- }
3467
+ }
3468
+ /** What the user picked, `system` follows the OS setting. */
3469
+ export type UiThemePreference = 'system' | 'light' | 'dark';
3470
+ export interface UiThemeConfig {
3471
+ /** localStorage key the preference is kept under. */
3472
+ storageKey: string;
3473
+ }
3474
+ export declare const UI_THEME_CONFIG: InjectionToken<UiThemeConfig>;
3475
+ /**
3476
+ * Switches between light and dark by toggling `.dark` on `<html>`, which the
3477
+ * library's tokens key off. Add it with `provideUiTheme()`.
3478
+ *
3479
+ * To stop the page flashing the wrong theme before the app boots, apply the
3480
+ * stored class early with a small inline script in `index.html`'s `<head>`:
3481
+ *
3482
+ * ```html
3483
+ * <script>
3484
+ * try {
3485
+ * const preference = localStorage.getItem('ui-theme') ?? 'system';
3486
+ * const dark = preference === 'dark' ||
3487
+ * (preference === 'system' && matchMedia('(prefers-color-scheme: dark)').matches);
3488
+ * document.documentElement.classList.toggle('dark', dark);
3489
+ * } catch {}
3490
+ * </script>
3491
+ * ```
3492
+ */
3493
+ export declare class UiThemeService {
3494
+ private readonly document;
3495
+ private readonly storageKey;
3496
+ private readonly media;
3497
+ readonly preference: import("@angular/core").WritableSignal<UiThemePreference>;
3498
+ private readonly systemDark;
3499
+ /** Whether dark is showing now, resolved from the preference and the OS setting. */
3500
+ readonly isDark: import("@angular/core").Signal<boolean>;
3501
+ constructor();
3502
+ private stored;
3503
+ static ɵfac: i0.ɵɵFactoryDeclaration<UiThemeService, never>;
3504
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
3505
+ }
3506
+ /** Starts theme switching at boot. Read or change it through `UiThemeService`. */
3507
+ export declare function provideUiTheme(config?: Partial<UiThemeConfig>): EnvironmentProviders;