@evinvest/uikit 0.24.0 → 0.26.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/README.md +147 -4
- package/dist/components/alert-dialog.js +1 -1
- package/dist/components/alert-dialog.js.map +1 -1
- package/dist/components/app-shell.js +85 -0
- package/dist/components/app-shell.js.map +1 -0
- package/dist/components/bottom-tab-bar.js +91 -0
- package/dist/components/bottom-tab-bar.js.map +1 -0
- package/dist/components/dialog.js +2 -1
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/drawer.js +6 -4
- package/dist/components/drawer.js.map +1 -1
- package/dist/components/list-rows.js +73 -0
- package/dist/components/list-rows.js.map +1 -0
- package/dist/components/mobile-app-bar.js +51 -0
- package/dist/components/mobile-app-bar.js.map +1 -0
- package/dist/components/nav-badge.js +61 -0
- package/dist/components/nav-badge.js.map +1 -0
- package/dist/components/nav-link.js +50 -0
- package/dist/components/nav-link.js.map +1 -0
- package/dist/components/nav-model.js +55 -0
- package/dist/components/nav-model.js.map +1 -0
- package/dist/components/page-frame.js +92 -0
- package/dist/components/page-frame.js.map +1 -0
- package/dist/components/resource-error.js +47 -0
- package/dist/components/resource-error.js.map +1 -0
- package/dist/components/section-nav.js +86 -0
- package/dist/components/section-nav.js.map +1 -0
- package/dist/components/settled.js +19 -0
- package/dist/components/settled.js.map +1 -0
- package/dist/components/sheet.js +8 -2
- package/dist/components/sheet.js.map +1 -1
- package/dist/components/shell-icons.js +57 -0
- package/dist/components/shell-icons.js.map +1 -0
- package/dist/components/shell-nav.js +141 -0
- package/dist/components/shell-nav.js.map +1 -0
- package/dist/components/system-banner.js +53 -0
- package/dist/components/system-banner.js.map +1 -0
- package/dist/components/use-shell-nav.js +46 -0
- package/dist/components/use-shell-nav.js.map +1 -0
- package/dist/generated/alert-dialog.js +2 -2
- package/dist/generated/alert-dialog.js.map +1 -1
- package/dist/generated/dialog.js +3 -3
- package/dist/generated/dialog.js.map +1 -1
- package/dist/generated/drawer.js +1 -1
- package/dist/generated/drawer.js.map +1 -1
- package/dist/generated/sheet.js +3 -3
- package/dist/generated/sheet.js.map +1 -1
- package/dist/index.d.ts +451 -6
- package/dist/index.js +12 -0
- package/dist/primitives/focus-scope.js +22 -6
- package/dist/primitives/focus-scope.js.map +1 -1
- package/package.json +1 -1
- package/styles/theme.css +180 -1
- package/styles/tokens.css +182 -2
package/dist/generated/drawer.js
CHANGED
|
@@ -5,7 +5,7 @@ const drawerDirectionClasses = {
|
|
|
5
5
|
"left": "inset-y-0 left-0 w-3/4 flex-row border-r sm:max-w-sm",
|
|
6
6
|
"right": "inset-y-0 right-0 w-3/4 flex-row border-l sm:max-w-sm"
|
|
7
7
|
};
|
|
8
|
-
const DRAWER_OVERLAY = "fixed inset-0 z-50 bg-black/50";
|
|
8
|
+
const DRAWER_OVERLAY = "fixed inset-0 z-50 bg-black/50 data-[state=closed]:pointer-events-none";
|
|
9
9
|
const DRAWER_HANDLE = "bg-muted mx-auto mt-4 h-2 w-[100px] shrink-0 rounded-full";
|
|
10
10
|
const DRAWER_BODY = "flex min-h-0 flex-1 flex-col overflow-y-auto";
|
|
11
11
|
const DRAWER_HEADER = "flex flex-col gap-0.5 p-4 text-center sm:gap-1.5 sm:text-left";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/generated/drawer.ts"],"sourcesContent":["// AUTO-GENERATED by `nix run .#gen` — do not edit.\n\nexport const DRAWER_CONTENT_BASE = \"bg-background fixed z-50 flex h-auto border border-border\";\n\nexport const drawerDirectionClasses = {\n \"bottom\": \"inset-x-0 bottom-0 mt-24 max-h-[80vh] flex-col rounded-t-lg border-b-0\",\n \"top\": \"inset-x-0 top-0 mb-24 max-h-[80vh] flex-col rounded-b-lg border-t-0\",\n \"left\": \"inset-y-0 left-0 w-3/4 flex-row border-r sm:max-w-sm\",\n \"right\": \"inset-y-0 right-0 w-3/4 flex-row border-l sm:max-w-sm\",\n} as const;\nexport type DrawerDirection = keyof typeof drawerDirectionClasses;\n\nexport const DRAWER_OVERLAY = \"fixed inset-0 z-50 bg-black/50\";\n\nexport const DRAWER_HANDLE = \"bg-muted mx-auto mt-4 h-2 w-[100px] shrink-0 rounded-full\";\n\nexport const DRAWER_BODY = \"flex min-h-0 flex-1 flex-col overflow-y-auto\";\n\nexport const DRAWER_HEADER = \"flex flex-col gap-0.5 p-4 text-center sm:gap-1.5 sm:text-left\";\n\nexport const DRAWER_FOOTER = \"mt-auto flex flex-col gap-2 p-4\";\n\nexport const DRAWER_TITLE = \"text-ink font-semibold\";\n\nexport const DRAWER_DESCRIPTION = \"text-ink-soft text-sm\";\n"],"mappings":"AAEO,MAAM,sBAAsB;AAE5B,MAAM,yBAAyB;AAAA,EACpC,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AACX;AAGO,MAAM,iBAAiB;AAEvB,MAAM,gBAAgB;AAEtB,MAAM,cAAc;AAEpB,MAAM,gBAAgB;AAEtB,MAAM,gBAAgB;AAEtB,MAAM,eAAe;AAErB,MAAM,qBAAqB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/generated/drawer.ts"],"sourcesContent":["// AUTO-GENERATED by `nix run .#gen` — do not edit.\n\nexport const DRAWER_CONTENT_BASE = \"bg-background fixed z-50 flex h-auto border border-border\";\n\nexport const drawerDirectionClasses = {\n \"bottom\": \"inset-x-0 bottom-0 mt-24 max-h-[80vh] flex-col rounded-t-lg border-b-0\",\n \"top\": \"inset-x-0 top-0 mb-24 max-h-[80vh] flex-col rounded-b-lg border-t-0\",\n \"left\": \"inset-y-0 left-0 w-3/4 flex-row border-r sm:max-w-sm\",\n \"right\": \"inset-y-0 right-0 w-3/4 flex-row border-l sm:max-w-sm\",\n} as const;\nexport type DrawerDirection = keyof typeof drawerDirectionClasses;\n\nexport const DRAWER_OVERLAY = \"fixed inset-0 z-50 bg-black/50 data-[state=closed]:pointer-events-none\";\n\nexport const DRAWER_HANDLE = \"bg-muted mx-auto mt-4 h-2 w-[100px] shrink-0 rounded-full\";\n\nexport const DRAWER_BODY = \"flex min-h-0 flex-1 flex-col overflow-y-auto\";\n\nexport const DRAWER_HEADER = \"flex flex-col gap-0.5 p-4 text-center sm:gap-1.5 sm:text-left\";\n\nexport const DRAWER_FOOTER = \"mt-auto flex flex-col gap-2 p-4\";\n\nexport const DRAWER_TITLE = \"text-ink font-semibold\";\n\nexport const DRAWER_DESCRIPTION = \"text-ink-soft text-sm\";\n"],"mappings":"AAEO,MAAM,sBAAsB;AAE5B,MAAM,yBAAyB;AAAA,EACpC,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AACX;AAGO,MAAM,iBAAiB;AAEvB,MAAM,gBAAgB;AAEtB,MAAM,cAAc;AAEpB,MAAM,gBAAgB;AAEtB,MAAM,gBAAgB;AAEtB,MAAM,eAAe;AAErB,MAAM,qBAAqB;","names":[]}
|
package/dist/generated/sheet.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const SHEET_OVERLAY = "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50";
|
|
2
|
-
const SHEET_CONTENT = "bg-background border-border data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500";
|
|
3
|
-
const SHEET_CLOSE = "ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none";
|
|
1
|
+
const SHEET_OVERLAY = "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=closed]:fill-mode-forwards data-[state=closed]:pointer-events-none fixed inset-0 z-50 bg-black/50";
|
|
2
|
+
const SHEET_CONTENT = "bg-background border-border data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=closed]:fill-mode-forwards outline-hidden";
|
|
3
|
+
const SHEET_CLOSE = "ring-offset-background focus-visible:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:pointer-events-none";
|
|
4
4
|
const SHEET_SIDE_RIGHT = "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm";
|
|
5
5
|
const SHEET_SIDE_LEFT = "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm";
|
|
6
6
|
const SHEET_SIDE_TOP = "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/generated/sheet.ts"],"sourcesContent":["// AUTO-GENERATED by `nix run .#gen` — do not edit.\n\nexport const SHEET_OVERLAY = \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\";\n\nexport const SHEET_CONTENT = \"bg-background border-border data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500\";\n\nexport const SHEET_CLOSE = \"ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none\";\n\nexport const SHEET_SIDE_RIGHT = \"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm\";\n\nexport const SHEET_SIDE_LEFT = \"data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm\";\n\nexport const SHEET_SIDE_TOP = \"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b\";\n\nexport const SHEET_SIDE_BOTTOM = \"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t\";\n\nexport const SHEET_HEADER = \"flex flex-col gap-1.5 p-4\";\n\nexport const SHEET_FOOTER = \"mt-auto flex flex-col gap-2 p-4\";\n\nexport const SHEET_TITLE = \"text-ink font-semibold\";\n\nexport const SHEET_DESCRIPTION = \"text-ink-soft text-sm\";\n"],"mappings":"AAEO,MAAM,gBAAgB;AAEtB,MAAM,gBAAgB;AAEtB,MAAM,cAAc;AAEpB,MAAM,mBAAmB;AAEzB,MAAM,kBAAkB;AAExB,MAAM,iBAAiB;AAEvB,MAAM,oBAAoB;AAE1B,MAAM,eAAe;AAErB,MAAM,eAAe;AAErB,MAAM,cAAc;AAEpB,MAAM,oBAAoB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/generated/sheet.ts"],"sourcesContent":["// AUTO-GENERATED by `nix run .#gen` — do not edit.\n\nexport const SHEET_OVERLAY = \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=closed]:fill-mode-forwards data-[state=closed]:pointer-events-none fixed inset-0 z-50 bg-black/50\";\n\nexport const SHEET_CONTENT = \"bg-background border-border data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=closed]:fill-mode-forwards outline-hidden\";\n\nexport const SHEET_CLOSE = \"ring-offset-background focus-visible:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:pointer-events-none\";\n\nexport const SHEET_SIDE_RIGHT = \"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm\";\n\nexport const SHEET_SIDE_LEFT = \"data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm\";\n\nexport const SHEET_SIDE_TOP = \"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b\";\n\nexport const SHEET_SIDE_BOTTOM = \"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t\";\n\nexport const SHEET_HEADER = \"flex flex-col gap-1.5 p-4\";\n\nexport const SHEET_FOOTER = \"mt-auto flex flex-col gap-2 p-4\";\n\nexport const SHEET_TITLE = \"text-ink font-semibold\";\n\nexport const SHEET_DESCRIPTION = \"text-ink-soft text-sm\";\n"],"mappings":"AAEO,MAAM,gBAAgB;AAEtB,MAAM,gBAAgB;AAEtB,MAAM,cAAc;AAEpB,MAAM,mBAAmB;AAEzB,MAAM,kBAAkB;AAExB,MAAM,iBAAiB;AAEvB,MAAM,oBAAoB;AAE1B,MAAM,eAAe;AAErB,MAAM,eAAe;AAErB,MAAM,cAAc;AAEpB,MAAM,oBAAoB;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -138,16 +138,34 @@ declare function useFloating(opts: {
|
|
|
138
138
|
offset?: number;
|
|
139
139
|
}): FloatingResult;
|
|
140
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Where focus lands when the scope opens. `first` is the first Tab stop inside
|
|
143
|
+
* (an input, an alert dialog's least destructive action); `container` is the
|
|
144
|
+
* scope root itself, so a reader starts at the top and the first Tab reaches the
|
|
145
|
+
* first control — right for a panel of content, where the first stop may be an
|
|
146
|
+
* action one keypress away from firing.
|
|
147
|
+
*/
|
|
148
|
+
type InitialFocus = "first" | "container";
|
|
149
|
+
interface FocusScopeOptions {
|
|
150
|
+
/** Default `first`; falls back to the container when nothing inside is focusable. */
|
|
151
|
+
initialFocus?: InitialFocus;
|
|
152
|
+
/**
|
|
153
|
+
* Where focus goes back on close when the element focused before opening is
|
|
154
|
+
* no use: `<body>` (Safari does not focus a clicked button), or detached (the
|
|
155
|
+
* opener was re-rendered away). Pass the overlay's trigger.
|
|
156
|
+
*/
|
|
157
|
+
returnFocusTo?: React.RefObject<HTMLElement | null>;
|
|
158
|
+
}
|
|
141
159
|
/**
|
|
142
160
|
* Traps Tab focus inside the returned ref's subtree and restores focus to the
|
|
143
161
|
* previously-focused element on unmount — the dep-light core of dialogs/menus,
|
|
144
|
-
* replacing `@radix-ui/react-focus-scope`. On mount, focuses
|
|
145
|
-
*
|
|
162
|
+
* replacing `@radix-ui/react-focus-scope`. On mount, focuses per
|
|
163
|
+
* `initialFocus`; the root gets `tabindex="-1"` whenever it is the target.
|
|
146
164
|
*
|
|
147
165
|
* Rust dialogs rely on the browser's native focus order within a fixed overlay;
|
|
148
166
|
* see the README "Limitations".
|
|
149
167
|
*/
|
|
150
|
-
declare function useFocusScope(enabled: boolean): React.RefObject<HTMLDivElement | null>;
|
|
168
|
+
declare function useFocusScope(enabled: boolean, { initialFocus, returnFocusTo }?: FocusScopeOptions): React.RefObject<HTMLDivElement | null>;
|
|
151
169
|
|
|
152
170
|
/**
|
|
153
171
|
* Keeps an overlay mounted through its exit animation. Enter animations
|
|
@@ -1277,8 +1295,10 @@ interface DialogOverlayProps extends React.ComponentProps<"div"> {
|
|
|
1277
1295
|
declare function DialogOverlay({ className, ...props }: DialogOverlayProps): React.JSX.Element;
|
|
1278
1296
|
interface DialogContentProps extends React.ComponentProps<"div"> {
|
|
1279
1297
|
showCloseButton?: boolean;
|
|
1298
|
+
/** Where focus lands on open. Default `first` — a dialog is usually a short form. */
|
|
1299
|
+
initialFocus?: InitialFocus;
|
|
1280
1300
|
}
|
|
1281
|
-
declare function DialogContent({ className, children, showCloseButton, ...props }: DialogContentProps): React.JSX.Element | null;
|
|
1301
|
+
declare function DialogContent({ className, children, showCloseButton, initialFocus, ...props }: DialogContentProps): React.JSX.Element | null;
|
|
1282
1302
|
interface DialogCloseProps extends React.ComponentProps<"button"> {
|
|
1283
1303
|
asChild?: boolean;
|
|
1284
1304
|
}
|
|
@@ -1332,8 +1352,14 @@ interface SheetOverlayProps extends React.ComponentProps<"div"> {
|
|
|
1332
1352
|
declare function SheetOverlay({ className, ...props }: SheetOverlayProps): React.JSX.Element;
|
|
1333
1353
|
interface SheetContentProps extends React.ComponentProps<"div"> {
|
|
1334
1354
|
side?: "top" | "right" | "bottom" | "left";
|
|
1355
|
+
/**
|
|
1356
|
+
* Where focus lands on open. Default `container`: a sheet is a panel of
|
|
1357
|
+
* content, and its first Tab stop is as likely an action as a field — the
|
|
1358
|
+
* panel itself takes focus and the first Tab reaches the first control.
|
|
1359
|
+
*/
|
|
1360
|
+
initialFocus?: InitialFocus;
|
|
1335
1361
|
}
|
|
1336
|
-
declare function SheetContent({ className, children, side, ...props }: SheetContentProps): React.JSX.Element | null;
|
|
1362
|
+
declare function SheetContent({ className, children, side, initialFocus, ...props }: SheetContentProps): React.JSX.Element | null;
|
|
1337
1363
|
interface SheetCloseProps extends React.ComponentProps<"button"> {
|
|
1338
1364
|
asChild?: boolean;
|
|
1339
1365
|
}
|
|
@@ -1862,4 +1888,423 @@ declare function OrderFormSubmit({ side, className, ...props }: OrderFormSubmitP
|
|
|
1862
1888
|
/** The open-orders pane with nothing in it. */
|
|
1863
1889
|
declare function OpenOrdersEmpty({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
1864
1890
|
|
|
1865
|
-
|
|
1891
|
+
/** Where the shell swaps the bottom tab bar for the rail. */
|
|
1892
|
+
type ShellBreakpoint = "md" | "lg";
|
|
1893
|
+
interface AppShellProps extends React.ComponentProps<"div"> {
|
|
1894
|
+
/** The desktop rail — a `ShellNav`. Shown from `breakpoint` up. */
|
|
1895
|
+
rail?: React.ReactNode;
|
|
1896
|
+
/** The phone's tab bar — a `BottomTabBar`. Pinned to the viewport bottom below `breakpoint`. */
|
|
1897
|
+
tabBar?: React.ReactNode;
|
|
1898
|
+
/** Strips above the page (`SystemBanner`s). An empty slot takes no room. */
|
|
1899
|
+
banner?: React.ReactNode;
|
|
1900
|
+
/** Default `lg`. */
|
|
1901
|
+
breakpoint?: ShellBreakpoint;
|
|
1902
|
+
/** Props for the `<main>` the page renders into (an `id` for a skip link, say). */
|
|
1903
|
+
mainProps?: React.ComponentProps<"main">;
|
|
1904
|
+
}
|
|
1905
|
+
/**
|
|
1906
|
+
* The signed-in app's frame: a rail beside a content column on a wide screen, a
|
|
1907
|
+
* bottom tab bar under it on a phone. Layout only — the nav, the banners and the
|
|
1908
|
+
* page are slots, so the shell knows nothing about routes, roles or data.
|
|
1909
|
+
*
|
|
1910
|
+
* Fills the viewport less `--ev-shell-offset` (the room a host shell's own header
|
|
1911
|
+
* takes); the rail sticks under that offset at full remaining height and scrolls
|
|
1912
|
+
* by itself when it cannot fit. The column reserves the tab bar's height plus
|
|
1913
|
+
* the bottom safe area, so the bar never covers content.
|
|
1914
|
+
*/
|
|
1915
|
+
declare function AppShell({ rail, tabBar, banner, breakpoint, mainProps, className, children, ...props }: AppShellProps): React.JSX.Element;
|
|
1916
|
+
|
|
1917
|
+
/**
|
|
1918
|
+
* How a {@link NavItem} decides it is the current one.
|
|
1919
|
+
*
|
|
1920
|
+
* - `"prefix"` (default) — the path is the item's own or lies beneath it, on a
|
|
1921
|
+
* segment boundary: `/invest` claims `/invest/arb` but not `/investors`. An
|
|
1922
|
+
* item at `/` is exact, or it would claim every page.
|
|
1923
|
+
* - `"exact"` — the path is the item's own and nothing beneath it.
|
|
1924
|
+
* - a function — whatever it answers for the path.
|
|
1925
|
+
*/
|
|
1926
|
+
type NavMatch = "exact" | "prefix" | ((pathname: string) => boolean);
|
|
1927
|
+
/** State a row is rendered in; what `trailing` and `renderItem` are told. */
|
|
1928
|
+
interface NavItemState {
|
|
1929
|
+
active: boolean;
|
|
1930
|
+
/** Marked by a click whose navigation has not landed yet. */
|
|
1931
|
+
pending: boolean;
|
|
1932
|
+
}
|
|
1933
|
+
/** One destination, shared by the rail ({@link ShellNav}) and the tab bar. */
|
|
1934
|
+
interface NavItem {
|
|
1935
|
+
/** Stable key; also what `onNavigate` / `onItemIntent` hand back. */
|
|
1936
|
+
id: string;
|
|
1937
|
+
href: string;
|
|
1938
|
+
label: React.ReactNode;
|
|
1939
|
+
icon?: React.ComponentType<{
|
|
1940
|
+
className?: string;
|
|
1941
|
+
}>;
|
|
1942
|
+
/** A count (`NavBadge`, capped at 99+, `0` draws nothing) or your own node. */
|
|
1943
|
+
badge?: number | React.ReactNode;
|
|
1944
|
+
/** Anything after the label — a status chip; a function is told the row's state. */
|
|
1945
|
+
trailing?: React.ReactNode | ((state: NavItemState) => React.ReactNode);
|
|
1946
|
+
/**
|
|
1947
|
+
* Leaves the app: rendered as a plain `<a>` (never `linkComponent`), never
|
|
1948
|
+
* current, never marked pending — a `mailto:`, a docs site.
|
|
1949
|
+
*/
|
|
1950
|
+
external?: boolean;
|
|
1951
|
+
/** Passed to the anchor; `_blank` gets `rel="noopener noreferrer"`. */
|
|
1952
|
+
target?: React.HTMLAttributeAnchorTarget;
|
|
1953
|
+
match?: NavMatch;
|
|
1954
|
+
/**
|
|
1955
|
+
* More paths this item claims, prefix-matched — the one tab standing in for
|
|
1956
|
+
* a whole group of rail rows (`["/profile", "/notifications"]`).
|
|
1957
|
+
*/
|
|
1958
|
+
also?: readonly string[];
|
|
1959
|
+
/** Rendered, not focusable, never current. */
|
|
1960
|
+
disabled?: boolean;
|
|
1961
|
+
}
|
|
1962
|
+
/** A titled run of items; the rail draws one marker per group. */
|
|
1963
|
+
interface NavGroup {
|
|
1964
|
+
id: string;
|
|
1965
|
+
/** The eyebrow above the rows; also the list's accessible name. */
|
|
1966
|
+
label?: React.ReactNode;
|
|
1967
|
+
items: readonly NavItem[];
|
|
1968
|
+
}
|
|
1969
|
+
/**
|
|
1970
|
+
* How strongly `item` claims `pathname`, or `null` when it does not. Used to
|
|
1971
|
+
* pick ONE current item when several match — the rail and the tab bar each
|
|
1972
|
+
* draw a single marker, so two current rows is not a state they can show.
|
|
1973
|
+
*/
|
|
1974
|
+
declare function navItemMatch(item: NavItem, pathname: string): number | null;
|
|
1975
|
+
/** Whether `item` claims `pathname` at all, regardless of its neighbours. */
|
|
1976
|
+
declare function isNavItemActive(item: NavItem, pathname: string): boolean;
|
|
1977
|
+
/** The single current item for `pathname`: the strongest claim, ties to the first. */
|
|
1978
|
+
declare function resolveActiveNavItem(items: Iterable<NavItem>, pathname: string): NavItem | undefined;
|
|
1979
|
+
/**
|
|
1980
|
+
* A click the app should handle in place. A modified or non-primary click opens
|
|
1981
|
+
* the page elsewhere (a tab, a window, the context menu) and the router lets the
|
|
1982
|
+
* browser have it, so the current row stays current; `defaultPrevented` is the
|
|
1983
|
+
* same courtesy to anything upstream that claimed the click.
|
|
1984
|
+
*/
|
|
1985
|
+
declare function isPlainLeftClick(e: React.MouseEvent): boolean;
|
|
1986
|
+
|
|
1987
|
+
/**
|
|
1988
|
+
* The optimistic half of a nav: the id of the item just clicked, until the
|
|
1989
|
+
* pathname catches up.
|
|
1990
|
+
*
|
|
1991
|
+
* A router that waits for the next page's payload changes the pathname 150–300ms
|
|
1992
|
+
* after the click — exactly the window in which a highlight that has not moved
|
|
1993
|
+
* reads as a click that did not land. So the clicked item is marked at once.
|
|
1994
|
+
*
|
|
1995
|
+
* The entry remembers the pathname it was made on, so the moment the pathname
|
|
1996
|
+
* changes it is stale by construction and the URL is the truth again. It is
|
|
1997
|
+
* cleared during render, not in an effect (an effect would paint one frame with
|
|
1998
|
+
* the URL's row marked and the stale one not), and cleared rather than ignored:
|
|
1999
|
+
* left behind, it would come back to life on a return to the page it was made
|
|
2000
|
+
* on. A click that never navigates is forgotten by the next one.
|
|
2001
|
+
*/
|
|
2002
|
+
declare function usePendingNavigation(pathname: string): readonly [pendingId: string | null, markPending: (id: string) => void];
|
|
2003
|
+
|
|
2004
|
+
interface NavLinkCallbacks {
|
|
2005
|
+
/** Hover or focus on an item — the moment to prefetch its route. */
|
|
2006
|
+
onItemIntent?: ((item: NavItem) => void) | undefined;
|
|
2007
|
+
/** A plain left click on an in-app item, after it is marked pending. */
|
|
2008
|
+
onNavigate?: ((item: NavItem) => void) | undefined;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
interface ShellNavLabels {
|
|
2012
|
+
/** Accessible name of the nav holding `groups`. Default `"Main"`. */
|
|
2013
|
+
primary?: string;
|
|
2014
|
+
/** Accessible name of the nav holding `footerGroups`. Default `"Account"`. */
|
|
2015
|
+
footer?: string;
|
|
2016
|
+
/** Spoken text of a numeric badge, given the real count. Default `"{n} new"`. */
|
|
2017
|
+
badge?: (count: number) => string;
|
|
2018
|
+
}
|
|
2019
|
+
interface ShellNavProps extends Omit<React.ComponentProps<"aside">, "children">, NavLinkCallbacks {
|
|
2020
|
+
groups: readonly NavGroup[];
|
|
2021
|
+
/** Pinned to the bottom of the rail (profile, notifications, settings). */
|
|
2022
|
+
footerGroups?: readonly NavGroup[];
|
|
2023
|
+
/** The router's current path — `usePathname()` in Next. */
|
|
2024
|
+
pathname: string;
|
|
2025
|
+
/** Your router's link (`next/link`); defaults to a plain `<a>`. */
|
|
2026
|
+
linkComponent?: React.ElementType;
|
|
2027
|
+
/** Above the groups — the brand lock-up. */
|
|
2028
|
+
header?: React.ReactNode;
|
|
2029
|
+
/** Below the footer groups — the signed-in account, a sign-out. */
|
|
2030
|
+
footer?: React.ReactNode;
|
|
2031
|
+
/** Replaces a row's content (icon, label, badge); the link, `aria-current` and the marker stay the kit's. */
|
|
2032
|
+
renderItem?: (item: NavItem, state: NavItemState) => React.ReactNode;
|
|
2033
|
+
labels?: ShellNavLabels;
|
|
2034
|
+
}
|
|
2035
|
+
/**
|
|
2036
|
+
* The app's left rail: data-driven groups, a footer block pinned to the bottom,
|
|
2037
|
+
* one sliding marker per group, and an optimistic mark on click so the row
|
|
2038
|
+
* answers the click rather than the router's round-trip.
|
|
2039
|
+
*
|
|
2040
|
+
* Exactly one row across the rail is current — the strongest claim on the path
|
|
2041
|
+
* (see {@link resolveActiveNavItem}) — so overlapping `prefix` items are safe.
|
|
2042
|
+
* Visibility (roles, flags) is the caller's: pass only the items to show.
|
|
2043
|
+
*/
|
|
2044
|
+
declare function ShellNav({ groups, footerGroups, pathname, linkComponent, header, footer, renderItem, onItemIntent, onNavigate, labels, className, ...props }: ShellNavProps): React.JSX.Element;
|
|
2045
|
+
|
|
2046
|
+
type NavBadgeVariant = "pill" | "corner";
|
|
2047
|
+
interface NavBadgeProps extends Omit<React.ComponentProps<"span">, "children"> {
|
|
2048
|
+
count: number;
|
|
2049
|
+
/** Above this the badge shows `{max}+`. */
|
|
2050
|
+
max?: number;
|
|
2051
|
+
/**
|
|
2052
|
+
* The spoken text, given the REAL count — the one figure the cap throws away.
|
|
2053
|
+
* Default: `"{n} new"`.
|
|
2054
|
+
*/
|
|
2055
|
+
label?: (count: number) => string;
|
|
2056
|
+
/**
|
|
2057
|
+
* `pill` sits in a row after the label (the rail); `corner` is the solid dot on
|
|
2058
|
+
* an icon's top-right corner (the tab bar) — its parent must be `relative`.
|
|
2059
|
+
*/
|
|
2060
|
+
variant?: NavBadgeVariant;
|
|
2061
|
+
/** A pill on the marked row: inverted so it reads on the marker's fill. */
|
|
2062
|
+
active?: boolean;
|
|
2063
|
+
}
|
|
2064
|
+
/**
|
|
2065
|
+
* A count on a nav row or tab, capped so a neglected inbox cannot widen the
|
|
2066
|
+
* rail. Draws nothing for `0` or less.
|
|
2067
|
+
*
|
|
2068
|
+
* The visible figure is `aria-hidden` and the spoken one rides in an `sr-only`
|
|
2069
|
+
* span rather than an `aria-label`: a label on a plain span is not part of the
|
|
2070
|
+
* name the browser computes for the link around it, while text is — so the row
|
|
2071
|
+
* reads "Notifications, 150 new".
|
|
2072
|
+
*/
|
|
2073
|
+
declare function NavBadge({ count, max, label, variant, active, className, ...props }: NavBadgeProps): React.JSX.Element | null;
|
|
2074
|
+
type NavDotTone = "primary" | "positive" | "warn" | "error";
|
|
2075
|
+
interface NavDotProps extends Omit<React.ComponentProps<"span">, "children"> {
|
|
2076
|
+
tone?: NavDotTone;
|
|
2077
|
+
/** Spoken text; without one the dot is decoration and hidden from AT. */
|
|
2078
|
+
label?: string;
|
|
2079
|
+
/** Pin to an icon's top-right corner (parent `relative`), as the tab bar does. */
|
|
2080
|
+
corner?: boolean;
|
|
2081
|
+
}
|
|
2082
|
+
/** A presence dot — "something here", no figure. */
|
|
2083
|
+
declare function NavDot({ tone, label, corner, className, ...props }: NavDotProps): React.JSX.Element;
|
|
2084
|
+
|
|
2085
|
+
interface BottomTabBarLabels {
|
|
2086
|
+
/** Accessible name of the bar. Default `"Main"`. */
|
|
2087
|
+
nav?: string;
|
|
2088
|
+
/** Spoken text of a numeric badge, given the real count. Default `"{n} new"`. */
|
|
2089
|
+
badge?: (count: number) => string;
|
|
2090
|
+
}
|
|
2091
|
+
interface BottomTabBarProps extends Omit<React.ComponentProps<"nav">, "children">, NavLinkCallbacks {
|
|
2092
|
+
/**
|
|
2093
|
+
* The tabs, in order. Five is the most a phone holds — every label gets a
|
|
2094
|
+
* fifth of ~390px. A tab standing in for several rail rows lists their paths
|
|
2095
|
+
* in `also`. `trailing` is not drawn here; `badge` sits on the icon's corner.
|
|
2096
|
+
*/
|
|
2097
|
+
items: readonly NavItem[];
|
|
2098
|
+
pathname: string;
|
|
2099
|
+
linkComponent?: React.ElementType;
|
|
2100
|
+
labels?: BottomTabBarLabels;
|
|
2101
|
+
}
|
|
2102
|
+
/**
|
|
2103
|
+
* The mobile tab bar: equal tabs, one rule that slides between them, and a
|
|
2104
|
+
* corner badge. Position-agnostic — `AppShell` pins it to the bottom of the
|
|
2105
|
+
* viewport and hides it from its breakpoint up; the bar itself reserves the
|
|
2106
|
+
* bottom safe area under its `--shell-tab-bar-h`.
|
|
2107
|
+
*
|
|
2108
|
+
* The rule is a single node translated by whole tab widths (it is exactly one
|
|
2109
|
+
* tab wide, so the two cannot drift); on a route no tab claims it fades out
|
|
2110
|
+
* where it stands. That is why each tab is `min-w-0`: a long label must
|
|
2111
|
+
* truncate, never widen its tab off the rule's arithmetic.
|
|
2112
|
+
*/
|
|
2113
|
+
declare function BottomTabBar({ items, pathname, linkComponent, onItemIntent, onNavigate, labels, className, ...props }: BottomTabBarProps): React.JSX.Element;
|
|
2114
|
+
|
|
2115
|
+
interface MobileAppBarLabels {
|
|
2116
|
+
/** Accessible name of the back control. Default `"Back"`. */
|
|
2117
|
+
back?: string;
|
|
2118
|
+
}
|
|
2119
|
+
type MobileAppBarBack = {
|
|
2120
|
+
href: string;
|
|
2121
|
+
} | {
|
|
2122
|
+
onClick: () => void;
|
|
2123
|
+
};
|
|
2124
|
+
interface MobileAppBarProps extends Omit<React.ComponentProps<"header">, "title"> {
|
|
2125
|
+
title: React.ReactNode;
|
|
2126
|
+
/** A pushed screen: a back link (`href`) or a back button (`onClick`); centres the title. */
|
|
2127
|
+
back?: MobileAppBarBack;
|
|
2128
|
+
/** Trailing action — Save, a menu. */
|
|
2129
|
+
right?: React.ReactNode;
|
|
2130
|
+
linkComponent?: React.ElementType;
|
|
2131
|
+
/** Hidden from this breakpoint up, where the page heading takes over. Default `lg`; `false` never hides. */
|
|
2132
|
+
hideFrom?: ShellBreakpoint | false;
|
|
2133
|
+
labels?: MobileAppBarLabels;
|
|
2134
|
+
}
|
|
2135
|
+
/**
|
|
2136
|
+
* The bar that titles a screen on a phone. A root screen puts the title flush
|
|
2137
|
+
* left with an optional action; a pushed one (`back`) centres it between the
|
|
2138
|
+
* back control and a matching spacer. Sticks under `--ev-shell-offset` and
|
|
2139
|
+
* arrives with the screen (`data-enter="rise"`), one step ahead of a
|
|
2140
|
+
* `PageFrame`'s sections.
|
|
2141
|
+
*/
|
|
2142
|
+
declare function MobileAppBar({ title, back, right, linkComponent, hideFrom, labels, className, ...props }: MobileAppBarProps): React.JSX.Element;
|
|
2143
|
+
|
|
2144
|
+
type SectionLabelTone = "muted" | "accent";
|
|
2145
|
+
interface SectionLabelProps extends React.HTMLAttributes<HTMLElement> {
|
|
2146
|
+
as?: React.ElementType;
|
|
2147
|
+
/** `muted` labels a group or a section; `accent` announces a hero figure. */
|
|
2148
|
+
tone?: SectionLabelTone;
|
|
2149
|
+
}
|
|
2150
|
+
/** The tracked-uppercase label above a figure, a group or a section. */
|
|
2151
|
+
declare function SectionLabel({ as: Comp, tone, className, ...props }: SectionLabelProps): React.JSX.Element;
|
|
2152
|
+
interface PageHeadingProps extends Omit<React.ComponentProps<"header">, "title"> {
|
|
2153
|
+
title: React.ReactNode;
|
|
2154
|
+
/** What the screen is for, in a sentence. */
|
|
2155
|
+
description?: React.ReactNode;
|
|
2156
|
+
eyebrow?: React.ReactNode;
|
|
2157
|
+
/** The screen's own controls, on the right. */
|
|
2158
|
+
actions?: React.ReactNode;
|
|
2159
|
+
}
|
|
2160
|
+
/** The title row: eyebrow → title → description on the left, actions on the right. */
|
|
2161
|
+
declare function PageHeading({ title, description, eyebrow, actions, className, ...props }: PageHeadingProps): React.JSX.Element;
|
|
2162
|
+
type PageFrameWidth = "full" | "content";
|
|
2163
|
+
interface PageFrameProps extends Omit<React.ComponentProps<"div">, "title"> {
|
|
2164
|
+
/** Omit when the screen's heading is its own composition. */
|
|
2165
|
+
title?: React.ReactNode;
|
|
2166
|
+
description?: React.ReactNode;
|
|
2167
|
+
eyebrow?: React.ReactNode;
|
|
2168
|
+
actions?: React.ReactNode;
|
|
2169
|
+
/**
|
|
2170
|
+
* The bar titling the screen on a phone (`MobileAppBar`). With one, the heading
|
|
2171
|
+
* shows from `breakpoint` up only and the sections arrive a step after the bar.
|
|
2172
|
+
*/
|
|
2173
|
+
appBar?: React.ReactNode;
|
|
2174
|
+
/** Default `lg`. */
|
|
2175
|
+
breakpoint?: ShellBreakpoint;
|
|
2176
|
+
/** `full` fills the column (the rail already bounds it); `content` caps it at a reading measure. */
|
|
2177
|
+
width?: PageFrameWidth;
|
|
2178
|
+
headingClassName?: string;
|
|
2179
|
+
}
|
|
2180
|
+
/**
|
|
2181
|
+
* The frame every screen sits in: one inset, one section rhythm, one title scale,
|
|
2182
|
+
* so moving between screens never reads as moving between products.
|
|
2183
|
+
*
|
|
2184
|
+
* Its sections arrive in sequence by CSS alone (`data-enter="stagger"`, see
|
|
2185
|
+
* motion.css): every direct child fades and rises `--ev-rise`, one
|
|
2186
|
+
* `--ev-stagger-section` after the previous, the heading first. Server-safe —
|
|
2187
|
+
* no motion library, no hydration needed for the entrance.
|
|
2188
|
+
*/
|
|
2189
|
+
declare function PageFrame({ title, description, eyebrow, actions, appBar, breakpoint, width, headingClassName, className, style, children, ...props }: PageFrameProps): React.JSX.Element;
|
|
2190
|
+
|
|
2191
|
+
interface SectionNavItem {
|
|
2192
|
+
id: string;
|
|
2193
|
+
label: React.ReactNode;
|
|
2194
|
+
icon?: React.ComponentType<{
|
|
2195
|
+
className?: string;
|
|
2196
|
+
}>;
|
|
2197
|
+
/** A link (`?section=…`, a sub-route) instead of a button calling `onValueChange`. */
|
|
2198
|
+
href?: string;
|
|
2199
|
+
/** After the label — a count, a status chip. */
|
|
2200
|
+
trailing?: React.ReactNode;
|
|
2201
|
+
disabled?: boolean;
|
|
2202
|
+
}
|
|
2203
|
+
interface SectionNavGroup {
|
|
2204
|
+
id: string;
|
|
2205
|
+
label?: React.ReactNode;
|
|
2206
|
+
/** One line under the label saying what kind of thing lives here. */
|
|
2207
|
+
description?: React.ReactNode;
|
|
2208
|
+
items: readonly SectionNavItem[];
|
|
2209
|
+
}
|
|
2210
|
+
interface SectionNavLabels {
|
|
2211
|
+
/** Accessible name of the nav. Default `"Sections"`. */
|
|
2212
|
+
nav?: string;
|
|
2213
|
+
}
|
|
2214
|
+
interface SectionNavProps extends Omit<React.ComponentProps<"nav">, "children"> {
|
|
2215
|
+
groups: readonly SectionNavGroup[];
|
|
2216
|
+
/** The current section's id. */
|
|
2217
|
+
value: string;
|
|
2218
|
+
/** Called by button items (those without `href`), and by link items on click. */
|
|
2219
|
+
onValueChange?: (id: string) => void;
|
|
2220
|
+
linkComponent?: React.ElementType;
|
|
2221
|
+
labels?: SectionNavLabels;
|
|
2222
|
+
}
|
|
2223
|
+
/**
|
|
2224
|
+
* A screen's own section rail — settings panes, a document's chapters: grouped
|
|
2225
|
+
* rows, one current (`aria-current`), each a button or a link. The shell's rail
|
|
2226
|
+
* is `ShellNav`; this one lives inside a page, so it carries a tint rather than
|
|
2227
|
+
* the rail's solid marker and does not slide.
|
|
2228
|
+
*/
|
|
2229
|
+
declare function SectionNav({ groups, value, onValueChange, linkComponent, labels, className, ...props }: SectionNavProps): React.JSX.Element;
|
|
2230
|
+
|
|
2231
|
+
interface ResourceErrorLabels {
|
|
2232
|
+
/** The retry button. Default `"Try again"`. */
|
|
2233
|
+
retry?: string;
|
|
2234
|
+
}
|
|
2235
|
+
interface ResourceErrorBase extends Omit<React.ComponentProps<"div">, "title" | "children"> {
|
|
2236
|
+
/** What failed, already in the reader's words — the kit formats no errors. */
|
|
2237
|
+
message: React.ReactNode;
|
|
2238
|
+
labels?: ResourceErrorLabels;
|
|
2239
|
+
}
|
|
2240
|
+
type ResourceErrorProps = ResourceErrorBase & ({
|
|
2241
|
+
/** One line under the page header — for dense screens where a block would push everything down. */
|
|
2242
|
+
variant?: "inline";
|
|
2243
|
+
title?: never;
|
|
2244
|
+
/** Re-run the read; boxes the line so the button and the message read as one thing. */
|
|
2245
|
+
onRetry?: () => void;
|
|
2246
|
+
/** The retry is in flight: the button is disabled and its icon spins. */
|
|
2247
|
+
retrying?: boolean;
|
|
2248
|
+
} | {
|
|
2249
|
+
/** The kit's `Alert` with a heading — for screens that address the reader. */
|
|
2250
|
+
variant: "alert";
|
|
2251
|
+
title?: React.ReactNode;
|
|
2252
|
+
onRetry?: never;
|
|
2253
|
+
retrying?: never;
|
|
2254
|
+
});
|
|
2255
|
+
/**
|
|
2256
|
+
* What a screen shows when a read it needed never arrived. Whether there is
|
|
2257
|
+
* anything to report stays with the caller — only it knows whether stale data is
|
|
2258
|
+
* still on screen, and a failed refresh over figures the reader can see belongs
|
|
2259
|
+
* beside them, not in place of them.
|
|
2260
|
+
*/
|
|
2261
|
+
declare function ResourceError(props: ResourceErrorProps): React.JSX.Element;
|
|
2262
|
+
|
|
2263
|
+
type SystemBannerTone = "warn" | "info";
|
|
2264
|
+
interface SystemBannerLabels {
|
|
2265
|
+
/** The close button. Default `"Dismiss"`. */
|
|
2266
|
+
dismiss?: string;
|
|
2267
|
+
}
|
|
2268
|
+
interface SystemBannerProps extends Omit<React.ComponentProps<"div">, "title"> {
|
|
2269
|
+
/** `warn` — a platform state (maintenance, read-only); `info` — an announcement. */
|
|
2270
|
+
tone?: SystemBannerTone;
|
|
2271
|
+
/** Bold lead before the message. */
|
|
2272
|
+
title?: React.ReactNode;
|
|
2273
|
+
/** Replaces the tone's glyph; `null` drops it. */
|
|
2274
|
+
icon?: React.ReactNode;
|
|
2275
|
+
/** Shows a close button; remembering the dismissal is the caller's. */
|
|
2276
|
+
onDismiss?: () => void;
|
|
2277
|
+
labels?: SystemBannerLabels;
|
|
2278
|
+
}
|
|
2279
|
+
/**
|
|
2280
|
+
* A slim full-width strip above the page — presentation only: where its state
|
|
2281
|
+
* comes from, and whether a dismissal sticks, are the caller's. Put it in
|
|
2282
|
+
* `AppShell`'s `banner` slot; several stack with a gap.
|
|
2283
|
+
*/
|
|
2284
|
+
declare function SystemBanner({ tone, title, icon, onDismiss, labels, className, children, ...props }: SystemBannerProps): React.JSX.Element;
|
|
2285
|
+
|
|
2286
|
+
interface SettledProps extends Omit<React.ComponentProps<"div">, "children"> {
|
|
2287
|
+
/** True while the data this surface needs is in flight. */
|
|
2288
|
+
loading: boolean;
|
|
2289
|
+
/** What stands in meanwhile — a `Skeleton` or a group of them. */
|
|
2290
|
+
skeleton: React.ReactNode;
|
|
2291
|
+
/** The content; also the empty and error states, guarded on the same condition. */
|
|
2292
|
+
children: React.ReactNode;
|
|
2293
|
+
}
|
|
2294
|
+
/**
|
|
2295
|
+
* The skeleton → content handover. Swapped in a single frame, a skeleton reads
|
|
2296
|
+
* as a flicker — the eye sees that something changed, not what. Here the
|
|
2297
|
+
* content fades and rises the last `--ev-rise` into place
|
|
2298
|
+
* (`data-state="revealed"`, motion.css).
|
|
2299
|
+
*
|
|
2300
|
+
* Deliberately not a cross-fade: the two would have to overlap, which means
|
|
2301
|
+
* taking one out of flow and animating a height, and the surface would jump
|
|
2302
|
+
* when the content is a different size. And no entrance when no skeleton was
|
|
2303
|
+
* shown — data already present on the first render cuts straight in; fading it
|
|
2304
|
+
* would invent a delay the data never had.
|
|
2305
|
+
*
|
|
2306
|
+
* `data-state`: `loading` → `revealed` after a skeleton, `ready` without one.
|
|
2307
|
+
*/
|
|
2308
|
+
declare function Settled({ loading, skeleton, children, ...props }: SettledProps): React.JSX.Element;
|
|
2309
|
+
|
|
2310
|
+
export { type Accent, Accordion, AccordionContent, AccordionItem, type AccordionItemProps, type AccordionProps, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, type AlertDialogActionProps, AlertDialogCancel, type AlertDialogCancelProps, AlertDialogContent, type AlertDialogContentProps, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, type AlertDialogOverlayProps, type AlertDialogProps, AlertDialogTitle, AlertDialogTrigger, type AlertDialogTriggerProps, type AlertProps, AlertTitle, type AlertVariant, type Align, AppShell, type AppShellProps, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, type BadgeVariant, type BookSide, BottomTabBar, type BottomTabBarLabels, type BottomTabBarProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, type BreadcrumbLinkProps, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, type ButtonGroupOrientation, type ButtonGroupProps, ButtonGroupSeparator, ButtonGroupText, type ButtonGroupTextProps, type ButtonProps, type ButtonSize, type ButtonVariant, type ButtonVariantsOptions, Calendar, type CalendarProps, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselEdgeFade, CarouselItem, CarouselNext, CarouselPrevious, type CarouselProps, type ChartConfig, ChartContainer, type ChartItem, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Check, Checkbox, type CheckboxProps, Collapsible, CollapsibleContent, type CollapsibleProps, CollapsibleTrigger, Command, CommandDialog, type CommandDialogProps, CommandEmpty, CommandGroup, type CommandGroupProps, CommandInput, CommandItem, type CommandItemProps, CommandList, type CommandProps, CommandSeparator, CommandShortcut, Container, type ContainerProps, ContextMenu, ContextMenuCheckboxItem, type ContextMenuCheckboxItemProps, ContextMenuContent, ContextMenuGroup, ContextMenuItem, type ContextMenuItemProps, ContextMenuLabel, type ContextMenuLabelProps, ContextMenuPortal, type ContextMenuProps, ContextMenuRadioGroup, type ContextMenuRadioGroupProps, ContextMenuRadioItem, type ContextMenuRadioItemProps, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, type ContextMenuSubProps, ContextMenuSubTrigger, type ContextMenuSubTriggerProps, ContextMenuTrigger, type ContextMenuTriggerProps, DateTimePicker, type DateTimePickerLabels, type DateTimePickerProps, Dialog, DialogClose, type DialogCloseProps, DialogContent, type DialogContentProps, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, type DialogOverlayProps, DialogPortal, type DialogPortalProps, type DialogProps, DialogTitle, DialogTrigger, type DialogTriggerProps, type DismissEvent, Display, Drawer, DrawerClose, type DrawerCloseProps, DrawerContent, DrawerDescription, type DrawerDirection, DrawerFooter, DrawerHeader, DrawerOverlay, type DrawerProps, DrawerTitle, DrawerTrigger, type DrawerTriggerProps, DropdownMenu, DropdownMenuCheckboxItem, type DropdownMenuCheckboxItemProps, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, type DropdownMenuLabelProps, DropdownMenuPortal, type DropdownMenuProps, DropdownMenuRadioGroup, type DropdownMenuRadioGroupProps, DropdownMenuRadioItem, type DropdownMenuRadioItemProps, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, type DropdownMenuSubProps, DropdownMenuSubTrigger, type DropdownMenuSubTriggerProps, DropdownMenuTrigger, type DropdownMenuTriggerProps, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, type EmptyMediaProps, type EmptyMediaVariant, EmptyTitle, Eyebrow, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, type FieldOrientation, FieldSeparator, FieldSet, FieldTitle, type FloatingResult, Footer, type FooterLink, type FooterLinkGroup, type FooterOffice, type FooterProps, Forbidden, Form, FormControl, FormDescription, FormItem, FormLabel, FormMessage, HoverCard, HoverCardContent, type HoverCardContentProps, type HoverCardProps, HoverCardTrigger, type HoverCardTriggerProps, type HoverIntentHandlers, InfoTip, InfoTipContent, type InfoTipContentProps, type InfoTipProps, InfoTipTrigger, type InfoTipTriggerProps, Input, InputGroup, InputGroupAddon, type InputGroupAddonAlign, type InputGroupAddonProps, InputGroupButton, type InputGroupButtonProps, type InputGroupButtonSize, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, type InputOTPProps, InputOTPSeparator, InputOTPSlot, type InputOTPSlotProps, type InputProps, type InputSize, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, type ItemMediaProps, type ItemMediaVariant, type ItemProps, ItemSeparator, type ItemSize, ItemTitle, type ItemVariant, Kbd, KbdGroup, Label, Logo, type LogoProps, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, type MenubarMenuProps, MenubarRadioGroup, type MenubarRadioGroupProps, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, type MenubarSubProps, MenubarSubTrigger, MenubarTrigger, MobileAppBar, type MobileAppBarBack, type MobileAppBarLabels, type MobileAppBarProps, NativeSelect, NativeSelectGroup, NativeSelectOption, type NativeSelectProps, type NativeSelectSize, NavBadge, type NavBadgeProps, type NavBadgeVariant, NavDot, type NavDotProps, type NavDotTone, type NavGroup, type NavItem, type NavItemState, type NavMatch, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, type NavigationMenuItemProps, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NotFound, OpenOrdersEmpty, OrderBook, OrderBookHead, type OrderBookHeadProps, OrderBookRow, type OrderBookRowProps, OrderBookSpread, OrderForm, OrderFormRow, type OrderFormRowProps, OrderFormSubmit, type OrderFormSubmitProps, type OrderSide, PageFrame, type PageFrameProps, type PageFrameWidth, PageHeading, type PageHeadingProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, type PaginationLinkProps, PaginationNext, PaginationPrevious, type Polarity, Popover, PopoverAnchor, type PopoverAnchorProps, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, type PopoverTriggerProps, Portal, type PortalProps, PortalProvider, type PortalProviderProps, Progress, type ProgressProps, Prose, RadioGroup, RadioGroupItem, type RadioGroupItemProps, type RadioGroupProps, type ResizableDirection, ResizableHandle, type ResizableHandleProps, ResizablePanel, ResizablePanelGroup, type ResizablePanelGroupProps, type ResizablePanelProps, ResourceError, type ResourceErrorLabels, type ResourceErrorProps, ScrollArea, ScrollBar, type ScrollBarOrientation, type ScrollBarProps, Section, SectionDescriptor, type SectionDescriptorProps, SectionHead, type SectionHeadProps, SectionLabel, type SectionLabelProps, type SectionLabelTone, SectionNav, type SectionNavGroup, type SectionNavItem, type SectionNavLabels, type SectionNavProps, type SectionProps, Select, SelectContent, type SelectContentProps, SelectGroup, SelectItem, type SelectItemProps, SelectLabel, type SelectProps, SelectSeparator, SelectTrigger, type SelectTriggerProps, type SelectTriggerSize, SelectValue, type SelectValueProps, Separator, type SeparatorOrientation, type SeparatorProps, ServerError, type ServerErrorProps, Settled, type SettledProps, Sheet, SheetClose, type SheetCloseProps, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, type SheetOverlayProps, type SheetProps, SheetTitle, SheetTrigger, type SheetTriggerProps, type ShellBreakpoint, ShellNav, type ShellNavLabels, type ShellNavProps, type Side, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, type SidebarGroupLabelProps, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuButton, type SidebarMenuButtonProps, type SidebarMenuButtonSize, SidebarMenuItem, type SidebarProps, SidebarProvider, type SidebarProviderProps, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slider, type SliderProps, Slot, type SlotProps, Spinner, Stat, type StatProps, type StatusLinkData, type StatusPageProps, StatusScreen, type StatusScreenProps, type Surface, Switch, type SwitchProps, SystemBanner, type SystemBannerLabels, type SystemBannerProps, type SystemBannerTone, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, type TabsContentProps, TabsList, type TabsProps, TabsTrigger, type TabsTriggerProps, Terminal, type TerminalArea, TerminalChart, TerminalPane, TerminalPaneBody, TerminalPaneHeader, type TerminalPaneProps, TerminalTicker, Textarea, type TextareaProps, type TextareaSize, TickerStat, type TickerStatProps, type Toast, type ToastFn, type ToastOptions, type ToastPosition, type ToastState, type ToastVariant, Toaster, type ToasterProps, Toggle, ToggleGroup, ToggleGroupItem, type ToggleGroupItemProps, type ToggleGroupProps, type ToggleProps, type ToggleSize, type ToggleVariant, type ToggleVariantsOptions, Tooltip, TooltipContent, type TooltipContentProps, type TooltipProps, TooltipProvider, type TooltipProviderProps, TooltipTrigger, type TooltipTriggerProps, TradesTapeRow, type TradesTapeRowProps, buttonVariants, cn, isNavItemActive, isPlainLeftClick, mergeRefs, navItemMatch, navigationMenuTriggerStyle, resolveActiveNavItem, statusCtaClass, toast, toggleVariants, useControllableState, useDismissableLayer, useFloating, useFocusScope, useHoverIntent, usePendingNavigation, usePresence, useRovingFocus, useSidebar };
|
package/dist/index.js
CHANGED
|
@@ -71,3 +71,15 @@ export { Toaster, toast, } from "./components/sonner.js";
|
|
|
71
71
|
export { Form, FormControl, FormDescription, FormItem, FormLabel, FormMessage, } from "./components/form.js";
|
|
72
72
|
export { ResizableHandle, ResizablePanel, ResizablePanelGroup, } from "./components/resizable.js";
|
|
73
73
|
export { OpenOrdersEmpty, OrderBook, OrderBookHead, OrderBookRow, OrderBookSpread, OrderForm, OrderFormRow, OrderFormSubmit, Terminal, TerminalChart, TerminalPane, TerminalPaneBody, TerminalPaneHeader, TerminalTicker, TickerStat, TradesTapeRow, } from "./components/terminal.js";
|
|
74
|
+
export { AppShell } from "./components/app-shell.js";
|
|
75
|
+
export { isNavItemActive, isPlainLeftClick, navItemMatch, resolveActiveNavItem, } from "./components/nav-model.js";
|
|
76
|
+
export { usePendingNavigation } from "./components/use-shell-nav.js";
|
|
77
|
+
export { ShellNav } from "./components/shell-nav.js";
|
|
78
|
+
export { NavBadge, NavDot } from "./components/nav-badge.js";
|
|
79
|
+
export { BottomTabBar } from "./components/bottom-tab-bar.js";
|
|
80
|
+
export { MobileAppBar } from "./components/mobile-app-bar.js";
|
|
81
|
+
export { PageFrame, PageHeading, SectionLabel } from "./components/page-frame.js";
|
|
82
|
+
export { SectionNav } from "./components/section-nav.js";
|
|
83
|
+
export { ResourceError } from "./components/resource-error.js";
|
|
84
|
+
export { SystemBanner } from "./components/system-banner.js";
|
|
85
|
+
export { Settled } from "./components/settled.js";
|
|
@@ -16,15 +16,25 @@ function focusable(root) {
|
|
|
16
16
|
(el) => el.offsetWidth > 0 || el.offsetHeight > 0 || el === document.activeElement
|
|
17
17
|
);
|
|
18
18
|
}
|
|
19
|
-
function
|
|
19
|
+
function usable(el) {
|
|
20
|
+
return !!el && el !== document.body && el.isConnected;
|
|
21
|
+
}
|
|
22
|
+
function focusRoot(root) {
|
|
23
|
+
if (!root.hasAttribute("tabindex")) root.tabIndex = -1;
|
|
24
|
+
root.focus();
|
|
25
|
+
}
|
|
26
|
+
function useFocusScope(enabled, { initialFocus = "first", returnFocusTo } = {}) {
|
|
20
27
|
const ref = React.useRef(null);
|
|
28
|
+
const fallbackRef = React.useRef(returnFocusTo);
|
|
29
|
+
fallbackRef.current = returnFocusTo;
|
|
21
30
|
React.useEffect(() => {
|
|
22
31
|
if (!enabled) return;
|
|
23
32
|
const root = ref.current;
|
|
24
33
|
if (!root) return;
|
|
25
34
|
const previouslyFocused = document.activeElement;
|
|
26
|
-
const first = focusable(root)[0];
|
|
27
|
-
(first
|
|
35
|
+
const first = initialFocus === "first" ? focusable(root)[0] : void 0;
|
|
36
|
+
if (first) first.focus();
|
|
37
|
+
else focusRoot(root);
|
|
28
38
|
function onKeyDown(event) {
|
|
29
39
|
if (event.key !== "Tab" || !root) return;
|
|
30
40
|
const items = focusable(root);
|
|
@@ -35,7 +45,10 @@ function useFocusScope(enabled) {
|
|
|
35
45
|
const firstEl = items[0];
|
|
36
46
|
const lastEl = items[items.length - 1];
|
|
37
47
|
const active = document.activeElement;
|
|
38
|
-
if (
|
|
48
|
+
if (active === root) {
|
|
49
|
+
event.preventDefault();
|
|
50
|
+
(event.shiftKey ? lastEl : firstEl).focus();
|
|
51
|
+
} else if (event.shiftKey && active === firstEl) {
|
|
39
52
|
event.preventDefault();
|
|
40
53
|
lastEl.focus();
|
|
41
54
|
} else if (!event.shiftKey && active === lastEl) {
|
|
@@ -46,9 +59,12 @@ function useFocusScope(enabled) {
|
|
|
46
59
|
root.addEventListener("keydown", onKeyDown);
|
|
47
60
|
return () => {
|
|
48
61
|
root.removeEventListener("keydown", onKeyDown);
|
|
49
|
-
|
|
62
|
+
const active = document.activeElement;
|
|
63
|
+
if (active && active !== document.body && !root.contains(active)) return;
|
|
64
|
+
const target = usable(previouslyFocused) ? previouslyFocused : fallbackRef.current?.current;
|
|
65
|
+
if (usable(target)) target.focus({ preventScroll: true });
|
|
50
66
|
};
|
|
51
|
-
}, [enabled]);
|
|
67
|
+
}, [enabled, initialFocus]);
|
|
52
68
|
return ref;
|
|
53
69
|
}
|
|
54
70
|
export {
|