@bricks-toolkit/toolkit 0.1.26 → 0.1.27
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.
|
@@ -1,32 +1,53 @@
|
|
|
1
1
|
import { cn } from './chunk-OCPFOFJ4.mjs';
|
|
2
|
-
import { forwardRef,
|
|
3
|
-
import { ClockIcon, XMarkIcon,
|
|
4
|
-
import { jsxs, jsx
|
|
2
|
+
import { forwardRef, useId, useRef, useState, useEffect } from 'react';
|
|
3
|
+
import { ClockIcon, XMarkIcon, ChevronDownIcon } from '@heroicons/react/24/outline';
|
|
4
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
function parseTypedTime(str) {
|
|
7
|
+
const clean = str.trim();
|
|
8
|
+
if (!clean) return null;
|
|
9
|
+
const match24 = /^(\d{2}):(\d{2})$/.exec(clean);
|
|
10
|
+
if (match24?.[1] && match24[2]) {
|
|
11
|
+
const hour = parseInt(match24[1], 10);
|
|
12
|
+
const minute = parseInt(match24[2], 10);
|
|
13
|
+
if (hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59) {
|
|
14
|
+
return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
15
18
|
}
|
|
16
|
-
function
|
|
17
|
-
|
|
19
|
+
function formatTime12(iso) {
|
|
20
|
+
if (!iso) return "";
|
|
21
|
+
const parts = iso.split(":");
|
|
22
|
+
if (parts.length < 2 || !parts[0] || !parts[1]) return iso;
|
|
23
|
+
const hour = parseInt(parts[0], 10);
|
|
24
|
+
const minute = parseInt(parts[1], 10);
|
|
25
|
+
if (isNaN(hour) || isNaN(minute)) return iso;
|
|
26
|
+
const displayHour = hour % 12 || 12;
|
|
27
|
+
const ampm = hour >= 12 ? "PM" : "AM";
|
|
28
|
+
return `${String(displayHour)}:${String(minute).padStart(2, "0")} ${ampm}`;
|
|
18
29
|
}
|
|
19
|
-
function formatDisplay(
|
|
20
|
-
if (!
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
function formatDisplay(iso, use12Hour) {
|
|
31
|
+
if (!iso) return "";
|
|
32
|
+
return use12Hour ? formatTime12(iso) : iso;
|
|
33
|
+
}
|
|
34
|
+
function generateTimeSlots(step, use12Hour) {
|
|
35
|
+
const slots = [];
|
|
36
|
+
const limit = 24 * 60;
|
|
37
|
+
const s = step > 0 && step <= 720 ? step : 1;
|
|
38
|
+
for (let minutes = 0; minutes < limit; minutes += s) {
|
|
39
|
+
const hour = Math.floor(minutes / 60);
|
|
40
|
+
const minute = minutes % 60;
|
|
41
|
+
const value = `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
|
|
42
|
+
const label = use12Hour ? (() => {
|
|
43
|
+
const displayHour = hour % 12 || 12;
|
|
44
|
+
const ampm = hour >= 12 ? "PM" : "AM";
|
|
45
|
+
return `${String(displayHour)}:${String(minute).padStart(2, "0")} ${ampm}`;
|
|
46
|
+
})() : value;
|
|
47
|
+
slots.push({ label, value });
|
|
26
48
|
}
|
|
27
|
-
return
|
|
49
|
+
return slots;
|
|
28
50
|
}
|
|
29
|
-
var ITEM_HEIGHT = 36;
|
|
30
51
|
var sizeClasses = {
|
|
31
52
|
xs: "h-6 px-2 text-xs",
|
|
32
53
|
sm: "h-8 px-3 text-sm",
|
|
@@ -79,104 +100,12 @@ var stateMessageClasses = {
|
|
|
79
100
|
success: "text-success font-medium",
|
|
80
101
|
warning: "text-warning font-medium"
|
|
81
102
|
};
|
|
82
|
-
function ScrollColumn({ items, selected, onSelect, label }) {
|
|
83
|
-
const listRef = useRef(null);
|
|
84
|
-
const scrollToSelected = useCallback(
|
|
85
|
-
(behavior = "smooth") => {
|
|
86
|
-
if (!listRef.current) return;
|
|
87
|
-
const idx = items.indexOf(selected);
|
|
88
|
-
if (idx < 0) return;
|
|
89
|
-
const top = idx * ITEM_HEIGHT - ITEM_HEIGHT * 2;
|
|
90
|
-
if (typeof listRef.current.scrollTo === "function") {
|
|
91
|
-
listRef.current.scrollTo({ top: Math.max(0, top), behavior });
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
[items, selected]
|
|
95
|
-
);
|
|
96
|
-
useEffect(() => {
|
|
97
|
-
scrollToSelected("instant");
|
|
98
|
-
}, []);
|
|
99
|
-
useEffect(() => {
|
|
100
|
-
scrollToSelected("smooth");
|
|
101
|
-
}, [scrollToSelected]);
|
|
102
|
-
const step = (dir) => {
|
|
103
|
-
const idx = items.indexOf(selected);
|
|
104
|
-
const next = items[(idx + dir + items.length) % items.length];
|
|
105
|
-
if (next) onSelect(next);
|
|
106
|
-
};
|
|
107
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-0.5", "aria-label": label, role: "group", children: [
|
|
108
|
-
/* @__PURE__ */ jsx(
|
|
109
|
-
"button",
|
|
110
|
-
{
|
|
111
|
-
type: "button",
|
|
112
|
-
onClick: () => {
|
|
113
|
-
step(-1);
|
|
114
|
-
},
|
|
115
|
-
className: "p-1 rounded hover:bg-hover text-text-secondary hover:text-text transition-colors",
|
|
116
|
-
"aria-label": `Decrease ${label}`,
|
|
117
|
-
children: /* @__PURE__ */ jsx(ChevronUpIcon, { className: "w-4 h-4" })
|
|
118
|
-
}
|
|
119
|
-
),
|
|
120
|
-
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
121
|
-
/* @__PURE__ */ jsx(
|
|
122
|
-
"div",
|
|
123
|
-
{
|
|
124
|
-
className: "absolute inset-x-0 rounded-lg bg-primary/10 border-y border-primary/20 pointer-events-none",
|
|
125
|
-
style: { top: ITEM_HEIGHT * 2, height: ITEM_HEIGHT }
|
|
126
|
-
}
|
|
127
|
-
),
|
|
128
|
-
/* @__PURE__ */ jsxs(
|
|
129
|
-
"div",
|
|
130
|
-
{
|
|
131
|
-
ref: listRef,
|
|
132
|
-
className: "overflow-y-auto scrollbar-none",
|
|
133
|
-
style: { height: ITEM_HEIGHT * 5, width: 56 },
|
|
134
|
-
children: [
|
|
135
|
-
/* @__PURE__ */ jsx("div", { style: { height: ITEM_HEIGHT * 2 } }),
|
|
136
|
-
items.map((item) => /* @__PURE__ */ jsx(
|
|
137
|
-
"button",
|
|
138
|
-
{
|
|
139
|
-
type: "button",
|
|
140
|
-
onClick: () => {
|
|
141
|
-
onSelect(item);
|
|
142
|
-
},
|
|
143
|
-
className: cn(
|
|
144
|
-
"w-full flex items-center justify-center rounded-lg text-sm font-medium transition-colors duration-150",
|
|
145
|
-
"hover:bg-hover",
|
|
146
|
-
selected === item ? "text-primary font-bold" : "text-text-secondary"
|
|
147
|
-
),
|
|
148
|
-
style: { height: ITEM_HEIGHT },
|
|
149
|
-
"aria-pressed": selected === item,
|
|
150
|
-
"aria-label": `${label} ${item}`,
|
|
151
|
-
children: item
|
|
152
|
-
},
|
|
153
|
-
item
|
|
154
|
-
)),
|
|
155
|
-
/* @__PURE__ */ jsx("div", { style: { height: ITEM_HEIGHT * 2 } })
|
|
156
|
-
]
|
|
157
|
-
}
|
|
158
|
-
)
|
|
159
|
-
] }),
|
|
160
|
-
/* @__PURE__ */ jsx(
|
|
161
|
-
"button",
|
|
162
|
-
{
|
|
163
|
-
type: "button",
|
|
164
|
-
onClick: () => {
|
|
165
|
-
step(1);
|
|
166
|
-
},
|
|
167
|
-
className: "p-1 rounded hover:bg-hover text-text-secondary hover:text-text transition-colors",
|
|
168
|
-
"aria-label": `Increase ${label}`,
|
|
169
|
-
children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "w-4 h-4" })
|
|
170
|
-
}
|
|
171
|
-
)
|
|
172
|
-
] });
|
|
173
|
-
}
|
|
174
103
|
function AddonIcon({ children, side, size, onClick, asButton = false, ariaLabel }) {
|
|
175
104
|
const iconSize = {
|
|
176
|
-
xs: "w-3
|
|
177
|
-
sm: "w-
|
|
105
|
+
xs: "w-3 h-3",
|
|
106
|
+
sm: "w-3.5 h-3.5",
|
|
178
107
|
md: "w-4 h-4",
|
|
179
|
-
lg: "w-5 h-5",
|
|
108
|
+
lg: "w-4.5 h-4.5",
|
|
180
109
|
xl: "w-5 h-5"
|
|
181
110
|
};
|
|
182
111
|
const base = cn(
|
|
@@ -190,7 +119,7 @@ function AddonIcon({ children, side, size, onClick, asButton = false, ariaLabel
|
|
|
190
119
|
{
|
|
191
120
|
type: "button",
|
|
192
121
|
onClick,
|
|
193
|
-
className: cn(base, "cursor-pointer hover:text-text transition-colors"),
|
|
122
|
+
className: cn(base, "cursor-pointer hover:text-text transition-colors z-20"),
|
|
194
123
|
tabIndex: -1,
|
|
195
124
|
"aria-label": ariaLabel,
|
|
196
125
|
children
|
|
@@ -201,7 +130,7 @@ function AddonIcon({ children, side, size, onClick, asButton = false, ariaLabel
|
|
|
201
130
|
"span",
|
|
202
131
|
{
|
|
203
132
|
"aria-hidden": !ariaLabel,
|
|
204
|
-
className: cn(base, "pointer-events-none"),
|
|
133
|
+
className: cn(base, "pointer-events-none z-20"),
|
|
205
134
|
"aria-label": ariaLabel,
|
|
206
135
|
children
|
|
207
136
|
}
|
|
@@ -254,26 +183,47 @@ var TimePicker = forwardRef(
|
|
|
254
183
|
minuteStep = 1,
|
|
255
184
|
use12Hour = false,
|
|
256
185
|
name,
|
|
257
|
-
type,
|
|
258
186
|
"aria-label": ariaLabel,
|
|
259
187
|
"aria-describedby": ariaDescribedby
|
|
260
188
|
}, ref) => {
|
|
261
|
-
const internalRef = useRef(null);
|
|
262
189
|
const generatedId = useId();
|
|
263
190
|
const inputId = idProp ?? generatedId;
|
|
264
191
|
const helperId = `${inputId}-helper`;
|
|
265
192
|
const stateMessageId = `${inputId}-state`;
|
|
266
193
|
const popoverId = `${inputId}-popover`;
|
|
194
|
+
const internalRef = useRef(null);
|
|
195
|
+
const inputRef = useRef(null);
|
|
196
|
+
const dropdownRef = useRef(null);
|
|
197
|
+
const debounceTimerRef = useRef(null);
|
|
267
198
|
const isControlled = value !== void 0;
|
|
268
199
|
const [internalValue, setInternalValue] = useState(defaultValue ?? "");
|
|
269
200
|
const displayValue = isControlled ? value : internalValue;
|
|
270
|
-
const { hours: selHours, minutes: selMinutes } = parseTime(displayValue);
|
|
271
|
-
const selAmpm = selHours >= 12 ? "PM" : "AM";
|
|
272
|
-
const selHours12 = selHours % 12 || 12;
|
|
273
|
-
const pickerHour = String(use12Hour ? selHours12 : selHours).padStart(2, "0");
|
|
274
|
-
const pickerMinute = String(selMinutes).padStart(2, "0");
|
|
275
|
-
const pickerAmpm = selAmpm;
|
|
276
201
|
const [isOpen, setIsOpen] = useState(false);
|
|
202
|
+
const [typedValue, setTypedValue] = useState(null);
|
|
203
|
+
const displayInputValue = typedValue ?? formatDisplay(displayValue, use12Hour);
|
|
204
|
+
const timeSlots = generateTimeSlots(minuteStep, use12Hour);
|
|
205
|
+
const filteredSlots = timeSlots.filter((slot) => {
|
|
206
|
+
if (!displayInputValue) return true;
|
|
207
|
+
const typedClean = displayInputValue.replace(/[^0-9]/g, "");
|
|
208
|
+
const slotLabelClean = slot.label.replace(/[^0-9]/g, "");
|
|
209
|
+
const slotValueClean = slot.value.replace(/[^0-9]/g, "");
|
|
210
|
+
return slot.label.toLowerCase().includes(displayInputValue.toLowerCase()) || slot.value.includes(displayInputValue) || slotLabelClean.includes(typedClean) || slotValueClean.includes(typedClean);
|
|
211
|
+
});
|
|
212
|
+
useEffect(() => {
|
|
213
|
+
if (isOpen && dropdownRef.current) {
|
|
214
|
+
const activeItem = dropdownRef.current.querySelector('[data-active="true"]');
|
|
215
|
+
if (activeItem) {
|
|
216
|
+
activeItem.scrollIntoView({ block: "nearest" });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}, [isOpen]);
|
|
220
|
+
useEffect(() => {
|
|
221
|
+
return () => {
|
|
222
|
+
if (debounceTimerRef.current) {
|
|
223
|
+
clearTimeout(debounceTimerRef.current);
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
}, []);
|
|
277
227
|
useEffect(() => {
|
|
278
228
|
if (!isOpen) return;
|
|
279
229
|
function handleClick(e) {
|
|
@@ -285,45 +235,91 @@ var TimePicker = forwardRef(
|
|
|
285
235
|
return () => {
|
|
286
236
|
document.removeEventListener("mousedown", handleClick);
|
|
287
237
|
};
|
|
288
|
-
}, [isOpen
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
(_, i) => String(i * minuteStep).padStart(2, "0")
|
|
293
|
-
);
|
|
294
|
-
const applyTime = useCallback(
|
|
295
|
-
(h, m, ap) => {
|
|
296
|
-
let hours24 = parseInt(h, 10);
|
|
297
|
-
if (use12Hour) {
|
|
298
|
-
if (ap === "AM" && hours24 === 12) hours24 = 0;
|
|
299
|
-
if (ap === "PM" && hours24 !== 12) hours24 += 12;
|
|
300
|
-
}
|
|
301
|
-
const iso = toTimeString(hours24, parseInt(m, 10));
|
|
302
|
-
if (!isControlled) setInternalValue(iso);
|
|
303
|
-
onChange?.(iso);
|
|
304
|
-
onTimeChange?.(iso);
|
|
305
|
-
},
|
|
306
|
-
[isControlled, onChange, onTimeChange, use12Hour]
|
|
307
|
-
);
|
|
308
|
-
const handleHourSelect = (h) => {
|
|
309
|
-
applyTime(h, pickerMinute, pickerAmpm);
|
|
310
|
-
};
|
|
311
|
-
const handleMinuteSelect = (m) => {
|
|
312
|
-
applyTime(pickerHour, m, pickerAmpm);
|
|
313
|
-
};
|
|
314
|
-
const handleAmpmSelect = (ap) => {
|
|
315
|
-
const a = ap;
|
|
316
|
-
applyTime(pickerHour, pickerMinute, a);
|
|
317
|
-
};
|
|
318
|
-
const handleClear = () => {
|
|
238
|
+
}, [isOpen]);
|
|
239
|
+
const handleClear = (e) => {
|
|
240
|
+
e.stopPropagation();
|
|
241
|
+
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
|
|
319
242
|
if (!isControlled) setInternalValue("");
|
|
320
243
|
onChange?.("");
|
|
321
244
|
onTimeChange?.(null);
|
|
245
|
+
setTypedValue(null);
|
|
322
246
|
};
|
|
323
|
-
const toggleOpen = () => {
|
|
247
|
+
const toggleOpen = (e) => {
|
|
248
|
+
e.stopPropagation();
|
|
324
249
|
if (disabled || isLoading) return;
|
|
325
250
|
setIsOpen((prev) => !prev);
|
|
326
251
|
};
|
|
252
|
+
const handleInputChange = (e) => {
|
|
253
|
+
let val = e.target.value;
|
|
254
|
+
val = val.replace(/[^0-9:]/g, "");
|
|
255
|
+
if (val.length > 5) {
|
|
256
|
+
val = val.slice(0, 5);
|
|
257
|
+
}
|
|
258
|
+
const currentLength = typedValue?.length ?? 0;
|
|
259
|
+
if (val.length === 2 && !val.includes(":") && val.length > currentLength) {
|
|
260
|
+
val = val + ":";
|
|
261
|
+
}
|
|
262
|
+
if (val.length === 5) {
|
|
263
|
+
const parts = val.split(":");
|
|
264
|
+
if (parts[0] && parts[1]) {
|
|
265
|
+
let hours = parseInt(parts[0], 10);
|
|
266
|
+
let minutes = parseInt(parts[1], 10);
|
|
267
|
+
if (hours > 23) hours = 23;
|
|
268
|
+
if (minutes > 59) minutes = 59;
|
|
269
|
+
val = `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
setTypedValue(val);
|
|
273
|
+
if (debounceTimerRef.current) {
|
|
274
|
+
clearTimeout(debounceTimerRef.current);
|
|
275
|
+
}
|
|
276
|
+
debounceTimerRef.current = setTimeout(() => {
|
|
277
|
+
const parsed = parseTypedTime(val);
|
|
278
|
+
if (parsed) {
|
|
279
|
+
if (!isControlled) setInternalValue(parsed);
|
|
280
|
+
onChange?.(parsed);
|
|
281
|
+
onTimeChange?.(parsed);
|
|
282
|
+
}
|
|
283
|
+
}, 1e3);
|
|
284
|
+
};
|
|
285
|
+
const handleKeyDown = (e) => {
|
|
286
|
+
const allowedKeys = [
|
|
287
|
+
"Backspace",
|
|
288
|
+
"Delete",
|
|
289
|
+
"ArrowLeft",
|
|
290
|
+
"ArrowRight",
|
|
291
|
+
"Tab",
|
|
292
|
+
"Escape",
|
|
293
|
+
"Enter"
|
|
294
|
+
];
|
|
295
|
+
if (allowedKeys.includes(e.key) || e.ctrlKey || e.metaKey) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
if (!/[0-9:]/.test(e.key)) {
|
|
299
|
+
e.preventDefault();
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
const handleInputBlur = () => {
|
|
303
|
+
setTimeout(() => {
|
|
304
|
+
if (debounceTimerRef.current) {
|
|
305
|
+
clearTimeout(debounceTimerRef.current);
|
|
306
|
+
}
|
|
307
|
+
const finalVal = typedValue ?? displayValue;
|
|
308
|
+
const parsed = parseTypedTime(finalVal);
|
|
309
|
+
if (parsed) {
|
|
310
|
+
if (!isControlled) setInternalValue(parsed);
|
|
311
|
+
onChange?.(parsed);
|
|
312
|
+
onTimeChange?.(parsed);
|
|
313
|
+
}
|
|
314
|
+
setTypedValue(null);
|
|
315
|
+
}, 150);
|
|
316
|
+
};
|
|
317
|
+
const handleInputFocus = () => {
|
|
318
|
+
setTypedValue(displayValue);
|
|
319
|
+
if (!disabled && !isLoading) {
|
|
320
|
+
setIsOpen(true);
|
|
321
|
+
}
|
|
322
|
+
};
|
|
327
323
|
const showClear = clearable && displayValue.length > 0 && !disabled && !isLoading;
|
|
328
324
|
const rightPad = {
|
|
329
325
|
xs: "pr-6",
|
|
@@ -376,33 +372,35 @@ var TimePicker = forwardRef(
|
|
|
376
372
|
/* @__PURE__ */ jsxs("div", { className: "relative flex flex-1 items-center", children: [
|
|
377
373
|
/* @__PURE__ */ jsx(AddonIcon, { side: "left", size, children: leftElement ?? /* @__PURE__ */ jsx(ClockIcon, { className: "w-full h-full" }) }),
|
|
378
374
|
/* @__PURE__ */ jsx(
|
|
379
|
-
"
|
|
375
|
+
"input",
|
|
380
376
|
{
|
|
377
|
+
ref: inputRef,
|
|
381
378
|
id: inputId,
|
|
382
|
-
type:
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
379
|
+
type: "text",
|
|
380
|
+
value: displayInputValue,
|
|
381
|
+
onChange: handleInputChange,
|
|
382
|
+
onKeyDown: handleKeyDown,
|
|
383
|
+
onFocus: handleInputFocus,
|
|
384
|
+
onBlur: handleInputBlur,
|
|
385
|
+
placeholder,
|
|
387
386
|
"aria-label": ariaLabel ?? label ?? "Time picker",
|
|
388
387
|
"aria-describedby": describedBy,
|
|
389
388
|
"aria-required": required,
|
|
390
389
|
"aria-invalid": state === "error" ? true : void 0,
|
|
391
390
|
disabled: Boolean(disabled) || Boolean(isLoading),
|
|
392
|
-
onClick: toggleOpen,
|
|
393
391
|
name,
|
|
394
392
|
className: cn(
|
|
395
|
-
"w-full flex items-center text-left transition-colors duration-150
|
|
393
|
+
"w-full flex items-center text-left transition-colors duration-150",
|
|
396
394
|
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
395
|
+
"focus:outline-none focus:ring-0",
|
|
397
396
|
sizeClasses[size],
|
|
398
397
|
variantClasses[variant],
|
|
399
398
|
stateVariantClasses[state][variant],
|
|
400
399
|
"pl-9",
|
|
401
|
-
|
|
400
|
+
rightPad[size],
|
|
402
401
|
prefix !== void 0 && suffix !== void 0 ? "rounded-none" : prefix !== void 0 ? "rounded-l-none" : suffix !== void 0 ? "rounded-r-none" : "",
|
|
403
402
|
inputClassName
|
|
404
|
-
)
|
|
405
|
-
children: displayValue ? /* @__PURE__ */ jsx("span", { className: "text-text", children: formatDisplay(displayValue, use12Hour) }) : /* @__PURE__ */ jsx("span", { className: "text-text-muted", children: placeholder })
|
|
403
|
+
)
|
|
406
404
|
}
|
|
407
405
|
),
|
|
408
406
|
isLoading ? /* @__PURE__ */ jsx(AddonIcon, { side: "right", size, children: /* @__PURE__ */ jsxs(
|
|
@@ -444,12 +442,68 @@ var TimePicker = forwardRef(
|
|
|
444
442
|
ariaLabel: "Clear time",
|
|
445
443
|
children: /* @__PURE__ */ jsx(XMarkIcon, { className: "w-full h-full", strokeWidth: 2.5 })
|
|
446
444
|
}
|
|
447
|
-
) : rightElement ? /* @__PURE__ */ jsx(AddonIcon, { side: "right", size, children: rightElement }) :
|
|
445
|
+
) : rightElement ? /* @__PURE__ */ jsx(AddonIcon, { side: "right", size, children: rightElement }) : /* @__PURE__ */ jsx(
|
|
446
|
+
AddonIcon,
|
|
447
|
+
{
|
|
448
|
+
side: "right",
|
|
449
|
+
size,
|
|
450
|
+
asButton: true,
|
|
451
|
+
onClick: toggleOpen,
|
|
452
|
+
ariaLabel: "Open time picker dropdown",
|
|
453
|
+
children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "w-full h-full text-text-secondary/70 hover:text-text transition-colors" })
|
|
454
|
+
}
|
|
455
|
+
)
|
|
448
456
|
] }),
|
|
449
457
|
suffix !== void 0 && /* @__PURE__ */ jsx(Addon, { side: "right", children: suffix })
|
|
450
458
|
]
|
|
451
459
|
}
|
|
452
460
|
),
|
|
461
|
+
/* @__PURE__ */ jsx(
|
|
462
|
+
"div",
|
|
463
|
+
{
|
|
464
|
+
id: popoverId,
|
|
465
|
+
ref: dropdownRef,
|
|
466
|
+
role: "listbox",
|
|
467
|
+
"aria-label": "Time options",
|
|
468
|
+
className: cn(
|
|
469
|
+
"absolute top-full left-0 z-50 mt-1.5 w-full max-h-60 overflow-y-auto",
|
|
470
|
+
"bg-surface/90 backdrop-blur-md border border-border/80 rounded-xl shadow-xl py-1.5",
|
|
471
|
+
"transition-all duration-200 origin-top ease-out",
|
|
472
|
+
isOpen ? "opacity-100 scale-100 pointer-events-auto translate-y-0" : "opacity-0 scale-95 pointer-events-none -translate-y-1"
|
|
473
|
+
),
|
|
474
|
+
children: filteredSlots.length > 0 ? filteredSlots.map((slot) => {
|
|
475
|
+
const isSelected = slot.value === displayValue;
|
|
476
|
+
return /* @__PURE__ */ jsxs(
|
|
477
|
+
"button",
|
|
478
|
+
{
|
|
479
|
+
type: "button",
|
|
480
|
+
"data-active": isSelected,
|
|
481
|
+
onMouseDown: (e) => {
|
|
482
|
+
e.preventDefault();
|
|
483
|
+
},
|
|
484
|
+
onClick: () => {
|
|
485
|
+
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
|
|
486
|
+
if (!isControlled) setInternalValue(slot.value);
|
|
487
|
+
onChange?.(slot.value);
|
|
488
|
+
onTimeChange?.(slot.value);
|
|
489
|
+
setTypedValue(null);
|
|
490
|
+
setIsOpen(false);
|
|
491
|
+
},
|
|
492
|
+
className: cn(
|
|
493
|
+
"w-full text-left px-4 py-2.5 text-sm transition-all duration-normal cursor-pointer flex items-center justify-between",
|
|
494
|
+
"hover:bg-primary/5 hover:text-primary hover:pl-5 font-medium",
|
|
495
|
+
isSelected ? "bg-primary/10 text-primary font-bold pl-5" : "text-text-secondary"
|
|
496
|
+
),
|
|
497
|
+
children: [
|
|
498
|
+
/* @__PURE__ */ jsx("span", { children: slot.label }),
|
|
499
|
+
isSelected && /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-primary animate-pulse" })
|
|
500
|
+
]
|
|
501
|
+
},
|
|
502
|
+
slot.value
|
|
503
|
+
);
|
|
504
|
+
}) : /* @__PURE__ */ jsx("div", { className: "text-center text-xs text-text-muted py-3", children: "No matching times found" })
|
|
505
|
+
}
|
|
506
|
+
),
|
|
453
507
|
helperText !== void 0 && /* @__PURE__ */ jsx(
|
|
454
508
|
"p",
|
|
455
509
|
{
|
|
@@ -470,65 +524,6 @@ var TimePicker = forwardRef(
|
|
|
470
524
|
),
|
|
471
525
|
children: stateMessage
|
|
472
526
|
}
|
|
473
|
-
),
|
|
474
|
-
/* @__PURE__ */ jsx(
|
|
475
|
-
"div",
|
|
476
|
-
{
|
|
477
|
-
id: popoverId,
|
|
478
|
-
role: "dialog",
|
|
479
|
-
"aria-label": "Time picker",
|
|
480
|
-
"aria-modal": "true",
|
|
481
|
-
className: cn(
|
|
482
|
-
"absolute top-full left-0 z-50 mt-1",
|
|
483
|
-
"bg-surface border border-border rounded-xl shadow-xl",
|
|
484
|
-
"transition-all duration-200 origin-top",
|
|
485
|
-
isOpen ? "opacity-100 scale-100 pointer-events-auto" : "opacity-0 scale-95 pointer-events-none"
|
|
486
|
-
),
|
|
487
|
-
children: /* @__PURE__ */ jsxs("div", { className: "p-4", children: [
|
|
488
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-bold text-text-muted uppercase tracking-widest mb-3 text-center", children: "Select Time" }),
|
|
489
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-1", children: [
|
|
490
|
-
/* @__PURE__ */ jsx(
|
|
491
|
-
ScrollColumn,
|
|
492
|
-
{
|
|
493
|
-
items: hourItems,
|
|
494
|
-
selected: pickerHour,
|
|
495
|
-
onSelect: handleHourSelect,
|
|
496
|
-
label: "Hour"
|
|
497
|
-
}
|
|
498
|
-
),
|
|
499
|
-
/* @__PURE__ */ jsx(
|
|
500
|
-
"div",
|
|
501
|
-
{
|
|
502
|
-
className: "flex items-center self-center pb-2 text-text-muted font-bold text-lg select-none",
|
|
503
|
-
style: { height: ITEM_HEIGHT },
|
|
504
|
-
children: ":"
|
|
505
|
-
}
|
|
506
|
-
),
|
|
507
|
-
/* @__PURE__ */ jsx(
|
|
508
|
-
ScrollColumn,
|
|
509
|
-
{
|
|
510
|
-
items: minuteItems,
|
|
511
|
-
selected: pickerMinute,
|
|
512
|
-
onSelect: handleMinuteSelect,
|
|
513
|
-
label: "Minute"
|
|
514
|
-
}
|
|
515
|
-
),
|
|
516
|
-
use12Hour && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
517
|
-
/* @__PURE__ */ jsx("div", { className: "w-px self-stretch bg-border mx-1" }),
|
|
518
|
-
/* @__PURE__ */ jsx(
|
|
519
|
-
ScrollColumn,
|
|
520
|
-
{
|
|
521
|
-
items: ["AM", "PM"],
|
|
522
|
-
selected: pickerAmpm,
|
|
523
|
-
onSelect: handleAmpmSelect,
|
|
524
|
-
label: "AM/PM"
|
|
525
|
-
}
|
|
526
|
-
)
|
|
527
|
-
] })
|
|
528
|
-
] }),
|
|
529
|
-
/* @__PURE__ */ jsx("div", { className: "mt-3 pt-3 border-t border-border text-center", children: /* @__PURE__ */ jsx("span", { className: "text-sm font-bold text-primary font-mono", children: displayValue ? formatDisplay(displayValue, use12Hour) : "\u2013\u2013:\u2013\u2013" }) })
|
|
530
|
-
] })
|
|
531
|
-
}
|
|
532
527
|
)
|
|
533
528
|
]
|
|
534
529
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -7,7 +7,7 @@ require('./chunk-NMJ5CVZH.cjs');
|
|
|
7
7
|
var chunkOEU5VG3D_cjs = require('./chunk-OEU5VG3D.cjs');
|
|
8
8
|
var chunkY6AN7AWX_cjs = require('./chunk-Y6AN7AWX.cjs');
|
|
9
9
|
var chunkXFNRKHHF_cjs = require('./chunk-XFNRKHHF.cjs');
|
|
10
|
-
var
|
|
10
|
+
var chunkC5CAUNLU_cjs = require('./chunk-C5CAUNLU.cjs');
|
|
11
11
|
var chunkYMMNWJT6_cjs = require('./chunk-YMMNWJT6.cjs');
|
|
12
12
|
var chunkQ3IFXFFD_cjs = require('./chunk-Q3IFXFFD.cjs');
|
|
13
13
|
var chunkYK7IS7JL_cjs = require('./chunk-YK7IS7JL.cjs');
|
|
@@ -651,7 +651,7 @@ Object.defineProperty(exports, "TextInput", {
|
|
|
651
651
|
});
|
|
652
652
|
Object.defineProperty(exports, "TimePicker", {
|
|
653
653
|
enumerable: true,
|
|
654
|
-
get: function () { return
|
|
654
|
+
get: function () { return chunkC5CAUNLU_cjs.TimePicker; }
|
|
655
655
|
});
|
|
656
656
|
Object.defineProperty(exports, "Toaster", {
|
|
657
657
|
enumerable: true,
|
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import './chunk-SBNNV6FE.mjs';
|
|
|
5
5
|
export { Pagination, Table } from './chunk-7364SUK6.mjs';
|
|
6
6
|
export { Tabs } from './chunk-G4HVY6FM.mjs';
|
|
7
7
|
export { TextInput } from './chunk-CMER5LO3.mjs';
|
|
8
|
-
export { TimePicker } from './chunk-
|
|
8
|
+
export { TimePicker } from './chunk-XAQT2CYE.mjs';
|
|
9
9
|
export { Toaster } from './chunk-YOTCXSXL.mjs';
|
|
10
10
|
export { Sidebar } from './chunk-PJH2KEWK.mjs';
|
|
11
11
|
export { Header } from './chunk-EL7COTGN.mjs';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkC5CAUNLU_cjs = require('../chunk-C5CAUNLU.cjs');
|
|
4
4
|
require('../chunk-L5VQZZVR.cjs');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
Object.defineProperty(exports, "TimePicker", {
|
|
9
9
|
enumerable: true,
|
|
10
|
-
get: function () { return
|
|
10
|
+
get: function () { return chunkC5CAUNLU_cjs.TimePicker; }
|
|
11
11
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { TimePicker } from '../chunk-
|
|
1
|
+
export { TimePicker } from '../chunk-XAQT2CYE.mjs';
|
|
2
2
|
import '../chunk-OCPFOFJ4.mjs';
|