@misoto22/design 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/components/Accordion/Accordion.d.ts +34 -0
- package/dist/components/Accordion/Accordion.js +37 -0
- package/dist/components/Accordion/Accordion.js.map +1 -0
- package/dist/components/Alert/Alert.d.ts +32 -0
- package/dist/components/Alert/Alert.js +49 -0
- package/dist/components/Alert/Alert.js.map +1 -0
- package/dist/components/AppShell/AppShell.d.ts +38 -0
- package/dist/components/AppShell/AppShell.js +92 -0
- package/dist/components/AppShell/AppShell.js.map +1 -0
- package/dist/components/Avatar/Avatar.d.ts +29 -0
- package/dist/components/Avatar/Avatar.js +39 -0
- package/dist/components/Avatar/Avatar.js.map +1 -0
- package/dist/components/Badge/Badge.d.ts +30 -0
- package/dist/components/Badge/Badge.js +29 -0
- package/dist/components/Badge/Badge.js.map +1 -0
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +31 -0
- package/dist/components/Breadcrumb/Breadcrumb.js +31 -0
- package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -0
- package/dist/components/Button/Button.d.ts +70 -0
- package/dist/components/Button/Button.js +81 -0
- package/dist/components/Button/Button.js.map +1 -0
- package/dist/components/Calendar/Calendar.d.ts +28 -0
- package/dist/components/Calendar/Calendar.js +87 -0
- package/dist/components/Calendar/Calendar.js.map +1 -0
- package/dist/components/Card/Card.d.ts +49 -0
- package/dist/components/Card/Card.js +64 -0
- package/dist/components/Card/Card.js.map +1 -0
- package/dist/components/Checkbox/Checkbox.d.ts +23 -0
- package/dist/components/Checkbox/Checkbox.js +24 -0
- package/dist/components/Checkbox/Checkbox.js.map +1 -0
- package/dist/components/Collapsible/Collapsible.d.ts +31 -0
- package/dist/components/Collapsible/Collapsible.js +35 -0
- package/dist/components/Collapsible/Collapsible.js.map +1 -0
- package/dist/components/Combobox/Combobox.d.ts +63 -0
- package/dist/components/Combobox/Combobox.js +151 -0
- package/dist/components/Combobox/Combobox.js.map +1 -0
- package/dist/components/Command/Command.d.ts +98 -0
- package/dist/components/Command/Command.js +166 -0
- package/dist/components/Command/Command.js.map +1 -0
- package/dist/components/ContextMenu/ContextMenu.d.ts +38 -0
- package/dist/components/ContextMenu/ContextMenu.js +79 -0
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -0
- package/dist/components/DatePicker/DatePicker.d.ts +98 -0
- package/dist/components/DatePicker/DatePicker.js +214 -0
- package/dist/components/DatePicker/DatePicker.js.map +1 -0
- package/dist/components/Dialog/Dialog.d.ts +48 -0
- package/dist/components/Dialog/Dialog.js +72 -0
- package/dist/components/Dialog/Dialog.js.map +1 -0
- package/dist/components/DropdownMenu/DropdownMenu.d.ts +49 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +89 -0
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -0
- package/dist/components/EmptyState/EmptyState.d.ts +31 -0
- package/dist/components/EmptyState/EmptyState.js +30 -0
- package/dist/components/EmptyState/EmptyState.js.map +1 -0
- package/dist/components/ErrorState/ErrorState.d.ts +34 -0
- package/dist/components/ErrorState/ErrorState.js +32 -0
- package/dist/components/ErrorState/ErrorState.js.map +1 -0
- package/dist/components/Field/Field.d.ts +44 -0
- package/dist/components/Field/Field.js +54 -0
- package/dist/components/Field/Field.js.map +1 -0
- package/dist/components/FigureBand/FigureBand.d.ts +51 -0
- package/dist/components/FigureBand/FigureBand.js +52 -0
- package/dist/components/FigureBand/FigureBand.js.map +1 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.d.ts +29 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js +32 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js.map +1 -0
- package/dist/components/Input/Input.d.ts +22 -0
- package/dist/components/Input/Input.js +21 -0
- package/dist/components/Input/Input.js.map +1 -0
- package/dist/components/Kbd/Kbd.d.ts +20 -0
- package/dist/components/Kbd/Kbd.js +21 -0
- package/dist/components/Kbd/Kbd.js.map +1 -0
- package/dist/components/LinkArrow/LinkArrow.d.ts +24 -0
- package/dist/components/LinkArrow/LinkArrow.js +24 -0
- package/dist/components/LinkArrow/LinkArrow.js.map +1 -0
- package/dist/components/NativeSelect/NativeSelect.d.ts +27 -0
- package/dist/components/NativeSelect/NativeSelect.js +46 -0
- package/dist/components/NativeSelect/NativeSelect.js.map +1 -0
- package/dist/components/NavItem/NavItem.d.ts +39 -0
- package/dist/components/NavItem/NavItem.js +31 -0
- package/dist/components/NavItem/NavItem.js.map +1 -0
- package/dist/components/Pagination/Pagination.d.ts +44 -0
- package/dist/components/Pagination/Pagination.js +109 -0
- package/dist/components/Pagination/Pagination.js.map +1 -0
- package/dist/components/Popover/Popover.d.ts +39 -0
- package/dist/components/Popover/Popover.js +57 -0
- package/dist/components/Popover/Popover.js.map +1 -0
- package/dist/components/Progress/Progress.d.ts +31 -0
- package/dist/components/Progress/Progress.js +45 -0
- package/dist/components/Progress/Progress.js.map +1 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts +43 -0
- package/dist/components/RadioGroup/RadioGroup.js +43 -0
- package/dist/components/RadioGroup/RadioGroup.js.map +1 -0
- package/dist/components/ScrollArea/ScrollArea.d.ts +31 -0
- package/dist/components/ScrollArea/ScrollArea.js +54 -0
- package/dist/components/ScrollArea/ScrollArea.js.map +1 -0
- package/dist/components/SearchableMenu/SearchableMenu.d.ts +59 -0
- package/dist/components/SearchableMenu/SearchableMenu.js +79 -0
- package/dist/components/SearchableMenu/SearchableMenu.js.map +1 -0
- package/dist/components/Select/Select.d.ts +71 -0
- package/dist/components/Select/Select.js +114 -0
- package/dist/components/Select/Select.js.map +1 -0
- package/dist/components/Separator/Separator.d.ts +30 -0
- package/dist/components/Separator/Separator.js +35 -0
- package/dist/components/Separator/Separator.js.map +1 -0
- package/dist/components/Sheet/Sheet.d.ts +38 -0
- package/dist/components/Sheet/Sheet.js +68 -0
- package/dist/components/Sheet/Sheet.js.map +1 -0
- package/dist/components/Skeleton/Skeleton.d.ts +63 -0
- package/dist/components/Skeleton/Skeleton.js +44 -0
- package/dist/components/Skeleton/Skeleton.js.map +1 -0
- package/dist/components/Slider/Slider.d.ts +35 -0
- package/dist/components/Slider/Slider.js +52 -0
- package/dist/components/Slider/Slider.js.map +1 -0
- package/dist/components/Spinner/Spinner.d.ts +50 -0
- package/dist/components/Spinner/Spinner.js +48 -0
- package/dist/components/Spinner/Spinner.js.map +1 -0
- package/dist/components/StatusDot/StatusDot.d.ts +29 -0
- package/dist/components/StatusDot/StatusDot.js +44 -0
- package/dist/components/StatusDot/StatusDot.js.map +1 -0
- package/dist/components/StatusPill/StatusPill.d.ts +25 -0
- package/dist/components/StatusPill/StatusPill.js +31 -0
- package/dist/components/StatusPill/StatusPill.js.map +1 -0
- package/dist/components/Switch/Switch.d.ts +23 -0
- package/dist/components/Switch/Switch.js +23 -0
- package/dist/components/Switch/Switch.js.map +1 -0
- package/dist/components/Table/Table.d.ts +96 -0
- package/dist/components/Table/Table.js +136 -0
- package/dist/components/Table/Table.js.map +1 -0
- package/dist/components/Tabs/Tabs.d.ts +35 -0
- package/dist/components/Tabs/Tabs.js +48 -0
- package/dist/components/Tabs/Tabs.js.map +1 -0
- package/dist/components/Tag/Tag.d.ts +28 -0
- package/dist/components/Tag/Tag.js +22 -0
- package/dist/components/Tag/Tag.js.map +1 -0
- package/dist/components/Textarea/Textarea.d.ts +20 -0
- package/dist/components/Textarea/Textarea.js +32 -0
- package/dist/components/Textarea/Textarea.js.map +1 -0
- package/dist/components/Toast/Toast.d.ts +24 -0
- package/dist/components/Toast/Toast.js +41 -0
- package/dist/components/Toast/Toast.js.map +1 -0
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +41 -0
- package/dist/components/ToggleGroup/ToggleGroup.js +78 -0
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -0
- package/dist/components/Tooltip/Tooltip.d.ts +43 -0
- package/dist/components/Tooltip/Tooltip.js +40 -0
- package/dist/components/Tooltip/Tooltip.js.map +1 -0
- package/dist/fonts/hanken-grotesk-300.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-400.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-500.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-600.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-700.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-400.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-500.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-600.woff2 +0 -0
- package/dist/fonts/newsreader-300.woff2 +0 -0
- package/dist/fonts/newsreader-400.woff2 +0 -0
- package/dist/fonts/newsreader-500.woff2 +0 -0
- package/dist/fonts/newsreader-600.woff2 +0 -0
- package/dist/fonts.css +96 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +63 -0
- package/dist/index.js.map +1 -0
- package/dist/keyframes.css +212 -0
- package/dist/lib/cn.d.ts +21 -0
- package/dist/lib/cn.js +9 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/lib/control.d.ts +31 -0
- package/dist/lib/control.js +14 -0
- package/dist/lib/control.js.map +1 -0
- package/dist/lib/index.d.ts +4 -0
- package/dist/lib/index.js +11 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/overlay-container.d.ts +38 -0
- package/dist/lib/overlay-container.js +15 -0
- package/dist/lib/overlay-container.js.map +1 -0
- package/dist/lib/useSelectionIndicator.d.ts +29 -0
- package/dist/lib/useSelectionIndicator.js +45 -0
- package/dist/lib/useSelectionIndicator.js.map +1 -0
- package/dist/semantic.css +127 -0
- package/dist/styles.css +98 -0
- package/dist/themes.css +115 -0
- package/dist/tokens/brand.d.ts +47 -0
- package/dist/tokens/brand.js +38 -0
- package/dist/tokens/brand.js.map +1 -0
- package/dist/tokens.css +323 -0
- package/dist/tokens.d.ts +153 -0
- package/dist/tokens.js +766 -0
- package/dist/tokens.json +765 -0
- package/package.json +130 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ArrowDown, ArrowUp, ChevronsUpDown } from "lucide-react";
|
|
3
|
+
import { cn } from "../../lib/cn.js";
|
|
4
|
+
const ALIGN = {
|
|
5
|
+
start: "text-start",
|
|
6
|
+
center: "text-center",
|
|
7
|
+
end: "text-end"
|
|
8
|
+
};
|
|
9
|
+
const ROWS = "[&_thead]:border-b [&_thead]:border-(--rule-hard) [&_tbody_tr]:border-b [&_tbody_tr]:border-(--rule) [&_tbody_tr:last-child]:border-b-0";
|
|
10
|
+
const SOFT_HEAD = "[&_thead]:border-(--rule-2)";
|
|
11
|
+
const COLUMNS = "[&_th]:border-e [&_td]:border-e [&_th]:border-(--rule) [&_td]:border-(--rule) [&_th:last-child]:border-e-0 [&_td:last-child]:border-e-0";
|
|
12
|
+
const BOXED = "rounded-(--radius) border border-(--rule-2) [--table-pad-x:0.75rem]";
|
|
13
|
+
const BORDERS = {
|
|
14
|
+
rows: ROWS,
|
|
15
|
+
grid: cn(ROWS, COLUMNS, "[--table-pad-x:0.75rem]"),
|
|
16
|
+
bordered: cn(ROWS, SOFT_HEAD, BOXED),
|
|
17
|
+
"bordered-grid": cn(ROWS, SOFT_HEAD, COLUMNS, BOXED),
|
|
18
|
+
none: ""
|
|
19
|
+
};
|
|
20
|
+
function Table({
|
|
21
|
+
caption,
|
|
22
|
+
showCaption = false,
|
|
23
|
+
stickyHeader = false,
|
|
24
|
+
borders = "rows",
|
|
25
|
+
density = "comfortable",
|
|
26
|
+
className,
|
|
27
|
+
children,
|
|
28
|
+
...rest
|
|
29
|
+
}) {
|
|
30
|
+
return /* @__PURE__ */ jsx(
|
|
31
|
+
"div",
|
|
32
|
+
{
|
|
33
|
+
tabIndex: 0,
|
|
34
|
+
role: "region",
|
|
35
|
+
"aria-label": caption,
|
|
36
|
+
"data-table-density": density,
|
|
37
|
+
className: cn("w-full overflow-x-auto scroll-slim", BORDERS[borders]),
|
|
38
|
+
children: /* @__PURE__ */ jsxs(
|
|
39
|
+
"table",
|
|
40
|
+
{
|
|
41
|
+
className: cn(
|
|
42
|
+
"w-full border-collapse text-start text-sm",
|
|
43
|
+
stickyHeader && "[&_thead]:sticky [&_thead]:top-0 [&_thead]:z-(--z-rule) [&_thead]:bg-(--paper)",
|
|
44
|
+
className
|
|
45
|
+
),
|
|
46
|
+
...rest,
|
|
47
|
+
children: [
|
|
48
|
+
/* @__PURE__ */ jsx("caption", { className: cn(showCaption ? "pb-3 text-start eyebrow text-(--ink-3-aa)" : "sr-only"), children: caption }),
|
|
49
|
+
children
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
function THead({ className, ...rest }) {
|
|
57
|
+
return /* @__PURE__ */ jsx("thead", { className, ...rest });
|
|
58
|
+
}
|
|
59
|
+
function TBody({ className, ...rest }) {
|
|
60
|
+
return /* @__PURE__ */ jsx("tbody", { className, ...rest });
|
|
61
|
+
}
|
|
62
|
+
function TR({ className, ...rest }) {
|
|
63
|
+
return /* @__PURE__ */ jsx("tr", { className, ...rest });
|
|
64
|
+
}
|
|
65
|
+
const CELL = "px-[var(--table-pad-x,0)] [&:not(:last-child)]:pe-[calc(var(--table-pad-x,0px)+1.5rem)]";
|
|
66
|
+
const SORT_ICON = {
|
|
67
|
+
ascending: ArrowUp,
|
|
68
|
+
descending: ArrowDown,
|
|
69
|
+
none: ChevronsUpDown
|
|
70
|
+
};
|
|
71
|
+
function TH({
|
|
72
|
+
align = "start",
|
|
73
|
+
sortable = false,
|
|
74
|
+
sortDirection = "none",
|
|
75
|
+
onSort,
|
|
76
|
+
className,
|
|
77
|
+
children,
|
|
78
|
+
...rest
|
|
79
|
+
}) {
|
|
80
|
+
const Icon = SORT_ICON[sortDirection];
|
|
81
|
+
return /* @__PURE__ */ jsx(
|
|
82
|
+
"th",
|
|
83
|
+
{
|
|
84
|
+
scope: "col",
|
|
85
|
+
"aria-sort": sortable ? sortDirection : void 0,
|
|
86
|
+
className: cn(CELL, "py-3 align-bottom eyebrow text-(--ink-3-aa)", ALIGN[align], className),
|
|
87
|
+
...rest,
|
|
88
|
+
children: sortable ? /* @__PURE__ */ jsxs(
|
|
89
|
+
"button",
|
|
90
|
+
{
|
|
91
|
+
type: "button",
|
|
92
|
+
onClick: onSort,
|
|
93
|
+
className: cn(
|
|
94
|
+
"group inline-flex items-center gap-1.5 eyebrow transition-colors duration-(--duration-fast) hover:text-(--ink)",
|
|
95
|
+
sortDirection === "none" ? "text-(--ink-3-aa)" : "text-(--ink)"
|
|
96
|
+
),
|
|
97
|
+
children: [
|
|
98
|
+
children,
|
|
99
|
+
/* @__PURE__ */ jsx(
|
|
100
|
+
Icon,
|
|
101
|
+
{
|
|
102
|
+
size: 12,
|
|
103
|
+
strokeWidth: 2,
|
|
104
|
+
"aria-hidden": true,
|
|
105
|
+
className: cn(
|
|
106
|
+
"shrink-0 transition-opacity",
|
|
107
|
+
sortDirection === "none" && "opacity-40 group-hover:opacity-100"
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
) : children
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
function TD({ align = "start", className, ...rest }) {
|
|
118
|
+
return /* @__PURE__ */ jsx(
|
|
119
|
+
"td",
|
|
120
|
+
{
|
|
121
|
+
className: cn(CELL, "py-[var(--table-pad-y)] align-top text-(--ink-2)", ALIGN[align], className),
|
|
122
|
+
...rest
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
var Table_default = Table;
|
|
127
|
+
export {
|
|
128
|
+
TBody,
|
|
129
|
+
TD,
|
|
130
|
+
TH,
|
|
131
|
+
THead,
|
|
132
|
+
TR,
|
|
133
|
+
Table,
|
|
134
|
+
Table_default as default
|
|
135
|
+
};
|
|
136
|
+
//# sourceMappingURL=Table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Table/Table.tsx"],"sourcesContent":["import { ArrowDown, ArrowUp, ChevronsUpDown } from 'lucide-react'\nimport type { HTMLAttributes, TableHTMLAttributes, TdHTMLAttributes, ThHTMLAttributes } from 'react'\nimport { cn } from '../../lib/cn'\n\nexport type TableAlign = 'start' | 'center' | 'end'\n\n/**\n * Which rules the table draws.\n *\n * `rows` is the default and the right answer for reading down a column: one\n * hairline between records and nothing else, so the eye tracks a line across\n * without a grid competing for it. `grid` adds the vertical rules a dense\n * numeric table needs to keep columns apart. `bordered` puts an edge around the\n * whole thing, for a table that sits loose on a page rather than inside a card\n * that already has one. `none` is for a table inside something that draws its\n * own structure.\n */\nexport type TableBorders = 'rows' | 'grid' | 'bordered' | 'bordered-grid' | 'none'\n\nconst ALIGN: Record<TableAlign, string> = {\n start: 'text-start',\n center: 'text-center',\n end: 'text-end',\n}\n\n/**\n * Every rule the table draws, expressed from ONE element.\n *\n * Not React context, which was the first attempt: `createContext` makes the\n * module client-only, which turned every table on every page into a hydration\n * boundary and took the static build down with it. Descendant selectors from\n * the wrapper reach the same cells, cost nothing at runtime, and keep the whole\n * component server-renderable.\n *\n * `--table-pad-x` rather than a padding class per mode, because the ruled\n * variants need symmetric padding inside their boxes while the plain one wants\n * a trailing gap and no leading one.\n */\nconst ROWS =\n '[&_thead]:border-b [&_thead]:border-(--rule-hard) [&_tbody_tr]:border-b [&_tbody_tr]:border-(--rule) [&_tbody_tr:last-child]:border-b-0'\nconst SOFT_HEAD = '[&_thead]:border-(--rule-2)'\nconst COLUMNS =\n '[&_th]:border-e [&_td]:border-e [&_th]:border-(--rule) [&_td]:border-(--rule) [&_th:last-child]:border-e-0 [&_td:last-child]:border-e-0'\nconst BOXED = 'rounded-(--radius) border border-(--rule-2) [--table-pad-x:0.75rem]'\n\nconst BORDERS: Record<TableBorders, string> = {\n rows: ROWS,\n grid: cn(ROWS, COLUMNS, '[--table-pad-x:0.75rem]'),\n bordered: cn(ROWS, SOFT_HEAD, BOXED),\n 'bordered-grid': cn(ROWS, SOFT_HEAD, COLUMNS, BOXED),\n none: '',\n}\n\nexport interface TableProps extends TableHTMLAttributes<HTMLTableElement> {\n /**\n * Describes the table for a screen reader, which cannot see the heading above\n * it. Rendered as a visually-hidden `<caption>` — required, because an\n * unnamed table in a page with three tables is unnavigable.\n */\n caption: string\n /** Prints the caption instead of hiding it. */\n showCaption?: boolean\n /**\n * Pins the header row while the body scrolls. Needs a bounded height on the\n * container — otherwise the page scrolls, not the table, and nothing sticks.\n */\n stickyHeader?: boolean\n /** Which rules to draw. See {@link TableBorders}. */\n borders?: TableBorders\n /** Tightens the row padding, for a table that is mostly numbers. */\n density?: 'comfortable' | 'compact'\n}\n\n/**\n * A ruled data table.\n *\n * Wrapped in its own horizontally scrolling container, because a table is the\n * one block that legitimately exceeds the measure — and a page that scrolls\n * sideways as a whole is a layout bug, while a table that does is a table.\n *\n * That container is focusable, and it has to be. A scrollable region whose\n * contents are not themselves focusable is unreachable by keyboard: there is no\n * element to Tab to and therefore no way to press an arrow key at it, so the\n * columns past the fold simply do not exist for anyone not using a mouse.\n *\n * No zebra striping at any border setting. In a monochrome system a striped row\n * is a second surface competing with the page ground, and the hairline between\n * rows is already enough to track a line across.\n *\n * @example\n * <Table caption=\"Deploy history\">\n * <THead><TR><TH>Commit</TH><TH align=\"end\" sortable sortDirection={dir} onSort={sort}>Duration</TH></TR></THead>\n * <TBody><TR><TD>a1b2c3d</TD><TD align=\"end\">2m 14s</TD></TR></TBody>\n * </Table>\n * @example\n * <Table caption=\"Inventory\" borders=\"bordered-grid\" density=\"compact\">…</Table>\n */\nexport function Table({\n caption,\n showCaption = false,\n stickyHeader = false,\n borders = 'rows',\n density = 'comfortable',\n className,\n children,\n ...rest\n}: TableProps) {\n return (\n <div\n tabIndex={0}\n role=\"region\"\n aria-label={caption}\n data-table-density={density}\n className={cn('w-full overflow-x-auto scroll-slim', BORDERS[borders])}\n >\n <table\n className={cn(\n 'w-full border-collapse text-start text-sm',\n stickyHeader &&\n '[&_thead]:sticky [&_thead]:top-0 [&_thead]:z-(--z-rule) [&_thead]:bg-(--paper)',\n className,\n )}\n {...rest}\n >\n <caption className={cn(showCaption ? 'pb-3 text-start eyebrow text-(--ink-3-aa)' : 'sr-only')}>\n {caption}\n </caption>\n {children}\n </table>\n </div>\n )\n}\n\n/** Header group. The rule under it is drawn by the table's border setting. */\nexport function THead({ className, ...rest }: HTMLAttributes<HTMLTableSectionElement>) {\n return <thead className={className} {...rest} />\n}\n\nexport function TBody({ className, ...rest }: HTMLAttributes<HTMLTableSectionElement>) {\n return <tbody className={className} {...rest} />\n}\n\nexport function TR({ className, ...rest }: HTMLAttributes<HTMLTableRowElement>) {\n return <tr className={className} {...rest} />\n}\n\nexport type SortDirection = 'ascending' | 'descending' | 'none'\n\nexport interface THProps extends Omit<ThHTMLAttributes<HTMLTableCellElement>, 'align'> {\n /** Which edge the column's contents sit against. Numbers belong at `end`. */\n align?: TableAlign\n /** Makes the label a button and shows the sort marker. */\n sortable?: boolean\n /**\n * Which way this column is sorted. Also set as `aria-sort`, which is the\n * only way a screen reader learns a table is ordered at all — a caret drawn\n * in the header tells it nothing.\n */\n sortDirection?: SortDirection\n onSort?: () => void\n}\n\n/**\n * Cell padding, in one string both cells share.\n *\n * `--table-pad-x` is 0 by default and set by the ruled variants, so the plain\n * table keeps its trailing gap and no leading one while a boxed table gets\n * symmetric padding inside its border.\n */\nconst CELL =\n 'px-[var(--table-pad-x,0)] [&:not(:last-child)]:pe-[calc(var(--table-pad-x,0px)+1.5rem)]'\n\nconst SORT_ICON = {\n ascending: ArrowUp,\n descending: ArrowDown,\n none: ChevronsUpDown,\n} as const\n\n/**\n * A column label. Mono and uppercase, so it never reads as data.\n *\n * When sortable, the label becomes a `<button>` INSIDE the `<th>` rather than\n * the `<th>` becoming clickable: a cell with a click handler is not focusable\n * and not announced as a control, so the sort exists only for a mouse.\n *\n * Sorting is per column and opt-in. A table where every header is a button\n * invites the reader to try sorting a column the data cannot be ordered by.\n */\nexport function TH({\n align = 'start',\n sortable = false,\n sortDirection = 'none',\n onSort,\n className,\n children,\n ...rest\n}: THProps) {\n const Icon = SORT_ICON[sortDirection]\n\n return (\n <th\n scope=\"col\"\n aria-sort={sortable ? sortDirection : undefined}\n className={cn(CELL, 'py-3 align-bottom eyebrow text-(--ink-3-aa)', ALIGN[align], className)}\n {...rest}\n >\n {sortable ? (\n <button\n type=\"button\"\n onClick={onSort}\n className={cn(\n 'group inline-flex items-center gap-1.5 eyebrow transition-colors duration-(--duration-fast) hover:text-(--ink)',\n sortDirection === 'none' ? 'text-(--ink-3-aa)' : 'text-(--ink)',\n )}\n >\n {children}\n <Icon\n size={12}\n strokeWidth={2}\n aria-hidden\n className={cn(\n 'shrink-0 transition-opacity',\n sortDirection === 'none' && 'opacity-40 group-hover:opacity-100',\n )}\n />\n </button>\n ) : (\n children\n )}\n </th>\n )\n}\n\nexport interface TDProps extends Omit<TdHTMLAttributes<HTMLTableCellElement>, 'align'> {\n /** Which edge the cell's contents sit against. Match the column's header. */\n align?: TableAlign\n}\n\nexport function TD({ align = 'start', className, ...rest }: TDProps) {\n return (\n <td\n className={cn(CELL, 'py-[var(--table-pad-y)] align-top text-(--ink-2)', ALIGN[align], className)}\n {...rest}\n />\n )\n}\n\nexport default Table\n"],"mappings":"AAmHM,SASE,KATF;AAnHN,SAAS,WAAW,SAAS,sBAAsB;AAEnD,SAAS,UAAU;AAiBnB,MAAM,QAAoC;AAAA,EACxC,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,KAAK;AACP;AAeA,MAAM,OACJ;AACF,MAAM,YAAY;AAClB,MAAM,UACJ;AACF,MAAM,QAAQ;AAEd,MAAM,UAAwC;AAAA,EAC5C,MAAM;AAAA,EACN,MAAM,GAAG,MAAM,SAAS,yBAAyB;AAAA,EACjD,UAAU,GAAG,MAAM,WAAW,KAAK;AAAA,EACnC,iBAAiB,GAAG,MAAM,WAAW,SAAS,KAAK;AAAA,EACnD,MAAM;AACR;AA8CO,SAAS,MAAM;AAAA,EACpB;AAAA,EACA,cAAc;AAAA,EACd,eAAe;AAAA,EACf,UAAU;AAAA,EACV,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAe;AACb,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,sBAAoB;AAAA,MACpB,WAAW,GAAG,sCAAsC,QAAQ,OAAO,CAAC;AAAA,MAEpE;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YACA,gBACE;AAAA,YACF;AAAA,UACF;AAAA,UACC,GAAG;AAAA,UAEJ;AAAA,gCAAC,aAAQ,WAAW,GAAG,cAAc,8CAA8C,SAAS,GACzF,mBACH;AAAA,YACC;AAAA;AAAA;AAAA,MACH;AAAA;AAAA,EACF;AAEJ;AAGO,SAAS,MAAM,EAAE,WAAW,GAAG,KAAK,GAA4C;AACrF,SAAO,oBAAC,WAAM,WAAuB,GAAG,MAAM;AAChD;AAEO,SAAS,MAAM,EAAE,WAAW,GAAG,KAAK,GAA4C;AACrF,SAAO,oBAAC,WAAM,WAAuB,GAAG,MAAM;AAChD;AAEO,SAAS,GAAG,EAAE,WAAW,GAAG,KAAK,GAAwC;AAC9E,SAAO,oBAAC,QAAG,WAAuB,GAAG,MAAM;AAC7C;AAyBA,MAAM,OACJ;AAEF,MAAM,YAAY;AAAA,EAChB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,MAAM;AACR;AAYO,SAAS,GAAG;AAAA,EACjB,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAY;AACV,QAAM,OAAO,UAAU,aAAa;AAEpC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN,aAAW,WAAW,gBAAgB;AAAA,MACtC,WAAW,GAAG,MAAM,+CAA+C,MAAM,KAAK,GAAG,SAAS;AAAA,MACzF,GAAG;AAAA,MAEH,qBACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,WAAW;AAAA,YACT;AAAA,YACA,kBAAkB,SAAS,sBAAsB;AAAA,UACnD;AAAA,UAEC;AAAA;AAAA,YACD;AAAA,cAAC;AAAA;AAAA,gBACC,MAAM;AAAA,gBACN,aAAa;AAAA,gBACb,eAAW;AAAA,gBACX,WAAW;AAAA,kBACT;AAAA,kBACA,kBAAkB,UAAU;AAAA,gBAC9B;AAAA;AAAA,YACF;AAAA;AAAA;AAAA,MACF,IAEA;AAAA;AAAA,EAEJ;AAEJ;AAOO,SAAS,GAAG,EAAE,QAAQ,SAAS,WAAW,GAAG,KAAK,GAAY;AACnE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,MAAM,oDAAoD,MAAM,KAAK,GAAG,SAAS;AAAA,MAC9F,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,IAAO,gBAAQ;","names":[]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ComponentProps } from 'react';
|
|
3
|
+
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
|
4
|
+
|
|
5
|
+
/** Radix Tabs root, re-exported as a typed passthrough. */
|
|
6
|
+
declare const Tabs: react.ForwardRefExoticComponent<TabsPrimitive.TabsProps & react.RefAttributes<HTMLDivElement>>;
|
|
7
|
+
/**
|
|
8
|
+
* The tab strip.
|
|
9
|
+
*
|
|
10
|
+
* Scrolls horizontally rather than wrapping. A wrapped second row of tabs moves
|
|
11
|
+
* every tab below it when the strip grows, and the reader loses the one they
|
|
12
|
+
* were about to click.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* <Tabs defaultValue="preview">
|
|
16
|
+
* <TabsList>
|
|
17
|
+
* <TabsTrigger value="preview">Preview</TabsTrigger>
|
|
18
|
+
* <TabsTrigger value="code">Code</TabsTrigger>
|
|
19
|
+
* </TabsList>
|
|
20
|
+
* <TabsContent value="preview">…</TabsContent>
|
|
21
|
+
* </Tabs>
|
|
22
|
+
*/
|
|
23
|
+
declare function TabsList({ className, ...rest }: ComponentProps<typeof TabsPrimitive.List>): react.JSX.Element;
|
|
24
|
+
/**
|
|
25
|
+
* One tab.
|
|
26
|
+
*
|
|
27
|
+
* The active marker is a 2px ink rule pulled onto the strip's own border with
|
|
28
|
+
* `-mb-px`, so the two occupy the same line instead of stacking into a 3px
|
|
29
|
+
* edge. 44px tall, because a tab is a pointer target like any other.
|
|
30
|
+
*/
|
|
31
|
+
declare function TabsTrigger({ className, ...rest }: ComponentProps<typeof TabsPrimitive.Trigger>): react.JSX.Element;
|
|
32
|
+
/** The panel paired to a {@link TabsTrigger} by matching `value`. */
|
|
33
|
+
declare function TabsContent({ className, ...rest }: ComponentProps<typeof TabsPrimitive.Content>): react.JSX.Element;
|
|
34
|
+
|
|
35
|
+
export { Tabs, TabsContent, TabsList, TabsTrigger, Tabs as default };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
|
+
const Tabs = TabsPrimitive.Root;
|
|
6
|
+
function TabsList({ className, ...rest }) {
|
|
7
|
+
return /* @__PURE__ */ jsx(
|
|
8
|
+
TabsPrimitive.List,
|
|
9
|
+
{
|
|
10
|
+
className: cn(
|
|
11
|
+
"flex items-center gap-1 overflow-x-auto border-b border-(--rule-2) scroll-slim",
|
|
12
|
+
className
|
|
13
|
+
),
|
|
14
|
+
...rest
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
function TabsTrigger({ className, ...rest }) {
|
|
19
|
+
return /* @__PURE__ */ jsx(
|
|
20
|
+
TabsPrimitive.Trigger,
|
|
21
|
+
{
|
|
22
|
+
className: cn(
|
|
23
|
+
"-mb-px min-h-(--control-h-md) shrink-0 whitespace-nowrap border-b-2 border-transparent px-3.5 py-2 text-sm text-(--ink-3-aa) transition-colors duration-(--duration-fast) hover:text-(--ink) data-[state=active]:border-(--accent) data-[state=active]:text-(--accent-on-muted)",
|
|
24
|
+
className
|
|
25
|
+
),
|
|
26
|
+
...rest
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
function TabsContent({ className, ...rest }) {
|
|
31
|
+
return /* @__PURE__ */ jsx(
|
|
32
|
+
TabsPrimitive.Content,
|
|
33
|
+
{
|
|
34
|
+
"data-m22-animated": true,
|
|
35
|
+
className: cn("pt-5 data-[state=active]:animate-[m22-panel-in_var(--duration-fast)_var(--ease)]", className),
|
|
36
|
+
...rest
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
var Tabs_default = Tabs;
|
|
41
|
+
export {
|
|
42
|
+
Tabs,
|
|
43
|
+
TabsContent,
|
|
44
|
+
TabsList,
|
|
45
|
+
TabsTrigger,
|
|
46
|
+
Tabs_default as default
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=Tabs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Tabs/Tabs.tsx"],"sourcesContent":["'use client'\n\nimport * as TabsPrimitive from '@radix-ui/react-tabs'\nimport type { ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\n\n/** Radix Tabs root, re-exported as a typed passthrough. */\nexport const Tabs = TabsPrimitive.Root\n\n/**\n * The tab strip.\n *\n * Scrolls horizontally rather than wrapping. A wrapped second row of tabs moves\n * every tab below it when the strip grows, and the reader loses the one they\n * were about to click.\n *\n * @example\n * <Tabs defaultValue=\"preview\">\n * <TabsList>\n * <TabsTrigger value=\"preview\">Preview</TabsTrigger>\n * <TabsTrigger value=\"code\">Code</TabsTrigger>\n * </TabsList>\n * <TabsContent value=\"preview\">…</TabsContent>\n * </Tabs>\n */\nexport function TabsList({ className, ...rest }: ComponentProps<typeof TabsPrimitive.List>) {\n return (\n <TabsPrimitive.List\n className={cn(\n 'flex items-center gap-1 overflow-x-auto border-b border-(--rule-2) scroll-slim',\n className,\n )}\n {...rest}\n />\n )\n}\n\n/**\n * One tab.\n *\n * The active marker is a 2px ink rule pulled onto the strip's own border with\n * `-mb-px`, so the two occupy the same line instead of stacking into a 3px\n * edge. 44px tall, because a tab is a pointer target like any other.\n */\nexport function TabsTrigger({ className, ...rest }: ComponentProps<typeof TabsPrimitive.Trigger>) {\n return (\n <TabsPrimitive.Trigger\n className={cn(\n '-mb-px min-h-(--control-h-md) shrink-0 whitespace-nowrap border-b-2 border-transparent px-3.5 py-2 text-sm text-(--ink-3-aa) transition-colors duration-(--duration-fast) hover:text-(--ink) data-[state=active]:border-(--accent) data-[state=active]:text-(--accent-on-muted)',\n className,\n )}\n {...rest}\n />\n )\n}\n\n/** The panel paired to a {@link TabsTrigger} by matching `value`. */\nexport function TabsContent({ className, ...rest }: ComponentProps<typeof TabsPrimitive.Content>) {\n return (\n <TabsPrimitive.Content\n data-m22-animated\n className={cn('pt-5 data-[state=active]:animate-[m22-panel-in_var(--duration-fast)_var(--ease)]', className)}\n {...rest}\n />\n )\n}\n\nexport default Tabs\n"],"mappings":";AA2BI;AAzBJ,YAAY,mBAAmB;AAE/B,SAAS,UAAU;AAGZ,MAAM,OAAO,cAAc;AAkB3B,SAAS,SAAS,EAAE,WAAW,GAAG,KAAK,GAA8C;AAC1F,SACE;AAAA,IAAC,cAAc;AAAA,IAAd;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AASO,SAAS,YAAY,EAAE,WAAW,GAAG,KAAK,GAAiD;AAChG,SACE;AAAA,IAAC,cAAc;AAAA,IAAd;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAGO,SAAS,YAAY,EAAE,WAAW,GAAG,KAAK,GAAiD;AAChG,SACE;AAAA,IAAC,cAAc;AAAA,IAAd;AAAA,MACC,qBAAiB;AAAA,MACjB,WAAW,GAAG,oFAAoF,SAAS;AAAA,MAC1G,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,IAAO,eAAQ;","names":[]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface TagProps extends HTMLAttributes<HTMLSpanElement> {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
/** Renders the pressed/selected look. Pair with `aria-pressed` on a wrapper button. */
|
|
7
|
+
active?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A subject label — a topic, a technology, a filter facet.
|
|
11
|
+
*
|
|
12
|
+
* Distinct from `Badge`, which carries a state or a count. A tag names what
|
|
13
|
+
* something is ABOUT, so several sit together in a row and the reader scans
|
|
14
|
+
* them; a badge is one fact about one record.
|
|
15
|
+
*
|
|
16
|
+
* Presentational on purpose. To make a tag filter a list, wrap it in a button
|
|
17
|
+
* or a link at the call site and pass `active` — that keeps the focus ring,
|
|
18
|
+
* the pressed state and the keyboard handling with the element that actually
|
|
19
|
+
* owns them.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* <Tag>TypeScript</Tag>
|
|
23
|
+
* @example
|
|
24
|
+
* <button type="button" aria-pressed={on} onClick={toggle}><Tag active={on}>Rust</Tag></button>
|
|
25
|
+
*/
|
|
26
|
+
declare function Tag({ children, active, className, ...rest }: TagProps): react.JSX.Element;
|
|
27
|
+
|
|
28
|
+
export { Tag, type TagProps, Tag as default };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
function Tag({ children, active = false, className, ...rest }) {
|
|
4
|
+
return /* @__PURE__ */ jsx(
|
|
5
|
+
"span",
|
|
6
|
+
{
|
|
7
|
+
className: cn(
|
|
8
|
+
"inline-flex items-center rounded-(--radius-sm) px-2.5 py-1 font-mono text-xs tracking-wide transition-colors duration-(--duration-fast)",
|
|
9
|
+
active ? "bg-(--accent) text-(--accent-foreground)" : "bg-(--stone) text-(--ink-3-aa)",
|
|
10
|
+
className
|
|
11
|
+
),
|
|
12
|
+
...rest,
|
|
13
|
+
children
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
var Tag_default = Tag;
|
|
18
|
+
export {
|
|
19
|
+
Tag,
|
|
20
|
+
Tag_default as default
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=Tag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Tag/Tag.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\nexport interface TagProps extends HTMLAttributes<HTMLSpanElement> {\n children: ReactNode\n /** Renders the pressed/selected look. Pair with `aria-pressed` on a wrapper button. */\n active?: boolean\n}\n\n/**\n * A subject label — a topic, a technology, a filter facet.\n *\n * Distinct from `Badge`, which carries a state or a count. A tag names what\n * something is ABOUT, so several sit together in a row and the reader scans\n * them; a badge is one fact about one record.\n *\n * Presentational on purpose. To make a tag filter a list, wrap it in a button\n * or a link at the call site and pass `active` — that keeps the focus ring,\n * the pressed state and the keyboard handling with the element that actually\n * owns them.\n *\n * @example\n * <Tag>TypeScript</Tag>\n * @example\n * <button type=\"button\" aria-pressed={on} onClick={toggle}><Tag active={on}>Rust</Tag></button>\n */\nexport function Tag({ children, active = false, className, ...rest }: TagProps) {\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-(--radius-sm) px-2.5 py-1 font-mono text-xs tracking-wide transition-colors duration-(--duration-fast)',\n active ? 'bg-(--accent) text-(--accent-foreground)' : 'bg-(--stone) text-(--ink-3-aa)',\n className,\n )}\n {...rest}\n >\n {children}\n </span>\n )\n}\n\nexport default Tag\n"],"mappings":"AA4BI;AA3BJ,SAAS,UAAU;AAyBZ,SAAS,IAAI,EAAE,UAAU,SAAS,OAAO,WAAW,GAAG,KAAK,GAAa;AAC9E,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,SAAS,6CAA6C;AAAA,QACtD;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,cAAQ;","names":[]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { TextareaHTMLAttributes, Ref } from 'react';
|
|
3
|
+
|
|
4
|
+
interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
5
|
+
/** Paints the resting border with `--danger` and reflects `aria-invalid`. */
|
|
6
|
+
invalid?: boolean;
|
|
7
|
+
ref?: Ref<HTMLTextAreaElement>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Multi-line text entry.
|
|
11
|
+
*
|
|
12
|
+
* Resizes vertically only: horizontal resize lets a reader drag the control
|
|
13
|
+
* past the measure and past the page's own gutter.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* <Field label="Notes" htmlFor="notes"><Textarea id="notes" rows={4} /></Field>
|
|
17
|
+
*/
|
|
18
|
+
declare function Textarea({ invalid, className, ref, 'aria-invalid': ariaInvalid, ...rest }: TextareaProps): react.JSX.Element;
|
|
19
|
+
|
|
20
|
+
export { Textarea, type TextareaProps, Textarea as default };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
import { CONTROL_BASE, CONTROL_BORDER, isInvalid } from "../../lib/control.js";
|
|
4
|
+
function Textarea({
|
|
5
|
+
invalid,
|
|
6
|
+
className,
|
|
7
|
+
ref,
|
|
8
|
+
"aria-invalid": ariaInvalid,
|
|
9
|
+
...rest
|
|
10
|
+
}) {
|
|
11
|
+
const bad = isInvalid(invalid, ariaInvalid);
|
|
12
|
+
return /* @__PURE__ */ jsx(
|
|
13
|
+
"textarea",
|
|
14
|
+
{
|
|
15
|
+
ref,
|
|
16
|
+
"aria-invalid": ariaInvalid ?? (invalid ? true : void 0),
|
|
17
|
+
className: cn(
|
|
18
|
+
CONTROL_BASE,
|
|
19
|
+
"min-h-24 resize-y",
|
|
20
|
+
bad ? CONTROL_BORDER.invalid : CONTROL_BORDER.resting,
|
|
21
|
+
className
|
|
22
|
+
),
|
|
23
|
+
...rest
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
var Textarea_default = Textarea;
|
|
28
|
+
export {
|
|
29
|
+
Textarea,
|
|
30
|
+
Textarea_default as default
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=Textarea.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Textarea/Textarea.tsx"],"sourcesContent":["import type { Ref, TextareaHTMLAttributes } from 'react'\nimport { cn } from '../../lib/cn'\nimport { CONTROL_BASE, CONTROL_BORDER, isInvalid } from '../../lib/control'\n\nexport interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** Paints the resting border with `--danger` and reflects `aria-invalid`. */\n invalid?: boolean\n ref?: Ref<HTMLTextAreaElement>\n}\n\n/**\n * Multi-line text entry.\n *\n * Resizes vertically only: horizontal resize lets a reader drag the control\n * past the measure and past the page's own gutter.\n *\n * @example\n * <Field label=\"Notes\" htmlFor=\"notes\"><Textarea id=\"notes\" rows={4} /></Field>\n */\nexport function Textarea({\n invalid,\n className,\n ref,\n 'aria-invalid': ariaInvalid,\n ...rest\n}: TextareaProps) {\n const bad = isInvalid(invalid, ariaInvalid)\n return (\n <textarea\n ref={ref}\n aria-invalid={ariaInvalid ?? (invalid ? true : undefined)}\n className={cn(\n CONTROL_BASE,\n 'min-h-24 resize-y',\n bad ? CONTROL_BORDER.invalid : CONTROL_BORDER.resting,\n className,\n )}\n {...rest}\n />\n )\n}\n\nexport default Textarea\n"],"mappings":"AA4BI;AA3BJ,SAAS,UAAU;AACnB,SAAS,cAAc,gBAAgB,iBAAiB;AAiBjD,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB,GAAG;AACL,GAAkB;AAChB,QAAM,MAAM,UAAU,SAAS,WAAW;AAC1C,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,gBAAc,gBAAgB,UAAU,OAAO;AAAA,MAC/C,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA,MAAM,eAAe,UAAU,eAAe;AAAA,QAC9C;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,IAAO,mBAAQ;","names":[]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ToasterProps } from 'sonner';
|
|
3
|
+
export { toast } from 'sonner';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Transient confirmations, mounted once near the app root.
|
|
7
|
+
*
|
|
8
|
+
* A toast is for something that succeeded and needs no response. Anything the
|
|
9
|
+
* reader must act on belongs in the page — a toast is dismissed by time, and
|
|
10
|
+
* time is not an acknowledgement.
|
|
11
|
+
*
|
|
12
|
+
* `richColors` stays off by default: sonner's rich palette is not this system's
|
|
13
|
+
* status scale, and turning it on reintroduces chroma the White Reset spends
|
|
14
|
+
* only on state.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // app root
|
|
18
|
+
* <Toaster />
|
|
19
|
+
* // anywhere
|
|
20
|
+
* toast.success('Saved')
|
|
21
|
+
*/
|
|
22
|
+
declare function Toaster({ position, closeButton, richColors, style, ...rest }: ToasterProps): react.JSX.Element;
|
|
23
|
+
|
|
24
|
+
export { Toaster, Toaster as default };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Toaster as SonnerToaster, toast } from "sonner";
|
|
4
|
+
const TOKEN_STYLE = {
|
|
5
|
+
"--normal-bg": "var(--paper)",
|
|
6
|
+
"--normal-text": "var(--ink)",
|
|
7
|
+
"--normal-border": "var(--rule-2)",
|
|
8
|
+
"--success-bg": "var(--paper)",
|
|
9
|
+
"--success-text": "var(--ok)",
|
|
10
|
+
"--success-border": "var(--rule-2)",
|
|
11
|
+
"--error-bg": "var(--paper)",
|
|
12
|
+
"--error-text": "var(--danger)",
|
|
13
|
+
"--error-border": "var(--rule-2)",
|
|
14
|
+
"--border-radius": "var(--radius)",
|
|
15
|
+
fontFamily: "var(--sans)"
|
|
16
|
+
};
|
|
17
|
+
function Toaster({
|
|
18
|
+
position = "bottom-right",
|
|
19
|
+
closeButton = true,
|
|
20
|
+
richColors = false,
|
|
21
|
+
style,
|
|
22
|
+
...rest
|
|
23
|
+
}) {
|
|
24
|
+
return /* @__PURE__ */ jsx(
|
|
25
|
+
SonnerToaster,
|
|
26
|
+
{
|
|
27
|
+
position,
|
|
28
|
+
closeButton,
|
|
29
|
+
richColors,
|
|
30
|
+
style: { ...TOKEN_STYLE, ...style },
|
|
31
|
+
...rest
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
var Toast_default = Toaster;
|
|
36
|
+
export {
|
|
37
|
+
Toaster,
|
|
38
|
+
Toast_default as default,
|
|
39
|
+
toast
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=Toast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Toast/Toast.tsx"],"sourcesContent":["'use client'\n\nimport { Toaster as SonnerToaster, toast } from 'sonner'\nimport type { ToasterProps } from 'sonner'\nimport type { CSSProperties } from 'react'\n\n/**\n * Sonner's own custom properties, pointed at this system's tokens.\n *\n * Set as inline style on the Toaster rather than in a stylesheet: sonner\n * renders its list into a portal at the end of `<body>`, outside whatever\n * element a consumer's CSS is scoped to, and the inline style is the one place\n * guaranteed to reach it.\n *\n * Cast because this `@types/react` `CSSProperties` has no custom-property index\n * signature.\n */\nconst TOKEN_STYLE = {\n '--normal-bg': 'var(--paper)',\n '--normal-text': 'var(--ink)',\n '--normal-border': 'var(--rule-2)',\n '--success-bg': 'var(--paper)',\n '--success-text': 'var(--ok)',\n '--success-border': 'var(--rule-2)',\n '--error-bg': 'var(--paper)',\n '--error-text': 'var(--danger)',\n '--error-border': 'var(--rule-2)',\n '--border-radius': 'var(--radius)',\n fontFamily: 'var(--sans)',\n} as CSSProperties\n\n/**\n * Transient confirmations, mounted once near the app root.\n *\n * A toast is for something that succeeded and needs no response. Anything the\n * reader must act on belongs in the page — a toast is dismissed by time, and\n * time is not an acknowledgement.\n *\n * `richColors` stays off by default: sonner's rich palette is not this system's\n * status scale, and turning it on reintroduces chroma the White Reset spends\n * only on state.\n *\n * @example\n * // app root\n * <Toaster />\n * // anywhere\n * toast.success('Saved')\n */\nexport function Toaster({\n position = 'bottom-right',\n closeButton = true,\n richColors = false,\n style,\n ...rest\n}: ToasterProps) {\n return (\n <SonnerToaster\n position={position}\n closeButton={closeButton}\n richColors={richColors}\n style={{ ...TOKEN_STYLE, ...style }}\n {...rest}\n />\n )\n}\n\nexport { toast }\nexport default Toaster\n"],"mappings":";AAwDI;AAtDJ,SAAS,WAAW,eAAe,aAAa;AAehD,MAAM,cAAc;AAAA,EAClB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,YAAY;AACd;AAmBO,SAAS,QAAQ;AAAA,EACtB,WAAW;AAAA,EACX,cAAc;AAAA,EACd,aAAa;AAAA,EACb;AAAA,EACA,GAAG;AACL,GAAiB;AACf,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,EAAE,GAAG,aAAa,GAAG,MAAM;AAAA,MACjC,GAAG;AAAA;AAAA,EACN;AAEJ;AAGA,IAAO,gBAAQ;","names":[]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ComponentProps } from 'react';
|
|
3
|
+
import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group';
|
|
4
|
+
|
|
5
|
+
type ToggleGroupProps = ComponentProps<typeof ToggleGroupPrimitive.Root>;
|
|
6
|
+
/**
|
|
7
|
+
* A segmented control: several options, one strip.
|
|
8
|
+
*
|
|
9
|
+
* `type="single"` is a choice — Radix gives it radio semantics, and it is the
|
|
10
|
+
* right shape for a view switcher or a density setting. `type="multiple"` is a
|
|
11
|
+
* set of independent toggles, which is a different thing announced differently;
|
|
12
|
+
* choosing the wrong one is how a "filter by tag" control ends up telling a
|
|
13
|
+
* screen reader that picking one tag unpicks the others.
|
|
14
|
+
*
|
|
15
|
+
* The two look different on purpose. A single-value strip moves ONE filled pill
|
|
16
|
+
* between its options, so the eye follows a thing travelling; a multiple-value
|
|
17
|
+
* strip fills each pressed option separately, because there is no single
|
|
18
|
+
* selection to travel. Two people looking at a screenshot should be able to
|
|
19
|
+
* tell which kind they are looking at, and before this they could not.
|
|
20
|
+
*
|
|
21
|
+
* Distinct from `Tabs`, which switches PANELS and owns a tabpanel relationship.
|
|
22
|
+
* A toggle group changes a value.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* <ToggleGroup type="single" defaultValue="grid" aria-label="Layout">
|
|
26
|
+
* <ToggleGroupItem value="grid">Grid</ToggleGroupItem>
|
|
27
|
+
* <ToggleGroupItem value="list">List</ToggleGroupItem>
|
|
28
|
+
* </ToggleGroup>
|
|
29
|
+
*/
|
|
30
|
+
declare function ToggleGroup({ className, children, ...props }: ToggleGroupProps): react.JSX.Element;
|
|
31
|
+
type ToggleGroupItemProps = ComponentProps<typeof ToggleGroupPrimitive.Item>;
|
|
32
|
+
/**
|
|
33
|
+
* One segment.
|
|
34
|
+
*
|
|
35
|
+
* In a single-value group the item draws no background of its own — the
|
|
36
|
+
* travelling pill behind it does — so it only changes ink. In a multiple-value
|
|
37
|
+
* group it fills, because there is nothing travelling.
|
|
38
|
+
*/
|
|
39
|
+
declare function ToggleGroupItem({ className, value, ...props }: ToggleGroupItemProps): react.JSX.Element;
|
|
40
|
+
|
|
41
|
+
export { ToggleGroup, ToggleGroupItem, type ToggleGroupItemProps, type ToggleGroupProps, ToggleGroup as default };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
|
|
4
|
+
import { createContext, useContext, useState } from "react";
|
|
5
|
+
import { cn } from "../../lib/cn.js";
|
|
6
|
+
import { useSelectionIndicator } from "../../lib/useSelectionIndicator.js";
|
|
7
|
+
const SingleValueContext = createContext(null);
|
|
8
|
+
function ToggleGroup({ className, children, ...props }) {
|
|
9
|
+
const single = props.type === "single";
|
|
10
|
+
const [uncontrolled, setUncontrolled] = useState(
|
|
11
|
+
(single ? props.defaultValue : void 0) ?? ""
|
|
12
|
+
);
|
|
13
|
+
const value = single ? props.value ?? uncontrolled : null;
|
|
14
|
+
const [ref, indicator] = useSelectionIndicator(value);
|
|
15
|
+
const root = /* @__PURE__ */ jsxs(
|
|
16
|
+
ToggleGroupPrimitive.Root,
|
|
17
|
+
{
|
|
18
|
+
ref,
|
|
19
|
+
className: cn(
|
|
20
|
+
// `w-fit` as well as `inline-flex`: a flex or grid parent stretches its
|
|
21
|
+
// children to the track by default, and `inline-flex` does not opt out
|
|
22
|
+
// of that. Without it the strip grew to whatever the widest sibling was
|
|
23
|
+
// — a label above it — and left dead space after the last segment.
|
|
24
|
+
"relative inline-flex w-fit items-center gap-1 rounded-(--radius-pill) border border-(--rule-2) p-1",
|
|
25
|
+
className
|
|
26
|
+
),
|
|
27
|
+
...props,
|
|
28
|
+
onValueChange: (next) => {
|
|
29
|
+
if (single) setUncontrolled(next ?? "");
|
|
30
|
+
props.onValueChange?.(next);
|
|
31
|
+
},
|
|
32
|
+
children: [
|
|
33
|
+
single && indicator.ready && /* @__PURE__ */ jsx(
|
|
34
|
+
"span",
|
|
35
|
+
{
|
|
36
|
+
"aria-hidden": true,
|
|
37
|
+
"data-m22-animated": true,
|
|
38
|
+
className: "absolute rounded-(--radius-pill) bg-(--accent) transition-[transform,width] duration-(--duration-base) ease-(--ease-out-expo) motion-reduce:transition-none",
|
|
39
|
+
style: {
|
|
40
|
+
transform: `translate(${indicator.offset}px, ${indicator.top}px)`,
|
|
41
|
+
width: indicator.width,
|
|
42
|
+
height: indicator.height,
|
|
43
|
+
insetInlineStart: 0,
|
|
44
|
+
top: 0
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
),
|
|
48
|
+
children
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
return single ? /* @__PURE__ */ jsx(SingleValueContext.Provider, { value, children: root }) : root;
|
|
53
|
+
}
|
|
54
|
+
function ToggleGroupItem({ className, value, ...props }) {
|
|
55
|
+
const selected = useContext(SingleValueContext);
|
|
56
|
+
const isSingle = selected !== null;
|
|
57
|
+
const active = isSingle && selected === value;
|
|
58
|
+
return /* @__PURE__ */ jsx(
|
|
59
|
+
ToggleGroupPrimitive.Item,
|
|
60
|
+
{
|
|
61
|
+
value,
|
|
62
|
+
"data-indicator-active": active ? "true" : void 0,
|
|
63
|
+
className: cn(
|
|
64
|
+
"relative z-1 inline-flex min-h-(--control-h-sm) items-center justify-center gap-2 rounded-(--radius-pill) px-3.5 text-sm transition-colors duration-(--duration-fast) disabled:opacity-(--disabled-opacity) disabled:pointer-events-none",
|
|
65
|
+
isSingle ? active ? "text-(--accent-foreground)" : "text-(--ink-3-aa) hover:text-(--ink)" : "text-(--ink-3-aa) hover:text-(--ink) data-[state=on]:bg-(--accent) data-[state=on]:text-(--accent-foreground)",
|
|
66
|
+
className
|
|
67
|
+
),
|
|
68
|
+
...props
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
var ToggleGroup_default = ToggleGroup;
|
|
73
|
+
export {
|
|
74
|
+
ToggleGroup,
|
|
75
|
+
ToggleGroupItem,
|
|
76
|
+
ToggleGroup_default as default
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=ToggleGroup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ToggleGroup/ToggleGroup.tsx"],"sourcesContent":["'use client'\n\nimport * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group'\nimport { createContext, useContext, useState, type ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useSelectionIndicator } from '../../lib/useSelectionIndicator'\n\nexport type ToggleGroupProps = ComponentProps<typeof ToggleGroupPrimitive.Root>\n\n/** Lets an item know whether the group tracks one value or several. */\nconst SingleValueContext = createContext<string | null>(null)\n\n/**\n * A segmented control: several options, one strip.\n *\n * `type=\"single\"` is a choice — Radix gives it radio semantics, and it is the\n * right shape for a view switcher or a density setting. `type=\"multiple\"` is a\n * set of independent toggles, which is a different thing announced differently;\n * choosing the wrong one is how a \"filter by tag\" control ends up telling a\n * screen reader that picking one tag unpicks the others.\n *\n * The two look different on purpose. A single-value strip moves ONE filled pill\n * between its options, so the eye follows a thing travelling; a multiple-value\n * strip fills each pressed option separately, because there is no single\n * selection to travel. Two people looking at a screenshot should be able to\n * tell which kind they are looking at, and before this they could not.\n *\n * Distinct from `Tabs`, which switches PANELS and owns a tabpanel relationship.\n * A toggle group changes a value.\n *\n * @example\n * <ToggleGroup type=\"single\" defaultValue=\"grid\" aria-label=\"Layout\">\n * <ToggleGroupItem value=\"grid\">Grid</ToggleGroupItem>\n * <ToggleGroupItem value=\"list\">List</ToggleGroupItem>\n * </ToggleGroup>\n */\nexport function ToggleGroup({ className, children, ...props }: ToggleGroupProps) {\n // Tracked here rather than left to Radix alone, because the sliding pill has\n // to know which item to measure — and an uncontrolled group never tells\n // anyone what it picked.\n const single = props.type === 'single'\n const [uncontrolled, setUncontrolled] = useState<string>(\n (single ? (props.defaultValue as string | undefined) : undefined) ?? '',\n )\n const value = single ? ((props.value as string | undefined) ?? uncontrolled) : null\n const [ref, indicator] = useSelectionIndicator<HTMLDivElement>(value)\n\n const root = (\n <ToggleGroupPrimitive.Root\n ref={ref}\n className={cn(\n // `w-fit` as well as `inline-flex`: a flex or grid parent stretches its\n // children to the track by default, and `inline-flex` does not opt out\n // of that. Without it the strip grew to whatever the widest sibling was\n // — a label above it — and left dead space after the last segment.\n 'relative inline-flex w-fit items-center gap-1 rounded-(--radius-pill) border border-(--rule-2) p-1',\n className,\n )}\n {...props}\n onValueChange={(next: never) => {\n if (single) setUncontrolled((next as string) ?? '')\n ;(props.onValueChange as ((v: never) => void) | undefined)?.(next)\n }}\n >\n {single && indicator.ready && (\n <span\n aria-hidden\n data-m22-animated\n className=\"absolute rounded-(--radius-pill) bg-(--accent) transition-[transform,width] duration-(--duration-base) ease-(--ease-out-expo) motion-reduce:transition-none\"\n style={{\n transform: `translate(${indicator.offset}px, ${indicator.top}px)`,\n width: indicator.width,\n height: indicator.height,\n insetInlineStart: 0,\n top: 0,\n }}\n />\n )}\n {children}\n </ToggleGroupPrimitive.Root>\n )\n\n return single ? (\n <SingleValueContext.Provider value={value}>{root}</SingleValueContext.Provider>\n ) : (\n root\n )\n}\n\nexport type ToggleGroupItemProps = ComponentProps<typeof ToggleGroupPrimitive.Item>\n\n/**\n * One segment.\n *\n * In a single-value group the item draws no background of its own — the\n * travelling pill behind it does — so it only changes ink. In a multiple-value\n * group it fills, because there is nothing travelling.\n */\nexport function ToggleGroupItem({ className, value, ...props }: ToggleGroupItemProps) {\n const selected = useContext(SingleValueContext)\n const isSingle = selected !== null\n const active = isSingle && selected === value\n\n return (\n <ToggleGroupPrimitive.Item\n value={value}\n data-indicator-active={active ? 'true' : undefined}\n className={cn(\n 'relative z-1 inline-flex min-h-(--control-h-sm) items-center justify-center gap-2 rounded-(--radius-pill) px-3.5 text-sm transition-colors duration-(--duration-fast) disabled:opacity-(--disabled-opacity) disabled:pointer-events-none',\n isSingle\n ? active\n ? 'text-(--accent-foreground)'\n : 'text-(--ink-3-aa) hover:text-(--ink)'\n : 'text-(--ink-3-aa) hover:text-(--ink) data-[state=on]:bg-(--accent) data-[state=on]:text-(--accent-foreground)',\n className,\n )}\n {...props}\n />\n )\n}\n\nexport default ToggleGroup\n"],"mappings":";AAgDI,SAiBI,KAjBJ;AA9CJ,YAAY,0BAA0B;AACtC,SAAS,eAAe,YAAY,gBAAqC;AACzE,SAAS,UAAU;AACnB,SAAS,6BAA6B;AAKtC,MAAM,qBAAqB,cAA6B,IAAI;AA0BrD,SAAS,YAAY,EAAE,WAAW,UAAU,GAAG,MAAM,GAAqB;AAI/E,QAAM,SAAS,MAAM,SAAS;AAC9B,QAAM,CAAC,cAAc,eAAe,IAAI;AAAA,KACrC,SAAU,MAAM,eAAsC,WAAc;AAAA,EACvE;AACA,QAAM,QAAQ,SAAW,MAAM,SAAgC,eAAgB;AAC/E,QAAM,CAAC,KAAK,SAAS,IAAI,sBAAsC,KAAK;AAEpE,QAAM,OACJ;AAAA,IAAC,qBAAqB;AAAA,IAArB;AAAA,MACC;AAAA,MACA,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,QAKT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MACJ,eAAe,CAAC,SAAgB;AAC9B,YAAI,OAAQ,iBAAiB,QAAmB,EAAE;AACjD,QAAC,MAAM,gBAAqD,IAAI;AAAA,MACnE;AAAA,MAEC;AAAA,kBAAU,UAAU,SACnB;AAAA,UAAC;AAAA;AAAA,YACC,eAAW;AAAA,YACX,qBAAiB;AAAA,YACjB,WAAU;AAAA,YACV,OAAO;AAAA,cACL,WAAW,aAAa,UAAU,MAAM,OAAO,UAAU,GAAG;AAAA,cAC5D,OAAO,UAAU;AAAA,cACjB,QAAQ,UAAU;AAAA,cAClB,kBAAkB;AAAA,cAClB,KAAK;AAAA,YACP;AAAA;AAAA,QACF;AAAA,QAED;AAAA;AAAA;AAAA,EACH;AAGF,SAAO,SACL,oBAAC,mBAAmB,UAAnB,EAA4B,OAAe,gBAAK,IAEjD;AAEJ;AAWO,SAAS,gBAAgB,EAAE,WAAW,OAAO,GAAG,MAAM,GAAyB;AACpF,QAAM,WAAW,WAAW,kBAAkB;AAC9C,QAAM,WAAW,aAAa;AAC9B,QAAM,SAAS,YAAY,aAAa;AAExC,SACE;AAAA,IAAC,qBAAqB;AAAA,IAArB;AAAA,MACC;AAAA,MACA,yBAAuB,SAAS,SAAS;AAAA,MACzC,WAAW;AAAA,QACT;AAAA,QACA,WACI,SACE,+BACA,yCACF;AAAA,QACJ;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,IAAO,sBAAQ;","names":[]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ComponentProps, ReactNode } from 'react';
|
|
3
|
+
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Wrap the app — or the smallest subtree that has tooltips — once. Radix needs
|
|
7
|
+
* it to share the open/close timing between neighbouring triggers, which is
|
|
8
|
+
* what stops a row of icon buttons flashing a tooltip per hover.
|
|
9
|
+
*/
|
|
10
|
+
declare const TooltipProvider: react.FC<TooltipPrimitive.TooltipProviderProps>;
|
|
11
|
+
interface TooltipProps extends Pick<ComponentProps<typeof TooltipPrimitive.Root>, 'open' | 'defaultOpen' | 'onOpenChange' | 'delayDuration'> {
|
|
12
|
+
/** The element the tooltip describes. Must be focusable. */
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
/**
|
|
15
|
+
* The tip. Keep it to a phrase — a tooltip is unreachable on touch and
|
|
16
|
+
* invisible to a reader who is scanning, so anything a user NEEDS belongs on
|
|
17
|
+
* the page instead.
|
|
18
|
+
*/
|
|
19
|
+
content: ReactNode;
|
|
20
|
+
side?: ComponentProps<typeof TooltipPrimitive.Content>['side'];
|
|
21
|
+
sideOffset?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A short label on hover and on focus.
|
|
25
|
+
*
|
|
26
|
+
* `asChild` on the trigger by design: the tooltip must not add a wrapper that
|
|
27
|
+
* swallows the trigger's own focus ring or breaks a flex row. It also means the
|
|
28
|
+
* child has to be focusable — a `<div>` trigger gets no keyboard tooltip, which
|
|
29
|
+
* is the failure this API shape makes obvious rather than silent.
|
|
30
|
+
*
|
|
31
|
+
* Not a replacement for an accessible name. An icon-only button still needs its
|
|
32
|
+
* own `aria-label`; the tooltip repeats that name for sighted pointer users.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* <TooltipProvider>
|
|
36
|
+
* <Tooltip content="Copy to clipboard">
|
|
37
|
+
* <Button iconOnly aria-label="Copy"><Copy size={16} /></Button>
|
|
38
|
+
* </Tooltip>
|
|
39
|
+
* </TooltipProvider>
|
|
40
|
+
*/
|
|
41
|
+
declare function Tooltip({ children, content, side, sideOffset, ...root }: TooltipProps): react.JSX.Element;
|
|
42
|
+
|
|
43
|
+
export { Tooltip, type TooltipProps, TooltipProvider, Tooltip as default };
|