@repraze/kernelkit 0.1.0-alpha.3 → 0.1.0-alpha.5
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 +17 -0
- package/dist/components/alert-dialog.d.ts.map +1 -1
- package/dist/components/alert-dialog.js +4 -1
- package/dist/components/alert-dialog.js.map +1 -1
- package/dist/components/alert.js +3 -3
- package/dist/components/alert.js.map +1 -1
- package/dist/components/badge.js +1 -1
- package/dist/components/badge.js.map +1 -1
- package/dist/components/button.js +1 -1
- package/dist/components/button.js.map +1 -1
- package/dist/components/calendar.d.ts +8 -1
- package/dist/components/calendar.d.ts.map +1 -1
- package/dist/components/calendar.js +33 -11
- package/dist/components/calendar.js.map +1 -1
- package/dist/components/callout.js +2 -2
- package/dist/components/callout.js.map +1 -1
- package/dist/components/combobox.js +1 -1
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/date-picker.d.ts +11 -5
- package/dist/components/date-picker.d.ts.map +1 -1
- package/dist/components/date-picker.js +29 -7
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/description-list.d.ts +26 -0
- package/dist/components/description-list.d.ts.map +1 -0
- package/dist/components/description-list.js +59 -0
- package/dist/components/description-list.js.map +1 -0
- package/dist/components/locale.d.ts +19 -0
- package/dist/components/locale.d.ts.map +1 -0
- package/dist/components/locale.js +54 -0
- package/dist/components/locale.js.map +1 -0
- package/dist/components/popover.d.ts +1 -1
- package/dist/components/popover.d.ts.map +1 -1
- package/dist/components/popover.js +2 -2
- package/dist/components/popover.js.map +1 -1
- package/dist/components/progress.d.ts +19 -6
- package/dist/components/progress.d.ts.map +1 -1
- package/dist/components/progress.js +18 -3
- package/dist/components/progress.js.map +1 -1
- package/dist/components/search-dialog.d.ts +6 -1
- package/dist/components/search-dialog.d.ts.map +1 -1
- package/dist/components/search-dialog.js +13 -1
- package/dist/components/search-dialog.js.map +1 -1
- package/dist/components/search-trigger.d.ts +4 -1
- package/dist/components/search-trigger.d.ts.map +1 -1
- package/dist/components/search-trigger.js +5 -2
- package/dist/components/search-trigger.js.map +1 -1
- package/dist/components/shimmer.d.ts +13 -0
- package/dist/components/shimmer.d.ts.map +1 -0
- package/dist/components/shimmer.js +21 -0
- package/dist/components/shimmer.js.map +1 -0
- package/dist/components/spinner.d.ts +28 -6
- package/dist/components/spinner.d.ts.map +1 -1
- package/dist/components/spinner.js +66 -14
- package/dist/components/spinner.js.map +1 -1
- package/dist/components/stepper.d.ts +64 -0
- package/dist/components/stepper.d.ts.map +1 -0
- package/dist/components/stepper.js +167 -0
- package/dist/components/stepper.js.map +1 -0
- package/dist/components/tag-input.d.ts +47 -0
- package/dist/components/tag-input.d.ts.map +1 -0
- package/dist/components/tag-input.js +211 -0
- package/dist/components/tag-input.js.map +1 -0
- package/dist/components/time-input.d.ts +75 -0
- package/dist/components/time-input.d.ts.map +1 -0
- package/dist/components/time-input.js +341 -0
- package/dist/components/time-input.js.map +1 -0
- package/dist/components/time-select.d.ts +49 -0
- package/dist/components/time-select.d.ts.map +1 -0
- package/dist/components/time-select.js +178 -0
- package/dist/components/time-select.js.map +1 -0
- package/dist/components/timeline.d.ts +41 -0
- package/dist/components/timeline.d.ts.map +1 -0
- package/dist/components/timeline.js +83 -0
- package/dist/components/timeline.js.map +1 -0
- package/dist/components/toast.d.ts.map +1 -1
- package/dist/components/toast.js +4 -2
- package/dist/components/toast.js.map +1 -1
- package/dist/components/tree.d.ts +87 -0
- package/dist/components/tree.d.ts.map +1 -0
- package/dist/components/tree.js +516 -0
- package/dist/components/tree.js.map +1 -0
- package/dist/docs/doc-kit.d.ts +72 -0
- package/dist/docs/doc-kit.d.ts.map +1 -0
- package/dist/docs/doc-kit.js +45 -0
- package/dist/docs/doc-kit.js.map +1 -0
- package/dist/docs/doc-page.d.ts +27 -0
- package/dist/docs/doc-page.d.ts.map +1 -0
- package/dist/docs/doc-page.js +33 -0
- package/dist/docs/doc-page.js.map +1 -0
- package/dist/docs/docs-index.d.ts +60 -0
- package/dist/docs/docs-index.d.ts.map +1 -0
- package/dist/docs/docs-index.js +45 -0
- package/dist/docs/docs-index.js.map +1 -0
- package/dist/docs/docs-nav.d.ts +13 -0
- package/dist/docs/docs-nav.d.ts.map +1 -0
- package/dist/docs/docs-nav.js +8 -0
- package/dist/docs/docs-nav.js.map +1 -0
- package/dist/docs/docs-search.d.ts +19 -0
- package/dist/docs/docs-search.d.ts.map +1 -0
- package/dist/docs/docs-search.js +33 -0
- package/dist/docs/docs-search.js.map +1 -0
- package/dist/docs/index.d.ts +7 -0
- package/dist/docs/index.d.ts.map +1 -0
- package/dist/docs/index.js +7 -0
- package/dist/docs/index.js.map +1 -0
- package/dist/docs/review-matrix.d.ts +25 -0
- package/dist/docs/review-matrix.d.ts.map +1 -0
- package/dist/docs/review-matrix.js +31 -0
- package/dist/docs/review-matrix.js.map +1 -0
- package/dist/hooks/use-theme-palette.d.ts +8 -0
- package/dist/hooks/use-theme-palette.d.ts.map +1 -0
- package/dist/hooks/use-theme-palette.js +24 -0
- package/dist/hooks/use-theme-palette.js.map +1 -0
- package/dist/hooks/use-time-format.d.ts +23 -0
- package/dist/hooks/use-time-format.d.ts.map +1 -0
- package/dist/hooks/use-time-format.js +52 -0
- package/dist/hooks/use-time-format.js.map +1 -0
- package/dist/lib/color.d.ts +5 -1
- package/dist/lib/color.d.ts.map +1 -1
- package/dist/lib/color.js +14 -2
- package/dist/lib/color.js.map +1 -1
- package/dist/lib/recipes.d.ts +5 -4
- package/dist/lib/recipes.d.ts.map +1 -1
- package/dist/lib/recipes.js +7 -5
- package/dist/lib/recipes.js.map +1 -1
- package/dist/provider/theme-provider.d.ts +10 -1
- package/dist/provider/theme-provider.d.ts.map +1 -1
- package/dist/provider/theme-provider.js +23 -8
- package/dist/provider/theme-provider.js.map +1 -1
- package/dist/site/brand.d.ts +20 -0
- package/dist/site/brand.d.ts.map +1 -0
- package/dist/site/brand.js +17 -0
- package/dist/site/brand.js.map +1 -0
- package/dist/site/github-icon.d.ts +4 -0
- package/dist/site/github-icon.d.ts.map +1 -0
- package/dist/site/github-icon.js +6 -0
- package/dist/site/github-icon.js.map +1 -0
- package/dist/site/index.d.ts +6 -0
- package/dist/site/index.d.ts.map +1 -0
- package/dist/site/index.js +6 -0
- package/dist/site/index.js.map +1 -0
- package/dist/site/suite-footer.d.ts +24 -0
- package/dist/site/suite-footer.d.ts.map +1 -0
- package/dist/site/suite-footer.js +19 -0
- package/dist/site/suite-footer.js.map +1 -0
- package/dist/site/suite-header.d.ts +40 -0
- package/dist/site/suite-header.d.ts.map +1 -0
- package/dist/site/suite-header.js +19 -0
- package/dist/site/suite-header.js.map +1 -0
- package/dist/site/use-page-title.d.ts +3 -0
- package/dist/site/use-page-title.d.ts.map +1 -0
- package/dist/site/use-page-title.js +8 -0
- package/dist/site/use-page-title.js.map +1 -0
- package/dist/vite/index.d.ts +65 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +242 -0
- package/dist/vite/index.js.map +1 -0
- package/package.json +39 -3
- package/src/components/alert-dialog.tsx +4 -1
- package/src/components/alert.tsx +3 -3
- package/src/components/badge.tsx +1 -1
- package/src/components/button.tsx +1 -1
- package/src/components/calendar.tsx +48 -4
- package/src/components/callout.tsx +2 -2
- package/src/components/combobox.tsx +1 -1
- package/src/components/date-picker.tsx +43 -9
- package/src/components/description-list.tsx +107 -0
- package/src/components/locale.tsx +67 -0
- package/src/components/popover.tsx +3 -1
- package/src/components/progress.tsx +70 -4
- package/src/components/search-dialog.tsx +14 -1
- package/src/components/search-trigger.tsx +8 -2
- package/src/components/shimmer.tsx +36 -0
- package/src/components/spinner.tsx +126 -23
- package/src/components/stepper.tsx +346 -0
- package/src/components/tag-input.tsx +345 -0
- package/src/components/time-input.tsx +578 -0
- package/src/components/time-select.tsx +291 -0
- package/src/components/timeline.tsx +190 -0
- package/src/components/toast.tsx +4 -4
- package/src/components/tree.tsx +832 -0
- package/src/docs/doc-kit.tsx +176 -0
- package/src/docs/doc-page.tsx +126 -0
- package/src/docs/docs-index.ts +108 -0
- package/src/docs/docs-nav.tsx +47 -0
- package/src/docs/docs-search.tsx +88 -0
- package/src/docs/index.ts +6 -0
- package/src/docs/review-matrix.tsx +67 -0
- package/src/hooks/use-theme-palette.ts +25 -0
- package/src/hooks/use-time-format.ts +72 -0
- package/src/lib/color.ts +19 -2
- package/src/lib/recipes.ts +7 -5
- package/src/provider/theme-provider.tsx +34 -9
- package/src/site/brand.tsx +41 -0
- package/src/site/github-icon.tsx +10 -0
- package/src/site/index.ts +5 -0
- package/src/site/suite-footer.tsx +68 -0
- package/src/site/suite-header.tsx +114 -0
- package/src/site/use-page-title.ts +8 -0
- package/src/styles/kernelkit.css +58 -0
- package/src/styles/site.css +15 -0
- package/src/vite/client.d.ts +11 -0
- package/src/vite/index.ts +298 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { Popover, PopoverContent, PopoverTrigger } from "@repraze/kernelkit/components/popover";
|
|
4
|
+
import { useTimeFormat } from "@repraze/kernelkit/hooks/use-time-format";
|
|
5
|
+
import { fieldSurface, invalidRing } from "@repraze/kernelkit/lib/recipes";
|
|
6
|
+
import { cva } from "class-variance-authority";
|
|
7
|
+
import { cn } from "cn";
|
|
8
|
+
import { ClockIcon } from "lucide-react";
|
|
9
|
+
import * as React from "react";
|
|
10
|
+
/**
|
|
11
|
+
* Segmented time field (GUIDELINES §4, §6). The container is the field surface; it rings while any
|
|
12
|
+
* segment has focus, like a text input does on click.
|
|
13
|
+
*/
|
|
14
|
+
const timeInputVariants = cva([
|
|
15
|
+
fieldSurface,
|
|
16
|
+
invalidRing,
|
|
17
|
+
"inline-flex w-fit min-w-0 cursor-text items-center text-base md:text-sm",
|
|
18
|
+
"has-[[data-slot=time-input-segment]:focus]:border-ring has-[[data-slot=time-input-segment]:focus]:ring-3 has-[[data-slot=time-input-segment]:focus]:ring-ring/50",
|
|
19
|
+
"data-disabled:cursor-not-allowed data-disabled:bg-field-disabled data-disabled:opacity-50",
|
|
20
|
+
"[&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
21
|
+
], {
|
|
22
|
+
variants: {
|
|
23
|
+
size: {
|
|
24
|
+
// icon inset and icon-to-text gap match a Button with an inline-start icon (DatePicker's
|
|
25
|
+
// trigger), counting the segment's own 2px padding: 8 / 6px default, 6 / 4px sm, 10 / 8px lg
|
|
26
|
+
sm: "h-7 gap-0.5 rounded-md ps-1.5 pe-2 md:text-[0.8rem] [&_svg]:size-3.5",
|
|
27
|
+
default: "h-8 gap-1 ps-2 pe-2.5 [&_svg]:size-4",
|
|
28
|
+
lg: "h-9 gap-1.5 ps-2.5 pe-3 [&_svg]:size-4",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
defaultVariants: { size: "default" },
|
|
32
|
+
});
|
|
33
|
+
/** One editable part (hours, minutes, seconds, AM/PM). Focus is a solid accent chip, like a native text selection (a tint vanished on the dark field). */
|
|
34
|
+
const timeInputSegmentVariants = cva("rounded-box px-0.5 font-mono tabular-nums outline-none caret-transparent select-none transition-[color,background-color] hover:bg-hover focus:bg-primary focus:text-primary-foreground data-placeholder:text-muted-foreground data-placeholder:focus:text-primary-foreground aria-disabled:pointer-events-none");
|
|
35
|
+
const EMPTY = { hour: null, minute: null, second: null, period: null };
|
|
36
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
37
|
+
function parse(value, cycle) {
|
|
38
|
+
const m = value ? /^(\d{1,2}):(\d{2})(?::(\d{2}))?$/.exec(value) : null;
|
|
39
|
+
if (!m) {
|
|
40
|
+
return EMPTY;
|
|
41
|
+
}
|
|
42
|
+
const h = Math.min(23, Number(m[1]));
|
|
43
|
+
const minute = Math.min(59, Number(m[2]));
|
|
44
|
+
const second = m[3] === undefined ? 0 : Math.min(59, Number(m[3]));
|
|
45
|
+
if (cycle === 24) {
|
|
46
|
+
return { hour: h, minute, second, period: null };
|
|
47
|
+
}
|
|
48
|
+
return { hour: h % 12 || 12, minute, second, period: h < 12 ? "AM" : "PM" };
|
|
49
|
+
}
|
|
50
|
+
function serialize(s, cycle, seconds) {
|
|
51
|
+
if (s.hour === null || s.minute === null || (seconds && s.second === null) || (cycle === 12 && !s.period)) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const h = cycle === 24 ? s.hour : (s.hour % 12) + (s.period === "PM" ? 12 : 0);
|
|
55
|
+
return `${pad(h)}:${pad(s.minute)}${seconds ? `:${pad(s.second ?? 0)}` : ""}`;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A time field split into segments, each a spinbutton: arrows step with wrap, digits fill and move on,
|
|
59
|
+
* Backspace clears, Left / Right (or `:`) move between segments, `a` / `p` set the period.
|
|
60
|
+
*/
|
|
61
|
+
function TimeInput({ value, defaultValue = null, onValueChange, seconds = false, hourCycle: hourCyclePreference = "auto", locale, step = 1, size = "default", disabled = false, icon = true, picker = true, name, id, className, ...props }) {
|
|
62
|
+
const [pickerOpen, setPickerOpen] = React.useState(false);
|
|
63
|
+
const fmt = useTimeFormat(hourCyclePreference, locale);
|
|
64
|
+
const hourCycle = fmt.hourCycle;
|
|
65
|
+
const controlled = value !== undefined;
|
|
66
|
+
const [segs, setSegs] = React.useState(() => parse(controlled ? value : defaultValue, hourCycle));
|
|
67
|
+
// the locale's cycle can arrive after hydration (SSR renders 24h): carry the time over to the new cycle
|
|
68
|
+
const [segsCycle, setSegsCycle] = React.useState(hourCycle);
|
|
69
|
+
if (segsCycle !== hourCycle) {
|
|
70
|
+
setSegsCycle(hourCycle);
|
|
71
|
+
setSegs(parse(serialize(fill(segs, segsCycle), segsCycle, seconds), hourCycle));
|
|
72
|
+
}
|
|
73
|
+
// controlled: follow outside changes that differ from what the segments already say
|
|
74
|
+
const [seen, setSeen] = React.useState(value);
|
|
75
|
+
if (controlled && value !== seen) {
|
|
76
|
+
setSeen(value);
|
|
77
|
+
if (value !== serialize(segs, hourCycle, seconds)) {
|
|
78
|
+
setSegs(parse(value, hourCycle));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const typed = React.useRef("");
|
|
82
|
+
const refs = React.useRef({});
|
|
83
|
+
// visual order: the day period leads in locales that write it first ("午前 09:30")
|
|
84
|
+
const parts = [
|
|
85
|
+
...(hourCycle === 12 && fmt.periodFirst ? ["period"] : []),
|
|
86
|
+
"hour",
|
|
87
|
+
"minute",
|
|
88
|
+
...(seconds ? ["second"] : []),
|
|
89
|
+
...(hourCycle === 12 && !fmt.periodFirst ? ["period"] : []),
|
|
90
|
+
];
|
|
91
|
+
const update = (patch) => {
|
|
92
|
+
const next = { ...segs, ...patch };
|
|
93
|
+
const before = serialize(segs, hourCycle, seconds);
|
|
94
|
+
const after = serialize(next, hourCycle, seconds);
|
|
95
|
+
setSegs(next);
|
|
96
|
+
if (controlled) {
|
|
97
|
+
setSeen(after);
|
|
98
|
+
}
|
|
99
|
+
if (after !== before) {
|
|
100
|
+
onValueChange?.(after);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const move = (from, delta) => {
|
|
104
|
+
const target = parts[parts.indexOf(from) + delta];
|
|
105
|
+
if (target) {
|
|
106
|
+
refs.current[target]?.focus();
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const range = (part) => part === "hour" ? (hourCycle === 12 ? [1, 12] : [0, 23]) : part === "period" ? [0, 1] : [0, 59];
|
|
110
|
+
const onKeyDown = (e, part) => {
|
|
111
|
+
if (disabled || e.metaKey || e.ctrlKey || e.altKey) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const rtl = getComputedStyle(e.currentTarget).direction === "rtl";
|
|
115
|
+
const key = e.key;
|
|
116
|
+
const [min, max] = range(part);
|
|
117
|
+
const current = part === "period" ? (segs.period === null ? null : segs.period === "AM" ? 0 : 1) : segs[part];
|
|
118
|
+
const set = (n) => update(part === "period" ? { period: n === null ? null : n === 0 ? "AM" : "PM" } : { [part]: n });
|
|
119
|
+
if (key === "ArrowUp" || key === "ArrowDown" || key === "PageUp" || key === "PageDown") {
|
|
120
|
+
e.preventDefault();
|
|
121
|
+
typed.current = "";
|
|
122
|
+
const dir = key === "ArrowUp" || key === "PageUp" ? 1 : -1;
|
|
123
|
+
const by = part === "minute" ? step : 1;
|
|
124
|
+
const span = max - min + 1;
|
|
125
|
+
if (current === null) {
|
|
126
|
+
set(dir > 0 ? min : part === "minute" ? max - (max % step) : max);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// snap to the step grid, then wrap
|
|
130
|
+
const snapped = part === "minute" && current % by ? current - (current % by) + (dir > 0 ? 0 : by) : current;
|
|
131
|
+
set(((((snapped - min + dir * by) % span) + span) % span) + min);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else if (key === "Home" || key === "End") {
|
|
135
|
+
e.preventDefault();
|
|
136
|
+
set(key === "Home" ? min : max);
|
|
137
|
+
}
|
|
138
|
+
else if (key === "Backspace" || key === "Delete") {
|
|
139
|
+
e.preventDefault();
|
|
140
|
+
typed.current = "";
|
|
141
|
+
if (current === null && key === "Backspace") {
|
|
142
|
+
move(part, -1);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
set(null);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else if (key === (rtl ? "ArrowRight" : "ArrowLeft")) {
|
|
149
|
+
e.preventDefault();
|
|
150
|
+
move(part, -1);
|
|
151
|
+
}
|
|
152
|
+
else if (key === (rtl ? "ArrowLeft" : "ArrowRight") || key === ":" || key === "." || key === " ") {
|
|
153
|
+
e.preventDefault();
|
|
154
|
+
move(part, 1);
|
|
155
|
+
}
|
|
156
|
+
else if (part === "period" && /^[ap]$/i.test(key)) {
|
|
157
|
+
e.preventDefault();
|
|
158
|
+
set(key.toLowerCase() === "a" ? 0 : 1);
|
|
159
|
+
}
|
|
160
|
+
else if (part !== "period" && /^\d$/.test(key)) {
|
|
161
|
+
e.preventDefault();
|
|
162
|
+
const buffer = typed.current + key;
|
|
163
|
+
const n = Number(buffer);
|
|
164
|
+
if (buffer.length === 2 || n * 10 > max) {
|
|
165
|
+
// complete: take it if it fits, else start over with this digit
|
|
166
|
+
const final = n >= min && n <= max ? n : Number(key);
|
|
167
|
+
set(final);
|
|
168
|
+
typed.current = "";
|
|
169
|
+
move(part, 1);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
// first digit: shown, and kept pending for a second one ("0" in a 1-12 hour shows empty)
|
|
173
|
+
typed.current = buffer;
|
|
174
|
+
set(n < min ? null : n);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
else if (key === "Tab") {
|
|
178
|
+
typed.current = "";
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
const label = { hour: "Hours", minute: "Minutes", second: "Seconds", period: "AM/PM" };
|
|
182
|
+
const segment = (part) => {
|
|
183
|
+
const [min, max] = range(part);
|
|
184
|
+
const v = part === "period" ? segs.period : segs[part];
|
|
185
|
+
const text = v === null ? "--" : typeof v === "number" ? fmt.digits(v) : v === "AM" ? fmt.am : fmt.pm;
|
|
186
|
+
return (_jsx("span", { ref: (el) => {
|
|
187
|
+
refs.current[part] = el;
|
|
188
|
+
}, id: part === "hour" ? id : undefined, role: "spinbutton", tabIndex: disabled ? -1 : 0, "aria-label": label[part], "aria-valuemin": min, "aria-valuemax": max, "aria-valuenow": v === null ? undefined : part === "period" ? (v === "AM" ? 0 : 1) : v, "aria-valuetext": v === null ? "Empty" : String(text), "aria-disabled": disabled || undefined, inputMode: part === "period" ? "text" : "numeric", "data-slot": "time-input-segment", "data-part": part, "data-placeholder": v === null ? "" : undefined, className: timeInputSegmentVariants(), onKeyDown: (e) => onKeyDown(e, part), onFocus: () => {
|
|
189
|
+
typed.current = "";
|
|
190
|
+
}, children: text }, part));
|
|
191
|
+
};
|
|
192
|
+
const fieldRef = React.useRef(null);
|
|
193
|
+
const current = serialize(segs, hourCycle, seconds);
|
|
194
|
+
return (_jsxs("div", { ref: fieldRef, role: "group", "data-slot": "time-input", "data-size": size, "data-disabled": disabled ? "" : undefined, className: cn(timeInputVariants({ size }), className), onMouseDown: (e) => {
|
|
195
|
+
// a click on the padding or icon goes to the first empty segment, else the first one
|
|
196
|
+
const target = e.target;
|
|
197
|
+
if (!disabled && !target.closest("[data-slot=time-input-segment],[data-slot=time-input-picker]")) {
|
|
198
|
+
e.preventDefault();
|
|
199
|
+
const empty = parts.find((p) => (p === "period" ? segs.period : segs[p]) === null);
|
|
200
|
+
refs.current[empty ?? "hour"]?.focus();
|
|
201
|
+
}
|
|
202
|
+
}, ...props, children: [icon && picker ? (_jsxs(Popover, { open: pickerOpen, onOpenChange: setPickerOpen, children: [_jsx(PopoverTrigger, { "data-slot": "time-input-picker", disabled: disabled, "aria-label": "Choose time",
|
|
203
|
+
// a bare icon in the same place and size as a plain icon (and DatePicker's), with a
|
|
204
|
+
// 32px hit area; hover and open turn it foreground, keyboard focus rings it
|
|
205
|
+
className: "relative flex shrink-0 cursor-pointer items-center justify-center rounded-box text-muted-foreground outline-none transition-colors after:absolute after:-inset-2 hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none data-popup-open:text-primary-text", children: _jsx(ClockIcon, {}) }), _jsx(PopoverContent, { "data-slot": "time-input-content",
|
|
206
|
+
// anchored to the whole field, not the icon, so it lines up like DatePicker's
|
|
207
|
+
anchor: fieldRef, align: "start", className: "w-auto p-1", initialFocus: pickerFocusTarget, children: _jsx(TimeColumns, { value: serialize(fill(segs, hourCycle), hourCycle, seconds), onValueChange: (next) => {
|
|
208
|
+
const parsed = parse(next, hourCycle);
|
|
209
|
+
update(parsed);
|
|
210
|
+
}, onCommit: () => setPickerOpen(false), seconds: seconds, hourCycle: hourCycle, locale: locale, step: step }) })] })) : (icon && _jsx(ClockIcon, { className: "text-muted-foreground" })), _jsxs("span", { "data-slot": "time-input-segments", className: "flex items-center", children: [hourCycle === 12 && fmt.periodFirst && _jsx("span", { className: "me-1", children: segment("period") }), segment("hour"), _jsx("span", { "aria-hidden": true, className: "text-muted-foreground", children: ":" }), segment("minute"), seconds && (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": true, className: "text-muted-foreground", children: ":" }), segment("second")] })), hourCycle === 12 && !fmt.periodFirst && _jsx("span", { className: "ms-1", children: segment("period") })] }), name && _jsx("input", { type: "hidden", name: name, value: current ?? "" })] }));
|
|
211
|
+
}
|
|
212
|
+
/** Empty segments take their first value, so the picker always shows a full time. */
|
|
213
|
+
function fill(s, cycle) {
|
|
214
|
+
return {
|
|
215
|
+
hour: s.hour ?? (cycle === 12 ? 12 : 0),
|
|
216
|
+
minute: s.minute ?? 0,
|
|
217
|
+
second: s.second ?? 0,
|
|
218
|
+
period: s.period ?? (cycle === 12 ? "AM" : null),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/** The popover opens on the hours column's selected option (found once the popup is in the DOM). */
|
|
222
|
+
function pickerFocusTarget() {
|
|
223
|
+
return document.querySelector("[data-slot=time-input-content] [data-slot=time-columns-column] [data-slot=time-columns-option][tabindex='0']");
|
|
224
|
+
}
|
|
225
|
+
/** A column of the picker: a listbox of option buttons, scrolled so the selected one sits in the middle. */
|
|
226
|
+
const timeColumnsOptionVariants = cva([
|
|
227
|
+
"flex h-8 w-full shrink-0 snap-center items-center justify-center rounded-md font-mono text-sm tabular-nums outline-none select-none",
|
|
228
|
+
"transition-[color,background-color] duration-100 motion-reduce:transition-none",
|
|
229
|
+
"hover:bg-hover",
|
|
230
|
+
// selected: the vivid fill, like Calendar's selected day
|
|
231
|
+
"aria-selected:bg-primary aria-selected:text-primary-foreground aria-selected:hover:bg-primary/85",
|
|
232
|
+
]);
|
|
233
|
+
/**
|
|
234
|
+
* Hours | minutes | (seconds) | (AM/PM) as scrollable listboxes. A click or tap picks; ↑↓ / Home / End
|
|
235
|
+
* pick within a column, ← → move between columns, Enter commits. Every pick fires `onValueChange` with a
|
|
236
|
+
* full time. Embed it in a popover (TimeInput does) or inline.
|
|
237
|
+
*/
|
|
238
|
+
function TimeColumns({ value, onValueChange, onCommit, seconds = false, hourCycle: hourCyclePreference = "auto", locale, step = 1, className, ...props }) {
|
|
239
|
+
const fmt = useTimeFormat(hourCyclePreference, locale);
|
|
240
|
+
const hourCycle = fmt.hourCycle;
|
|
241
|
+
const segs = parse(value, hourCycle);
|
|
242
|
+
const full = fill(segs, hourCycle);
|
|
243
|
+
const empty = value === null;
|
|
244
|
+
const withValue = (list, v) => v === null || list.includes(v) ? list : [...list, v].sort((a, b) => a - b);
|
|
245
|
+
const periodColumn = { part: "period", label: "AM/PM", options: ["AM", "PM"] };
|
|
246
|
+
const columns = [
|
|
247
|
+
...(hourCycle === 12 && fmt.periodFirst ? [periodColumn] : []),
|
|
248
|
+
{
|
|
249
|
+
part: "hour",
|
|
250
|
+
label: "Hours",
|
|
251
|
+
options: hourCycle === 12
|
|
252
|
+
? [12, ...Array.from({ length: 11 }, (_, i) => i + 1)]
|
|
253
|
+
: Array.from({ length: 24 }, (_, i) => i),
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
part: "minute",
|
|
257
|
+
label: "Minutes",
|
|
258
|
+
options: withValue(Array.from({ length: Math.ceil(60 / Math.max(1, step)) }, (_, i) => i * Math.max(1, step)), segs.minute),
|
|
259
|
+
},
|
|
260
|
+
...(seconds
|
|
261
|
+
? [{ part: "second", label: "Seconds", options: Array.from({ length: 60 }, (_, i) => i) }]
|
|
262
|
+
: []),
|
|
263
|
+
...(hourCycle === 12 && !fmt.periodFirst ? [periodColumn] : []),
|
|
264
|
+
];
|
|
265
|
+
const pick = (part, option) => {
|
|
266
|
+
onValueChange(serialize({ ...full, [part]: option }, hourCycle, seconds));
|
|
267
|
+
};
|
|
268
|
+
const root = React.useRef(null);
|
|
269
|
+
const center = (behavior) => {
|
|
270
|
+
root.current?.querySelectorAll("[data-slot=time-columns-column]").forEach((col) => {
|
|
271
|
+
const opt = col.querySelector("[tabindex='0']");
|
|
272
|
+
if (opt) {
|
|
273
|
+
col.scrollTo({ top: opt.offsetTop - (col.clientHeight - opt.offsetHeight) / 2, behavior });
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
};
|
|
277
|
+
// centre the selection on mount, follow it after keyboard picks
|
|
278
|
+
React.useLayoutEffect(() => center("instant"), []);
|
|
279
|
+
const onKeyDown = (e, ci, oi) => {
|
|
280
|
+
const col = columns[ci];
|
|
281
|
+
const rtl = getComputedStyle(e.currentTarget).direction === "rtl";
|
|
282
|
+
const go = (i) => {
|
|
283
|
+
e.preventDefault();
|
|
284
|
+
const next = Math.max(0, Math.min(col.options.length - 1, i));
|
|
285
|
+
pick(col.part, col.options[next]);
|
|
286
|
+
requestAnimationFrame(() => {
|
|
287
|
+
const btn = root.current?.querySelectorAll("[data-slot=time-columns-column]")[ci]
|
|
288
|
+
?.children[next];
|
|
289
|
+
btn?.focus({ preventScroll: true });
|
|
290
|
+
btn?.scrollIntoView({ block: "nearest" });
|
|
291
|
+
});
|
|
292
|
+
};
|
|
293
|
+
const toColumn = (delta) => {
|
|
294
|
+
e.preventDefault();
|
|
295
|
+
root.current
|
|
296
|
+
?.querySelectorAll("[data-slot=time-columns-column]")[ci + delta]?.querySelector("[tabindex='0']")
|
|
297
|
+
?.focus();
|
|
298
|
+
};
|
|
299
|
+
switch (e.key) {
|
|
300
|
+
case "ArrowDown":
|
|
301
|
+
return go(oi + 1);
|
|
302
|
+
case "ArrowUp":
|
|
303
|
+
return go(oi - 1);
|
|
304
|
+
case "PageDown":
|
|
305
|
+
return go(oi + 5);
|
|
306
|
+
case "PageUp":
|
|
307
|
+
return go(oi - 5);
|
|
308
|
+
case "Home":
|
|
309
|
+
return go(0);
|
|
310
|
+
case "End":
|
|
311
|
+
return go(col.options.length - 1);
|
|
312
|
+
case "ArrowLeft":
|
|
313
|
+
return toColumn(rtl ? 1 : -1);
|
|
314
|
+
case "ArrowRight":
|
|
315
|
+
return toColumn(rtl ? -1 : 1);
|
|
316
|
+
case "Enter":
|
|
317
|
+
e.preventDefault();
|
|
318
|
+
if (empty) {
|
|
319
|
+
pick(col.part, col.options[oi]);
|
|
320
|
+
}
|
|
321
|
+
onCommit?.();
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
return (_jsx("div", { ref: root, "data-slot": "time-columns", className: cn("flex gap-1", className), ...props, children: columns.map((col, ci) => {
|
|
326
|
+
const current = full[col.part];
|
|
327
|
+
const active = Math.max(0, col.options.indexOf(current));
|
|
328
|
+
return (_jsx("div", { "data-slot": "time-columns-frame", className: "rounded-md has-focus-visible:ring-2 has-focus-visible:ring-ring/50", children: _jsx("div", { role: "listbox", "aria-label": col.label, "data-slot": "time-columns-column", "data-part": col.part, className: cn(
|
|
329
|
+
// room above and below so the first and last options can sit in the middle
|
|
330
|
+
"no-scrollbar relative flex h-56 w-14 snap-y snap-proximity flex-col gap-0.5 overflow-y-auto overscroll-contain scroll-fade-y py-24", "rounded-md"), children: col.options.map((option, oi) => {
|
|
331
|
+
const selected = !empty && option === current;
|
|
332
|
+
return (_jsx("button", { type: "button", role: "option", "aria-selected": selected, tabIndex: oi === active ? 0 : -1, "data-slot": "time-columns-option", className: timeColumnsOptionVariants(), onClick: () => pick(col.part, option), onKeyDown: (e) => onKeyDown(e, ci, oi), children: typeof option === "number"
|
|
333
|
+
? fmt.digits(option)
|
|
334
|
+
: option === "AM"
|
|
335
|
+
? fmt.am
|
|
336
|
+
: fmt.pm }, String(option)));
|
|
337
|
+
}) }) }, col.part));
|
|
338
|
+
}) }));
|
|
339
|
+
}
|
|
340
|
+
export { parse as parseTime, serialize as serializeTime, TimeColumns, timeColumnsOptionVariants, TimeInput, timeInputSegmentVariants, timeInputVariants, };
|
|
341
|
+
//# sourceMappingURL=time-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time-input.js","sourceRoot":"","sources":["../../src/components/time-input.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type HourCyclePreference } from "@repraze/kernelkit/hooks/use-time-format";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
declare function formatTime(minutes: number, cycle: 12 | 24): string;
|
|
4
|
+
declare function formatDuration(minutes: number): string;
|
|
5
|
+
/**
|
|
6
|
+
* Lenient match, like Google Calendar's time list: "9" → 09:xx and 9 PM, "930" / "9:3" → 09:30,
|
|
7
|
+
* "9p" → 21:xx, "21" → 21:xx. Returns the exact time when the query is a complete one ("10:10", "7:05pm").
|
|
8
|
+
*/
|
|
9
|
+
declare function matchTime(query: string, cycle?: 12 | 24): {
|
|
10
|
+
test: (minutes: number) => boolean;
|
|
11
|
+
exact: number | null;
|
|
12
|
+
};
|
|
13
|
+
declare const timeSelectVariants: (props?: ({
|
|
14
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
15
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
16
|
+
interface TimeSelectProps {
|
|
17
|
+
/** 24-hour `"HH:mm"`, or `null`. */
|
|
18
|
+
value?: string | null;
|
|
19
|
+
defaultValue?: string | null;
|
|
20
|
+
onValueChange?: (value: string | null) => void;
|
|
21
|
+
/** Minutes between slots. */
|
|
22
|
+
step?: number;
|
|
23
|
+
/** First slot, `"HH:mm"`. */
|
|
24
|
+
min?: string;
|
|
25
|
+
/** Last slot, `"HH:mm"`. */
|
|
26
|
+
max?: string;
|
|
27
|
+
/** How times are shown; `"auto"` follows the user's locale. The value stays 24-hour. */
|
|
28
|
+
hourCycle?: HourCyclePreference;
|
|
29
|
+
/** BCP 47 locale for `"auto"` and the labels ("9:30 AM", "午前9:30"); defaults to the browser's. */
|
|
30
|
+
locale?: string;
|
|
31
|
+
/** A start time: slots begin there and show their duration, "(1 h 30 min)", like an end-time list. */
|
|
32
|
+
durationFrom?: string | null;
|
|
33
|
+
placeholder?: string;
|
|
34
|
+
size?: "sm" | "default" | "lg";
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
"aria-invalid"?: boolean;
|
|
37
|
+
"aria-label"?: string;
|
|
38
|
+
id?: string;
|
|
39
|
+
name?: string;
|
|
40
|
+
className?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A time from a list of slots, Google Calendar style: open it and pick, or type a few characters
|
|
44
|
+
* ("9", "930", "9p") to filter. A complete time typed off the grid ("10:10") is offered too.
|
|
45
|
+
*/
|
|
46
|
+
declare function TimeSelect({ value, defaultValue, onValueChange, step, min, max, hourCycle: hourCyclePreference, locale, durationFrom, placeholder: placeholderProp, size, disabled, id, name, className, ...aria }: TimeSelectProps): React.JSX.Element;
|
|
47
|
+
export { formatDuration, formatTime, matchTime, TimeSelect, timeSelectVariants };
|
|
48
|
+
export type { TimeSelectProps };
|
|
49
|
+
//# sourceMappingURL=time-select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time-select.d.ts","sourceRoot":"","sources":["../../src/components/time-select.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAC,KAAK,mBAAmB,EAAgB,MAAM,0CAA0C,CAAC;AAGjG,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAoB/B,iBAAS,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,UAIlD;AAED,iBAAS,cAAc,CAAC,OAAO,EAAE,MAAM,UAOtC;AAED;;;GAGG;AACH,iBAAS,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,EAAE,GAAG,EAAO;oBAsB1B,MAAM;;EA2BhC;AAMD,QAAA,MAAM,kBAAkB;;8EAYvB,CAAC;AAEF,UAAU,eAAe;IACrB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wFAAwF;IACxF,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,kGAAkG;IAClG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sGAAsG;IACtG,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,iBAAS,UAAU,CAAC,EAChB,KAAK,EACL,YAAmB,EACnB,aAAa,EACb,IAAS,EACT,GAAa,EACb,GAAa,EACb,SAAS,EAAE,mBAA4B,EACvC,MAAM,EACN,YAAY,EACZ,WAAW,EAAE,eAAe,EAC5B,IAAgB,EAChB,QAAQ,EACR,EAAE,EACF,IAAI,EACJ,SAAS,EACT,GAAG,IAAI,EACV,EAAE,eAAe,qBAsHjB;AAED,OAAO,EAAC,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,kBAAkB,EAAC,CAAC;AAC/E,YAAY,EAAC,eAAe,EAAC,CAAC"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Combobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, } from "@repraze/kernelkit/components/combobox";
|
|
4
|
+
import { useTimeFormat } from "@repraze/kernelkit/hooks/use-time-format";
|
|
5
|
+
import { cva } from "class-variance-authority";
|
|
6
|
+
import { cn } from "cn";
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
/* ------------------------------------------------------------------------------------------------
|
|
9
|
+
* Time helpers (minutes since midnight)
|
|
10
|
+
* ----------------------------------------------------------------------------------------------*/
|
|
11
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
12
|
+
function toMinutes(value) {
|
|
13
|
+
const m = value ? /^(\d{1,2}):(\d{2})/.exec(value) : null;
|
|
14
|
+
if (!m) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const h = Number(m[1]);
|
|
18
|
+
const min = Number(m[2]);
|
|
19
|
+
return h > 23 || min > 59 ? null : h * 60 + min;
|
|
20
|
+
}
|
|
21
|
+
const toValue = (minutes) => `${pad(Math.floor(minutes / 60))}:${pad(minutes % 60)}`;
|
|
22
|
+
function formatTime(minutes, cycle) {
|
|
23
|
+
const h = Math.floor(minutes / 60);
|
|
24
|
+
const m = pad(minutes % 60);
|
|
25
|
+
return cycle === 24 ? `${pad(h)}:${m}` : `${h % 12 || 12}:${m} ${h < 12 ? "AM" : "PM"}`;
|
|
26
|
+
}
|
|
27
|
+
function formatDuration(minutes) {
|
|
28
|
+
if (minutes < 60) {
|
|
29
|
+
return `${minutes} min`;
|
|
30
|
+
}
|
|
31
|
+
const h = Math.floor(minutes / 60);
|
|
32
|
+
const m = minutes % 60;
|
|
33
|
+
return m ? `${h} h ${m} min` : `${h} h`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Lenient match, like Google Calendar's time list: "9" → 09:xx and 9 PM, "930" / "9:3" → 09:30,
|
|
37
|
+
* "9p" → 21:xx, "21" → 21:xx. Returns the exact time when the query is a complete one ("10:10", "7:05pm").
|
|
38
|
+
*/
|
|
39
|
+
function matchTime(query, cycle = 24) {
|
|
40
|
+
const q = query
|
|
41
|
+
.toLowerCase()
|
|
42
|
+
.replace(/\s+/g, "")
|
|
43
|
+
.replace(/\.(?=\d)/, ":");
|
|
44
|
+
const meridiem = /(a|am|p|pm)$/.exec(q)?.[1]?.[0];
|
|
45
|
+
const body = meridiem ? q.replace(/(a|am|p|pm)$/, "") : q;
|
|
46
|
+
if (!/^\d{0,2}(:\d{0,2})?$|^\d{3,4}$/.test(body) || (!body && !meridiem)) {
|
|
47
|
+
return { test: () => false, exact: null };
|
|
48
|
+
}
|
|
49
|
+
let hourText;
|
|
50
|
+
let minuteText;
|
|
51
|
+
if (body.includes(":")) {
|
|
52
|
+
[hourText = "", minuteText = ""] = body.split(":");
|
|
53
|
+
}
|
|
54
|
+
else if (body.length > 2) {
|
|
55
|
+
hourText = body.slice(0, body.length - 2);
|
|
56
|
+
minuteText = body.slice(-2);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
hourText = body;
|
|
60
|
+
minuteText = "";
|
|
61
|
+
}
|
|
62
|
+
const test = (minutes) => {
|
|
63
|
+
const h24 = Math.floor(minutes / 60);
|
|
64
|
+
const h12 = h24 % 12 || 12;
|
|
65
|
+
const pm = h24 >= 12;
|
|
66
|
+
if (meridiem && (meridiem === "p") !== pm) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
// 24h display: hours are read as 24h ("9" is 09:xx) unless a meridiem is typed
|
|
70
|
+
const hourOk = !hourText ||
|
|
71
|
+
(meridiem || cycle === 12
|
|
72
|
+
? Number(hourText) === h12 || (!meridiem && Number(hourText) === h24)
|
|
73
|
+
: Number(hourText) === h24);
|
|
74
|
+
return hourOk && pad(minutes % 60).startsWith(minuteText);
|
|
75
|
+
};
|
|
76
|
+
// a complete time typed off the grid ("10:10") is offered as its own option
|
|
77
|
+
let exact = null;
|
|
78
|
+
const h = Number(hourText);
|
|
79
|
+
if (hourText && minuteText.length === 2) {
|
|
80
|
+
const m = Number(minuteText);
|
|
81
|
+
const h24 = meridiem ? (h % 12) + (meridiem === "p" ? 12 : 0) : h;
|
|
82
|
+
if (m < 60 && h24 < 24 && (!meridiem || (h >= 1 && h <= 12))) {
|
|
83
|
+
exact = h24 * 60 + m;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { test, exact };
|
|
87
|
+
}
|
|
88
|
+
/* ------------------------------------------------------------------------------------------------
|
|
89
|
+
* TimeSelect
|
|
90
|
+
* ----------------------------------------------------------------------------------------------*/
|
|
91
|
+
const timeSelectVariants = cva("w-36 font-normal *:data-[slot=input-group-control]:font-mono *:data-[slot=input-group-control]:tabular-nums", {
|
|
92
|
+
variants: {
|
|
93
|
+
size: {
|
|
94
|
+
sm: "h-7 rounded-md text-[0.8rem]",
|
|
95
|
+
default: "h-8",
|
|
96
|
+
lg: "h-9",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
defaultVariants: { size: "default" },
|
|
100
|
+
});
|
|
101
|
+
/**
|
|
102
|
+
* A time from a list of slots, Google Calendar style: open it and pick, or type a few characters
|
|
103
|
+
* ("9", "930", "9p") to filter. A complete time typed off the grid ("10:10") is offered too.
|
|
104
|
+
*/
|
|
105
|
+
function TimeSelect({ value, defaultValue = null, onValueChange, step = 30, min = "00:00", max = "23:59", hourCycle: hourCyclePreference = "auto", locale, durationFrom, placeholder: placeholderProp, size = "default", disabled, id, name, className, ...aria }) {
|
|
106
|
+
const controlled = value !== undefined;
|
|
107
|
+
const [inner, setInner] = React.useState(defaultValue);
|
|
108
|
+
const current = controlled ? value : inner;
|
|
109
|
+
const currentMin = toMinutes(current);
|
|
110
|
+
const set = (next) => {
|
|
111
|
+
if (!controlled) {
|
|
112
|
+
setInner(next);
|
|
113
|
+
}
|
|
114
|
+
onValueChange?.(next);
|
|
115
|
+
};
|
|
116
|
+
const from = toMinutes(durationFrom);
|
|
117
|
+
const slots = React.useMemo(() => {
|
|
118
|
+
const lo = Math.max(toMinutes(min) ?? 0, from ?? 0);
|
|
119
|
+
const hi = toMinutes(max) ?? 23 * 60 + 59;
|
|
120
|
+
const s = Math.max(1, step);
|
|
121
|
+
const list = [];
|
|
122
|
+
// durationFrom: the grid starts at the start time; otherwise it is aligned on midnight
|
|
123
|
+
for (let t = from !== null ? lo : Math.ceil(lo / s) * s; t <= hi; t += s) {
|
|
124
|
+
list.push(t);
|
|
125
|
+
}
|
|
126
|
+
return list;
|
|
127
|
+
}, [min, max, step, from]);
|
|
128
|
+
const fmt = useTimeFormat(hourCyclePreference, locale);
|
|
129
|
+
const hourCycle = fmt.hourCycle;
|
|
130
|
+
const placeholder = placeholderProp ?? (hourCycle === 12 ? "--:-- --" : "--:--");
|
|
131
|
+
const label = fmt.format;
|
|
132
|
+
// filter only once the user types: opening on a picked time lists every slot, scrolled to it
|
|
133
|
+
const [input, setInput] = React.useState(currentMin === null ? "" : label(currentMin));
|
|
134
|
+
const [query, setQuery] = React.useState(null);
|
|
135
|
+
// re-label when the value changes or the locale's format arrives after hydration
|
|
136
|
+
const seenKey = `${current}|${hourCycle}|${fmt.am}|${fmt.pm}`;
|
|
137
|
+
const [seen, setSeen] = React.useState(seenKey);
|
|
138
|
+
if (seenKey !== seen) {
|
|
139
|
+
setSeen(seenKey);
|
|
140
|
+
setInput(currentMin === null ? "" : label(currentMin));
|
|
141
|
+
}
|
|
142
|
+
const items = React.useMemo(() => {
|
|
143
|
+
const base = currentMin !== null && !slots.includes(currentMin) ? [...slots, currentMin].sort((a, b) => a - b) : slots;
|
|
144
|
+
if (!query) {
|
|
145
|
+
return base;
|
|
146
|
+
}
|
|
147
|
+
const { test, exact } = matchTime(query, hourCycle);
|
|
148
|
+
// the typed text also matches the localized label ("p.m.", "午後")
|
|
149
|
+
const q = query.toLowerCase().replace(/\s+/g, "");
|
|
150
|
+
const hits = base.filter((t) => test(t) || label(t).toLowerCase().replace(/\s+/g, "").includes(q));
|
|
151
|
+
return exact !== null && !hits.includes(exact) ? [exact, ...hits] : hits;
|
|
152
|
+
}, [slots, currentMin, query, hourCycle, label]);
|
|
153
|
+
const listRef = React.useRef(null);
|
|
154
|
+
return (_jsxs(Combobox, { items: items, filter: null,
|
|
155
|
+
// typing highlights the first match, so Enter takes it
|
|
156
|
+
autoHighlight: true, value: currentMin, onValueChange: (next) => {
|
|
157
|
+
setQuery(null);
|
|
158
|
+
set(next === null ? null : toValue(next));
|
|
159
|
+
}, inputValue: input, onInputValueChange: (text, details) => {
|
|
160
|
+
setInput(text);
|
|
161
|
+
if (details.reason === "input-change") {
|
|
162
|
+
setQuery(text.trim() || null);
|
|
163
|
+
}
|
|
164
|
+
}, onOpenChange: (open) => {
|
|
165
|
+
if (open) {
|
|
166
|
+
// the selected slot in view (Base UI highlights it; the list starts at the top)
|
|
167
|
+
requestAnimationFrame(() => listRef.current
|
|
168
|
+
?.querySelector("[data-selected]")
|
|
169
|
+
?.scrollIntoView({ block: "center" }));
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
setQuery(null);
|
|
173
|
+
setInput(currentMin === null ? "" : label(currentMin));
|
|
174
|
+
}
|
|
175
|
+
}, itemToStringLabel: label, disabled: disabled, name: name, children: [_jsx(ComboboxInput, { id: id, placeholder: placeholder, disabled: disabled, inputMode: "text", autoComplete: "off", className: cn(timeSelectVariants({ size }), className), ...aria }), _jsxs(ComboboxContent, { "data-slot": "time-select-content", children: [_jsx(ComboboxEmpty, { children: "No matching time." }), _jsx(ComboboxList, { ref: listRef, children: (minutes) => (_jsxs(ComboboxItem, { value: minutes, className: "tabular-nums", children: [_jsx("span", { className: "font-mono", children: label(minutes) }), from !== null && minutes >= from && (_jsx("span", { className: "ms-auto font-alt text-xs text-muted-foreground", children: formatDuration(minutes - from) }))] }, minutes)) })] })] }));
|
|
176
|
+
}
|
|
177
|
+
export { formatDuration, formatTime, matchTime, TimeSelect, timeSelectVariants };
|
|
178
|
+
//# sourceMappingURL=time-select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time-select.js","sourceRoot":"","sources":["../../src/components/time-select.tsx"],"names":[],"mappings":"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"}
|