@hilum/ui 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.d.ts +350 -290
- package/dist/index.js +489 -435
- package/dist/index.js.map +1 -1
- package/llms.txt +9 -9
- package/package.json +1 -1
- package/src/components/accordion.tsx +5 -5
- package/src/components/action-panel.tsx +8 -6
- package/src/components/activity-feed.tsx +7 -5
- package/src/components/alert-dialog.tsx +5 -5
- package/src/components/alert.tsx +5 -5
- package/src/components/avatar-stack.tsx +3 -3
- package/src/components/avatar.tsx +4 -4
- package/src/components/badge.tsx +7 -7
- package/src/components/breadcrumb.tsx +5 -6
- package/src/components/button-group.tsx +7 -4
- package/src/components/button.tsx +7 -7
- package/src/components/calendar.tsx +10 -10
- package/src/components/card-heading.tsx +3 -3
- package/src/components/card.tsx +4 -4
- package/src/components/chart.tsx +10 -10
- package/src/components/checkbox.tsx +2 -2
- package/src/components/color-input.tsx +7 -5
- package/src/components/color-picker.tsx +8 -6
- package/src/components/combobox.tsx +66 -31
- package/src/components/command-palette.tsx +13 -11
- package/src/components/command.tsx +14 -12
- package/src/components/context-menu.tsx +16 -16
- package/src/components/data-table.tsx +18 -7
- package/src/components/date-picker.tsx +2 -2
- package/src/components/description-list.tsx +10 -8
- package/src/components/dialog.tsx +4 -4
- package/src/components/drawer.tsx +5 -5
- package/src/components/dropdown-menu.tsx +16 -16
- package/src/components/empty-state.tsx +5 -3
- package/src/components/field.tsx +4 -4
- package/src/components/grid-list.tsx +17 -13
- package/src/components/hover-card.tsx +1 -1
- package/src/components/input-group.tsx +10 -10
- package/src/components/input-number.tsx +7 -7
- package/src/components/input-otp.tsx +3 -3
- package/src/components/input.tsx +4 -4
- package/src/components/kbd.tsx +1 -1
- package/src/components/label.tsx +1 -1
- package/src/components/media-object.tsx +2 -0
- package/src/components/menubar.tsx +21 -21
- package/src/components/native-select.tsx +5 -5
- package/src/components/navigation-menu.tsx +10 -10
- package/src/components/notification.tsx +13 -11
- package/src/components/page-heading.tsx +8 -8
- package/src/components/pagination.tsx +1 -1
- package/src/components/popover.tsx +1 -1
- package/src/components/progress.tsx +1 -1
- package/src/components/property-row.tsx +3 -1
- package/src/components/radio-card.tsx +10 -8
- package/src/components/radio-group.tsx +4 -4
- package/src/components/resizable.tsx +3 -3
- package/src/components/scroll-area.tsx +1 -1
- package/src/components/section-heading.tsx +3 -3
- package/src/components/select.tsx +13 -13
- package/src/components/separator.tsx +1 -1
- package/src/components/sheet.tsx +4 -4
- package/src/components/sidebar.tsx +20 -20
- package/src/components/skeleton.tsx +1 -1
- package/src/components/slider.tsx +2 -2
- package/src/components/sonner.tsx +9 -8
- package/src/components/stacked-list.tsx +5 -5
- package/src/components/stat-card.tsx +9 -7
- package/src/components/steps.tsx +16 -14
- package/src/components/switch.tsx +2 -2
- package/src/components/table.tsx +9 -9
- package/src/components/tabs.tsx +2 -2
- package/src/components/textarea.tsx +4 -4
- package/src/components/toggle.tsx +9 -9
- package/src/components/tooltip.tsx +1 -1
|
@@ -42,7 +42,7 @@ function ColorInput({
|
|
|
42
42
|
return (
|
|
43
43
|
<div
|
|
44
44
|
className={cn(
|
|
45
|
-
"inline-flex h-8 items-stretch gap-0 rounded-md border border-
|
|
45
|
+
"inline-flex h-8 items-stretch gap-0 rounded-md border border-border bg-card overflow-hidden",
|
|
46
46
|
"focus-within:ring-2 focus-within:ring-brand-primary/20 focus-within:border-brand-primary",
|
|
47
47
|
disabled && "opacity-50 pointer-events-none",
|
|
48
48
|
className,
|
|
@@ -65,19 +65,19 @@ function ColorInput({
|
|
|
65
65
|
commitHex("#" + (e.target as HTMLInputElement).value.replace(/^#/, ""));
|
|
66
66
|
}}
|
|
67
67
|
spellCheck={false}
|
|
68
|
-
className="w-[5.5rem] caption text-
|
|
68
|
+
className="w-[5.5rem] caption text-foreground px-2 bg-transparent border-l border-border focus:outline-none uppercase"
|
|
69
69
|
/>
|
|
70
70
|
{typeof opacity === "number" && onOpacityChange && (
|
|
71
|
-
<div className="relative flex items-center border-l border-
|
|
71
|
+
<div className="relative flex items-center border-l border-border">
|
|
72
72
|
<input
|
|
73
73
|
type="number"
|
|
74
74
|
min={0}
|
|
75
75
|
max={100}
|
|
76
76
|
value={Math.round(opacity)}
|
|
77
77
|
onChange={(e) => onOpacityChange(Number(e.target.value))}
|
|
78
|
-
className="w-12 caption text-
|
|
78
|
+
className="w-12 caption text-foreground px-2 bg-transparent focus:outline-none text-right [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
|
79
79
|
/>
|
|
80
|
-
<span aria-hidden className="caption-xs text-
|
|
80
|
+
<span aria-hidden className="caption-xs text-muted-foreground pr-2">
|
|
81
81
|
%
|
|
82
82
|
</span>
|
|
83
83
|
</div>
|
|
@@ -86,5 +86,7 @@ function ColorInput({
|
|
|
86
86
|
);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
ColorInput.displayName = "ColorInput";
|
|
90
|
+
|
|
89
91
|
export { ColorInput };
|
|
90
92
|
export type { ColorInputProps };
|
|
@@ -45,8 +45,8 @@ function ColorPicker({
|
|
|
45
45
|
disabled={disabled}
|
|
46
46
|
aria-label={ariaLabel}
|
|
47
47
|
className={cn(
|
|
48
|
-
"inline-flex h-8 w-8 items-center justify-center rounded-md border border-
|
|
49
|
-
"transition-colors hover:border-
|
|
48
|
+
"inline-flex h-8 w-8 items-center justify-center rounded-md border border-border bg-card",
|
|
49
|
+
"transition-colors hover:border-border",
|
|
50
50
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-primary/20 focus-visible:border-brand-primary",
|
|
51
51
|
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
52
52
|
className,
|
|
@@ -63,7 +63,7 @@ function ColorPicker({
|
|
|
63
63
|
<Popover.Content
|
|
64
64
|
align="start"
|
|
65
65
|
sideOffset={6}
|
|
66
|
-
className="z-50 w-56 rounded-xl bg-
|
|
66
|
+
className="z-50 w-56 rounded-xl bg-card p-3 shadow-natural outline-none"
|
|
67
67
|
>
|
|
68
68
|
<input
|
|
69
69
|
type="color"
|
|
@@ -72,10 +72,10 @@ function ColorPicker({
|
|
|
72
72
|
setHex(e.target.value);
|
|
73
73
|
onChange(e.target.value);
|
|
74
74
|
}}
|
|
75
|
-
className="h-10 w-full cursor-pointer rounded-md border border-
|
|
75
|
+
className="h-10 w-full cursor-pointer rounded-md border border-border bg-card p-0.5"
|
|
76
76
|
/>
|
|
77
77
|
<div className="mt-2 flex items-center gap-2">
|
|
78
|
-
<span className="caption text-
|
|
78
|
+
<span className="caption text-muted-foreground">Hex</span>
|
|
79
79
|
<input
|
|
80
80
|
type="text"
|
|
81
81
|
value={hex}
|
|
@@ -84,7 +84,7 @@ function ColorPicker({
|
|
|
84
84
|
onKeyDown={(e) => {
|
|
85
85
|
if (e.key === "Enter") commit((e.target as HTMLInputElement).value);
|
|
86
86
|
}}
|
|
87
|
-
className="flex-1 h-7 rounded-md border border-
|
|
87
|
+
className="flex-1 h-7 rounded-md border border-border bg-card px-2 caption text-foreground focus:outline-none focus:border-brand-primary"
|
|
88
88
|
/>
|
|
89
89
|
</div>
|
|
90
90
|
{presets && presets.length > 0 && (
|
|
@@ -107,5 +107,7 @@ function ColorPicker({
|
|
|
107
107
|
);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
ColorPicker.displayName = "ColorPicker";
|
|
111
|
+
|
|
110
112
|
export { ColorPicker };
|
|
111
113
|
export type { ColorPickerProps };
|
|
@@ -33,8 +33,10 @@ function Combobox({
|
|
|
33
33
|
}: ComboboxProps) {
|
|
34
34
|
const [open, setOpen] = React.useState(false);
|
|
35
35
|
const [query, setQuery] = React.useState("");
|
|
36
|
+
const [activeIndex, setActiveIndex] = React.useState(-1);
|
|
36
37
|
const containerRef = React.useRef<HTMLDivElement>(null);
|
|
37
38
|
const inputRef = React.useRef<HTMLInputElement>(null);
|
|
39
|
+
const listboxId = React.useId();
|
|
38
40
|
|
|
39
41
|
const selectedOption = options.find((o) => o.value === value);
|
|
40
42
|
|
|
@@ -47,6 +49,11 @@ function Combobox({
|
|
|
47
49
|
o.description?.toLowerCase().includes(query.toLowerCase()),
|
|
48
50
|
);
|
|
49
51
|
|
|
52
|
+
// Reset active index when the filtered list changes
|
|
53
|
+
React.useEffect(() => {
|
|
54
|
+
setActiveIndex(-1);
|
|
55
|
+
}, [filtered.length, open]);
|
|
56
|
+
|
|
50
57
|
// Close on outside click
|
|
51
58
|
React.useEffect(() => {
|
|
52
59
|
function onMouseDown(e: MouseEvent) {
|
|
@@ -59,25 +66,45 @@ function Combobox({
|
|
|
59
66
|
return () => document.removeEventListener("mousedown", onMouseDown);
|
|
60
67
|
}, []);
|
|
61
68
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
function closeDropdown() {
|
|
70
|
+
setOpen(false);
|
|
71
|
+
setQuery("");
|
|
72
|
+
setActiveIndex(-1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function selectOption(opt: ComboboxOption) {
|
|
76
|
+
onValueChange?.(opt.value);
|
|
77
|
+
closeDropdown();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function handleInputKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
|
|
81
|
+
if (e.key === "Escape") {
|
|
82
|
+
closeDropdown();
|
|
83
|
+
return;
|
|
70
84
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
85
|
+
if (e.key === "ArrowDown") {
|
|
86
|
+
e.preventDefault();
|
|
87
|
+
if (!open) { setOpen(true); return; }
|
|
88
|
+
setActiveIndex((i) => Math.min(i + 1, filtered.length - 1));
|
|
89
|
+
} else if (e.key === "ArrowUp") {
|
|
90
|
+
e.preventDefault();
|
|
91
|
+
setActiveIndex((i) => Math.max(i - 1, 0));
|
|
92
|
+
} else if (e.key === "Enter") {
|
|
93
|
+
e.preventDefault();
|
|
94
|
+
if (!open) { setOpen(true); return; }
|
|
95
|
+
const target = activeIndex >= 0 ? filtered[activeIndex] : filtered[0];
|
|
96
|
+
if (target) selectOption(target);
|
|
97
|
+
} else if (e.key === "Tab") {
|
|
98
|
+
closeDropdown();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
74
101
|
|
|
75
102
|
return (
|
|
76
103
|
<div ref={containerRef} className={cn("relative", className)}>
|
|
77
104
|
{/* Trigger */}
|
|
78
105
|
<div className="relative flex items-center">
|
|
79
106
|
{selectedOption?.avatar && !open && (
|
|
80
|
-
<div className="pointer-events-none absolute left-2.5 flex size-5 items-center justify-center rounded-full bg-
|
|
107
|
+
<div className="pointer-events-none absolute left-2.5 flex size-5 items-center justify-center rounded-full bg-muted caption-xs font-semibold text-muted-foreground shrink-0">
|
|
81
108
|
{selectedOption.avatar}
|
|
82
109
|
</div>
|
|
83
110
|
)}
|
|
@@ -92,10 +119,14 @@ function Combobox({
|
|
|
92
119
|
type="text"
|
|
93
120
|
role="combobox"
|
|
94
121
|
aria-expanded={open}
|
|
122
|
+
aria-haspopup="listbox"
|
|
123
|
+
aria-controls={open ? listboxId : undefined}
|
|
124
|
+
aria-activedescendant={open && activeIndex >= 0 ? `${listboxId}-option-${activeIndex}` : undefined}
|
|
125
|
+
aria-autocomplete="list"
|
|
95
126
|
className={cn(
|
|
96
|
-
"flex h-9 w-full rounded-lg border border-
|
|
97
|
-
"placeholder:text-
|
|
98
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-
|
|
127
|
+
"flex h-9 w-full rounded-lg border border-border bg-card pr-8 body text-foreground",
|
|
128
|
+
"placeholder:text-muted-foreground",
|
|
129
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30 focus-visible:border-border",
|
|
99
130
|
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
100
131
|
selectedOption?.avatar && !open
|
|
101
132
|
? "pl-8"
|
|
@@ -113,15 +144,16 @@ function Combobox({
|
|
|
113
144
|
setOpen(true);
|
|
114
145
|
setQuery("");
|
|
115
146
|
}}
|
|
147
|
+
onKeyDown={handleInputKeyDown}
|
|
116
148
|
/>
|
|
117
149
|
<button
|
|
118
150
|
type="button"
|
|
119
151
|
tabIndex={-1}
|
|
120
|
-
|
|
152
|
+
aria-label={open ? "Close" : "Open"}
|
|
153
|
+
className="absolute inset-y-0 right-0 flex items-center px-2 text-muted-foreground hover:text-muted-foreground transition-colors"
|
|
121
154
|
onClick={() => {
|
|
122
155
|
if (open) {
|
|
123
|
-
|
|
124
|
-
setQuery("");
|
|
156
|
+
closeDropdown();
|
|
125
157
|
} else {
|
|
126
158
|
setOpen(true);
|
|
127
159
|
inputRef.current?.focus();
|
|
@@ -134,37 +166,38 @@ function Combobox({
|
|
|
134
166
|
|
|
135
167
|
{/* Dropdown */}
|
|
136
168
|
{open && (
|
|
137
|
-
<div className="absolute z-50 mt-1 w-full overflow-hidden rounded-lg border border-
|
|
138
|
-
<ul role="listbox" className="max-h-60 overflow-auto py-1">
|
|
169
|
+
<div className="absolute z-50 mt-1 w-full overflow-hidden rounded-lg border border-border bg-card shadow-elevated">
|
|
170
|
+
<ul id={listboxId} role="listbox" className="max-h-60 overflow-auto py-1">
|
|
139
171
|
{filtered.length === 0 ? (
|
|
140
|
-
<li className="px-3 py-2 body text-
|
|
172
|
+
<li className="px-3 py-2 body text-muted-foreground">{emptyText}</li>
|
|
141
173
|
) : (
|
|
142
|
-
filtered.map((option) => {
|
|
174
|
+
filtered.map((option, idx) => {
|
|
143
175
|
const isSelected = option.value === value;
|
|
176
|
+
const isActive = idx === activeIndex;
|
|
144
177
|
return (
|
|
145
178
|
<li
|
|
146
179
|
key={option.value}
|
|
180
|
+
id={`${listboxId}-option-${idx}`}
|
|
147
181
|
role="option"
|
|
148
182
|
aria-selected={isSelected}
|
|
149
183
|
className={cn(
|
|
150
184
|
"flex cursor-pointer select-none items-center gap-2.5 px-3 py-2 body transition-colors",
|
|
151
185
|
isSelected
|
|
152
|
-
? "bg-brand-primary text-
|
|
153
|
-
:
|
|
186
|
+
? "bg-brand-primary text-background"
|
|
187
|
+
: isActive
|
|
188
|
+
? "bg-muted text-foreground"
|
|
189
|
+
: "text-foreground hover:bg-muted",
|
|
154
190
|
)}
|
|
155
191
|
onMouseDown={(e) => e.preventDefault()}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
setQuery("");
|
|
159
|
-
setOpen(false);
|
|
160
|
-
}}
|
|
192
|
+
onMouseEnter={() => setActiveIndex(idx)}
|
|
193
|
+
onClick={() => selectOption(option)}
|
|
161
194
|
>
|
|
162
195
|
{/* Avatar */}
|
|
163
196
|
{option.avatar && (
|
|
164
197
|
<div
|
|
165
198
|
className={cn(
|
|
166
199
|
"flex size-6 shrink-0 items-center justify-center rounded-full caption-xs font-semibold",
|
|
167
|
-
isSelected ? "bg-
|
|
200
|
+
isSelected ? "bg-card/20 text-background" : "bg-muted text-muted-foreground",
|
|
168
201
|
)}
|
|
169
202
|
>
|
|
170
203
|
{option.avatar}
|
|
@@ -185,7 +218,7 @@ function Combobox({
|
|
|
185
218
|
<p
|
|
186
219
|
className={cn(
|
|
187
220
|
"caption truncate",
|
|
188
|
-
isSelected ? "text-
|
|
221
|
+
isSelected ? "text-background/70" : "text-muted-foreground",
|
|
189
222
|
)}
|
|
190
223
|
>
|
|
191
224
|
{option.description}
|
|
@@ -204,4 +237,6 @@ function Combobox({
|
|
|
204
237
|
);
|
|
205
238
|
}
|
|
206
239
|
|
|
240
|
+
Combobox.displayName = "Combobox";
|
|
241
|
+
|
|
207
242
|
export { Combobox };
|
|
@@ -73,12 +73,12 @@ function CommandPalette({
|
|
|
73
73
|
<Dialog open={open} onOpenChange={(v) => !v && onClose()}>
|
|
74
74
|
<DialogContent className="gap-0 overflow-hidden p-0 sm:max-w-xl">
|
|
75
75
|
{/* Search input */}
|
|
76
|
-
<div className="flex items-center gap-3 border-b border-
|
|
77
|
-
<Search size={16} className="shrink-0 text-
|
|
76
|
+
<div className="flex items-center gap-3 border-b border-border px-4">
|
|
77
|
+
<Search size={16} className="shrink-0 text-muted-foreground" />
|
|
78
78
|
<input
|
|
79
79
|
ref={inputRef}
|
|
80
80
|
type="text"
|
|
81
|
-
className="h-12 flex-1 bg-transparent body text-
|
|
81
|
+
className="h-12 flex-1 bg-transparent body text-foreground placeholder:text-muted-foreground focus:outline-none"
|
|
82
82
|
placeholder={placeholder}
|
|
83
83
|
value={query}
|
|
84
84
|
onChange={(e) => setQuery(e.target.value)}
|
|
@@ -88,7 +88,7 @@ function CommandPalette({
|
|
|
88
88
|
}}
|
|
89
89
|
/>
|
|
90
90
|
<kbd className="hidden items-center gap-0.5 sm:flex">
|
|
91
|
-
<span className="caption-xs font-medium text-
|
|
91
|
+
<span className="caption-xs font-medium text-muted-foreground rounded border border-border px-1.5 py-0.5">
|
|
92
92
|
esc
|
|
93
93
|
</span>
|
|
94
94
|
</kbd>
|
|
@@ -97,31 +97,31 @@ function CommandPalette({
|
|
|
97
97
|
{/* Results */}
|
|
98
98
|
<div className="max-h-80 overflow-y-auto">
|
|
99
99
|
{filtered.length === 0 ? (
|
|
100
|
-
<p className="px-4 py-8 text-center body text-
|
|
100
|
+
<p className="px-4 py-8 text-center body text-muted-foreground">{emptyText}</p>
|
|
101
101
|
) : (
|
|
102
102
|
<ul role="list" className="py-2">
|
|
103
103
|
{categories.map((cat) => (
|
|
104
104
|
<li key={cat}>
|
|
105
|
-
{cat && <p className="label px-4 py-2 text-
|
|
105
|
+
{cat && <p className="label px-4 py-2 text-muted-foreground">{cat}</p>}
|
|
106
106
|
{grouped[cat].map((item, i) => (
|
|
107
107
|
<button
|
|
108
108
|
key={item.id ?? i}
|
|
109
109
|
type="button"
|
|
110
|
-
className="flex w-full items-center gap-3 px-4 py-2.5 body text-left transition-colors hover:bg-
|
|
110
|
+
className="flex w-full items-center gap-3 px-4 py-2.5 body text-left transition-colors hover:bg-muted focus-visible:bg-muted focus-visible:outline-none"
|
|
111
111
|
onClick={() => handleSelect(item)}
|
|
112
112
|
>
|
|
113
113
|
{item.icon && (
|
|
114
|
-
<span className="flex size-8 shrink-0 items-center justify-center rounded-lg border border-
|
|
114
|
+
<span className="flex size-8 shrink-0 items-center justify-center rounded-lg border border-border bg-card text-muted-foreground">
|
|
115
115
|
{item.icon}
|
|
116
116
|
</span>
|
|
117
117
|
)}
|
|
118
118
|
<div className="min-w-0 flex-1">
|
|
119
|
-
<p className="font-medium text-
|
|
119
|
+
<p className="font-medium text-foreground truncate">{item.label}</p>
|
|
120
120
|
{item.description && (
|
|
121
|
-
<p className="caption text-
|
|
121
|
+
<p className="caption text-muted-foreground truncate">{item.description}</p>
|
|
122
122
|
)}
|
|
123
123
|
</div>
|
|
124
|
-
<ArrowRight size={13} className="shrink-0 text-
|
|
124
|
+
<ArrowRight size={13} className="shrink-0 text-muted-foreground" />
|
|
125
125
|
</button>
|
|
126
126
|
))}
|
|
127
127
|
</li>
|
|
@@ -134,4 +134,6 @@ function CommandPalette({
|
|
|
134
134
|
);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
CommandPalette.displayName = "CommandPalette";
|
|
138
|
+
|
|
137
139
|
export { CommandPalette };
|
|
@@ -44,7 +44,7 @@ function Command({ className, children, onSelect, ...props }: CommandProps) {
|
|
|
44
44
|
<CommandVisibleCtx.Provider value={visibleCount}>
|
|
45
45
|
<div
|
|
46
46
|
className={cn(
|
|
47
|
-
"flex flex-col overflow-hidden rounded-xl border border-
|
|
47
|
+
"flex flex-col overflow-hidden rounded-xl border border-border bg-card",
|
|
48
48
|
className,
|
|
49
49
|
)}
|
|
50
50
|
{...props}
|
|
@@ -62,8 +62,8 @@ const CommandInput = React.forwardRef<
|
|
|
62
62
|
>(({ className, ...props }, ref) => {
|
|
63
63
|
const { query, setQuery } = React.useContext(CommandCtx);
|
|
64
64
|
return (
|
|
65
|
-
<div className="flex items-center gap-2 border-b border-
|
|
66
|
-
<Search size={14} className="shrink-0 text-
|
|
65
|
+
<div className="flex items-center gap-2 border-b border-border px-3">
|
|
66
|
+
<Search size={14} className="shrink-0 text-muted-foreground" />
|
|
67
67
|
<input
|
|
68
68
|
ref={ref}
|
|
69
69
|
type="text"
|
|
@@ -71,8 +71,8 @@ const CommandInput = React.forwardRef<
|
|
|
71
71
|
autoCorrect="off"
|
|
72
72
|
spellCheck={false}
|
|
73
73
|
className={cn(
|
|
74
|
-
"flex h-10 w-full bg-transparent body text-
|
|
75
|
-
"placeholder:text-
|
|
74
|
+
"flex h-10 w-full bg-transparent body text-foreground",
|
|
75
|
+
"placeholder:text-muted-foreground focus:outline-none",
|
|
76
76
|
className,
|
|
77
77
|
)}
|
|
78
78
|
value={query}
|
|
@@ -135,7 +135,7 @@ const CommandEmpty = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLD
|
|
|
135
135
|
return (
|
|
136
136
|
<div
|
|
137
137
|
ref={ref}
|
|
138
|
-
className={cn("py-6 text-center caption text-
|
|
138
|
+
className={cn("py-6 text-center caption text-muted-foreground", className)}
|
|
139
139
|
{...props}
|
|
140
140
|
>
|
|
141
141
|
{children}
|
|
@@ -152,7 +152,7 @@ interface CommandGroupProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
152
152
|
const CommandGroup = React.forwardRef<HTMLDivElement, CommandGroupProps>(
|
|
153
153
|
({ className, heading, children, ...props }, ref) => (
|
|
154
154
|
<div ref={ref} role="group" className={cn("py-1", className)} {...props}>
|
|
155
|
-
{heading && <p className="px-3 pb-1 pt-0.5 label text-
|
|
155
|
+
{heading && <p className="px-3 pb-1 pt-0.5 label text-muted-foreground">{heading}</p>}
|
|
156
156
|
{children}
|
|
157
157
|
</div>
|
|
158
158
|
),
|
|
@@ -197,9 +197,9 @@ const CommandItem = React.forwardRef<HTMLDivElement, CommandItemProps>(
|
|
|
197
197
|
tabIndex={disabled ? undefined : 0}
|
|
198
198
|
className={cn(
|
|
199
199
|
"relative flex cursor-default select-none items-center gap-2 rounded-md px-2.5 py-1.5 mx-1",
|
|
200
|
-
"body text-
|
|
201
|
-
"hover:bg-
|
|
202
|
-
"focus:bg-
|
|
200
|
+
"body text-muted-foreground outline-none transition-colors",
|
|
201
|
+
"hover:bg-muted hover:text-foreground",
|
|
202
|
+
"focus:bg-muted focus:text-foreground",
|
|
203
203
|
disabled && "pointer-events-none opacity-40",
|
|
204
204
|
className,
|
|
205
205
|
)}
|
|
@@ -221,7 +221,7 @@ CommandItem.displayName = "CommandItem";
|
|
|
221
221
|
|
|
222
222
|
const CommandSeparator = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
223
223
|
({ className, ...props }, ref) => (
|
|
224
|
-
<div ref={ref} className={cn("my-1 h-px bg-
|
|
224
|
+
<div ref={ref} className={cn("my-1 h-px bg-muted", className)} {...props} />
|
|
225
225
|
),
|
|
226
226
|
);
|
|
227
227
|
CommandSeparator.displayName = "CommandSeparator";
|
|
@@ -229,13 +229,15 @@ CommandSeparator.displayName = "CommandSeparator";
|
|
|
229
229
|
function CommandShortcut({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) {
|
|
230
230
|
return (
|
|
231
231
|
<span
|
|
232
|
-
className={cn("ml-auto caption text-
|
|
232
|
+
className={cn("ml-auto caption text-muted-foreground tracking-widest font-medium", className)}
|
|
233
233
|
{...props}
|
|
234
234
|
/>
|
|
235
235
|
);
|
|
236
236
|
}
|
|
237
237
|
CommandShortcut.displayName = "CommandShortcut";
|
|
238
238
|
|
|
239
|
+
Command.displayName = "Command";
|
|
240
|
+
|
|
239
241
|
export {
|
|
240
242
|
Command,
|
|
241
243
|
CommandInput,
|
|
@@ -20,7 +20,7 @@ const ContextMenuContent = React.forwardRef<
|
|
|
20
20
|
<ContextMenu.Content
|
|
21
21
|
ref={ref}
|
|
22
22
|
className={cn(
|
|
23
|
-
"z-50 min-w-[8rem] bg-
|
|
23
|
+
"z-50 min-w-[8rem] bg-card rounded-xl shadow-natural p-1",
|
|
24
24
|
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
25
25
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
26
26
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
@@ -47,8 +47,8 @@ const ContextMenuItem = React.forwardRef<
|
|
|
47
47
|
"relative flex cursor-default select-none items-center gap-2 rounded-md px-2.5 py-1.5",
|
|
48
48
|
"body outline-none transition-colors",
|
|
49
49
|
destructive
|
|
50
|
-
? "text-
|
|
51
|
-
: "text-
|
|
50
|
+
? "text-destructive focus:bg-destructive/10 focus:text-destructive"
|
|
51
|
+
: "text-muted-foreground focus:bg-muted focus:text-foreground",
|
|
52
52
|
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
53
53
|
inset && "pl-8",
|
|
54
54
|
className,
|
|
@@ -66,8 +66,8 @@ const ContextMenuCheckboxItem = React.forwardRef<
|
|
|
66
66
|
ref={ref}
|
|
67
67
|
className={cn(
|
|
68
68
|
"relative flex cursor-default select-none items-center gap-2 rounded-md pl-8 pr-2.5 py-1.5",
|
|
69
|
-
"body text-
|
|
70
|
-
"focus:bg-
|
|
69
|
+
"body text-muted-foreground outline-none transition-colors",
|
|
70
|
+
"focus:bg-muted focus:text-foreground",
|
|
71
71
|
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
72
72
|
className,
|
|
73
73
|
)}
|
|
@@ -75,7 +75,7 @@ const ContextMenuCheckboxItem = React.forwardRef<
|
|
|
75
75
|
>
|
|
76
76
|
<span className="absolute left-2 flex size-3.5 items-center justify-center">
|
|
77
77
|
<ContextMenu.ItemIndicator>
|
|
78
|
-
<Check size={13} className="text-
|
|
78
|
+
<Check size={13} className="text-foreground" />
|
|
79
79
|
</ContextMenu.ItemIndicator>
|
|
80
80
|
</span>
|
|
81
81
|
{children}
|
|
@@ -91,8 +91,8 @@ const ContextMenuRadioItem = React.forwardRef<
|
|
|
91
91
|
ref={ref}
|
|
92
92
|
className={cn(
|
|
93
93
|
"relative flex cursor-default select-none items-center gap-2 rounded-md pl-8 pr-2.5 py-1.5",
|
|
94
|
-
"body text-
|
|
95
|
-
"focus:bg-
|
|
94
|
+
"body text-muted-foreground outline-none transition-colors",
|
|
95
|
+
"focus:bg-muted focus:text-foreground",
|
|
96
96
|
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
97
97
|
className,
|
|
98
98
|
)}
|
|
@@ -100,7 +100,7 @@ const ContextMenuRadioItem = React.forwardRef<
|
|
|
100
100
|
>
|
|
101
101
|
<span className="absolute left-2 flex size-3.5 items-center justify-center">
|
|
102
102
|
<ContextMenu.ItemIndicator>
|
|
103
|
-
<Circle size={8} className="fill-
|
|
103
|
+
<Circle size={8} className="fill-foreground text-foreground" />
|
|
104
104
|
</ContextMenu.ItemIndicator>
|
|
105
105
|
</span>
|
|
106
106
|
{children}
|
|
@@ -116,7 +116,7 @@ const ContextMenuLabel = React.forwardRef<
|
|
|
116
116
|
>(({ className, inset, ...props }, ref) => (
|
|
117
117
|
<ContextMenu.Label
|
|
118
118
|
ref={ref}
|
|
119
|
-
className={cn("px-2.5 py-1 label text-
|
|
119
|
+
className={cn("px-2.5 py-1 label text-muted-foreground", inset && "pl-8", className)}
|
|
120
120
|
{...props}
|
|
121
121
|
/>
|
|
122
122
|
));
|
|
@@ -128,7 +128,7 @@ const ContextMenuSeparator = React.forwardRef<
|
|
|
128
128
|
>(({ className, ...props }, ref) => (
|
|
129
129
|
<ContextMenu.Separator
|
|
130
130
|
ref={ref}
|
|
131
|
-
className={cn("mx-1 my-1 h-px bg-
|
|
131
|
+
className={cn("mx-1 my-1 h-px bg-muted", className)}
|
|
132
132
|
{...props}
|
|
133
133
|
/>
|
|
134
134
|
));
|
|
@@ -144,15 +144,15 @@ const ContextMenuSubTrigger = React.forwardRef<
|
|
|
144
144
|
ref={ref}
|
|
145
145
|
className={cn(
|
|
146
146
|
"relative flex cursor-default select-none items-center gap-2 rounded-md px-2.5 py-1.5",
|
|
147
|
-
"body text-
|
|
148
|
-
"focus:bg-
|
|
147
|
+
"body text-muted-foreground outline-none transition-colors",
|
|
148
|
+
"focus:bg-muted focus:text-foreground data-[state=open]:bg-muted",
|
|
149
149
|
inset && "pl-8",
|
|
150
150
|
className,
|
|
151
151
|
)}
|
|
152
152
|
{...props}
|
|
153
153
|
>
|
|
154
154
|
{children}
|
|
155
|
-
<ChevronRight size={14} className="ml-auto text-
|
|
155
|
+
<ChevronRight size={14} className="ml-auto text-muted-foreground" />
|
|
156
156
|
</ContextMenu.SubTrigger>
|
|
157
157
|
));
|
|
158
158
|
ContextMenuSubTrigger.displayName = "ContextMenuSubTrigger";
|
|
@@ -164,7 +164,7 @@ const ContextMenuSubContent = React.forwardRef<
|
|
|
164
164
|
<ContextMenu.SubContent
|
|
165
165
|
ref={ref}
|
|
166
166
|
className={cn(
|
|
167
|
-
"z-50 min-w-[8rem] bg-
|
|
167
|
+
"z-50 min-w-[8rem] bg-card rounded-xl border border-border shadow-natural p-1",
|
|
168
168
|
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
169
169
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
170
170
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
@@ -177,7 +177,7 @@ const ContextMenuSubContent = React.forwardRef<
|
|
|
177
177
|
ContextMenuSubContent.displayName = "ContextMenuSubContent";
|
|
178
178
|
|
|
179
179
|
function ContextMenuShortcut({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) {
|
|
180
|
-
return <span className={cn("ml-auto caption text-
|
|
180
|
+
return <span className={cn("ml-auto caption text-muted-foreground", className)} {...props} />;
|
|
181
181
|
}
|
|
182
182
|
ContextMenuShortcut.displayName = "ContextMenuShortcut";
|
|
183
183
|
|
|
@@ -67,12 +67,23 @@ function DataTable<TData>({
|
|
|
67
67
|
{table.getHeaderGroups().map((headerGroup) => (
|
|
68
68
|
<TableRow key={headerGroup.id}>
|
|
69
69
|
{headerGroup.headers.map((header) => (
|
|
70
|
-
<TableHead
|
|
70
|
+
<TableHead
|
|
71
|
+
key={header.id}
|
|
72
|
+
aria-sort={
|
|
73
|
+
header.column.getCanSort()
|
|
74
|
+
? header.column.getIsSorted() === "asc"
|
|
75
|
+
? "ascending"
|
|
76
|
+
: header.column.getIsSorted() === "desc"
|
|
77
|
+
? "descending"
|
|
78
|
+
: "none"
|
|
79
|
+
: undefined
|
|
80
|
+
}
|
|
81
|
+
>
|
|
71
82
|
{header.isPlaceholder ? null : header.column.getCanSort() ? (
|
|
72
83
|
<button
|
|
73
84
|
className={cn(
|
|
74
|
-
"flex items-center gap-1 transition-colors hover:text-
|
|
75
|
-
header.column.getIsSorted() && "text-
|
|
85
|
+
"flex items-center gap-1 transition-colors hover:text-muted-foreground",
|
|
86
|
+
header.column.getIsSorted() && "text-foreground",
|
|
76
87
|
)}
|
|
77
88
|
onClick={header.column.getToggleSortingHandler()}
|
|
78
89
|
>
|
|
@@ -82,7 +93,7 @@ function DataTable<TData>({
|
|
|
82
93
|
) : header.column.getIsSorted() === "desc" ? (
|
|
83
94
|
<ChevronDown size={12} className="text-brand-primary" />
|
|
84
95
|
) : (
|
|
85
|
-
<ChevronsUpDown size={12} className="text-
|
|
96
|
+
<ChevronsUpDown size={12} className="text-muted-foreground" />
|
|
86
97
|
)}
|
|
87
98
|
</button>
|
|
88
99
|
) : (
|
|
@@ -106,7 +117,7 @@ function DataTable<TData>({
|
|
|
106
117
|
))
|
|
107
118
|
) : (
|
|
108
119
|
<TableRow>
|
|
109
|
-
<TableCell colSpan={columns.length} className="h-24 text-center text-
|
|
120
|
+
<TableCell colSpan={columns.length} className="h-24 text-center text-muted-foreground">
|
|
110
121
|
No results.
|
|
111
122
|
</TableCell>
|
|
112
123
|
</TableRow>
|
|
@@ -115,12 +126,12 @@ function DataTable<TData>({
|
|
|
115
126
|
</Table>
|
|
116
127
|
{showPagination && (
|
|
117
128
|
<div className="flex items-center justify-between">
|
|
118
|
-
<p className="caption text-
|
|
129
|
+
<p className="caption text-muted-foreground">
|
|
119
130
|
{table.getFilteredRowModel().rows.length} result
|
|
120
131
|
{table.getFilteredRowModel().rows.length !== 1 ? "s" : ""}
|
|
121
132
|
</p>
|
|
122
133
|
<div className="flex items-center gap-2">
|
|
123
|
-
<span className="caption text-
|
|
134
|
+
<span className="caption text-muted-foreground">
|
|
124
135
|
Page {table.getState().pagination.pageIndex + 1} of {table.getPageCount()}
|
|
125
136
|
</span>
|
|
126
137
|
<Button
|
|
@@ -36,12 +36,12 @@ function DatePicker({
|
|
|
36
36
|
variant="outline"
|
|
37
37
|
className={cn(
|
|
38
38
|
"w-[240px] justify-start gap-2 text-left font-normal",
|
|
39
|
-
!value && "text-
|
|
39
|
+
!value && "text-muted-foreground",
|
|
40
40
|
className,
|
|
41
41
|
)}
|
|
42
42
|
disabled={disabled}
|
|
43
43
|
>
|
|
44
|
-
<CalendarIcon size={14} className="text-
|
|
44
|
+
<CalendarIcon size={14} className="text-muted-foreground shrink-0" />
|
|
45
45
|
{value ? formatDate(value) : <span>{placeholder}</span>}
|
|
46
46
|
</Button>
|
|
47
47
|
</PopoverTrigger>
|