@ratio-ui/core 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/catalogue.json +2829 -72
- package/dist/components/alert/Alert.d.ts +18 -0
- package/dist/components/alert/Alert.js +67 -0
- package/dist/components/alert/index.d.ts +2 -0
- package/dist/components/alert/index.js +1 -0
- package/dist/components/alert-dialog/AlertDialog.d.ts +48 -0
- package/dist/components/alert-dialog/AlertDialog.js +76 -0
- package/dist/components/alert-dialog/index.d.ts +2 -0
- package/dist/components/alert-dialog/index.js +1 -0
- package/dist/components/app-shell/AppShell.d.ts +22 -0
- package/dist/components/app-shell/AppShell.js +39 -0
- package/dist/components/app-shell/context.js +5 -0
- package/dist/components/app-shell/index.d.ts +2 -0
- package/dist/components/app-shell/index.js +1 -0
- package/dist/components/avatar/Avatar.d.ts +22 -0
- package/dist/components/avatar/Avatar.js +38 -0
- package/dist/components/avatar/index.d.ts +2 -0
- package/dist/components/avatar/index.js +1 -0
- package/dist/components/button/Button.d.ts +37 -0
- package/dist/components/button/Button.js +41 -0
- package/dist/components/button/index.d.ts +2 -0
- package/dist/components/button/index.js +1 -0
- package/dist/components/calendar/Calendar.d.ts +20 -0
- package/dist/components/calendar/Calendar.js +119 -0
- package/dist/components/calendar/index.d.ts +2 -0
- package/dist/components/calendar/index.js +1 -0
- package/dist/components/card/Card.d.ts +33 -0
- package/dist/components/card/Card.js +53 -0
- package/dist/components/card/index.d.ts +2 -0
- package/dist/components/card/index.js +1 -0
- package/dist/components/checkbox/Checkbox.d.ts +10 -0
- package/dist/components/checkbox/Checkbox.js +28 -0
- package/dist/components/checkbox/index.d.ts +2 -0
- package/dist/components/checkbox/index.js +1 -0
- package/dist/components/checkbox-list/CheckboxList.d.ts +36 -0
- package/dist/components/checkbox-list/CheckboxList.js +93 -0
- package/dist/components/checkbox-list/index.d.ts +2 -0
- package/dist/components/checkbox-list/index.js +1 -0
- package/dist/components/collapsible/Collapsible.d.ts +24 -0
- package/dist/components/collapsible/Collapsible.js +58 -0
- package/dist/components/collapsible/index.d.ts +2 -0
- package/dist/components/collapsible/index.js +1 -0
- package/dist/components/data-table/DataTable.d.ts +65 -0
- package/dist/components/data-table/DataTable.js +141 -0
- package/dist/components/data-table/index.d.ts +2 -0
- package/dist/components/data-table/index.js +1 -0
- package/dist/components/date-picker/DatePicker.d.ts +33 -0
- package/dist/components/date-picker/DatePicker.js +104 -0
- package/dist/components/date-picker/index.d.ts +2 -0
- package/dist/components/date-picker/index.js +1 -0
- package/dist/components/date-range-picker/DateRangePicker.d.ts +39 -0
- package/dist/components/date-range-picker/DateRangePicker.js +142 -0
- package/dist/components/date-range-picker/index.d.ts +2 -0
- package/dist/components/date-range-picker/index.js +1 -0
- package/dist/components/definition/Definition.d.ts +14 -0
- package/dist/components/definition/Definition.js +29 -0
- package/dist/components/definition/index.d.ts +2 -0
- package/dist/components/definition/index.js +1 -0
- package/dist/components/dialog/Dialog.d.ts +44 -0
- package/dist/components/dialog/Dialog.js +79 -0
- package/dist/components/dialog/index.d.ts +2 -0
- package/dist/components/dialog/index.js +1 -0
- package/dist/components/dropdown-menu/DropdownMenu.d.ts +73 -0
- package/dist/components/dropdown-menu/DropdownMenu.js +116 -0
- package/dist/components/dropdown-menu/index.d.ts +2 -0
- package/dist/components/dropdown-menu/index.js +1 -0
- package/dist/components/empty-state/EmptyState.d.ts +15 -0
- package/dist/components/empty-state/EmptyState.js +30 -0
- package/dist/components/empty-state/index.d.ts +2 -0
- package/dist/components/empty-state/index.js +1 -0
- package/dist/components/field/Field.d.ts +35 -0
- package/dist/components/field/Field.js +67 -0
- package/dist/components/field/Label.d.ts +8 -0
- package/dist/components/field/Label.js +13 -0
- package/dist/components/field/index.d.ts +3 -0
- package/dist/components/field/index.js +3 -0
- package/dist/components/filter-tabs/FilterTabs.d.ts +28 -0
- package/dist/components/filter-tabs/FilterTabs.js +37 -0
- package/dist/components/filter-tabs/index.d.ts +2 -0
- package/dist/components/filter-tabs/index.js +1 -0
- package/dist/components/global-search/GlobalSearch.d.ts +51 -0
- package/dist/components/global-search/GlobalSearch.js +144 -0
- package/dist/components/global-search/index.d.ts +2 -0
- package/dist/components/global-search/index.js +1 -0
- package/dist/components/icon/registry.d.ts +3 -2
- package/dist/components/icon/registry.js +57 -1
- package/dist/components/input/Input.d.ts +19 -0
- package/dist/components/input/Input.js +26 -0
- package/dist/components/input/index.d.ts +2 -0
- package/dist/components/input/index.js +1 -0
- package/dist/components/input-group/InputGroup.d.ts +42 -0
- package/dist/components/input-group/InputGroup.js +83 -0
- package/dist/components/input-group/index.d.ts +2 -0
- package/dist/components/input-group/index.js +1 -0
- package/dist/components/kbd/Kbd.d.ts +17 -0
- package/dist/components/kbd/Kbd.js +21 -0
- package/dist/components/kbd/index.d.ts +2 -0
- package/dist/components/kbd/index.js +1 -0
- package/dist/components/link/Link.d.ts +22 -0
- package/dist/components/link/Link.js +31 -0
- package/dist/components/link/index.d.ts +2 -0
- package/dist/components/link/index.js +1 -0
- package/dist/components/link-provider/LinkProvider.d.ts +29 -0
- package/dist/components/link-provider/LinkProvider.js +15 -0
- package/dist/components/link-provider/RatioLink.js +18 -0
- package/dist/components/link-provider/context.js +4 -0
- package/dist/components/link-provider/index.d.ts +2 -0
- package/dist/components/link-provider/index.js +1 -0
- package/dist/components/media-grid/MediaGrid.d.ts +49 -0
- package/dist/components/media-grid/MediaGrid.js +303 -0
- package/dist/components/media-grid/index.d.ts +2 -0
- package/dist/components/media-grid/index.js +1 -0
- package/dist/components/metric-strip/MetricStrip.d.ts +23 -0
- package/dist/components/metric-strip/MetricStrip.js +39 -0
- package/dist/components/metric-strip/index.d.ts +2 -0
- package/dist/components/metric-strip/index.js +1 -0
- package/dist/components/money-input/MoneyInput.d.ts +30 -0
- package/dist/components/money-input/MoneyInput.js +72 -0
- package/dist/components/money-input/index.d.ts +2 -0
- package/dist/components/money-input/index.js +1 -0
- package/dist/components/page-header/PageHeader.d.ts +37 -0
- package/dist/components/page-header/PageHeader.js +62 -0
- package/dist/components/page-header/index.d.ts +2 -0
- package/dist/components/page-header/index.js +1 -0
- package/dist/components/pagination/Pagination.d.ts +18 -0
- package/dist/components/pagination/Pagination.js +59 -0
- package/dist/components/pagination/index.d.ts +2 -0
- package/dist/components/pagination/index.js +1 -0
- package/dist/components/popover/Popover.d.ts +27 -0
- package/dist/components/popover/Popover.js +47 -0
- package/dist/components/popover/index.d.ts +2 -0
- package/dist/components/popover/index.js +1 -0
- package/dist/components/save-bar/SaveBar.d.ts +27 -0
- package/dist/components/save-bar/SaveBar.js +37 -0
- package/dist/components/save-bar/index.d.ts +2 -0
- package/dist/components/save-bar/index.js +1 -0
- package/dist/components/search-field/SearchField.d.ts +23 -0
- package/dist/components/search-field/SearchField.js +66 -0
- package/dist/components/search-field/index.d.ts +2 -0
- package/dist/components/search-field/index.js +1 -0
- package/dist/components/select/Select.d.ts +40 -0
- package/dist/components/select/Select.js +84 -0
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/index.js +1 -0
- package/dist/components/side-nav/SideNav.d.ts +64 -0
- package/dist/components/side-nav/SideNav.js +194 -0
- package/dist/components/side-nav/index.d.ts +2 -0
- package/dist/components/side-nav/index.js +1 -0
- package/dist/components/skeleton/Skeleton.d.ts +13 -0
- package/dist/components/skeleton/Skeleton.js +21 -0
- package/dist/components/skeleton/index.d.ts +2 -0
- package/dist/components/skeleton/index.js +1 -0
- package/dist/components/spinner/Spinner.d.ts +11 -0
- package/dist/components/spinner/Spinner.js +16 -0
- package/dist/components/spinner/index.d.ts +2 -0
- package/dist/components/spinner/index.js +1 -0
- package/dist/components/status-pill/StatusPill.d.ts +14 -0
- package/dist/components/status-pill/StatusPill.js +19 -0
- package/dist/components/status-pill/index.d.ts +2 -0
- package/dist/components/status-pill/index.js +1 -0
- package/dist/components/summary-chips/SummaryChips.d.ts +17 -0
- package/dist/components/summary-chips/SummaryChips.js +19 -0
- package/dist/components/summary-chips/index.d.ts +2 -0
- package/dist/components/summary-chips/index.js +1 -0
- package/dist/components/switch/Switch.d.ts +10 -0
- package/dist/components/switch/Switch.js +20 -0
- package/dist/components/switch/index.d.ts +2 -0
- package/dist/components/switch/index.js +1 -0
- package/dist/components/table/Table.d.ts +46 -0
- package/dist/components/table/Table.js +87 -0
- package/dist/components/table/index.d.ts +2 -0
- package/dist/components/table/index.js +1 -0
- package/dist/components/table-loader/TableLoader.d.ts +31 -0
- package/dist/components/table-loader/TableLoader.js +35 -0
- package/dist/components/table-loader/index.d.ts +2 -0
- package/dist/components/table-loader/index.js +1 -0
- package/dist/components/tabs/Tabs.d.ts +23 -0
- package/dist/components/tabs/Tabs.js +41 -0
- package/dist/components/tabs/index.d.ts +2 -0
- package/dist/components/tabs/index.js +1 -0
- package/dist/components/tag-input/TagInput.d.ts +44 -0
- package/dist/components/tag-input/TagInput.js +102 -0
- package/dist/components/tag-input/index.d.ts +2 -0
- package/dist/components/tag-input/index.js +1 -0
- package/dist/components/textarea/Textarea.d.ts +15 -0
- package/dist/components/textarea/Textarea.js +21 -0
- package/dist/components/textarea/index.d.ts +2 -0
- package/dist/components/textarea/index.js +1 -0
- package/dist/components/toaster/Toaster.d.ts +32 -0
- package/dist/components/toaster/Toaster.js +89 -0
- package/dist/components/toaster/index.d.ts +2 -0
- package/dist/components/toaster/index.js +1 -0
- package/dist/components/tooltip/Tooltip.d.ts +18 -0
- package/dist/components/tooltip/Tooltip.js +35 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tooltip/index.js +1 -0
- package/dist/components/top-bar/StoreSwitcher.d.ts +26 -0
- package/dist/components/top-bar/StoreSwitcher.js +48 -0
- package/dist/components/top-bar/TopBar.d.ts +24 -0
- package/dist/components/top-bar/TopBar.js +53 -0
- package/dist/components/top-bar/index.d.ts +3 -0
- package/dist/components/top-bar/index.js +3 -0
- package/dist/components/unit-input/UnitInput.d.ts +33 -0
- package/dist/components/unit-input/UnitInput.js +47 -0
- package/dist/components/unit-input/index.d.ts +2 -0
- package/dist/components/unit-input/index.js +1 -0
- package/dist/index.d.ts +102 -1
- package/dist/index.js +54 -2
- package/dist/lib/cn.js +38 -27
- package/dist/lib/format.d.ts +92 -0
- package/dist/lib/format.js +222 -0
- package/dist/styles.css +1 -1
- package/package.json +205 -3
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn.js";
|
|
2
|
+
import { Icon } from "../icon/Icon.js";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { Menu } from "@base-ui/react/menu";
|
|
5
|
+
// src/components/dropdown-menu/DropdownMenu.tsx
|
|
6
|
+
/** The root of a menu of actions that opens from a trigger. Compose it with DropdownMenuTrigger and DropdownMenuContent. */
|
|
7
|
+
function DropdownMenu(props) {
|
|
8
|
+
return /* @__PURE__ */ jsx(Menu.Root, { ...props });
|
|
9
|
+
}
|
|
10
|
+
/** The control that opens the menu. It is a button, and carries aria-expanded and aria-haspopup. */
|
|
11
|
+
function DropdownMenuTrigger(props) {
|
|
12
|
+
return /* @__PURE__ */ jsx(Menu.Trigger, { ...props });
|
|
13
|
+
}
|
|
14
|
+
const POPUP = "rt:z-50 rt:max-h-80 rt:min-w-40 rt:overflow-y-auto rt:rounded-lg rt:bg-popover rt:py-1.5 rt:text-popover-foreground rt:shadow-ring-strong rt:forced-outline rt:outline-none";
|
|
15
|
+
/** The menu panel: a white popup with a hairline ring, 8px corners and no shadow. It opens in a portal. */
|
|
16
|
+
function DropdownMenuContent({ side = "bottom", align = "start", sideOffset = 4, alignOffset = 0, ...props }) {
|
|
17
|
+
return /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(Menu.Positioner, {
|
|
18
|
+
className: "rt:isolate rt:z-50 rt:outline-none",
|
|
19
|
+
side,
|
|
20
|
+
align,
|
|
21
|
+
sideOffset,
|
|
22
|
+
alignOffset,
|
|
23
|
+
children: /* @__PURE__ */ jsx(Menu.Popup, {
|
|
24
|
+
className: POPUP,
|
|
25
|
+
...props
|
|
26
|
+
})
|
|
27
|
+
}) });
|
|
28
|
+
}
|
|
29
|
+
/** Groups items under one DropdownMenuLabel, so assistive technology announces the label with the group. */
|
|
30
|
+
function DropdownMenuGroup(props) {
|
|
31
|
+
return /* @__PURE__ */ jsx(Menu.Group, { ...props });
|
|
32
|
+
}
|
|
33
|
+
/** The caption of a group, in the design system's label style: 12px, uppercase, subdued. Place it inside DropdownMenuGroup. */
|
|
34
|
+
function DropdownMenuLabel(props) {
|
|
35
|
+
return /* @__PURE__ */ jsx(Menu.GroupLabel, {
|
|
36
|
+
className: "rt:px-3 rt:py-1 rt:text-label rt:uppercase rt:text-foreground-subdued",
|
|
37
|
+
...props
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
const ROW = "rt:relative rt:flex rt:h-7 rt:cursor-default rt:items-center rt:gap-2 rt:px-3 rt:text-b3 rt:text-foreground rt:outline-none rt:select-none rt:transition-colors rt:data-highlighted:bg-accent rt:data-highlighted:text-accent-foreground rt:data-disabled:pointer-events-none rt:data-disabled:opacity-50";
|
|
41
|
+
/** One action in the menu. It runs onClick and closes the menu; disabled is drawn at half opacity and cannot be chosen. */
|
|
42
|
+
function DropdownMenuItem({ variant = "default", ...props }) {
|
|
43
|
+
return /* @__PURE__ */ jsx(Menu.Item, {
|
|
44
|
+
"data-variant": variant,
|
|
45
|
+
className: cn(ROW, variant === "destructive" && "rt:text-destructive-foreground rt:data-highlighted:bg-destructive-hover rt:data-highlighted:text-destructive-foreground"),
|
|
46
|
+
...props
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/** A key hint pushed to the end of an item. It is a hint only: the host binds the key. */
|
|
50
|
+
function DropdownMenuShortcut({ children }) {
|
|
51
|
+
return /* @__PURE__ */ jsx("span", {
|
|
52
|
+
className: "rt:ml-auto rt:text-c1 rt:text-foreground-subdued",
|
|
53
|
+
children
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/** A hairline between groups of items. */
|
|
57
|
+
function DropdownMenuSeparator(props) {
|
|
58
|
+
return /* @__PURE__ */ jsx(Menu.Separator, {
|
|
59
|
+
className: "rt:my-1.5 rt:h-px rt:bg-divider",
|
|
60
|
+
...props
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/** The root of a nested menu. Hold a DropdownMenuSubTrigger and a DropdownMenuSubContent. */
|
|
64
|
+
function DropdownMenuSub(props) {
|
|
65
|
+
return /* @__PURE__ */ jsx(Menu.SubmenuRoot, { ...props });
|
|
66
|
+
}
|
|
67
|
+
/** The item that opens a submenu, on hover, click or ArrowRight. A chevron at its end marks it. */
|
|
68
|
+
function DropdownMenuSubTrigger({ children, ...props }) {
|
|
69
|
+
return /* @__PURE__ */ jsxs(Menu.SubmenuTrigger, {
|
|
70
|
+
className: cn(ROW, "rt:data-popup-open:bg-accent"),
|
|
71
|
+
...props,
|
|
72
|
+
children: [children, /* @__PURE__ */ jsx("span", {
|
|
73
|
+
className: "rt:ml-auto rt:flex",
|
|
74
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
75
|
+
name: "chevron-right",
|
|
76
|
+
size: 8
|
|
77
|
+
})
|
|
78
|
+
})]
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/** The panel of a submenu. It opens to the side of its trigger. */
|
|
82
|
+
function DropdownMenuSubContent({ side = "right", alignOffset = -6, sideOffset = 0, ...props }) {
|
|
83
|
+
return /* @__PURE__ */ jsx(DropdownMenuContent, {
|
|
84
|
+
side,
|
|
85
|
+
alignOffset,
|
|
86
|
+
sideOffset,
|
|
87
|
+
...props
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/** An item that toggles an option. A check shows at its start while it is on and keeps the menu open, so several options can be changed in one visit. */
|
|
91
|
+
function DropdownMenuCheckboxItem({ children, ...props }) {
|
|
92
|
+
return /* @__PURE__ */ jsxs(Menu.CheckboxItem, {
|
|
93
|
+
className: cn(ROW, "rt:pl-8"),
|
|
94
|
+
...props,
|
|
95
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
96
|
+
className: "rt:absolute rt:left-3 rt:flex",
|
|
97
|
+
children: /* @__PURE__ */ jsx(Menu.CheckboxItemIndicator, { children: /* @__PURE__ */ jsx(Icon, { name: "check" }) })
|
|
98
|
+
}), children]
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/** Holds radio items and the one chosen value. */
|
|
102
|
+
function DropdownMenuRadioGroup(props) {
|
|
103
|
+
return /* @__PURE__ */ jsx(Menu.RadioGroup, { ...props });
|
|
104
|
+
}
|
|
105
|
+
/** One choice of a DropdownMenuRadioGroup. A dot shows at its start while it is the chosen value. */
|
|
106
|
+
function DropdownMenuRadioItem({ children, ...props }) {
|
|
107
|
+
return /* @__PURE__ */ jsxs(Menu.RadioItem, {
|
|
108
|
+
className: cn(ROW, "rt:pl-8"),
|
|
109
|
+
...props,
|
|
110
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
111
|
+
className: "rt:absolute rt:left-3 rt:flex",
|
|
112
|
+
children: /* @__PURE__ */ jsx(Menu.RadioItemIndicator, { children: /* @__PURE__ */ jsx("span", { className: "rt:block rt:size-1.5 rt:rounded-3xl rt:bg-current" }) })
|
|
113
|
+
}), children]
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuCheckboxItemProps, DropdownMenuContent, DropdownMenuContentProps, DropdownMenuGroup, DropdownMenuGroupProps, DropdownMenuItem, DropdownMenuItemProps, DropdownMenuLabel, DropdownMenuLabelProps, DropdownMenuProps, DropdownMenuRadioGroup, DropdownMenuRadioGroupProps, DropdownMenuRadioItem, DropdownMenuRadioItemProps, DropdownMenuSeparator, DropdownMenuSeparatorProps, DropdownMenuShortcut, DropdownMenuShortcutProps, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubContentProps, DropdownMenuSubProps, DropdownMenuSubTrigger, DropdownMenuSubTriggerProps, DropdownMenuTrigger, DropdownMenuTriggerProps } from "./DropdownMenu.js";
|
|
2
|
+
export { DropdownMenu, DropdownMenuCheckboxItem, type DropdownMenuCheckboxItemProps, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, type DropdownMenuGroupProps, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, type DropdownMenuLabelProps, type DropdownMenuProps, DropdownMenuRadioGroup, type DropdownMenuRadioGroupProps, DropdownMenuRadioItem, type DropdownMenuRadioItemProps, DropdownMenuSeparator, type DropdownMenuSeparatorProps, DropdownMenuShortcut, type DropdownMenuShortcutProps, DropdownMenuSub, DropdownMenuSubContent, type DropdownMenuSubContentProps, type DropdownMenuSubProps, DropdownMenuSubTrigger, type DropdownMenuSubTriggerProps, DropdownMenuTrigger, type DropdownMenuTriggerProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "./DropdownMenu.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { HTMLAttributes, JSX, ReactNode } from "react";
|
|
2
|
+
/** The props of EmptyState: the HTML attributes of its div, except className, style, children and title. */
|
|
3
|
+
export type EmptyStateProps = Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'style' | 'children' | 'title'> & {
|
|
4
|
+
/** One clause that says why nothing is shown, in sentence case with no period. */
|
|
5
|
+
title: ReactNode;
|
|
6
|
+
/** An optional second clause that says what to do next. */
|
|
7
|
+
description?: ReactNode;
|
|
8
|
+
/** An optional action, usually one Button. */
|
|
9
|
+
action?: ReactNode;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* What a list, table or panel shows when it has nothing to show: one clause and an optional action, centred in a
|
|
13
|
+
* hairline container.
|
|
14
|
+
*/
|
|
15
|
+
export declare function EmptyState({ title, description, action, ...rest }: EmptyStateProps): JSX.Element;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Text } from "../text/Text.js";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
// src/components/empty-state/EmptyState.tsx
|
|
4
|
+
/**
|
|
5
|
+
* What a list, table or panel shows when it has nothing to show: one clause and an optional action, centred in a
|
|
6
|
+
* hairline container.
|
|
7
|
+
*/
|
|
8
|
+
function EmptyState({ title, description, action, ...rest }) {
|
|
9
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
10
|
+
"data-slot": "empty-state",
|
|
11
|
+
...rest,
|
|
12
|
+
className: "rt:flex rt:w-full rt:min-w-0 rt:flex-col rt:items-center rt:justify-center rt:gap-6 rt:rounded-lg rt:border rt:border-border rt:bg-background rt:p-6 rt:text-center",
|
|
13
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
14
|
+
className: "rt:flex rt:flex-col rt:items-center rt:gap-1",
|
|
15
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
16
|
+
as: "p",
|
|
17
|
+
variant: "b4",
|
|
18
|
+
children: title
|
|
19
|
+
}), description ? /* @__PURE__ */ jsx(Text, {
|
|
20
|
+
as: "p",
|
|
21
|
+
tone: "subdued",
|
|
22
|
+
children: description
|
|
23
|
+
}) : null]
|
|
24
|
+
}), action ? /* @__PURE__ */ jsx("div", {
|
|
25
|
+
"data-slot": "empty-state-action",
|
|
26
|
+
children: action
|
|
27
|
+
}) : null]
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
export { EmptyState };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { EmptyState } from "./EmptyState.js";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { JSX, ReactElement, ReactNode } from "react";
|
|
2
|
+
/** The props of Field. */
|
|
3
|
+
export type FieldProps = {
|
|
4
|
+
/** The label text. */
|
|
5
|
+
label: ReactNode;
|
|
6
|
+
/** Help text under the control. An error replaces it. */
|
|
7
|
+
hint?: ReactNode;
|
|
8
|
+
/** The error message. It shows under the control beside the alert glyph and marks the control invalid. */
|
|
9
|
+
error?: ReactNode;
|
|
10
|
+
/** An explanation of the field, opened from a small info icon beside the label by keyboard, touch or hover. */
|
|
11
|
+
info?: ReactNode;
|
|
12
|
+
/** Shows a star after the label and marks the control aria-required. */
|
|
13
|
+
required?: boolean;
|
|
14
|
+
/** Dims the label and disables the control. */
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* The control: one element, such as Input, which gets an id, aria-describedby, aria-invalid, aria-required and disabled.
|
|
18
|
+
* When the control sits inside a wrapper such as InputGroup, pass a function instead and spread the props it receives
|
|
19
|
+
* onto the input itself.
|
|
20
|
+
*/
|
|
21
|
+
children: ReactElement<Record<string, unknown>> | ((props: FieldControlProps) => ReactNode);
|
|
22
|
+
};
|
|
23
|
+
/** The props Field hands to a function child, to spread onto the control. */
|
|
24
|
+
export type FieldControlProps = {
|
|
25
|
+
id: string;
|
|
26
|
+
'aria-describedby'?: string;
|
|
27
|
+
'aria-invalid'?: true;
|
|
28
|
+
'aria-required'?: true;
|
|
29
|
+
disabled?: true;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* A form row: label, control, hint and error. It wires the label to the control by id, links the hint and error with
|
|
33
|
+
* aria-describedby, and sets aria-invalid when there is an error. The control keeps an id it already has.
|
|
34
|
+
*/
|
|
35
|
+
export declare function Field({ label, hint, error, info, required, disabled, children }: FieldProps): JSX.Element;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Icon } from "../icon/Icon.js";
|
|
2
|
+
import { Definition } from "../definition/Definition.js";
|
|
3
|
+
import { Label } from "./Label.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { cloneElement, useId } from "react";
|
|
6
|
+
// src/components/field/Field.tsx
|
|
7
|
+
/**
|
|
8
|
+
* A form row: label, control, hint and error. It wires the label to the control by id, links the hint and error with
|
|
9
|
+
* aria-describedby, and sets aria-invalid when there is an error. The control keeps an id it already has.
|
|
10
|
+
*/
|
|
11
|
+
function Field({ label, hint, error, info, required, disabled, children }) {
|
|
12
|
+
const generatedId = useId();
|
|
13
|
+
const own = typeof children === "function" ? void 0 : children.props.id;
|
|
14
|
+
const id = typeof own === "string" && own !== "" ? own : generatedId;
|
|
15
|
+
const hasError = error !== void 0 && error !== null && error !== false && error !== "";
|
|
16
|
+
const hasHint = !hasError && hint !== void 0 && hint !== null && hint !== false && hint !== "";
|
|
17
|
+
const messageId = `${id}-message`;
|
|
18
|
+
const described = [typeof children === "function" ? void 0 : children.props["aria-describedby"], hasError || hasHint ? messageId : void 0].filter((part) => typeof part === "string" && part !== "").join(" ");
|
|
19
|
+
const wiring = {
|
|
20
|
+
id,
|
|
21
|
+
...described === "" ? {} : { "aria-describedby": described },
|
|
22
|
+
...hasError ? { "aria-invalid": true } : {},
|
|
23
|
+
...required === true ? { "aria-required": true } : {},
|
|
24
|
+
...disabled === true ? { disabled: true } : {}
|
|
25
|
+
};
|
|
26
|
+
const control = typeof children === "function" ? children(wiring) : cloneElement(children, { ...wiring });
|
|
27
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
28
|
+
"data-slot": "field",
|
|
29
|
+
className: "rt:flex rt:w-full rt:flex-col rt:gap-1.5",
|
|
30
|
+
children: [
|
|
31
|
+
/* @__PURE__ */ jsxs("div", {
|
|
32
|
+
className: `rt:flex rt:items-center rt:gap-1.5${disabled === true ? " rt:opacity-50" : ""}`,
|
|
33
|
+
children: [/* @__PURE__ */ jsxs(Label, {
|
|
34
|
+
htmlFor: id,
|
|
35
|
+
children: [label, required === true ? /* @__PURE__ */ jsx("span", {
|
|
36
|
+
"aria-hidden": "true",
|
|
37
|
+
className: "rt:text-foreground-subdued",
|
|
38
|
+
children: "*"
|
|
39
|
+
}) : null]
|
|
40
|
+
}), info === void 0 || info === null || info === false || info === "" ? null : /* @__PURE__ */ jsx(Definition, {
|
|
41
|
+
definition: info,
|
|
42
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
43
|
+
name: "info-circle",
|
|
44
|
+
tone: "subdued",
|
|
45
|
+
label: "More information"
|
|
46
|
+
})
|
|
47
|
+
})]
|
|
48
|
+
}),
|
|
49
|
+
control,
|
|
50
|
+
hasError ? /* @__PURE__ */ jsxs("p", {
|
|
51
|
+
id: messageId,
|
|
52
|
+
role: "alert",
|
|
53
|
+
className: "rt:flex rt:items-start rt:gap-1.5 rt:text-b1 rt:text-error",
|
|
54
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
55
|
+
className: "rt:mt-1 rt:text-error-icon",
|
|
56
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "alert-triangle" })
|
|
57
|
+
}), /* @__PURE__ */ jsx("span", { children: error })]
|
|
58
|
+
}) : null,
|
|
59
|
+
hasHint ? /* @__PURE__ */ jsx("p", {
|
|
60
|
+
id: messageId,
|
|
61
|
+
className: "rt:text-b1 rt:text-foreground-subdued",
|
|
62
|
+
children: hint
|
|
63
|
+
}) : null
|
|
64
|
+
]
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export { Field };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { JSX, LabelHTMLAttributes, Ref } from "react";
|
|
2
|
+
/** The props of Label: the HTML attributes of a label, except className and style. */
|
|
3
|
+
export type LabelProps = Omit<LabelHTMLAttributes<HTMLLabelElement>, 'className' | 'style'> & {
|
|
4
|
+
/** Receives the label element. */
|
|
5
|
+
ref?: Ref<HTMLLabelElement>;
|
|
6
|
+
};
|
|
7
|
+
/** The text that names a control, in the 12px medium label type. Point htmlFor at the control's id; Field does this for you. */
|
|
8
|
+
export declare function Label({ htmlFor, ref, ...rest }: LabelProps): JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
// src/components/field/Label.tsx
|
|
3
|
+
/** The text that names a control, in the 12px medium label type. Point htmlFor at the control's id; Field does this for you. */
|
|
4
|
+
function Label({ htmlFor, ref, ...rest }) {
|
|
5
|
+
return /* @__PURE__ */ jsx("label", {
|
|
6
|
+
"data-slot": "label",
|
|
7
|
+
htmlFor,
|
|
8
|
+
ref,
|
|
9
|
+
className: "rt:flex rt:w-fit rt:items-center rt:gap-1 rt:text-b2 rt:text-foreground rt:select-none",
|
|
10
|
+
...rest
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export { Label };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ComponentProps, JSX } from "react";
|
|
2
|
+
/** One choice of FilterTabs. */
|
|
3
|
+
export type FilterTabsItem = {
|
|
4
|
+
/** The value reported when the item is chosen. Unique in the list. */
|
|
5
|
+
value: string;
|
|
6
|
+
/** The text of the chip, one or two words in sentence case. */
|
|
7
|
+
label: string;
|
|
8
|
+
/** Stops the item being chosen and dims it to 50%. Defaults to false. */
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
};
|
|
11
|
+
/** The props of FilterTabs. */
|
|
12
|
+
export type FilterTabsProps = Omit<ComponentProps<'div'>, 'className' | 'style' | 'children' | 'defaultValue' | 'onChange'> & {
|
|
13
|
+
/** The choices, in order. */
|
|
14
|
+
items: FilterTabsItem[];
|
|
15
|
+
/** The chosen value when controlled. */
|
|
16
|
+
value?: string;
|
|
17
|
+
/** The chosen value at the start when uncontrolled. Defaults to the first item. */
|
|
18
|
+
defaultValue?: string;
|
|
19
|
+
/** Called with the new value when another item is chosen. Choosing the chosen item again does nothing. */
|
|
20
|
+
onValueChange?: (value: string) => void;
|
|
21
|
+
/** Disables every item. Defaults to false. */
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* A single choice that filters a list, such as All, Active and Inactive above a table: the design system's Tab chips in a
|
|
26
|
+
* row with an 8px gap. One item is always chosen. For sections of a page use Tabs instead.
|
|
27
|
+
*/
|
|
28
|
+
export declare function FilterTabs({ items, value, defaultValue, onValueChange, disabled, ...rest }: FilterTabsProps): JSX.Element;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Toggle } from "@base-ui/react/toggle";
|
|
5
|
+
import { ToggleGroup } from "@base-ui/react/toggle-group";
|
|
6
|
+
// src/components/filter-tabs/FilterTabs.tsx
|
|
7
|
+
/**
|
|
8
|
+
* A single choice that filters a list, such as All, Active and Inactive above a table: the design system's Tab chips in a
|
|
9
|
+
* row with an 8px gap. One item is always chosen. For sections of a page use Tabs instead.
|
|
10
|
+
*/
|
|
11
|
+
function FilterTabs({ items, value, defaultValue, onValueChange, disabled, ...rest }) {
|
|
12
|
+
const [inner, setInner] = useState(defaultValue ?? items[0]?.value);
|
|
13
|
+
const wanted = value ?? inner;
|
|
14
|
+
const chosen = items.some((item) => item.value === wanted) ? wanted : items[0]?.value;
|
|
15
|
+
const handle = (next) => {
|
|
16
|
+
const picked = next[0];
|
|
17
|
+
if (picked === void 0) return;
|
|
18
|
+
setInner(picked);
|
|
19
|
+
onValueChange?.(picked);
|
|
20
|
+
};
|
|
21
|
+
return /* @__PURE__ */ jsx(ToggleGroup, {
|
|
22
|
+
"data-slot": "filter-tabs",
|
|
23
|
+
className: cn("rt:flex rt:flex-wrap rt:items-center rt:gap-2"),
|
|
24
|
+
disabled,
|
|
25
|
+
value: chosen === void 0 ? [] : [chosen],
|
|
26
|
+
onValueChange: handle,
|
|
27
|
+
...rest,
|
|
28
|
+
children: items.map((item) => /* @__PURE__ */ jsx(Toggle, {
|
|
29
|
+
value: item.value,
|
|
30
|
+
disabled: item.disabled,
|
|
31
|
+
"data-slot": "filter-tabs-item",
|
|
32
|
+
className: cn("rt:inline-flex rt:h-9 rt:cursor-pointer rt:items-center rt:justify-center rt:rounded-lg rt:whitespace-nowrap", "rt:bg-background rt:text-b3 rt:transition-colors rt:forced-outline", "rt:border rt:border-border rt:px-3 rt:text-tab-inactive rt:hover:bg-primary-tint", "rt:data-pressed:border-0 rt:data-pressed:px-2.75 rt:data-pressed:font-semibold rt:data-pressed:text-primary", "rt:data-pressed:shadow-ring-accent-hairline", "rt:focus-visible:focus-ring rt:data-disabled:cursor-default rt:data-disabled:opacity-50"),
|
|
33
|
+
children: item.label
|
|
34
|
+
}, item.value))
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export { FilterTabs };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FilterTabs } from "./FilterTabs.js";
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { IconName } from "../icon/registry.js";
|
|
2
|
+
import "../icon/index.js";
|
|
3
|
+
import { JSX } from "react";
|
|
4
|
+
/** One result row: what it is called, a line of detail and an optional icon. */
|
|
5
|
+
export interface GlobalSearchResult {
|
|
6
|
+
/** A stable id, unique across all groups. */
|
|
7
|
+
id: string;
|
|
8
|
+
/** The name shown on the row. */
|
|
9
|
+
label: string;
|
|
10
|
+
/** A second line of detail, such as a SKU or an order status. */
|
|
11
|
+
description?: string;
|
|
12
|
+
/** An icon drawn before the label. */
|
|
13
|
+
icon?: IconName;
|
|
14
|
+
}
|
|
15
|
+
/** A group of results, such as Products or Orders. The app fills it. */
|
|
16
|
+
export interface GlobalSearchGroup {
|
|
17
|
+
/** A stable id for the group. */
|
|
18
|
+
id: string;
|
|
19
|
+
/** The heading of the group. */
|
|
20
|
+
label: string;
|
|
21
|
+
/** The results to show, already limited by the app. */
|
|
22
|
+
items: GlobalSearchResult[];
|
|
23
|
+
/** How many results exist in all. When it is above items.length, a "+N more" row follows the items. */
|
|
24
|
+
total?: number;
|
|
25
|
+
}
|
|
26
|
+
/** The props of GlobalSearch. */
|
|
27
|
+
export interface GlobalSearchProps {
|
|
28
|
+
/** The accessible name of the field, such as "Search the dashboard". */
|
|
29
|
+
label: string;
|
|
30
|
+
/** The text typed in the field. */
|
|
31
|
+
value: string;
|
|
32
|
+
/** Called on every change of the text. Debounce and fetch in the app. */
|
|
33
|
+
onValueChange: (value: string) => void;
|
|
34
|
+
/** The results for the current text, grouped. The app supplies them; nothing is filtered here. */
|
|
35
|
+
groups: GlobalSearchGroup[];
|
|
36
|
+
/** Recent items, shown under "Recent" while the field is empty. */
|
|
37
|
+
recent?: GlobalSearchResult[];
|
|
38
|
+
/** Called when a result is chosen by click or Enter. */
|
|
39
|
+
onSelect?: (result: GlobalSearchResult) => void;
|
|
40
|
+
/** Called when a "+N more" row is chosen, with its group. */
|
|
41
|
+
onShowMore?: (group: GlobalSearchGroup) => void;
|
|
42
|
+
/** The placeholder of the field. Defaults to "Search". */
|
|
43
|
+
placeholder?: string;
|
|
44
|
+
/** The copy when the text matches nothing. Defaults to "No results". */
|
|
45
|
+
emptyText?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The search in the top bar. Typing opens a panel of grouped results that the app supplies, an empty field shows recent
|
|
49
|
+
* items, and the arrow keys, Enter and Escape work the list. Cmd+K or Ctrl+K focuses the field from anywhere.
|
|
50
|
+
*/
|
|
51
|
+
export declare function GlobalSearch({ label, value, onValueChange, groups, recent, onSelect, onShowMore, placeholder, emptyText }: GlobalSearchProps): JSX.Element;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { Icon } from "../icon/Icon.js";
|
|
2
|
+
import { formatCount } from "../../lib/format.js";
|
|
3
|
+
import { InputGroup, InputGroupAddon, InputGroupShortcut } from "../input-group/InputGroup.js";
|
|
4
|
+
import { Kbd, KbdGroup } from "../kbd/Kbd.js";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { useEffect, useRef, useState } from "react";
|
|
7
|
+
import { Autocomplete } from "@base-ui/react/autocomplete";
|
|
8
|
+
// src/components/global-search/GlobalSearch.tsx
|
|
9
|
+
/**
|
|
10
|
+
* The search in the top bar. Typing opens a panel of grouped results that the app supplies, an empty field shows recent
|
|
11
|
+
* items, and the arrow keys, Enter and Escape work the list. Cmd+K or Ctrl+K focuses the field from anywhere.
|
|
12
|
+
*/
|
|
13
|
+
function GlobalSearch({ label, value, onValueChange, groups, recent = [], onSelect, onShowMore, placeholder = "Search", emptyText = "No results" }) {
|
|
14
|
+
const [open, setOpen] = useState(false);
|
|
15
|
+
const inputRef = useRef(null);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const onKey = (event) => {
|
|
18
|
+
if (!event.defaultPrevented && (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
|
|
19
|
+
event.preventDefault();
|
|
20
|
+
inputRef.current?.focus();
|
|
21
|
+
setOpen(true);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
document.addEventListener("keydown", onKey);
|
|
25
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
26
|
+
}, []);
|
|
27
|
+
const typed = value !== "";
|
|
28
|
+
const rows = typed ? groups.filter((group) => group.items.length > 0).map((group) => ({
|
|
29
|
+
id: group.id,
|
|
30
|
+
label: group.label,
|
|
31
|
+
items: group.total !== void 0 && group.total > group.items.length ? [...group.items, {
|
|
32
|
+
id: `${group.id}:more`,
|
|
33
|
+
label: `+${group.total - group.items.length} more`,
|
|
34
|
+
more: group
|
|
35
|
+
}] : group.items
|
|
36
|
+
})) : recent.length > 0 ? [{
|
|
37
|
+
id: "recent",
|
|
38
|
+
label: "Recent",
|
|
39
|
+
items: recent
|
|
40
|
+
}] : [];
|
|
41
|
+
const showEmpty = typed && rows.length === 0;
|
|
42
|
+
const found = typed ? groups.reduce((sum, group) => sum + (group.items.length > 0 ? Math.max(group.total ?? 0, group.items.length) : 0), 0) : 0;
|
|
43
|
+
const status = found > 0 ? `${formatCount(found)} ${found === 1 ? "result" : "results"}` : "";
|
|
44
|
+
const showPanel = open && (rows.length > 0 || showEmpty);
|
|
45
|
+
const choose = (row) => {
|
|
46
|
+
setOpen(false);
|
|
47
|
+
if (row.more !== void 0) onShowMore?.(row.more);
|
|
48
|
+
else onSelect?.(row);
|
|
49
|
+
};
|
|
50
|
+
return /* @__PURE__ */ jsxs(Autocomplete.Root, {
|
|
51
|
+
items: rows,
|
|
52
|
+
filter: null,
|
|
53
|
+
value,
|
|
54
|
+
onValueChange,
|
|
55
|
+
open: showPanel,
|
|
56
|
+
onOpenChange: setOpen,
|
|
57
|
+
itemToStringValue: (item) => item.more === void 0 ? item.label : value,
|
|
58
|
+
children: [/* @__PURE__ */ jsxs(InputGroup, { children: [
|
|
59
|
+
/* @__PURE__ */ jsx(InputGroupAddon, { children: /* @__PURE__ */ jsx(Icon, {
|
|
60
|
+
name: "search",
|
|
61
|
+
tone: "icon"
|
|
62
|
+
}) }),
|
|
63
|
+
/* @__PURE__ */ jsx(Autocomplete.Input, {
|
|
64
|
+
ref: inputRef,
|
|
65
|
+
"aria-label": label,
|
|
66
|
+
placeholder,
|
|
67
|
+
autoComplete: "off",
|
|
68
|
+
onFocus: () => setOpen(true),
|
|
69
|
+
className: "rt:h-full rt:min-w-0 rt:flex-1 rt:bg-transparent rt:text-b3 rt:text-foreground rt:placeholder:text-muted-foreground rt:outline-none"
|
|
70
|
+
}),
|
|
71
|
+
/* @__PURE__ */ jsx(InputGroupAddon, {
|
|
72
|
+
align: "end",
|
|
73
|
+
children: /* @__PURE__ */ jsx(InputGroupShortcut, {
|
|
74
|
+
"aria-hidden": "true",
|
|
75
|
+
children: "⌘K"
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
] }), /* @__PURE__ */ jsx(Autocomplete.Portal, { children: /* @__PURE__ */ jsx(Autocomplete.Positioner, {
|
|
79
|
+
align: "start",
|
|
80
|
+
sideOffset: 4,
|
|
81
|
+
className: "rt:isolate rt:z-50",
|
|
82
|
+
children: /* @__PURE__ */ jsxs(Autocomplete.Popup, {
|
|
83
|
+
"data-slot": "global-search-panel",
|
|
84
|
+
className: "rt:flex rt:w-120 rt:max-w-full rt:flex-col rt:rounded-lg rt:border rt:border-border rt:bg-popover rt:text-b3 rt:text-popover-foreground rt:outline-hidden",
|
|
85
|
+
children: [
|
|
86
|
+
/* @__PURE__ */ jsx(Autocomplete.Empty, {
|
|
87
|
+
className: "rt:text-muted-foreground rt:not-empty:p-3",
|
|
88
|
+
children: showEmpty ? emptyText : null
|
|
89
|
+
}),
|
|
90
|
+
/* @__PURE__ */ jsx(Autocomplete.Status, {
|
|
91
|
+
className: "rt:sr-only",
|
|
92
|
+
children: status
|
|
93
|
+
}),
|
|
94
|
+
/* @__PURE__ */ jsx(Autocomplete.List, {
|
|
95
|
+
className: "rt:max-h-80 rt:overflow-y-auto rt:p-1 rt:outline-none",
|
|
96
|
+
children: (group) => /* @__PURE__ */ jsxs(Autocomplete.Group, {
|
|
97
|
+
items: group.items,
|
|
98
|
+
className: "rt:flex rt:flex-col",
|
|
99
|
+
children: [/* @__PURE__ */ jsx(Autocomplete.GroupLabel, {
|
|
100
|
+
className: "rt:px-2 rt:py-1.5 rt:text-c1 rt:text-muted-foreground",
|
|
101
|
+
children: group.label
|
|
102
|
+
}), /* @__PURE__ */ jsx(Autocomplete.Collection, { children: (row) => /* @__PURE__ */ jsxs(Autocomplete.Item, {
|
|
103
|
+
value: row,
|
|
104
|
+
onClick: () => choose(row),
|
|
105
|
+
className: "rt:flex rt:cursor-default rt:items-center rt:gap-2 rt:rounded-md rt:px-2 rt:py-1.5 rt:outline-none rt:select-none rt:data-highlighted:bg-muted",
|
|
106
|
+
children: [row.icon !== void 0 ? /* @__PURE__ */ jsx(Icon, {
|
|
107
|
+
name: row.icon,
|
|
108
|
+
tone: "icon"
|
|
109
|
+
}) : null, row.more !== void 0 ? /* @__PURE__ */ jsx("span", {
|
|
110
|
+
className: "rt:text-primary",
|
|
111
|
+
children: row.label
|
|
112
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
113
|
+
className: "rt:truncate",
|
|
114
|
+
children: row.label
|
|
115
|
+
}), row.description !== void 0 ? /* @__PURE__ */ jsx("span", {
|
|
116
|
+
className: "rt:ml-auto rt:truncate rt:text-muted-foreground",
|
|
117
|
+
children: row.description
|
|
118
|
+
}) : null] })]
|
|
119
|
+
}, row.id) })]
|
|
120
|
+
}, group.id)
|
|
121
|
+
}),
|
|
122
|
+
/* @__PURE__ */ jsxs("div", {
|
|
123
|
+
className: "rt:flex rt:items-center rt:gap-3 rt:border-t rt:border-border rt:px-3 rt:py-2 rt:text-c1 rt:text-muted-foreground",
|
|
124
|
+
children: [
|
|
125
|
+
/* @__PURE__ */ jsxs("span", {
|
|
126
|
+
className: "rt:inline-flex rt:items-center rt:gap-1",
|
|
127
|
+
children: [/* @__PURE__ */ jsxs(KbdGroup, { children: [/* @__PURE__ */ jsx(Kbd, { children: "↑" }), /* @__PURE__ */ jsx(Kbd, { children: "↓" })] }), "to move"]
|
|
128
|
+
}),
|
|
129
|
+
/* @__PURE__ */ jsxs("span", {
|
|
130
|
+
className: "rt:inline-flex rt:items-center rt:gap-1",
|
|
131
|
+
children: [/* @__PURE__ */ jsx(Kbd, { children: "↵" }), "to select"]
|
|
132
|
+
}),
|
|
133
|
+
/* @__PURE__ */ jsxs("span", {
|
|
134
|
+
className: "rt:inline-flex rt:items-center rt:gap-1",
|
|
135
|
+
children: [/* @__PURE__ */ jsx(Kbd, { children: "esc" }), "to close"]
|
|
136
|
+
})
|
|
137
|
+
]
|
|
138
|
+
})
|
|
139
|
+
]
|
|
140
|
+
})
|
|
141
|
+
}) })]
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
export { GlobalSearch };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { GlobalSearch } from "./GlobalSearch.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import "@tabler/icons-react";
|
|
2
2
|
/**
|
|
3
3
|
* The name of an icon. The design system's own glyphs come first (plus, search, export, the two pagination chevrons and
|
|
4
|
-
* the five navigation glyphs);
|
|
4
|
+
* the five navigation glyphs); the rest are Tabler icons drawn with a 1.5px line: check, x, alert-triangle, info-circle,
|
|
5
|
+
* the dashboard's navigation glyphs (nav-orders to nav-settings), import, more and menu (the phone menu button) and calendar (the date pickers' open button).
|
|
5
6
|
*/
|
|
6
|
-
export type IconName = 'plus' | 'search' | 'export' | 'chevron-left' | 'chevron-right' | 'nav-home' | 'nav-shortcut' | 'nav-product' | 'nav-product-2' | 'nav-chevron' | 'nav-caret-down' | 'check' | 'x' | 'alert-triangle' | 'info-circle';
|
|
7
|
+
export type IconName = 'plus' | 'search' | 'export' | 'chevron-left' | 'chevron-right' | 'nav-home' | 'nav-shortcut' | 'nav-product' | 'nav-product-2' | 'nav-chevron' | 'nav-caret-down' | 'check' | 'x' | 'alert-triangle' | 'info-circle' | 'nav-orders' | 'nav-customers' | 'nav-growth' | 'nav-discounts' | 'nav-content' | 'nav-markets' | 'nav-analytics' | 'nav-sales-channels' | 'nav-apps' | 'nav-settings' | 'import' | 'more' | 'menu' | 'calendar';
|