kaze-design-system 0.9.0 → 0.10.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/CHANGELOG.md +19 -0
- package/components.css +2 -1
- package/dist/components/Alert/Alert.js +21 -7
- package/dist/components/Badge/Badge.js +5 -2
- package/dist/components/Button/Button.js +12 -3
- package/dist/components/CommandPalette/CommandPalette.js +1 -0
- package/dist/components/Dialog/Dialog.js +35 -15
- package/dist/components/Disclosure/Disclosure.js +2 -0
- package/dist/components/Dropdown/Dropdown.js +2 -0
- package/dist/components/FAB/FAB.js +17 -5
- package/dist/components/FilterPill/FilterPill.js +1 -0
- package/dist/components/HelpButton/HelpButton.js +2 -0
- package/dist/components/List/List.js +22 -18
- package/dist/components/Meter/Meter.js +5 -6
- package/dist/components/Navbar/Navbar.js +4 -1
- package/dist/components/NumberField/NumberField.js +11 -2
- package/dist/components/Pagination/Pagination.js +22 -5
- package/dist/components/Progress/Progress.js +5 -3
- package/dist/components/Search/Search.js +13 -3
- package/dist/components/SegmentedControl/SegmentedControl.js +1 -0
- package/dist/components/Sidebar/Sidebar.js +7 -6
- package/dist/components/StatusBadge/StatusBadge.js +6 -6
- package/dist/components/Stepper/Stepper.js +40 -36
- package/dist/components/Tabs/Tabs.js +46 -11
- package/dist/components/Timeline/Timeline.js +15 -14
- package/dist/components/Toast/Toast.js +12 -8
- package/dist/components/Tooltip/Tooltip.js +25 -6
- package/dist/components/Tracker/Tracker.js +18 -10
- package/dist/index.js +2 -0
- package/dist/lib/Slot.js +52 -0
- package/dist/lib/deprecate.js +26 -0
- package/dist/types/components/Alert/Alert.d.ts +6 -2
- package/dist/types/components/Avatar/Avatar.d.ts +2 -1
- package/dist/types/components/Badge/Badge.d.ts +6 -2
- package/dist/types/components/Button/Button.d.ts +4 -1
- package/dist/types/components/Dialog/Dialog.d.ts +4 -1
- package/dist/types/components/Disclosure/Disclosure.d.ts +2 -1
- package/dist/types/components/EmptyState/EmptyState.d.ts +2 -1
- package/dist/types/components/FAB/FAB.d.ts +4 -1
- package/dist/types/components/HelpButton/HelpButton.d.ts +2 -1
- package/dist/types/components/Icon/Icon.d.ts +2 -1
- package/dist/types/components/List/List.d.ts +2 -0
- package/dist/types/components/Logo/Logo.d.ts +3 -1
- package/dist/types/components/Logo/index.d.ts +1 -1
- package/dist/types/components/Meter/Meter.d.ts +9 -4
- package/dist/types/components/Meter/index.d.ts +1 -1
- package/dist/types/components/Navbar/Navbar.d.ts +2 -0
- package/dist/types/components/NumberField/NumberField.d.ts +3 -1
- package/dist/types/components/Pagination/Pagination.d.ts +6 -1
- package/dist/types/components/Progress/Progress.d.ts +7 -3
- package/dist/types/components/Search/Search.d.ts +5 -1
- package/dist/types/components/Section/Section.d.ts +2 -1
- package/dist/types/components/SegmentedControl/SegmentedControl.d.ts +2 -1
- package/dist/types/components/Sidebar/Sidebar.d.ts +2 -0
- package/dist/types/components/StatusBadge/StatusBadge.d.ts +1 -1
- package/dist/types/components/Stepper/Stepper.d.ts +4 -1
- package/dist/types/components/Tabs/Tabs.d.ts +18 -7
- package/dist/types/components/Timeline/Timeline.d.ts +6 -2
- package/dist/types/components/Toast/Toast.d.ts +9 -3
- package/dist/types/components/Tooltip/Tooltip.d.ts +5 -0
- package/dist/types/components/Tracker/Tracker.d.ts +7 -3
- package/dist/types/components/index.d.ts +5 -2
- package/dist/types/lib/Slot.d.ts +16 -0
- package/dist/types/lib/deprecate.d.ts +8 -0
- package/dist/types/lib/types.d.ts +4 -0
- package/package.json +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { jsxs,
|
|
1
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
|
+
import { Slot } from "../../lib/Slot.js";
|
|
4
5
|
const Sidebar = forwardRef(
|
|
5
6
|
({ children, logo, footer, navLabel = "メインナビゲーション", className, ...rest }, ref) => {
|
|
6
7
|
return /* @__PURE__ */ jsxs("aside", { ref, className: cn("sidebar", className), ...rest, children: [
|
|
@@ -12,10 +13,10 @@ const Sidebar = forwardRef(
|
|
|
12
13
|
);
|
|
13
14
|
Sidebar.displayName = "Sidebar";
|
|
14
15
|
const NavItem = forwardRef(
|
|
15
|
-
({ icon, active, as: asProp, href, className, children, ...rest }, ref) => {
|
|
16
|
-
const Component = asProp ?? (href ? "a" : "button");
|
|
16
|
+
({ icon, active, as: asProp, href, asChild, className, children, ...rest }, ref) => {
|
|
17
|
+
const Component = asChild ? Slot : asProp ?? (href ? "a" : "button");
|
|
17
18
|
const typeAttr = Component === "button" ? { type: "button" } : {};
|
|
18
|
-
return /* @__PURE__ */
|
|
19
|
+
return /* @__PURE__ */ jsx(
|
|
19
20
|
Component,
|
|
20
21
|
{
|
|
21
22
|
ref,
|
|
@@ -24,10 +25,10 @@ const NavItem = forwardRef(
|
|
|
24
25
|
href,
|
|
25
26
|
...typeAttr,
|
|
26
27
|
...rest,
|
|
27
|
-
children: [
|
|
28
|
+
children: asChild ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
28
29
|
icon && /* @__PURE__ */ jsx("span", { className: "nav-item__icon", children: icon }),
|
|
29
30
|
children
|
|
30
|
-
]
|
|
31
|
+
] })
|
|
31
32
|
}
|
|
32
33
|
);
|
|
33
34
|
}
|
|
@@ -2,17 +2,17 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import { Badge } from "../Badge/Badge.js";
|
|
4
4
|
const STATUS_CONFIG = {
|
|
5
|
-
live: {
|
|
6
|
-
stale: {
|
|
7
|
-
missing: {
|
|
8
|
-
manual: {
|
|
9
|
-
loading: {
|
|
5
|
+
live: { tone: "positive", label: "自動更新" },
|
|
6
|
+
stale: { tone: "warning", label: "要更新" },
|
|
7
|
+
missing: { tone: "negative", label: "欠損" },
|
|
8
|
+
manual: { tone: "default", label: "手動" },
|
|
9
|
+
loading: { tone: "info", label: "取得中" }
|
|
10
10
|
};
|
|
11
11
|
const StatusBadge = forwardRef(
|
|
12
12
|
({ status, label, dot = true, live, ...rest }, ref) => {
|
|
13
13
|
const config = STATUS_CONFIG[status];
|
|
14
14
|
const isLive = live ?? (status === "live" || status === "loading");
|
|
15
|
-
return /* @__PURE__ */ jsx(Badge, { ref,
|
|
15
|
+
return /* @__PURE__ */ jsx(Badge, { ref, tone: config.tone, dot, live: isLive, ...rest, children: label ?? config.label });
|
|
16
16
|
}
|
|
17
17
|
);
|
|
18
18
|
StatusBadge.displayName = "StatusBadge";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
|
+
import { renamedProp } from "../../lib/deprecate.js";
|
|
4
5
|
const CheckIcon = () => /* @__PURE__ */ jsx(
|
|
5
6
|
"svg",
|
|
6
7
|
{
|
|
@@ -17,46 +18,49 @@ const CheckIcon = () => /* @__PURE__ */ jsx(
|
|
|
17
18
|
}
|
|
18
19
|
);
|
|
19
20
|
const Stepper = forwardRef(
|
|
20
|
-
({ steps,
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
({ steps, step: stepProp, currentStep: currentStepProp, className, ...rest }, ref) => {
|
|
22
|
+
const currentStep = renamedProp("Stepper", "currentStep", "step", currentStepProp, stepProp) ?? 0;
|
|
23
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn("stepper", className), ...rest, children: /* @__PURE__ */ jsx("ol", { className: "stepper__list", children: steps.map((step, i) => {
|
|
24
|
+
const isCompleted = i < currentStep;
|
|
25
|
+
const isActive = i === currentStep;
|
|
26
|
+
return /* @__PURE__ */ jsxs(
|
|
27
|
+
"li",
|
|
28
|
+
{
|
|
29
|
+
className: "stepper__item",
|
|
30
|
+
"aria-current": isActive ? "step" : void 0,
|
|
31
|
+
children: [
|
|
32
|
+
/* @__PURE__ */ jsxs("div", { className: cn("stepper__step", isActive && "stepper__step--active"), children: [
|
|
33
|
+
/* @__PURE__ */ jsx(
|
|
34
|
+
"span",
|
|
35
|
+
{
|
|
36
|
+
className: cn(
|
|
37
|
+
"stepper__circle",
|
|
38
|
+
isActive && "stepper__circle--active",
|
|
39
|
+
isCompleted && "stepper__circle--completed"
|
|
40
|
+
),
|
|
41
|
+
children: isCompleted ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
42
|
+
/* @__PURE__ */ jsx(CheckIcon, {}),
|
|
43
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "完了" })
|
|
44
|
+
] }) : i + 1
|
|
45
|
+
}
|
|
46
|
+
),
|
|
47
|
+
/* @__PURE__ */ jsx("span", { className: "stepper__label", children: step.label })
|
|
48
|
+
] }),
|
|
49
|
+
i < steps.length - 1 && /* @__PURE__ */ jsx(
|
|
31
50
|
"span",
|
|
32
51
|
{
|
|
33
52
|
className: cn(
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
),
|
|
38
|
-
children: isCompleted ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
39
|
-
/* @__PURE__ */ jsx(CheckIcon, {}),
|
|
40
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "完了" })
|
|
41
|
-
] }) : i + 1
|
|
53
|
+
"stepper__connector",
|
|
54
|
+
isCompleted && "stepper__connector--completed"
|
|
55
|
+
)
|
|
42
56
|
}
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"stepper__connector",
|
|
51
|
-
isCompleted && "stepper__connector--completed"
|
|
52
|
-
)
|
|
53
|
-
}
|
|
54
|
-
)
|
|
55
|
-
]
|
|
56
|
-
},
|
|
57
|
-
i
|
|
58
|
-
);
|
|
59
|
-
}) }) })
|
|
57
|
+
)
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
i
|
|
61
|
+
);
|
|
62
|
+
}) }) });
|
|
63
|
+
}
|
|
60
64
|
);
|
|
61
65
|
Stepper.displayName = "Stepper";
|
|
62
66
|
export {
|
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { forwardRef, useContext, useId, useRef, useEffect,
|
|
3
|
+
import { forwardRef, useContext, useId, useState, useCallback, useMemo, useRef, useEffect, createContext } from "react";
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
5
|
import { composeEventHandlers } from "../../lib/composeEventHandlers.js";
|
|
6
|
-
|
|
6
|
+
import { warnDeprecated } from "../../lib/deprecate.js";
|
|
7
|
+
import { Slot } from "../../lib/Slot.js";
|
|
8
|
+
const TabsContext = createContext(void 0);
|
|
7
9
|
const TabGroup = forwardRef(
|
|
8
|
-
({ children, className, ...rest }, ref) => {
|
|
10
|
+
({ value: valueProp, defaultValue, onValueChange, children, className, ...rest }, ref) => {
|
|
9
11
|
const prefix = useId();
|
|
10
|
-
|
|
12
|
+
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
13
|
+
const isControlled = valueProp !== void 0;
|
|
14
|
+
const value = isControlled ? valueProp : internalValue;
|
|
15
|
+
const select = useCallback(
|
|
16
|
+
(next) => {
|
|
17
|
+
if (!isControlled) setInternalValue(next);
|
|
18
|
+
onValueChange?.(next);
|
|
19
|
+
},
|
|
20
|
+
[isControlled, onValueChange]
|
|
21
|
+
);
|
|
22
|
+
const context = useMemo(() => ({ prefix, value, select }), [prefix, value, select]);
|
|
23
|
+
return /* @__PURE__ */ jsx(TabsContext.Provider, { value: context, children: /* @__PURE__ */ jsx("div", { ref, className, ...rest, children }) });
|
|
11
24
|
}
|
|
12
25
|
);
|
|
13
26
|
TabGroup.displayName = "TabGroup";
|
|
@@ -80,25 +93,39 @@ const Tabs = forwardRef(
|
|
|
80
93
|
);
|
|
81
94
|
Tabs.displayName = "Tabs";
|
|
82
95
|
const Tab = forwardRef(
|
|
83
|
-
({ active, id, value, className, children, ...rest }, ref) => {
|
|
84
|
-
const
|
|
96
|
+
({ active: activeProp, id, value, asChild, className, children, onClick, ...rest }, ref) => {
|
|
97
|
+
const context = useContext(TabsContext);
|
|
85
98
|
const fallbackPrefix = useId();
|
|
86
|
-
const prefix =
|
|
99
|
+
const prefix = context?.prefix ?? fallbackPrefix;
|
|
100
|
+
if (activeProp !== void 0) {
|
|
101
|
+
warnDeprecated(
|
|
102
|
+
"Tab.active",
|
|
103
|
+
"Tab の `active` は `TabGroup` の `value` / `defaultValue` に置き換わりました。次のマイナーバージョンで削除します"
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
const active = context?.value !== void 0 ? value !== void 0 && value === context.value : activeProp;
|
|
87
107
|
const tabId = id ?? (value ? `${prefix}-tab-${value}` : void 0);
|
|
88
108
|
const panelId = value ? `${prefix}-panel-${value}` : void 0;
|
|
89
109
|
const text = typeof children === "string" ? children : void 0;
|
|
110
|
+
const handleClick = () => {
|
|
111
|
+
if (value !== void 0) context?.select(value);
|
|
112
|
+
};
|
|
113
|
+
const Comp = asChild ? Slot : "button";
|
|
90
114
|
return /* @__PURE__ */ jsx(
|
|
91
|
-
|
|
115
|
+
Comp,
|
|
92
116
|
{
|
|
93
117
|
ref,
|
|
94
118
|
id: tabId,
|
|
95
119
|
role: "tab",
|
|
120
|
+
type: asChild ? void 0 : "button",
|
|
96
121
|
"aria-selected": active,
|
|
97
122
|
"aria-controls": panelId,
|
|
98
123
|
tabIndex: active ? 0 : -1,
|
|
99
124
|
className: cn("tab", active && "tab--active", className),
|
|
125
|
+
"data-state": active ? "active" : "inactive",
|
|
100
126
|
"data-text": text,
|
|
101
127
|
...rest,
|
|
128
|
+
onClick: composeEventHandlers(onClick, handleClick),
|
|
102
129
|
children
|
|
103
130
|
}
|
|
104
131
|
);
|
|
@@ -106,12 +133,19 @@ const Tab = forwardRef(
|
|
|
106
133
|
);
|
|
107
134
|
Tab.displayName = "Tab";
|
|
108
135
|
const TabPanel = forwardRef(
|
|
109
|
-
({ value, selected, children, className, ...rest }, ref) => {
|
|
110
|
-
const
|
|
136
|
+
({ value, selected: selectedProp, children, className, ...rest }, ref) => {
|
|
137
|
+
const context = useContext(TabsContext);
|
|
111
138
|
const fallbackPrefix = useId();
|
|
112
|
-
const prefix =
|
|
139
|
+
const prefix = context?.prefix ?? fallbackPrefix;
|
|
113
140
|
const panelId = `${prefix}-panel-${value}`;
|
|
114
141
|
const tabId = `${prefix}-tab-${value}`;
|
|
142
|
+
if (selectedProp !== void 0) {
|
|
143
|
+
warnDeprecated(
|
|
144
|
+
"TabPanel.selected",
|
|
145
|
+
"TabPanel の `selected` は `TabGroup` の `value` / `defaultValue` に置き換わりました。次のマイナーバージョンで削除します"
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
const selected = context?.value !== void 0 ? context.value : selectedProp;
|
|
115
149
|
if (value !== selected) return null;
|
|
116
150
|
return /* @__PURE__ */ jsx(
|
|
117
151
|
"div",
|
|
@@ -122,6 +156,7 @@ const TabPanel = forwardRef(
|
|
|
122
156
|
tabIndex: 0,
|
|
123
157
|
"aria-labelledby": tabId,
|
|
124
158
|
className: cn("tab-panel", className),
|
|
159
|
+
"data-state": "active",
|
|
125
160
|
...rest,
|
|
126
161
|
children
|
|
127
162
|
}
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
|
+
import { renamedProp } from "../../lib/deprecate.js";
|
|
3
4
|
import { cn } from "../../lib/utils.js";
|
|
4
5
|
const Timeline = forwardRef(
|
|
5
6
|
({ className, children, ...rest }, ref) => /* @__PURE__ */ jsx("ul", { ref, className: cn("timeline", className), ...rest, children })
|
|
6
7
|
);
|
|
7
8
|
Timeline.displayName = "Timeline";
|
|
8
9
|
const TimelineItem = forwardRef(
|
|
9
|
-
({ time, title, description,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
({ time, title, description, tone: toneProp, status, className, ...rest }, ref) => {
|
|
11
|
+
const tone = renamedProp("TimelineItem", "status", "tone", status, toneProp) ?? "default";
|
|
12
|
+
return /* @__PURE__ */ jsxs("li", { ref, "data-tone": tone, className: cn("timeline-item", className), ...rest, children: [
|
|
13
|
+
/* @__PURE__ */ jsx(
|
|
14
|
+
"span",
|
|
15
|
+
{
|
|
16
|
+
className: cn("timeline-item__dot", tone !== "default" && `timeline-item__dot--${tone}`)
|
|
17
|
+
}
|
|
18
|
+
),
|
|
19
|
+
time && /* @__PURE__ */ jsx("span", { className: "timeline-item__time", children: time }),
|
|
20
|
+
/* @__PURE__ */ jsx("span", { className: "timeline-item__title", children: title }),
|
|
21
|
+
description && /* @__PURE__ */ jsx("span", { className: "timeline-item__description", children: description })
|
|
22
|
+
] });
|
|
23
|
+
}
|
|
23
24
|
);
|
|
24
25
|
TimelineItem.displayName = "TimelineItem";
|
|
25
26
|
export {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useRef, useCallback, useMemo, useContext, createContext, forwardRef, useEffect } from "react";
|
|
4
4
|
import { createPortal } from "react-dom";
|
|
5
|
+
import { renamedProp } from "../../lib/deprecate.js";
|
|
5
6
|
import { cn } from "../../lib/utils.js";
|
|
6
7
|
const ToastContext = createContext(null);
|
|
7
8
|
function useToast() {
|
|
@@ -60,7 +61,8 @@ const ToastItem = forwardRef(function ToastItem2(props, ref) {
|
|
|
60
61
|
else focusRef.current = false;
|
|
61
62
|
if (!hoverRef.current && !focusRef.current && !removing) startTimer();
|
|
62
63
|
};
|
|
63
|
-
const
|
|
64
|
+
const tone = data.tone ?? data.variant ?? "default";
|
|
65
|
+
const variantClass = tone !== "default" ? `toast--${tone}` : void 0;
|
|
64
66
|
return (
|
|
65
67
|
// biome-ignore lint/a11y/noStaticElementInteractions: hover/focus handlers only pause the auto-dismiss timer (WCAG 2.2.1); the element is a live region, not a control.
|
|
66
68
|
/* @__PURE__ */ jsxs(
|
|
@@ -68,8 +70,10 @@ const ToastItem = forwardRef(function ToastItem2(props, ref) {
|
|
|
68
70
|
{
|
|
69
71
|
ref,
|
|
70
72
|
className: cn("toast", variantClass),
|
|
71
|
-
role:
|
|
73
|
+
role: tone === "negative" || tone === "warning" ? "alert" : "status",
|
|
72
74
|
"aria-atomic": "true",
|
|
75
|
+
"data-tone": tone,
|
|
76
|
+
"data-state": removing ? "closing" : "open",
|
|
73
77
|
"data-removing": removing || void 0,
|
|
74
78
|
onMouseEnter: () => pause("hover"),
|
|
75
79
|
onMouseLeave: () => resume("hover"),
|
|
@@ -78,8 +82,8 @@ const ToastItem = forwardRef(function ToastItem2(props, ref) {
|
|
|
78
82
|
if (!e.currentTarget.contains(e.relatedTarget)) resume("focus");
|
|
79
83
|
},
|
|
80
84
|
children: [
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
tone !== "default" && /* @__PURE__ */ jsxs("span", { className: "toast__icon", "aria-hidden": "true", children: [
|
|
86
|
+
tone === "positive" && /* @__PURE__ */ jsx(
|
|
83
87
|
"svg",
|
|
84
88
|
{
|
|
85
89
|
"aria-hidden": "true",
|
|
@@ -95,7 +99,7 @@ const ToastItem = forwardRef(function ToastItem2(props, ref) {
|
|
|
95
99
|
children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
|
|
96
100
|
}
|
|
97
101
|
),
|
|
98
|
-
|
|
102
|
+
tone === "negative" && /* @__PURE__ */ jsxs(
|
|
99
103
|
"svg",
|
|
100
104
|
{
|
|
101
105
|
"aria-hidden": "true",
|
|
@@ -115,7 +119,7 @@ const ToastItem = forwardRef(function ToastItem2(props, ref) {
|
|
|
115
119
|
]
|
|
116
120
|
}
|
|
117
121
|
),
|
|
118
|
-
|
|
122
|
+
tone === "warning" && /* @__PURE__ */ jsxs(
|
|
119
123
|
"svg",
|
|
120
124
|
{
|
|
121
125
|
"aria-hidden": "true",
|
|
@@ -135,7 +139,7 @@ const ToastItem = forwardRef(function ToastItem2(props, ref) {
|
|
|
135
139
|
]
|
|
136
140
|
}
|
|
137
141
|
),
|
|
138
|
-
|
|
142
|
+
tone === "info" && /* @__PURE__ */ jsxs(
|
|
139
143
|
"svg",
|
|
140
144
|
{
|
|
141
145
|
"aria-hidden": "true",
|
|
@@ -206,7 +210,7 @@ function ToastProvider({
|
|
|
206
210
|
id,
|
|
207
211
|
title: options.title,
|
|
208
212
|
description: options.description,
|
|
209
|
-
|
|
213
|
+
tone: renamedProp("Toast", "variant", "tone", options.variant, options.tone) ?? "default",
|
|
210
214
|
duration: options.duration ?? 4e3
|
|
211
215
|
};
|
|
212
216
|
setToasts((prev) => [...prev, newToast]);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
3
|
-
import { forwardRef, useState, useRef, useId,
|
|
3
|
+
import { forwardRef, useState, useCallback, useRef, useId, useEffect, useLayoutEffect, cloneElement, version } from "react";
|
|
4
4
|
import { createPortal } from "react-dom";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
6
|
const GAP = 8;
|
|
@@ -57,8 +57,27 @@ function getChildRef(child) {
|
|
|
57
57
|
return child.ref;
|
|
58
58
|
}
|
|
59
59
|
const Tooltip = forwardRef(
|
|
60
|
-
({
|
|
61
|
-
|
|
60
|
+
({
|
|
61
|
+
content,
|
|
62
|
+
children,
|
|
63
|
+
open: openProp,
|
|
64
|
+
defaultOpen = false,
|
|
65
|
+
onOpenChange,
|
|
66
|
+
side = "top",
|
|
67
|
+
delay = 200,
|
|
68
|
+
className,
|
|
69
|
+
style
|
|
70
|
+
}, ref) => {
|
|
71
|
+
const [internalOpen, setInternalOpen] = useState(defaultOpen);
|
|
72
|
+
const isControlled = openProp !== void 0;
|
|
73
|
+
const open = isControlled ? openProp : internalOpen;
|
|
74
|
+
const setOpen = useCallback(
|
|
75
|
+
(next) => {
|
|
76
|
+
if (!isControlled) setInternalOpen(next);
|
|
77
|
+
onOpenChange?.(next);
|
|
78
|
+
},
|
|
79
|
+
[isControlled, onOpenChange]
|
|
80
|
+
);
|
|
62
81
|
const [mounted, setMounted] = useState(false);
|
|
63
82
|
const [position, setPosition] = useState({ top: 0, left: 0 });
|
|
64
83
|
const triggerRef = useRef(null);
|
|
@@ -99,11 +118,11 @@ const Tooltip = forwardRef(
|
|
|
99
118
|
const show = useCallback(() => {
|
|
100
119
|
clearTimers();
|
|
101
120
|
showTimerRef.current = setTimeout(() => setOpen(true), delay);
|
|
102
|
-
}, [delay, clearTimers]);
|
|
121
|
+
}, [delay, clearTimers, setOpen]);
|
|
103
122
|
const hide = useCallback(() => {
|
|
104
123
|
clearTimers();
|
|
105
124
|
hideTimerRef.current = setTimeout(() => setOpen(false), HIDE_GRACE_MS);
|
|
106
|
-
}, [clearTimers]);
|
|
125
|
+
}, [clearTimers, setOpen]);
|
|
107
126
|
const keepOpen = useCallback(() => {
|
|
108
127
|
if (hideTimerRef.current) clearTimeout(hideTimerRef.current);
|
|
109
128
|
hideTimerRef.current = null;
|
|
@@ -118,7 +137,7 @@ const Tooltip = forwardRef(
|
|
|
118
137
|
};
|
|
119
138
|
document.addEventListener("keydown", onKeyDown);
|
|
120
139
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
121
|
-
}, [open, clearTimers]);
|
|
140
|
+
}, [open, clearTimers, setOpen]);
|
|
122
141
|
const childProps = children.props;
|
|
123
142
|
const childRef = getChildRef(children);
|
|
124
143
|
const describedBy = [childProps["aria-describedby"], tooltipId].filter(Boolean).join(" ");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
|
+
import { renamedProp } from "../../lib/deprecate.js";
|
|
3
4
|
import { cn } from "../../lib/utils.js";
|
|
4
5
|
const STATUS_LABELS = {
|
|
5
6
|
positive: "正常",
|
|
@@ -8,8 +9,11 @@ const STATUS_LABELS = {
|
|
|
8
9
|
info: "情報",
|
|
9
10
|
default: "データなし"
|
|
10
11
|
};
|
|
12
|
+
function resolveTone(item) {
|
|
13
|
+
return renamedProp("Tracker", "status", "tone", item.status, item.tone) ?? "default";
|
|
14
|
+
}
|
|
11
15
|
function segmentText(item) {
|
|
12
|
-
const status = STATUS_LABELS[item
|
|
16
|
+
const status = STATUS_LABELS[resolveTone(item)];
|
|
13
17
|
if (!item.tooltip || item.tooltip === status) return status;
|
|
14
18
|
return `${item.tooltip}(${status})`;
|
|
15
19
|
}
|
|
@@ -25,15 +29,19 @@ const Tracker = forwardRef(
|
|
|
25
29
|
role: "figure",
|
|
26
30
|
"aria-label": label ?? `${data.length}区間`,
|
|
27
31
|
...rest,
|
|
28
|
-
children: /* @__PURE__ */ jsx("ol", { className: "tracker__list", children: data.map((item, i) =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
children: /* @__PURE__ */ jsx("ol", { className: "tracker__list", children: data.map((item, i) => {
|
|
33
|
+
const tone = resolveTone(item);
|
|
34
|
+
return /* @__PURE__ */ jsx(
|
|
35
|
+
"li",
|
|
36
|
+
{
|
|
37
|
+
"data-tone": tone,
|
|
38
|
+
className: cn("tracker__segment", `tracker__segment--${tone}`),
|
|
39
|
+
title: item.tooltip,
|
|
40
|
+
children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: segmentText(item) })
|
|
41
|
+
},
|
|
42
|
+
i
|
|
43
|
+
);
|
|
44
|
+
}) })
|
|
37
45
|
}
|
|
38
46
|
)
|
|
39
47
|
);
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { ThemeProvider, useTheme } from "./hooks/useTheme.js";
|
|
3
|
+
import { Slot } from "./lib/Slot.js";
|
|
3
4
|
import { Alert } from "./components/Alert/Alert.js";
|
|
4
5
|
import { AppLayout } from "./components/Layout/Layout.js";
|
|
5
6
|
import { Avatar } from "./components/Avatar/Avatar.js";
|
|
@@ -147,6 +148,7 @@ export {
|
|
|
147
148
|
SidebarDivider,
|
|
148
149
|
SidebarGroupLabel,
|
|
149
150
|
Skeleton,
|
|
151
|
+
Slot,
|
|
150
152
|
Sparkline,
|
|
151
153
|
SplitSection,
|
|
152
154
|
StatItem,
|
package/dist/lib/Slot.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { version, forwardRef, Children, isValidElement, cloneElement } from "react";
|
|
3
|
+
import { composeEventHandlers } from "./composeEventHandlers.js";
|
|
4
|
+
import { cn } from "./utils.js";
|
|
5
|
+
const REACT_MAJOR = Number.parseInt(version.split(".")[0] ?? "0", 10);
|
|
6
|
+
function assignRef(ref, node) {
|
|
7
|
+
if (typeof ref === "function") ref(node);
|
|
8
|
+
else if (ref) ref.current = node;
|
|
9
|
+
}
|
|
10
|
+
function getElementRef(element) {
|
|
11
|
+
if (REACT_MAJOR >= 19) return element.props.ref;
|
|
12
|
+
return element.ref;
|
|
13
|
+
}
|
|
14
|
+
const Slot = forwardRef(
|
|
15
|
+
({ children, ...slotProps }, forwardedRef) => {
|
|
16
|
+
const child = Children.only(children);
|
|
17
|
+
if (!isValidElement(child)) {
|
|
18
|
+
throw new Error("[kaze] Slot (asChild) には React 要素を 1 つだけ渡してください");
|
|
19
|
+
}
|
|
20
|
+
const merged = mergeProps(slotProps, child.props);
|
|
21
|
+
const childRef = getElementRef(child);
|
|
22
|
+
merged.ref = (node) => {
|
|
23
|
+
assignRef(childRef, node);
|
|
24
|
+
assignRef(forwardedRef, node);
|
|
25
|
+
};
|
|
26
|
+
return cloneElement(child, merged);
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
Slot.displayName = "Slot";
|
|
30
|
+
function mergeProps(slotProps, childProps) {
|
|
31
|
+
const merged = { ...slotProps };
|
|
32
|
+
for (const [key, childValue] of Object.entries(childProps)) {
|
|
33
|
+
if (childValue === void 0) continue;
|
|
34
|
+
const slotValue = slotProps[key];
|
|
35
|
+
if (key === "className") {
|
|
36
|
+
merged.className = cn(slotValue, childValue);
|
|
37
|
+
} else if (key === "style") {
|
|
38
|
+
merged.style = {
|
|
39
|
+
...slotValue,
|
|
40
|
+
...childValue
|
|
41
|
+
};
|
|
42
|
+
} else if (/^on[A-Z]/.test(key) && typeof slotValue === "function" && typeof childValue === "function") {
|
|
43
|
+
merged[key] = composeEventHandlers(childValue, slotValue);
|
|
44
|
+
} else {
|
|
45
|
+
merged[key] = childValue;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return merged;
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
Slot
|
|
52
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const warned = /* @__PURE__ */ new Set();
|
|
2
|
+
function isProduction() {
|
|
3
|
+
try {
|
|
4
|
+
return typeof process !== "undefined" && process.env.NODE_ENV === "production";
|
|
5
|
+
} catch {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
function warnDeprecated(key, message) {
|
|
10
|
+
if (isProduction() || warned.has(key)) return;
|
|
11
|
+
warned.add(key);
|
|
12
|
+
console.warn(`[kaze] ${message}`);
|
|
13
|
+
}
|
|
14
|
+
function renamedProp(component, oldName, newName, oldValue, newValue) {
|
|
15
|
+
if (newValue !== void 0) return newValue;
|
|
16
|
+
if (oldValue === void 0) return void 0;
|
|
17
|
+
warnDeprecated(
|
|
18
|
+
`${component}.${oldName}`,
|
|
19
|
+
`${component} の \`${oldName}\` は \`${newName}\` に改名しました。次のマイナーバージョンで削除します`
|
|
20
|
+
);
|
|
21
|
+
return oldValue;
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
renamedProp,
|
|
25
|
+
warnDeprecated
|
|
26
|
+
};
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { type ReactNode, type HTMLAttributes } from "react";
|
|
2
|
-
|
|
2
|
+
import type { Tone } from "../../lib/types";
|
|
3
|
+
/** @deprecated `Tone` を使う */
|
|
4
|
+
export type AlertVariant = Tone;
|
|
3
5
|
export interface AlertProps extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
-
|
|
6
|
+
tone?: Tone;
|
|
7
|
+
/** @deprecated `tone` に改名。次のマイナーで削除 */
|
|
8
|
+
variant?: Tone;
|
|
5
9
|
icon?: ReactNode;
|
|
6
10
|
title?: string;
|
|
7
11
|
children: ReactNode;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type HTMLAttributes } from "react";
|
|
2
|
-
|
|
2
|
+
import type { Size } from "../../lib/types";
|
|
3
|
+
export type AvatarSize = Extract<Size, "xs" | "sm" | "md" | "lg">;
|
|
3
4
|
export interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {
|
|
4
5
|
size?: AvatarSize;
|
|
5
6
|
src?: string;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { type HTMLAttributes } from "react";
|
|
2
|
-
|
|
2
|
+
import type { Tone } from "../../lib/types";
|
|
3
|
+
/** @deprecated `Tone` を使う */
|
|
4
|
+
export type BadgeVariant = Tone;
|
|
3
5
|
export interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
|
|
4
|
-
|
|
6
|
+
tone?: Tone;
|
|
7
|
+
/** @deprecated `tone` に改名。次のマイナーで削除 */
|
|
8
|
+
variant?: Tone;
|
|
5
9
|
dot?: boolean;
|
|
6
10
|
/** Solid (inverted) style: filled background with white text */
|
|
7
11
|
solid?: boolean;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { type ButtonHTMLAttributes } from "react";
|
|
2
|
+
import type { Size } from "../../lib/types";
|
|
2
3
|
export type ButtonVariant = "primary" | "secondary" | "outline" | "ghost" | "destructive";
|
|
3
|
-
export type ButtonSize = "xs" | "sm" | "md" | "lg"
|
|
4
|
+
export type ButtonSize = Extract<Size, "xs" | "sm" | "md" | "lg">;
|
|
4
5
|
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
5
6
|
variant?: ButtonVariant;
|
|
6
7
|
size?: ButtonSize;
|
|
7
8
|
fullWidth?: boolean;
|
|
8
9
|
iconOnly?: boolean;
|
|
10
|
+
/** 子要素にスタイルと振る舞いを委ねる(Next.js の Link など) */
|
|
11
|
+
asChild?: boolean;
|
|
9
12
|
}
|
|
10
13
|
export declare const Button: import("react").ForwardRefExoticComponent<ButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { type HTMLAttributes, type RefObject } from "react";
|
|
2
2
|
export interface DialogProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
3
|
open: boolean;
|
|
4
|
-
|
|
4
|
+
/** Escape / 背景クリック / 閉じる操作で呼ばれる。`open` を false にするのは呼び出し側 */
|
|
5
|
+
onOpenChange?: (open: boolean) => void;
|
|
6
|
+
/** @deprecated `onOpenChange` に改名。次のマイナーで削除 */
|
|
7
|
+
onClose?: () => void;
|
|
5
8
|
/** @deprecated useFocusTrap handles focus restoration automatically. Kept for backward compat: ignored. */
|
|
6
9
|
returnFocusRef?: RefObject<HTMLElement | null>;
|
|
7
10
|
}
|