kaze-design-system 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -9
- package/components.css +476 -0
- package/dist/components/Alert/Alert.js +7 -16
- package/dist/components/Badge/Badge.js +1 -6
- package/dist/components/BarChart/BarChart.js +19 -15
- package/dist/components/BarList/BarList.js +2 -16
- package/dist/components/Card/Card.js +5 -3
- package/dist/components/CategoryBar/CategoryBar.js +88 -0
- package/dist/components/ChartLegend/ChartLegend.js +43 -0
- package/dist/components/Checkbox/Checkbox.js +1 -10
- package/dist/components/ColumnChart/ColumnChart.js +290 -0
- package/dist/components/CommandPalette/CommandPalette.js +3 -9
- package/dist/components/DescriptionList/DescriptionList.js +11 -14
- package/dist/components/Dialog/Dialog.js +1 -10
- package/dist/components/Disclosure/Disclosure.js +1 -4
- package/dist/components/DonutChart/DonutChart.js +54 -50
- package/dist/components/Dropdown/Dropdown.js +2 -11
- package/dist/components/FAQ/FAQ.js +36 -46
- package/dist/components/FeatureGrid/FeatureGrid.js +1 -5
- package/dist/components/FilterPill/FilterPill.js +1 -5
- package/dist/components/FormField/FormField.js +2 -15
- package/dist/components/Grid/Grid.js +1 -9
- package/dist/components/Heatmap/Heatmap.js +255 -0
- package/dist/components/HelpButton/HelpButton.js +1 -9
- package/dist/components/LPFooter/LPFooter.js +1 -10
- package/dist/components/LineChart/LineChart.js +314 -0
- package/dist/components/List/List.js +2 -15
- package/dist/components/Logo/Logo.js +1 -10
- package/dist/components/Meter/Meter.js +1 -4
- package/dist/components/Metric/Metric.js +2 -17
- package/dist/components/Navbar/Navbar.js +2 -10
- package/dist/components/NumberField/NumberField.js +30 -7
- package/dist/components/Pagination/Pagination.js +37 -46
- package/dist/components/Pricing/Pricing.js +2 -17
- package/dist/components/Progress/Progress.js +3 -18
- package/dist/components/Radio/Radio.js +2 -14
- package/dist/components/Search/Search.js +10 -1
- package/dist/components/Section/Section.js +4 -12
- package/dist/components/SegmentedControl/SegmentedControl.js +120 -0
- package/dist/components/Sidebar/Sidebar.js +7 -31
- package/dist/components/SplitSection/SplitSection.js +1 -5
- package/dist/components/StatusBadge/StatusBadge.js +1 -11
- package/dist/components/Stepper/Stepper.js +29 -27
- package/dist/components/Table/Table.js +5 -3
- package/dist/components/Tabs/Tabs.js +29 -36
- package/dist/components/Testimonial/Testimonial.js +19 -23
- package/dist/components/Text/Text.js +1 -11
- package/dist/components/Toast/Toast.js +103 -116
- package/dist/components/Tooltip/Tooltip.js +89 -92
- package/dist/components/TopBar/TopBar.js +4 -12
- package/dist/hooks/useLegendToggle.js +1 -4
- package/dist/hooks/useTheme.js +1 -4
- package/dist/index.js +12 -0
- package/dist/lib/chartScale.js +38 -0
- package/dist/types/components/CategoryBar/CategoryBar.d.ts +28 -0
- package/dist/types/components/CategoryBar/index.d.ts +2 -0
- package/dist/types/components/ChartLegend/ChartLegend.d.ts +17 -0
- package/dist/types/components/ChartLegend/index.d.ts +2 -0
- package/dist/types/components/ColumnChart/ColumnChart.d.ts +33 -0
- package/dist/types/components/ColumnChart/index.d.ts +2 -0
- package/dist/types/components/Dropdown/Dropdown.d.ts +2 -3
- package/dist/types/components/Heatmap/Heatmap.d.ts +49 -0
- package/dist/types/components/Heatmap/index.d.ts +2 -0
- package/dist/types/components/LineChart/LineChart.d.ts +40 -0
- package/dist/types/components/LineChart/index.d.ts +2 -0
- package/dist/types/components/SegmentedControl/SegmentedControl.d.ts +21 -0
- package/dist/types/components/SegmentedControl/index.d.ts +2 -0
- package/dist/types/components/Sidebar/index.d.ts +1 -1
- package/dist/types/components/Toast/Toast.d.ts +1 -1
- package/dist/types/components/index.d.ts +13 -1
- package/dist/types/hooks/useTheme.d.ts +1 -1
- package/dist/types/lib/chartScale.d.ts +19 -0
- package/dist/types/lib/utils.d.ts +1 -1
- package/package.json +7 -3
|
@@ -30,56 +30,60 @@ const DonutChart = forwardRef(
|
|
|
30
30
|
dashOffset
|
|
31
31
|
};
|
|
32
32
|
});
|
|
33
|
-
return /* @__PURE__ */ jsxs(
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
33
|
+
return /* @__PURE__ */ jsxs(
|
|
34
|
+
"div",
|
|
35
|
+
{
|
|
36
|
+
ref,
|
|
37
|
+
role: "img",
|
|
38
|
+
"aria-label": ariaLabel,
|
|
39
|
+
className: cn("donut-chart", className),
|
|
40
|
+
...rest,
|
|
41
|
+
children: [
|
|
42
|
+
/* @__PURE__ */ jsxs(
|
|
43
|
+
"svg",
|
|
44
|
+
{
|
|
45
|
+
className: "donut-chart__svg",
|
|
46
|
+
width: size,
|
|
47
|
+
height: size,
|
|
48
|
+
viewBox: `0 0 ${size} ${size}`,
|
|
49
|
+
"aria-hidden": "true",
|
|
50
|
+
children: [
|
|
51
|
+
/* @__PURE__ */ jsx(
|
|
52
|
+
"circle",
|
|
53
|
+
{
|
|
54
|
+
className: "donut-chart__track",
|
|
55
|
+
cx: center,
|
|
56
|
+
cy: center,
|
|
57
|
+
r: radius,
|
|
58
|
+
strokeWidth
|
|
59
|
+
}
|
|
60
|
+
),
|
|
61
|
+
segments.map((seg) => /* @__PURE__ */ jsx(
|
|
62
|
+
"circle",
|
|
63
|
+
{
|
|
64
|
+
className: "donut-chart__segment",
|
|
65
|
+
cx: center,
|
|
66
|
+
cy: center,
|
|
67
|
+
r: radius,
|
|
68
|
+
strokeWidth,
|
|
69
|
+
stroke: seg.color,
|
|
70
|
+
strokeDasharray: `${seg.dashLength} ${circumference - seg.dashLength}`,
|
|
71
|
+
strokeDashoffset: seg.dashOffset
|
|
72
|
+
},
|
|
73
|
+
seg.label
|
|
74
|
+
)),
|
|
75
|
+
centerLabel && /* @__PURE__ */ jsx("text", { className: "donut-chart__center-label", x: center, y: center, children: centerLabel })
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
),
|
|
79
|
+
showLegend && /* @__PURE__ */ jsx("div", { className: "donut-chart__legend", children: segments.map((seg) => /* @__PURE__ */ jsxs("span", { className: "donut-chart__legend-item", children: [
|
|
80
|
+
/* @__PURE__ */ jsx("span", { className: "donut-chart__legend-dot", style: { background: seg.color } }),
|
|
81
|
+
/* @__PURE__ */ jsx("span", { className: "donut-chart__legend-label", children: seg.label }),
|
|
82
|
+
/* @__PURE__ */ jsx("span", { className: "donut-chart__legend-value", children: seg.value })
|
|
83
|
+
] }, seg.label)) })
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
);
|
|
83
87
|
}
|
|
84
88
|
);
|
|
85
89
|
DonutChart.displayName = "DonutChart";
|
|
@@ -7,9 +7,7 @@ const DropdownContext = createContext(null);
|
|
|
7
7
|
function useDropdownContext() {
|
|
8
8
|
const context = useContext(DropdownContext);
|
|
9
9
|
if (!context) {
|
|
10
|
-
throw new Error(
|
|
11
|
-
"Dropdown compound components must be used within a <Dropdown>"
|
|
12
|
-
);
|
|
10
|
+
throw new Error("Dropdown compound components must be used within a <Dropdown>");
|
|
13
11
|
}
|
|
14
12
|
return context;
|
|
15
13
|
}
|
|
@@ -91,14 +89,7 @@ const DropdownTrigger = forwardRef(
|
|
|
91
89
|
DropdownTrigger.displayName = "DropdownTrigger";
|
|
92
90
|
const DropdownMenu = forwardRef(
|
|
93
91
|
({ children, className, ...rest }, ref) => {
|
|
94
|
-
const {
|
|
95
|
-
open,
|
|
96
|
-
setOpen,
|
|
97
|
-
triggerRef,
|
|
98
|
-
highlightedIndex,
|
|
99
|
-
setHighlightedIndex,
|
|
100
|
-
resetItems
|
|
101
|
-
} = useDropdownContext();
|
|
92
|
+
const { open, setOpen, triggerRef, highlightedIndex, setHighlightedIndex, resetItems } = useDropdownContext();
|
|
102
93
|
const menuRef = useRef(null);
|
|
103
94
|
const [position, setPosition] = useState({
|
|
104
95
|
top: 0,
|
|
@@ -2,59 +2,49 @@
|
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { forwardRef, useState } from "react";
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
|
-
const FAQ = forwardRef(
|
|
6
|
-
({ className,
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
);
|
|
5
|
+
const FAQ = forwardRef(({ className, children, ...rest }, ref) => {
|
|
6
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn("faq", className), ...rest, children });
|
|
7
|
+
});
|
|
10
8
|
FAQ.displayName = "FAQ";
|
|
11
9
|
const FAQItem = forwardRef(
|
|
12
10
|
({ question, answer, className, children, ...rest }, ref) => {
|
|
13
11
|
const [open, setOpen] = useState(false);
|
|
14
|
-
return /* @__PURE__ */ jsxs(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
12
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cn("faq__item", open && "faq__item--open", className), ...rest, children: [
|
|
13
|
+
/* @__PURE__ */ jsxs(
|
|
14
|
+
"button",
|
|
15
|
+
{
|
|
16
|
+
type: "button",
|
|
17
|
+
className: "faq__trigger",
|
|
18
|
+
"aria-expanded": open,
|
|
19
|
+
onClick: () => setOpen((prev) => !prev),
|
|
20
|
+
children: [
|
|
21
|
+
question,
|
|
22
|
+
/* @__PURE__ */ jsx(
|
|
23
|
+
"svg",
|
|
24
|
+
{
|
|
25
|
+
className: "faq__chevron",
|
|
26
|
+
width: "16",
|
|
27
|
+
height: "16",
|
|
28
|
+
viewBox: "0 0 16 16",
|
|
29
|
+
fill: "none",
|
|
30
|
+
"aria-hidden": "true",
|
|
31
|
+
children: /* @__PURE__ */ jsx(
|
|
32
|
+
"path",
|
|
32
33
|
{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"aria-hidden": "true",
|
|
39
|
-
children: /* @__PURE__ */ jsx(
|
|
40
|
-
"path",
|
|
41
|
-
{
|
|
42
|
-
d: "M4 6l4 4 4-4",
|
|
43
|
-
stroke: "currentColor",
|
|
44
|
-
strokeWidth: "2",
|
|
45
|
-
strokeLinecap: "round",
|
|
46
|
-
strokeLinejoin: "round"
|
|
47
|
-
}
|
|
48
|
-
)
|
|
34
|
+
d: "M4 6l4 4 4-4",
|
|
35
|
+
stroke: "currentColor",
|
|
36
|
+
strokeWidth: "2",
|
|
37
|
+
strokeLinecap: "round",
|
|
38
|
+
strokeLinejoin: "round"
|
|
49
39
|
}
|
|
50
40
|
)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
);
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
),
|
|
46
|
+
/* @__PURE__ */ jsx("div", { className: "faq__answer", children: /* @__PURE__ */ jsx("div", { className: "faq__answer-inner", children: answer ?? children }) })
|
|
47
|
+
] });
|
|
58
48
|
}
|
|
59
49
|
);
|
|
60
50
|
FAQItem.displayName = "FAQItem";
|
|
@@ -7,11 +7,7 @@ const FeatureGrid = forwardRef(
|
|
|
7
7
|
"div",
|
|
8
8
|
{
|
|
9
9
|
ref,
|
|
10
|
-
className: cn(
|
|
11
|
-
"feature-grid",
|
|
12
|
-
columns !== 3 && `feature-grid--cols-${columns}`,
|
|
13
|
-
className
|
|
14
|
-
),
|
|
10
|
+
className: cn("feature-grid", columns !== 3 && `feature-grid--cols-${columns}`, className),
|
|
15
11
|
...rest,
|
|
16
12
|
children
|
|
17
13
|
}
|
|
@@ -9,11 +9,7 @@ const FilterPill = forwardRef(
|
|
|
9
9
|
{
|
|
10
10
|
ref,
|
|
11
11
|
type: "button",
|
|
12
|
-
className: cn(
|
|
13
|
-
"filter-pill",
|
|
14
|
-
active && "filter-pill--active",
|
|
15
|
-
className
|
|
16
|
-
),
|
|
12
|
+
className: cn("filter-pill", active && "filter-pill--active", className),
|
|
17
13
|
style: pillStyle,
|
|
18
14
|
"aria-pressed": active,
|
|
19
15
|
...rest,
|
|
@@ -2,17 +2,7 @@ import { jsxs, jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { forwardRef, useId, isValidElement, cloneElement } from "react";
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
4
|
const FormField = forwardRef(
|
|
5
|
-
({
|
|
6
|
-
label,
|
|
7
|
-
description,
|
|
8
|
-
error,
|
|
9
|
-
required,
|
|
10
|
-
maxLength,
|
|
11
|
-
currentLength,
|
|
12
|
-
children,
|
|
13
|
-
className,
|
|
14
|
-
...rest
|
|
15
|
-
}, ref) => {
|
|
5
|
+
({ label, description, error, required, maxLength, currentLength, children, className, ...rest }, ref) => {
|
|
16
6
|
const generatedId = useId();
|
|
17
7
|
const inputId = `form-field-${generatedId}`;
|
|
18
8
|
const descriptionId = description ? `${inputId}-description` : void 0;
|
|
@@ -29,10 +19,7 @@ const FormField = forwardRef(
|
|
|
29
19
|
"label",
|
|
30
20
|
{
|
|
31
21
|
htmlFor: inputId,
|
|
32
|
-
className: cn(
|
|
33
|
-
"form-field__label",
|
|
34
|
-
required && "form-field__label--required"
|
|
35
|
-
),
|
|
22
|
+
className: cn("form-field__label", required && "form-field__label--required"),
|
|
36
23
|
children: label
|
|
37
24
|
}
|
|
38
25
|
),
|
|
@@ -35,15 +35,7 @@ const Grid = forwardRef(
|
|
|
35
35
|
...resolvedGapMd != null ? { "--grid-gap-md": resolvedGapMd } : {},
|
|
36
36
|
...resolvedGapSm != null ? { "--grid-gap-sm": resolvedGapSm } : {}
|
|
37
37
|
};
|
|
38
|
-
return /* @__PURE__ */ jsx(
|
|
39
|
-
"div",
|
|
40
|
-
{
|
|
41
|
-
ref,
|
|
42
|
-
className: cn("grid", className),
|
|
43
|
-
style: vars,
|
|
44
|
-
...rest
|
|
45
|
-
}
|
|
46
|
-
);
|
|
38
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn("grid", className), style: vars, ...rest });
|
|
47
39
|
}
|
|
48
40
|
);
|
|
49
41
|
Grid.displayName = "Grid";
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef, useRef, useState } from "react";
|
|
4
|
+
import { cn } from "../../lib/utils.js";
|
|
5
|
+
import { defaultFormat } from "../../lib/chartScale.js";
|
|
6
|
+
const DAY_MS = 864e5;
|
|
7
|
+
const DATE_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
8
|
+
const WEEKDAY_LABELS = ["日", "月", "火", "水", "木", "金", "土"];
|
|
9
|
+
const LABELLED_WEEKDAYS = /* @__PURE__ */ new Set([1, 3, 5]);
|
|
10
|
+
function parseDay(date) {
|
|
11
|
+
const m = DATE_RE.exec(date);
|
|
12
|
+
if (!m) return null;
|
|
13
|
+
const ms = Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
|
|
14
|
+
const d = new Date(ms);
|
|
15
|
+
if (d.getUTCMonth() !== Number(m[2]) - 1) return null;
|
|
16
|
+
return ms / DAY_MS;
|
|
17
|
+
}
|
|
18
|
+
function formatDay(day) {
|
|
19
|
+
return new Date(day * DAY_MS).toISOString().slice(0, 10);
|
|
20
|
+
}
|
|
21
|
+
function levelOf(value, max, levels) {
|
|
22
|
+
if (value === null || value <= 0 || max <= 0) return 0;
|
|
23
|
+
return Math.min(levels, Math.max(1, Math.ceil(value / max * levels)));
|
|
24
|
+
}
|
|
25
|
+
function levelColor(level, levels) {
|
|
26
|
+
if (level === 0) return void 0;
|
|
27
|
+
const pct = levels === 1 ? 100 : Math.round(25 + 75 * (level - 1) / (levels - 1));
|
|
28
|
+
return `color-mix(in srgb, var(--heatmap-color) ${pct}%, var(--color-bg-tertiary))`;
|
|
29
|
+
}
|
|
30
|
+
const Heatmap = forwardRef(
|
|
31
|
+
({
|
|
32
|
+
variant = "matrix",
|
|
33
|
+
rows = [],
|
|
34
|
+
columns = [],
|
|
35
|
+
values = [],
|
|
36
|
+
data = [],
|
|
37
|
+
startDate,
|
|
38
|
+
endDate,
|
|
39
|
+
weekStartsOn = 1,
|
|
40
|
+
color = "var(--chart-1)",
|
|
41
|
+
levels = 5,
|
|
42
|
+
max,
|
|
43
|
+
cellSize = 16,
|
|
44
|
+
gap = 3,
|
|
45
|
+
showLegend = true,
|
|
46
|
+
formatValue = defaultFormat,
|
|
47
|
+
formatTooltip,
|
|
48
|
+
"aria-label": ariaLabel,
|
|
49
|
+
className,
|
|
50
|
+
style,
|
|
51
|
+
...rest
|
|
52
|
+
}, ref) => {
|
|
53
|
+
const rootRef = useRef(null);
|
|
54
|
+
const [tip, setTip] = useState(null);
|
|
55
|
+
const stepCount = Math.max(1, Math.floor(levels));
|
|
56
|
+
const cells = [];
|
|
57
|
+
let gridColumns = 0;
|
|
58
|
+
const monthLabels = [];
|
|
59
|
+
let maxValue = max;
|
|
60
|
+
if (variant === "matrix") {
|
|
61
|
+
gridColumns = columns.length;
|
|
62
|
+
rows.forEach((row, r) => {
|
|
63
|
+
columns.forEach((column, c) => {
|
|
64
|
+
const raw = values[r]?.[c];
|
|
65
|
+
cells.push({
|
|
66
|
+
key: `${r}:${c}`,
|
|
67
|
+
row,
|
|
68
|
+
column,
|
|
69
|
+
value: typeof raw === "number" && Number.isFinite(raw) ? raw : null,
|
|
70
|
+
gridRow: r + 2,
|
|
71
|
+
gridColumn: c + 2
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
} else {
|
|
76
|
+
const byDay = /* @__PURE__ */ new Map();
|
|
77
|
+
for (const d of data) {
|
|
78
|
+
const day = parseDay(d.date);
|
|
79
|
+
if (day === null || !Number.isFinite(d.value)) continue;
|
|
80
|
+
byDay.set(day, (byDay.get(day) ?? 0) + d.value);
|
|
81
|
+
}
|
|
82
|
+
const days = [...byDay.keys()];
|
|
83
|
+
const start = startDate ? parseDay(startDate) : days.length ? Math.min(...days) : null;
|
|
84
|
+
const end = endDate ? parseDay(endDate) : days.length ? Math.max(...days) : null;
|
|
85
|
+
if (start !== null && end !== null && end >= start) {
|
|
86
|
+
const rowOf = (day) => (new Date(day * DAY_MS).getUTCDay() - weekStartsOn + 7) % 7;
|
|
87
|
+
const gridStart = start - rowOf(start);
|
|
88
|
+
gridColumns = Math.floor((end - gridStart) / 7) + 1;
|
|
89
|
+
let lastLabelWeek = -Infinity;
|
|
90
|
+
let lastMonth = -1;
|
|
91
|
+
for (let day = start; day <= end; day++) {
|
|
92
|
+
const week = Math.floor((day - gridStart) / 7);
|
|
93
|
+
const month = new Date(day * DAY_MS).getUTCMonth();
|
|
94
|
+
if (month !== lastMonth) {
|
|
95
|
+
if (week - lastLabelWeek >= 3) {
|
|
96
|
+
monthLabels.push({ label: `${month + 1}月`, gridColumn: week + 2 });
|
|
97
|
+
lastLabelWeek = week;
|
|
98
|
+
}
|
|
99
|
+
lastMonth = month;
|
|
100
|
+
}
|
|
101
|
+
cells.push({
|
|
102
|
+
key: formatDay(day),
|
|
103
|
+
date: formatDay(day),
|
|
104
|
+
value: byDay.get(day) ?? null,
|
|
105
|
+
gridRow: rowOf(day) + 2,
|
|
106
|
+
gridColumn: week + 2
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (maxValue === void 0) {
|
|
112
|
+
maxValue = cells.reduce((acc, c) => c.value !== null && c.value > acc ? c.value : acc, 0);
|
|
113
|
+
}
|
|
114
|
+
const scaleMax = maxValue;
|
|
115
|
+
const show = (cell, el) => {
|
|
116
|
+
const root = rootRef.current;
|
|
117
|
+
if (!root) return;
|
|
118
|
+
const a = el.getBoundingClientRect();
|
|
119
|
+
const b = root.getBoundingClientRect();
|
|
120
|
+
const { row, column, date, value } = cell;
|
|
121
|
+
setTip({
|
|
122
|
+
x: a.left - b.left + a.width / 2,
|
|
123
|
+
y: a.top - b.top,
|
|
124
|
+
cell: { row, column, date, value }
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
const tooltipBody = (cell) => {
|
|
128
|
+
if (formatTooltip) return /* @__PURE__ */ jsx("div", { className: "chart-tooltip__title", children: formatTooltip(cell) });
|
|
129
|
+
const title = cell.date ?? `${cell.row} ${cell.column}`;
|
|
130
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
131
|
+
/* @__PURE__ */ jsx("div", { className: "chart-tooltip__title", children: title }),
|
|
132
|
+
/* @__PURE__ */ jsxs("div", { className: "chart-tooltip__row", children: [
|
|
133
|
+
/* @__PURE__ */ jsx("span", { className: "chart-tooltip__label", children: "値" }),
|
|
134
|
+
/* @__PURE__ */ jsx("span", { className: "chart-tooltip__value", children: cell.value === null ? "データなし" : formatValue(cell.value) })
|
|
135
|
+
] })
|
|
136
|
+
] });
|
|
137
|
+
};
|
|
138
|
+
const rootStyle = {
|
|
139
|
+
"--heatmap-color": color,
|
|
140
|
+
"--heatmap-cell": `${cellSize}px`,
|
|
141
|
+
"--heatmap-gap": `${gap}px`,
|
|
142
|
+
...style
|
|
143
|
+
};
|
|
144
|
+
const longestColumnLabel = columns.reduce((m, c) => Math.max(m, String(c).length), 0);
|
|
145
|
+
const columnLabelStep = Math.max(1, Math.ceil((longestColumnLabel * 8 + 6) / (cellSize + gap)));
|
|
146
|
+
const gridStyle = {
|
|
147
|
+
gridTemplateColumns: `auto repeat(${gridColumns}, var(--heatmap-cell))`,
|
|
148
|
+
gridTemplateRows: `auto repeat(${variant === "matrix" ? rows.length : 7}, var(--heatmap-cell))`
|
|
149
|
+
};
|
|
150
|
+
return /* @__PURE__ */ jsxs(
|
|
151
|
+
"div",
|
|
152
|
+
{
|
|
153
|
+
ref: (node) => {
|
|
154
|
+
rootRef.current = node;
|
|
155
|
+
if (typeof ref === "function") ref(node);
|
|
156
|
+
else if (ref) ref.current = node;
|
|
157
|
+
},
|
|
158
|
+
role: "img",
|
|
159
|
+
"aria-label": ariaLabel,
|
|
160
|
+
className: cn("chart", "heatmap", `heatmap--${variant}`, className),
|
|
161
|
+
style: rootStyle,
|
|
162
|
+
...rest,
|
|
163
|
+
children: [
|
|
164
|
+
/* @__PURE__ */ jsx("div", { className: "heatmap__scroll", children: /* @__PURE__ */ jsxs("div", { className: "heatmap__grid", style: gridStyle, onMouseLeave: () => setTip(null), children: [
|
|
165
|
+
variant === "matrix" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
166
|
+
columns.map((c, i) => /* @__PURE__ */ jsx(
|
|
167
|
+
"span",
|
|
168
|
+
{
|
|
169
|
+
hidden: i % columnLabelStep !== 0,
|
|
170
|
+
className: "heatmap__label heatmap__label--column",
|
|
171
|
+
style: { gridRow: 1, gridColumn: i + 2 },
|
|
172
|
+
children: c
|
|
173
|
+
},
|
|
174
|
+
`c${i}`
|
|
175
|
+
)),
|
|
176
|
+
rows.map((r, i) => /* @__PURE__ */ jsx(
|
|
177
|
+
"span",
|
|
178
|
+
{
|
|
179
|
+
className: "heatmap__label heatmap__label--row",
|
|
180
|
+
style: { gridRow: i + 2, gridColumn: 1 },
|
|
181
|
+
children: r
|
|
182
|
+
},
|
|
183
|
+
`r${i}`
|
|
184
|
+
))
|
|
185
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
186
|
+
monthLabels.map((m) => /* @__PURE__ */ jsx(
|
|
187
|
+
"span",
|
|
188
|
+
{
|
|
189
|
+
className: "heatmap__label heatmap__label--month",
|
|
190
|
+
style: { gridRow: 1, gridColumn: `${m.gridColumn} / span 3` },
|
|
191
|
+
children: m.label
|
|
192
|
+
},
|
|
193
|
+
m.gridColumn
|
|
194
|
+
)),
|
|
195
|
+
Array.from({ length: 7 }, (_, row) => {
|
|
196
|
+
const dow = (row + weekStartsOn) % 7;
|
|
197
|
+
return LABELLED_WEEKDAYS.has(dow) ? /* @__PURE__ */ jsx(
|
|
198
|
+
"span",
|
|
199
|
+
{
|
|
200
|
+
className: "heatmap__label heatmap__label--row",
|
|
201
|
+
style: { gridRow: row + 2, gridColumn: 1 },
|
|
202
|
+
children: WEEKDAY_LABELS[dow]
|
|
203
|
+
},
|
|
204
|
+
dow
|
|
205
|
+
) : null;
|
|
206
|
+
})
|
|
207
|
+
] }),
|
|
208
|
+
cells.map((cell) => {
|
|
209
|
+
const level = levelOf(cell.value, scaleMax, stepCount);
|
|
210
|
+
const { key, gridRow, gridColumn } = cell;
|
|
211
|
+
return (
|
|
212
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: pointer-only tooltip; the chart is exposed as role=img
|
|
213
|
+
/* @__PURE__ */ jsx(
|
|
214
|
+
"span",
|
|
215
|
+
{
|
|
216
|
+
className: cn("heatmap__cell", level === 0 && "heatmap__cell--empty"),
|
|
217
|
+
"data-level": level,
|
|
218
|
+
style: { gridRow, gridColumn, background: levelColor(level, stepCount) },
|
|
219
|
+
onMouseEnter: (e) => show(cell, e.currentTarget)
|
|
220
|
+
},
|
|
221
|
+
key
|
|
222
|
+
)
|
|
223
|
+
);
|
|
224
|
+
})
|
|
225
|
+
] }) }),
|
|
226
|
+
showLegend && /* @__PURE__ */ jsxs("div", { className: "heatmap__legend", "aria-hidden": "true", children: [
|
|
227
|
+
/* @__PURE__ */ jsx("span", { children: "少" }),
|
|
228
|
+
Array.from({ length: stepCount }, (_, i) => i + 1).map((level) => /* @__PURE__ */ jsx(
|
|
229
|
+
"span",
|
|
230
|
+
{
|
|
231
|
+
className: "heatmap__swatch",
|
|
232
|
+
style: { background: levelColor(level, stepCount) }
|
|
233
|
+
},
|
|
234
|
+
level
|
|
235
|
+
)),
|
|
236
|
+
/* @__PURE__ */ jsx("span", { children: "多" })
|
|
237
|
+
] }),
|
|
238
|
+
tip && /* @__PURE__ */ jsx(
|
|
239
|
+
"div",
|
|
240
|
+
{
|
|
241
|
+
className: "chart-tooltip heatmap__tooltip",
|
|
242
|
+
style: { left: tip.x, top: tip.y },
|
|
243
|
+
"aria-hidden": "true",
|
|
244
|
+
children: tooltipBody(tip.cell)
|
|
245
|
+
}
|
|
246
|
+
)
|
|
247
|
+
]
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
);
|
|
252
|
+
Heatmap.displayName = "Heatmap";
|
|
253
|
+
export {
|
|
254
|
+
Heatmap
|
|
255
|
+
};
|
|
@@ -31,15 +31,7 @@ function computePosition(trigger, pop, side) {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
const HelpButton = forwardRef(
|
|
34
|
-
({
|
|
35
|
-
title,
|
|
36
|
-
children,
|
|
37
|
-
position = "bottom",
|
|
38
|
-
size = "md",
|
|
39
|
-
icon,
|
|
40
|
-
ariaLabel = "ヘルプ",
|
|
41
|
-
className
|
|
42
|
-
}, ref) => {
|
|
34
|
+
({ title, children, position = "bottom", size = "md", icon, ariaLabel = "ヘルプ", className }, ref) => {
|
|
43
35
|
const [open, setOpen] = useState(false);
|
|
44
36
|
const [coords, setCoords] = useState({
|
|
45
37
|
top: 0,
|
|
@@ -2,16 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
4
|
const LPFooter = forwardRef(
|
|
5
|
-
({
|
|
6
|
-
logo,
|
|
7
|
-
description,
|
|
8
|
-
columns,
|
|
9
|
-
bottomLeft,
|
|
10
|
-
bottomRight,
|
|
11
|
-
className,
|
|
12
|
-
children,
|
|
13
|
-
...rest
|
|
14
|
-
}, ref) => {
|
|
5
|
+
({ logo, description, columns, bottomLeft, bottomRight, className, children, ...rest }, ref) => {
|
|
15
6
|
return /* @__PURE__ */ jsx("footer", { ref, className: cn("lp-footer", className), ...rest, children: /* @__PURE__ */ jsxs("div", { className: "lp-footer__inner", children: [
|
|
16
7
|
/* @__PURE__ */ jsxs("div", { className: "lp-footer__grid", children: [
|
|
17
8
|
/* @__PURE__ */ jsxs("div", { className: "lp-footer__brand", children: [
|