minka-ds 0.1.7 → 0.1.8

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minka-ds",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Minka product design system — tokenized component library",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -21,13 +21,14 @@ import { Tabs, TabsList, TabsTrigger } from "./tabs"
21
21
  interface FilterCategory {
22
22
  id: string
23
23
  label: string
24
- type?: "list" | "date" | "amount"
24
+ type?: "list" | "date" | "amount" | "hours"
25
25
  values?: string[]
26
26
  renderValue?: (value: string) => React.ReactNode
27
27
  }
28
28
 
29
29
  type AmountValue = { exact: number } | { min?: number; max?: number }
30
- type CategoryValue = string | DateRange | AmountValue
30
+ type HoursValue = { from: string; to: string }
31
+ type CategoryValue = string | DateRange | AmountValue | HoursValue
31
32
 
32
33
 
33
34
  type Step = 1 | 2 | 3
@@ -58,6 +59,8 @@ function FilterCombobox({
58
59
  const [amountExact, setAmountExact] = React.useState("")
59
60
  const [amountMin, setAmountMin] = React.useState("")
60
61
  const [amountMax, setAmountMax] = React.useState("")
62
+ const [hoursInput, setHoursInput] = React.useState("")
63
+ const [hoursInputTo, setHoursInputTo] = React.useState("")
61
64
  const [search, setSearch] = React.useState("")
62
65
 
63
66
  const containerRef = React.useRef<HTMLDivElement>(null)
@@ -90,6 +93,8 @@ function FilterCombobox({
90
93
  setAmountExact("")
91
94
  setAmountMin("")
92
95
  setAmountMax("")
96
+ setHoursInput("")
97
+ setHoursInputTo("")
93
98
  }
94
99
 
95
100
  function handleToggle() {
@@ -117,6 +122,16 @@ function FilterCombobox({
117
122
  return
118
123
  }
119
124
 
125
+ if (cat.type === "hours") {
126
+ setSelectedCategory(cat)
127
+ setSelectedValues(new Set())
128
+ setHoursInput("")
129
+ setHoursInputTo("")
130
+ setSearch("")
131
+ setStep(2)
132
+ return
133
+ }
134
+
120
135
  if (cat.type === "amount") {
121
136
  const custom = existing.find((v): v is AmountValue =>
122
137
  typeof v === "object" && ("exact" in v || "min" in v || "max" in v)
@@ -160,6 +175,12 @@ function FilterCombobox({
160
175
  handleClose()
161
176
  }
162
177
 
178
+ function applyCustomHours() {
179
+ if (!selectedCategory || !hoursInput || !hoursInputTo) return
180
+ onApply(selectedCategory.id, [{ from: hoursInput, to: hoursInputTo }])
181
+ handleClose()
182
+ }
183
+
163
184
  function applyCustomAmount() {
164
185
  if (!selectedCategory) return
165
186
  let value: AmountValue
@@ -190,6 +211,7 @@ function FilterCombobox({
190
211
 
191
212
  const isDate = selectedCategory?.type === "date"
192
213
  const isAmount = selectedCategory?.type === "amount"
214
+ const isHours = selectedCategory?.type === "hours"
193
215
 
194
216
  const step2AllValues = selectedCategory?.values ?? []
195
217
 
@@ -218,7 +240,7 @@ function FilterCombobox({
218
240
  dropdownAlign === "right" ? "absolute right-0 top-full mt-1.5 overflow-hidden [border-radius:var(--radius-popover)]" : "absolute left-0 top-full mt-1.5 overflow-hidden [border-radius:var(--radius-popover)]",
219
241
  "bg-[var(--color-bg-overlay)] shadow-[var(--shadow-popover)] ring-1 ring-[var(--color-border-subtle)]",
220
242
  "[z-index:var(--z-floating)]",
221
- step === 3 && isDate ? "w-auto" : "w-56"
243
+ step === 3 && isDate ? "w-auto" : step === 3 && isHours ? "w-80" : "w-56"
222
244
  )}>
223
245
 
224
246
  {/* Step 1 — category list (multi-category mode only) */}
@@ -251,17 +273,28 @@ function FilterCombobox({
251
273
  ? <EmptyRow />
252
274
  : step2Filtered.map(value => (
253
275
  <li key={value}>
254
- <CheckRow
255
- checked={selectedValues.has(value)}
256
- onToggle={() => toggleValue(value)}
257
- >
258
- {selectedCategory.renderValue?.(value) ?? value}
259
- </CheckRow>
276
+ {selectedCategory.type === "hours" ? (
277
+ <PickerRow onClick={() => { onApply(selectedCategory.id, [value]); handleClose() }}>
278
+ {selectedCategory.renderValue?.(value) ?? value}
279
+ </PickerRow>
280
+ ) : (
281
+ <CheckRow
282
+ checked={selectedValues.has(value)}
283
+ onToggle={() => toggleValue(value)}
284
+ >
285
+ {selectedCategory.renderValue?.(value) ?? value}
286
+ </CheckRow>
287
+ )}
260
288
  </li>
261
289
  ))
262
290
  }
291
+ {selectedCategory.type === "hours" && (
292
+ <li>
293
+ <PickerRow onClick={() => setStep(3)}>Custom range</PickerRow>
294
+ </li>
295
+ )}
263
296
  </ul>
264
- {selectedValues.size > 0 && (
297
+ {selectedValues.size > 0 && selectedCategory.type !== "hours" && (
265
298
  <div className="p-1">
266
299
  <Button size="sm" className="w-full" onClick={applyValues}>
267
300
  Apply
@@ -293,6 +326,39 @@ function FilterCombobox({
293
326
  </>
294
327
  )}
295
328
 
329
+ {/* Step 3 — hours custom range */}
330
+ {step === 3 && isHours && (
331
+ <>
332
+ <StepHeader
333
+ title="Custom range"
334
+ onBack={() => setStep(2)}
335
+ />
336
+ <div className="p-2 flex flex-col gap-2">
337
+ <div className="flex items-center gap-2">
338
+ <Input
339
+ type="time"
340
+ value={hoursInput}
341
+ onChange={e => setHoursInput(e.target.value)}
342
+ className="flex-1"
343
+ />
344
+ <span className="text-body-sm text-[var(--color-text-muted)] shrink-0">–</span>
345
+ <Input
346
+ type="time"
347
+ value={hoursInputTo}
348
+ onChange={e => setHoursInputTo(e.target.value)}
349
+ className="flex-1"
350
+ />
351
+ </div>
352
+ {hoursInput !== "" && hoursInputTo !== "" &&
353
+ !isNaN(parseFloat(hoursInput)) && !isNaN(parseFloat(hoursInputTo)) && (
354
+ <Button size="sm" className="w-full" onClick={applyCustomHours}>
355
+ Apply
356
+ </Button>
357
+ )}
358
+ </div>
359
+ </>
360
+ )}
361
+
296
362
  {/* Step 3 — custom amount */}
297
363
  {step === 3 && isAmount && (
298
364
  <>
@@ -446,4 +512,4 @@ function EmptyRow() {
446
512
  // ── Exports ────────────────────────────────────────────────────────────────────
447
513
 
448
514
  export { FilterCombobox }
449
- export type { FilterCategory, CategoryValue, AmountValue }
515
+ export type { FilterCategory, CategoryValue, AmountValue, HoursValue }