@joanroucoux/cairn-ui 0.1.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/joanroucoux-cairn-ui.mjs +831 -185
- package/fesm2022/joanroucoux-cairn-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/styles/fonts/OFL.txt +93 -0
- package/styles/fonts/rubik-latin-400-normal.woff2 +0 -0
- package/styles/fonts/rubik-latin-500-normal.woff2 +0 -0
- package/styles/fonts/rubik-latin-600-normal.woff2 +0 -0
- package/styles/fonts/rubik-latin-700-normal.woff2 +0 -0
- package/styles/fonts.css +29 -0
- package/styles/theme.css +31 -0
- package/styles/tokens.css +74 -0
- package/types/joanroucoux-cairn-ui.d.ts +241 -38
package/styles/tokens.css
CHANGED
|
@@ -54,6 +54,80 @@
|
|
|
54
54
|
--accent-foreground: light-dark(#111414, #edefee);
|
|
55
55
|
--destructive: light-dark(#b8443c, #a33a33);
|
|
56
56
|
--destructive-foreground: light-dark(#fafbfa, #fafbfa);
|
|
57
|
+
|
|
58
|
+
/* Type - Rubik, one family for logotype and interface (self-hosted, 400/500/600/700).
|
|
59
|
+
Names follow Tailwind 4 namespaces: registered in @theme they yield text-body, rounded-control,
|
|
60
|
+
ease-out... Reset Tailwind's defaults (--text-*: initial) so only this scale exists.
|
|
61
|
+
Weights: 400 text, 500 labels and buttons, 600 titles and the dominant figure, 700 logotype only. */
|
|
62
|
+
--font-sans: 'Rubik', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
|
|
63
|
+
--numeric: tabular-nums; /* amounts that align: tables, lists, columns. The lone big figure stays proportional. */
|
|
64
|
+
--text-caption: 0.75rem;
|
|
65
|
+
--text-caption--line-height: 1.0625rem; /* 12/17 axes, badges, price dates */
|
|
66
|
+
--text-label: 0.875rem;
|
|
67
|
+
--text-label--line-height: 1.25rem; /* 14/20 labels, secondary text, cells */
|
|
68
|
+
--text-body: 1rem;
|
|
69
|
+
--text-body--line-height: 1.5rem; /* 16/24 rows, body, inputs (no iOS zoom) */
|
|
70
|
+
--text-title: 1.25rem;
|
|
71
|
+
--text-title--line-height: 1.75rem; /* 20/28 card and section titles */
|
|
72
|
+
--text-heading: 1.75rem;
|
|
73
|
+
--text-heading--line-height: 2.125rem; /* 28/34 page title in the header */
|
|
74
|
+
--text-display: 2.5rem;
|
|
75
|
+
--text-display--line-height: 2.75rem; /* 40/44 the one dominant figure */
|
|
76
|
+
--tracking-display: -0.02em; /* heading, display */
|
|
77
|
+
--tracking-caption: 0.01em; /* caption */
|
|
78
|
+
|
|
79
|
+
/* Space - Tailwind's 4px step stays; these name the recurring gaps */
|
|
80
|
+
--gutter: 1rem; /* page side padding */
|
|
81
|
+
--inset-card: 1rem; /* card padding */
|
|
82
|
+
--stack-group: 1rem; /* between items of one group */
|
|
83
|
+
--stack-section: 1rem; /* between cards */
|
|
84
|
+
--row-min: 2.75rem; /* 44px touch target */
|
|
85
|
+
--header-height: 3.5rem; /* page header below the status bar / above the content */
|
|
86
|
+
|
|
87
|
+
/* Radius - one rule: controls 8, containers 12, pills round.
|
|
88
|
+
A control nested in a control subtracts its inset: calc(var(--radius-control) - 2px). */
|
|
89
|
+
--radius-control: 0.5rem; /* button, input, select, segmented, nav item, row hover */
|
|
90
|
+
--radius-container: 0.75rem; /* card, dialog, sheet top corners, tooltip */
|
|
91
|
+
--radius-pill: 9999px; /* avatar, badge, delta pill */
|
|
92
|
+
|
|
93
|
+
/* Motion - only transform and opacity animate. Never ease-in. Exits are faster than entries.
|
|
94
|
+
Nothing animates on page entry: the dashboard opens several times a day. */
|
|
95
|
+
--duration-press: 120ms; /* press feedback, on pointer down */
|
|
96
|
+
--duration-fast: 180ms; /* menus, segmented thumb */
|
|
97
|
+
--duration-base: 260ms; /* dialogs, sheets, list to detail, chart range change */
|
|
98
|
+
--duration-exit: 180ms; /* every exit */
|
|
99
|
+
--ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* what appears or moves */
|
|
100
|
+
--ease-sheet: cubic-bezier(0.32, 0.72, 0, 1); /* sheets rising from the bottom, and back */
|
|
101
|
+
--press-scale: 0.97;
|
|
102
|
+
--enter-scale: 0.95; /* dialogs and menus start at scale(0.95) and opacity 0, never scale(0) */
|
|
103
|
+
--pulse-duration: 1600ms; /* skeleton opacity pulse */
|
|
104
|
+
|
|
105
|
+
/* Browser theme color (meta theme-color, iOS status bar) follows the top of the page:
|
|
106
|
+
light #f7f8f8, dark #0a0b0b - the --background values. */
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@media (min-width: 64rem) {
|
|
110
|
+
:root {
|
|
111
|
+
--gutter: 2rem;
|
|
112
|
+
--inset-card: 1.5rem;
|
|
113
|
+
--stack-section: 1.5rem;
|
|
114
|
+
--header-height: 4.5rem;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@media (pointer: fine) {
|
|
119
|
+
:root {
|
|
120
|
+
--row-min: 2.5rem; /* 40px with a mouse: denser tables */
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@media (prefers-reduced-motion: reduce) {
|
|
125
|
+
:root {
|
|
126
|
+
--press-scale: 1;
|
|
127
|
+
--enter-scale: 1; /* slides and scales become short fades */
|
|
128
|
+
--duration-base: 150ms;
|
|
129
|
+
--pulse-duration: 0ms;
|
|
130
|
+
}
|
|
57
131
|
}
|
|
58
132
|
|
|
59
133
|
:root[data-theme='light'] {
|
|
@@ -1,5 +1,69 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { Signal, ElementRef } from '@angular/core';
|
|
2
|
+
import { InjectionToken, Signal, ElementRef } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
/** App-wide "amounts are hidden" state. Defaults to never masked; the app overrides it. */
|
|
5
|
+
declare const UI_AMOUNT_MASKED: InjectionToken<Signal<boolean>>;
|
|
6
|
+
/** Available figure styles. `AmountNumeric` is derived from this tuple. */
|
|
7
|
+
declare const AMOUNT_NUMERICS: readonly ["tabular", "proportional"];
|
|
8
|
+
type AmountNumeric = (typeof AMOUNT_NUMERICS)[number];
|
|
9
|
+
/** Available masking behaviors. `AmountMasking` is derived from this tuple. */
|
|
10
|
+
declare const AMOUNT_MASKINGS: readonly ["dots", "hide"];
|
|
11
|
+
type AmountMasking = (typeof AMOUNT_MASKINGS)[number];
|
|
12
|
+
/**
|
|
13
|
+
* A number or an amount of money, formatted for the locale and masked when the app hides amounts.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* <ui-amount [value]="total" currency="EUR" numeric="proportional" />
|
|
17
|
+
* <ui-amount [value]="dayChange" currency="EUR" signed whenMasked="hide" />
|
|
18
|
+
*/
|
|
19
|
+
declare class UiAmount {
|
|
20
|
+
#private;
|
|
21
|
+
readonly value: _angular_core.InputSignal<number | null | undefined>;
|
|
22
|
+
readonly currency: _angular_core.InputSignal<string | undefined>;
|
|
23
|
+
readonly locale: _angular_core.InputSignal<string>;
|
|
24
|
+
readonly signed: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
25
|
+
readonly fractionDigits: _angular_core.InputSignal<number>;
|
|
26
|
+
readonly numeric: _angular_core.InputSignal<"tabular" | "proportional">;
|
|
27
|
+
readonly whenMasked: _angular_core.InputSignal<"dots" | "hide">;
|
|
28
|
+
protected readonly hidden: Signal<boolean>;
|
|
29
|
+
protected readonly text: Signal<string>;
|
|
30
|
+
protected readonly classes: Signal<string>;
|
|
31
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiAmount, never>;
|
|
32
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiAmount, "ui-amount", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "currency": { "alias": "currency"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "signed": { "alias": "signed"; "required": false; "isSignal": true; }; "fractionDigits": { "alias": "fractionDigits"; "required": false; "isSignal": true; }; "numeric": { "alias": "numeric"; "required": false; "isSignal": true; }; "whenMasked": { "alias": "whenMasked"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type AmountFormatOptions = {
|
|
36
|
+
locale: string;
|
|
37
|
+
currency?: string;
|
|
38
|
+
signed?: boolean;
|
|
39
|
+
fractionDigits?: number;
|
|
40
|
+
};
|
|
41
|
+
/** Formats a number or an amount for the locale, with a missing value as an em dash and masking behind four bullets. */
|
|
42
|
+
declare function formatAmount(value: number | null | undefined, options: AmountFormatOptions, masked?: boolean): string;
|
|
43
|
+
|
|
44
|
+
/** Available async block states. `AsyncState` is derived from this tuple. */
|
|
45
|
+
declare const ASYNC_STATES: readonly ["loading", "error", "empty", "ready"];
|
|
46
|
+
type AsyncState = (typeof ASYNC_STATES)[number];
|
|
47
|
+
/**
|
|
48
|
+
* The three states of a block that depends on a service call, next to the ready content.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* <ui-async [state]="totalState()" errorTitle="Total could not be loaded" errorMessage="The server did not answer." retryLabel="Retry" (retry)="reload()">
|
|
52
|
+
* <span asyncLoading><ui-skeleton shape="figure" /></span>
|
|
53
|
+
* <span asyncEmpty>Add a holding to see your total.</span>
|
|
54
|
+
* <span>{{ total() }}</span>
|
|
55
|
+
* </ui-async>
|
|
56
|
+
*/
|
|
57
|
+
declare class UiAsync {
|
|
58
|
+
readonly state: _angular_core.InputSignal<"loading" | "error" | "empty" | "ready">;
|
|
59
|
+
readonly errorTitle: _angular_core.InputSignal<string | undefined>;
|
|
60
|
+
readonly errorMessage: _angular_core.InputSignal<string | undefined>;
|
|
61
|
+
readonly retryLabel: _angular_core.InputSignal<string | undefined>;
|
|
62
|
+
readonly retry: _angular_core.OutputEmitterRef<void>;
|
|
63
|
+
protected readonly retryButtonClasses = "mt-2 relative inline-flex items-center justify-center gap-2 rounded-control font-medium whitespace-nowrap cursor-pointer select-none touch-manipulation transition-[transform,background-color,opacity] duration-(--duration-press) ease-out active:scale-(--press-scale) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring) min-h-(--row-min) px-4 text-label bg-(--card) text-(--foreground) shadow-[inset_0_0_0_1px_var(--border)] hover:bg-(--glow)";
|
|
64
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiAsync, never>;
|
|
65
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiAsync, "ui-async", never, { "state": { "alias": "state"; "required": true; "isSignal": true; }; "errorTitle": { "alias": "errorTitle"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "retryLabel": { "alias": "retryLabel"; "required": false; "isSignal": true; }; }, { "retry": "retry"; }, never, ["[asyncLoading]", "[asyncEmpty]", "*"], true, never>;
|
|
66
|
+
}
|
|
3
67
|
|
|
4
68
|
/** Available avatar sizes. `AvatarSize` is derived from this tuple. */
|
|
5
69
|
declare const AVATAR_SIZES: readonly ["sm", "md"];
|
|
@@ -13,52 +77,49 @@ type AvatarSize = (typeof AVATAR_SIZES)[number];
|
|
|
13
77
|
declare class UiAvatar {
|
|
14
78
|
readonly initials: _angular_core.InputSignal<string>;
|
|
15
79
|
readonly label: _angular_core.InputSignal<string>;
|
|
16
|
-
readonly size: _angular_core.InputSignal<"
|
|
80
|
+
readonly size: _angular_core.InputSignal<"md" | "sm">;
|
|
17
81
|
protected readonly classes: _angular_core.Signal<string>;
|
|
18
82
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiAvatar, never>;
|
|
19
83
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiAvatar, "ui-avatar", never, { "initials": { "alias": "initials"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": true; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
20
84
|
}
|
|
21
85
|
|
|
22
86
|
/** Available badge variants. `BadgeVariant` is derived from this tuple. */
|
|
23
|
-
declare const BADGE_VARIANTS: readonly ["
|
|
87
|
+
declare const BADGE_VARIANTS: readonly ["neutral", "outline"];
|
|
24
88
|
type BadgeVariant = (typeof BADGE_VARIANTS)[number];
|
|
25
89
|
/**
|
|
26
|
-
* Small status descriptor for counts, states or labels.
|
|
90
|
+
* Small status descriptor for counts, states or labels, such as an instrument's asset class.
|
|
27
91
|
*
|
|
28
92
|
* @example
|
|
29
|
-
* <ui-badge
|
|
93
|
+
* <ui-badge>ETF</ui-badge>
|
|
30
94
|
*/
|
|
31
95
|
declare class UiBadge {
|
|
32
|
-
readonly variant: _angular_core.InputSignal<"
|
|
96
|
+
readonly variant: _angular_core.InputSignal<"neutral" | "outline">;
|
|
33
97
|
protected readonly classes: _angular_core.Signal<string>;
|
|
34
98
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiBadge, never>;
|
|
35
99
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiBadge, "ui-badge", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
36
100
|
}
|
|
37
101
|
|
|
38
102
|
/** Available button variants. `ButtonVariant` is derived from this tuple. */
|
|
39
|
-
declare const BUTTON_VARIANTS: readonly ["primary", "
|
|
103
|
+
declare const BUTTON_VARIANTS: readonly ["primary", "outline", "ghost", "destructive"];
|
|
40
104
|
type ButtonVariant = (typeof BUTTON_VARIANTS)[number];
|
|
41
|
-
/** Available button sizes. `md` is the
|
|
42
|
-
declare const BUTTON_SIZES: readonly ["
|
|
105
|
+
/** Available button sizes. `md` is the touch target Cairn asks for everywhere. */
|
|
106
|
+
declare const BUTTON_SIZES: readonly ["md", "lg", "xl", "icon"];
|
|
43
107
|
type ButtonSize = (typeof BUTTON_SIZES)[number];
|
|
44
108
|
/**
|
|
45
|
-
* Styled native button
|
|
46
|
-
* button behavior (type, disabled, form submission, accessibility) for free.
|
|
47
|
-
*
|
|
48
|
-
* Also applies to an anchor, for the one case where the action really is a navigation:
|
|
49
|
-
* a download the browser has to perform itself. The element stays a link, and so does
|
|
50
|
-
* its role - never use this to make an ordinary link look like a form control.
|
|
109
|
+
* Styled native button or anchor, applied as an attribute so the host keeps every native behavior.
|
|
51
110
|
*
|
|
52
111
|
* @example
|
|
53
|
-
* <button ui-button variant="destructive"
|
|
54
|
-
* <
|
|
112
|
+
* <button ui-button variant="destructive">Delete</button>
|
|
113
|
+
* <button ui-button size="icon" variant="ghost" aria-label="More actions">...</button>
|
|
55
114
|
*/
|
|
56
115
|
declare class UiButton {
|
|
57
|
-
readonly variant: _angular_core.InputSignal<"
|
|
58
|
-
readonly size: _angular_core.InputSignal<"
|
|
116
|
+
readonly variant: _angular_core.InputSignal<"outline" | "primary" | "ghost" | "destructive">;
|
|
117
|
+
readonly size: _angular_core.InputSignal<"md" | "lg" | "xl" | "icon">;
|
|
118
|
+
readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
59
119
|
protected readonly classes: _angular_core.Signal<string>;
|
|
120
|
+
constructor();
|
|
60
121
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiButton, never>;
|
|
61
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiButton, "button[ui-button], a[ui-button]", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
122
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiButton, "button[ui-button], a[ui-button]", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
62
123
|
}
|
|
63
124
|
|
|
64
125
|
/** Available card variants. `CardVariant` is derived from this tuple. */
|
|
@@ -75,7 +136,7 @@ type CardPadding = (typeof CARD_PADDINGS)[number];
|
|
|
75
136
|
*/
|
|
76
137
|
declare class UiCard {
|
|
77
138
|
readonly variant: _angular_core.InputSignal<"default" | "elevated">;
|
|
78
|
-
readonly padding: _angular_core.InputSignal<"
|
|
139
|
+
readonly padding: _angular_core.InputSignal<"md" | "sm" | "none">;
|
|
79
140
|
protected readonly classes: _angular_core.Signal<string>;
|
|
80
141
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiCard, never>;
|
|
81
142
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiCard, "ui-card", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "padding": { "alias": "padding"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
@@ -125,8 +186,8 @@ declare class UiDelta {
|
|
|
125
186
|
declare const DIALOG_WIDTHS: readonly ["md", "lg"];
|
|
126
187
|
type DialogWidth = (typeof DIALOG_WIDTHS)[number];
|
|
127
188
|
/**
|
|
128
|
-
* Modal dialog on the native <dialog>:
|
|
129
|
-
*
|
|
189
|
+
* Modal dialog on the native <dialog>: a sheet rising from the bottom under `64rem`, centered
|
|
190
|
+
* above it. Two projection slots - the body, and [dialogActions] for the footer.
|
|
130
191
|
*
|
|
131
192
|
* @example
|
|
132
193
|
* <ui-dialog heading="Delete this holding?" [open]="confirming()" (dismissed)="confirming.set(false)">
|
|
@@ -139,7 +200,7 @@ declare class UiDialog {
|
|
|
139
200
|
readonly heading: _angular_core.InputSignal<string>;
|
|
140
201
|
readonly description: _angular_core.InputSignal<string | undefined>;
|
|
141
202
|
readonly width: _angular_core.InputSignal<"md" | "lg">;
|
|
142
|
-
readonly open: _angular_core.
|
|
203
|
+
readonly open: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
143
204
|
readonly dismissed: _angular_core.OutputEmitterRef<void>;
|
|
144
205
|
protected readonly headingId: string;
|
|
145
206
|
protected readonly descriptionId: string;
|
|
@@ -178,10 +239,11 @@ declare class UiField {
|
|
|
178
239
|
readonly labelHidden: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
179
240
|
readonly hint: _angular_core.InputSignal<string | undefined>;
|
|
180
241
|
readonly error: _angular_core.InputSignal<string | undefined>;
|
|
242
|
+
readonly unit: _angular_core.InputSignal<string | undefined>;
|
|
181
243
|
protected readonly hintId: string;
|
|
182
244
|
protected readonly errorId: string;
|
|
183
245
|
protected readonly control: _angular_core.Signal<UiControl | undefined>;
|
|
184
|
-
protected readonly labelClasses: _angular_core.Signal<"sr-only" | "text-
|
|
246
|
+
protected readonly labelClasses: _angular_core.Signal<"sr-only" | "text-label font-medium text-(--muted-foreground)">;
|
|
185
247
|
/**
|
|
186
248
|
* The caller's own `error` wins: it is the only way to report something the control does not
|
|
187
249
|
* know about, such as a search box refusing an empty query.
|
|
@@ -189,10 +251,10 @@ declare class UiField {
|
|
|
189
251
|
protected readonly message: _angular_core.Signal<string | undefined>;
|
|
190
252
|
constructor();
|
|
191
253
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiField, never>;
|
|
192
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiField, "ui-field", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "labelHidden": { "alias": "labelHidden"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; }, {}, ["control"], ["*"], true, never>;
|
|
254
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiField, "ui-field", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "labelHidden": { "alias": "labelHidden"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; "unit": { "alias": "unit"; "required": false; "isSignal": true; }; }, {}, ["control"], ["*"], true, never>;
|
|
193
255
|
}
|
|
194
256
|
|
|
195
|
-
/** Available control sizes. `md` is the
|
|
257
|
+
/** Available control sizes. `md` is the 44/40px touch target. */
|
|
196
258
|
declare const CONTROL_SIZES: readonly ["sm", "md"];
|
|
197
259
|
type ControlSize = (typeof CONTROL_SIZES)[number];
|
|
198
260
|
/**
|
|
@@ -207,7 +269,7 @@ type ControlSize = (typeof CONTROL_SIZES)[number];
|
|
|
207
269
|
* <input uiInput type="email" placeholder="you@example.com" />
|
|
208
270
|
*/
|
|
209
271
|
declare class UiInput implements UiControl {
|
|
210
|
-
readonly size: _angular_core.InputSignal<"
|
|
272
|
+
readonly size: _angular_core.InputSignal<"md" | "sm">;
|
|
211
273
|
readonly errors: _angular_core.InputSignal<readonly UiControlError[]>;
|
|
212
274
|
readonly touched: _angular_core.InputSignal<boolean>;
|
|
213
275
|
protected readonly classes: _angular_core.Signal<string>;
|
|
@@ -232,6 +294,61 @@ declare class UiTextarea implements UiControl {
|
|
|
232
294
|
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<UiTextarea, "textarea[uiTextarea]", never, { "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
233
295
|
}
|
|
234
296
|
|
|
297
|
+
/**
|
|
298
|
+
* One action of a `ui-menu`; `destructive` paints it in `--negative`.
|
|
299
|
+
*
|
|
300
|
+
* @example
|
|
301
|
+
* <button uiMenuItem destructive (click)="remove()">Delete the line</button>
|
|
302
|
+
*/
|
|
303
|
+
declare class UiMenuItem {
|
|
304
|
+
#private;
|
|
305
|
+
readonly destructive: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
306
|
+
protected readonly classes: _angular_core.Signal<string>;
|
|
307
|
+
focus(): void;
|
|
308
|
+
hasFocus(): boolean;
|
|
309
|
+
protected onClick(): void;
|
|
310
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiMenuItem, never>;
|
|
311
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<UiMenuItem, "button[uiMenuItem]", never, { "destructive": { "alias": "destructive"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Secondary actions menu, opened from its trigger through the native Popover API.
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* <button ui-button size="icon" aria-label="More" [uiMenuTrigger]="menu">...</button>
|
|
318
|
+
* <ui-menu #menu label="Line actions">
|
|
319
|
+
* <button uiMenuItem (click)="edit()">Edit</button>
|
|
320
|
+
* <button uiMenuItem destructive (click)="remove()">Delete the line</button>
|
|
321
|
+
* </ui-menu>
|
|
322
|
+
*/
|
|
323
|
+
declare class UiMenu {
|
|
324
|
+
#private;
|
|
325
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
326
|
+
readonly menuId: string;
|
|
327
|
+
readonly isOpen: _angular_core.WritableSignal<boolean>;
|
|
328
|
+
protected readonly classes = "m-0 min-w-44 p-1 rounded-container bg-(--elevated) shadow-[0_8px_24px_rgb(0_0_0/0.16)] text-(--foreground) transition-[opacity,transform,overlay,display] transition-discrete duration-(--duration-fast) ease-out starting:open:opacity-0 starting:open:scale-(--enter-scale) opacity-0 scale-(--enter-scale) open:opacity-100 open:scale-100";
|
|
329
|
+
protected readonly items: _angular_core.Signal<readonly UiMenuItem[]>;
|
|
330
|
+
open(trigger: HTMLElement): void;
|
|
331
|
+
close(): void;
|
|
332
|
+
protected onToggle(event: Event): void;
|
|
333
|
+
protected onKeydown(event: KeyboardEvent): void;
|
|
334
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiMenu, never>;
|
|
335
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiMenu, "ui-menu", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; }, {}, ["items"], ["*"], true, never>;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Opens a `ui-menu` from a trigger element and wires `aria-haspopup`, `aria-expanded` and
|
|
339
|
+
* `aria-controls` on it.
|
|
340
|
+
*
|
|
341
|
+
* @example
|
|
342
|
+
* <button ui-button size="icon" aria-label="More" [uiMenuTrigger]="menu">...</button>
|
|
343
|
+
*/
|
|
344
|
+
declare class UiMenuTrigger {
|
|
345
|
+
#private;
|
|
346
|
+
readonly uiMenuTrigger: _angular_core.InputSignal<UiMenu>;
|
|
347
|
+
protected toggle(): void;
|
|
348
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiMenuTrigger, never>;
|
|
349
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<UiMenuTrigger, "[uiMenuTrigger]", never, { "uiMenuTrigger": { "alias": "uiMenuTrigger"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
350
|
+
}
|
|
351
|
+
|
|
235
352
|
/** Ramp step used to paint the fill. `MeterTone` is derived from this tuple. */
|
|
236
353
|
declare const METER_TONES: readonly [1, 2, 3, 4, 5, 6];
|
|
237
354
|
type MeterTone = (typeof METER_TONES)[number];
|
|
@@ -246,19 +363,51 @@ declare class UiMeter {
|
|
|
246
363
|
readonly value: _angular_core.InputSignal<number>;
|
|
247
364
|
readonly label: _angular_core.InputSignal<string>;
|
|
248
365
|
readonly valueText: _angular_core.InputSignal<string>;
|
|
249
|
-
readonly tone: _angular_core.InputSignal<2 |
|
|
366
|
+
readonly tone: _angular_core.InputSignal<2 | 1 | 3 | 4 | 5 | 6>;
|
|
250
367
|
protected readonly percent: _angular_core.Signal<number>;
|
|
251
368
|
protected readonly fillClasses: _angular_core.Signal<string>;
|
|
252
369
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiMeter, never>;
|
|
253
370
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiMeter, "ui-meter", never, { "value": { "alias": "value"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": true; "isSignal": true; }; "valueText": { "alias": "valueText"; "required": true; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
254
371
|
}
|
|
255
372
|
|
|
373
|
+
/**
|
|
374
|
+
* One destination of the sidebar navigation (Portfolio, Holdings, Allocation, Accounts).
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* <a ui-nav-item [active]="url === '/'" routerLink="/">
|
|
378
|
+
* <lucide-icon navIcon name="house" />
|
|
379
|
+
* Portfolio
|
|
380
|
+
* </a>
|
|
381
|
+
*/
|
|
382
|
+
declare class UiNavItem {
|
|
383
|
+
readonly active: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
384
|
+
protected readonly classes: _angular_core.Signal<string>;
|
|
385
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiNavItem, never>;
|
|
386
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiNavItem, "a[ui-nav-item]", never, { "active": { "alias": "active"; "required": false; "isSignal": true; }; }, {}, never, ["[navIcon]", "*"], true, never>;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Clickable row of a list: a holding, an envelope, an account.
|
|
391
|
+
*
|
|
392
|
+
* @example
|
|
393
|
+
* <a ui-row [selected]="holding.id === openId()" [routerLink]="['/holdings', holding.id]">
|
|
394
|
+
* {{ holding.name }}
|
|
395
|
+
* </a>
|
|
396
|
+
*/
|
|
397
|
+
declare class UiRow {
|
|
398
|
+
readonly selected: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
399
|
+
protected readonly classes: _angular_core.Signal<string>;
|
|
400
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiRow, never>;
|
|
401
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiRow, "a[ui-row], button[ui-row]", never, { "selected": { "alias": "selected"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
402
|
+
}
|
|
403
|
+
|
|
256
404
|
type SegmentedOption = {
|
|
257
405
|
value: string;
|
|
258
406
|
label: string;
|
|
259
407
|
};
|
|
260
408
|
/**
|
|
261
|
-
* Exclusive choice within a small, known set: a time range, a unit, a mode.
|
|
409
|
+
* Exclusive choice within a small, known set: a time range, a unit, a mode. The selected option's
|
|
410
|
+
* background is a single thumb that slides under it in `transform`, instead of being redrawn.
|
|
262
411
|
*
|
|
263
412
|
* @example
|
|
264
413
|
* <ui-segmented [options]="ranges" label="Time range" [(value)]="range" />
|
|
@@ -268,6 +417,7 @@ declare class UiSegmented {
|
|
|
268
417
|
readonly label: _angular_core.InputSignal<string>;
|
|
269
418
|
readonly value: _angular_core.ModelSignal<string>;
|
|
270
419
|
protected readonly radios: _angular_core.Signal<readonly ElementRef<HTMLButtonElement>[]>;
|
|
420
|
+
protected readonly thumbIndex: _angular_core.Signal<number>;
|
|
271
421
|
protected optionClasses(optionValue: string): string;
|
|
272
422
|
protected tabIndexFor(optionValue: string): number;
|
|
273
423
|
protected select(optionValue: string): void;
|
|
@@ -287,7 +437,7 @@ declare class UiSegmented {
|
|
|
287
437
|
* <select uiSelect><option value="pea">PEA</option></select>
|
|
288
438
|
*/
|
|
289
439
|
declare class UiSelect implements UiControl {
|
|
290
|
-
readonly size: _angular_core.InputSignal<"
|
|
440
|
+
readonly size: _angular_core.InputSignal<"md" | "sm">;
|
|
291
441
|
readonly errors: _angular_core.InputSignal<readonly UiControlError[]>;
|
|
292
442
|
readonly touched: _angular_core.InputSignal<boolean>;
|
|
293
443
|
protected readonly classes: _angular_core.Signal<string>;
|
|
@@ -296,19 +446,21 @@ declare class UiSelect implements UiControl {
|
|
|
296
446
|
}
|
|
297
447
|
|
|
298
448
|
/**
|
|
299
|
-
* Decorative placeholder for content that is still loading
|
|
300
|
-
*
|
|
449
|
+
* Decorative, pulsing placeholder for content that is still loading, at the shape of the content
|
|
450
|
+
* it stands in for.
|
|
301
451
|
*
|
|
302
452
|
* @example
|
|
453
|
+
* <ui-skeleton shape="figure" />
|
|
303
454
|
* <ui-skeleton [lines]="3" />
|
|
304
|
-
* <ui-skeleton [height]="196" />
|
|
305
455
|
*/
|
|
306
456
|
declare class UiSkeleton {
|
|
457
|
+
readonly shape: _angular_core.InputSignal<"figure" | "text" | "row" | "chart" | "ring">;
|
|
307
458
|
readonly lines: _angular_core.InputSignal<number>;
|
|
308
459
|
readonly height: _angular_core.InputSignal<number>;
|
|
460
|
+
protected readonly animation = "cairn-pulse var(--pulse-duration) var(--ease-out) infinite alternate";
|
|
309
461
|
protected readonly bars: _angular_core.Signal<("62%" | "100%")[]>;
|
|
310
462
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiSkeleton, never>;
|
|
311
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiSkeleton, "ui-skeleton", never, { "lines": { "alias": "lines"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
463
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiSkeleton, "ui-skeleton", never, { "shape": { "alias": "shape"; "required": false; "isSignal": true; }; "lines": { "alias": "lines"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
312
464
|
}
|
|
313
465
|
|
|
314
466
|
/** Available stat sizes. `StatSize` is derived from this tuple. */
|
|
@@ -332,12 +484,24 @@ type StatSize = (typeof STAT_SIZES)[number];
|
|
|
332
484
|
declare class UiStat {
|
|
333
485
|
readonly label: _angular_core.InputSignal<string>;
|
|
334
486
|
readonly size: _angular_core.InputSignal<"hero" | "tile">;
|
|
335
|
-
protected readonly labelClasses = "text-
|
|
487
|
+
protected readonly labelClasses = "text-label font-medium text-(--subtle-foreground)";
|
|
336
488
|
protected readonly valueClasses: _angular_core.Signal<string>;
|
|
337
489
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiStat, never>;
|
|
338
490
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiStat, "ui-stat", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, {}, never, ["[uiStatValue]", "[uiStatDelta]", "[uiStatCaption]", "[uiStatAside]"], true, never>;
|
|
339
491
|
}
|
|
340
492
|
|
|
493
|
+
/**
|
|
494
|
+
* Native checkbox styled as an iOS-style switch, exposed to assistive technology as `role="switch"`.
|
|
495
|
+
*
|
|
496
|
+
* @example
|
|
497
|
+
* <input type="checkbox" uiSwitch [checked]="hidden()" (change)="toggle()" aria-label="Hide amounts" />
|
|
498
|
+
*/
|
|
499
|
+
declare class UiSwitch {
|
|
500
|
+
protected readonly classes = "relative shrink-0 w-[51px] h-[31px] appearance-none cursor-pointer rounded-pill bg-(--muted) checked:bg-(--primary) transition-colors duration-(--duration-fast) ease-out disabled:pointer-events-none disabled:opacity-40 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring) before:absolute before:inset-x-0 before:top-1/2 before:-translate-y-1/2 before:h-(--row-min) before:content-[''] after:absolute after:top-0.5 after:left-0.5 after:size-[27px] after:rounded-pill after:bg-(--card) after:shadow-[0_1px_3px_rgb(0_0_0/0.2)] after:transition-transform after:duration-(--duration-fast) after:ease-out after:content-[''] checked:after:translate-x-[20px]";
|
|
501
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiSwitch, never>;
|
|
502
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<UiSwitch, "input[type=checkbox][uiSwitch]", never, {}, {}, never, never, true, never>;
|
|
503
|
+
}
|
|
504
|
+
|
|
341
505
|
/** Breakpoints a secondary column can be held back until. */
|
|
342
506
|
declare const CELL_BREAKPOINTS: readonly ["md", "lg"];
|
|
343
507
|
type CellBreakpoint = (typeof CELL_BREAKPOINTS)[number];
|
|
@@ -346,6 +510,20 @@ declare class UiTable {
|
|
|
346
510
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiTable, never>;
|
|
347
511
|
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<UiTable, "table[uiTable]", never, {}, {}, never, never, true, never>;
|
|
348
512
|
}
|
|
513
|
+
/**
|
|
514
|
+
* Body or group row. `group` draws the muted banner that opens each account inside a list of
|
|
515
|
+
* holdings: it carries no hover state of its own, unlike an ordinary row.
|
|
516
|
+
*
|
|
517
|
+
* @example
|
|
518
|
+
* <tr uiTr>...
|
|
519
|
+
* <tr uiTr group>...
|
|
520
|
+
*/
|
|
521
|
+
declare class UiTr {
|
|
522
|
+
readonly group: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
523
|
+
protected readonly classes: _angular_core.Signal<"min-h-(--row-min) rounded-control bg-(--muted) font-semibold" | "rounded-control hover:bg-(--glow)">;
|
|
524
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiTr, never>;
|
|
525
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<UiTr, "tr[uiTr]", never, { "group": { "alias": "group"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
526
|
+
}
|
|
349
527
|
/**
|
|
350
528
|
* Column header. `numeric` right-aligns and lines the digits up; `from` holds a
|
|
351
529
|
* secondary column back until the viewport is wide enough for it.
|
|
@@ -369,5 +547,30 @@ declare class UiTd {
|
|
|
369
547
|
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<UiTd, "td[uiTd]", never, { "numeric": { "alias": "numeric"; "required": false; "isSignal": true; }; "from": { "alias": "from"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
370
548
|
}
|
|
371
549
|
|
|
372
|
-
|
|
373
|
-
|
|
550
|
+
/**
|
|
551
|
+
* Bottom navigation bar for iPhone: 52px of tabs plus the home indicator's safe area.
|
|
552
|
+
*
|
|
553
|
+
* @example
|
|
554
|
+
* <nav ui-tab-bar>
|
|
555
|
+
* <a ui-tab [active]="url === '/'" routerLink="/"><lucide-icon tabIcon name="house" />Portfolio</a>
|
|
556
|
+
* </nav>
|
|
557
|
+
*/
|
|
558
|
+
declare class UiTabBar {
|
|
559
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiTabBar, never>;
|
|
560
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiTabBar, "nav[ui-tab-bar]", never, {}, {}, never, ["*"], true, never>;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* One destination of `ui-tab-bar`.
|
|
564
|
+
*
|
|
565
|
+
* @example
|
|
566
|
+
* <a ui-tab active routerLink="/"><lucide-icon tabIcon name="house" />Portfolio</a>
|
|
567
|
+
*/
|
|
568
|
+
declare class UiTab {
|
|
569
|
+
readonly active: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
570
|
+
protected readonly classes: _angular_core.Signal<string>;
|
|
571
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UiTab, never>;
|
|
572
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UiTab, "a[ui-tab]", never, { "active": { "alias": "active"; "required": false; "isSignal": true; }; }, {}, never, ["[tabIcon]", "*"], true, never>;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
export { AMOUNT_MASKINGS, AMOUNT_NUMERICS, ASYNC_STATES, AVATAR_SIZES, BADGE_VARIANTS, BUTTON_SIZES, BUTTON_VARIANTS, CARD_PADDINGS, CARD_VARIANTS, CELL_BREAKPOINTS, CONTROL_SIZES, DELTA_EMPHASES, DIALOG_WIDTHS, METER_TONES, STAT_SIZES, UI_AMOUNT_MASKED, UiAmount, UiAsync, UiAvatar, UiBadge, UiButton, UiCard, UiDelta, UiDialog, UiField, UiInput, UiMenu, UiMenuItem, UiMenuTrigger, UiMeter, UiNavItem, UiRow, UiSegmented, UiSelect, UiSkeleton, UiStat, UiSwitch, UiTab, UiTabBar, UiTable, UiTd, UiTextarea, UiTh, UiTr, formatAmount };
|
|
576
|
+
export type { AmountFormatOptions, AmountMasking, AmountNumeric, AsyncState, AvatarSize, BadgeVariant, ButtonSize, ButtonVariant, CardPadding, CardVariant, CellBreakpoint, ControlSize, DeltaEmphasis, DialogWidth, MeterTone, SegmentedOption, StatSize, UiControlError };
|