@craftzbay/ui 0.9.0 → 0.11.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 +82 -10
- package/dist-lib/__tests__/helpers/color.d.ts +9 -0
- package/dist-lib/__tests__/helpers/theme.d.ts +18 -0
- package/dist-lib/components/ui/Accordion.js +71 -0
- package/dist-lib/components/ui/Accordion.js.map +1 -0
- package/dist-lib/components/ui/Alert.d.ts +17 -1
- package/dist-lib/components/ui/Alert.js +79 -0
- package/dist-lib/components/ui/Alert.js.map +1 -0
- package/dist-lib/components/ui/Avatar.d.ts +3 -3
- package/dist-lib/components/ui/Avatar.js +94 -0
- package/dist-lib/components/ui/Avatar.js.map +1 -0
- package/dist-lib/components/ui/Badge.d.ts +4 -2
- package/dist-lib/components/ui/Badge.js +76 -0
- package/dist-lib/components/ui/Badge.js.map +1 -0
- package/dist-lib/components/ui/Breadcrumbs.d.ts +2 -0
- package/dist-lib/components/ui/Breadcrumbs.js +52 -0
- package/dist-lib/components/ui/Breadcrumbs.js.map +1 -0
- package/dist-lib/components/ui/Button.d.ts +6 -4
- package/dist-lib/components/ui/Button.js +131 -0
- package/dist-lib/components/ui/Button.js.map +1 -0
- package/dist-lib/components/ui/Calendar.d.ts +7 -1
- package/dist-lib/components/ui/Calendar.js +139 -0
- package/dist-lib/components/ui/Calendar.js.map +1 -0
- package/dist-lib/components/ui/Card.d.ts +3 -1
- package/dist-lib/components/ui/Card.js +97 -0
- package/dist-lib/components/ui/Card.js.map +1 -0
- package/dist-lib/components/ui/Carousel.d.ts +11 -7
- package/dist-lib/components/ui/Carousel.js +174 -0
- package/dist-lib/components/ui/Carousel.js.map +1 -0
- package/dist-lib/components/ui/Chart.d.ts +68 -7
- package/dist-lib/components/ui/Chart.js +487 -0
- package/dist-lib/components/ui/Chart.js.map +1 -0
- package/dist-lib/components/ui/Checkbox.js +70 -0
- package/dist-lib/components/ui/Checkbox.js.map +1 -0
- package/dist-lib/components/ui/Combobox.d.ts +9 -0
- package/dist-lib/components/ui/Combobox.js +195 -0
- package/dist-lib/components/ui/Combobox.js.map +1 -0
- package/dist-lib/components/ui/CommandPalette.d.ts +9 -6
- package/dist-lib/components/ui/CommandPalette.js +179 -0
- package/dist-lib/components/ui/CommandPalette.js.map +1 -0
- package/dist-lib/components/ui/ContextMenu.d.ts +7 -2
- package/dist-lib/components/ui/ContextMenu.js +165 -0
- package/dist-lib/components/ui/ContextMenu.js.map +1 -0
- package/dist-lib/components/ui/DataGrid.d.ts +17 -4
- package/dist-lib/components/ui/DataGrid.js +99 -0
- package/dist-lib/components/ui/DataGrid.js.map +1 -0
- package/dist-lib/components/ui/DatePicker.d.ts +16 -13
- package/dist-lib/components/ui/DatePicker.js +193 -0
- package/dist-lib/components/ui/DatePicker.js.map +1 -0
- package/dist-lib/components/ui/DesignSystemProvider.d.ts +102 -41
- package/dist-lib/components/ui/DesignSystemProvider.js +135 -0
- package/dist-lib/components/ui/DesignSystemProvider.js.map +1 -0
- package/dist-lib/components/ui/Dialog.d.ts +19 -4
- package/dist-lib/components/ui/Dialog.js +165 -0
- package/dist-lib/components/ui/Dialog.js.map +1 -0
- package/dist-lib/components/ui/Drawer.d.ts +23 -2
- package/dist-lib/components/ui/Drawer.js +132 -0
- package/dist-lib/components/ui/Drawer.js.map +1 -0
- package/dist-lib/components/ui/DropdownMenu.js +169 -0
- package/dist-lib/components/ui/DropdownMenu.js.map +1 -0
- package/dist-lib/components/ui/EmptyState.d.ts +2 -0
- package/dist-lib/components/ui/EmptyState.js +46 -0
- package/dist-lib/components/ui/EmptyState.js.map +1 -0
- package/dist-lib/components/ui/ErrorState.d.ts +13 -2
- package/dist-lib/components/ui/ErrorState.js +69 -0
- package/dist-lib/components/ui/ErrorState.js.map +1 -0
- package/dist-lib/components/ui/FileUpload.d.ts +3 -0
- package/dist-lib/components/ui/FileUpload.js +111 -0
- package/dist-lib/components/ui/FileUpload.js.map +1 -0
- package/dist-lib/components/ui/Form.d.ts +16 -2
- package/dist-lib/components/ui/Form.js +131 -0
- package/dist-lib/components/ui/Form.js.map +1 -0
- package/dist-lib/components/ui/Icon.d.ts +1 -1
- package/dist-lib/components/ui/Icon.js +32 -0
- package/dist-lib/components/ui/Icon.js.map +1 -0
- package/dist-lib/components/ui/IconButton.d.ts +3 -3
- package/dist-lib/components/ui/IconButton.js +64 -0
- package/dist-lib/components/ui/IconButton.js.map +1 -0
- package/dist-lib/components/ui/Input.d.ts +9 -4
- package/dist-lib/components/ui/Input.js +149 -0
- package/dist-lib/components/ui/Input.js.map +1 -0
- package/dist-lib/components/ui/Kbd.js +24 -0
- package/dist-lib/components/ui/Kbd.js.map +1 -0
- package/dist-lib/components/ui/MultiSelect.d.ts +3 -1
- package/dist-lib/components/ui/MultiSelect.js +210 -0
- package/dist-lib/components/ui/MultiSelect.js.map +1 -0
- package/dist-lib/components/ui/Pagination.d.ts +23 -0
- package/dist-lib/components/ui/Pagination.js +153 -0
- package/dist-lib/components/ui/Pagination.js.map +1 -0
- package/dist-lib/components/ui/Popover.js +35 -0
- package/dist-lib/components/ui/Popover.js.map +1 -0
- package/dist-lib/components/ui/Progress.d.ts +3 -3
- package/dist-lib/components/ui/Progress.js +100 -0
- package/dist-lib/components/ui/Progress.js.map +1 -0
- package/dist-lib/components/ui/RadioGroup.d.ts +1 -1
- package/dist-lib/components/ui/RadioGroup.js +81 -0
- package/dist-lib/components/ui/RadioGroup.js.map +1 -0
- package/dist-lib/components/ui/RelativeTime.d.ts +19 -0
- package/dist-lib/components/ui/RelativeTime.js +31 -0
- package/dist-lib/components/ui/RelativeTime.js.map +1 -0
- package/dist-lib/components/ui/ScrollArea.d.ts +9 -1
- package/dist-lib/components/ui/ScrollArea.js +60 -0
- package/dist-lib/components/ui/ScrollArea.js.map +1 -0
- package/dist-lib/components/ui/Select.d.ts +6 -1
- package/dist-lib/components/ui/Select.js +139 -0
- package/dist-lib/components/ui/Select.js.map +1 -0
- package/dist-lib/components/ui/Separator.js +26 -0
- package/dist-lib/components/ui/Separator.js.map +1 -0
- package/dist-lib/components/ui/Sheet.d.ts +10 -1
- package/dist-lib/components/ui/Sheet.js +136 -0
- package/dist-lib/components/ui/Sheet.js.map +1 -0
- package/dist-lib/components/ui/Sidebar.d.ts +29 -14
- package/dist-lib/components/ui/Sidebar.js +212 -0
- package/dist-lib/components/ui/Sidebar.js.map +1 -0
- package/dist-lib/components/ui/Skeleton.d.ts +13 -2
- package/dist-lib/components/ui/Skeleton.js +29 -0
- package/dist-lib/components/ui/Skeleton.js.map +1 -0
- package/dist-lib/components/ui/Slider.js +64 -0
- package/dist-lib/components/ui/Slider.js.map +1 -0
- package/dist-lib/components/ui/Snackbar.d.ts +1 -1
- package/dist-lib/components/ui/Snackbar.js +57 -0
- package/dist-lib/components/ui/Snackbar.js.map +1 -0
- package/dist-lib/components/ui/Spinner.js +54 -0
- package/dist-lib/components/ui/Spinner.js.map +1 -0
- package/dist-lib/components/ui/Stepper.d.ts +6 -0
- package/dist-lib/components/ui/Stepper.js +111 -0
- package/dist-lib/components/ui/Stepper.js.map +1 -0
- package/dist-lib/components/ui/Switch.js +80 -0
- package/dist-lib/components/ui/Switch.js.map +1 -0
- package/dist-lib/components/ui/Table.d.ts +41 -5
- package/dist-lib/components/ui/Table.js +179 -0
- package/dist-lib/components/ui/Table.js.map +1 -0
- package/dist-lib/components/ui/Tabs.d.ts +1 -1
- package/dist-lib/components/ui/Tabs.js +91 -0
- package/dist-lib/components/ui/Tabs.js.map +1 -0
- package/dist-lib/components/ui/TagInput.d.ts +17 -2
- package/dist-lib/components/ui/TagInput.js +111 -0
- package/dist-lib/components/ui/TagInput.js.map +1 -0
- package/dist-lib/components/ui/Textarea.js +88 -0
- package/dist-lib/components/ui/Textarea.js.map +1 -0
- package/dist-lib/components/ui/Timeline.d.ts +16 -6
- package/dist-lib/components/ui/Timeline.js +56 -0
- package/dist-lib/components/ui/Timeline.js.map +1 -0
- package/dist-lib/components/ui/Toast.d.ts +1 -1
- package/dist-lib/components/ui/Toast.js +158 -0
- package/dist-lib/components/ui/Toast.js.map +1 -0
- package/dist-lib/components/ui/Tooltip.d.ts +4 -1
- package/dist-lib/components/ui/Tooltip.js +60 -0
- package/dist-lib/components/ui/Tooltip.js.map +1 -0
- package/dist-lib/components/ui/TopNav.d.ts +7 -3
- package/dist-lib/components/ui/TopNav.js +62 -0
- package/dist-lib/components/ui/TopNav.js.map +1 -0
- package/dist-lib/components/ui/Tree.d.ts +34 -7
- package/dist-lib/components/ui/Tree.js +170 -0
- package/dist-lib/components/ui/Tree.js.map +1 -0
- package/dist-lib/hooks/use-debounce.d.ts +19 -0
- package/dist-lib/hooks/use-debounce.js +36 -0
- package/dist-lib/hooks/use-debounce.js.map +1 -0
- package/dist-lib/hooks/use-delayed-loading.d.ts +21 -0
- package/dist-lib/hooks/use-delayed-loading.js +20 -0
- package/dist-lib/hooks/use-delayed-loading.js.map +1 -0
- package/dist-lib/hooks/use-field-ids.d.ts +30 -0
- package/dist-lib/hooks/use-field-ids.js +18 -0
- package/dist-lib/hooks/use-field-ids.js.map +1 -0
- package/dist-lib/hooks/use-media-query.d.ts +3 -1
- package/dist-lib/hooks/use-media-query.js +22 -0
- package/dist-lib/hooks/use-media-query.js.map +1 -0
- package/dist-lib/hooks/use-modifier-key.d.ts +13 -0
- package/dist-lib/hooks/use-modifier-key.js +19 -0
- package/dist-lib/hooks/use-modifier-key.js.map +1 -0
- package/dist-lib/hooks/use-strings.d.ts +5 -0
- package/dist-lib/hooks/use-strings.js +12 -0
- package/dist-lib/hooks/use-strings.js.map +1 -0
- package/dist-lib/hooks/use-toast.d.ts +7 -2
- package/dist-lib/hooks/use-toast.js +67 -0
- package/dist-lib/hooks/use-toast.js.map +1 -0
- package/dist-lib/icon.d.ts +8 -0
- package/dist-lib/icon.js +7 -0
- package/dist-lib/icon.js.map +1 -0
- package/dist-lib/icons/index.d.ts +80 -88
- package/dist-lib/icons/index.js +163 -0
- package/dist-lib/icons/index.js.map +1 -0
- package/dist-lib/illustrations/index.d.ts +1 -0
- package/dist-lib/illustrations/index.js +114 -0
- package/dist-lib/illustrations/index.js.map +1 -0
- package/dist-lib/index.d.ts +68 -59
- package/dist-lib/index.js +288 -4530
- package/dist-lib/index.js.map +1 -1
- package/dist-lib/lib/format.d.ts +65 -0
- package/dist-lib/lib/format.js +95 -0
- package/dist-lib/lib/format.js.map +1 -0
- package/dist-lib/lib/return-focus.d.ts +11 -0
- package/dist-lib/lib/return-focus.js +12 -0
- package/dist-lib/lib/return-focus.js.map +1 -0
- package/dist-lib/lib/strings.d.ts +190 -0
- package/dist-lib/lib/strings.js +141 -0
- package/dist-lib/lib/strings.js.map +1 -0
- package/dist-lib/lib/strings.mn.d.ts +3 -0
- package/dist-lib/lib/strings.mn.js +115 -0
- package/dist-lib/lib/strings.mn.js.map +1 -0
- package/dist-lib/lib/utils.d.ts +0 -1
- package/dist-lib/lib/utils.js +10 -0
- package/dist-lib/lib/utils.js.map +1 -0
- package/dist-lib/styles.css +1 -1
- package/dist-lib/theme.css +840 -0
- package/package.json +38 -8
- package/dist-lib/index.cjs +0 -8
- package/dist-lib/index.cjs.map +0 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef as b } from "react";
|
|
4
|
+
import { Check as h } from "../../icons/index.js";
|
|
5
|
+
import { cn as e } from "../../lib/utils.js";
|
|
6
|
+
import { useStrings as N } from "../../hooks/use-strings.js";
|
|
7
|
+
const z = b(function({
|
|
8
|
+
steps: i,
|
|
9
|
+
current: a,
|
|
10
|
+
orientation: t = "horizontal",
|
|
11
|
+
stateLabels: p,
|
|
12
|
+
className: d,
|
|
13
|
+
"aria-label": f,
|
|
14
|
+
...x
|
|
15
|
+
}, u) {
|
|
16
|
+
const n = N(), g = p ?? {
|
|
17
|
+
complete: n.stepper.complete,
|
|
18
|
+
current: n.stepper.current,
|
|
19
|
+
upcoming: n.stepper.upcoming
|
|
20
|
+
};
|
|
21
|
+
return /* @__PURE__ */ s(
|
|
22
|
+
"ol",
|
|
23
|
+
{
|
|
24
|
+
ref: u,
|
|
25
|
+
"aria-label": f ?? n.stepper.label,
|
|
26
|
+
className: e(
|
|
27
|
+
t === "horizontal" ? "flex w-full items-center" : "flex flex-col gap-6",
|
|
28
|
+
d
|
|
29
|
+
),
|
|
30
|
+
...x,
|
|
31
|
+
children: i.map((o, r) => {
|
|
32
|
+
const l = r < a ? "complete" : r === a ? "current" : "upcoming", m = r === i.length - 1;
|
|
33
|
+
return /* @__PURE__ */ c(
|
|
34
|
+
"li",
|
|
35
|
+
{
|
|
36
|
+
"aria-current": l === "current" ? "step" : void 0,
|
|
37
|
+
className: e(
|
|
38
|
+
t === "horizontal" ? "flex flex-1 items-center gap-3 last:flex-initial" : "flex items-start gap-3"
|
|
39
|
+
),
|
|
40
|
+
children: [
|
|
41
|
+
/* @__PURE__ */ c(
|
|
42
|
+
"div",
|
|
43
|
+
{
|
|
44
|
+
className: e(
|
|
45
|
+
t === "horizontal" ? "flex items-center gap-3" : "flex flex-col items-center"
|
|
46
|
+
),
|
|
47
|
+
children: [
|
|
48
|
+
/* @__PURE__ */ s(
|
|
49
|
+
"span",
|
|
50
|
+
{
|
|
51
|
+
"aria-hidden": !0,
|
|
52
|
+
className: e(
|
|
53
|
+
"inline-flex size-7 items-center justify-center rounded-full text-xs font-semibold transition-colors",
|
|
54
|
+
l === "complete" && "bg-accent text-on-accent",
|
|
55
|
+
l === "current" && "bg-card border-accent text-accent border-2",
|
|
56
|
+
l === "upcoming" && "bg-background-muted text-foreground-subtle border-border border"
|
|
57
|
+
),
|
|
58
|
+
children: l === "complete" ? /* @__PURE__ */ s(h, { className: "size-4" }) : r + 1
|
|
59
|
+
}
|
|
60
|
+
),
|
|
61
|
+
t === "vertical" && !m && /* @__PURE__ */ s(
|
|
62
|
+
"span",
|
|
63
|
+
{
|
|
64
|
+
className: e(
|
|
65
|
+
"mt-1 min-h-6 w-px flex-1",
|
|
66
|
+
r < a ? "bg-accent" : "bg-border"
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
/* @__PURE__ */ c("div", { className: e("flex flex-col", t === "horizontal" && "min-w-0"), children: [
|
|
74
|
+
/* @__PURE__ */ c(
|
|
75
|
+
"span",
|
|
76
|
+
{
|
|
77
|
+
className: e(
|
|
78
|
+
"text-sm font-medium",
|
|
79
|
+
l === "upcoming" ? "text-foreground-subtle" : "text-foreground"
|
|
80
|
+
),
|
|
81
|
+
children: [
|
|
82
|
+
o.title,
|
|
83
|
+
/* @__PURE__ */ c("span", { className: "sr-only", children: [
|
|
84
|
+
", ",
|
|
85
|
+
g[l]
|
|
86
|
+
] })
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
),
|
|
90
|
+
t === "vertical" && o.description && /* @__PURE__ */ s("p", { className: "text-foreground-muted mt-0.5 text-xs", children: o.description })
|
|
91
|
+
] }),
|
|
92
|
+
t === "horizontal" && !m && /* @__PURE__ */ s(
|
|
93
|
+
"span",
|
|
94
|
+
{
|
|
95
|
+
"aria-hidden": !0,
|
|
96
|
+
className: e("mx-2 h-px flex-1", r < a ? "bg-accent" : "bg-border")
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
r
|
|
102
|
+
);
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
z.displayName = "Stepper";
|
|
108
|
+
export {
|
|
109
|
+
z as Stepper
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=Stepper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Stepper.js","sources":["../../../src/components/ui/Stepper.tsx"],"sourcesContent":["'use client';\n\nimport { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { Check } from '@/icons';\nimport { cn } from '@/lib/utils';\nimport { useStrings } from '@/hooks/use-strings';\n\nexport interface Step {\n /** Step heading. */\n title: ReactNode;\n /** Optional secondary description, only shown in vertical orientation. */\n description?: ReactNode;\n}\n\nexport interface StepperProps extends HTMLAttributes<HTMLOListElement> {\n /** Ordered list of steps. */\n steps: Step[];\n /** 0-indexed active step. Steps before it are marked complete. */\n current: number;\n /** Layout direction. */\n orientation?: 'horizontal' | 'vertical';\n /** sr-only state words announced after each title (i18n). */\n stateLabels?: { complete: string; current: string; upcoming: string };\n}\n\n/**\n * Multi-step progress indicator. Use the horizontal variant in narrow flows\n * (top of an onboarding modal) and vertical for deeper context.\n *\n * @example Onboarding\n * <Stepper\n * current={step}\n * steps={[\n * { title: 'Workspace' },\n * { title: 'Invite team' },\n * { title: 'Connect data' },\n * { title: 'Done' },\n * ]}\n * />\n *\n * @do Keep titles 1–2 words. Save explanations for the page body.\n * @dont Use Stepper for free-form navigation. It implies a linear flow.\n */\nexport const Stepper = forwardRef<HTMLOListElement, StepperProps>(function Stepper(\n {\n steps,\n current,\n orientation = 'horizontal',\n stateLabels: stateLabelsProp,\n className,\n 'aria-label': ariaLabel,\n ...props\n },\n ref,\n) {\n const strings = useStrings();\n const stateLabels = stateLabelsProp ?? {\n complete: strings.stepper.complete,\n current: strings.stepper.current,\n upcoming: strings.stepper.upcoming,\n };\n return (\n <ol\n ref={ref}\n aria-label={ariaLabel ?? strings.stepper.label}\n className={cn(\n orientation === 'horizontal' ? 'flex w-full items-center' : 'flex flex-col gap-6',\n className,\n )}\n {...props}\n >\n {steps.map((step, i) => {\n const state = i < current ? 'complete' : i === current ? 'current' : 'upcoming';\n const isLast = i === steps.length - 1;\n return (\n <li\n key={i}\n aria-current={state === 'current' ? 'step' : undefined}\n className={cn(\n orientation === 'horizontal'\n ? 'flex flex-1 items-center gap-3 last:flex-initial'\n : 'flex items-start gap-3',\n )}\n >\n <div\n className={cn(\n orientation === 'horizontal'\n ? 'flex items-center gap-3'\n : 'flex flex-col items-center',\n )}\n >\n <span\n aria-hidden\n className={cn(\n 'inline-flex size-7 items-center justify-center rounded-full text-xs font-semibold transition-colors',\n state === 'complete' && 'bg-accent text-on-accent',\n state === 'current' && 'bg-card border-accent text-accent border-2',\n state === 'upcoming' &&\n 'bg-background-muted text-foreground-subtle border-border border',\n )}\n >\n {state === 'complete' ? <Check className=\"size-4\" /> : i + 1}\n </span>\n {orientation === 'vertical' && !isLast && (\n <span\n className={cn(\n 'mt-1 min-h-6 w-px flex-1',\n i < current ? 'bg-accent' : 'bg-border',\n )}\n />\n )}\n </div>\n <div className={cn('flex flex-col', orientation === 'horizontal' && 'min-w-0')}>\n <span\n className={cn(\n 'text-sm font-medium',\n state === 'upcoming' ? 'text-foreground-subtle' : 'text-foreground',\n )}\n >\n {step.title}\n <span className=\"sr-only\">, {stateLabels[state]}</span>\n </span>\n {orientation === 'vertical' && step.description && (\n <p className=\"text-foreground-muted mt-0.5 text-xs\">{step.description}</p>\n )}\n </div>\n {orientation === 'horizontal' && !isLast && (\n <span\n aria-hidden\n className={cn('mx-2 h-px flex-1', i < current ? 'bg-accent' : 'bg-border')}\n />\n )}\n </li>\n );\n })}\n </ol>\n );\n});\nStepper.displayName = 'Stepper';\n"],"names":["Stepper","forwardRef","steps","current","orientation","stateLabelsProp","className","ariaLabel","props","ref","strings","useStrings","stateLabels","jsx","cn","step","i","state","isLast","jsxs","Check"],"mappings":";;;;;;AA2CO,MAAMA,IAAUC,EAA2C,SAChE;AAAA,EACE,OAAAC;AAAA,EACA,SAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,aAAaC;AAAA,EACb,WAAAC;AAAA,EACA,cAAcC;AAAA,EACd,GAAGC;AACL,GACAC,GACA;AACA,QAAMC,IAAUC,EAAA,GACVC,IAAcP,KAAmB;AAAA,IACrC,UAAUK,EAAQ,QAAQ;AAAA,IAC1B,SAASA,EAAQ,QAAQ;AAAA,IACzB,UAAUA,EAAQ,QAAQ;AAAA,EAAA;AAE5B,SACE,gBAAAG;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAJ;AAAA,MACA,cAAYF,KAAaG,EAAQ,QAAQ;AAAA,MACzC,WAAWI;AAAA,QACTV,MAAgB,eAAe,6BAA6B;AAAA,QAC5DE;AAAA,MAAA;AAAA,MAED,GAAGE;AAAA,MAEH,UAAAN,EAAM,IAAI,CAACa,GAAMC,MAAM;AACtB,cAAMC,IAAQD,IAAIb,IAAU,aAAaa,MAAMb,IAAU,YAAY,YAC/De,IAASF,MAAMd,EAAM,SAAS;AACpC,eACE,gBAAAiB;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,gBAAcF,MAAU,YAAY,SAAS;AAAA,YAC7C,WAAWH;AAAA,cACTV,MAAgB,eACZ,qDACA;AAAA,YAAA;AAAA,YAGN,UAAA;AAAA,cAAA,gBAAAe;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAWL;AAAA,oBACTV,MAAgB,eACZ,4BACA;AAAA,kBAAA;AAAA,kBAGN,UAAA;AAAA,oBAAA,gBAAAS;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,eAAW;AAAA,wBACX,WAAWC;AAAA,0BACT;AAAA,0BACAG,MAAU,cAAc;AAAA,0BACxBA,MAAU,aAAa;AAAA,0BACvBA,MAAU,cACR;AAAA,wBAAA;AAAA,wBAGH,gBAAU,aAAa,gBAAAJ,EAACO,KAAM,WAAU,UAAS,IAAKJ,IAAI;AAAA,sBAAA;AAAA,oBAAA;AAAA,oBAE5DZ,MAAgB,cAAc,CAACc,KAC9B,gBAAAL;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,WAAWC;AAAA,0BACT;AAAA,0BACAE,IAAIb,IAAU,cAAc;AAAA,wBAAA;AAAA,sBAC9B;AAAA,oBAAA;AAAA,kBACF;AAAA,gBAAA;AAAA,cAAA;AAAA,cAGJ,gBAAAgB,EAAC,SAAI,WAAWL,EAAG,iBAAiBV,MAAgB,gBAAgB,SAAS,GAC3E,UAAA;AAAA,gBAAA,gBAAAe;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAWL;AAAA,sBACT;AAAA,sBACAG,MAAU,aAAa,2BAA2B;AAAA,oBAAA;AAAA,oBAGnD,UAAA;AAAA,sBAAAF,EAAK;AAAA,sBACN,gBAAAI,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA;AAAA,wBAAA;AAAA,wBAAGP,EAAYK,CAAK;AAAA,sBAAA,EAAA,CAAE;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEjDb,MAAgB,cAAcW,EAAK,iCACjC,KAAA,EAAE,WAAU,wCAAwC,UAAAA,EAAK,YAAA,CAAY;AAAA,cAAA,GAE1E;AAAA,cACCX,MAAgB,gBAAgB,CAACc,KAChC,gBAAAL;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,eAAW;AAAA,kBACX,WAAWC,EAAG,oBAAoBE,IAAIb,IAAU,cAAc,WAAW;AAAA,gBAAA;AAAA,cAAA;AAAA,YAC3E;AAAA,UAAA;AAAA,UAtDGa;AAAA,QAAA;AAAA,MA0DX,CAAC;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC;AACDhB,EAAQ,cAAc;"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as e, jsxs as l } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef as k, useId as y } from "react";
|
|
4
|
+
import * as f from "@radix-ui/react-switch";
|
|
5
|
+
import { cn as t } from "../../lib/utils.js";
|
|
6
|
+
const N = {
|
|
7
|
+
sm: 'h-4 w-7 before:absolute before:-inset-x-1 before:-inset-y-1.5 before:content-[""]',
|
|
8
|
+
md: 'h-5 w-9 before:absolute before:-inset-x-1 before:-inset-y-1 before:content-[""]'
|
|
9
|
+
}, S = {
|
|
10
|
+
sm: "size-3 data-[state=checked]:translate-x-3",
|
|
11
|
+
md: "size-4 data-[state=checked]:translate-x-4"
|
|
12
|
+
}, I = k(
|
|
13
|
+
function({
|
|
14
|
+
className: b,
|
|
15
|
+
label: a,
|
|
16
|
+
description: r,
|
|
17
|
+
labelPosition: s = "after",
|
|
18
|
+
size: i = "md",
|
|
19
|
+
hideLabel: u,
|
|
20
|
+
id: m,
|
|
21
|
+
disabled: n,
|
|
22
|
+
"aria-describedby": h,
|
|
23
|
+
...v
|
|
24
|
+
}, x) {
|
|
25
|
+
const g = y(), o = m ?? g, c = r ? `${o}-desc` : void 0, p = [c, h].filter(Boolean).join(" ") || void 0, w = /* @__PURE__ */ e(
|
|
26
|
+
f.Root,
|
|
27
|
+
{
|
|
28
|
+
ref: x,
|
|
29
|
+
id: o,
|
|
30
|
+
disabled: n,
|
|
31
|
+
"aria-describedby": p,
|
|
32
|
+
className: t(
|
|
33
|
+
"peer relative inline-flex shrink-0 items-center rounded-full border-2 border-transparent",
|
|
34
|
+
"transition-colors duration-[var(--duration-base)] ease-[var(--ease-out)]",
|
|
35
|
+
"focus-visible:ring-ring focus-visible:ring-offset-background outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
|
36
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
37
|
+
"data-[state=checked]:bg-accent data-[state=unchecked]:bg-switch-track-off",
|
|
38
|
+
"aria-invalid:ring-danger aria-invalid:ring-2",
|
|
39
|
+
N[i]
|
|
40
|
+
),
|
|
41
|
+
...v,
|
|
42
|
+
children: /* @__PURE__ */ e(
|
|
43
|
+
f.Thumb,
|
|
44
|
+
{
|
|
45
|
+
className: t(
|
|
46
|
+
"bg-switch-thumb pointer-events-none block rounded-full shadow-sm",
|
|
47
|
+
"transition-transform duration-[var(--duration-base)] ease-[var(--ease-out)]",
|
|
48
|
+
"translate-x-0",
|
|
49
|
+
S[i]
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
), d = a && /* @__PURE__ */ l("div", { className: "flex flex-col gap-0.5 select-none", children: [
|
|
55
|
+
/* @__PURE__ */ e(
|
|
56
|
+
"label",
|
|
57
|
+
{
|
|
58
|
+
htmlFor: o,
|
|
59
|
+
className: t(
|
|
60
|
+
"text-foreground text-sm",
|
|
61
|
+
n && "cursor-not-allowed opacity-50",
|
|
62
|
+
u && "sr-only"
|
|
63
|
+
),
|
|
64
|
+
children: a
|
|
65
|
+
}
|
|
66
|
+
),
|
|
67
|
+
r && /* @__PURE__ */ e("p", { id: c, className: "text-foreground-subtle text-xs", children: r })
|
|
68
|
+
] });
|
|
69
|
+
return /* @__PURE__ */ l("div", { className: t("inline-flex items-center gap-2.5", b), children: [
|
|
70
|
+
s === "before" && d,
|
|
71
|
+
w,
|
|
72
|
+
s === "after" && d
|
|
73
|
+
] });
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
I.displayName = "Switch";
|
|
77
|
+
export {
|
|
78
|
+
I as Switch
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=Switch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Switch.js","sources":["../../../src/components/ui/Switch.tsx"],"sourcesContent":["'use client';\n\nimport {\n forwardRef,\n useId,\n type ComponentPropsWithoutRef,\n type ElementRef,\n type ReactNode,\n} from 'react';\nimport * as SwitchPrimitive from '@radix-ui/react-switch';\nimport { cn } from '@/lib/utils';\n\nexport interface SwitchProps extends Omit<\n ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>,\n 'asChild'\n> {\n /** Inline label rendered to the right. */\n label?: ReactNode;\n /** Secondary description rendered below the label. */\n description?: ReactNode;\n /** Position the label before the switch instead of after. */\n labelPosition?: 'before' | 'after';\n /** Visual size. */\n size?: 'sm' | 'md';\n /** Hide the label visually while keeping it accessible. */\n hideLabel?: boolean;\n}\n\n// Tracks are 28×16 (`sm`) / 36×20 (`md`) visually; the `before:` halo lifts\n// the hit area to ≥24px tall without changing the drawing (WCAG 2.5.8).\nconst trackSize = {\n sm: 'h-4 w-7 before:absolute before:-inset-x-1 before:-inset-y-1.5 before:content-[\"\"]',\n md: 'h-5 w-9 before:absolute before:-inset-x-1 before:-inset-y-1 before:content-[\"\"]',\n} as const;\nconst thumbSize = {\n sm: 'size-3 data-[state=checked]:translate-x-3',\n md: 'size-4 data-[state=checked]:translate-x-4',\n} as const;\n\n/**\n * Binary on/off toggle for instant-apply settings. Use Checkbox when the\n * choice is part of a form that needs explicit submission.\n *\n * @example Instant toggle\n * <Switch label=\"Email digest\" checked={on} onCheckedChange={setOn} />\n *\n * @example With description\n * <Switch label=\"Two-factor authentication\"\n * description=\"Required for admins on production accounts.\"\n * checked={tfa}\n * onCheckedChange={setTfa} />\n *\n * @do Use Switch when the change takes effect immediately. Pair with\n * a toast confirming the new state.\n * @dont Use Switch inside a form that requires submission — Checkbox\n * better matches that mental model.\n */\nexport const Switch = forwardRef<ElementRef<typeof SwitchPrimitive.Root>, SwitchProps>(\n function Switch(\n {\n className,\n label,\n description,\n labelPosition = 'after',\n size = 'md',\n hideLabel,\n id,\n disabled,\n 'aria-describedby': ariaDescribedby,\n ...props\n },\n ref,\n ) {\n const autoId = useId();\n const fieldId = id ?? autoId;\n const descId = description ? `${fieldId}-desc` : undefined;\n const describedBy = [descId, ariaDescribedby].filter(Boolean).join(' ') || undefined;\n\n const control = (\n <SwitchPrimitive.Root\n ref={ref}\n id={fieldId}\n disabled={disabled}\n aria-describedby={describedBy}\n className={cn(\n 'peer relative inline-flex shrink-0 items-center rounded-full border-2 border-transparent',\n 'transition-colors duration-[var(--duration-base)] ease-[var(--ease-out)]',\n 'focus-visible:ring-ring focus-visible:ring-offset-background outline-none focus-visible:ring-2 focus-visible:ring-offset-2',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n 'data-[state=checked]:bg-accent data-[state=unchecked]:bg-switch-track-off',\n 'aria-invalid:ring-danger aria-invalid:ring-2',\n trackSize[size],\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n className={cn(\n 'bg-switch-thumb pointer-events-none block rounded-full shadow-sm',\n 'transition-transform duration-[var(--duration-base)] ease-[var(--ease-out)]',\n 'translate-x-0',\n thumbSize[size],\n )}\n />\n </SwitchPrimitive.Root>\n );\n\n const labelBlock = label && (\n <div className=\"flex flex-col gap-0.5 select-none\">\n <label\n htmlFor={fieldId}\n className={cn(\n 'text-foreground text-sm',\n disabled && 'cursor-not-allowed opacity-50',\n hideLabel && 'sr-only',\n )}\n >\n {label}\n </label>\n {description && (\n <p id={descId} className=\"text-foreground-subtle text-xs\">\n {description}\n </p>\n )}\n </div>\n );\n\n return (\n <div className={cn('inline-flex items-center gap-2.5', className)}>\n {labelPosition === 'before' && labelBlock}\n {control}\n {labelPosition === 'after' && labelBlock}\n </div>\n );\n },\n);\n\nSwitch.displayName = 'Switch';\n"],"names":["trackSize","thumbSize","Switch","forwardRef","className","label","description","labelPosition","size","hideLabel","id","disabled","ariaDescribedby","props","ref","autoId","useId","fieldId","descId","describedBy","control","jsx","SwitchPrimitive","cn","labelBlock","jsxs"],"mappings":";;;;;AA8BA,MAAMA,IAAY;AAAA,EAChB,IAAI;AAAA,EACJ,IAAI;AACN,GACMC,IAAY;AAAA,EAChB,IAAI;AAAA,EACJ,IAAI;AACN,GAoBaC,IAASC;AAAA,EACpB,SACE;AAAA,IACE,WAAAC;AAAA,IACA,OAAAC;AAAA,IACA,aAAAC;AAAA,IACA,eAAAC,IAAgB;AAAA,IAChB,MAAAC,IAAO;AAAA,IACP,WAAAC;AAAA,IACA,IAAAC;AAAA,IACA,UAAAC;AAAA,IACA,oBAAoBC;AAAA,IACpB,GAAGC;AAAA,EAAA,GAELC,GACA;AACA,UAAMC,IAASC,EAAA,GACTC,IAAUP,KAAMK,GAChBG,IAASZ,IAAc,GAAGW,CAAO,UAAU,QAC3CE,IAAc,CAACD,GAAQN,CAAe,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,KAAK,QAErEQ,IACJ,gBAAAC;AAAA,MAACC,EAAgB;AAAA,MAAhB;AAAA,QACC,KAAAR;AAAA,QACA,IAAIG;AAAA,QACJ,UAAAN;AAAA,QACA,oBAAkBQ;AAAA,QAClB,WAAWI;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACAvB,EAAUQ,CAAI;AAAA,QAAA;AAAA,QAEf,GAAGK;AAAA,QAEJ,UAAA,gBAAAQ;AAAA,UAACC,EAAgB;AAAA,UAAhB;AAAA,YACC,WAAWC;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,cACAtB,EAAUO,CAAI;AAAA,YAAA;AAAA,UAChB;AAAA,QAAA;AAAA,MACF;AAAA,IAAA,GAIEgB,IAAanB,KACjB,gBAAAoB,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,MAAA,gBAAAJ;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAASJ;AAAA,UACT,WAAWM;AAAA,YACT;AAAA,YACAZ,KAAY;AAAA,YACZF,KAAa;AAAA,UAAA;AAAA,UAGd,UAAAJ;AAAA,QAAA;AAAA,MAAA;AAAA,MAEFC,KACC,gBAAAe,EAAC,KAAA,EAAE,IAAIH,GAAQ,WAAU,kCACtB,UAAAZ,EAAA,CACH;AAAA,IAAA,GAEJ;AAGF,6BACG,OAAA,EAAI,WAAWiB,EAAG,oCAAoCnB,CAAS,GAC7D,UAAA;AAAA,MAAAG,MAAkB,YAAYiB;AAAA,MAC9BJ;AAAA,MACAb,MAAkB,WAAWiB;AAAA,IAAA,GAChC;AAAA,EAEJ;AACF;AAEAtB,EAAO,cAAc;"}
|
|
@@ -1,15 +1,51 @@
|
|
|
1
|
-
import { HTMLAttributes, ThHTMLAttributes, TdHTMLAttributes } from 'react';
|
|
2
|
-
export
|
|
1
|
+
import { CSSProperties, HTMLAttributes, ThHTMLAttributes, TdHTMLAttributes } from 'react';
|
|
2
|
+
export interface TableProps extends HTMLAttributes<HTMLTableElement> {
|
|
3
|
+
/** Class for the scroll wrapper (border, radius, height). */
|
|
4
|
+
containerClassName?: string;
|
|
5
|
+
/**
|
|
6
|
+
* Max height of the scroll wrapper. Required for the sticky header to
|
|
7
|
+
* work — `<thead>` sticks to the nearest scroll container, so a wrapper
|
|
8
|
+
* with no height cap never scrolls. e.g. `maxHeight="24rem"`.
|
|
9
|
+
*/
|
|
10
|
+
maxHeight?: CSSProperties['maxHeight'];
|
|
11
|
+
/**
|
|
12
|
+
* Accessible name of the scroll wrapper (it is a focusable `group` so
|
|
13
|
+
* keyboard users can scroll wide / capped tables). Defaults to
|
|
14
|
+
* `strings.table.scrollRegion`; pass the table's own title when you have one.
|
|
15
|
+
*/
|
|
16
|
+
scrollLabel?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const Table: import('react').ForwardRefExoticComponent<TableProps & import('react').RefAttributes<HTMLTableElement>>;
|
|
3
19
|
export declare const TableHeader: import('react').ForwardRefExoticComponent<HTMLAttributes<HTMLTableSectionElement> & import('react').RefAttributes<HTMLTableSectionElement>>;
|
|
4
20
|
export declare const TableBody: import('react').ForwardRefExoticComponent<HTMLAttributes<HTMLTableSectionElement> & import('react').RefAttributes<HTMLTableSectionElement>>;
|
|
5
21
|
export declare const TableFooter: import('react').ForwardRefExoticComponent<HTMLAttributes<HTMLTableSectionElement> & import('react').RefAttributes<HTMLTableSectionElement>>;
|
|
6
22
|
export declare const TableRow: import('react').ForwardRefExoticComponent<HTMLAttributes<HTMLTableRowElement> & {
|
|
23
|
+
/**
|
|
24
|
+
* Visual selected state (`data-state="selected"`). `aria-selected` is only
|
|
25
|
+
* valid on rows of an ARIA grid, so it is emitted only when the row
|
|
26
|
+
* carries `role="row"` (i.e. you opted into `role="grid"` on the table).
|
|
27
|
+
*/
|
|
7
28
|
selected?: boolean;
|
|
8
29
|
} & import('react').RefAttributes<HTMLTableRowElement>>;
|
|
9
|
-
export
|
|
10
|
-
export
|
|
30
|
+
export type TableCellAlign = 'left' | 'center' | 'right';
|
|
31
|
+
export interface TableHeadProps extends Omit<ThHTMLAttributes<HTMLTableCellElement>, 'align'> {
|
|
32
|
+
/** Horizontal alignment; `right` also applies tabular figures. */
|
|
33
|
+
align?: TableCellAlign;
|
|
34
|
+
/**
|
|
35
|
+
* Render the header label in small caps (`uppercase tracking-wide`).
|
|
36
|
+
* Off by default — mixed case reads better for long / Cyrillic labels.
|
|
37
|
+
* @default false
|
|
38
|
+
*/
|
|
39
|
+
uppercase?: boolean;
|
|
40
|
+
}
|
|
41
|
+
export declare const TableHead: import('react').ForwardRefExoticComponent<TableHeadProps & import('react').RefAttributes<HTMLTableCellElement>>;
|
|
42
|
+
export interface TableCellProps extends Omit<TdHTMLAttributes<HTMLTableCellElement>, 'align'> {
|
|
43
|
+
/** Horizontal alignment; `right` also applies tabular figures for numbers. */
|
|
44
|
+
align?: TableCellAlign;
|
|
45
|
+
}
|
|
46
|
+
export declare const TableCell: import('react').ForwardRefExoticComponent<TableCellProps & import('react').RefAttributes<HTMLTableCellElement>>;
|
|
11
47
|
export declare const TableCaption: import('react').ForwardRefExoticComponent<HTMLAttributes<HTMLTableCaptionElement> & import('react').RefAttributes<HTMLTableCaptionElement>>;
|
|
12
|
-
export interface TableSortHeaderProps extends
|
|
48
|
+
export interface TableSortHeaderProps extends TableHeadProps {
|
|
13
49
|
/** Stable column key used in `currentSort.key`. */
|
|
14
50
|
sortKey: string;
|
|
15
51
|
/** Currently sorted column + direction (or null). */
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as o, jsxs as T } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef as l } from "react";
|
|
4
|
+
import { ArrowUp as v, ArrowDown as x, ArrowUpDown as N } from "../../icons/index.js";
|
|
5
|
+
import { cn as r } from "../../lib/utils.js";
|
|
6
|
+
import { useStrings as h } from "../../hooks/use-strings.js";
|
|
7
|
+
const y = l(function({ className: t, containerClassName: e, maxHeight: a, scrollLabel: s, ...n }, d) {
|
|
8
|
+
const u = h();
|
|
9
|
+
return (
|
|
10
|
+
// Whether the wrapper actually overflows is not knowable statically, so it
|
|
11
|
+
// is always a tab stop (WCAG 2.1.1 / axe scrollable-region-focusable).
|
|
12
|
+
/* @__PURE__ */ o(
|
|
13
|
+
"div",
|
|
14
|
+
{
|
|
15
|
+
role: "group",
|
|
16
|
+
"aria-label": s ?? u.table.scrollRegion,
|
|
17
|
+
tabIndex: 0,
|
|
18
|
+
className: r(
|
|
19
|
+
"relative isolate w-full overflow-auto",
|
|
20
|
+
"focus-visible:ring-ring focus-visible:ring-offset-background outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
|
21
|
+
e
|
|
22
|
+
),
|
|
23
|
+
style: a !== void 0 ? { maxHeight: a } : void 0,
|
|
24
|
+
children: /* @__PURE__ */ o(
|
|
25
|
+
"table",
|
|
26
|
+
{
|
|
27
|
+
ref: d,
|
|
28
|
+
className: r("w-full caption-bottom border-collapse text-sm", t),
|
|
29
|
+
...n
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
y.displayName = "Table";
|
|
37
|
+
const w = l(function({ className: t, ...e }, a) {
|
|
38
|
+
return /* @__PURE__ */ o(
|
|
39
|
+
"thead",
|
|
40
|
+
{
|
|
41
|
+
ref: a,
|
|
42
|
+
className: r(
|
|
43
|
+
"bg-background-subtle text-foreground-muted sticky top-0 z-10",
|
|
44
|
+
"[&_tr]:border-border [&_tr]:border-b",
|
|
45
|
+
t
|
|
46
|
+
),
|
|
47
|
+
...e
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
w.displayName = "TableHeader";
|
|
52
|
+
const k = l(function({ className: t, ...e }, a) {
|
|
53
|
+
return /* @__PURE__ */ o("tbody", { ref: a, className: r("[&_tr:last-child]:border-0", t), ...e });
|
|
54
|
+
});
|
|
55
|
+
k.displayName = "TableBody";
|
|
56
|
+
const C = l(function({ className: t, ...e }, a) {
|
|
57
|
+
return /* @__PURE__ */ o(
|
|
58
|
+
"tfoot",
|
|
59
|
+
{
|
|
60
|
+
ref: a,
|
|
61
|
+
className: r("border-border bg-background-subtle border-t font-medium", t),
|
|
62
|
+
...e
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
C.displayName = "TableFooter";
|
|
67
|
+
const H = l(function({ className: t, selected: e, role: a, ...s }, n) {
|
|
68
|
+
return /* @__PURE__ */ o(
|
|
69
|
+
"tr",
|
|
70
|
+
{
|
|
71
|
+
ref: n,
|
|
72
|
+
role: a,
|
|
73
|
+
"data-state": e ? "selected" : void 0,
|
|
74
|
+
"aria-selected": e && a === "row" ? !0 : void 0,
|
|
75
|
+
className: r(
|
|
76
|
+
"border-border border-b transition-colors duration-[var(--duration-fast)]",
|
|
77
|
+
"hover:bg-background-subtle",
|
|
78
|
+
"data-[state=selected]:bg-accent-soft data-[state=selected]:hover:bg-accent-soft",
|
|
79
|
+
t
|
|
80
|
+
),
|
|
81
|
+
...s
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
H.displayName = "TableRow";
|
|
86
|
+
const f = {
|
|
87
|
+
left: "text-left",
|
|
88
|
+
center: "text-center",
|
|
89
|
+
/* Numeric columns: right-aligned + tabular figures so digits line up. */
|
|
90
|
+
right: "text-right tabular"
|
|
91
|
+
}, m = l(function({ className: t, uppercase: e = !1, align: a = "left", ...s }, n) {
|
|
92
|
+
return /* @__PURE__ */ o(
|
|
93
|
+
"th",
|
|
94
|
+
{
|
|
95
|
+
ref: n,
|
|
96
|
+
className: r(
|
|
97
|
+
"text-foreground-subtle h-10 px-3 align-middle text-xs font-medium",
|
|
98
|
+
f[a],
|
|
99
|
+
e && "tracking-wide uppercase",
|
|
100
|
+
"[&:has([role=checkbox])]:w-10 [&:has([role=checkbox])]:pr-0",
|
|
101
|
+
t
|
|
102
|
+
),
|
|
103
|
+
...s
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
m.displayName = "TableHead";
|
|
108
|
+
const R = l(function({ className: t, align: e = "left", ...a }, s) {
|
|
109
|
+
return /* @__PURE__ */ o(
|
|
110
|
+
"td",
|
|
111
|
+
{
|
|
112
|
+
ref: s,
|
|
113
|
+
className: r("text-foreground px-3 py-3 align-middle", f[e], t),
|
|
114
|
+
...a
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
});
|
|
118
|
+
R.displayName = "TableCell";
|
|
119
|
+
const z = l(function({ className: t, ...e }, a) {
|
|
120
|
+
return /* @__PURE__ */ o(
|
|
121
|
+
"caption",
|
|
122
|
+
{
|
|
123
|
+
ref: a,
|
|
124
|
+
className: r("text-foreground-subtle mt-4 text-sm", t),
|
|
125
|
+
...e
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
z.displayName = "TableCaption";
|
|
130
|
+
const j = l(
|
|
131
|
+
function({ sortKey: t, currentSort: e, onSortChange: a, children: s, className: n, align: d = "left", ...u }, g) {
|
|
132
|
+
const c = (e == null ? void 0 : e.key) === t, b = c ? e == null ? void 0 : e.direction : void 0, p = () => {
|
|
133
|
+
a(t, c && b === "asc" ? "desc" : "asc");
|
|
134
|
+
};
|
|
135
|
+
return /* @__PURE__ */ o(
|
|
136
|
+
m,
|
|
137
|
+
{
|
|
138
|
+
ref: g,
|
|
139
|
+
align: d,
|
|
140
|
+
className: r("p-0", n),
|
|
141
|
+
"aria-sort": c ? b === "asc" ? "ascending" : "descending" : void 0,
|
|
142
|
+
...u,
|
|
143
|
+
children: /* @__PURE__ */ T(
|
|
144
|
+
"button",
|
|
145
|
+
{
|
|
146
|
+
type: "button",
|
|
147
|
+
onClick: p,
|
|
148
|
+
className: r(
|
|
149
|
+
"inline-flex h-10 w-full items-center gap-1.5 px-3 outline-none",
|
|
150
|
+
d === "right" && "flex-row-reverse",
|
|
151
|
+
d === "center" && "justify-center",
|
|
152
|
+
"transition-colors duration-[var(--duration-fast)]",
|
|
153
|
+
"hover:text-foreground focus-visible:text-foreground",
|
|
154
|
+
"focus-visible:ring-ring focus-visible:ring-offset-background rounded-sm focus-visible:ring-2 focus-visible:ring-offset-2",
|
|
155
|
+
c && "text-foreground"
|
|
156
|
+
),
|
|
157
|
+
children: [
|
|
158
|
+
s,
|
|
159
|
+
b === "asc" ? /* @__PURE__ */ o(v, { className: "size-3.5", "aria-hidden": !0 }) : b === "desc" ? /* @__PURE__ */ o(x, { className: "size-3.5", "aria-hidden": !0 }) : /* @__PURE__ */ o(N, { className: "size-3.5 opacity-40", "aria-hidden": !0 })
|
|
160
|
+
]
|
|
161
|
+
}
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
j.displayName = "TableSortHeader";
|
|
168
|
+
export {
|
|
169
|
+
y as Table,
|
|
170
|
+
k as TableBody,
|
|
171
|
+
z as TableCaption,
|
|
172
|
+
R as TableCell,
|
|
173
|
+
C as TableFooter,
|
|
174
|
+
m as TableHead,
|
|
175
|
+
w as TableHeader,
|
|
176
|
+
H as TableRow,
|
|
177
|
+
j as TableSortHeader
|
|
178
|
+
};
|
|
179
|
+
//# sourceMappingURL=Table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Table.js","sources":["../../../src/components/ui/Table.tsx"],"sourcesContent":["'use client';\n\nimport {\n forwardRef,\n type CSSProperties,\n type HTMLAttributes,\n type ThHTMLAttributes,\n type TdHTMLAttributes,\n} from 'react';\nimport { ArrowDown, ArrowUp, ArrowUpDown } from '@/icons';\nimport { cn } from '@/lib/utils';\nimport { useStrings } from '@/hooks/use-strings';\n\n/* -----------------------------------------------------------------------------\n * Table primitives — minimal sugar over <table>. Pair with a sortable\n * header helper (`TableSortHeader`) when you need built-in sort visuals.\n * Empty + loading states are pure composition with the rest of the system.\n * --------------------------------------------------------------------------- */\n\nexport interface TableProps extends HTMLAttributes<HTMLTableElement> {\n /** Class for the scroll wrapper (border, radius, height). */\n containerClassName?: string;\n /**\n * Max height of the scroll wrapper. Required for the sticky header to\n * work — `<thead>` sticks to the nearest scroll container, so a wrapper\n * with no height cap never scrolls. e.g. `maxHeight=\"24rem\"`.\n */\n maxHeight?: CSSProperties['maxHeight'];\n /**\n * Accessible name of the scroll wrapper (it is a focusable `group` so\n * keyboard users can scroll wide / capped tables). Defaults to\n * `strings.table.scrollRegion`; pass the table's own title when you have one.\n */\n scrollLabel?: string;\n}\n\nexport const Table = forwardRef<HTMLTableElement, TableProps>(function Table(\n { className, containerClassName, maxHeight, scrollLabel, ...props },\n ref,\n) {\n const strings = useStrings();\n return (\n // Whether the wrapper actually overflows is not knowable statically, so it\n // is always a tab stop (WCAG 2.1.1 / axe scrollable-region-focusable).\n <div\n role=\"group\"\n aria-label={scrollLabel ?? strings.table.scrollRegion}\n tabIndex={0}\n className={cn(\n 'relative isolate w-full overflow-auto',\n 'focus-visible:ring-ring focus-visible:ring-offset-background outline-none focus-visible:ring-2 focus-visible:ring-offset-2',\n containerClassName,\n )}\n style={maxHeight !== undefined ? { maxHeight } : undefined}\n >\n <table\n ref={ref}\n className={cn('w-full caption-bottom border-collapse text-sm', className)}\n {...props}\n />\n </div>\n );\n});\nTable.displayName = 'Table';\n\nexport const TableHeader = forwardRef<\n HTMLTableSectionElement,\n HTMLAttributes<HTMLTableSectionElement>\n>(function TableHeader({ className, ...props }, ref) {\n return (\n <thead\n ref={ref}\n className={cn(\n 'bg-background-subtle text-foreground-muted sticky top-0 z-10',\n '[&_tr]:border-border [&_tr]:border-b',\n className,\n )}\n {...props}\n />\n );\n});\nTableHeader.displayName = 'TableHeader';\n\nexport const TableBody = forwardRef<\n HTMLTableSectionElement,\n HTMLAttributes<HTMLTableSectionElement>\n>(function TableBody({ className, ...props }, ref) {\n return <tbody ref={ref} className={cn('[&_tr:last-child]:border-0', className)} {...props} />;\n});\nTableBody.displayName = 'TableBody';\n\nexport const TableFooter = forwardRef<\n HTMLTableSectionElement,\n HTMLAttributes<HTMLTableSectionElement>\n>(function TableFooter({ className, ...props }, ref) {\n return (\n <tfoot\n ref={ref}\n className={cn('border-border bg-background-subtle border-t font-medium', className)}\n {...props}\n />\n );\n});\nTableFooter.displayName = 'TableFooter';\n\nexport const TableRow = forwardRef<\n HTMLTableRowElement,\n HTMLAttributes<HTMLTableRowElement> & {\n /**\n * Visual selected state (`data-state=\"selected\"`). `aria-selected` is only\n * valid on rows of an ARIA grid, so it is emitted only when the row\n * carries `role=\"row\"` (i.e. you opted into `role=\"grid\"` on the table).\n */\n selected?: boolean;\n }\n>(function TableRow({ className, selected, role, ...props }, ref) {\n return (\n <tr\n ref={ref}\n role={role}\n data-state={selected ? 'selected' : undefined}\n aria-selected={selected && role === 'row' ? true : undefined}\n className={cn(\n 'border-border border-b transition-colors duration-[var(--duration-fast)]',\n 'hover:bg-background-subtle',\n 'data-[state=selected]:bg-accent-soft data-[state=selected]:hover:bg-accent-soft',\n className,\n )}\n {...props}\n />\n );\n});\nTableRow.displayName = 'TableRow';\n\nexport type TableCellAlign = 'left' | 'center' | 'right';\n\nconst alignClass: Record<TableCellAlign, string> = {\n left: 'text-left',\n center: 'text-center',\n /* Numeric columns: right-aligned + tabular figures so digits line up. */\n right: 'text-right tabular',\n};\n\nexport interface TableHeadProps extends Omit<ThHTMLAttributes<HTMLTableCellElement>, 'align'> {\n /** Horizontal alignment; `right` also applies tabular figures. */\n align?: TableCellAlign;\n /**\n * Render the header label in small caps (`uppercase tracking-wide`).\n * Off by default — mixed case reads better for long / Cyrillic labels.\n * @default false\n */\n uppercase?: boolean;\n}\n\nexport const TableHead = forwardRef<HTMLTableCellElement, TableHeadProps>(function TableHead(\n { className, uppercase = false, align = 'left', ...props },\n ref,\n) {\n return (\n <th\n ref={ref}\n className={cn(\n 'text-foreground-subtle h-10 px-3 align-middle text-xs font-medium',\n alignClass[align],\n uppercase && 'tracking-wide uppercase',\n '[&:has([role=checkbox])]:w-10 [&:has([role=checkbox])]:pr-0',\n className,\n )}\n {...props}\n />\n );\n});\nTableHead.displayName = 'TableHead';\n\nexport interface TableCellProps extends Omit<TdHTMLAttributes<HTMLTableCellElement>, 'align'> {\n /** Horizontal alignment; `right` also applies tabular figures for numbers. */\n align?: TableCellAlign;\n}\n\nexport const TableCell = forwardRef<HTMLTableCellElement, TableCellProps>(function TableCell(\n { className, align = 'left', ...props },\n ref,\n) {\n return (\n <td\n ref={ref}\n className={cn('text-foreground px-3 py-3 align-middle', alignClass[align], className)}\n {...props}\n />\n );\n});\nTableCell.displayName = 'TableCell';\n\nexport const TableCaption = forwardRef<\n HTMLTableCaptionElement,\n HTMLAttributes<HTMLTableCaptionElement>\n>(function TableCaption({ className, ...props }, ref) {\n return (\n <caption\n ref={ref}\n className={cn('text-foreground-subtle mt-4 text-sm', className)}\n {...props}\n />\n );\n});\nTableCaption.displayName = 'TableCaption';\n\nexport interface TableSortHeaderProps extends TableHeadProps {\n /** Stable column key used in `currentSort.key`. */\n sortKey: string;\n /** Currently sorted column + direction (or null). */\n currentSort: { key: string; direction: 'asc' | 'desc' } | null;\n /** Called when the user clicks the header. */\n onSortChange: (key: string, direction: 'asc' | 'desc') => void;\n}\n\n/**\n * Sortable column header. Click toggles asc → desc → asc; the icon reflects\n * the current state.\n *\n * @example\n * <TableSortHeader sortKey=\"name\" currentSort={sort} onSortChange={onSort}>\n * Name\n * </TableSortHeader>\n *\n * @do Sort by one column at a time. Multi-sort hides state from users.\n * @dont Sort silently — the icon must change so users see what changed.\n */\nexport const TableSortHeader = forwardRef<HTMLTableCellElement, TableSortHeaderProps>(\n function TableSortHeader(\n { sortKey, currentSort, onSortChange, children, className, align = 'left', ...props },\n ref,\n ) {\n const active = currentSort?.key === sortKey;\n const direction = active ? currentSort?.direction : undefined;\n const handle = () => {\n onSortChange(sortKey, active && direction === 'asc' ? 'desc' : 'asc');\n };\n return (\n <TableHead\n ref={ref}\n align={align}\n className={cn('p-0', className)}\n // aria-sort only on the sorted column — 'none' everywhere else is noise.\n aria-sort={active ? (direction === 'asc' ? 'ascending' : 'descending') : undefined}\n {...props}\n >\n <button\n type=\"button\"\n onClick={handle}\n className={cn(\n 'inline-flex h-10 w-full items-center gap-1.5 px-3 outline-none',\n align === 'right' && 'flex-row-reverse',\n align === 'center' && 'justify-center',\n 'transition-colors duration-[var(--duration-fast)]',\n 'hover:text-foreground focus-visible:text-foreground',\n 'focus-visible:ring-ring focus-visible:ring-offset-background rounded-sm focus-visible:ring-2 focus-visible:ring-offset-2',\n active && 'text-foreground',\n )}\n >\n {children}\n {direction === 'asc' ? (\n <ArrowUp className=\"size-3.5\" aria-hidden />\n ) : direction === 'desc' ? (\n <ArrowDown className=\"size-3.5\" aria-hidden />\n ) : (\n <ArrowUpDown className=\"size-3.5 opacity-40\" aria-hidden />\n )}\n </button>\n </TableHead>\n );\n },\n);\nTableSortHeader.displayName = 'TableSortHeader';\n"],"names":["Table","forwardRef","className","containerClassName","maxHeight","scrollLabel","props","ref","strings","useStrings","jsx","cn","TableHeader","TableBody","TableFooter","TableRow","selected","role","alignClass","TableHead","uppercase","align","TableCell","TableCaption","TableSortHeader","sortKey","currentSort","onSortChange","children","active","direction","handle","jsxs","ArrowUp","ArrowDown","ArrowUpDown"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ComponentPropsWithoutRef } from 'react';
|
|
2
|
-
import { VariantProps } from '../../lib/cva';
|
|
2
|
+
import { VariantProps } from '../../lib/cva.js';
|
|
3
3
|
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
|
4
4
|
export declare const Tabs: import('react').ForwardRefExoticComponent<TabsPrimitive.TabsProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
5
5
|
declare const list: (props?: ({
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as i } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef as s, useContext as v, createContext as c } from "react";
|
|
4
|
+
import * as n from "@radix-ui/react-tabs";
|
|
5
|
+
import { cn as o } from "../../lib/utils.js";
|
|
6
|
+
import { cva as f } from "class-variance-authority";
|
|
7
|
+
const N = n.Root, l = c("underline"), g = f("inline-flex items-center", {
|
|
8
|
+
variants: {
|
|
9
|
+
variant: {
|
|
10
|
+
underline: "gap-4 border-b border-border w-full",
|
|
11
|
+
pills: "gap-1 rounded-lg bg-background-muted p-1"
|
|
12
|
+
},
|
|
13
|
+
size: {
|
|
14
|
+
sm: "h-9 text-xs",
|
|
15
|
+
md: "h-10 text-sm",
|
|
16
|
+
lg: "h-11 text-sm"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
defaultVariants: { variant: "underline", size: "md" }
|
|
20
|
+
}), b = s(
|
|
21
|
+
function({ className: t, variant: a = "underline", size: e, ...r }, u) {
|
|
22
|
+
return /* @__PURE__ */ i(l.Provider, { value: a ?? "underline", children: /* @__PURE__ */ i(
|
|
23
|
+
n.List,
|
|
24
|
+
{
|
|
25
|
+
ref: u,
|
|
26
|
+
"data-variant": a,
|
|
27
|
+
className: o(g({ variant: a, size: e }), t),
|
|
28
|
+
...r
|
|
29
|
+
}
|
|
30
|
+
) });
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
b.displayName = "TabsList";
|
|
34
|
+
const m = s(function({ className: t, ...a }, e) {
|
|
35
|
+
const r = v(l);
|
|
36
|
+
return /* @__PURE__ */ i(
|
|
37
|
+
n.Trigger,
|
|
38
|
+
{
|
|
39
|
+
ref: e,
|
|
40
|
+
"data-variant": r,
|
|
41
|
+
className: o(
|
|
42
|
+
"inline-flex items-center gap-2 font-medium whitespace-nowrap",
|
|
43
|
+
"transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out)] outline-none",
|
|
44
|
+
"focus-visible:ring-ring focus-visible:ring-offset-background focus-visible:ring-2 focus-visible:ring-offset-2",
|
|
45
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
46
|
+
// Underline variant
|
|
47
|
+
"data-[variant=underline]:relative data-[variant=underline]:h-full",
|
|
48
|
+
"data-[variant=underline]:text-foreground-muted data-[variant=underline]:px-1",
|
|
49
|
+
"data-[variant=underline]:hover:text-foreground",
|
|
50
|
+
"data-[variant=underline]:data-[state=active]:text-foreground",
|
|
51
|
+
"data-[variant=underline]:data-[state=active]:after:absolute",
|
|
52
|
+
"data-[variant=underline]:data-[state=active]:after:inset-x-0",
|
|
53
|
+
"data-[variant=underline]:data-[state=active]:after:-bottom-px",
|
|
54
|
+
"data-[variant=underline]:data-[state=active]:after:h-0.5",
|
|
55
|
+
"data-[variant=underline]:data-[state=active]:after:bg-accent",
|
|
56
|
+
// Pills variant
|
|
57
|
+
"data-[variant=pills]:h-full data-[variant=pills]:rounded-md data-[variant=pills]:px-3",
|
|
58
|
+
"data-[variant=pills]:text-foreground-muted",
|
|
59
|
+
"data-[variant=pills]:hover:text-foreground",
|
|
60
|
+
"data-[variant=pills]:data-[state=active]:bg-card",
|
|
61
|
+
"data-[variant=pills]:data-[state=active]:text-foreground",
|
|
62
|
+
"data-[variant=pills]:data-[state=active]:shadow-xs",
|
|
63
|
+
t
|
|
64
|
+
),
|
|
65
|
+
...a
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
m.displayName = "TabsTrigger";
|
|
70
|
+
const p = s(function({ className: t, ...a }, e) {
|
|
71
|
+
return /* @__PURE__ */ i(
|
|
72
|
+
n.Content,
|
|
73
|
+
{
|
|
74
|
+
ref: e,
|
|
75
|
+
className: o(
|
|
76
|
+
"mt-4 outline-none",
|
|
77
|
+
"focus-visible:ring-ring focus-visible:ring-offset-background focus-visible:ring-2 focus-visible:ring-offset-2",
|
|
78
|
+
t
|
|
79
|
+
),
|
|
80
|
+
...a
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
p.displayName = "TabsContent";
|
|
85
|
+
export {
|
|
86
|
+
N as Tabs,
|
|
87
|
+
p as TabsContent,
|
|
88
|
+
b as TabsList,
|
|
89
|
+
m as TabsTrigger
|
|
90
|
+
};
|
|
91
|
+
//# sourceMappingURL=Tabs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tabs.js","sources":["../../../src/components/ui/Tabs.tsx"],"sourcesContent":["'use client';\n\nimport {\n createContext,\n forwardRef,\n useContext,\n type ComponentPropsWithoutRef,\n type ElementRef,\n} from 'react';\nimport * as TabsPrimitive from '@radix-ui/react-tabs';\nimport { cn } from '@/lib/utils';\nimport { cva, type VariantProps } from '@/lib/cva';\n\n/* -----------------------------------------------------------------------------\n * Two visual variants — `underline` (refined-minimal default) and `pills`.\n * Variant is set on `TabsList`; trigger styles auto-derive via data-attr.\n * --------------------------------------------------------------------------- */\n\nexport const Tabs = TabsPrimitive.Root;\n\ntype TabsVariant = 'underline' | 'pills';\n/* Triggers read the list variant from context and stamp their own\n `data-variant`, so no ancestor selector can leak into nested Tabs. */\nconst TabsVariantContext = createContext<TabsVariant>('underline');\n\nconst list = cva('inline-flex items-center', {\n variants: {\n variant: {\n underline: 'gap-4 border-b border-border w-full',\n pills: 'gap-1 rounded-lg bg-background-muted p-1',\n },\n size: {\n sm: 'h-9 text-xs',\n md: 'h-10 text-sm',\n lg: 'h-11 text-sm',\n },\n },\n defaultVariants: { variant: 'underline', size: 'md' },\n});\n\nexport interface TabsListProps\n extends ComponentPropsWithoutRef<typeof TabsPrimitive.List>, VariantProps<typeof list> {}\n\nexport const TabsList = forwardRef<ElementRef<typeof TabsPrimitive.List>, TabsListProps>(\n function TabsList({ className, variant = 'underline', size, ...props }, ref) {\n return (\n <TabsVariantContext.Provider value={variant ?? 'underline'}>\n <TabsPrimitive.List\n ref={ref}\n data-variant={variant}\n className={cn(list({ variant, size }), className)}\n {...props}\n />\n </TabsVariantContext.Provider>\n );\n },\n);\nTabsList.displayName = 'TabsList';\n\nexport const TabsTrigger = forwardRef<\n ElementRef<typeof TabsPrimitive.Trigger>,\n ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(function TabsTrigger({ className, ...props }, ref) {\n const variant = useContext(TabsVariantContext);\n return (\n <TabsPrimitive.Trigger\n ref={ref}\n data-variant={variant}\n className={cn(\n 'inline-flex items-center gap-2 font-medium whitespace-nowrap',\n 'transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out)] outline-none',\n 'focus-visible:ring-ring focus-visible:ring-offset-background focus-visible:ring-2 focus-visible:ring-offset-2',\n 'disabled:pointer-events-none disabled:opacity-50',\n // Underline variant\n 'data-[variant=underline]:relative data-[variant=underline]:h-full',\n 'data-[variant=underline]:text-foreground-muted data-[variant=underline]:px-1',\n 'data-[variant=underline]:hover:text-foreground',\n 'data-[variant=underline]:data-[state=active]:text-foreground',\n 'data-[variant=underline]:data-[state=active]:after:absolute',\n 'data-[variant=underline]:data-[state=active]:after:inset-x-0',\n 'data-[variant=underline]:data-[state=active]:after:-bottom-px',\n 'data-[variant=underline]:data-[state=active]:after:h-0.5',\n 'data-[variant=underline]:data-[state=active]:after:bg-accent',\n // Pills variant\n 'data-[variant=pills]:h-full data-[variant=pills]:rounded-md data-[variant=pills]:px-3',\n 'data-[variant=pills]:text-foreground-muted',\n 'data-[variant=pills]:hover:text-foreground',\n 'data-[variant=pills]:data-[state=active]:bg-card',\n 'data-[variant=pills]:data-[state=active]:text-foreground',\n 'data-[variant=pills]:data-[state=active]:shadow-xs',\n className,\n )}\n {...props}\n />\n );\n});\nTabsTrigger.displayName = 'TabsTrigger';\n\nexport const TabsContent = forwardRef<\n ElementRef<typeof TabsPrimitive.Content>,\n ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(function TabsContent({ className, ...props }, ref) {\n return (\n <TabsPrimitive.Content\n ref={ref}\n className={cn(\n 'mt-4 outline-none',\n 'focus-visible:ring-ring focus-visible:ring-offset-background focus-visible:ring-2 focus-visible:ring-offset-2',\n className,\n )}\n {...props}\n />\n );\n});\nTabsContent.displayName = 'TabsContent';\n\n/**\n * @example Underline (default)\n * <Tabs defaultValue=\"overview\">\n * <TabsList>\n * <TabsTrigger value=\"overview\">Overview</TabsTrigger>\n * <TabsTrigger value=\"activity\">Activity</TabsTrigger>\n * </TabsList>\n * <TabsContent value=\"overview\">…</TabsContent>\n * <TabsContent value=\"activity\">…</TabsContent>\n * </Tabs>\n *\n * @example Pills\n * <TabsList variant=\"pills\"><TabsTrigger value=\"all\">All</TabsTrigger>…</TabsList>\n *\n * @do Use `underline` at the top of a page or panel. Use `pills` inside a\n * card or for filter-style switches.\n * @dont Mix variants on the same screen — pick one and commit.\n */\n"],"names":["Tabs","TabsPrimitive","TabsVariantContext","createContext","list","cva","TabsList","forwardRef","className","variant","size","props","ref","jsx","cn","TabsTrigger","useContext","TabsContent"],"mappings":";;;;;;AAkBO,MAAMA,IAAOC,EAAc,MAK5BC,IAAqBC,EAA2B,WAAW,GAE3DC,IAAOC,EAAI,4BAA4B;AAAA,EAC3C,UAAU;AAAA,IACR,SAAS;AAAA,MACP,WAAW;AAAA,MACX,OAAO;AAAA,IAAA;AAAA,IAET,MAAM;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IAAA;AAAA,EACN;AAAA,EAEF,iBAAiB,EAAE,SAAS,aAAa,MAAM,KAAA;AACjD,CAAC,GAKYC,IAAWC;AAAA,EACtB,SAAkB,EAAE,WAAAC,GAAW,SAAAC,IAAU,aAAa,MAAAC,GAAM,GAAGC,EAAA,GAASC,GAAK;AAC3E,6BACGV,EAAmB,UAAnB,EAA4B,OAAOO,KAAW,aAC7C,UAAA,gBAAAI;AAAA,MAACZ,EAAc;AAAA,MAAd;AAAA,QACC,KAAAW;AAAA,QACA,gBAAcH;AAAA,QACd,WAAWK,EAAGV,EAAK,EAAE,SAAAK,GAAS,MAAAC,EAAA,CAAM,GAAGF,CAAS;AAAA,QAC/C,GAAGG;AAAA,MAAA;AAAA,IAAA,GAER;AAAA,EAEJ;AACF;AACAL,EAAS,cAAc;AAEhB,MAAMS,IAAcR,EAGzB,SAAqB,EAAE,WAAAC,GAAW,GAAGG,EAAA,GAASC,GAAK;AACnD,QAAMH,IAAUO,EAAWd,CAAkB;AAC7C,SACE,gBAAAW;AAAA,IAACZ,EAAc;AAAA,IAAd;AAAA,MACC,KAAAW;AAAA,MACA,gBAAcH;AAAA,MACd,WAAWK;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,QAEA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,QAEA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACAN;AAAA,MAAA;AAAA,MAED,GAAGG;AAAA,IAAA;AAAA,EAAA;AAGV,CAAC;AACDI,EAAY,cAAc;AAEnB,MAAME,IAAcV,EAGzB,SAAqB,EAAE,WAAAC,GAAW,GAAGG,EAAA,GAASC,GAAK;AACnD,SACE,gBAAAC;AAAA,IAACZ,EAAc;AAAA,IAAd;AAAA,MACC,KAAAW;AAAA,MACA,WAAWE;AAAA,QACT;AAAA,QACA;AAAA,QACAN;AAAA,MAAA;AAAA,MAED,GAAGG;AAAA,IAAA;AAAA,EAAA;AAGV,CAAC;AACDM,EAAY,cAAc;"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
1
2
|
export interface TagInputProps {
|
|
2
3
|
/** Controlled list of tags. */
|
|
3
4
|
value?: string[];
|
|
@@ -5,16 +6,30 @@ export interface TagInputProps {
|
|
|
5
6
|
defaultValue?: string[];
|
|
6
7
|
/** Called when the tag list changes. */
|
|
7
8
|
onChange?: (tags: string[]) => void;
|
|
9
|
+
/** Visible label rendered above the field. */
|
|
10
|
+
label?: ReactNode;
|
|
11
|
+
/** Visually conceal the label while keeping it for screen readers. */
|
|
12
|
+
hideLabel?: boolean;
|
|
13
|
+
/** Hint below the field. Hidden while `error` is set. */
|
|
14
|
+
description?: ReactNode;
|
|
8
15
|
/** Placeholder shown inside the inline input. */
|
|
9
16
|
placeholder?: string;
|
|
10
17
|
/** Maximum number of tags. */
|
|
11
18
|
max?: number;
|
|
12
19
|
/** Disable the editor. */
|
|
13
20
|
disabled?: boolean;
|
|
14
|
-
/**
|
|
15
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Validation state. `true` only paints the danger border; a ReactNode also
|
|
23
|
+
* renders the message below the field and wires `aria-describedby`.
|
|
24
|
+
*/
|
|
25
|
+
error?: boolean | ReactNode;
|
|
16
26
|
/** Treat these characters as separators (default: Enter + comma). */
|
|
17
27
|
separators?: string[];
|
|
28
|
+
/** Consumer-supplied id for the inline input. */
|
|
29
|
+
id?: string;
|
|
30
|
+
/** Extra ids to append to `aria-describedby`. */
|
|
31
|
+
'aria-describedby'?: string;
|
|
32
|
+
'aria-label'?: string;
|
|
18
33
|
className?: string;
|
|
19
34
|
}
|
|
20
35
|
/**
|