@twentyfirstmedia/ui-core 0.5.0 → 0.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/dist/components/admin.d.ts.map +1 -1
- package/dist/components/admin.js +31 -21
- package/dist/components/admin.js.map +1 -1
- package/dist/components/agents.d.ts.map +1 -1
- package/dist/components/agents.js +21 -18
- package/dist/components/agents.js.map +1 -1
- package/dist/components/app-chrome.d.ts.map +1 -1
- package/dist/components/app-chrome.js +5 -5
- package/dist/components/app-chrome.js.map +1 -1
- package/dist/components/approvals.d.ts.map +1 -1
- package/dist/components/approvals.js +2 -2
- package/dist/components/approvals.js.map +1 -1
- package/dist/components/building-blocks.d.ts.map +1 -1
- package/dist/components/building-blocks.js +13 -10
- package/dist/components/building-blocks.js.map +1 -1
- package/dist/components/charts.d.ts +2 -2
- package/dist/components/charts.d.ts.map +1 -1
- package/dist/components/charts.js +14 -11
- package/dist/components/charts.js.map +1 -1
- package/dist/components/chat.d.ts +2 -2
- package/dist/components/chat.d.ts.map +1 -1
- package/dist/components/chat.js +22 -18
- package/dist/components/chat.js.map +1 -1
- package/dist/components/commerce.d.ts.map +1 -1
- package/dist/components/commerce.js +20 -16
- package/dist/components/commerce.js.map +1 -1
- package/dist/components/data-display.d.ts +0 -5
- package/dist/components/data-display.d.ts.map +1 -1
- package/dist/components/data-display.js +41 -22
- package/dist/components/data-display.js.map +1 -1
- package/dist/components/data-table.d.ts +2 -2
- package/dist/components/data-table.d.ts.map +1 -1
- package/dist/components/data-table.js +3 -3
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/developer.d.ts.map +1 -1
- package/dist/components/developer.js +7 -6
- package/dist/components/developer.js.map +1 -1
- package/dist/components/feedback.d.ts.map +1 -1
- package/dist/components/feedback.js +5 -4
- package/dist/components/feedback.js.map +1 -1
- package/dist/components/forms.d.ts.map +1 -1
- package/dist/components/forms.js +63 -21
- package/dist/components/forms.js.map +1 -1
- package/dist/components/foundation.d.ts.map +1 -1
- package/dist/components/foundation.js +13 -9
- package/dist/components/foundation.js.map +1 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -1
- package/dist/components/index.js.map +1 -1
- package/dist/components/inputs.d.ts.map +1 -1
- package/dist/components/inputs.js +33 -8
- package/dist/components/inputs.js.map +1 -1
- package/dist/components/mail.d.ts.map +1 -1
- package/dist/components/mail.js +5 -5
- package/dist/components/mail.js.map +1 -1
- package/dist/components/media.d.ts.map +1 -1
- package/dist/components/media.js +62 -11
- package/dist/components/media.js.map +1 -1
- package/dist/components/navigation.d.ts +3 -1
- package/dist/components/navigation.d.ts.map +1 -1
- package/dist/components/navigation.js +287 -20
- package/dist/components/navigation.js.map +1 -1
- package/dist/components/operations.d.ts.map +1 -1
- package/dist/components/operations.js +10 -10
- package/dist/components/operations.js.map +1 -1
- package/dist/components/overlays.d.ts.map +1 -1
- package/dist/components/overlays.js +2 -2
- package/dist/components/overlays.js.map +1 -1
- package/dist/components/previews.js +2 -2
- package/dist/components/previews.js.map +1 -1
- package/dist/components/primitives.js +2 -2
- package/dist/components/primitives.js.map +1 -1
- package/dist/components/qr-code.d.ts +8 -0
- package/dist/components/qr-code.d.ts.map +1 -0
- package/dist/components/qr-code.js +18 -0
- package/dist/components/qr-code.js.map +1 -0
- package/dist/components/real-estate.d.ts.map +1 -1
- package/dist/components/real-estate.js +5 -5
- package/dist/components/real-estate.js.map +1 -1
- package/dist/components/rich-text-editor.d.ts.map +1 -1
- package/dist/components/rich-text-editor.js +1 -1
- package/dist/components/rich-text-editor.js.map +1 -1
- package/dist/components/select-menu.js +1 -1
- package/dist/components/select-menu.js.map +1 -1
- package/dist/components/shell.d.ts +0 -4
- package/dist/components/shell.d.ts.map +1 -1
- package/dist/components/shell.js +100 -7
- package/dist/components/shell.js.map +1 -1
- package/dist/components/site.d.ts.map +1 -1
- package/dist/components/site.js +8 -6
- package/dist/components/site.js.map +1 -1
- package/dist/components/status.d.ts.map +1 -1
- package/dist/components/status.js +2 -2
- package/dist/components/status.js.map +1 -1
- package/dist/components/system.d.ts.map +1 -1
- package/dist/components/system.js +3 -2
- package/dist/components/system.js.map +1 -1
- package/dist/components/types.d.ts +257 -18
- package/dist/components/types.d.ts.map +1 -1
- package/dist/components/workspace.d.ts.map +1 -1
- package/dist/components/workspace.js +15 -12
- package/dist/components/workspace.js.map +1 -1
- package/dist/qr.d.ts +14 -0
- package/dist/qr.d.ts.map +1 -0
- package/dist/qr.js +298 -0
- package/dist/qr.js.map +1 -0
- package/dist/strings.d.ts +30 -4
- package/dist/strings.d.ts.map +1 -1
- package/dist/strings.js +15 -0
- package/dist/strings.js.map +1 -1
- package/dist/themes.css +2345 -176
- package/package.json +2 -1
- package/src/components/admin.tsx +66 -23
- package/src/components/agents.tsx +22 -20
- package/src/components/app-chrome.tsx +9 -5
- package/src/components/approvals.tsx +3 -1
- package/src/components/building-blocks.tsx +24 -13
- package/src/components/charts.tsx +17 -12
- package/src/components/chat.tsx +54 -31
- package/src/components/commerce.tsx +58 -24
- package/src/components/data-display.tsx +106 -38
- package/src/components/data-table.tsx +11 -7
- package/src/components/developer.tsx +15 -6
- package/src/components/feedback.tsx +5 -3
- package/src/components/forms.tsx +101 -23
- package/src/components/foundation.tsx +9 -5
- package/src/components/index.ts +10 -1
- package/src/components/inputs.tsx +44 -7
- package/src/components/mail.tsx +7 -3
- package/src/components/media.tsx +88 -16
- package/src/components/navigation.tsx +651 -71
- package/src/components/operations.tsx +17 -8
- package/src/components/overlays.tsx +7 -2
- package/src/components/previews.tsx +2 -2
- package/src/components/primitives.tsx +2 -2
- package/src/components/qr-code.tsx +30 -0
- package/src/components/real-estate.tsx +7 -4
- package/src/components/rich-text-editor.tsx +7 -1
- package/src/components/select-menu.tsx +1 -1
- package/src/components/shell.tsx +237 -11
- package/src/components/site.tsx +18 -4
- package/src/components/status.tsx +2 -0
- package/src/components/system.tsx +3 -2
- package/src/components/types.ts +261 -18
- package/src/components/workspace.tsx +37 -15
- package/src/qr.ts +300 -0
- package/src/strings.ts +56 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import { cx } from "../cx.js";
|
|
2
3
|
import { Button, TintIcon } from "./foundation.js";
|
|
3
4
|
import type { AuthCardProps, IconName, StatusScreenProps, Tint } from "./types.js";
|
|
4
5
|
|
|
@@ -40,7 +41,7 @@ export function StatusScreen(p: StatusScreenProps) {
|
|
|
40
41
|
} as Record<string, [string, string, IconName, Tint]>
|
|
41
42
|
)[code] || [p.title, p.text, "sparkle", "sky"];
|
|
42
43
|
return (
|
|
43
|
-
<div className="tf-status-screen">
|
|
44
|
+
<div style={p.style} className={cx("tf-status-screen", p.className)}>
|
|
44
45
|
<div className="tf-status-art" aria-hidden>
|
|
45
46
|
{/^\d+$/.test(code) && <span className="tf-status-code">{code}</span>}
|
|
46
47
|
<TintIcon icon={p.icon || d[2]} tint={p.tint || d[3]} size={56} />
|
|
@@ -70,7 +71,7 @@ export function StatusScreen(p: StatusScreenProps) {
|
|
|
70
71
|
|
|
71
72
|
export function AuthCard(p: AuthCardProps) {
|
|
72
73
|
return (
|
|
73
|
-
<div className="tf-auth">
|
|
74
|
+
<div style={p.style} className={cx("tf-auth", p.className)}>
|
|
74
75
|
{p.brand && (
|
|
75
76
|
<div className="tf-auth-brand">
|
|
76
77
|
<span className="tf-brand-word">{p.brand}</span>
|
package/src/components/types.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ChangeEvent,
|
|
3
|
+
CSSProperties,
|
|
4
|
+
ElementType,
|
|
5
|
+
FocusEvent,
|
|
6
|
+
InputHTMLAttributes,
|
|
7
|
+
KeyboardEvent,
|
|
8
|
+
MouseEvent,
|
|
9
|
+
ReactNode,
|
|
10
|
+
Ref,
|
|
11
|
+
} from "react";
|
|
2
12
|
import type { IconName } from "../icons.js";
|
|
3
13
|
import type { ToastOptions } from "../toast-store.js";
|
|
4
14
|
import type { Surface } from "../provider.js";
|
|
@@ -137,9 +147,21 @@ export interface SearchFieldProps extends BaseProps {
|
|
|
137
147
|
placeholder?: string;
|
|
138
148
|
/** Accessible name (default: the placeholder, or "Search"). */
|
|
139
149
|
label?: string;
|
|
150
|
+
/** The key hint, e.g. "⌘K" (hidden on touch screens). */
|
|
140
151
|
shortcut?: string;
|
|
152
|
+
/** ⌘/Ctrl + the hint's last key (K for "⌘K") focuses the field, except while typing elsewhere. */
|
|
153
|
+
bindShortcut?: boolean;
|
|
141
154
|
value?: string;
|
|
155
|
+
defaultValue?: string;
|
|
142
156
|
onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
|
|
157
|
+
onKeyDown?: (e: KeyboardEvent<HTMLInputElement>) => void;
|
|
158
|
+
onFocus?: (e: FocusEvent<HTMLInputElement>) => void;
|
|
159
|
+
onBlur?: (e: FocusEvent<HTMLInputElement>) => void;
|
|
160
|
+
id?: string;
|
|
161
|
+
name?: string;
|
|
162
|
+
autoFocus?: boolean;
|
|
163
|
+
/** For a search with suggestions (combobox): role, aria-controls, aria-activedescendant … */
|
|
164
|
+
inputProps?: InputHTMLAttributes<HTMLInputElement>;
|
|
143
165
|
}
|
|
144
166
|
export interface CheckboxProps extends BaseProps {
|
|
145
167
|
name?: string;
|
|
@@ -214,7 +236,10 @@ export interface PanelProps extends BaseProps {
|
|
|
214
236
|
surface?: Surface;
|
|
215
237
|
}
|
|
216
238
|
export interface PageHeaderProps extends BaseProps {
|
|
217
|
-
|
|
239
|
+
/** A breadcrumb above the title (see `Breadcrumb`): labels, or items with `href`/`onClick`. */
|
|
240
|
+
crumbs?: (string | Crumb)[];
|
|
241
|
+
/** The element crumb links render as, e.g. Next.js `Link`. */
|
|
242
|
+
crumbLinkAs?: ElementType;
|
|
218
243
|
title: string;
|
|
219
244
|
subtitle?: string;
|
|
220
245
|
actions?: ReactNode[];
|
|
@@ -225,7 +250,8 @@ export interface NavItem {
|
|
|
225
250
|
count?: number;
|
|
226
251
|
}
|
|
227
252
|
export interface TopBarProps extends BaseProps {
|
|
228
|
-
|
|
253
|
+
/** The product name, or a node (a logo mark with the name). */
|
|
254
|
+
brand?: ReactNode;
|
|
229
255
|
tag?: string;
|
|
230
256
|
items: NavItem[];
|
|
231
257
|
active?: string;
|
|
@@ -245,6 +271,14 @@ export interface RailItem {
|
|
|
245
271
|
export interface SideRailProps extends BaseProps {
|
|
246
272
|
top?: RailItem[];
|
|
247
273
|
bottom?: RailItem[];
|
|
274
|
+
/** Names next to the icons (controlled); every button has a tooltip while collapsed. */
|
|
275
|
+
expanded?: boolean;
|
|
276
|
+
defaultExpanded?: boolean;
|
|
277
|
+
onExpandedChange?: (expanded: boolean) => void;
|
|
278
|
+
/** A button at the foot that expands and collapses the rail. */
|
|
279
|
+
toggle?: boolean;
|
|
280
|
+
/** Accessible name of the rail (default "Tools"). */
|
|
281
|
+
label?: string;
|
|
248
282
|
}
|
|
249
283
|
export interface FloatingLayoutProps extends BaseProps {
|
|
250
284
|
/** What the UI floats over, filling the layout: a map, a 3D canvas, a video, a photo. */
|
|
@@ -257,7 +291,23 @@ export interface FloatingLayoutProps extends BaseProps {
|
|
|
257
291
|
end?: ReactNode;
|
|
258
292
|
/** Bar along the bottom edge (dock, playback, a summary). */
|
|
259
293
|
bottom?: ReactNode;
|
|
260
|
-
/**
|
|
294
|
+
/** Controls of the background (zoom, compass, locate) in the free corner above the bottom bar. */
|
|
295
|
+
controls?: ReactNode;
|
|
296
|
+
/** Source notes of the background (map attribution), under `controls`, clear of every slot. */
|
|
297
|
+
attribution?: ReactNode;
|
|
298
|
+
/** Width of the start column (default 320px) and of the end column (default 340px). */
|
|
299
|
+
startWidth?: number | string;
|
|
300
|
+
endWidth?: number | string;
|
|
301
|
+
/**
|
|
302
|
+
* Below 720px of width the end slot becomes a bottom sheet over the background, with a handle
|
|
303
|
+
* that expands and collapses it (default true). `false` stacks it with the others.
|
|
304
|
+
*/
|
|
305
|
+
endSheet?: boolean;
|
|
306
|
+
/**
|
|
307
|
+
* Height of the layout (default 640). Below 720px of width the slots stack: top, start, end,
|
|
308
|
+
* bottom. The layout sets `--floating-safe-top/-start/-end/-bottom` (px) to the space its
|
|
309
|
+
* slots take, so map libraries can keep their own controls clear of them.
|
|
310
|
+
*/
|
|
261
311
|
height?: number | string;
|
|
262
312
|
/** Glass for every surface in the slots (default) or solid surfaces. */
|
|
263
313
|
surface?: Surface;
|
|
@@ -304,6 +354,11 @@ export interface TableProps extends BaseProps {
|
|
|
304
354
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- rows are app data
|
|
305
355
|
rows: Record<string, any>[];
|
|
306
356
|
animate?: boolean;
|
|
357
|
+
/**
|
|
358
|
+
* Cards instead of columns when the table's box is narrow (up to 600px): every row stacks its
|
|
359
|
+
* cells, each with its column label. Without it narrow tables scroll sideways.
|
|
360
|
+
*/
|
|
361
|
+
stack?: boolean;
|
|
307
362
|
}
|
|
308
363
|
export interface ProgressProps extends BaseProps {
|
|
309
364
|
value: number;
|
|
@@ -324,8 +379,21 @@ export interface EmptyStateProps extends BaseProps {
|
|
|
324
379
|
tint?: Tint;
|
|
325
380
|
action?: ReactNode;
|
|
326
381
|
}
|
|
382
|
+
/** A breadcrumb: a plain label, or one with an address or a handler. */
|
|
383
|
+
export interface Crumb {
|
|
384
|
+
label: string;
|
|
385
|
+
href?: string;
|
|
386
|
+
onClick?: () => void;
|
|
387
|
+
}
|
|
327
388
|
export interface BreadcrumbProps extends BaseProps {
|
|
328
|
-
|
|
389
|
+
/** The trail; the last one is the current page. Items with `href` are links, with `onClick` buttons. */
|
|
390
|
+
items: (string | Crumb)[];
|
|
391
|
+
/** The element links render as (default `a`), e.g. Next.js `Link`. */
|
|
392
|
+
linkAs?: ElementType;
|
|
393
|
+
/** Makes every crumb but the last a button; receives its index. */
|
|
394
|
+
onNavigate?: (index: number) => void;
|
|
395
|
+
/** Accessible name of the navigation (default "Breadcrumb"). */
|
|
396
|
+
label?: string;
|
|
329
397
|
}
|
|
330
398
|
export interface PaginationProps extends BaseProps {
|
|
331
399
|
/** Number of pages. */
|
|
@@ -339,10 +407,17 @@ export interface PaginationProps extends BaseProps {
|
|
|
339
407
|
defaultPage?: number;
|
|
340
408
|
/** A page was picked (previous, next or a number); receives the new 1-based page. */
|
|
341
409
|
onChange?: (page: number) => void;
|
|
410
|
+
/** Link mode for server-rendered lists: the address of a page; pages become links. */
|
|
411
|
+
href?: (page: number) => string;
|
|
412
|
+
/** The element links render as (default `a`), e.g. Next.js `Link`. */
|
|
413
|
+
linkAs?: ElementType;
|
|
414
|
+
/** Accessible name of the navigation (default "Pagination"), e.g. "Search results pages". */
|
|
415
|
+
label?: string;
|
|
342
416
|
}
|
|
343
417
|
export interface AppShellProps extends BaseProps {
|
|
344
418
|
active?: string;
|
|
345
|
-
|
|
419
|
+
/** The product name, or a node (a logo mark with the name; collapsed sidebars show it whole). */
|
|
420
|
+
brand?: ReactNode;
|
|
346
421
|
tag?: string;
|
|
347
422
|
nav?: NavItem[];
|
|
348
423
|
user?: { name: string; email?: string };
|
|
@@ -355,6 +430,19 @@ export interface AppShellProps extends BaseProps {
|
|
|
355
430
|
dockItems?: DockProps["items"];
|
|
356
431
|
railTop?: RailItem[];
|
|
357
432
|
railBottom?: RailItem[];
|
|
433
|
+
/**
|
|
434
|
+
* `top` (default): navigation in the top bar, tools in the side rail. `sidebar`: a labelled
|
|
435
|
+
* sidebar on the frame, with groups, nesting and a drawer on phones.
|
|
436
|
+
*/
|
|
437
|
+
navigation?: "top" | "sidebar";
|
|
438
|
+
/** With `navigation="sidebar"`: groups instead of the flat `nav` list. */
|
|
439
|
+
sidebarGroups?: SidebarGroup[];
|
|
440
|
+
/** With `navigation="sidebar"`: more sidebar props (collapsed, storageKey, shortcut, linkAs …). */
|
|
441
|
+
sidebar?: Partial<Omit<SidebarProps, "variant" | "groups">>;
|
|
442
|
+
/** With `navigation="sidebar"`: the workspace switcher at the top instead of the brand. */
|
|
443
|
+
workspaces?: WorkspaceSwitcherProps;
|
|
444
|
+
/** The account menu's entries (with `navigation="sidebar"` at the foot of the sidebar). */
|
|
445
|
+
userMenu?: (MenuItem | "-")[];
|
|
358
446
|
children?: ReactNode;
|
|
359
447
|
}
|
|
360
448
|
export interface StaggerProps extends BaseProps {
|
|
@@ -372,6 +460,8 @@ export interface CountUpProps extends BaseProps {
|
|
|
372
460
|
duration?: number;
|
|
373
461
|
delay?: number;
|
|
374
462
|
className?: string;
|
|
463
|
+
/** `false`: show the value without counting (it is always the value on the server). */
|
|
464
|
+
animate?: boolean;
|
|
375
465
|
}
|
|
376
466
|
export interface ListRowProps extends BaseProps {
|
|
377
467
|
avatar?: string;
|
|
@@ -385,6 +475,18 @@ export interface ListRowProps extends BaseProps {
|
|
|
385
475
|
unread?: boolean;
|
|
386
476
|
active?: boolean;
|
|
387
477
|
onClick?: () => void;
|
|
478
|
+
/** Makes the row a link (with `linkAs` for a router's link). */
|
|
479
|
+
href?: string;
|
|
480
|
+
linkAs?: ElementType;
|
|
481
|
+
/**
|
|
482
|
+
* Buttons of the row's own (rename, remove …), outside the clickable area so nothing interactive
|
|
483
|
+
* is nested. Without `onClick` and `href` the row is not interactive at all.
|
|
484
|
+
*/
|
|
485
|
+
actions?: ReactNode;
|
|
486
|
+
/** Lines the title may take before it ends in an ellipsis (default: it wraps freely). */
|
|
487
|
+
titleLines?: number;
|
|
488
|
+
/** Lines the subtitle may take (default 1); badges and facts wrap within them. */
|
|
489
|
+
subtitleLines?: number;
|
|
388
490
|
}
|
|
389
491
|
export interface TimelineProps extends BaseProps {
|
|
390
492
|
items: {
|
|
@@ -673,6 +775,14 @@ export interface TextFieldProps extends Omit<FormFieldProps, "children"> {
|
|
|
673
775
|
inputMode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search";
|
|
674
776
|
onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
|
|
675
777
|
onBlur?: (e: ChangeEvent<HTMLInputElement>) => void;
|
|
778
|
+
onKeyDown?: (e: KeyboardEvent<HTMLInputElement>) => void;
|
|
779
|
+
/**
|
|
780
|
+
* An interactive control at the end of the field (an `IconButton`: clear, copy, locate …). Unlike
|
|
781
|
+
* `suffix` it can be clicked, and it stays when the field shows an error or success mark.
|
|
782
|
+
*/
|
|
783
|
+
action?: ReactNode;
|
|
784
|
+
/** For `type="password"`: a button that shows and hides the password (default true). */
|
|
785
|
+
reveal?: boolean;
|
|
676
786
|
}
|
|
677
787
|
export interface RadioGroupProps extends BaseProps {
|
|
678
788
|
label?: string;
|
|
@@ -766,10 +876,18 @@ export interface SliderProps extends BaseProps {
|
|
|
766
876
|
marks?: boolean;
|
|
767
877
|
hint?: string;
|
|
768
878
|
}
|
|
879
|
+
export interface OtpInputHandle {
|
|
880
|
+
/** Empties every cell and focuses the first. */
|
|
881
|
+
reset: () => void;
|
|
882
|
+
}
|
|
769
883
|
export interface OtpInputProps extends BaseProps {
|
|
770
884
|
length?: number;
|
|
771
885
|
onComplete?: (code: string) => void;
|
|
772
886
|
error?: boolean;
|
|
887
|
+
/** Empties the cells when `error` turns on, ready for the next try (default true). */
|
|
888
|
+
clearOnError?: boolean;
|
|
889
|
+
/** `ref.current.reset()` empties the cells on demand. */
|
|
890
|
+
ref?: Ref<OtpInputHandle>;
|
|
773
891
|
label?: string;
|
|
774
892
|
}
|
|
775
893
|
export interface UploadFile {
|
|
@@ -789,9 +907,10 @@ export interface FileDropProps extends BaseProps {
|
|
|
789
907
|
/**
|
|
790
908
|
* The person picked or dropped files: the real `File` objects, after `accept` and `multiple`.
|
|
791
909
|
* Upload them yourself. To show progress, control `files` and set each `progress`; an
|
|
792
|
-
* uncontrolled list shows them with their size only.
|
|
910
|
+
* uncontrolled list shows them with their size only. Return `false` to list none of them, or
|
|
911
|
+
* the files to list (for example after checking their size).
|
|
793
912
|
*/
|
|
794
|
-
onFiles?: (files: File[]) => void;
|
|
913
|
+
onFiles?: (files: File[]) => void | boolean | File[];
|
|
795
914
|
/** Dropped files that do not match `accept` (show an inline Alert). */
|
|
796
915
|
onReject?: (files: File[]) => void;
|
|
797
916
|
/** A listed file was removed or its upload cancelled. */
|
|
@@ -806,6 +925,10 @@ export interface FileDropProps extends BaseProps {
|
|
|
806
925
|
/** Accepted types, as for `<input type="file">` ("image/*,.pdf"); also checked on drop. */
|
|
807
926
|
accept?: string;
|
|
808
927
|
multiple?: boolean;
|
|
928
|
+
/** No picking or dropping; the list stays visible. */
|
|
929
|
+
disabled?: boolean;
|
|
930
|
+
/** Takes part in a surrounding form under this name: the listed files are submitted with it. */
|
|
931
|
+
name?: string;
|
|
809
932
|
}
|
|
810
933
|
export interface TooltipProps extends BaseProps {
|
|
811
934
|
label: ReactNode;
|
|
@@ -962,6 +1085,8 @@ export interface LegendProps extends BaseProps {
|
|
|
962
1085
|
/* ── Kit 3: AI chat & agents ── */
|
|
963
1086
|
export interface Source {
|
|
964
1087
|
title: string;
|
|
1088
|
+
/** More about the source in a tooltip: dataset, publisher, date ("Stand") … */
|
|
1089
|
+
detail?: ReactNode;
|
|
965
1090
|
icon?: IconName;
|
|
966
1091
|
url?: string;
|
|
967
1092
|
onClick?: () => void;
|
|
@@ -1175,6 +1300,11 @@ export interface CheckoutStepsProps extends BaseProps {
|
|
|
1175
1300
|
steps?: string[];
|
|
1176
1301
|
current?: number;
|
|
1177
1302
|
onPick?: (i: number) => void;
|
|
1303
|
+
/**
|
|
1304
|
+
* Numbers only, with the label of the current step (screen readers still hear every label).
|
|
1305
|
+
* Narrow containers (up to 560px) get this on their own.
|
|
1306
|
+
*/
|
|
1307
|
+
compact?: boolean;
|
|
1178
1308
|
}
|
|
1179
1309
|
export interface OrderTimelineProps extends BaseProps {
|
|
1180
1310
|
status: "Placed" | "Paid" | "Packed" | "Shipped" | "Delivered" | "Refunded" | "Cancelled";
|
|
@@ -1183,7 +1313,15 @@ export interface OrderTimelineProps extends BaseProps {
|
|
|
1183
1313
|
export interface PlanCardProps extends BaseProps {
|
|
1184
1314
|
name: string;
|
|
1185
1315
|
text?: string;
|
|
1186
|
-
|
|
1316
|
+
/**
|
|
1317
|
+
* A number is formatted as money (0 = "Free", null = "Let's talk"); any other node is shown as
|
|
1318
|
+
* it is, e.g. a placeholder ("—") or a price the app formatted itself.
|
|
1319
|
+
*/
|
|
1320
|
+
price: number | null | ReactNode;
|
|
1321
|
+
/** Before the price, e.g. "from". */
|
|
1322
|
+
pricePrefix?: ReactNode;
|
|
1323
|
+
/** Under the price: net or gross, billed yearly, VAT note … */
|
|
1324
|
+
priceNote?: ReactNode;
|
|
1187
1325
|
was?: number;
|
|
1188
1326
|
per?: string;
|
|
1189
1327
|
features?: string[];
|
|
@@ -1194,6 +1332,9 @@ export interface PlanCardProps extends BaseProps {
|
|
|
1194
1332
|
/** Disable the button, e.g. while a checkout starts or when the plan cannot be picked. */
|
|
1195
1333
|
disabled?: boolean;
|
|
1196
1334
|
onPick?: () => void;
|
|
1335
|
+
/** The action as a link (checkout or sign-up page), with `linkAs` for a router's link. */
|
|
1336
|
+
href?: string;
|
|
1337
|
+
linkAs?: ElementType;
|
|
1197
1338
|
}
|
|
1198
1339
|
|
|
1199
1340
|
/* ── Kit 3: system screens ── */
|
|
@@ -1885,6 +2026,8 @@ export interface TilePickerProps extends BaseProps {
|
|
|
1885
2026
|
multiple?: boolean;
|
|
1886
2027
|
min?: number;
|
|
1887
2028
|
label?: string;
|
|
2029
|
+
/** `list`: one compact row per option (small picture or icon beside the label), e.g. on phones. */
|
|
2030
|
+
layout?: "grid" | "list";
|
|
1888
2031
|
}
|
|
1889
2032
|
export interface ColorFieldProps extends BaseProps {
|
|
1890
2033
|
label?: ReactNode;
|
|
@@ -2134,6 +2277,8 @@ export interface WorkspaceSwitcherProps extends BaseProps {
|
|
|
2134
2277
|
footer?: ReactNode;
|
|
2135
2278
|
variant?: "frame";
|
|
2136
2279
|
width?: number;
|
|
2280
|
+
/** Only the workspace's mark, its name as the accessible name (a collapsed sidebar). */
|
|
2281
|
+
compact?: boolean;
|
|
2137
2282
|
}
|
|
2138
2283
|
export interface ExportDialogProps extends BaseProps {
|
|
2139
2284
|
open?: boolean;
|
|
@@ -2158,6 +2303,12 @@ export interface ExportDialogProps extends BaseProps {
|
|
|
2158
2303
|
}
|
|
2159
2304
|
export interface TwoFactorSetupProps extends BaseProps {
|
|
2160
2305
|
qr?: ReactNode;
|
|
2306
|
+
/** The otpauth:// link: the kit draws its QR code (instead of `qr`). */
|
|
2307
|
+
qrValue?: string;
|
|
2308
|
+
/** A "Trust this device" checkbox under the code field; a string replaces its label. */
|
|
2309
|
+
trustDevice?: boolean | string;
|
|
2310
|
+
/** The trust checkbox changed. */
|
|
2311
|
+
onTrustChange?: (trusted: boolean) => void;
|
|
2161
2312
|
secret: string;
|
|
2162
2313
|
onVerify?: (code: string) => boolean | Promise<boolean>;
|
|
2163
2314
|
codes?: string[];
|
|
@@ -2214,7 +2365,13 @@ export interface GalleryProps extends BaseProps {
|
|
|
2214
2365
|
loading?: "lazy" | "eager";
|
|
2215
2366
|
/** `referrerPolicy` of every image, e.g. `"no-referrer"` for photos from other hosts. */
|
|
2216
2367
|
referrerPolicy?: ImageReferrerPolicy;
|
|
2368
|
+
/** First image when uncontrolled. */
|
|
2217
2369
|
start?: number;
|
|
2370
|
+
/** The shown image (controlled, 0-based), with `onIndexChange`. */
|
|
2371
|
+
index?: number;
|
|
2372
|
+
onIndexChange?: (index: number) => void;
|
|
2373
|
+
/** Accessible name of the gallery (default "Images"), e.g. the listing's title. */
|
|
2374
|
+
label?: string;
|
|
2218
2375
|
ratio?: string;
|
|
2219
2376
|
thumbs?: boolean;
|
|
2220
2377
|
fullscreen?: boolean;
|
|
@@ -2356,13 +2513,21 @@ export interface CookieConsentProps extends BaseProps {
|
|
|
2356
2513
|
categories?: {
|
|
2357
2514
|
id: string;
|
|
2358
2515
|
label: string;
|
|
2359
|
-
|
|
2516
|
+
/** What the category covers; may hold a link to the details. */
|
|
2517
|
+
text?: ReactNode;
|
|
2360
2518
|
required?: boolean;
|
|
2361
2519
|
default?: boolean;
|
|
2362
2520
|
}[];
|
|
2363
2521
|
onSave?: (choices: Record<string, boolean>) => void;
|
|
2364
2522
|
open?: boolean;
|
|
2365
2523
|
inline?: boolean;
|
|
2524
|
+
/**
|
|
2525
|
+
* "Only necessary" and "Accept all" with the same weight (both secondary buttons), as German
|
|
2526
|
+
* data protection authorities expect on the first layer.
|
|
2527
|
+
*/
|
|
2528
|
+
equalChoice?: boolean;
|
|
2529
|
+
/** Id of the banner (its text is referenced by `aria-describedby`). */
|
|
2530
|
+
id?: string;
|
|
2366
2531
|
}
|
|
2367
2532
|
export interface AnnouncementBarProps extends BaseProps {
|
|
2368
2533
|
children: ReactNode;
|
|
@@ -2432,6 +2597,8 @@ export interface ToggleGroupProps extends BaseProps {
|
|
|
2432
2597
|
/** Accessible name of the group. */
|
|
2433
2598
|
label: string;
|
|
2434
2599
|
size?: "sm" | "md";
|
|
2600
|
+
/** Fills the width and shares it evenly; labels end in an ellipsis when space runs short. */
|
|
2601
|
+
block?: boolean;
|
|
2435
2602
|
}
|
|
2436
2603
|
export interface ButtonGroupProps extends BaseProps {
|
|
2437
2604
|
/** Accessible name of the group. */
|
|
@@ -2515,6 +2682,8 @@ export interface SelectMenuProps extends FieldProps, BaseProps {
|
|
|
2515
2682
|
onChange?: (value: string) => void;
|
|
2516
2683
|
placeholder?: string;
|
|
2517
2684
|
disabled?: boolean;
|
|
2685
|
+
/** `sm`: a compact trigger, e.g. a sort menu next to a heading. */
|
|
2686
|
+
size?: "sm" | "md";
|
|
2518
2687
|
}
|
|
2519
2688
|
|
|
2520
2689
|
/* ── Navigation ── */
|
|
@@ -2551,31 +2720,91 @@ export interface NavigationMenuProps extends BaseProps {
|
|
|
2551
2720
|
export interface SidebarItem {
|
|
2552
2721
|
id?: string;
|
|
2553
2722
|
label: string;
|
|
2554
|
-
|
|
2723
|
+
/** Required for pages; options in a filter group usually go without. */
|
|
2724
|
+
icon?: IconName;
|
|
2555
2725
|
count?: number;
|
|
2556
|
-
/**
|
|
2726
|
+
/** A small marker instead of a number: `"dot"` for new activity, or a short word such as "New". */
|
|
2727
|
+
badge?: string;
|
|
2728
|
+
/** Renders the item as a link to this address (with `linkAs` for a router's link, e.g. Next.js `Link`). */
|
|
2729
|
+
href?: string;
|
|
2730
|
+
/** Opens `href` in a new tab and says so. */
|
|
2731
|
+
external?: boolean;
|
|
2732
|
+
disabled?: boolean;
|
|
2733
|
+
/** A menu behind a "…" button on the item (rename, share, remove …). */
|
|
2734
|
+
actions?: (MenuItem | "-")[];
|
|
2735
|
+
/** One level of nested pages, shown when the item is open (as a flyout when the sidebar is collapsed). */
|
|
2557
2736
|
items?: Omit<SidebarItem, "items">[];
|
|
2737
|
+
/**
|
|
2738
|
+
* Makes the item a filter option: a checkbox (or a radio in a group with `select: "single"`)
|
|
2739
|
+
* with its label and `count`, instead of a page.
|
|
2740
|
+
*/
|
|
2741
|
+
checked?: boolean;
|
|
2742
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
2558
2743
|
}
|
|
2559
2744
|
export interface SidebarGroup {
|
|
2745
|
+
id?: string;
|
|
2560
2746
|
label?: string;
|
|
2561
|
-
items
|
|
2747
|
+
items?: SidebarItem[];
|
|
2748
|
+
/** Any content instead of (or after) the items: a `RangeSlider`, `DateRangePicker`, chips … */
|
|
2749
|
+
content?: ReactNode;
|
|
2750
|
+
/** For filter options (items with `checked`): `single` makes them radios (one choice per group). */
|
|
2751
|
+
select?: "multiple" | "single";
|
|
2752
|
+
/** The label folds the group open and shut. */
|
|
2753
|
+
collapsible?: boolean;
|
|
2754
|
+
/** For a collapsible group: starts open (default true). */
|
|
2755
|
+
defaultOpen?: boolean;
|
|
2756
|
+
/** A small button next to the label, e.g. "+" to add a project. */
|
|
2757
|
+
action?: { label: string; icon?: IconName; onClick?: () => void };
|
|
2562
2758
|
}
|
|
2563
2759
|
export interface SidebarProps extends BaseProps {
|
|
2564
2760
|
groups: SidebarGroup[];
|
|
2565
2761
|
/** Id (or label) of the current page. */
|
|
2566
2762
|
current?: string;
|
|
2567
2763
|
onPick?: (id: string) => void;
|
|
2764
|
+
/**
|
|
2765
|
+
* `floating` (default): a card with rounded corners and a shadow. `attached`: full height, flush
|
|
2766
|
+
* with the edge of the screen, divided by a line. `shell`: on the dark frame of `AppShell`.
|
|
2767
|
+
*/
|
|
2768
|
+
variant?: "floating" | "attached" | "shell";
|
|
2568
2769
|
/** Icons only. */
|
|
2569
2770
|
collapsed?: boolean;
|
|
2570
2771
|
defaultCollapsed?: boolean;
|
|
2571
2772
|
onCollapsedChange?: (collapsed: boolean) => void;
|
|
2572
|
-
/**
|
|
2573
|
-
|
|
2574
|
-
/**
|
|
2575
|
-
|
|
2576
|
-
/**
|
|
2773
|
+
/** Remember the collapsed state in the browser under this key. */
|
|
2774
|
+
storageKey?: string;
|
|
2775
|
+
/** ⌘B (Ctrl+B) collapses and expands the sidebar, except while typing in a field. */
|
|
2776
|
+
shortcut?: boolean;
|
|
2777
|
+
/** The element items with an `href` render as (default `a`), e.g. Next.js `Link`. */
|
|
2778
|
+
linkAs?: ElementType;
|
|
2779
|
+
/** On phones (up to 760px wide): whether the drawer is open (controlled). */
|
|
2780
|
+
mobileOpen?: boolean;
|
|
2781
|
+
onMobileOpenChange?: (open: boolean) => void;
|
|
2782
|
+
/** Top of the sidebar (brand, `WorkspaceSwitcher`); a function gets the collapsed state. */
|
|
2783
|
+
header?: ReactNode | ((state: { collapsed: boolean }) => ReactNode);
|
|
2784
|
+
/** Bottom of the sidebar (`UserMenu`, settings); a function gets the collapsed state. */
|
|
2785
|
+
footer?: ReactNode | ((state: { collapsed: boolean }) => ReactNode);
|
|
2786
|
+
/**
|
|
2787
|
+
* `nav` (default) for app navigation. `aside` for filters, settings or other tools beside the
|
|
2788
|
+
* content: a complementary region instead of a navigation landmark.
|
|
2789
|
+
*/
|
|
2790
|
+
as?: "nav" | "aside";
|
|
2791
|
+
/** Offers the collapse button and the icons-only mode (default true; filters usually set false). */
|
|
2792
|
+
collapsible?: boolean;
|
|
2793
|
+
/** Accessible name of the navigation (or the aside). */
|
|
2577
2794
|
label?: string;
|
|
2578
2795
|
}
|
|
2796
|
+
export interface UserMenuProps extends BaseProps {
|
|
2797
|
+
name: string;
|
|
2798
|
+
email?: string;
|
|
2799
|
+
/** Picture URL; initials otherwise. */
|
|
2800
|
+
avatar?: string;
|
|
2801
|
+
/** The menu: profile, settings, sign out … */
|
|
2802
|
+
items?: (MenuItem | "-")[];
|
|
2803
|
+
/** Only the avatar (a collapsed sidebar). */
|
|
2804
|
+
compact?: boolean;
|
|
2805
|
+
/** Where the menu opens (default `top`, for the foot of a sidebar). */
|
|
2806
|
+
side?: "top" | "bottom";
|
|
2807
|
+
}
|
|
2579
2808
|
|
|
2580
2809
|
/* ── ResizablePanels ── */
|
|
2581
2810
|
export interface ResizablePanelsProps extends BaseProps {
|
|
@@ -2590,3 +2819,17 @@ export interface ResizablePanelsProps extends BaseProps {
|
|
|
2590
2819
|
/** Accessible names of the panels, used for the resize handles. */
|
|
2591
2820
|
labels?: string[];
|
|
2592
2821
|
}
|
|
2822
|
+
|
|
2823
|
+
/* ── QrCode ── */
|
|
2824
|
+
export interface QrCodeProps extends BaseProps {
|
|
2825
|
+
/** The text to encode: an otpauth:// link, a URL … */
|
|
2826
|
+
value: string;
|
|
2827
|
+
/** Error correction: L, M (default), Q or H. */
|
|
2828
|
+
level?: "L" | "M" | "Q" | "H";
|
|
2829
|
+
/** Width and height (default: the width of its container). */
|
|
2830
|
+
size?: number | string;
|
|
2831
|
+
/** Light modules around the code (default 4, the standard quiet zone). */
|
|
2832
|
+
quiet?: number;
|
|
2833
|
+
/** Accessible name (default "QR code"). */
|
|
2834
|
+
label?: string;
|
|
2835
|
+
}
|
|
@@ -31,7 +31,11 @@ import type {
|
|
|
31
31
|
export function SubNav(p: SubNavProps) {
|
|
32
32
|
const t = useStrings(WORKSPACE_STRINGS);
|
|
33
33
|
return (
|
|
34
|
-
<nav
|
|
34
|
+
<nav
|
|
35
|
+
style={p.style}
|
|
36
|
+
className={cx("tf-subnav", p.className)}
|
|
37
|
+
aria-label={t.sectionPages(p.eyebrow)}
|
|
38
|
+
>
|
|
35
39
|
<div className="tf-subnav-head">
|
|
36
40
|
{p.eyebrow && <span className="tf-subnav-eyebrow">{p.eyebrow}</span>}
|
|
37
41
|
{p.action && (
|
|
@@ -74,8 +78,9 @@ export function Drawer(p: DrawerProps) {
|
|
|
74
78
|
if (!pr.mounted) return null;
|
|
75
79
|
return (
|
|
76
80
|
<div
|
|
81
|
+
style={p.style}
|
|
77
82
|
{...leaving(pr.closing)}
|
|
78
|
-
className={cx("tf-drawer-wrap", p.inline && "inline")}
|
|
83
|
+
className={cx("tf-drawer-wrap", p.inline && "inline", p.className)}
|
|
79
84
|
onMouseDown={(e) => {
|
|
80
85
|
if (e.target === e.currentTarget && p.onClose) p.onClose?.();
|
|
81
86
|
}}
|
|
@@ -180,8 +185,9 @@ export function CommandPalette(p: CommandPaletteProps) {
|
|
|
180
185
|
if (!pr.mounted) return null;
|
|
181
186
|
return (
|
|
182
187
|
<div
|
|
188
|
+
style={p.style}
|
|
183
189
|
{...leaving(pr.closing)}
|
|
184
|
-
className={cx("tf-palette-wrap", p.inline && "inline")}
|
|
190
|
+
className={cx("tf-palette-wrap", p.inline && "inline", p.className)}
|
|
185
191
|
onMouseDown={(e) => {
|
|
186
192
|
if (e.target === e.currentTarget && p.onClose) p.onClose?.();
|
|
187
193
|
}}
|
|
@@ -273,7 +279,12 @@ export function NotificationList(p: NotificationListProps) {
|
|
|
273
279
|
const f = React.useState<"all" | "unread">("all"),
|
|
274
280
|
items = (p.items || []).filter((n) => f[0] === "all" || n.unread);
|
|
275
281
|
return (
|
|
276
|
-
<div
|
|
282
|
+
<div
|
|
283
|
+
style={p.style}
|
|
284
|
+
className={cx("tf-notes", p.className)}
|
|
285
|
+
role="region"
|
|
286
|
+
aria-label={t.notifications}
|
|
287
|
+
>
|
|
277
288
|
<div
|
|
278
289
|
className="tf-header"
|
|
279
290
|
style={{
|
|
@@ -353,12 +364,13 @@ export function Flow(p: FlowProps) {
|
|
|
353
364
|
const t = useStrings(WORKSPACE_STRINGS);
|
|
354
365
|
return (
|
|
355
366
|
<ol
|
|
356
|
-
className="tf-flow tf-stagger"
|
|
357
|
-
style={
|
|
358
|
-
{
|
|
367
|
+
className={cx("tf-flow tf-stagger", p.className)}
|
|
368
|
+
style={{
|
|
369
|
+
...({
|
|
359
370
|
"--base": "120ms",
|
|
360
|
-
} as React.CSSProperties
|
|
361
|
-
|
|
371
|
+
} as React.CSSProperties),
|
|
372
|
+
...p.style,
|
|
373
|
+
}}
|
|
362
374
|
>
|
|
363
375
|
{(p.steps || []).map((s, i) => {
|
|
364
376
|
const steps = STEP(),
|
|
@@ -467,7 +479,7 @@ export function FileThumb(p: FileThumbProps) {
|
|
|
467
479
|
</span>
|
|
468
480
|
);
|
|
469
481
|
return (
|
|
470
|
-
<span className="tf-t-doc">
|
|
482
|
+
<span style={p.style} className={cx("tf-t-doc", p.className)}>
|
|
471
483
|
<b>{(p.title || "").replace(/\.[^.]+$/, "")}</b>
|
|
472
484
|
{Array.from(
|
|
473
485
|
{
|
|
@@ -489,7 +501,12 @@ export function FileCard(p: FileCardProps) {
|
|
|
489
501
|
const t = useStrings(WORKSPACE_STRINGS);
|
|
490
502
|
const k = FILE_KIND[p.kind] || FILE_KIND.doc;
|
|
491
503
|
return (
|
|
492
|
-
<button
|
|
504
|
+
<button
|
|
505
|
+
style={p.style}
|
|
506
|
+
type="button"
|
|
507
|
+
className={cx("tf-filecard", p.className)}
|
|
508
|
+
onClick={p.onClick}
|
|
509
|
+
>
|
|
493
510
|
<span className={"tf-thumb tf-bg-" + k[1]}>
|
|
494
511
|
<FileThumb kind={p.kind} title={p.name} />
|
|
495
512
|
</span>
|
|
@@ -507,7 +524,12 @@ export function Wizard(p: WizardProps) {
|
|
|
507
524
|
cur = p.current || 0,
|
|
508
525
|
done = p.done || {};
|
|
509
526
|
return (
|
|
510
|
-
<div
|
|
527
|
+
<div
|
|
528
|
+
style={p.style}
|
|
529
|
+
className={cx("tf-wizard", p.className)}
|
|
530
|
+
role="group"
|
|
531
|
+
aria-label={p.label || t.setup}
|
|
532
|
+
>
|
|
511
533
|
<aside className="tf-wizard-rail">
|
|
512
534
|
{p.brand && (
|
|
513
535
|
<span
|
|
@@ -570,7 +592,7 @@ export function PermissionMatrix(p: PermissionMatrixProps) {
|
|
|
570
592
|
const box = React.useRef<HTMLDivElement>(null);
|
|
571
593
|
useScrollFocus(box);
|
|
572
594
|
return (
|
|
573
|
-
<div ref={box} className="tf-scroll">
|
|
595
|
+
<div style={p.style} ref={box} className={cx("tf-scroll", p.className)}>
|
|
574
596
|
<table className="tf-table tf-perm">
|
|
575
597
|
<thead>
|
|
576
598
|
<tr>
|
|
@@ -648,7 +670,7 @@ export function InvoicePreview(p: InvoicePreviewProps) {
|
|
|
648
670
|
});
|
|
649
671
|
const fmt = p.format || money2;
|
|
650
672
|
return (
|
|
651
|
-
<div className="tf-paper">
|
|
673
|
+
<div style={p.style} className={cx("tf-paper", p.className)}>
|
|
652
674
|
<div className="tf-paper-top">
|
|
653
675
|
<div>
|
|
654
676
|
{p.brand && (
|
|
@@ -720,7 +742,7 @@ export function TransactionRow(p: TransactionRowProps) {
|
|
|
720
742
|
const open = React.useState(false),
|
|
721
743
|
inc = p.amount > 0;
|
|
722
744
|
return (
|
|
723
|
-
<div className={cx("tf-tx", !p.matched && "unmatched")}>
|
|
745
|
+
<div style={p.style} className={cx("tf-tx", !p.matched && "unmatched", p.className)}>
|
|
724
746
|
<div className="tf-tx-row">
|
|
725
747
|
<TintIcon icon={inc ? "download" : "send"} tint={inc ? "mint" : "plain"} />
|
|
726
748
|
<div className="tf-tx-text">
|