minka-ds 0.3.8 → 0.3.10
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/package.json +1 -1
- package/src/components/ui/button-group.tsx +1 -1
- package/src/components/ui/date-time-range-picker.tsx +23 -2
- package/src/components/ui/input-group.tsx +1 -1
- package/src/components/ui/input.tsx +1 -1
- package/src/components/ui/search-bar.tsx +47 -106
- package/src/components/ui/tab-count.tsx +1 -1
- package/tokens/primitives.css +19 -19
- package/tokens/semantic.css +4 -1
package/package.json
CHANGED
|
@@ -55,7 +55,7 @@ function ButtonGroupText({
|
|
|
55
55
|
return (
|
|
56
56
|
<Comp
|
|
57
57
|
className={cn(
|
|
58
|
-
"flex items-center gap-2 [border-radius:var(--radius-button)] border border-[var(--color-border-default)] bg-[var(--color-bg-raised)] px-4 text-label text-[var(--color-text-muted)] [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
|
|
58
|
+
"flex h-9 items-center gap-2 [border-radius:var(--radius-button)] border border-[var(--color-border-default)] bg-[var(--color-bg-raised)] px-4 text-label text-[var(--color-text-muted)] [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
|
|
59
59
|
className
|
|
60
60
|
)}
|
|
61
61
|
{...props}
|
|
@@ -29,7 +29,25 @@ export function DateTimeRangePicker({
|
|
|
29
29
|
const range: DateRange | undefined =
|
|
30
30
|
value?.from ? { from: value.from, to: value.to } : undefined
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
// A range is "complete" once from and to differ (or a real end was picked).
|
|
33
|
+
const isComplete = Boolean(value?.from && value?.to && value.from.getTime() !== value.to.getTime())
|
|
34
|
+
|
|
35
|
+
function handleRangeSelect(
|
|
36
|
+
selected: DateRange | undefined,
|
|
37
|
+
selectedDay: Date,
|
|
38
|
+
) {
|
|
39
|
+
// If a complete range already exists, any click starts a brand-new range
|
|
40
|
+
// anchored on the clicked day — instead of extending the old one. This also
|
|
41
|
+
// frees the user from the max-range cap that was anchored on the old `from`.
|
|
42
|
+
if (isComplete) {
|
|
43
|
+
onChange({
|
|
44
|
+
from: selectedDay,
|
|
45
|
+
to: selectedDay,
|
|
46
|
+
startTime: value?.startTime ?? "",
|
|
47
|
+
endTime: value?.endTime ?? "",
|
|
48
|
+
})
|
|
49
|
+
return
|
|
50
|
+
}
|
|
33
51
|
if (!selected?.from) { onChange(null); return }
|
|
34
52
|
onChange({
|
|
35
53
|
from: selected.from,
|
|
@@ -49,8 +67,11 @@ export function DateTimeRangePicker({
|
|
|
49
67
|
onChange({ ...value, endTime: e.target.value })
|
|
50
68
|
}
|
|
51
69
|
|
|
70
|
+
// Only cap the calendar while the user is picking the second date (from set,
|
|
71
|
+
// range not yet complete). Once complete, all dates stay clickable so a fresh
|
|
72
|
+
// click elsewhere can start a new range.
|
|
52
73
|
const disabledAfter =
|
|
53
|
-
maxRangeDays && range?.from
|
|
74
|
+
maxRangeDays && range?.from && !isComplete
|
|
54
75
|
? { after: new Date(range.from.getTime() + maxRangeDays * 86_400_000) }
|
|
55
76
|
: undefined
|
|
56
77
|
|
|
@@ -120,7 +120,7 @@ function InputGroupText({ className, ...props }: React.ComponentProps<"span">) {
|
|
|
120
120
|
return (
|
|
121
121
|
<span
|
|
122
122
|
className={cn(
|
|
123
|
-
"flex items-center gap-2 text-body-sm text-[var(--color-text-muted)] [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
|
|
123
|
+
"flex items-center gap-2 px-3 text-body-sm text-[var(--color-text-muted)] [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
|
|
124
124
|
className
|
|
125
125
|
)}
|
|
126
126
|
{...props}
|
|
@@ -8,7 +8,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
|
|
8
8
|
type={type}
|
|
9
9
|
data-slot="input"
|
|
10
10
|
className={cn(
|
|
11
|
-
"h-9 w-full min-w-0 [border-radius:var(--radius-input)] border border-[var(--color-border-default)] bg-
|
|
11
|
+
"h-9 w-full min-w-0 [border-radius:var(--radius-input)] border border-[var(--color-border-default)] bg-[var(--color-bg-raised)] px-3 py-1 text-body-sm shadow-xs transition-[color,box-shadow] outline-none selection:bg-[var(--color-action-primary-default)] selection:text-[var(--color-action-primary-foreground)] file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-label-sm file:text-[var(--color-text-default)] placeholder:text-[var(--color-text-hint)] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
12
12
|
"focus-visible:border-[var(--color-border-focus)] focus-visible:ring-[3px] focus-visible:ring-[var(--color-border-focus)]/50",
|
|
13
13
|
"aria-invalid:border-[var(--color-border-error)] aria-invalid:ring-[3px] aria-invalid:ring-[var(--color-border-error)]/20",
|
|
14
14
|
className
|
|
@@ -6,7 +6,6 @@ import type { DateRange } from "react-day-picker"
|
|
|
6
6
|
|
|
7
7
|
import { cn } from "../../lib/utils"
|
|
8
8
|
import type { DateTimeRange } from "./date-time-range-picker"
|
|
9
|
-
import { Button } from "./button"
|
|
10
9
|
import { FilterChip } from "./filter-chip"
|
|
11
10
|
import { FilterCombobox } from "./filter-combobox"
|
|
12
11
|
import type { FilterCategory, CategoryValue } from "./filter-combobox"
|
|
@@ -90,9 +89,8 @@ function SearchBar({
|
|
|
90
89
|
children,
|
|
91
90
|
className,
|
|
92
91
|
}: SearchBarProps) {
|
|
93
|
-
const hasActiveFilters
|
|
94
|
-
const
|
|
95
|
-
const showFilterBar = hasActiveFilters || alwaysShowFilterBar
|
|
92
|
+
const hasActiveFilters = Object.values(activeFilters).some(v => v.length > 0)
|
|
93
|
+
const showFilterBar = hasActiveFilters || alwaysShowFilterBar
|
|
96
94
|
|
|
97
95
|
return (
|
|
98
96
|
<div data-search-bar className={cn("relative flex flex-col", className)}>
|
|
@@ -116,31 +114,14 @@ function SearchBar({
|
|
|
116
114
|
onFocus={onFocus}
|
|
117
115
|
autoComplete="off"
|
|
118
116
|
/>
|
|
119
|
-
{(!!value || (
|
|
117
|
+
{(!!value || (!value && !!kbdHint)) && (
|
|
120
118
|
<InputGroupAddon align="inline-end">
|
|
121
119
|
{value && (
|
|
122
120
|
<InputGroupButton size="sm" variant="ghost" onClick={() => onChange("")} className="text-[var(--color-text-muted)] hover:text-[var(--color-text-default)]">
|
|
123
121
|
<XIcon className="size-4" />
|
|
124
122
|
</InputGroupButton>
|
|
125
123
|
)}
|
|
126
|
-
{!value && kbdHint &&
|
|
127
|
-
{hasFilterCategories && !hasActiveFilters && !alwaysShowFilterBar && (
|
|
128
|
-
<>
|
|
129
|
-
{!value && kbdHint && <Kbd>{kbdHint}</Kbd>}
|
|
130
|
-
<span className="h-4 w-px bg-[var(--color-border-default)]" />
|
|
131
|
-
<FilterCombobox
|
|
132
|
-
categories={filterCategories}
|
|
133
|
-
onApply={onApplyFilter ?? (() => {})}
|
|
134
|
-
activeFilters={activeFilters}
|
|
135
|
-
dropdownAlign="right"
|
|
136
|
-
trigger={({ onClick }) => (
|
|
137
|
-
<InputGroupButton size="sm" variant="ghost" onClick={onClick} className="text-[var(--color-text-muted)] hover:text-[var(--color-text-default)]">
|
|
138
|
-
Advanced search
|
|
139
|
-
</InputGroupButton>
|
|
140
|
-
)}
|
|
141
|
-
/>
|
|
142
|
-
</>
|
|
143
|
-
)}
|
|
124
|
+
{!value && kbdHint && <Kbd>{kbdHint}</Kbd>}
|
|
144
125
|
</InputGroupAddon>
|
|
145
126
|
)}
|
|
146
127
|
</InputGroup>
|
|
@@ -148,98 +129,58 @@ function SearchBar({
|
|
|
148
129
|
{/* Filter bar */}
|
|
149
130
|
{showFilterBar && (
|
|
150
131
|
<div className="flex flex-wrap items-center gap-3 [border-bottom-left-radius:var(--radius-card)] [border-bottom-right-radius:var(--radius-card)] border border-t-0 border-[var(--color-border-default)] bg-[var(--color-bg-raised)] px-3 py-2.5">
|
|
151
|
-
{
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
activeFilters={activeFilters}
|
|
166
|
-
trigger={({ onClick }) => (
|
|
167
|
-
<FilterChip
|
|
168
|
-
label={cat.label}
|
|
169
|
-
values={activeVals.map(v => ({
|
|
170
|
-
label: filterValueLabel(cat.id, v),
|
|
171
|
-
onRemove: cat.type === "datetime" ? undefined : () => onRemoveFilter?.(cat.id, v),
|
|
172
|
-
}))}
|
|
173
|
-
onLabelClick={onClick}
|
|
174
|
-
/>
|
|
175
|
-
)}
|
|
176
|
-
/>
|
|
177
|
-
)
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return (
|
|
181
|
-
<FilterCombobox
|
|
182
|
-
key={cat.id}
|
|
183
|
-
categories={[cat]}
|
|
184
|
-
onApply={onApplyFilter ?? (() => {})}
|
|
185
|
-
activeFilters={activeFilters}
|
|
186
|
-
trigger={({ onClick }) => (
|
|
187
|
-
<button
|
|
188
|
-
type="button"
|
|
189
|
-
onClick={onClick}
|
|
190
|
-
className="inline-flex items-center gap-1 rounded-full border border-[var(--color-border-default)] px-2 py-0.5 text-caption text-[var(--color-text-muted)] hover:text-[var(--color-text-default)] hover:border-[var(--color-border-hover,var(--color-border-default))] transition-colors"
|
|
191
|
-
>
|
|
192
|
-
{cat.label}
|
|
193
|
-
<PlusIcon className="size-3 shrink-0" />
|
|
194
|
-
</button>
|
|
195
|
-
)}
|
|
196
|
-
/>
|
|
197
|
-
)
|
|
198
|
-
})}
|
|
199
|
-
{hasActiveFilters && (
|
|
200
|
-
<FilterChip
|
|
201
|
-
variant="clear-all"
|
|
202
|
-
className="ml-auto"
|
|
203
|
-
onClear={onClearFilters ?? (() => {})}
|
|
204
|
-
/>
|
|
205
|
-
)}
|
|
206
|
-
</>
|
|
207
|
-
) : (
|
|
208
|
-
// Legacy mode: active chips + generic Add button
|
|
209
|
-
<>
|
|
210
|
-
{Object.entries(activeFilters)
|
|
211
|
-
.filter(([, vals]) => vals.length > 0)
|
|
212
|
-
.map(([categoryId, values]) => {
|
|
213
|
-
const cat = filterCategories.find(c => c.id === categoryId)
|
|
214
|
-
return (
|
|
132
|
+
{/* One trigger per category, active ones show chips */}
|
|
133
|
+
<span className="text-caption text-[var(--color-text-default)] shrink-0">Filters:</span>
|
|
134
|
+
{filterCategories.map(cat => {
|
|
135
|
+
const activeVals = activeFilters[cat.id] ?? []
|
|
136
|
+
const hasActive = activeVals.length > 0
|
|
137
|
+
|
|
138
|
+
if (hasActive) {
|
|
139
|
+
return (
|
|
140
|
+
<FilterCombobox
|
|
141
|
+
key={cat.id}
|
|
142
|
+
categories={[cat]}
|
|
143
|
+
onApply={onApplyFilter ?? (() => {})}
|
|
144
|
+
activeFilters={activeFilters}
|
|
145
|
+
trigger={({ onClick }) => (
|
|
215
146
|
<FilterChip
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
onRemove: () => onRemoveFilter?.(categoryId, v),
|
|
147
|
+
label={cat.label}
|
|
148
|
+
values={activeVals.map(v => ({
|
|
149
|
+
label: filterValueLabel(cat.id, v),
|
|
150
|
+
onRemove: cat.type === "datetime" ? undefined : () => onRemoveFilter?.(cat.id, v),
|
|
221
151
|
}))}
|
|
222
|
-
onLabelClick={
|
|
152
|
+
onLabelClick={onClick}
|
|
223
153
|
/>
|
|
224
|
-
)
|
|
225
|
-
|
|
154
|
+
)}
|
|
155
|
+
/>
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return (
|
|
226
160
|
<FilterCombobox
|
|
227
|
-
|
|
161
|
+
key={cat.id}
|
|
162
|
+
categories={[cat]}
|
|
228
163
|
onApply={onApplyFilter ?? (() => {})}
|
|
229
164
|
activeFilters={activeFilters}
|
|
230
165
|
trigger={({ onClick }) => (
|
|
231
|
-
<
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
166
|
+
<button
|
|
167
|
+
type="button"
|
|
168
|
+
onClick={onClick}
|
|
169
|
+
className="inline-flex items-center gap-1 rounded-full border border-[var(--color-border-default)] px-2 py-0.5 text-caption text-[var(--color-text-muted)] hover:text-[var(--color-text-default)] hover:border-[var(--color-border-hover,var(--color-border-default))] transition-colors"
|
|
170
|
+
>
|
|
171
|
+
{cat.label}
|
|
172
|
+
<PlusIcon className="size-3 shrink-0" />
|
|
173
|
+
</button>
|
|
235
174
|
)}
|
|
236
175
|
/>
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
176
|
+
)
|
|
177
|
+
})}
|
|
178
|
+
{hasActiveFilters && (
|
|
179
|
+
<FilterChip
|
|
180
|
+
variant="clear-all"
|
|
181
|
+
className="ml-auto"
|
|
182
|
+
onClear={onClearFilters ?? (() => {})}
|
|
183
|
+
/>
|
|
243
184
|
)}
|
|
244
185
|
</div>
|
|
245
186
|
)}
|
|
@@ -10,7 +10,7 @@ function TabCount({ count, className }: TabCountProps) {
|
|
|
10
10
|
return (
|
|
11
11
|
<span
|
|
12
12
|
className={cn(
|
|
13
|
-
"inline-flex items-center justify-center rounded-full bg-[var(--color-bg-disabled)] text-[var(--color-text-default)] text-[10px] font-semibold leading-none
|
|
13
|
+
"inline-flex items-center justify-center rounded-full bg-[var(--color-bg-disabled)] text-[var(--color-text-default)] text-[10px] font-semibold leading-none min-w-4 h-4 px-1 shrink-0",
|
|
14
14
|
className
|
|
15
15
|
)}
|
|
16
16
|
>
|
package/tokens/primitives.css
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
--primitive-beige-950: oklch(0.230 0.020 98);
|
|
36
36
|
|
|
37
37
|
--primitive-red-50: oklch(0.95 0.03 28);
|
|
38
|
-
--primitive-red-100: oklch(0.
|
|
38
|
+
--primitive-red-100: oklch(0.933859 0.034874 39.988);
|
|
39
39
|
--primitive-red-200: oklch(0.89 0.07 28);
|
|
40
40
|
--primitive-red-300: oklch(0.84 0.11 28);
|
|
41
41
|
--primitive-red-400: oklch(0.79 0.16 28);
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
--primitive-yellow-900: oklch(0.3 0.07 98);
|
|
71
71
|
--primitive-yellow-950: oklch(0.25 0.06 98);
|
|
72
72
|
|
|
73
|
-
--primitive-lulo-50: oklch(0.
|
|
73
|
+
--primitive-lulo-50: oklch(0.9654 0.1157 112.05);
|
|
74
74
|
--primitive-lulo-100: oklch(0.918 0.136 116);
|
|
75
75
|
--primitive-lulo-200: oklch(0.869 0.173 114);
|
|
76
76
|
--primitive-lulo-300: oklch(0.82 0.21 112);
|
|
@@ -99,12 +99,12 @@
|
|
|
99
99
|
--primitive-aquamarine-200: oklch(0.85 0.24 167);
|
|
100
100
|
--primitive-aquamarine-300: oklch(0.8 0.22 167);
|
|
101
101
|
--primitive-aquamarine-400: oklch(0.74 0.21 167);
|
|
102
|
-
--primitive-aquamarine-500: oklch(0.
|
|
103
|
-
--primitive-aquamarine-600: oklch(0.
|
|
104
|
-
--primitive-aquamarine-700: oklch(0.
|
|
105
|
-
--primitive-aquamarine-800: oklch(0.
|
|
106
|
-
--primitive-aquamarine-900: oklch(0.
|
|
107
|
-
--primitive-aquamarine-950: oklch(0.
|
|
102
|
+
--primitive-aquamarine-500: oklch(0.642 0.165 167);
|
|
103
|
+
--primitive-aquamarine-600: oklch(0.544 0.120 167);
|
|
104
|
+
--primitive-aquamarine-700: oklch(0.446 0.075 168);
|
|
105
|
+
--primitive-aquamarine-800: oklch(0.3479 0.0291 167.95);
|
|
106
|
+
--primitive-aquamarine-900: oklch(0.268 0.022 168);
|
|
107
|
+
--primitive-aquamarine-950: oklch(0.218 0.016 168);
|
|
108
108
|
|
|
109
109
|
--primitive-sea-50: oklch(0.94 0.04 220);
|
|
110
110
|
--primitive-sea-100: oklch(0.92 0.06 220);
|
|
@@ -118,17 +118,17 @@
|
|
|
118
118
|
--primitive-sea-900: oklch(0.29 0.07 220);
|
|
119
119
|
--primitive-sea-950: oklch(0.24 0.06 220);
|
|
120
120
|
|
|
121
|
-
--primitive-slate-50: oklch(0.
|
|
122
|
-
--primitive-slate-100: oklch(0.
|
|
123
|
-
--primitive-slate-200: oklch(0.
|
|
124
|
-
--primitive-slate-300: oklch(0.
|
|
125
|
-
--primitive-slate-400: oklch(0.762 0.
|
|
126
|
-
--primitive-slate-500: oklch(0.
|
|
127
|
-
--primitive-slate-600: oklch(0.
|
|
128
|
-
--primitive-slate-700: oklch(0.
|
|
129
|
-
--primitive-slate-800: oklch(0.
|
|
130
|
-
--primitive-slate-900: oklch(0.
|
|
131
|
-
--primitive-slate-950: oklch(0.
|
|
121
|
+
--primitive-slate-50: oklch(0.965 0.010 225);
|
|
122
|
+
--primitive-slate-100: oklch(0.930 0.018 226);
|
|
123
|
+
--primitive-slate-200: oklch(0.880 0.030 228);
|
|
124
|
+
--primitive-slate-300: oklch(0.825 0.044 229);
|
|
125
|
+
--primitive-slate-400: oklch(0.762 0.055 231);
|
|
126
|
+
--primitive-slate-500: oklch(0.6916 0.0616 232.57);
|
|
127
|
+
--primitive-slate-600: oklch(0.580 0.045 243);
|
|
128
|
+
--primitive-slate-700: oklch(0.468 0.030 254);
|
|
129
|
+
--primitive-slate-800: oklch(0.3555 0.0149 264.37);
|
|
130
|
+
--primitive-slate-900: oklch(0.270 0.012 268);
|
|
131
|
+
--primitive-slate-950: oklch(0.215 0.010 270);
|
|
132
132
|
|
|
133
133
|
--primitive-blue-50: oklch(0.95 0.03 257);
|
|
134
134
|
--primitive-blue-100: oklch(0.93 0.04 257);
|
package/tokens/semantic.css
CHANGED
|
@@ -154,8 +154,11 @@
|
|
|
154
154
|
--color-brand-beige: var(--primitive-beige-100);
|
|
155
155
|
--color-brand-yellow: var(--primitive-lulo-50);
|
|
156
156
|
--color-brand-rose: var(--primitive-red-100);
|
|
157
|
-
--color-brand-
|
|
157
|
+
--color-brand-coral: var(--primitive-red-500);
|
|
158
158
|
--color-brand-blue: var(--primitive-slate-500);
|
|
159
|
+
--color-brand-darkforest: var(--primitive-aquamarine-800);
|
|
160
|
+
--color-brand-navy: var(--primitive-slate-800);
|
|
161
|
+
--color-brand-bronze: var(--primitive-bronze-900);
|
|
159
162
|
|
|
160
163
|
/* z-index aliases */
|
|
161
164
|
--z-sticky: var(--primitive-z-raised);
|