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
|
@@ -24,24 +24,12 @@ const Radio = forwardRef(
|
|
|
24
24
|
);
|
|
25
25
|
Radio.displayName = "Radio";
|
|
26
26
|
const RadioGroup = forwardRef(
|
|
27
|
-
({
|
|
28
|
-
label,
|
|
29
|
-
orientation = "vertical",
|
|
30
|
-
error,
|
|
31
|
-
errorMessage,
|
|
32
|
-
className,
|
|
33
|
-
children,
|
|
34
|
-
...rest
|
|
35
|
-
}, ref) => {
|
|
27
|
+
({ label, orientation = "vertical", error, errorMessage, className, children, ...rest }, ref) => {
|
|
36
28
|
return /* @__PURE__ */ jsxs(
|
|
37
29
|
"fieldset",
|
|
38
30
|
{
|
|
39
31
|
ref,
|
|
40
|
-
className: cn(
|
|
41
|
-
"radio-group",
|
|
42
|
-
`radio-group--${orientation}`,
|
|
43
|
-
className
|
|
44
|
-
),
|
|
32
|
+
className: cn("radio-group", `radio-group--${orientation}`, className),
|
|
45
33
|
"aria-invalid": error || void 0,
|
|
46
34
|
...rest,
|
|
47
35
|
children: [
|
|
@@ -3,7 +3,16 @@ import { jsxs, jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { forwardRef, useState, useCallback } from "react";
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
5
|
const Search = forwardRef(
|
|
6
|
-
({
|
|
6
|
+
({
|
|
7
|
+
placeholder = "Search...",
|
|
8
|
+
shortcut,
|
|
9
|
+
onSearch,
|
|
10
|
+
value: valueProp,
|
|
11
|
+
onChange: onChangeProp,
|
|
12
|
+
"aria-label": ariaLabel,
|
|
13
|
+
className,
|
|
14
|
+
...rest
|
|
15
|
+
}, ref) => {
|
|
7
16
|
const [internalValue, setInternalValue] = useState("");
|
|
8
17
|
const isControlled = valueProp !== void 0;
|
|
9
18
|
const currentValue = isControlled ? valueProp : internalValue;
|
|
@@ -22,18 +22,10 @@ const Section = forwardRef(
|
|
|
22
22
|
Section.displayName = "Section";
|
|
23
23
|
const SectionHeader = forwardRef(
|
|
24
24
|
({ title, description, className, ...rest }, ref) => {
|
|
25
|
-
return /* @__PURE__ */ jsxs(
|
|
26
|
-
"
|
|
27
|
-
{
|
|
28
|
-
|
|
29
|
-
className: cn("section-header", className),
|
|
30
|
-
...rest,
|
|
31
|
-
children: [
|
|
32
|
-
/* @__PURE__ */ jsx("h2", { className: "section-header__title", children: title }),
|
|
33
|
-
description && /* @__PURE__ */ jsx("p", { className: "section-header__description", children: description })
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
);
|
|
25
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cn("section-header", className), ...rest, children: [
|
|
26
|
+
/* @__PURE__ */ jsx("h2", { className: "section-header__title", children: title }),
|
|
27
|
+
description && /* @__PURE__ */ jsx("p", { className: "section-header__description", children: description })
|
|
28
|
+
] });
|
|
37
29
|
}
|
|
38
30
|
);
|
|
39
31
|
SectionHeader.displayName = "SectionHeader";
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef, useState, useRef } from "react";
|
|
4
|
+
import { cn } from "../../lib/utils.js";
|
|
5
|
+
const SegmentedControl = forwardRef(
|
|
6
|
+
({
|
|
7
|
+
options,
|
|
8
|
+
value: valueProp,
|
|
9
|
+
defaultValue,
|
|
10
|
+
onValueChange,
|
|
11
|
+
size = "md",
|
|
12
|
+
fullWidth = false,
|
|
13
|
+
name,
|
|
14
|
+
className,
|
|
15
|
+
onKeyDown,
|
|
16
|
+
"aria-label": ariaLabel,
|
|
17
|
+
...rest
|
|
18
|
+
}, ref) => {
|
|
19
|
+
const [inner, setInner] = useState(defaultValue);
|
|
20
|
+
const isControlled = valueProp !== void 0;
|
|
21
|
+
const current = isControlled ? valueProp : inner;
|
|
22
|
+
const buttons = useRef({});
|
|
23
|
+
const enabled = options.filter((o) => !o.disabled);
|
|
24
|
+
const selected = options.find((o) => o.value === current && !o.disabled);
|
|
25
|
+
const tabStop = selected?.value ?? enabled[0]?.value;
|
|
26
|
+
const selectedIndex = selected ? options.indexOf(selected) : -1;
|
|
27
|
+
const select = (v) => {
|
|
28
|
+
if (!isControlled) setInner(v);
|
|
29
|
+
if (v !== current) onValueChange?.(v);
|
|
30
|
+
};
|
|
31
|
+
const handleKeyDown = (e) => {
|
|
32
|
+
onKeyDown?.(e);
|
|
33
|
+
if (e.defaultPrevented || enabled.length === 0) return;
|
|
34
|
+
const focused = e.target.closest("[data-value]")?.getAttribute("data-value");
|
|
35
|
+
const from = enabled.findIndex((o) => o.value === focused);
|
|
36
|
+
let next;
|
|
37
|
+
switch (e.key) {
|
|
38
|
+
case "ArrowRight":
|
|
39
|
+
case "ArrowDown":
|
|
40
|
+
next = (from + 1) % enabled.length;
|
|
41
|
+
break;
|
|
42
|
+
case "ArrowLeft":
|
|
43
|
+
case "ArrowUp":
|
|
44
|
+
next = (from - 1 + enabled.length) % enabled.length;
|
|
45
|
+
break;
|
|
46
|
+
case "Home":
|
|
47
|
+
next = 0;
|
|
48
|
+
break;
|
|
49
|
+
case "End":
|
|
50
|
+
next = enabled.length - 1;
|
|
51
|
+
break;
|
|
52
|
+
default:
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
const target = enabled[next];
|
|
57
|
+
if (!target) return;
|
|
58
|
+
buttons.current[target.value]?.focus();
|
|
59
|
+
select(target.value);
|
|
60
|
+
};
|
|
61
|
+
return /* @__PURE__ */ jsxs(
|
|
62
|
+
"div",
|
|
63
|
+
{
|
|
64
|
+
ref,
|
|
65
|
+
role: "radiogroup",
|
|
66
|
+
"aria-label": ariaLabel,
|
|
67
|
+
className: cn(
|
|
68
|
+
"segmented-control",
|
|
69
|
+
size !== "md" && `segmented-control--${size}`,
|
|
70
|
+
fullWidth && "segmented-control--full",
|
|
71
|
+
className
|
|
72
|
+
),
|
|
73
|
+
onKeyDown: handleKeyDown,
|
|
74
|
+
...rest,
|
|
75
|
+
children: [
|
|
76
|
+
selectedIndex >= 0 && /* @__PURE__ */ jsx(
|
|
77
|
+
"span",
|
|
78
|
+
{
|
|
79
|
+
className: "segmented-control__indicator",
|
|
80
|
+
"aria-hidden": "true",
|
|
81
|
+
style: {
|
|
82
|
+
width: `calc((100% - 4px) / ${options.length})`,
|
|
83
|
+
transform: `translateX(${selectedIndex * 100}%)`
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
),
|
|
87
|
+
options.map((o) => {
|
|
88
|
+
const checked = o.value === selected?.value;
|
|
89
|
+
return (
|
|
90
|
+
// biome-ignore lint/a11y/useSemanticElements: custom radiogroup (roving tabindex + sliding pill); native radios cannot render the segment layout
|
|
91
|
+
/* @__PURE__ */ jsx(
|
|
92
|
+
"button",
|
|
93
|
+
{
|
|
94
|
+
ref: (el) => {
|
|
95
|
+
buttons.current[o.value] = el;
|
|
96
|
+
},
|
|
97
|
+
type: "button",
|
|
98
|
+
role: "radio",
|
|
99
|
+
"aria-checked": checked,
|
|
100
|
+
"data-value": o.value,
|
|
101
|
+
disabled: o.disabled,
|
|
102
|
+
tabIndex: o.value === tabStop ? 0 : -1,
|
|
103
|
+
className: "segmented-control__option",
|
|
104
|
+
onClick: () => select(o.value),
|
|
105
|
+
children: o.label
|
|
106
|
+
},
|
|
107
|
+
o.value
|
|
108
|
+
)
|
|
109
|
+
);
|
|
110
|
+
}),
|
|
111
|
+
name && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: selected?.value ?? "" })
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
SegmentedControl.displayName = "SegmentedControl";
|
|
118
|
+
export {
|
|
119
|
+
SegmentedControl
|
|
120
|
+
};
|
|
@@ -3,19 +3,11 @@ import { forwardRef } from "react";
|
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
4
|
const Sidebar = forwardRef(
|
|
5
5
|
({ children, logo, footer, className, ...rest }, ref) => {
|
|
6
|
-
return /* @__PURE__ */ jsxs(
|
|
7
|
-
"
|
|
8
|
-
{
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
...rest,
|
|
12
|
-
children: [
|
|
13
|
-
logo && /* @__PURE__ */ jsx("div", { className: "sidebar__logo", children: logo }),
|
|
14
|
-
/* @__PURE__ */ jsx("nav", { className: "sidebar__nav", children }),
|
|
15
|
-
footer && /* @__PURE__ */ jsx("div", { className: "sidebar__footer", children: footer })
|
|
16
|
-
]
|
|
17
|
-
}
|
|
18
|
-
);
|
|
6
|
+
return /* @__PURE__ */ jsxs("aside", { ref, className: cn("sidebar", className), ...rest, children: [
|
|
7
|
+
logo && /* @__PURE__ */ jsx("div", { className: "sidebar__logo", children: logo }),
|
|
8
|
+
/* @__PURE__ */ jsx("nav", { className: "sidebar__nav", children }),
|
|
9
|
+
footer && /* @__PURE__ */ jsx("div", { className: "sidebar__footer", children: footer })
|
|
10
|
+
] });
|
|
19
11
|
}
|
|
20
12
|
);
|
|
21
13
|
Sidebar.displayName = "Sidebar";
|
|
@@ -40,29 +32,13 @@ const NavItem = forwardRef(
|
|
|
40
32
|
NavItem.displayName = "NavItem";
|
|
41
33
|
const SidebarGroupLabel = forwardRef(
|
|
42
34
|
({ className, children, ...rest }, ref) => {
|
|
43
|
-
return /* @__PURE__ */ jsx(
|
|
44
|
-
"div",
|
|
45
|
-
{
|
|
46
|
-
ref,
|
|
47
|
-
className: cn("sidebar__group-label", className),
|
|
48
|
-
...rest,
|
|
49
|
-
children
|
|
50
|
-
}
|
|
51
|
-
);
|
|
35
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn("sidebar__group-label", className), ...rest, children });
|
|
52
36
|
}
|
|
53
37
|
);
|
|
54
38
|
SidebarGroupLabel.displayName = "SidebarGroupLabel";
|
|
55
39
|
const SidebarDivider = forwardRef(
|
|
56
40
|
({ className, ...rest }, ref) => {
|
|
57
|
-
return /* @__PURE__ */ jsx(
|
|
58
|
-
"div",
|
|
59
|
-
{
|
|
60
|
-
ref,
|
|
61
|
-
className: cn("sidebar__divider", className),
|
|
62
|
-
role: "separator",
|
|
63
|
-
...rest
|
|
64
|
-
}
|
|
65
|
-
);
|
|
41
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn("sidebar__divider", className), role: "separator", ...rest });
|
|
66
42
|
}
|
|
67
43
|
);
|
|
68
44
|
SidebarDivider.displayName = "SidebarDivider";
|
|
@@ -10,11 +10,7 @@ const SplitSection = forwardRef(
|
|
|
10
10
|
"section",
|
|
11
11
|
{
|
|
12
12
|
ref,
|
|
13
|
-
className: cn(
|
|
14
|
-
"split-section",
|
|
15
|
-
reverse && "split-section--reverse",
|
|
16
|
-
className
|
|
17
|
-
),
|
|
13
|
+
className: cn("split-section", reverse && "split-section--reverse", className),
|
|
18
14
|
...rest,
|
|
19
15
|
children: [
|
|
20
16
|
mediaSlot,
|
|
@@ -12,17 +12,7 @@ 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(
|
|
16
|
-
Badge,
|
|
17
|
-
{
|
|
18
|
-
ref,
|
|
19
|
-
variant: config.variant,
|
|
20
|
-
dot,
|
|
21
|
-
live: isLive,
|
|
22
|
-
...rest,
|
|
23
|
-
children: label ?? config.label
|
|
24
|
-
}
|
|
25
|
-
);
|
|
15
|
+
return /* @__PURE__ */ jsx(Badge, { ref, variant: config.variant, dot, live: isLive, ...rest, children: label ?? config.label });
|
|
26
16
|
}
|
|
27
17
|
);
|
|
28
18
|
StatusBadge.displayName = "StatusBadge";
|
|
@@ -1,42 +1,44 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
|
-
const CheckIcon = () => /* @__PURE__ */ jsx(
|
|
4
|
+
const CheckIcon = () => /* @__PURE__ */ jsx(
|
|
5
|
+
"svg",
|
|
6
|
+
{
|
|
7
|
+
"aria-hidden": "true",
|
|
8
|
+
width: "14",
|
|
9
|
+
height: "14",
|
|
10
|
+
viewBox: "0 0 24 24",
|
|
11
|
+
fill: "none",
|
|
12
|
+
stroke: "currentColor",
|
|
13
|
+
strokeWidth: "3",
|
|
14
|
+
strokeLinecap: "round",
|
|
15
|
+
strokeLinejoin: "round",
|
|
16
|
+
children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
|
|
17
|
+
}
|
|
18
|
+
);
|
|
5
19
|
const Stepper = forwardRef(
|
|
6
20
|
({ steps, currentStep, className, ...rest }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("stepper", className), ...rest, children: steps.map((step, i) => {
|
|
7
21
|
const isCompleted = i < currentStep;
|
|
8
22
|
const isActive = i === currentStep;
|
|
9
23
|
return /* @__PURE__ */ jsxs("div", { style: { display: "contents" }, children: [
|
|
10
|
-
/* @__PURE__ */ jsxs(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
/* @__PURE__ */ jsx(
|
|
19
|
-
"span",
|
|
20
|
-
{
|
|
21
|
-
className: cn(
|
|
22
|
-
"stepper__circle",
|
|
23
|
-
isActive && "stepper__circle--active",
|
|
24
|
-
isCompleted && "stepper__circle--completed"
|
|
25
|
-
),
|
|
26
|
-
children: isCompleted ? /* @__PURE__ */ jsx(CheckIcon, {}) : i + 1
|
|
27
|
-
}
|
|
24
|
+
/* @__PURE__ */ jsxs("div", { className: cn("stepper__step", isActive && "stepper__step--active"), children: [
|
|
25
|
+
/* @__PURE__ */ jsx(
|
|
26
|
+
"span",
|
|
27
|
+
{
|
|
28
|
+
className: cn(
|
|
29
|
+
"stepper__circle",
|
|
30
|
+
isActive && "stepper__circle--active",
|
|
31
|
+
isCompleted && "stepper__circle--completed"
|
|
28
32
|
),
|
|
29
|
-
/* @__PURE__ */ jsx(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
children: isCompleted ? /* @__PURE__ */ jsx(CheckIcon, {}) : i + 1
|
|
34
|
+
}
|
|
35
|
+
),
|
|
36
|
+
/* @__PURE__ */ jsx("span", { className: "stepper__label", children: step.label })
|
|
37
|
+
] }),
|
|
33
38
|
i < steps.length - 1 && /* @__PURE__ */ jsx(
|
|
34
39
|
"span",
|
|
35
40
|
{
|
|
36
|
-
className: cn(
|
|
37
|
-
"stepper__connector",
|
|
38
|
-
isCompleted && "stepper__connector--completed"
|
|
39
|
-
)
|
|
41
|
+
className: cn("stepper__connector", isCompleted && "stepper__connector--completed")
|
|
40
42
|
}
|
|
41
43
|
)
|
|
42
44
|
] }, i);
|
|
@@ -16,9 +16,11 @@ const Table = forwardRef(
|
|
|
16
16
|
}
|
|
17
17
|
);
|
|
18
18
|
Table.displayName = "Table";
|
|
19
|
-
const TableHeader = forwardRef(
|
|
20
|
-
|
|
21
|
-
});
|
|
19
|
+
const TableHeader = forwardRef(
|
|
20
|
+
({ className, children, ...rest }, ref) => {
|
|
21
|
+
return /* @__PURE__ */ jsx("thead", { ref, className, ...rest, children });
|
|
22
|
+
}
|
|
23
|
+
);
|
|
22
24
|
TableHeader.displayName = "TableHeader";
|
|
23
25
|
const TableBody = forwardRef(
|
|
24
26
|
({ className, children, ...rest }, ref) => {
|
|
@@ -12,48 +12,41 @@ const TabGroup = forwardRef(
|
|
|
12
12
|
TabGroup.displayName = "TabGroup";
|
|
13
13
|
const Tabs = forwardRef(
|
|
14
14
|
({ variant = "default", className, children, ...rest }, ref) => {
|
|
15
|
-
const handleKeyDown = useCallback(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
nextTab.click();
|
|
42
|
-
}
|
|
15
|
+
const handleKeyDown = useCallback((e) => {
|
|
16
|
+
const target = e.target;
|
|
17
|
+
if (target.getAttribute("role") !== "tab") return;
|
|
18
|
+
const tabs = Array.from(
|
|
19
|
+
e.currentTarget.querySelectorAll(
|
|
20
|
+
'[role="tab"]:not([disabled])'
|
|
21
|
+
)
|
|
22
|
+
);
|
|
23
|
+
const currentIndex = tabs.indexOf(target);
|
|
24
|
+
if (currentIndex === -1) return;
|
|
25
|
+
let nextIndex = null;
|
|
26
|
+
if (e.key === "ArrowRight") {
|
|
27
|
+
nextIndex = (currentIndex + 1) % tabs.length;
|
|
28
|
+
} else if (e.key === "ArrowLeft") {
|
|
29
|
+
nextIndex = (currentIndex - 1 + tabs.length) % tabs.length;
|
|
30
|
+
} else if (e.key === "Home") {
|
|
31
|
+
nextIndex = 0;
|
|
32
|
+
} else if (e.key === "End") {
|
|
33
|
+
nextIndex = tabs.length - 1;
|
|
34
|
+
}
|
|
35
|
+
if (nextIndex !== null) {
|
|
36
|
+
const nextTab = tabs[nextIndex];
|
|
37
|
+
if (nextTab) {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
nextTab.focus();
|
|
40
|
+
nextTab.click();
|
|
43
41
|
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
);
|
|
42
|
+
}
|
|
43
|
+
}, []);
|
|
47
44
|
return /* @__PURE__ */ jsx(
|
|
48
45
|
"div",
|
|
49
46
|
{
|
|
50
47
|
ref,
|
|
51
48
|
role: "tablist",
|
|
52
|
-
className: cn(
|
|
53
|
-
"tabs",
|
|
54
|
-
variant === "pills" && "tabs--pills",
|
|
55
|
-
className
|
|
56
|
-
),
|
|
49
|
+
className: cn("tabs", variant === "pills" && "tabs--pills", className),
|
|
57
50
|
onKeyDown: handleKeyDown,
|
|
58
51
|
...rest,
|
|
59
52
|
children
|
|
@@ -2,31 +2,27 @@ import { jsxs, jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
4
|
import { Avatar } from "../Avatar/Avatar.js";
|
|
5
|
-
const TestimonialGrid = forwardRef(
|
|
6
|
-
|
|
7
|
-
"div",
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
className: cn("testimonial-grid", className),
|
|
11
|
-
...rest,
|
|
12
|
-
children
|
|
13
|
-
}
|
|
14
|
-
);
|
|
15
|
-
});
|
|
5
|
+
const TestimonialGrid = forwardRef(
|
|
6
|
+
({ className, children, ...rest }, ref) => {
|
|
7
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn("testimonial-grid", className), ...rest, children });
|
|
8
|
+
}
|
|
9
|
+
);
|
|
16
10
|
TestimonialGrid.displayName = "TestimonialGrid";
|
|
17
|
-
const TestimonialCard = forwardRef(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/* @__PURE__ */
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
/* @__PURE__ */
|
|
25
|
-
|
|
11
|
+
const TestimonialCard = forwardRef(
|
|
12
|
+
({ quote, authorName, authorRole, authorImage, showIcon, className, ...rest }, ref) => {
|
|
13
|
+
const initials = authorName.split(/\s+/).map((w) => w[0]).join("").slice(0, 2);
|
|
14
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cn("testimonial", className), ...rest, children: [
|
|
15
|
+
/* @__PURE__ */ jsx("blockquote", { className: "testimonial__quote", children: quote }),
|
|
16
|
+
/* @__PURE__ */ jsxs("div", { className: "testimonial__author", children: [
|
|
17
|
+
showIcon && (authorImage ? /* @__PURE__ */ jsx(Avatar, { size: "sm", src: authorImage, alt: authorName }) : /* @__PURE__ */ jsx("span", { className: "testimonial__icon", children: initials })),
|
|
18
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
19
|
+
/* @__PURE__ */ jsx("span", { className: "testimonial__name", children: authorName }),
|
|
20
|
+
authorRole && /* @__PURE__ */ jsx("span", { className: "testimonial__role", children: authorRole })
|
|
21
|
+
] })
|
|
26
22
|
] })
|
|
27
|
-
] })
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
] });
|
|
24
|
+
}
|
|
25
|
+
);
|
|
30
26
|
TestimonialCard.displayName = "TestimonialCard";
|
|
31
27
|
export {
|
|
32
28
|
TestimonialCard,
|
|
@@ -1,17 +1,7 @@
|
|
|
1
1
|
import { forwardRef, createElement } from "react";
|
|
2
2
|
import { cn } from "../../lib/utils.js";
|
|
3
3
|
const Text = forwardRef(
|
|
4
|
-
({
|
|
5
|
-
variant = "body",
|
|
6
|
-
size,
|
|
7
|
-
weight,
|
|
8
|
-
color,
|
|
9
|
-
align,
|
|
10
|
-
as = "p",
|
|
11
|
-
className,
|
|
12
|
-
children,
|
|
13
|
-
...rest
|
|
14
|
-
}, ref) => {
|
|
4
|
+
({ variant = "body", size, weight, color, align, as = "p", className, children, ...rest }, ref) => {
|
|
15
5
|
return createElement(
|
|
16
6
|
as,
|
|
17
7
|
{
|