@aracreate/arm-ui 3.6.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/LICENSE +674 -0
- package/README.md +170 -0
- package/dist/big-calendar-overrides.css +196 -0
- package/dist/chunk-LGJWNA6J.mjs +2 -0
- package/dist/chunk-LGJWNA6J.mjs.map +1 -0
- package/dist/chunk-TD6NGM5I.js +2 -0
- package/dist/chunk-TD6NGM5I.js.map +1 -0
- package/dist/index.css +2 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +1531 -0
- package/dist/index.d.ts +1531 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/preset.d.mts +5 -0
- package/dist/preset.d.ts +5 -0
- package/dist/preset.js +242 -0
- package/dist/preset.js.map +1 -0
- package/dist/preset.mjs +242 -0
- package/dist/preset.mjs.map +1 -0
- package/dist/style.css +1028 -0
- package/dist/tokens.css +769 -0
- package/package.json +217 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,1531 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import react__default, { CSSProperties, ReactNode } from 'react';
|
|
3
|
+
import { HeaderProps, ToolbarProps } from 'react-big-calendar';
|
|
4
|
+
export { View } from 'react-big-calendar';
|
|
5
|
+
import { ClassValue } from 'clsx';
|
|
6
|
+
import { ThemeProps } from '@radix-ui/themes';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Skeleton — loading placeholder. Generalizes the local `Skel` helper and the
|
|
10
|
+
* inline `<div className="skeleton" .../>` blocks used in the users, user-detail,
|
|
11
|
+
* and home surfaces. Pulse animation + base color come from `.skeleton` in
|
|
12
|
+
* globals.css.
|
|
13
|
+
*/
|
|
14
|
+
interface SkeletonProps {
|
|
15
|
+
width?: number | string;
|
|
16
|
+
height?: number | string;
|
|
17
|
+
/** Border radius. Ignored when `circle` is set. Defaults to var(--radius-2). */
|
|
18
|
+
radius?: number | string;
|
|
19
|
+
/** Render as a circle (avatars). */
|
|
20
|
+
circle?: boolean;
|
|
21
|
+
/** Bottom margin. */
|
|
22
|
+
mb?: number | string;
|
|
23
|
+
className?: string;
|
|
24
|
+
style?: CSSProperties;
|
|
25
|
+
}
|
|
26
|
+
declare function Skeleton({ width, height, radius, circle, mb, className, style, }: SkeletonProps): react.JSX.Element;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* AccentHeader — the amber two-tone title bar Figma uses on cards, dialogs,
|
|
30
|
+
* and page banners (Target/Source Calendar, Preview, Upcoming Event, Confirm
|
|
31
|
+
* Logout, Terms hero). Build-once pattern per the design ledger: a solid
|
|
32
|
+
* `--accent-9` bar with a dark bold title, optionally with trailing controls
|
|
33
|
+
* (e.g. the Month/Week/Day toggle lives inside the bar on the Preview card).
|
|
34
|
+
*
|
|
35
|
+
* Figma refs: ui-ux/figma/crops/month-card.png, confirm-dialog.png.
|
|
36
|
+
*/
|
|
37
|
+
interface AccentHeaderProps {
|
|
38
|
+
title: ReactNode;
|
|
39
|
+
/** Right-aligned slot inside the bar (view toggles, actions). */
|
|
40
|
+
trailing?: ReactNode;
|
|
41
|
+
style?: CSSProperties;
|
|
42
|
+
}
|
|
43
|
+
declare function AccentHeader({ title, trailing, style }: AccentHeaderProps): react.JSX.Element;
|
|
44
|
+
/**
|
|
45
|
+
* AccentCard — white panel with an AccentHeader bar and rounded corners
|
|
46
|
+
* (measured r≈14 @1728 → var(--radius-5)) plus the soft card shadow seen on
|
|
47
|
+
* every Figma card. The header is clipped by the card's radius.
|
|
48
|
+
*/
|
|
49
|
+
interface AccentCardProps extends AccentHeaderProps {
|
|
50
|
+
children: ReactNode;
|
|
51
|
+
/** Radix padding scale for the body. Defaults to "4"; use "0" for flush content. */
|
|
52
|
+
bodyPadding?: "0" | "1" | "2" | "3" | "4" | "5" | "6";
|
|
53
|
+
}
|
|
54
|
+
declare function AccentCard({ title, trailing, children, bodyPadding, style, }: AccentCardProps): react.JSX.Element;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* ConfirmDialog — the confirm/cancel prompt used for destructive or
|
|
58
|
+
* state-changing actions (Confirm Logout, Remove account, etc). Built on
|
|
59
|
+
* Radix `AlertDialog` with a plain title/description and bottom-right
|
|
60
|
+
* actions, matching the app's other dialogs (e.g. ImportCalendarsDialog):
|
|
61
|
+
* neutral outline Cancel, amber-primary Confirm.
|
|
62
|
+
*/
|
|
63
|
+
interface ConfirmDialogProps {
|
|
64
|
+
/** Dialog title, rendered inside the AccentHeader bar. */
|
|
65
|
+
title: ReactNode;
|
|
66
|
+
/** Question / body copy. */
|
|
67
|
+
description: ReactNode;
|
|
68
|
+
/** Confirm button label. Defaults to "Yes". */
|
|
69
|
+
confirmLabel?: ReactNode;
|
|
70
|
+
/** Cancel button label. Defaults to "Cancel". */
|
|
71
|
+
cancelLabel?: ReactNode;
|
|
72
|
+
/** Called when the confirm action is activated (dialog still closes via AlertDialog.Action). */
|
|
73
|
+
onConfirm?: () => void;
|
|
74
|
+
/** Element that opens the dialog, rendered inside AlertDialog.Trigger. Omit for a fully controlled dialog. */
|
|
75
|
+
trigger?: ReactNode;
|
|
76
|
+
/** Controlled open state — omit for uncontrolled, trigger-driven usage. */
|
|
77
|
+
open?: boolean;
|
|
78
|
+
onOpenChange?: (open: boolean) => void;
|
|
79
|
+
}
|
|
80
|
+
declare function ConfirmDialog({ title, description, confirmLabel, cancelLabel, onConfirm, trigger, open, onOpenChange, }: ConfirmDialogProps): react.JSX.Element;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* PausedBadge — small outline pill marking a paused account. Sits top-left
|
|
84
|
+
* of AccountCard, immediately right of the avatar. White fill, 1px
|
|
85
|
+
* `--color-paused` border + text, full radius pill, a tiny circled pause
|
|
86
|
+
* glyph, then the label.
|
|
87
|
+
*
|
|
88
|
+
* Figma ref: ui-ux/figma/crops/account-card-menu.png. Measured 59×17 @1728
|
|
89
|
+
* (≈49×14 app scale) — genuinely tiny, so this is built directly rather than
|
|
90
|
+
* from Radix `Badge` (Badge's smallest size/padding can't hit an 18px
|
|
91
|
+
* height). Fit level: Light customization.
|
|
92
|
+
*
|
|
93
|
+
* Deviation: the glyph inside the circle is rendered at 8px rather than the
|
|
94
|
+
* ~10px in the base spec — at 10px it collided with the circle's stroke at
|
|
95
|
+
* this scale, so it was sized down to keep the badge legible instead of
|
|
96
|
+
* cluttered.
|
|
97
|
+
*/
|
|
98
|
+
interface PausedBadgeProps {
|
|
99
|
+
label?: string;
|
|
100
|
+
style?: CSSProperties;
|
|
101
|
+
}
|
|
102
|
+
declare function PausedBadge({ label, style }: PausedBadgeProps): react.JSX.Element;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* AccountCard — the account tile used on the accounts grid: avatar + name +
|
|
106
|
+
* email, an optional PausedBadge, and a kebab menu (Pause/Resume, Delete).
|
|
107
|
+
*
|
|
108
|
+
* Figma refs: ui-ux/figma/crops/account-grid-clean.png (clean 4×2 grid),
|
|
109
|
+
* ui-ux/figma/crops/account-card-menu.png (paused card, kebab menu open).
|
|
110
|
+
* Fit level: Direct/Light — Card composition + DropdownMenu with a native
|
|
111
|
+
* red item (no custom menu styling needed).
|
|
112
|
+
*/
|
|
113
|
+
interface AccountCardProps {
|
|
114
|
+
name: string;
|
|
115
|
+
email: string;
|
|
116
|
+
avatarSrc?: string;
|
|
117
|
+
/** Shows PausedBadge next to the avatar and swaps the kebab's first item to "Resume". */
|
|
118
|
+
paused?: boolean;
|
|
119
|
+
onPause?: () => void;
|
|
120
|
+
onResume?: () => void;
|
|
121
|
+
onDelete?: () => void;
|
|
122
|
+
/** Makes the card clickable (kebab menu excluded) — e.g. open the account's sync setup. */
|
|
123
|
+
onClick?: () => void;
|
|
124
|
+
/** Small overlay badge on the avatar's corner — e.g. a provider logo. */
|
|
125
|
+
badge?: ReactNode;
|
|
126
|
+
/** Tints the avatar with the account's color token (e.g. "var(--blue-9)"). */
|
|
127
|
+
accentColor?: string;
|
|
128
|
+
style?: CSSProperties;
|
|
129
|
+
}
|
|
130
|
+
declare function AccountCard({ name, email, avatarSrc, paused, onPause, onResume, onDelete, onClick, badge, accentColor, style, }: AccountCardProps): react.JSX.Element;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* MonthGrid — the month calendar grid from the Preview card (Target/Source
|
|
134
|
+
* Calendar → Preview flow). Pure Date math, no date library: weeks start
|
|
135
|
+
* Monday (Figma starts its week on Mon), and only the leading/trailing
|
|
136
|
+
* adjacent-month days needed to complete the first and last week are
|
|
137
|
+
* rendered (not a fixed 6 rows).
|
|
138
|
+
*
|
|
139
|
+
* Fit level: Truly custom (only genuine no-Radix-equivalent gap — layout via
|
|
140
|
+
* CSS grid, no date lib).
|
|
141
|
+
* Figma refs: ui-ux/figma/crops/preview-month.png, ui-ux/figma/crops/month-card.png.
|
|
142
|
+
*/
|
|
143
|
+
interface MonthGridProps {
|
|
144
|
+
/** Any date within the month to display. */
|
|
145
|
+
month: Date;
|
|
146
|
+
/** Called with the first-of-month date when the prev/next chevrons are used. */
|
|
147
|
+
onMonthChange?: (date: Date) => void;
|
|
148
|
+
/** Days that should render an event dot (matched by calendar day, time ignored). */
|
|
149
|
+
events?: Date[];
|
|
150
|
+
/** Per-day colored dots keyed by `date.toDateString()` → CSS color tokens (max 3 shown).
|
|
151
|
+
* Takes precedence over `events` when a day has an entry. */
|
|
152
|
+
dayDots?: Map<string, string[]>;
|
|
153
|
+
/** Defaults to `new Date()`. Pass a fixed date for stable/deterministic visuals. */
|
|
154
|
+
today?: Date;
|
|
155
|
+
/** Makes day cells clickable buttons; receives the clicked date. */
|
|
156
|
+
onSelectDay?: (date: Date) => void;
|
|
157
|
+
style?: CSSProperties;
|
|
158
|
+
}
|
|
159
|
+
declare function MonthGrid({ month, onMonthChange, events, dayDots, today, onSelectDay, style, }: MonthGridProps): react.JSX.Element;
|
|
160
|
+
|
|
161
|
+
interface ToastProps {
|
|
162
|
+
msg: string;
|
|
163
|
+
color?: "green" | "red";
|
|
164
|
+
onDone: () => void;
|
|
165
|
+
durationMs?: number;
|
|
166
|
+
}
|
|
167
|
+
/** Fixed bottom-right auto-dismissing confirmation — the shared shape for
|
|
168
|
+
* "did my save work" feedback across the app (previously a one-off local
|
|
169
|
+
* component on AdminUserDetailPage only). */
|
|
170
|
+
declare function Toast({ msg, color, onDone, durationMs }: ToastProps): react.JSX.Element;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* IconTile — the app's one icon-well treatment: a bordered rounded-square
|
|
174
|
+
* tile around a feature/action/logo icon. Used for app-shortcut icons,
|
|
175
|
+
* provider/account logos, and empty-state icons alike, so every "icon in a
|
|
176
|
+
* box" in the app reads as the same component instead of one-off inline
|
|
177
|
+
* styles with drifting border/radius/fill choices.
|
|
178
|
+
*/
|
|
179
|
+
interface IconTileProps {
|
|
180
|
+
children: ReactNode;
|
|
181
|
+
/** Tile size — defaults to var(--space-7), the size used across the app. */
|
|
182
|
+
size?: string;
|
|
183
|
+
}
|
|
184
|
+
declare function IconTile({ children, size }: IconTileProps): react.JSX.Element;
|
|
185
|
+
|
|
186
|
+
interface CardFooterProps {
|
|
187
|
+
children: ReactNode;
|
|
188
|
+
justify?: "end" | "between";
|
|
189
|
+
/** Omit the top margin when the content above already ends with its own
|
|
190
|
+
* bottom margin/gap (e.g. Flex `mb`) — avoids doubled spacing. */
|
|
191
|
+
noTopMargin?: boolean;
|
|
192
|
+
/** Match the enclosing container's own padding so the negative-margin
|
|
193
|
+
* breakout lines up flush with its edges. Defaults to Card size="3"'s
|
|
194
|
+
* var(--space-5); pass the container's actual padding otherwise (e.g.
|
|
195
|
+
* a default-size Card's var(--space-3), StepCard's var(--space-4)). */
|
|
196
|
+
pad?: string;
|
|
197
|
+
/** Match the enclosing container's own corner radius so the footer's
|
|
198
|
+
* bottom corners line up. Defaults to Card size="3"+'s var(--radius-5);
|
|
199
|
+
* default-size Card (1-2) uses var(--radius-4). */
|
|
200
|
+
radius?: string;
|
|
201
|
+
}
|
|
202
|
+
/** Full-bleed gray action bar for the bottom of a Card — breaks out of the
|
|
203
|
+
* Card's own padding so it reads as a distinct footer strip, same shape as
|
|
204
|
+
* ImportCalendarsDialog's button row. Use for any Card/Dialog that ends in
|
|
205
|
+
* one or more buttons instead of a plain Separator + Flex. */
|
|
206
|
+
declare function CardFooter({ children, justify, noTopMargin, pad, radius, }: CardFooterProps): react.JSX.Element;
|
|
207
|
+
|
|
208
|
+
interface EventBlockProps {
|
|
209
|
+
title: string;
|
|
210
|
+
time: string;
|
|
211
|
+
detail?: string;
|
|
212
|
+
color: string;
|
|
213
|
+
locked?: boolean;
|
|
214
|
+
}
|
|
215
|
+
/** Solid-colored calendar-event chip — a filled block in the sync's own
|
|
216
|
+
* color with white text, matching OneCal's SYNC PREVIEW mockups. Used
|
|
217
|
+
* anywhere a real (or sample) event needs to read as "this calendar's
|
|
218
|
+
* color", not a thin accent bar + badge. */
|
|
219
|
+
declare function EventBlock({ title, time, detail, color, locked }: EventBlockProps): react.JSX.Element;
|
|
220
|
+
|
|
221
|
+
interface DataTableRowProps {
|
|
222
|
+
children: ReactNode;
|
|
223
|
+
/** Grid/flex layout for the row — e.g. `{ display: "grid", gridTemplateColumns: "2fr 1fr 1fr" }`.
|
|
224
|
+
* Column shape varies per table, so it's always supplied by the caller rather than fixed here. */
|
|
225
|
+
style?: React.CSSProperties;
|
|
226
|
+
/** Draws the row separator above every row except the first — pass `idx > 0`. */
|
|
227
|
+
showBorder?: boolean;
|
|
228
|
+
/** Makes the row a keyboard-focusable, clickable target (role="button", Enter/Space activation,
|
|
229
|
+
* amber focus ring). Omit for plain display rows (most tables — see CalendarSyncsPage, which
|
|
230
|
+
* keeps its per-cell action button interactive instead of the row). */
|
|
231
|
+
onActivate?: () => void;
|
|
232
|
+
/** Highlights the row as the current selection — only meaningful with `onActivate`. */
|
|
233
|
+
selected?: boolean;
|
|
234
|
+
className?: string;
|
|
235
|
+
"aria-label"?: string;
|
|
236
|
+
}
|
|
237
|
+
/** Shared plumbing for the dense data-table-row pattern used across the admin
|
|
238
|
+
* users/audit tables, calendar syncs list, and home activity feed: hover
|
|
239
|
+
* wash, optional keyboard-accessible selection, and the border-top-except-
|
|
240
|
+
* first-row rule. Deliberately layout-agnostic — each table's column count
|
|
241
|
+
* and widths differ (see globals.css's own `.data-table-row` comment history),
|
|
242
|
+
* so `style` carries the grid/flex shape and `children` carries the cells;
|
|
243
|
+
* this component only owns the classes and interaction/border wiring that
|
|
244
|
+
* were previously hand-copied into five separate page files. */
|
|
245
|
+
declare function DataTableRow({ children, style, showBorder, onActivate, selected, className, "aria-label": ariaLabel, }: DataTableRowProps): react.JSX.Element;
|
|
246
|
+
|
|
247
|
+
interface MetricCardProps {
|
|
248
|
+
label: string;
|
|
249
|
+
value: string;
|
|
250
|
+
delta: string;
|
|
251
|
+
deltaDir: "up" | "down" | "flat";
|
|
252
|
+
/** Which delta direction reads as "good" for this metric — e.g. "up" for
|
|
253
|
+
* revenue, "down" for error rate. Colors the delta text green/red. */
|
|
254
|
+
goodDirection: "up" | "down";
|
|
255
|
+
/** Status-dot color (top-right corner) — pass a semantic token
|
|
256
|
+
* (`var(--green-9)`, `var(--red-9)`, `var(--amber-9)`, `var(--gray-9)`). */
|
|
257
|
+
statusColor: string;
|
|
258
|
+
/** Recent-history series for the inline sparkline. */
|
|
259
|
+
sparkline: number[];
|
|
260
|
+
}
|
|
261
|
+
/** Admin/platform stat tile: label + status dot, big value, delta indicator,
|
|
262
|
+
* inline sparkline. Used for dashboard "platform health" grids. */
|
|
263
|
+
declare function MetricCard({ label, value, delta, deltaDir, goodDirection, statusColor, sparkline, }: MetricCardProps): react.JSX.Element;
|
|
264
|
+
|
|
265
|
+
interface AppCardProps {
|
|
266
|
+
href: string;
|
|
267
|
+
icon: ReactNode;
|
|
268
|
+
name: string;
|
|
269
|
+
description: string;
|
|
270
|
+
}
|
|
271
|
+
/** Workspace-shortcut tile: icon + name header, description, "Open" CTA
|
|
272
|
+
* footer. Used for the home dashboard's granted-apps grid. */
|
|
273
|
+
declare function AppCard({ href, icon, name, description }: AppCardProps): react.JSX.Element;
|
|
274
|
+
|
|
275
|
+
interface ActivityRowProps {
|
|
276
|
+
/** Short colored tag, e.g. "AUTH", "ROLE", "PROV" — matches an audit-log
|
|
277
|
+
* action code. */
|
|
278
|
+
tag: string;
|
|
279
|
+
/** Tag color (semantic token, e.g. `var(--violet-9)`). */
|
|
280
|
+
tagColor: string;
|
|
281
|
+
msg: string;
|
|
282
|
+
actor?: string;
|
|
283
|
+
timeAgo?: string;
|
|
284
|
+
timestamp: string;
|
|
285
|
+
showBorder: boolean;
|
|
286
|
+
}
|
|
287
|
+
/** Sentry-style dense activity-feed row: colored type tag, message + actor,
|
|
288
|
+
* optional relative time, and a right-aligned monospace timestamp. Built on
|
|
289
|
+
* DataTableRow for the shared hover/border plumbing. */
|
|
290
|
+
declare function ActivityRow({ tag, tagColor, msg, actor, timeAgo, timestamp, showBorder, }: ActivityRowProps): react.JSX.Element;
|
|
291
|
+
|
|
292
|
+
interface DashboardErrorCardProps {
|
|
293
|
+
onRetry: () => void;
|
|
294
|
+
/** Defaults to "Couldn't load your dashboard." */
|
|
295
|
+
message?: string;
|
|
296
|
+
}
|
|
297
|
+
/** Generic "failed to load" state: warning icon, message, Retry CTA. */
|
|
298
|
+
declare function DashboardErrorCard({ onRetry, message }: DashboardErrorCardProps): react.JSX.Element;
|
|
299
|
+
|
|
300
|
+
interface PaginationProps {
|
|
301
|
+
/** 1-based. */
|
|
302
|
+
currentPage: number;
|
|
303
|
+
totalPages: number;
|
|
304
|
+
onPageChange: (page: number) => void;
|
|
305
|
+
/** Pages shown either side of the current one. */
|
|
306
|
+
siblingCount?: number;
|
|
307
|
+
/** Adds jump-to-first / jump-to-last controls. */
|
|
308
|
+
showFirstLast?: boolean;
|
|
309
|
+
/** Radix control size. */
|
|
310
|
+
size?: "1" | "2";
|
|
311
|
+
}
|
|
312
|
+
declare function Pagination({ currentPage, totalPages, onPageChange, siblingCount, showFirstLast, size, }: PaginationProps): react.JSX.Element;
|
|
313
|
+
|
|
314
|
+
/** Radix space-scale layout widths. Originally a subset of the app's
|
|
315
|
+
* src/lib/layout-tokens.ts covering only what this package's own components
|
|
316
|
+
* reference; now also exported so consumers stop hand-rolling their own
|
|
317
|
+
* copies (arm-admin had none at all, and core-fe carries a 5-constant
|
|
318
|
+
* fork). Values must match the app's copy — see README.md's "Files
|
|
319
|
+
* duplicated from the app". */
|
|
320
|
+
declare const layout: {
|
|
321
|
+
readonly contentMax: "calc(15 * var(--space-9) + var(--space-5))";
|
|
322
|
+
readonly accountCardW: "calc(3 * var(--space-9) + var(--space-8))";
|
|
323
|
+
readonly accountCardMinH: "calc(2 * var(--space-9) - var(--space-2))";
|
|
324
|
+
readonly monthTitleMinW: "calc(3 * var(--space-9) - var(--space-1))";
|
|
325
|
+
readonly bigCalendarH: "calc(10 * var(--space-9))";
|
|
326
|
+
readonly sidebarColBasis: "calc(4 * var(--space-9) - var(--space-2))";
|
|
327
|
+
readonly sidebarColMin: "calc(3 * var(--space-9) + var(--space-6))";
|
|
328
|
+
readonly syncColMin: "calc(5 * var(--space-9))";
|
|
329
|
+
readonly syncColWide: "calc(7 * var(--space-9) + var(--space-6))";
|
|
330
|
+
readonly dialogSm: "calc(6 * var(--space-9) - var(--space-2))";
|
|
331
|
+
readonly dialogBody: "calc(5 * var(--space-9) + var(--space-7))";
|
|
332
|
+
readonly authFormMax: "calc(6 * var(--space-9) + var(--space-8))";
|
|
333
|
+
readonly brandLogoMax: "calc(6 * var(--space-9) + var(--space-8) - var(--space-1))";
|
|
334
|
+
readonly connectedAccountCardH: "calc(var(--space-9) - var(--space-1))";
|
|
335
|
+
readonly dialogMd: "calc(6 * var(--space-9) + var(--space-6))";
|
|
336
|
+
readonly dialogLg: "calc(7 * var(--space-9) - var(--space-1))";
|
|
337
|
+
readonly emptyStateMax: "calc(10 * var(--space-9))";
|
|
338
|
+
readonly emptyStateCopyMax: "calc(6 * var(--space-9))";
|
|
339
|
+
readonly providerChooserMax: "calc(6 * var(--space-9) + var(--space-6))";
|
|
340
|
+
readonly auditColTime: "calc(var(--space-9) + var(--space-2))";
|
|
341
|
+
readonly auditColAction: "calc(var(--space-9) + var(--space-5) + var(--space-1))";
|
|
342
|
+
readonly searchFieldW: "calc(3 * var(--space-9) + var(--space-5) + var(--space-1))";
|
|
343
|
+
readonly settingsGridMin: "calc(5 * var(--space-9) + var(--space-5))";
|
|
344
|
+
readonly placeholderMd: "calc(6 * var(--space-9) + var(--space-4))";
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* One heading size per level, for every `<Heading>` in the platform.
|
|
349
|
+
*
|
|
350
|
+
* Headings used to pick a Radix `size` per instance, so the same `<h1>`
|
|
351
|
+
* rendered at 14.4px in the shell, 16.2px in a remote and 18px on Home, and
|
|
352
|
+
* an `<h3>` could equal its own `<h1>` or the 12.6px body copy. The level now
|
|
353
|
+
* decides the size: pass `size={headingSize[level]}` alongside `as={level}`.
|
|
354
|
+
*
|
|
355
|
+
* Values are Radix font-size steps, so they follow the Theme's `scaling`. At
|
|
356
|
+
* the platform's 90% that is h1 21.6px, h2 18px, h3 16.2px, h4 14.4px — every
|
|
357
|
+
* level one step apart and above body text (step 2, 12.6px).
|
|
358
|
+
*/
|
|
359
|
+
declare const headingSize: {
|
|
360
|
+
readonly h1: "6";
|
|
361
|
+
readonly h2: "5";
|
|
362
|
+
readonly h3: "4";
|
|
363
|
+
readonly h4: "3";
|
|
364
|
+
};
|
|
365
|
+
type HeadingLevel = keyof typeof headingSize;
|
|
366
|
+
|
|
367
|
+
/** Duplicated from the app's src/lib/mock.ts Role type (not imported) so
|
|
368
|
+
* this package has no dependency back into the app. Keep in sync if the
|
|
369
|
+
* app's role set changes. */
|
|
370
|
+
type Role = "admin" | "operator" | "user";
|
|
371
|
+
declare const SHELL_HEADER_H = "var(--space-9)";
|
|
372
|
+
interface NavItem {
|
|
373
|
+
label: string;
|
|
374
|
+
href: string;
|
|
375
|
+
Icon: React.ComponentType<{
|
|
376
|
+
width?: number;
|
|
377
|
+
height?: number;
|
|
378
|
+
style?: React.CSSProperties;
|
|
379
|
+
}>;
|
|
380
|
+
roles?: Role[];
|
|
381
|
+
children?: NavItem[];
|
|
382
|
+
end?: boolean;
|
|
383
|
+
root?: string;
|
|
384
|
+
}
|
|
385
|
+
interface SidebarUser {
|
|
386
|
+
name: string;
|
|
387
|
+
role: Role;
|
|
388
|
+
/** Profile photo URL. Omitted or unloadable falls back to the derived
|
|
389
|
+
* initials, so a consumer with no photo on the profile payload passes
|
|
390
|
+
* nothing and keeps the previous appearance. */
|
|
391
|
+
avatarSrc?: string;
|
|
392
|
+
}
|
|
393
|
+
interface SidebarDevRole {
|
|
394
|
+
role: Role;
|
|
395
|
+
email: string;
|
|
396
|
+
label: string;
|
|
397
|
+
}
|
|
398
|
+
interface SidebarProps {
|
|
399
|
+
collapsed: boolean;
|
|
400
|
+
onToggle?: () => void;
|
|
401
|
+
onClose?: () => void;
|
|
402
|
+
/** Nav items to render — the app owns its own route table (NAV_ITEMS). */
|
|
403
|
+
items: NavItem[];
|
|
404
|
+
/** Utility/meta hrefs (Settings, Admin Portal) that pin above the identity
|
|
405
|
+
* block instead of the main scrollable list. */
|
|
406
|
+
utilityHrefs: string[];
|
|
407
|
+
/** Currently signed-in user, or null/undefined if not authenticated. */
|
|
408
|
+
user?: SidebarUser | null;
|
|
409
|
+
onSignOut: () => void;
|
|
410
|
+
/** Calendar section only drills in once the app has at least one connected
|
|
411
|
+
* account — pass false to keep the global menu (e.g. no accounts yet). */
|
|
412
|
+
hasCalendarAccounts?: boolean;
|
|
413
|
+
brandLogoExpandedSrc?: string;
|
|
414
|
+
brandLogoCollapsedSrc?: string;
|
|
415
|
+
/** Where the account menu's Help entry opens, in a new tab. Omit to leave
|
|
416
|
+
* the entry out — there is no default, because a baked-in URL ships to every
|
|
417
|
+
* consumer whether or not that address is real. */
|
|
418
|
+
helpHref?: string;
|
|
419
|
+
/** Dev-only role switcher shown in the account menu — omit to hide it
|
|
420
|
+
* entirely (e.g. in a production build or a context with no such concept). */
|
|
421
|
+
devRoles?: SidebarDevRole[];
|
|
422
|
+
onDevRoleSelect?: (email: string) => void;
|
|
423
|
+
showDevRoles?: boolean;
|
|
424
|
+
}
|
|
425
|
+
declare function Sidebar({ collapsed, onToggle, onClose, items, utilityHrefs: utilityHrefsProp, user, onSignOut, hasCalendarAccounts, brandLogoExpandedSrc, brandLogoCollapsedSrc, helpHref, devRoles, onDevRoleSelect, showDevRoles, }: SidebarProps): react.JSX.Element;
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Single source of truth for status / role / activity / audit colors.
|
|
429
|
+
*
|
|
430
|
+
* Every consumer that renders a user's role, account status or an audit row
|
|
431
|
+
* previously defined its own map inline, and those copies had already started
|
|
432
|
+
* to drift — the admin portal's audit action map went stale twice while its
|
|
433
|
+
* action vocabulary grew, and only `tsc` caught it. Import from here instead.
|
|
434
|
+
*
|
|
435
|
+
* Two color conventions live side by side, matching how Radix is consumed:
|
|
436
|
+
* - Radix accent names ("amber" | "blue" | ...) passed to <Badge color={...} />.
|
|
437
|
+
* - Raw CSS-var tokens (e.g. "var(--green-9)") used for dots, tags and rails.
|
|
438
|
+
*/
|
|
439
|
+
declare const ROLE_META: Record<Role, {
|
|
440
|
+
label: string;
|
|
441
|
+
color: "amber" | "blue" | "gray";
|
|
442
|
+
}>;
|
|
443
|
+
declare const ROLE_LABELS: Record<Role, string>;
|
|
444
|
+
/** Derived, not stored. `suspended` is an admin disabling the account;
|
|
445
|
+
* `inactive` is an approved account nobody has signed into lately. Approval
|
|
446
|
+
* state (pending / rejected) is a separate axis and gets its own badge —
|
|
447
|
+
* an account can be approved and suspended at the same time. */
|
|
448
|
+
type UserStatus = "active" | "inactive" | "suspended";
|
|
449
|
+
declare const STATUS_META: Record<UserStatus, {
|
|
450
|
+
label: string;
|
|
451
|
+
color: string;
|
|
452
|
+
}>;
|
|
453
|
+
type MetricStatus = "ok" | "warn" | "error";
|
|
454
|
+
declare const METRIC_STATUS_COLOR: Record<MetricStatus, string>;
|
|
455
|
+
type ActivityType = "auth" | "sync" | "role" | "provision" | "health" | "error";
|
|
456
|
+
declare const ACTIVITY_META: Record<ActivityType, {
|
|
457
|
+
tag: string;
|
|
458
|
+
color: string;
|
|
459
|
+
}>;
|
|
460
|
+
/** The admin backend's own vocabulary — these strings are written by
|
|
461
|
+
* `AuditService.log` and must match it exactly. `action` is a plain varchar
|
|
462
|
+
* there, not a Postgres enum, so nothing but this map and a code review stops
|
|
463
|
+
* the two drifting apart. Add here whenever a new action is logged. */
|
|
464
|
+
type AuditAction = "USER_UPDATED" | "USER_DISABLED" | "USER_ENABLED" | "USER_APPROVED" | "USER_REJECTED" | "SIGNUP_NOTIFICATIONS_ON" | "SIGNUP_NOTIFICATIONS_OFF" | "APPROVAL_EMAIL_RESENT" | "USER_DELETED" | "ADMIN_GRANTED" | "ADMIN_REVOKED" | "ADMIN_ROLE_CHANGED" | "SESSION_REVOKED" | "APP_GRANTED" | "APP_REVOKED";
|
|
465
|
+
/** `badge` is for <Badge color={...} />, `tag`/`color` for the compact
|
|
466
|
+
* monospace tag used in per-user activity lists.
|
|
467
|
+
*
|
|
468
|
+
* `color` is step **11**, not step 9. Step 9 is Radix's solid-background step
|
|
469
|
+
* and was never a text colour: used as one it gave the amber UPD tag 1.58:1 on
|
|
470
|
+
* white, teal 3.07:1 and orange 2.97:1 — the amber one close to invisible
|
|
471
|
+
* rather than merely low-contrast, at 10.8px where the requirement is
|
|
472
|
+
* strictest. Step 11 is the scale's low-contrast *text* step and clears 4.5:1
|
|
473
|
+
* for every scale used here (4.51-6.17 on white).
|
|
474
|
+
*
|
|
475
|
+
* These tags render inside a Card, so white is the surface that matters. On a
|
|
476
|
+
* #F6F6F6 surface amber, teal, green and orange land at 4.17-4.36 — under AA —
|
|
477
|
+
* so do not move this tag onto the page background without re-measuring.
|
|
478
|
+
*
|
|
479
|
+
* `badge` is untouched: it feeds Radix's own <Badge>, which pairs its own text
|
|
480
|
+
* and background steps. */
|
|
481
|
+
declare const AUDIT_ACTION_META: Record<AuditAction, {
|
|
482
|
+
label: string;
|
|
483
|
+
tag: string;
|
|
484
|
+
badge: "amber" | "gray" | "yellow" | "red" | "green";
|
|
485
|
+
color: string;
|
|
486
|
+
}>;
|
|
487
|
+
/** Falls back rather than throwing: the backend can log an action this build
|
|
488
|
+
* has never heard of, and an unknown row must still render. */
|
|
489
|
+
declare function auditActionMeta(action: string): {
|
|
490
|
+
label: string;
|
|
491
|
+
tag: string;
|
|
492
|
+
badge: "amber" | "gray" | "yellow" | "red" | "green";
|
|
493
|
+
color: string;
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
declare function AuthCard({ children }: {
|
|
497
|
+
children: React.ReactNode;
|
|
498
|
+
}): react.JSX.Element;
|
|
499
|
+
|
|
500
|
+
declare function BrandPanel(): react.JSX.Element;
|
|
501
|
+
|
|
502
|
+
declare function GoogleIcon(): react.JSX.Element;
|
|
503
|
+
|
|
504
|
+
declare function MicrosoftIcon(): react.JSX.Element;
|
|
505
|
+
|
|
506
|
+
declare function OtpInput({ value, onChange, disabled }: {
|
|
507
|
+
value: string;
|
|
508
|
+
onChange: (v: string) => void;
|
|
509
|
+
disabled?: boolean;
|
|
510
|
+
}): react.JSX.Element;
|
|
511
|
+
|
|
512
|
+
interface OtpVerifyStepProps {
|
|
513
|
+
email: string;
|
|
514
|
+
title: React.ReactNode;
|
|
515
|
+
subtitle: React.ReactNode;
|
|
516
|
+
code: string;
|
|
517
|
+
onCodeChange: (value: string) => void;
|
|
518
|
+
otpDevHint: string | null;
|
|
519
|
+
error: string | null;
|
|
520
|
+
/** Optional inline recovery action shown next to `error` — for errors
|
|
521
|
+
* whose message describes a fix ("Start the signup process again") but
|
|
522
|
+
* that otherwise have no button actually doing it. */
|
|
523
|
+
errorAction?: {
|
|
524
|
+
label: string;
|
|
525
|
+
onClick: () => void;
|
|
526
|
+
};
|
|
527
|
+
busy: boolean;
|
|
528
|
+
otpExpiresAt: number | null;
|
|
529
|
+
otpSecondsLeft: number;
|
|
530
|
+
resendCooldown: number;
|
|
531
|
+
onResend: () => void;
|
|
532
|
+
onUseDifferentEmail: () => void;
|
|
533
|
+
}
|
|
534
|
+
declare function OtpVerifyStep({ email, title, subtitle, code, onCodeChange, otpDevHint, error, errorAction, busy, otpExpiresAt, otpSecondsLeft, resendCooldown, onResend, onUseDifferentEmail, }: OtpVerifyStepProps): react.JSX.Element;
|
|
535
|
+
|
|
536
|
+
/** Duplicated from the app's src/lib/mock.ts (not imported) so this package
|
|
537
|
+
* has no dependency back into the app. Keep in sync if the app's type changes. */
|
|
538
|
+
type CalendarProvider = "google" | "microsoft";
|
|
539
|
+
/** Renders the correct provider logo for a calendar account. Used in the
|
|
540
|
+
* provider chooser, consent screen, and per-account badges so a Google account
|
|
541
|
+
* and a Microsoft account are always distinguishable at a glance (color tells
|
|
542
|
+
* you WHICH account; this icon tells you WHICH provider). */
|
|
543
|
+
declare function ProviderIcon({ provider }: {
|
|
544
|
+
provider: CalendarProvider;
|
|
545
|
+
}): react.JSX.Element;
|
|
546
|
+
/** Human-readable provider names for consent copy and the chooser. */
|
|
547
|
+
declare const PROVIDER_LABEL: Record<CalendarProvider, string>;
|
|
548
|
+
|
|
549
|
+
type TopbarTitleRow = [
|
|
550
|
+
prefix: string,
|
|
551
|
+
section: string,
|
|
552
|
+
sectionHref: string,
|
|
553
|
+
page: string,
|
|
554
|
+
exact?: boolean
|
|
555
|
+
];
|
|
556
|
+
type TopbarAdminTitleRow = [prefix: string, page: string];
|
|
557
|
+
interface TopbarProps {
|
|
558
|
+
onSearchOpen: () => void;
|
|
559
|
+
onMenuOpen: () => void;
|
|
560
|
+
showMenu: boolean;
|
|
561
|
+
/** Override the breadcrumb route tables — defaults to arm-ui's own routes. */
|
|
562
|
+
titles?: TopbarTitleRow[];
|
|
563
|
+
adminTitles?: TopbarAdminTitleRow[];
|
|
564
|
+
}
|
|
565
|
+
declare function Topbar({ onSearchOpen, onMenuOpen, showMenu, titles, adminTitles, }: TopbarProps): react.JSX.Element;
|
|
566
|
+
|
|
567
|
+
type SearchResultType = "app" | "people" | "page";
|
|
568
|
+
interface SearchResult {
|
|
569
|
+
id: string;
|
|
570
|
+
title: string;
|
|
571
|
+
subtitle: string;
|
|
572
|
+
href: string;
|
|
573
|
+
type: SearchResultType;
|
|
574
|
+
}
|
|
575
|
+
interface SearchOverlayProps {
|
|
576
|
+
open: boolean;
|
|
577
|
+
onClose: () => void;
|
|
578
|
+
/** The searchable pool for the current user — the app owns its own
|
|
579
|
+
* content/routes and any role-based filtering before passing this in. */
|
|
580
|
+
results: SearchResult[];
|
|
581
|
+
onSelectResult: (result: SearchResult) => void;
|
|
582
|
+
title?: string;
|
|
583
|
+
placeholder?: string;
|
|
584
|
+
}
|
|
585
|
+
declare function SearchOverlay({ open, onClose, results: resultPool, onSelectResult, title, placeholder, }: SearchOverlayProps): react.JSX.Element;
|
|
586
|
+
|
|
587
|
+
/** Duplicated from the app's src/lib/calendar-mock.ts (not imported) so this
|
|
588
|
+
* package has no dependency back into the app. Keep in sync if the app's
|
|
589
|
+
* calendar data model changes. */
|
|
590
|
+
interface CalendarAccountCalendar {
|
|
591
|
+
id: string;
|
|
592
|
+
accountId: string;
|
|
593
|
+
name: string;
|
|
594
|
+
isPrimary: boolean;
|
|
595
|
+
/** Drives the import dialog's color dot, the legend, and month/week dots. */
|
|
596
|
+
colorToken: string;
|
|
597
|
+
}
|
|
598
|
+
interface CalendarAccount {
|
|
599
|
+
id: string;
|
|
600
|
+
provider: CalendarProvider;
|
|
601
|
+
email: string;
|
|
602
|
+
displayName: string;
|
|
603
|
+
initials: string;
|
|
604
|
+
authStatus: "active" | "reauth" | "failed";
|
|
605
|
+
calendars: CalendarAccountCalendar[];
|
|
606
|
+
}
|
|
607
|
+
declare function findCalendar(accounts: CalendarAccount[], calendarId: string): {
|
|
608
|
+
account: CalendarAccount;
|
|
609
|
+
calendar: CalendarAccountCalendar;
|
|
610
|
+
} | undefined;
|
|
611
|
+
interface AvailabilityBlock {
|
|
612
|
+
id: string;
|
|
613
|
+
calendarId: string;
|
|
614
|
+
accountId: string;
|
|
615
|
+
/** 0 = Monday … 6 = Sunday (week-relative) */
|
|
616
|
+
day: number;
|
|
617
|
+
startHour: number;
|
|
618
|
+
startMinute: number;
|
|
619
|
+
endHour: number;
|
|
620
|
+
endMinute: number;
|
|
621
|
+
title: string;
|
|
622
|
+
description?: string;
|
|
623
|
+
location?: string;
|
|
624
|
+
/** Marked private at the source — always renders as the sync's tag alone,
|
|
625
|
+
* regardless of that sync's field toggles. */
|
|
626
|
+
isPrivate: boolean;
|
|
627
|
+
}
|
|
628
|
+
interface DatedAvailabilityBlock extends AvailabilityBlock {
|
|
629
|
+
date: Date;
|
|
630
|
+
}
|
|
631
|
+
interface ResolvedBlock extends DatedAvailabilityBlock {
|
|
632
|
+
/** True when this occurrence is showing on a calendar it wasn't natively
|
|
633
|
+
* created on (i.e. merged in via a sync), as opposed to its home calendar. */
|
|
634
|
+
isMerged: boolean;
|
|
635
|
+
}
|
|
636
|
+
type SyncStatus = "synced" | "syncing" | "error";
|
|
637
|
+
interface CalendarSync {
|
|
638
|
+
id: string;
|
|
639
|
+
name: string;
|
|
640
|
+
targetCalendarId: string;
|
|
641
|
+
sourceCalendarIds: string[];
|
|
642
|
+
status: SyncStatus;
|
|
643
|
+
lastSyncedLabel?: string;
|
|
644
|
+
showTitle: boolean;
|
|
645
|
+
showDescription: boolean;
|
|
646
|
+
showLocation: boolean;
|
|
647
|
+
/** The sync's tag — the label its events carry on the target calendar.
|
|
648
|
+
* Optional so existing callers keep compiling; treat an absent value as the
|
|
649
|
+
* default, "Busy". */
|
|
650
|
+
tagLabel?: string;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
interface CalendarDayHeaderProps extends HeaderProps {
|
|
654
|
+
/** "Today" reference for the filled-circle marker. Defaults to the real
|
|
655
|
+
* current date — pass a fixed date for demo/mock consistency. */
|
|
656
|
+
today?: Date;
|
|
657
|
+
}
|
|
658
|
+
/** Week-view column header — replaces RBC's plain "22 Mon" label with a
|
|
659
|
+
* weekday caption + a filled amber circle on today's date number, matching
|
|
660
|
+
* the OneCal reference's today marker instead of the near-invisible
|
|
661
|
+
* `.rbc-today` background wash. */
|
|
662
|
+
declare function CalendarDayHeader({ date, today }: CalendarDayHeaderProps): react.JSX.Element;
|
|
663
|
+
|
|
664
|
+
/** OneCal-style flat calendar list (logo + name/email + control). */
|
|
665
|
+
declare function CalendarPickList({ accounts, mode, sourceCalendarIds, targetCalendarId, takenSourceIds, onToggleSource, onSelectTarget, fill, }: {
|
|
666
|
+
accounts: CalendarAccount[];
|
|
667
|
+
mode: "sources" | "target";
|
|
668
|
+
sourceCalendarIds: string[];
|
|
669
|
+
targetCalendarId: string | null;
|
|
670
|
+
takenSourceIds: Set<string>;
|
|
671
|
+
onToggleSource: (calendarId: string) => void;
|
|
672
|
+
onSelectTarget: (calendarId: string) => void;
|
|
673
|
+
/** Fill parent and scroll internally (step 2 dual lists). */
|
|
674
|
+
fill?: boolean;
|
|
675
|
+
}): react.JSX.Element;
|
|
676
|
+
|
|
677
|
+
/** DS-native replacement for react-big-calendar's default toolbar — pill nav
|
|
678
|
+
* arrows + Today button (left), label (center), Week/Month switch (right).
|
|
679
|
+
* All logic stays RBC's; this only swaps the rendered chrome.
|
|
680
|
+
* Props typed loosely (any event/resource) since RBC's Components<TEvent>
|
|
681
|
+
* requires the toolbar to accept ToolbarProps<TEvent>, not our own event type. */
|
|
682
|
+
declare function CalendarToolbar({ label, view, onNavigate, onView, }: ToolbarProps<object, object>): react.JSX.Element;
|
|
683
|
+
|
|
684
|
+
declare const PROVIDER_META: Record<CalendarProvider, {
|
|
685
|
+
label: string;
|
|
686
|
+
description: string;
|
|
687
|
+
}>;
|
|
688
|
+
/** Provider connect buttons — bordered, spaced action rows with hover / press /
|
|
689
|
+
* focus / connecting states (`.provider-choice` in globals.css). */
|
|
690
|
+
declare function ConnectProviderList({ connectingProvider, failedProvider, exhausted, onConnect, }: {
|
|
691
|
+
connectingProvider: CalendarProvider | null;
|
|
692
|
+
failedProvider: CalendarProvider | null;
|
|
693
|
+
/** True when the failure is "no more mock accounts for this provider" —
|
|
694
|
+
* not a real error, so Retry can't help and the copy should say so. */
|
|
695
|
+
exhausted?: boolean;
|
|
696
|
+
onConnect: (provider: CalendarProvider) => void;
|
|
697
|
+
}): react.JSX.Element;
|
|
698
|
+
|
|
699
|
+
/** Compact horizontal connected-account card — fills its grid cell (max 4 / row). */
|
|
700
|
+
declare function ConnectedAccountCard({ account, onRemove, onReconnect, onClick, }: {
|
|
701
|
+
account: CalendarAccount;
|
|
702
|
+
onRemove: () => void;
|
|
703
|
+
onReconnect?: () => void;
|
|
704
|
+
/** Opens account detail (calendars) — kebab clicks do not fire this. */
|
|
705
|
+
onClick?: () => void;
|
|
706
|
+
}): react.JSX.Element;
|
|
707
|
+
|
|
708
|
+
interface EmptyCardProps {
|
|
709
|
+
icon: ReactNode;
|
|
710
|
+
title: string;
|
|
711
|
+
description?: string;
|
|
712
|
+
action?: ReactNode;
|
|
713
|
+
/**
|
|
714
|
+
* Heading level for `title`. Defaults to `h2`.
|
|
715
|
+
*
|
|
716
|
+
* Radix's `Heading` renders an `h1` when given no `as`, which is what this
|
|
717
|
+
* component did — so every empty state emitted a second top-level heading
|
|
718
|
+
* underneath the shell's own page-title `h1`. A screen-reader user
|
|
719
|
+
* navigating by heading heard "Security", then "Nobody is suspended", as two
|
|
720
|
+
* peers. `h2` is right for the common case, because the shell owns the `h1`
|
|
721
|
+
* on every page this renders inside.
|
|
722
|
+
*
|
|
723
|
+
* It stays configurable because this also renders as a generic centered
|
|
724
|
+
* message — a 403, an unbuilt section — where the surrounding outline may
|
|
725
|
+
* differ.
|
|
726
|
+
*/
|
|
727
|
+
headingAs?: "h1" | "h2" | "h3" | "h4";
|
|
728
|
+
}
|
|
729
|
+
/** Cardless centered empty state — icon, heading, copy, action, no border/
|
|
730
|
+
* background/shadow, matching Vercel's flat "Continue to X" / "Connect a
|
|
731
|
+
* calendar" pattern (see ConnectProviderRows, which uses the same shape)
|
|
732
|
+
* instead of a bordered box floating in the page. */
|
|
733
|
+
declare function EmptyCard({ icon, title, description, action, headingAs, }: EmptyCardProps): react.JSX.Element;
|
|
734
|
+
|
|
735
|
+
interface ImportCalendarsDialogProps {
|
|
736
|
+
/** Account catalog whose calendars are offered. Null closes the dialog. */
|
|
737
|
+
account: CalendarAccount | null;
|
|
738
|
+
onOpenChange: (open: boolean) => void;
|
|
739
|
+
/** Called with checked calendar ids when the user confirms. */
|
|
740
|
+
onImport: (selectedCalendarIds: string[]) => void;
|
|
741
|
+
/** Pre-checked calendar ids (manage mode). Defaults to all calendars on `account`. */
|
|
742
|
+
initiallySelectedIds?: string[];
|
|
743
|
+
/**
|
|
744
|
+
* Calendars whose checkbox cannot be changed — the caller has a rule that
|
|
745
|
+
* forbids it, such as a sync depending on the calendar.
|
|
746
|
+
*
|
|
747
|
+
* The row keeps its current state and still counts toward the result — it
|
|
748
|
+
* simply cannot be changed. Without this a caller can only disable every row
|
|
749
|
+
* or none, so a row looks freely tickable right up to the moment the user is
|
|
750
|
+
* told no.
|
|
751
|
+
*
|
|
752
|
+
* Rendered as `data-disabled="true"`, which the package's own
|
|
753
|
+
* `.calendar-picker-row` rules already style.
|
|
754
|
+
*/
|
|
755
|
+
disabledIds?: string[];
|
|
756
|
+
/** Shown beside each disabled row, saying why it can't be changed. */
|
|
757
|
+
disabledReason?: string;
|
|
758
|
+
title?: string;
|
|
759
|
+
description?: string;
|
|
760
|
+
confirmLabel?: string;
|
|
761
|
+
}
|
|
762
|
+
/** Choose / change which calendars belong to a connected account — OneCal
|
|
763
|
+
* import step; also reused from the account detail popup to edit selection. */
|
|
764
|
+
declare function ImportCalendarsDialog({ account, onOpenChange, onImport, initiallySelectedIds, disabledIds, disabledReason, title, description, confirmLabel, }: ImportCalendarsDialogProps): react.JSX.Element;
|
|
765
|
+
|
|
766
|
+
/** The stand-in event the preview transforms. Not the user's data — see
|
|
767
|
+
* `SyncPreviewRailProps.sampleEvent`. */
|
|
768
|
+
interface SyncPreviewSampleEvent {
|
|
769
|
+
title: string;
|
|
770
|
+
time: string;
|
|
771
|
+
location: string;
|
|
772
|
+
description: string;
|
|
773
|
+
}
|
|
774
|
+
interface SyncPreviewRailProps {
|
|
775
|
+
hasSources: boolean;
|
|
776
|
+
hasTarget: boolean;
|
|
777
|
+
sourceLabel?: string;
|
|
778
|
+
targetLabel?: string;
|
|
779
|
+
showTitle: boolean;
|
|
780
|
+
showDescription: boolean;
|
|
781
|
+
showLocation: boolean;
|
|
782
|
+
/**
|
|
783
|
+
* The sync's tag — the label its blocker events carry on the target calendar.
|
|
784
|
+
* Shown on its own when titles are hidden, and appended to the title when
|
|
785
|
+
* they are shown. Defaults to "Busy" for a caller that has no tag to pass.
|
|
786
|
+
*/
|
|
787
|
+
tagLabel?: string;
|
|
788
|
+
/**
|
|
789
|
+
* CSS colour the posted block is painted, matching whatever colour the sync
|
|
790
|
+
* writes its events in on the target calendar. Omitted keeps the rail's own
|
|
791
|
+
* amber, which is what a sync that has chosen no colour actually gets — the
|
|
792
|
+
* calendar's default.
|
|
793
|
+
*
|
|
794
|
+
* A colour, not a provider's colour *id*: this library cannot map Google's
|
|
795
|
+
* palette (or anyone's) without depending on a backend, so the caller
|
|
796
|
+
* resolves the id and passes the result.
|
|
797
|
+
*/
|
|
798
|
+
accentColor?: string;
|
|
799
|
+
/**
|
|
800
|
+
* The stand-in event the preview transforms. It is illustrative, never the
|
|
801
|
+
* user's real data — override it to match your product's vocabulary.
|
|
802
|
+
*
|
|
803
|
+
* The rail always labels it as an example: an unannounced fabricated event
|
|
804
|
+
* reads as stray fixture data in a real app, which is exactly how this was
|
|
805
|
+
* first reported.
|
|
806
|
+
*/
|
|
807
|
+
sampleEvent?: SyncPreviewSampleEvent;
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Competitor-style SYNC PREVIEW (OneCal):
|
|
811
|
+
* - Source always shows the original event (never rewritten by field toggles).
|
|
812
|
+
* - Target shows the single block we post — title/location/description follow
|
|
813
|
+
* sync settings, and its title always carries the sync's tag (the tag alone
|
|
814
|
+
* when titles are off, `Gym - (Busy)` when they are on).
|
|
815
|
+
*/
|
|
816
|
+
declare function SyncPreviewRail({ hasSources, hasTarget, sourceLabel, targetLabel, showTitle, showDescription, showLocation, tagLabel, accentColor, sampleEvent, }: SyncPreviewRailProps): react.JSX.Element;
|
|
817
|
+
|
|
818
|
+
/** Guided first-run stepper on /calendar — OneCal numbered steps, our DS. */
|
|
819
|
+
declare function OnboardingStepper({ current }: {
|
|
820
|
+
current: number;
|
|
821
|
+
}): react.JSX.Element;
|
|
822
|
+
/** @deprecated Prefer OnboardingStepper. */
|
|
823
|
+
declare function OnboardingStepDots({ current, total }: {
|
|
824
|
+
current: number;
|
|
825
|
+
total?: number;
|
|
826
|
+
}): react.JSX.Element;
|
|
827
|
+
|
|
828
|
+
interface MiniMonthPickerProps {
|
|
829
|
+
cursor: Date;
|
|
830
|
+
onSelect: (d: Date) => void;
|
|
831
|
+
/** "Today" reference for the amber-ring marker. Defaults to the real
|
|
832
|
+
* current date — pass a fixed date for demo/mock consistency. */
|
|
833
|
+
today?: Date;
|
|
834
|
+
}
|
|
835
|
+
/** Compact date-jump picker for the calendar sidebar — OneCal-style layout
|
|
836
|
+
* (month nav + 7-col day grid, selected day filled), rebuilt on our own
|
|
837
|
+
* tokens/colors (amber selection, not blue). Clicking a day jumps the main
|
|
838
|
+
* grid's cursor to that date. */
|
|
839
|
+
declare function MiniMonthPicker({ cursor, onSelect, today }: MiniMonthPickerProps): react.JSX.Element;
|
|
840
|
+
|
|
841
|
+
interface WizardStepMeta {
|
|
842
|
+
n: string;
|
|
843
|
+
title: string;
|
|
844
|
+
description: string;
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* Full-width OneCal-style stepper.
|
|
848
|
+
* Layout per segment: [circle] title / description — generous padding so
|
|
849
|
+
* labels never collapse into the badge or each other.
|
|
850
|
+
*/
|
|
851
|
+
declare function WizardStepper({ steps, current, }: {
|
|
852
|
+
steps: readonly WizardStepMeta[];
|
|
853
|
+
current: number;
|
|
854
|
+
}): react.JSX.Element;
|
|
855
|
+
|
|
856
|
+
interface AccountCalendarsDialogProps {
|
|
857
|
+
/** The account to show, resolved by the app — null closes the dialog. */
|
|
858
|
+
account: CalendarAccount | null;
|
|
859
|
+
/** The account's full available-calendars catalog (may include calendars
|
|
860
|
+
* not currently imported) — used by "Change calendars". */
|
|
861
|
+
catalog: CalendarAccount | null;
|
|
862
|
+
onOpenChange: (open: boolean) => void;
|
|
863
|
+
onRemoveCalendar: (account: CalendarAccount, calendar: CalendarAccountCalendar) => void;
|
|
864
|
+
onSaveCalendars: (account: CalendarAccount, selectedCalendars: CalendarAccountCalendar[]) => void;
|
|
865
|
+
onReconnect?: (accountId: string) => void;
|
|
866
|
+
}
|
|
867
|
+
/** Account detail popup — view calendars, remove one, or change which are imported. */
|
|
868
|
+
declare function AccountCalendarsDialog({ account, catalog, onOpenChange, onRemoveCalendar, onSaveCalendars, onReconnect, }: AccountCalendarsDialogProps): react.JSX.Element;
|
|
869
|
+
|
|
870
|
+
interface BigCalendarViewProps {
|
|
871
|
+
blocks: ResolvedBlock[];
|
|
872
|
+
view: "week" | "month";
|
|
873
|
+
onViewChange: (v: "week" | "month") => void;
|
|
874
|
+
date: Date;
|
|
875
|
+
onNavigate: (d: Date) => void;
|
|
876
|
+
/** Connected accounts — used to resolve each block's calendar color. */
|
|
877
|
+
accounts: CalendarAccount[];
|
|
878
|
+
/** "Today" reference for RBC's own now-marker and CalendarDayHeader's
|
|
879
|
+
* circle. Defaults to the real current date — pass a fixed date for
|
|
880
|
+
* demo/mock consistency (RBC's own today and this component's header
|
|
881
|
+
* must agree, or two conflicting "today" indicators appear). */
|
|
882
|
+
today?: Date;
|
|
883
|
+
}
|
|
884
|
+
/** Real hour-grid week/month calendar via react-big-calendar (React 19
|
|
885
|
+
* compatible), restyled with our Radix tokens instead of its default CSS —
|
|
886
|
+
* see big-calendar-overrides.css. Renders our own event card (title, time
|
|
887
|
+
* range, location) via `components.event`, colored per calendar via
|
|
888
|
+
* `eventPropGetter`. */
|
|
889
|
+
declare function BigCalendarView({ blocks, view, onViewChange, date, onNavigate, accounts, today, }: BigCalendarViewProps): react.JSX.Element;
|
|
890
|
+
|
|
891
|
+
interface SyncDetailsDialogProps {
|
|
892
|
+
sync: CalendarSync | null;
|
|
893
|
+
/** Connected accounts — used to resolve source/target calendar names. */
|
|
894
|
+
accounts: CalendarAccount[];
|
|
895
|
+
onOpenChange: (open: boolean) => void;
|
|
896
|
+
onEdit: (syncId: string) => void;
|
|
897
|
+
}
|
|
898
|
+
/** OneCal-style View Details — flat label/value summary of sync config. */
|
|
899
|
+
declare function SyncDetailsDialog({ sync, accounts, onOpenChange, onEdit }: SyncDetailsDialogProps): react.JSX.Element;
|
|
900
|
+
|
|
901
|
+
interface UseConnectAccountOptions {
|
|
902
|
+
/** Currently connected accounts — passed to `connectProvider` so it can
|
|
903
|
+
* discover an account not already connected. */
|
|
904
|
+
accounts: CalendarAccount[];
|
|
905
|
+
/** Performs the actual "discover an account for this provider" round
|
|
906
|
+
* trip (real OAuth flow in a real app; the app's own mock/API layer
|
|
907
|
+
* today). Resolves null when no more accounts are available for that
|
|
908
|
+
* provider — not an error, `exhausted` distinguishes the two. */
|
|
909
|
+
connectProvider: (provider: CalendarProvider, connectedAccountIds: string[]) => Promise<CalendarAccount | null>;
|
|
910
|
+
/** Called once the user confirms which calendars to import for the
|
|
911
|
+
* newly-discovered account. */
|
|
912
|
+
onAccountAdded: (account: CalendarAccount) => void;
|
|
913
|
+
/** Called after `onAccountAdded` — e.g. navigate to the accounts list. */
|
|
914
|
+
onImported?: () => void;
|
|
915
|
+
}
|
|
916
|
+
/** Shared "discover account → import calendars" flow behind connecting a
|
|
917
|
+
* provider. Click a provider → brief spinner (no separate consent page) →
|
|
918
|
+
* ImportCalendarsDialog opens with that account's calendars → confirming
|
|
919
|
+
* adds the account and calls `onImported`. */
|
|
920
|
+
declare function useConnectAccount({ accounts, connectProvider, onAccountAdded, onImported }: UseConnectAccountOptions): {
|
|
921
|
+
connectingProvider: CalendarProvider | null;
|
|
922
|
+
pendingAccount: CalendarAccount | null;
|
|
923
|
+
failedProvider: CalendarProvider | null;
|
|
924
|
+
exhausted: boolean;
|
|
925
|
+
connect: (provider: CalendarProvider) => void;
|
|
926
|
+
confirmImport: (selectedCalendarIds: string[]) => void;
|
|
927
|
+
cancelImport: () => void;
|
|
928
|
+
dismissError: () => void;
|
|
929
|
+
};
|
|
930
|
+
|
|
931
|
+
interface AddAccountMenuProps extends UseConnectAccountOptions {
|
|
932
|
+
variant?: "button" | "tile";
|
|
933
|
+
/** Optional custom trigger; overrides `variant`. Must be a single element. */
|
|
934
|
+
trigger?: ReactNode;
|
|
935
|
+
}
|
|
936
|
+
/** "+ Connect Account" — button or dashed tile; opens provider picker then
|
|
937
|
+
* ImportCalendarsDialog. Trigger must be a single React element (Radix
|
|
938
|
+
* Themes DropdownMenu.Trigger always uses asChild). */
|
|
939
|
+
declare function AddAccountMenu({ variant, trigger, accounts, connectProvider, onAccountAdded, onImported, }: AddAccountMenuProps): react.JSX.Element;
|
|
940
|
+
|
|
941
|
+
type ConnectProviderRowsProps = UseConnectAccountOptions;
|
|
942
|
+
/** Connect-first UI — used on Manage Syncs (section home) and Accounts when
|
|
943
|
+
* no accounts are connected yet. Fills the content slot and centers as one
|
|
944
|
+
* composition; inner spacing matches Home empty cards (`py="6"`, `gap="3"`). */
|
|
945
|
+
declare function ConnectProviderRows({ accounts, connectProvider, onAccountAdded, onImported }: ConnectProviderRowsProps): react.JSX.Element;
|
|
946
|
+
|
|
947
|
+
interface CalendarMergedViewProps {
|
|
948
|
+
accounts: CalendarAccount[];
|
|
949
|
+
view: "week" | "month";
|
|
950
|
+
setView: (v: "week" | "month") => void;
|
|
951
|
+
hideClones: boolean;
|
|
952
|
+
setHideClones: (v: boolean) => void;
|
|
953
|
+
/** Union of source calendar ids across all syncs, excluding paused accounts. */
|
|
954
|
+
mergedCalendarIds: Set<string>;
|
|
955
|
+
/** mergedCalendarIds minus the user's legend hide toggles. */
|
|
956
|
+
visibleCalendarIds: Set<string>;
|
|
957
|
+
toggleCalendarVisible: (calendarId: string) => void;
|
|
958
|
+
getVisibleBlocksInRange: (start: Date, end: Date) => ResolvedBlock[];
|
|
959
|
+
/** "Manage accounts" link at the bottom of the legend rail. */
|
|
960
|
+
manageAccountsHref: string;
|
|
961
|
+
/** "Today" reference — defaults to the real current date; pass a fixed
|
|
962
|
+
* date for demo/mock consistency (also forwarded to BigCalendarView so
|
|
963
|
+
* the two don't disagree on what "today" is). */
|
|
964
|
+
today?: Date;
|
|
965
|
+
}
|
|
966
|
+
/** OneCal Calendar View chrome for a read-only merged grid — left rail
|
|
967
|
+
* (mini month picker + account-grouped visibility legend + hide synced +
|
|
968
|
+
* manage) + week/month hour grid. All calendar data and app navigation are
|
|
969
|
+
* supplied by the caller; this component owns only its own UI state
|
|
970
|
+
* (cursor date, collapsed account groups, narrow-viewport sidebar toggle). */
|
|
971
|
+
declare function CalendarMergedView({ accounts, view, setView, hideClones, setHideClones, mergedCalendarIds, visibleCalendarIds, toggleCalendarVisible, getVisibleBlocksInRange, manageAccountsHref, today, }: CalendarMergedViewProps): react.JSX.Element;
|
|
972
|
+
|
|
973
|
+
declare const colors: {
|
|
974
|
+
readonly primary: {
|
|
975
|
+
readonly 50: "#fef7e6";
|
|
976
|
+
readonly 100: "#fdecc0";
|
|
977
|
+
readonly 200: "#fbd886";
|
|
978
|
+
readonly 300: "#f9c44c";
|
|
979
|
+
readonly 400: "#f7b01f";
|
|
980
|
+
readonly 500: "#F9BF3B";
|
|
981
|
+
readonly 600: "#e6a82d";
|
|
982
|
+
readonly 700: "#cc8f1f";
|
|
983
|
+
readonly 800: "#b37611";
|
|
984
|
+
readonly 900: "#995d03";
|
|
985
|
+
};
|
|
986
|
+
readonly secondary: {
|
|
987
|
+
readonly 50: "#f8fafc";
|
|
988
|
+
readonly 100: "#f1f5f9";
|
|
989
|
+
readonly 200: "#e2e8f0";
|
|
990
|
+
readonly 300: "#cbd5e1";
|
|
991
|
+
readonly 400: "#94a3b8";
|
|
992
|
+
readonly 500: "#64748b";
|
|
993
|
+
readonly 600: "#475569";
|
|
994
|
+
readonly 700: "#334155";
|
|
995
|
+
readonly 800: "#1e293b";
|
|
996
|
+
readonly 900: "#0f172a";
|
|
997
|
+
};
|
|
998
|
+
readonly success: {
|
|
999
|
+
readonly 50: "#f0fdf4";
|
|
1000
|
+
readonly 100: "#dcfce7";
|
|
1001
|
+
readonly 200: "#bbf7d0";
|
|
1002
|
+
readonly 300: "#86efac";
|
|
1003
|
+
readonly 400: "#4ade80";
|
|
1004
|
+
readonly 500: "#22c55e";
|
|
1005
|
+
readonly 600: "#16a34a";
|
|
1006
|
+
readonly 700: "#15803d";
|
|
1007
|
+
readonly 800: "#166534";
|
|
1008
|
+
readonly 900: "#14532d";
|
|
1009
|
+
};
|
|
1010
|
+
readonly error: {
|
|
1011
|
+
readonly 50: "#fef2f2";
|
|
1012
|
+
readonly 100: "#fee2e2";
|
|
1013
|
+
readonly 200: "#fecaca";
|
|
1014
|
+
readonly 300: "#fca5a5";
|
|
1015
|
+
readonly 400: "#f87171";
|
|
1016
|
+
readonly 500: "#ef4444";
|
|
1017
|
+
readonly 600: "#dc2626";
|
|
1018
|
+
readonly 700: "#b91c1c";
|
|
1019
|
+
readonly 800: "#991b1b";
|
|
1020
|
+
readonly 900: "#7f1d1d";
|
|
1021
|
+
};
|
|
1022
|
+
readonly warning: {
|
|
1023
|
+
readonly 50: "#fffbeb";
|
|
1024
|
+
readonly 100: "#fef3c7";
|
|
1025
|
+
readonly 200: "#fde68a";
|
|
1026
|
+
readonly 300: "#fcd34d";
|
|
1027
|
+
readonly 400: "#fbbf24";
|
|
1028
|
+
readonly 500: "#f59e0b";
|
|
1029
|
+
readonly 600: "#d97706";
|
|
1030
|
+
readonly 700: "#b45309";
|
|
1031
|
+
readonly 800: "#92400e";
|
|
1032
|
+
readonly 900: "#78350f";
|
|
1033
|
+
};
|
|
1034
|
+
readonly info: {
|
|
1035
|
+
readonly 50: "#eff6ff";
|
|
1036
|
+
readonly 100: "#dbeafe";
|
|
1037
|
+
readonly 200: "#bfdbfe";
|
|
1038
|
+
readonly 300: "#93c5fd";
|
|
1039
|
+
readonly 400: "#60a5fa";
|
|
1040
|
+
readonly 500: "#3b82f6";
|
|
1041
|
+
readonly 600: "#2563eb";
|
|
1042
|
+
readonly 700: "#1d4ed8";
|
|
1043
|
+
readonly 800: "#1e40af";
|
|
1044
|
+
readonly 900: "#1e3a8a";
|
|
1045
|
+
};
|
|
1046
|
+
readonly neutral: {
|
|
1047
|
+
readonly 50: "#fafafa";
|
|
1048
|
+
readonly 100: "#f5f5f5";
|
|
1049
|
+
readonly 200: "#e5e5e5";
|
|
1050
|
+
readonly 300: "#d4d4d4";
|
|
1051
|
+
readonly 400: "#a3a3a3";
|
|
1052
|
+
readonly 500: "#737373";
|
|
1053
|
+
readonly 600: "#525252";
|
|
1054
|
+
readonly 700: "#404040";
|
|
1055
|
+
readonly 800: "#262626";
|
|
1056
|
+
readonly 900: "#171717";
|
|
1057
|
+
};
|
|
1058
|
+
readonly background: {
|
|
1059
|
+
readonly primary: "#ffffff";
|
|
1060
|
+
readonly secondary: "#f8fafc";
|
|
1061
|
+
readonly tertiary: "#f1f5f9";
|
|
1062
|
+
};
|
|
1063
|
+
readonly text: {
|
|
1064
|
+
readonly primary: "#0f172a";
|
|
1065
|
+
readonly secondary: "#475569";
|
|
1066
|
+
readonly tertiary: "#64748b";
|
|
1067
|
+
readonly disabled: "#94a3b8";
|
|
1068
|
+
};
|
|
1069
|
+
readonly border: {
|
|
1070
|
+
readonly primary: "#e2e8f0";
|
|
1071
|
+
readonly secondary: "#cbd5e1";
|
|
1072
|
+
readonly focus: "#3b82f6";
|
|
1073
|
+
readonly error: "#ef4444";
|
|
1074
|
+
};
|
|
1075
|
+
};
|
|
1076
|
+
declare const theme: {
|
|
1077
|
+
readonly colors: {
|
|
1078
|
+
readonly primary: {
|
|
1079
|
+
readonly 50: "#fef7e6";
|
|
1080
|
+
readonly 100: "#fdecc0";
|
|
1081
|
+
readonly 200: "#fbd886";
|
|
1082
|
+
readonly 300: "#f9c44c";
|
|
1083
|
+
readonly 400: "#f7b01f";
|
|
1084
|
+
readonly 500: "#F9BF3B";
|
|
1085
|
+
readonly 600: "#e6a82d";
|
|
1086
|
+
readonly 700: "#cc8f1f";
|
|
1087
|
+
readonly 800: "#b37611";
|
|
1088
|
+
readonly 900: "#995d03";
|
|
1089
|
+
};
|
|
1090
|
+
readonly secondary: {
|
|
1091
|
+
readonly 50: "#f8fafc";
|
|
1092
|
+
readonly 100: "#f1f5f9";
|
|
1093
|
+
readonly 200: "#e2e8f0";
|
|
1094
|
+
readonly 300: "#cbd5e1";
|
|
1095
|
+
readonly 400: "#94a3b8";
|
|
1096
|
+
readonly 500: "#64748b";
|
|
1097
|
+
readonly 600: "#475569";
|
|
1098
|
+
readonly 700: "#334155";
|
|
1099
|
+
readonly 800: "#1e293b";
|
|
1100
|
+
readonly 900: "#0f172a";
|
|
1101
|
+
};
|
|
1102
|
+
readonly success: {
|
|
1103
|
+
readonly 50: "#f0fdf4";
|
|
1104
|
+
readonly 100: "#dcfce7";
|
|
1105
|
+
readonly 200: "#bbf7d0";
|
|
1106
|
+
readonly 300: "#86efac";
|
|
1107
|
+
readonly 400: "#4ade80";
|
|
1108
|
+
readonly 500: "#22c55e";
|
|
1109
|
+
readonly 600: "#16a34a";
|
|
1110
|
+
readonly 700: "#15803d";
|
|
1111
|
+
readonly 800: "#166534";
|
|
1112
|
+
readonly 900: "#14532d";
|
|
1113
|
+
};
|
|
1114
|
+
readonly error: {
|
|
1115
|
+
readonly 50: "#fef2f2";
|
|
1116
|
+
readonly 100: "#fee2e2";
|
|
1117
|
+
readonly 200: "#fecaca";
|
|
1118
|
+
readonly 300: "#fca5a5";
|
|
1119
|
+
readonly 400: "#f87171";
|
|
1120
|
+
readonly 500: "#ef4444";
|
|
1121
|
+
readonly 600: "#dc2626";
|
|
1122
|
+
readonly 700: "#b91c1c";
|
|
1123
|
+
readonly 800: "#991b1b";
|
|
1124
|
+
readonly 900: "#7f1d1d";
|
|
1125
|
+
};
|
|
1126
|
+
readonly warning: {
|
|
1127
|
+
readonly 50: "#fffbeb";
|
|
1128
|
+
readonly 100: "#fef3c7";
|
|
1129
|
+
readonly 200: "#fde68a";
|
|
1130
|
+
readonly 300: "#fcd34d";
|
|
1131
|
+
readonly 400: "#fbbf24";
|
|
1132
|
+
readonly 500: "#f59e0b";
|
|
1133
|
+
readonly 600: "#d97706";
|
|
1134
|
+
readonly 700: "#b45309";
|
|
1135
|
+
readonly 800: "#92400e";
|
|
1136
|
+
readonly 900: "#78350f";
|
|
1137
|
+
};
|
|
1138
|
+
readonly info: {
|
|
1139
|
+
readonly 50: "#eff6ff";
|
|
1140
|
+
readonly 100: "#dbeafe";
|
|
1141
|
+
readonly 200: "#bfdbfe";
|
|
1142
|
+
readonly 300: "#93c5fd";
|
|
1143
|
+
readonly 400: "#60a5fa";
|
|
1144
|
+
readonly 500: "#3b82f6";
|
|
1145
|
+
readonly 600: "#2563eb";
|
|
1146
|
+
readonly 700: "#1d4ed8";
|
|
1147
|
+
readonly 800: "#1e40af";
|
|
1148
|
+
readonly 900: "#1e3a8a";
|
|
1149
|
+
};
|
|
1150
|
+
readonly neutral: {
|
|
1151
|
+
readonly 50: "#fafafa";
|
|
1152
|
+
readonly 100: "#f5f5f5";
|
|
1153
|
+
readonly 200: "#e5e5e5";
|
|
1154
|
+
readonly 300: "#d4d4d4";
|
|
1155
|
+
readonly 400: "#a3a3a3";
|
|
1156
|
+
readonly 500: "#737373";
|
|
1157
|
+
readonly 600: "#525252";
|
|
1158
|
+
readonly 700: "#404040";
|
|
1159
|
+
readonly 800: "#262626";
|
|
1160
|
+
readonly 900: "#171717";
|
|
1161
|
+
};
|
|
1162
|
+
readonly background: {
|
|
1163
|
+
readonly primary: "#ffffff";
|
|
1164
|
+
readonly secondary: "#f8fafc";
|
|
1165
|
+
readonly tertiary: "#f1f5f9";
|
|
1166
|
+
};
|
|
1167
|
+
readonly text: {
|
|
1168
|
+
readonly primary: "#0f172a";
|
|
1169
|
+
readonly secondary: "#475569";
|
|
1170
|
+
readonly tertiary: "#64748b";
|
|
1171
|
+
readonly disabled: "#94a3b8";
|
|
1172
|
+
};
|
|
1173
|
+
readonly border: {
|
|
1174
|
+
readonly primary: "#e2e8f0";
|
|
1175
|
+
readonly secondary: "#cbd5e1";
|
|
1176
|
+
readonly focus: "#3b82f6";
|
|
1177
|
+
readonly error: "#ef4444";
|
|
1178
|
+
};
|
|
1179
|
+
};
|
|
1180
|
+
readonly base: {
|
|
1181
|
+
readonly transition: "transition-all duration-200 ease-in-out motion-reduce:transition-none";
|
|
1182
|
+
readonly focus: "focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-background-primary focus-visible:ring-2";
|
|
1183
|
+
readonly disabled: "disabled:opacity-60 disabled:cursor-not-allowed disabled:pointer-events-none";
|
|
1184
|
+
readonly interactive: "cursor-pointer select-none";
|
|
1185
|
+
readonly highContrast: "forced-colors:border forced-colors:border-solid";
|
|
1186
|
+
};
|
|
1187
|
+
readonly sizes: {
|
|
1188
|
+
readonly xs: {
|
|
1189
|
+
readonly text: "text-xs";
|
|
1190
|
+
readonly padding: "px-2 py-1";
|
|
1191
|
+
readonly height: "h-6";
|
|
1192
|
+
readonly icon: "h-3 w-3";
|
|
1193
|
+
readonly gap: "gap-1";
|
|
1194
|
+
};
|
|
1195
|
+
readonly sm: {
|
|
1196
|
+
readonly text: "text-sm";
|
|
1197
|
+
readonly padding: "px-3 py-1.5";
|
|
1198
|
+
readonly height: "h-8";
|
|
1199
|
+
readonly icon: "h-4 w-4";
|
|
1200
|
+
readonly gap: "gap-1.5";
|
|
1201
|
+
};
|
|
1202
|
+
readonly md: {
|
|
1203
|
+
readonly text: "text-base";
|
|
1204
|
+
readonly padding: "px-4 py-2";
|
|
1205
|
+
readonly height: "h-10";
|
|
1206
|
+
readonly icon: "h-5 w-5";
|
|
1207
|
+
readonly gap: "gap-2";
|
|
1208
|
+
};
|
|
1209
|
+
readonly lg: {
|
|
1210
|
+
readonly text: "text-lg";
|
|
1211
|
+
readonly padding: "px-5 py-2.5";
|
|
1212
|
+
readonly height: "h-12";
|
|
1213
|
+
readonly icon: "h-6 w-6";
|
|
1214
|
+
readonly gap: "gap-2.5";
|
|
1215
|
+
};
|
|
1216
|
+
readonly xl: {
|
|
1217
|
+
readonly text: "text-xl";
|
|
1218
|
+
readonly padding: "px-6 py-3";
|
|
1219
|
+
readonly height: "h-14";
|
|
1220
|
+
readonly icon: "h-7 w-7";
|
|
1221
|
+
readonly gap: "gap-3";
|
|
1222
|
+
};
|
|
1223
|
+
};
|
|
1224
|
+
readonly variants: {
|
|
1225
|
+
readonly primary: {
|
|
1226
|
+
readonly solid: "bg-primary-9 text-neutral-12 hover:bg-primary-10 focus:ring-primary-8 active:bg-primary-10";
|
|
1227
|
+
readonly outline: "border border-primary-8 text-primary-11 hover:bg-primary-3 hover:border-primary-9 focus:ring-primary-8";
|
|
1228
|
+
readonly ghost: "text-primary-11 hover:bg-primary-3 hover:text-primary-12 focus:ring-primary-8";
|
|
1229
|
+
readonly soft: "bg-primary-3 text-primary-11 hover:bg-primary-4 focus:ring-primary-8";
|
|
1230
|
+
};
|
|
1231
|
+
readonly secondary: {
|
|
1232
|
+
readonly solid: "bg-secondary-500 text-white hover:bg-secondary-600 focus:ring-secondary-500 active:bg-secondary-700";
|
|
1233
|
+
readonly outline: "border border-secondary-300 text-secondary-700 hover:bg-secondary-50 hover:border-secondary-400 focus:ring-secondary-500";
|
|
1234
|
+
readonly ghost: "text-secondary-700 hover:bg-secondary-100 hover:text-secondary-800 focus:ring-secondary-500";
|
|
1235
|
+
readonly soft: "bg-secondary-100 text-secondary-800 hover:bg-secondary-200 focus:ring-secondary-500";
|
|
1236
|
+
};
|
|
1237
|
+
readonly destructive: {
|
|
1238
|
+
readonly solid: "bg-error-9 text-white hover:bg-error-10 focus:ring-error-8 active:bg-error-10";
|
|
1239
|
+
readonly outline: "border border-error-8 text-error-11 hover:bg-error-3 hover:border-error-9 focus:ring-error-8";
|
|
1240
|
+
readonly ghost: "text-error-11 hover:bg-error-3 hover:text-error-12 focus:ring-error-8";
|
|
1241
|
+
readonly soft: "bg-error-3 text-error-11 hover:bg-error-4 focus:ring-error-8";
|
|
1242
|
+
};
|
|
1243
|
+
readonly success: {
|
|
1244
|
+
readonly solid: "bg-success-9 text-white hover:bg-success-10 focus:ring-success-8 active:bg-success-10";
|
|
1245
|
+
readonly outline: "border border-success-8 text-success-11 hover:bg-success-3 hover:border-success-9 focus:ring-success-8";
|
|
1246
|
+
readonly ghost: "text-success-11 hover:bg-success-3 hover:text-success-12 focus:ring-success-8";
|
|
1247
|
+
readonly soft: "bg-success-3 text-success-11 hover:bg-success-4 focus:ring-success-8";
|
|
1248
|
+
};
|
|
1249
|
+
readonly warning: {
|
|
1250
|
+
readonly solid: "bg-warning-9 text-neutral-12 hover:bg-warning-10 focus:ring-warning-8 active:bg-warning-10";
|
|
1251
|
+
readonly outline: "border border-warning-8 text-warning-11 hover:bg-warning-3 hover:border-warning-9 focus:ring-warning-8";
|
|
1252
|
+
readonly ghost: "text-warning-11 hover:bg-warning-3 hover:text-warning-12 focus:ring-warning-8";
|
|
1253
|
+
readonly soft: "bg-warning-3 text-warning-11 hover:bg-warning-4 focus:ring-warning-8";
|
|
1254
|
+
};
|
|
1255
|
+
readonly info: {
|
|
1256
|
+
readonly solid: "bg-info-9 text-white hover:bg-info-10 focus:ring-info-8 active:bg-info-10";
|
|
1257
|
+
readonly outline: "border border-info-8 text-info-11 hover:bg-info-3 hover:border-info-9 focus:ring-info-8";
|
|
1258
|
+
readonly ghost: "text-info-11 hover:bg-info-3 hover:text-info-12 focus:ring-info-8";
|
|
1259
|
+
readonly soft: "bg-info-3 text-info-11 hover:bg-info-4 focus:ring-info-8";
|
|
1260
|
+
};
|
|
1261
|
+
};
|
|
1262
|
+
readonly radius: {
|
|
1263
|
+
readonly none: "rounded-none";
|
|
1264
|
+
readonly xs: "rounded-xs";
|
|
1265
|
+
readonly sm: "rounded-sm";
|
|
1266
|
+
readonly md: "rounded-md";
|
|
1267
|
+
readonly lg: "rounded-lg";
|
|
1268
|
+
readonly xl: "rounded-xl";
|
|
1269
|
+
readonly "2xl": "rounded-2xl";
|
|
1270
|
+
readonly "3xl": "rounded-3xl";
|
|
1271
|
+
readonly full: "rounded-full";
|
|
1272
|
+
};
|
|
1273
|
+
readonly spacing: {
|
|
1274
|
+
readonly none: "gap-0";
|
|
1275
|
+
readonly xs: "gap-1";
|
|
1276
|
+
readonly sm: "gap-2";
|
|
1277
|
+
readonly md: "gap-3";
|
|
1278
|
+
readonly lg: "gap-4";
|
|
1279
|
+
readonly xl: "gap-6";
|
|
1280
|
+
readonly "2xl": "gap-8";
|
|
1281
|
+
readonly "3xl": "gap-12";
|
|
1282
|
+
};
|
|
1283
|
+
readonly typography: {
|
|
1284
|
+
readonly xs: "text-xs leading-4";
|
|
1285
|
+
readonly sm: "text-sm leading-5";
|
|
1286
|
+
readonly base: "text-base leading-6";
|
|
1287
|
+
readonly lg: "text-lg leading-7";
|
|
1288
|
+
readonly xl: "text-xl leading-8";
|
|
1289
|
+
readonly "2xl": "text-2xl leading-9";
|
|
1290
|
+
readonly "3xl": "text-3xl leading-10";
|
|
1291
|
+
};
|
|
1292
|
+
readonly animations: {
|
|
1293
|
+
readonly duration: {
|
|
1294
|
+
readonly fast: "duration-150";
|
|
1295
|
+
readonly normal: "duration-200";
|
|
1296
|
+
readonly slow: "duration-300";
|
|
1297
|
+
};
|
|
1298
|
+
readonly easing: {
|
|
1299
|
+
readonly linear: "ease-linear";
|
|
1300
|
+
readonly in: "ease-in";
|
|
1301
|
+
readonly out: "ease-out";
|
|
1302
|
+
readonly inOut: "ease-in-out";
|
|
1303
|
+
};
|
|
1304
|
+
readonly fadeIn: "animate-in fade-in";
|
|
1305
|
+
readonly fadeOut: "animate-out fade-out";
|
|
1306
|
+
readonly slideIn: "animate-in slide-in-from-bottom-2";
|
|
1307
|
+
readonly slideOut: "animate-out slide-out-to-bottom-2";
|
|
1308
|
+
readonly scaleIn: "animate-in zoom-in-95";
|
|
1309
|
+
readonly scaleOut: "animate-out zoom-out-95";
|
|
1310
|
+
};
|
|
1311
|
+
readonly accessibility: {
|
|
1312
|
+
readonly srOnly: "sr-only";
|
|
1313
|
+
readonly focusTrap: "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2";
|
|
1314
|
+
readonly highContrast: "forced-colors:border forced-colors:border-solid";
|
|
1315
|
+
readonly reducedMotion: "motion-reduce:transition-none motion-reduce:animate-none";
|
|
1316
|
+
readonly touchTarget: "min-h-11 min-w-11";
|
|
1317
|
+
};
|
|
1318
|
+
};
|
|
1319
|
+
declare const getColor: (colorName: keyof typeof colors, shade?: keyof typeof colors.primary | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12) => string;
|
|
1320
|
+
type ThemeSize = keyof typeof theme.sizes;
|
|
1321
|
+
type ThemeVariant = keyof typeof theme.variants;
|
|
1322
|
+
type ThemeVariantStyle = keyof typeof theme.variants.primary;
|
|
1323
|
+
type ThemeRadius = keyof typeof theme.radius;
|
|
1324
|
+
type ThemeSpacing = keyof typeof theme.spacing;
|
|
1325
|
+
type ThemeColor = keyof typeof colors;
|
|
1326
|
+
type ThemeColorShade = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
|
|
1327
|
+
|
|
1328
|
+
interface BaseProps {
|
|
1329
|
+
/** Additional CSS class names */
|
|
1330
|
+
className?: string;
|
|
1331
|
+
/** Child elements */
|
|
1332
|
+
children?: react.ReactNode;
|
|
1333
|
+
/** Unique identifier for the component */
|
|
1334
|
+
id?: string;
|
|
1335
|
+
/** Test identifier for testing purposes */
|
|
1336
|
+
testId?: string;
|
|
1337
|
+
/** Custom styles */
|
|
1338
|
+
style?: react.CSSProperties;
|
|
1339
|
+
}
|
|
1340
|
+
interface InteractiveProps extends BaseProps {
|
|
1341
|
+
/** Whether the component is disabled */
|
|
1342
|
+
disabled?: boolean;
|
|
1343
|
+
/** Whether the component is in a loading state */
|
|
1344
|
+
loading?: boolean;
|
|
1345
|
+
/** Callback fired when the component is clicked */
|
|
1346
|
+
onClick?: (event: react.MouseEvent) => void;
|
|
1347
|
+
/** Callback fired when the component receives focus */
|
|
1348
|
+
onFocus?: (event: react.FocusEvent) => void;
|
|
1349
|
+
/** Callback fired when the component loses focus */
|
|
1350
|
+
onBlur?: (event: react.FocusEvent) => void;
|
|
1351
|
+
/** Callback fired on key down events */
|
|
1352
|
+
onKeyDown?: (event: react.KeyboardEvent) => void;
|
|
1353
|
+
}
|
|
1354
|
+
type Size = ThemeSize;
|
|
1355
|
+
type Variant = ThemeVariant;
|
|
1356
|
+
interface FormFieldProps extends InteractiveProps {
|
|
1357
|
+
/** Label text for the form field */
|
|
1358
|
+
label?: string;
|
|
1359
|
+
/** Error message to display */
|
|
1360
|
+
error?: string | string[];
|
|
1361
|
+
/** Helper text to provide additional context */
|
|
1362
|
+
helperText?: string;
|
|
1363
|
+
/** Whether the field is required */
|
|
1364
|
+
required?: boolean;
|
|
1365
|
+
/** Name attribute for form submission */
|
|
1366
|
+
name?: string;
|
|
1367
|
+
/** Placeholder text */
|
|
1368
|
+
placeholder?: string;
|
|
1369
|
+
/** Whether the field is read-only */
|
|
1370
|
+
readOnly?: boolean;
|
|
1371
|
+
/** Auto-complete attribute */
|
|
1372
|
+
autoComplete?: string;
|
|
1373
|
+
/** Auto-focus the field on mount */
|
|
1374
|
+
autoFocus?: boolean;
|
|
1375
|
+
}
|
|
1376
|
+
type PolymorphicRef<T extends react.ElementType> = react.ComponentPropsWithRef<T>["ref"];
|
|
1377
|
+
type PolymorphicComponentProps<T extends react.ElementType, P = object> = P & Omit<react.ComponentPropsWithoutRef<T>, keyof P> & {
|
|
1378
|
+
/** The element type to render as */
|
|
1379
|
+
as?: T;
|
|
1380
|
+
};
|
|
1381
|
+
type PolymorphicComponent<T extends react.ElementType, P = object> = <C extends react.ElementType = T>(props: PolymorphicComponentProps<C, P> & {
|
|
1382
|
+
ref?: PolymorphicRef<C>;
|
|
1383
|
+
}) => react.ReactElement | null;
|
|
1384
|
+
interface InteractionStates {
|
|
1385
|
+
/** Whether the component is in hover state */
|
|
1386
|
+
hover?: boolean;
|
|
1387
|
+
/** Whether the component is focused */
|
|
1388
|
+
focus?: boolean;
|
|
1389
|
+
/** Whether the component is active/pressed */
|
|
1390
|
+
active?: boolean;
|
|
1391
|
+
/** Whether the component is disabled */
|
|
1392
|
+
disabled?: boolean;
|
|
1393
|
+
/** Whether the component is loading */
|
|
1394
|
+
loading?: boolean;
|
|
1395
|
+
/** Whether the component has an error */
|
|
1396
|
+
error?: boolean;
|
|
1397
|
+
/** Whether the component is valid */
|
|
1398
|
+
valid?: boolean;
|
|
1399
|
+
}
|
|
1400
|
+
type ResponsiveValue<T> = T | {
|
|
1401
|
+
xs?: T;
|
|
1402
|
+
sm?: T;
|
|
1403
|
+
md?: T;
|
|
1404
|
+
lg?: T;
|
|
1405
|
+
xl?: T;
|
|
1406
|
+
"2xl"?: T;
|
|
1407
|
+
};
|
|
1408
|
+
interface ComponentState<T = unknown> {
|
|
1409
|
+
/** Current value */
|
|
1410
|
+
value?: T;
|
|
1411
|
+
/** Default value */
|
|
1412
|
+
defaultValue?: T;
|
|
1413
|
+
/** Callback fired when value changes */
|
|
1414
|
+
onChange?: (value: T, event?: react.ChangeEvent | react.MouseEvent) => void;
|
|
1415
|
+
/** Validation function */
|
|
1416
|
+
validate?: (value: T) => string | string[] | null;
|
|
1417
|
+
/** Whether the field has been touched */
|
|
1418
|
+
touched?: boolean;
|
|
1419
|
+
/** Whether the field is dirty (value changed from initial) */
|
|
1420
|
+
dirty?: boolean;
|
|
1421
|
+
}
|
|
1422
|
+
interface AccessibilityProps {
|
|
1423
|
+
/** Accessible name for the component */
|
|
1424
|
+
"aria-label"?: string;
|
|
1425
|
+
/** ID of element that labels this component */
|
|
1426
|
+
"aria-labelledby"?: string;
|
|
1427
|
+
/** ID of element that describes this component */
|
|
1428
|
+
"aria-describedby"?: string;
|
|
1429
|
+
/** Whether the component is expanded (for collapsible elements) */
|
|
1430
|
+
"aria-expanded"?: boolean;
|
|
1431
|
+
/** Whether the component is selected */
|
|
1432
|
+
"aria-selected"?: boolean;
|
|
1433
|
+
/** Whether the component is disabled */
|
|
1434
|
+
"aria-disabled"?: boolean;
|
|
1435
|
+
/** Whether the component is required */
|
|
1436
|
+
"aria-required"?: boolean;
|
|
1437
|
+
/** Whether the component has invalid input */
|
|
1438
|
+
"aria-invalid"?: boolean;
|
|
1439
|
+
/** Current value for range components */
|
|
1440
|
+
"aria-valuenow"?: number;
|
|
1441
|
+
/** Minimum value for range components */
|
|
1442
|
+
"aria-valuemin"?: number;
|
|
1443
|
+
/** Maximum value for range components */
|
|
1444
|
+
"aria-valuemax"?: number;
|
|
1445
|
+
/** Text description of current value */
|
|
1446
|
+
"aria-valuetext"?: string;
|
|
1447
|
+
/** ARIA role */
|
|
1448
|
+
role?: string;
|
|
1449
|
+
/** Tab index for keyboard navigation */
|
|
1450
|
+
tabIndex?: number;
|
|
1451
|
+
/** Whether element is hidden from screen readers */
|
|
1452
|
+
"aria-hidden"?: boolean;
|
|
1453
|
+
/** Live region politeness setting */
|
|
1454
|
+
"aria-live"?: "off" | "polite" | "assertive";
|
|
1455
|
+
/** Whether element is atomic for live regions */
|
|
1456
|
+
"aria-atomic"?: boolean;
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
declare function cn(...inputs: ClassValue[]): string;
|
|
1460
|
+
declare function getVariantStyles(variant: ThemeVariant, style?: ThemeVariantStyle): string;
|
|
1461
|
+
declare function getSizeStyles(size: ThemeSize): string;
|
|
1462
|
+
declare function getBaseStyles(): string;
|
|
1463
|
+
declare function getInteractiveStyles(): string;
|
|
1464
|
+
declare function getAccessibilityStyles(options?: {
|
|
1465
|
+
focusVisible?: boolean;
|
|
1466
|
+
highContrast?: boolean;
|
|
1467
|
+
reducedMotion?: boolean;
|
|
1468
|
+
}): string;
|
|
1469
|
+
declare function getResponsiveClasses<T extends string>(value: ResponsiveValue<T>, prefix?: string): string;
|
|
1470
|
+
declare function getSpacingClass(spacing: ThemeSpacing, type?: "gap" | "margin" | "padding"): string;
|
|
1471
|
+
declare function getRadiusClass(radius: ThemeRadius): string;
|
|
1472
|
+
declare function getTypographyClass(typography: keyof typeof theme.typography): string;
|
|
1473
|
+
declare function getBgClass(colorName: ThemeColor, shade?: ThemeColorShade): string;
|
|
1474
|
+
declare function getTextClass(colorName: ThemeColor, shade?: ThemeColorShade): string;
|
|
1475
|
+
declare function getBorderClass(colorName: ThemeColor, shade?: ThemeColorShade): string;
|
|
1476
|
+
declare function getHoverBgClass(colorName: ThemeColor, shade?: ThemeColorShade): string;
|
|
1477
|
+
declare function getHoverTextClass(colorName: ThemeColor, shade?: ThemeColorShade): string;
|
|
1478
|
+
declare function getFocusRingClass(colorName: ThemeColor, shade?: ThemeColorShade): string;
|
|
1479
|
+
declare function getAnimationClass(animation: keyof typeof theme.animations): string;
|
|
1480
|
+
declare function createCompoundVariants<T>(base: string, variants: Record<string, Record<string, string>>, compoundVariants?: Array<{
|
|
1481
|
+
conditions: Record<string, string>;
|
|
1482
|
+
className: string;
|
|
1483
|
+
}>): (props: T) => string;
|
|
1484
|
+
interface VariantConfig<T extends Record<string, Record<string, string>>> {
|
|
1485
|
+
base?: string;
|
|
1486
|
+
variants?: T;
|
|
1487
|
+
compoundVariants?: Array<{
|
|
1488
|
+
conditions: Partial<{
|
|
1489
|
+
[K in keyof T]: keyof T[K];
|
|
1490
|
+
}>;
|
|
1491
|
+
className: string;
|
|
1492
|
+
}>;
|
|
1493
|
+
defaultVariants?: Partial<{
|
|
1494
|
+
[K in keyof T]: keyof T[K];
|
|
1495
|
+
}>;
|
|
1496
|
+
}
|
|
1497
|
+
declare function createVariantGenerator<T extends Record<string, Record<string, string>>>(config: VariantConfig<T>): (props: Partial<{ [K in keyof T]: keyof T[K]; }> & {
|
|
1498
|
+
className?: string;
|
|
1499
|
+
}) => string;
|
|
1500
|
+
declare function mergeProps<T extends Record<string, unknown>>(defaultProps: Partial<T>, userProps: T): T;
|
|
1501
|
+
declare function conditionalClass(condition: boolean | undefined | null, trueClass: string, falseClass?: string): string;
|
|
1502
|
+
declare function getFocusableElements(container: HTMLElement): HTMLElement[];
|
|
1503
|
+
declare function handleArrowNavigation(event: KeyboardEvent, elements: HTMLElement[], currentIndex: number, options?: {
|
|
1504
|
+
loop?: boolean;
|
|
1505
|
+
orientation?: "horizontal" | "vertical" | "both";
|
|
1506
|
+
}): number;
|
|
1507
|
+
|
|
1508
|
+
interface UIProviderProps extends Omit<Partial<ThemeProps>, "children"> {
|
|
1509
|
+
children: ReactNode;
|
|
1510
|
+
}
|
|
1511
|
+
declare function UIProvider({ children, appearance, radius, scaling, accentColor, grayColor, panelBackground, className, }: UIProviderProps): react__default.JSX.Element;
|
|
1512
|
+
|
|
1513
|
+
declare function useControllableState<T>({ value, defaultValue, onChange, }: {
|
|
1514
|
+
value?: T;
|
|
1515
|
+
defaultValue?: T;
|
|
1516
|
+
onChange?: (value: T) => void;
|
|
1517
|
+
}): readonly [T | undefined, (newValue: T | ((prev: T | undefined) => T)) => void];
|
|
1518
|
+
|
|
1519
|
+
declare function useDisclosure(defaultOpen?: boolean): {
|
|
1520
|
+
isOpen: boolean;
|
|
1521
|
+
open: () => void;
|
|
1522
|
+
close: () => void;
|
|
1523
|
+
toggle: () => void;
|
|
1524
|
+
onOpen: () => void;
|
|
1525
|
+
onClose: () => void;
|
|
1526
|
+
onToggle: () => void;
|
|
1527
|
+
};
|
|
1528
|
+
|
|
1529
|
+
declare function useClickOutside<T extends HTMLElement = HTMLElement>(handler: () => void, enabled?: boolean): react.RefObject<T | null>;
|
|
1530
|
+
|
|
1531
|
+
export { ACTIVITY_META, AUDIT_ACTION_META, AccentCard, type AccentCardProps, AccentHeader, type AccentHeaderProps, type AccessibilityProps, AccountCalendarsDialog, type AccountCalendarsDialogProps, AccountCard, type AccountCardProps, ActivityRow, type ActivityRowProps, type ActivityType, AddAccountMenu, type AddAccountMenuProps, AppCard, type AppCardProps, type AuditAction, AuthCard, type AvailabilityBlock, type BaseProps, BigCalendarView, type BigCalendarViewProps, BrandPanel, type CalendarAccount, type CalendarAccountCalendar, CalendarDayHeader, type CalendarDayHeaderProps, CalendarMergedView, type CalendarMergedViewProps, CalendarPickList, type CalendarProvider, type CalendarSync, CalendarToolbar, CardFooter, type CardFooterProps, type ComponentState, ConfirmDialog, type ConfirmDialogProps, ConnectProviderList, ConnectProviderRows, type ConnectProviderRowsProps, ConnectedAccountCard, DashboardErrorCard, type DashboardErrorCardProps, DataTableRow, type DataTableRowProps, type DatedAvailabilityBlock, EmptyCard, type EmptyCardProps, EventBlock, type EventBlockProps, type FormFieldProps, GoogleIcon, type HeadingLevel, IconTile, type IconTileProps, ImportCalendarsDialog, type ImportCalendarsDialogProps, type InteractionStates, METRIC_STATUS_COLOR, MetricCard, type MetricCardProps, type MetricStatus, MicrosoftIcon, MiniMonthPicker, type MiniMonthPickerProps, MonthGrid, type MonthGridProps, type NavItem, OnboardingStepDots, OnboardingStepper, OtpInput, OtpVerifyStep, type OtpVerifyStepProps, PROVIDER_LABEL, PROVIDER_META, Pagination, type PaginationProps, PausedBadge, type PausedBadgeProps, type PolymorphicComponent, type PolymorphicComponentProps, ProviderIcon, ROLE_LABELS, ROLE_META, type ResolvedBlock, type ResponsiveValue, type Role, SHELL_HEADER_H, STATUS_META, SearchOverlay, type SearchOverlayProps, type SearchResult, type SearchResultType, Sidebar, type SidebarDevRole, type SidebarProps, type SidebarUser, type Size, Skeleton, type SkeletonProps, SyncDetailsDialog, type SyncDetailsDialogProps, SyncPreviewRail, type SyncStatus, Toast, type ToastProps, Topbar, type TopbarAdminTitleRow, type TopbarProps, type TopbarTitleRow, UIProvider, type UseConnectAccountOptions, type UserStatus, type Variant, type WizardStepMeta, WizardStepper, auditActionMeta, cn, colors, conditionalClass, createCompoundVariants, createVariantGenerator, findCalendar, getAccessibilityStyles, getAnimationClass, getBaseStyles, getBgClass, getBorderClass, getColor, getFocusRingClass, getFocusableElements, getHoverBgClass, getHoverTextClass, getInteractiveStyles, getRadiusClass, getResponsiveClasses, getSizeStyles, getSpacingClass, getTextClass, getTypographyClass, getVariantStyles, handleArrowNavigation, headingSize, layout, mergeProps, theme, useClickOutside, useConnectAccount, useControllableState, useDisclosure };
|