kaze-design-system 0.8.0 → 0.8.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/dist/components/Avatar/Avatar.js +2 -2
- package/dist/components/BarList/BarList.js +10 -2
- package/dist/components/ColumnChart/ColumnChart.js +5 -17
- package/dist/components/CommandPalette/CommandPalette.js +37 -29
- package/dist/components/Dialog/Dialog.js +1 -0
- package/dist/components/Disclosure/Disclosure.js +7 -6
- package/dist/components/Dropdown/Dropdown.js +20 -17
- package/dist/components/Icon/Icon.js +2 -12
- package/dist/components/LineChart/LineChart.js +5 -17
- package/dist/components/NumberField/NumberField.js +2 -0
- package/dist/components/Pagination/Pagination.js +3 -3
- package/dist/components/Search/Search.js +39 -35
- package/dist/components/Sidebar/Sidebar.js +4 -1
- package/dist/components/Stepper/Stepper.js +22 -19
- package/dist/components/Table/Table.js +1 -10
- package/dist/components/Toast/Toast.js +6 -1
- package/dist/lib/useChartWidth.js +28 -0
- package/dist/types/lib/useChartWidth.d.ts +14 -0
- package/package.json +1 -1
|
@@ -4,12 +4,12 @@ import { cn } from "../../lib/utils.js";
|
|
|
4
4
|
const Avatar = forwardRef(
|
|
5
5
|
({ size = "md", src, alt, fallback, className, ...rest }, ref) => {
|
|
6
6
|
const showFallback = !src && fallback;
|
|
7
|
+
const a11yProps = showFallback ? { role: "img", "aria-label": fallback } : {};
|
|
7
8
|
return /* @__PURE__ */ jsx(
|
|
8
9
|
"span",
|
|
9
10
|
{
|
|
10
11
|
ref,
|
|
11
|
-
|
|
12
|
-
"aria-label": showFallback ? fallback : void 0,
|
|
12
|
+
...a11yProps,
|
|
13
13
|
className: cn("avatar", `avatar--${size}`, className),
|
|
14
14
|
...rest,
|
|
15
15
|
children: src ? /* @__PURE__ */ jsx("img", { src, alt: alt ?? "" }) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: fallback })
|
|
@@ -7,7 +7,7 @@ const BarList = forwardRef(
|
|
|
7
7
|
(a, b) => sortOrder === "ascending" ? a.value - b.value : b.value - a.value
|
|
8
8
|
);
|
|
9
9
|
const maxValue = Math.max(...sorted.map((d) => d.value), 1);
|
|
10
|
-
return /* @__PURE__ */ jsx("div", { ref, className: cn("barlist", className), ...rest, children: sorted.map((item
|
|
10
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn("barlist", className), ...rest, children: sorted.map((item) => {
|
|
11
11
|
const pct = item.value / maxValue * 100;
|
|
12
12
|
const display = item.displayValue ?? (valueFormatter ? valueFormatter(item.value) : String(item.value));
|
|
13
13
|
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -27,7 +27,15 @@ const BarList = forwardRef(
|
|
|
27
27
|
/* @__PURE__ */ jsx("span", { className: "barlist__value", children: display })
|
|
28
28
|
] });
|
|
29
29
|
const LinkComponent = item.as ?? "a";
|
|
30
|
-
return item.href ? /* @__PURE__ */ jsx(
|
|
30
|
+
return item.href ? /* @__PURE__ */ jsx(
|
|
31
|
+
LinkComponent,
|
|
32
|
+
{
|
|
33
|
+
href: item.href,
|
|
34
|
+
className: "barlist__row barlist__row--link",
|
|
35
|
+
children: content
|
|
36
|
+
},
|
|
37
|
+
item.label
|
|
38
|
+
) : /* @__PURE__ */ jsx("div", { className: "barlist__row", children: content }, item.label);
|
|
31
39
|
}) });
|
|
32
40
|
}
|
|
33
41
|
);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
|
-
import { forwardRef,
|
|
3
|
+
import { forwardRef, useState, useCallback, useMemo } from "react";
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
5
|
import { CHART_COLORS } from "../../lib/chartColors.js";
|
|
6
6
|
import { niceScale, linearScale, defaultFormat } from "../../lib/chartScale.js";
|
|
7
|
+
import { useChartWidth } from "../../lib/useChartWidth.js";
|
|
7
8
|
import { ChartLegend } from "../ChartLegend/ChartLegend.js";
|
|
8
9
|
const FALLBACK_WIDTH = 640;
|
|
9
10
|
const PAD_TOP = 8;
|
|
@@ -43,23 +44,9 @@ const ColumnChart = forwardRef(
|
|
|
43
44
|
onBlur,
|
|
44
45
|
...rest
|
|
45
46
|
}, ref) => {
|
|
46
|
-
const wrapRef =
|
|
47
|
-
const [width, setWidth] = useState(FALLBACK_WIDTH);
|
|
47
|
+
const { ref: wrapRef, width, measured } = useChartWidth(FALLBACK_WIDTH);
|
|
48
48
|
const [hidden, setHidden] = useState([]);
|
|
49
49
|
const [active, setActive] = useState(null);
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
const el = wrapRef.current;
|
|
52
|
-
if (!el) return;
|
|
53
|
-
const measure = () => {
|
|
54
|
-
const w = el.clientWidth;
|
|
55
|
-
if (w > 0) setWidth(w);
|
|
56
|
-
};
|
|
57
|
-
measure();
|
|
58
|
-
if (typeof ResizeObserver === "undefined") return;
|
|
59
|
-
const ro = new ResizeObserver(measure);
|
|
60
|
-
ro.observe(el);
|
|
61
|
-
return () => ro.disconnect();
|
|
62
|
-
}, []);
|
|
63
50
|
const toggle = useCallback((key) => {
|
|
64
51
|
setHidden((prev) => prev.includes(key) ? prev.filter((k) => k !== key) : [...prev, key]);
|
|
65
52
|
}, []);
|
|
@@ -177,9 +164,10 @@ const ColumnChart = forwardRef(
|
|
|
177
164
|
"svg",
|
|
178
165
|
{
|
|
179
166
|
className: "chart__svg column-chart__svg",
|
|
180
|
-
width,
|
|
167
|
+
width: measured ? width : "100%",
|
|
181
168
|
height,
|
|
182
169
|
viewBox: `0 0 ${width} ${height}`,
|
|
170
|
+
preserveAspectRatio: measured ? void 0 : "none",
|
|
183
171
|
onPointerLeave: () => setActive(null),
|
|
184
172
|
"aria-hidden": "true",
|
|
185
173
|
children: [
|
|
@@ -37,10 +37,12 @@ const CommandPalette = forwardRef(
|
|
|
37
37
|
const groups = /* @__PURE__ */ new Map();
|
|
38
38
|
for (const cmd of filtered) {
|
|
39
39
|
const group = cmd.group ?? "";
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
const list = groups.get(group);
|
|
41
|
+
if (list) {
|
|
42
|
+
list.push(cmd);
|
|
43
|
+
} else {
|
|
44
|
+
groups.set(group, [cmd]);
|
|
42
45
|
}
|
|
43
|
-
groups.get(group).push(cmd);
|
|
44
46
|
}
|
|
45
47
|
return groups;
|
|
46
48
|
}, [filtered]);
|
|
@@ -118,6 +120,8 @@ const CommandPalette = forwardRef(
|
|
|
118
120
|
if (typeof document === "undefined") return null;
|
|
119
121
|
let flatIndex = 0;
|
|
120
122
|
return createPortal(
|
|
123
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: the backdrop only handles click-outside-to-close; keyboard users close the palette with Escape, and the backdrop itself must not be focusable.
|
|
124
|
+
// biome-ignore lint/a11y/useKeyWithClickEvents: Escape is handled by the dialog's onKeyDown; the backdrop has no keyboard role of its own.
|
|
121
125
|
/* @__PURE__ */ jsx("div", { className: "overlay", onClick: handleOverlayClick, children: /* @__PURE__ */ jsxs(
|
|
122
126
|
"div",
|
|
123
127
|
{
|
|
@@ -152,33 +156,37 @@ const CommandPalette = forwardRef(
|
|
|
152
156
|
group && /* @__PURE__ */ jsx("div", { className: "command-palette__group", children: group }),
|
|
153
157
|
cmds.map((cmd) => {
|
|
154
158
|
const index = flatIndex++;
|
|
155
|
-
return
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
"
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
"command-
|
|
163
|
-
index === highlightedIndex
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
children: [
|
|
168
|
-
cmd.icon && /* @__PURE__ */ jsx(
|
|
169
|
-
"span",
|
|
170
|
-
{
|
|
171
|
-
style: {
|
|
172
|
-
display: "inline-flex",
|
|
173
|
-
flexShrink: 0
|
|
174
|
-
},
|
|
175
|
-
children: cmd.icon
|
|
176
|
-
}
|
|
159
|
+
return (
|
|
160
|
+
// biome-ignore lint/a11y/useKeyWithClickEvents: Arrow/Enter selection is handled by the dialog's onKeyDown while focus stays on the search input (listbox pattern).
|
|
161
|
+
// biome-ignore lint/a11y/useFocusableInteractive: options must not take focus; focus stays on the search input and the highlighted option is tracked via aria-selected.
|
|
162
|
+
/* @__PURE__ */ jsxs(
|
|
163
|
+
"div",
|
|
164
|
+
{
|
|
165
|
+
role: "option",
|
|
166
|
+
"data-command-item": "",
|
|
167
|
+
"aria-selected": index === highlightedIndex,
|
|
168
|
+
className: cn(
|
|
169
|
+
"command-palette__item",
|
|
170
|
+
index === highlightedIndex && "command-palette__item--active"
|
|
177
171
|
),
|
|
178
|
-
cmd
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
172
|
+
onClick: () => handleSelect(cmd),
|
|
173
|
+
onMouseEnter: () => setHighlightedIndex(index),
|
|
174
|
+
children: [
|
|
175
|
+
cmd.icon && /* @__PURE__ */ jsx(
|
|
176
|
+
"span",
|
|
177
|
+
{
|
|
178
|
+
style: {
|
|
179
|
+
display: "inline-flex",
|
|
180
|
+
flexShrink: 0
|
|
181
|
+
},
|
|
182
|
+
children: cmd.icon
|
|
183
|
+
}
|
|
184
|
+
),
|
|
185
|
+
cmd.label
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
cmd.id
|
|
189
|
+
)
|
|
182
190
|
);
|
|
183
191
|
})
|
|
184
192
|
] }, group || "__default"))
|
|
@@ -62,6 +62,7 @@ const Dialog = forwardRef(
|
|
|
62
62
|
if (!visible) return null;
|
|
63
63
|
if (typeof document === "undefined") return null;
|
|
64
64
|
return createPortal(
|
|
65
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: the backdrop only handles click-outside-to-close; keyboard users close the dialog with Escape, and the backdrop itself must not be focusable.
|
|
65
66
|
/* @__PURE__ */ jsx(
|
|
66
67
|
"div",
|
|
67
68
|
{
|
|
@@ -11,15 +11,14 @@ const iconSvgProps = {
|
|
|
11
11
|
strokeWidth: 2,
|
|
12
12
|
strokeLinecap: "round",
|
|
13
13
|
strokeLinejoin: "round",
|
|
14
|
-
className: "disclosure__icon-svg"
|
|
15
|
-
"aria-hidden": true
|
|
14
|
+
className: "disclosure__icon-svg"
|
|
16
15
|
};
|
|
17
16
|
function renderIcon(icon) {
|
|
18
17
|
if (icon === "chevron" || icon == null) {
|
|
19
|
-
return /* @__PURE__ */ jsx("svg", { ...iconSvgProps, children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" }) });
|
|
18
|
+
return /* @__PURE__ */ jsx("svg", { ...iconSvgProps, "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" }) });
|
|
20
19
|
}
|
|
21
20
|
if (icon === "plus") {
|
|
22
|
-
return /* @__PURE__ */ jsxs("svg", { ...iconSvgProps, children: [
|
|
21
|
+
return /* @__PURE__ */ jsxs("svg", { ...iconSvgProps, "aria-hidden": "true", children: [
|
|
23
22
|
/* @__PURE__ */ jsx("path", { d: "M5 12h14" }),
|
|
24
23
|
/* @__PURE__ */ jsx("path", { d: "M12 5v14" })
|
|
25
24
|
] });
|
|
@@ -66,6 +65,7 @@ const Disclosure = forwardRef(
|
|
|
66
65
|
[isOpen, setOpen]
|
|
67
66
|
);
|
|
68
67
|
const contentId = useId();
|
|
68
|
+
const triggerId = useId();
|
|
69
69
|
const isBuiltInIcon = icon === "chevron" || icon === "plus";
|
|
70
70
|
const markerNode = useMemo(() => renderIcon(icon), [icon]);
|
|
71
71
|
return /* @__PURE__ */ jsxs(
|
|
@@ -85,6 +85,7 @@ const Disclosure = forwardRef(
|
|
|
85
85
|
/* @__PURE__ */ jsxs(
|
|
86
86
|
"button",
|
|
87
87
|
{
|
|
88
|
+
id: triggerId,
|
|
88
89
|
type: "button",
|
|
89
90
|
className: cn(
|
|
90
91
|
"disclosure__trigger",
|
|
@@ -122,10 +123,10 @@ const Disclosure = forwardRef(
|
|
|
122
123
|
}
|
|
123
124
|
),
|
|
124
125
|
/* @__PURE__ */ jsx(
|
|
125
|
-
"
|
|
126
|
+
"section",
|
|
126
127
|
{
|
|
127
128
|
id: contentId,
|
|
128
|
-
|
|
129
|
+
"aria-labelledby": triggerId,
|
|
129
130
|
className: cn("disclosure__content", contentClassName),
|
|
130
131
|
hidden: !isOpen,
|
|
131
132
|
children: /* @__PURE__ */ jsx("div", { className: "disclosure__content-inner", children })
|
|
@@ -66,23 +66,26 @@ const DropdownTrigger = forwardRef(
|
|
|
66
66
|
},
|
|
67
67
|
[setOpen]
|
|
68
68
|
);
|
|
69
|
-
return
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
69
|
+
return (
|
|
70
|
+
// biome-ignore lint/a11y/useSemanticElements: the trigger wraps arbitrary children (often a <Button>), and nesting a <button> inside a <button> is invalid HTML; the span gets role, tabIndex and keyboard handling instead.
|
|
71
|
+
/* @__PURE__ */ jsx(
|
|
72
|
+
"span",
|
|
73
|
+
{
|
|
74
|
+
ref: (node) => {
|
|
75
|
+
triggerRef.current = node;
|
|
76
|
+
if (typeof ref === "function") ref(node);
|
|
77
|
+
else if (ref) ref.current = node;
|
|
78
|
+
},
|
|
79
|
+
role: "button",
|
|
80
|
+
tabIndex: 0,
|
|
81
|
+
"aria-expanded": open ? "true" : "false",
|
|
82
|
+
"aria-haspopup": "menu",
|
|
83
|
+
onClick: handleClick,
|
|
84
|
+
onKeyDown: handleKeyDown,
|
|
85
|
+
style: { display: "inline-flex" },
|
|
86
|
+
children
|
|
87
|
+
}
|
|
88
|
+
)
|
|
86
89
|
);
|
|
87
90
|
}
|
|
88
91
|
);
|
|
@@ -10,18 +10,8 @@ const Icon = forwardRef(
|
|
|
10
10
|
lg: 20,
|
|
11
11
|
xl: 24
|
|
12
12
|
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
{
|
|
16
|
-
ref,
|
|
17
|
-
role: label ? "img" : void 0,
|
|
18
|
-
"aria-label": label,
|
|
19
|
-
"aria-hidden": label ? void 0 : true,
|
|
20
|
-
className: cn("icon", `icon--${size}`, className),
|
|
21
|
-
...rest,
|
|
22
|
-
children: /* @__PURE__ */ jsx(LucideComponent, { size: sizeMap[size], strokeWidth: 2 })
|
|
23
|
-
}
|
|
24
|
-
);
|
|
13
|
+
const a11yProps = label ? { role: "img", "aria-label": label } : { "aria-hidden": true };
|
|
14
|
+
return /* @__PURE__ */ jsx("span", { ref, ...a11yProps, className: cn("icon", `icon--${size}`, className), ...rest, children: /* @__PURE__ */ jsx(LucideComponent, { size: sizeMap[size], strokeWidth: 2 }) });
|
|
25
15
|
}
|
|
26
16
|
);
|
|
27
17
|
Icon.displayName = "Icon";
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
|
-
import { forwardRef, useRef, useState,
|
|
3
|
+
import { forwardRef, useRef, useState, useCallback } from "react";
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
5
|
import { CHART_COLORS } from "../../lib/chartColors.js";
|
|
6
6
|
import { niceScale, linearScale, defaultFormat } from "../../lib/chartScale.js";
|
|
7
|
+
import { useChartWidth } from "../../lib/useChartWidth.js";
|
|
7
8
|
import { ChartLegend } from "../ChartLegend/ChartLegend.js";
|
|
8
9
|
const PAD_TOP = 8;
|
|
9
10
|
const PAD_BOTTOM = 24;
|
|
@@ -101,24 +102,10 @@ const LineChart = forwardRef(
|
|
|
101
102
|
className,
|
|
102
103
|
...rest
|
|
103
104
|
}, ref) => {
|
|
104
|
-
const wrapRef =
|
|
105
|
+
const { ref: wrapRef, width, measured } = useChartWidth(INITIAL_WIDTH);
|
|
105
106
|
const svgRef = useRef(null);
|
|
106
|
-
const [width, setWidth] = useState(INITIAL_WIDTH);
|
|
107
107
|
const [hidden, setHidden] = useState([]);
|
|
108
108
|
const [active, setActive] = useState(null);
|
|
109
|
-
useEffect(() => {
|
|
110
|
-
const el = wrapRef.current;
|
|
111
|
-
if (!el) return;
|
|
112
|
-
const measure = () => {
|
|
113
|
-
const w = Math.round(el.getBoundingClientRect().width);
|
|
114
|
-
if (w > 0) setWidth(w);
|
|
115
|
-
};
|
|
116
|
-
measure();
|
|
117
|
-
if (typeof ResizeObserver === "undefined") return;
|
|
118
|
-
const ro = new ResizeObserver(measure);
|
|
119
|
-
ro.observe(el);
|
|
120
|
-
return () => ro.disconnect();
|
|
121
|
-
}, []);
|
|
122
109
|
const toggle = useCallback((key) => {
|
|
123
110
|
setHidden((h) => h.includes(key) ? h.filter((k) => k !== key) : [...h, key]);
|
|
124
111
|
}, []);
|
|
@@ -189,9 +176,10 @@ const LineChart = forwardRef(
|
|
|
189
176
|
className: "chart__svg line-chart__svg",
|
|
190
177
|
role: "img",
|
|
191
178
|
"aria-label": ariaLabel,
|
|
192
|
-
width,
|
|
179
|
+
width: measured ? width : "100%",
|
|
193
180
|
height,
|
|
194
181
|
viewBox: `0 0 ${width} ${height}`,
|
|
182
|
+
preserveAspectRatio: measured ? void 0 : "none",
|
|
195
183
|
tabIndex: 0,
|
|
196
184
|
onPointerMove: (e) => setActive(indexFromPointer(e)),
|
|
197
185
|
onPointerLeave: () => setActive(null),
|
|
@@ -127,6 +127,7 @@ const NumberField = forwardRef(
|
|
|
127
127
|
children: /* @__PURE__ */ jsx(
|
|
128
128
|
"svg",
|
|
129
129
|
{
|
|
130
|
+
"aria-hidden": "true",
|
|
130
131
|
width: "12",
|
|
131
132
|
height: "12",
|
|
132
133
|
viewBox: "0 0 12 12",
|
|
@@ -171,6 +172,7 @@ const NumberField = forwardRef(
|
|
|
171
172
|
children: /* @__PURE__ */ jsxs(
|
|
172
173
|
"svg",
|
|
173
174
|
{
|
|
175
|
+
"aria-hidden": "true",
|
|
174
176
|
width: "12",
|
|
175
177
|
height: "12",
|
|
176
178
|
viewBox: "0 0 12 12",
|
|
@@ -6,9 +6,9 @@ function getPages(current, total, siblings) {
|
|
|
6
6
|
const left = Math.max(2, current - siblings);
|
|
7
7
|
const right = Math.min(total - 1, current + siblings);
|
|
8
8
|
range.push(1);
|
|
9
|
-
if (left > 2) range.push("
|
|
9
|
+
if (left > 2) range.push("ellipsis-start");
|
|
10
10
|
for (let i = left; i <= right; i++) range.push(i);
|
|
11
|
-
if (right < total - 1) range.push("
|
|
11
|
+
if (right < total - 1) range.push("ellipsis-end");
|
|
12
12
|
if (total > 1) range.push(total);
|
|
13
13
|
return range;
|
|
14
14
|
}
|
|
@@ -38,7 +38,7 @@ const Pagination = forwardRef(
|
|
|
38
38
|
}
|
|
39
39
|
),
|
|
40
40
|
pages.map(
|
|
41
|
-
(page
|
|
41
|
+
(page) => typeof page === "string" ? /* @__PURE__ */ jsx("span", { className: "pagination__ellipsis", children: "…" }, page) : /* @__PURE__ */ jsx(
|
|
42
42
|
"button",
|
|
43
43
|
{
|
|
44
44
|
type: "button",
|
|
@@ -27,41 +27,45 @@ const Search = forwardRef(
|
|
|
27
27
|
},
|
|
28
28
|
[isControlled, onChangeProp, onSearch]
|
|
29
29
|
);
|
|
30
|
-
return
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
30
|
+
return (
|
|
31
|
+
// biome-ignore lint/a11y/useSemanticElements: the <search> element is not supported in all target browsers yet (Safari < 17); role="search" on a div exposes the same landmark.
|
|
32
|
+
/* @__PURE__ */ jsxs("div", { role: "search", className: cn("search", className), ...rest, children: [
|
|
33
|
+
/* @__PURE__ */ jsxs(
|
|
34
|
+
"svg",
|
|
35
|
+
{
|
|
36
|
+
className: "search__icon",
|
|
37
|
+
"aria-hidden": "true",
|
|
38
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
39
|
+
width: "14",
|
|
40
|
+
height: "14",
|
|
41
|
+
viewBox: "0 0 24 24",
|
|
42
|
+
fill: "none",
|
|
43
|
+
stroke: "currentColor",
|
|
44
|
+
strokeWidth: "2",
|
|
45
|
+
strokeLinecap: "round",
|
|
46
|
+
strokeLinejoin: "round",
|
|
47
|
+
children: [
|
|
48
|
+
/* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "8" }),
|
|
49
|
+
/* @__PURE__ */ jsx("path", { d: "m21 21-4.3-4.3" })
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
),
|
|
53
|
+
/* @__PURE__ */ jsx(
|
|
54
|
+
"input",
|
|
55
|
+
{
|
|
56
|
+
ref,
|
|
57
|
+
type: "text",
|
|
58
|
+
className: "search__input",
|
|
59
|
+
placeholder,
|
|
60
|
+
"aria-label": ariaLabel ?? placeholder,
|
|
61
|
+
value: currentValue,
|
|
62
|
+
onChange: handleChange
|
|
63
|
+
}
|
|
64
|
+
),
|
|
65
|
+
shortcut && // biome-ignore lint/a11y/noAriaHiddenOnFocusable: <kbd> has no tabIndex and is not focusable; the shortcut hint is visual only.
|
|
66
|
+
/* @__PURE__ */ jsx("kbd", { className: "search__kbd", "aria-hidden": "true", children: shortcut })
|
|
67
|
+
] })
|
|
68
|
+
);
|
|
65
69
|
}
|
|
66
70
|
);
|
|
67
71
|
Search.displayName = "Search";
|
|
@@ -38,7 +38,10 @@ const SidebarGroupLabel = forwardRef(
|
|
|
38
38
|
SidebarGroupLabel.displayName = "SidebarGroupLabel";
|
|
39
39
|
const SidebarDivider = forwardRef(
|
|
40
40
|
({ className, ...rest }, ref) => {
|
|
41
|
-
return
|
|
41
|
+
return (
|
|
42
|
+
// biome-ignore lint/a11y/useSemanticElements: the forwarded ref and props are typed as HTMLDivElement (public API); switching to <hr> would change the exported types.
|
|
43
|
+
/* @__PURE__ */ jsx("div", { ref, className: cn("sidebar__divider", className), role: "separator", ...rest })
|
|
44
|
+
);
|
|
42
45
|
}
|
|
43
46
|
);
|
|
44
47
|
SidebarDivider.displayName = "SidebarDivider";
|
|
@@ -20,28 +20,31 @@ const Stepper = forwardRef(
|
|
|
20
20
|
({ steps, currentStep, className, ...rest }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("stepper", className), ...rest, children: steps.map((step, i) => {
|
|
21
21
|
const isCompleted = i < currentStep;
|
|
22
22
|
const isActive = i === currentStep;
|
|
23
|
-
return
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
return (
|
|
24
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: steps are ordinal (the index is rendered as the step number) and labels are not guaranteed unique.
|
|
25
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "contents" }, children: [
|
|
26
|
+
/* @__PURE__ */ jsxs("div", { className: cn("stepper__step", isActive && "stepper__step--active"), children: [
|
|
27
|
+
/* @__PURE__ */ jsx(
|
|
28
|
+
"span",
|
|
29
|
+
{
|
|
30
|
+
className: cn(
|
|
31
|
+
"stepper__circle",
|
|
32
|
+
isActive && "stepper__circle--active",
|
|
33
|
+
isCompleted && "stepper__circle--completed"
|
|
34
|
+
),
|
|
35
|
+
children: isCompleted ? /* @__PURE__ */ jsx(CheckIcon, {}) : i + 1
|
|
36
|
+
}
|
|
37
|
+
),
|
|
38
|
+
/* @__PURE__ */ jsx("span", { className: "stepper__label", children: step.label })
|
|
39
|
+
] }),
|
|
40
|
+
i < steps.length - 1 && /* @__PURE__ */ jsx(
|
|
26
41
|
"span",
|
|
27
42
|
{
|
|
28
|
-
className: cn(
|
|
29
|
-
"stepper__circle",
|
|
30
|
-
isActive && "stepper__circle--active",
|
|
31
|
-
isCompleted && "stepper__circle--completed"
|
|
32
|
-
),
|
|
33
|
-
children: isCompleted ? /* @__PURE__ */ jsx(CheckIcon, {}) : i + 1
|
|
43
|
+
className: cn("stepper__connector", isCompleted && "stepper__connector--completed")
|
|
34
44
|
}
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
i < steps.length - 1 && /* @__PURE__ */ jsx(
|
|
39
|
-
"span",
|
|
40
|
-
{
|
|
41
|
-
className: cn("stepper__connector", isCompleted && "stepper__connector--completed")
|
|
42
|
-
}
|
|
43
|
-
)
|
|
44
|
-
] }, i);
|
|
45
|
+
)
|
|
46
|
+
] }, i)
|
|
47
|
+
);
|
|
45
48
|
}) })
|
|
46
49
|
);
|
|
47
50
|
Stepper.displayName = "Stepper";
|
|
@@ -3,16 +3,7 @@ import { forwardRef } from "react";
|
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
4
|
const Table = forwardRef(
|
|
5
5
|
({ compact, className, children, ...rest }, ref) => {
|
|
6
|
-
return /* @__PURE__ */ jsx("div", { className: "table-wrapper", children: /* @__PURE__ */ jsx(
|
|
7
|
-
"table",
|
|
8
|
-
{
|
|
9
|
-
ref,
|
|
10
|
-
role: "table",
|
|
11
|
-
className: cn("table", compact && "table--compact", className),
|
|
12
|
-
...rest,
|
|
13
|
-
children
|
|
14
|
-
}
|
|
15
|
-
) });
|
|
6
|
+
return /* @__PURE__ */ jsx("div", { className: "table-wrapper", children: /* @__PURE__ */ jsx("table", { ref, className: cn("table", compact && "table--compact", className), ...rest, children }) });
|
|
16
7
|
}
|
|
17
8
|
);
|
|
18
9
|
Table.displayName = "Table";
|
|
@@ -37,6 +37,7 @@ function ToastItem(props) {
|
|
|
37
37
|
data.variant === "positive" && /* @__PURE__ */ jsx(
|
|
38
38
|
"svg",
|
|
39
39
|
{
|
|
40
|
+
"aria-hidden": "true",
|
|
40
41
|
xmlns: "http://www.w3.org/2000/svg",
|
|
41
42
|
width: "16",
|
|
42
43
|
height: "16",
|
|
@@ -52,6 +53,7 @@ function ToastItem(props) {
|
|
|
52
53
|
data.variant === "negative" && /* @__PURE__ */ jsxs(
|
|
53
54
|
"svg",
|
|
54
55
|
{
|
|
56
|
+
"aria-hidden": "true",
|
|
55
57
|
xmlns: "http://www.w3.org/2000/svg",
|
|
56
58
|
width: "16",
|
|
57
59
|
height: "16",
|
|
@@ -71,6 +73,7 @@ function ToastItem(props) {
|
|
|
71
73
|
data.variant === "warning" && /* @__PURE__ */ jsxs(
|
|
72
74
|
"svg",
|
|
73
75
|
{
|
|
76
|
+
"aria-hidden": "true",
|
|
74
77
|
xmlns: "http://www.w3.org/2000/svg",
|
|
75
78
|
width: "16",
|
|
76
79
|
height: "16",
|
|
@@ -90,6 +93,7 @@ function ToastItem(props) {
|
|
|
90
93
|
data.variant === "info" && /* @__PURE__ */ jsxs(
|
|
91
94
|
"svg",
|
|
92
95
|
{
|
|
96
|
+
"aria-hidden": "true",
|
|
93
97
|
xmlns: "http://www.w3.org/2000/svg",
|
|
94
98
|
width: "16",
|
|
95
99
|
height: "16",
|
|
@@ -114,6 +118,7 @@ function ToastItem(props) {
|
|
|
114
118
|
/* @__PURE__ */ jsx("button", { type: "button", className: "toast__close", onClick: dismiss, "aria-label": closeLabel, children: /* @__PURE__ */ jsxs(
|
|
115
119
|
"svg",
|
|
116
120
|
{
|
|
121
|
+
"aria-hidden": "true",
|
|
117
122
|
xmlns: "http://www.w3.org/2000/svg",
|
|
118
123
|
width: "14",
|
|
119
124
|
height: "14",
|
|
@@ -155,7 +160,7 @@ function ToastProvider({
|
|
|
155
160
|
return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: { toast }, children: [
|
|
156
161
|
children,
|
|
157
162
|
typeof document !== "undefined" && createPortal(
|
|
158
|
-
/* @__PURE__ */ jsx("
|
|
163
|
+
/* @__PURE__ */ jsx("section", { className: "toast-container", "aria-label": containerLabel, "aria-live": "polite", children: toasts.map((t) => /* @__PURE__ */ jsx(ToastItem, { data: t, onRemove: removeToast, closeLabel }, t.id)) }),
|
|
159
164
|
document.body
|
|
160
165
|
)
|
|
161
166
|
] });
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useRef, useState, useLayoutEffect, useEffect } from "react";
|
|
3
|
+
const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
|
|
4
|
+
function useChartWidth(fallback) {
|
|
5
|
+
const ref = useRef(null);
|
|
6
|
+
const [width, setWidth] = useState(fallback);
|
|
7
|
+
const [measured, setMeasured] = useState(false);
|
|
8
|
+
useIsomorphicLayoutEffect(() => {
|
|
9
|
+
const el = ref.current;
|
|
10
|
+
if (!el) return;
|
|
11
|
+
const measure = () => {
|
|
12
|
+
const w = Math.round(el.getBoundingClientRect().width);
|
|
13
|
+
if (w > 0) {
|
|
14
|
+
setWidth(w);
|
|
15
|
+
setMeasured(true);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
measure();
|
|
19
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
20
|
+
const ro = new ResizeObserver(measure);
|
|
21
|
+
ro.observe(el);
|
|
22
|
+
return () => ro.disconnect();
|
|
23
|
+
}, []);
|
|
24
|
+
return { ref, width, measured };
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
useChartWidth
|
|
28
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
2
|
+
export interface ChartWidth<T extends HTMLElement> {
|
|
3
|
+
ref: RefObject<T | null>;
|
|
4
|
+
/** Measured width in px, or `fallback` until the first measurement */
|
|
5
|
+
width: number;
|
|
6
|
+
/**
|
|
7
|
+
* False until the container has been measured (SSR HTML and the first client
|
|
8
|
+
* paint before layout). Charts should stretch the SVG to 100% while false so
|
|
9
|
+
* server-rendered output fits the container instead of jumping on hydration.
|
|
10
|
+
*/
|
|
11
|
+
measured: boolean;
|
|
12
|
+
}
|
|
13
|
+
/** Track a container's width for SVG charts: measured before paint, then via ResizeObserver. */
|
|
14
|
+
export declare function useChartWidth<T extends HTMLElement>(fallback: number): ChartWidth<T>;
|