@bricks-toolkit/toolkit 0.1.18 → 0.1.20
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/dist/chunk-3YIGXRMU.mjs +509 -0
- package/dist/chunk-4PRNRENN.mjs +104 -0
- package/dist/chunk-BIKJK4L4.cjs +511 -0
- package/dist/chunk-E6KUCC56.mjs +804 -0
- package/dist/chunk-FK5HAWIU.cjs +531 -0
- package/dist/chunk-HG4BPC2T.cjs +806 -0
- package/dist/chunk-J53N2LAE.cjs +115 -0
- package/dist/chunk-LKNQH36V.mjs +529 -0
- package/dist/chunk-M5V2IWA6.mjs +565 -0
- package/dist/chunk-WVRXSANT.cjs +567 -0
- package/dist/date-picker/index.cjs +3 -2
- package/dist/date-picker/index.d.mts +23 -3
- package/dist/date-picker/index.d.ts +23 -3
- package/dist/date-picker/index.mjs +2 -1
- package/dist/date-time-picker/index.cjs +12 -0
- package/dist/date-time-picker/index.d.mts +52 -0
- package/dist/date-time-picker/index.d.ts +52 -0
- package/dist/date-time-picker/index.mjs +3 -0
- package/dist/index.cjs +29 -23
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +8 -6
- package/dist/phone/index.cjs +2 -2
- package/dist/phone/index.d.mts +2 -2
- package/dist/phone/index.d.ts +2 -2
- package/dist/phone/index.mjs +1 -1
- package/dist/time-picker/index.cjs +2 -2
- package/dist/time-picker/index.d.mts +22 -3
- package/dist/time-picker/index.d.ts +22 -3
- package/dist/time-picker/index.mjs +1 -1
- package/package.json +11 -1
- package/dist/chunk-7WNJ7L4Z.mjs +0 -335
- package/dist/chunk-DHC5LI2P.cjs +0 -338
- package/dist/chunk-DOKSG7AW.cjs +0 -450
- package/dist/chunk-VKQDW7C2.mjs +0 -336
- package/dist/chunk-W2ZAPLQH.cjs +0 -337
- package/dist/chunk-ZCLNSMIW.mjs +0 -448
|
@@ -0,0 +1,804 @@
|
|
|
1
|
+
import { parseISODate, toISODateString, buildCalendarGrid, getYearRange, MONTH_NAMES, DAY_NAMES_SHORT, isSameDay, isDisabledDate, MONTH_NAMES_SHORT, formatDate } from './chunk-4PRNRENN.mjs';
|
|
2
|
+
import { cn } from './chunk-OCPFOFJ4.mjs';
|
|
3
|
+
import { useId, useState, useMemo, useRef, useEffect, useCallback } from 'react';
|
|
4
|
+
import { CalendarIcon, XMarkIcon, ClockIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronDownIcon } from '@heroicons/react/24/outline';
|
|
5
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function parseTime(v) {
|
|
8
|
+
const parts = (v || "00:00").split(":");
|
|
9
|
+
const numbers = parts.map(Number);
|
|
10
|
+
const h = numbers[0];
|
|
11
|
+
const m = numbers[1];
|
|
12
|
+
return {
|
|
13
|
+
hours: h === void 0 || isNaN(h) ? 0 : h,
|
|
14
|
+
minutes: m === void 0 || isNaN(m) ? 0 : m
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function pad(n) {
|
|
18
|
+
return String(n).padStart(2, "0");
|
|
19
|
+
}
|
|
20
|
+
function toTimeString(h, m) {
|
|
21
|
+
return `${pad(h)}:${pad(m)}`;
|
|
22
|
+
}
|
|
23
|
+
function formatTimeDisplay(v, use12) {
|
|
24
|
+
if (!v) return "";
|
|
25
|
+
const { hours, minutes } = parseTime(v);
|
|
26
|
+
if (use12) {
|
|
27
|
+
const ap = hours >= 12 ? "PM" : "AM";
|
|
28
|
+
return `${pad(hours % 12 || 12)}:${pad(minutes)} ${ap}`;
|
|
29
|
+
}
|
|
30
|
+
return toTimeString(hours, minutes);
|
|
31
|
+
}
|
|
32
|
+
function parseDT(v) {
|
|
33
|
+
if (!v) return { date: "", time: "" };
|
|
34
|
+
const [date, time] = v.split("T");
|
|
35
|
+
return { date: date ?? "", time: time ?? "" };
|
|
36
|
+
}
|
|
37
|
+
function formatDTDisplay(v, locale, use12) {
|
|
38
|
+
if (!v) return "";
|
|
39
|
+
const { date, time } = parseDT(v);
|
|
40
|
+
const d = parseISODate(date);
|
|
41
|
+
const datePart = d ? formatDate(d, locale) : date;
|
|
42
|
+
const timePart = formatTimeDisplay(time, use12);
|
|
43
|
+
return timePart ? `${datePart} ${timePart}` : datePart;
|
|
44
|
+
}
|
|
45
|
+
var ITEM_H = 36;
|
|
46
|
+
var sizeClasses = {
|
|
47
|
+
xs: "h-6 px-2 text-xs",
|
|
48
|
+
sm: "h-8 px-3 text-sm",
|
|
49
|
+
md: "h-10 px-3 text-sm",
|
|
50
|
+
lg: "h-11 px-4 text-base",
|
|
51
|
+
xl: "h-12 px-4 text-lg"
|
|
52
|
+
};
|
|
53
|
+
var labelSizeClasses = {
|
|
54
|
+
xs: "text-xs",
|
|
55
|
+
sm: "text-xs",
|
|
56
|
+
md: "text-sm",
|
|
57
|
+
lg: "text-sm",
|
|
58
|
+
xl: "text-base"
|
|
59
|
+
};
|
|
60
|
+
var variantClasses = {
|
|
61
|
+
default: "rounded-md border border-border bg-surface shadow-sm focus-within:ring-2 focus-within:ring-primary/40 transition-all duration-200",
|
|
62
|
+
filled: "rounded-md border border-transparent bg-surface-secondary focus-within:bg-surface focus-within:ring-2 focus-within:ring-primary/40 transition-all duration-200",
|
|
63
|
+
flushed: "rounded-none border-0 border-b border-border bg-transparent",
|
|
64
|
+
unstyled: "border-0 bg-transparent p-0"
|
|
65
|
+
};
|
|
66
|
+
var stateVariantClasses = {
|
|
67
|
+
default: {
|
|
68
|
+
default: "border-border focus-within:border-primary",
|
|
69
|
+
filled: "focus-within:border-primary",
|
|
70
|
+
flushed: "border-border",
|
|
71
|
+
unstyled: ""
|
|
72
|
+
},
|
|
73
|
+
error: {
|
|
74
|
+
default: "border-error focus-within:ring-error/20",
|
|
75
|
+
filled: "bg-error/5 focus-within:ring-error/20",
|
|
76
|
+
flushed: "border-error",
|
|
77
|
+
unstyled: ""
|
|
78
|
+
},
|
|
79
|
+
success: {
|
|
80
|
+
default: "border-success focus-within:ring-success/20",
|
|
81
|
+
filled: "bg-success/5 focus-within:ring-success/20",
|
|
82
|
+
flushed: "border-success",
|
|
83
|
+
unstyled: ""
|
|
84
|
+
},
|
|
85
|
+
warning: {
|
|
86
|
+
default: "border-warning focus-within:ring-warning/20",
|
|
87
|
+
filled: "bg-warning/5 focus-within:ring-warning/20",
|
|
88
|
+
flushed: "border-warning",
|
|
89
|
+
unstyled: ""
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
var stateMsgClasses = {
|
|
93
|
+
default: "text-text-muted",
|
|
94
|
+
error: "text-error font-medium",
|
|
95
|
+
success: "text-success font-medium",
|
|
96
|
+
warning: "text-warning font-medium"
|
|
97
|
+
};
|
|
98
|
+
function ScrollColumn({
|
|
99
|
+
items,
|
|
100
|
+
selected,
|
|
101
|
+
onSelect,
|
|
102
|
+
label
|
|
103
|
+
}) {
|
|
104
|
+
const ref = useRef(null);
|
|
105
|
+
const scrollTo = useCallback(
|
|
106
|
+
(beh = "smooth") => {
|
|
107
|
+
if (!ref.current) return;
|
|
108
|
+
const idx = items.indexOf(selected);
|
|
109
|
+
if (idx < 0) return;
|
|
110
|
+
if (typeof ref.current.scrollTo === "function") {
|
|
111
|
+
ref.current.scrollTo({ top: Math.max(0, idx * ITEM_H - ITEM_H * 2), behavior: beh });
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
[items, selected]
|
|
115
|
+
);
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
scrollTo("instant");
|
|
118
|
+
}, []);
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
scrollTo("smooth");
|
|
121
|
+
}, [scrollTo]);
|
|
122
|
+
const step = (dir) => {
|
|
123
|
+
const idx = items.indexOf(selected);
|
|
124
|
+
const next = items[(idx + dir + items.length) % items.length];
|
|
125
|
+
if (next) onSelect(next);
|
|
126
|
+
};
|
|
127
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-0.5", role: "group", "aria-label": label, children: [
|
|
128
|
+
/* @__PURE__ */ jsx(
|
|
129
|
+
"button",
|
|
130
|
+
{
|
|
131
|
+
type: "button",
|
|
132
|
+
onClick: () => {
|
|
133
|
+
step(-1);
|
|
134
|
+
},
|
|
135
|
+
className: "p-1 rounded hover:bg-hover text-text-secondary",
|
|
136
|
+
"aria-label": `Prev ${label}`,
|
|
137
|
+
children: /* @__PURE__ */ jsx(ChevronUpIcon, { className: "w-4 h-4" })
|
|
138
|
+
}
|
|
139
|
+
),
|
|
140
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
141
|
+
/* @__PURE__ */ jsx(
|
|
142
|
+
"div",
|
|
143
|
+
{
|
|
144
|
+
className: "absolute inset-x-0 rounded-lg bg-primary/10 border-y border-primary/20 pointer-events-none",
|
|
145
|
+
style: { top: ITEM_H * 2, height: ITEM_H }
|
|
146
|
+
}
|
|
147
|
+
),
|
|
148
|
+
/* @__PURE__ */ jsxs("div", { ref, className: "overflow-y-auto", style: { height: ITEM_H * 5, width: 52 }, children: [
|
|
149
|
+
/* @__PURE__ */ jsx("div", { style: { height: ITEM_H * 2 } }),
|
|
150
|
+
items.map((item) => /* @__PURE__ */ jsx(
|
|
151
|
+
"button",
|
|
152
|
+
{
|
|
153
|
+
type: "button",
|
|
154
|
+
onClick: () => {
|
|
155
|
+
onSelect(item);
|
|
156
|
+
},
|
|
157
|
+
style: { height: ITEM_H },
|
|
158
|
+
className: cn(
|
|
159
|
+
"w-full flex items-center justify-center rounded-lg text-sm font-medium hover:bg-hover transition-colors",
|
|
160
|
+
selected === item ? "text-primary font-bold" : "text-text-secondary"
|
|
161
|
+
),
|
|
162
|
+
"aria-pressed": selected === item,
|
|
163
|
+
children: item
|
|
164
|
+
},
|
|
165
|
+
item
|
|
166
|
+
)),
|
|
167
|
+
/* @__PURE__ */ jsx("div", { style: { height: ITEM_H * 2 } })
|
|
168
|
+
] })
|
|
169
|
+
] }),
|
|
170
|
+
/* @__PURE__ */ jsx(
|
|
171
|
+
"button",
|
|
172
|
+
{
|
|
173
|
+
type: "button",
|
|
174
|
+
onClick: () => {
|
|
175
|
+
step(1);
|
|
176
|
+
},
|
|
177
|
+
className: "p-1 rounded hover:bg-hover text-text-secondary",
|
|
178
|
+
"aria-label": `Next ${label}`,
|
|
179
|
+
children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "w-4 h-4" })
|
|
180
|
+
}
|
|
181
|
+
)
|
|
182
|
+
] });
|
|
183
|
+
}
|
|
184
|
+
function AddonIcon({
|
|
185
|
+
children,
|
|
186
|
+
side,
|
|
187
|
+
size,
|
|
188
|
+
onClick,
|
|
189
|
+
asButton = false,
|
|
190
|
+
ariaLabel
|
|
191
|
+
}) {
|
|
192
|
+
const sz = {
|
|
193
|
+
xs: "w-3.5 h-3.5",
|
|
194
|
+
sm: "w-4 h-4",
|
|
195
|
+
md: "w-4 h-4",
|
|
196
|
+
lg: "w-5 h-5",
|
|
197
|
+
xl: "w-5 h-5"
|
|
198
|
+
};
|
|
199
|
+
const base = cn(
|
|
200
|
+
"absolute top-1/2 -translate-y-1/2 text-text-secondary flex items-center justify-center",
|
|
201
|
+
side === "left" ? "left-3" : "right-3",
|
|
202
|
+
sz[size]
|
|
203
|
+
);
|
|
204
|
+
if (asButton && onClick)
|
|
205
|
+
return /* @__PURE__ */ jsx(
|
|
206
|
+
"button",
|
|
207
|
+
{
|
|
208
|
+
type: "button",
|
|
209
|
+
onClick,
|
|
210
|
+
className: cn(base, "cursor-pointer hover:text-text"),
|
|
211
|
+
tabIndex: -1,
|
|
212
|
+
"aria-label": ariaLabel,
|
|
213
|
+
children
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn(base, "pointer-events-none"), "aria-label": ariaLabel, children });
|
|
217
|
+
}
|
|
218
|
+
function DateTimePicker({
|
|
219
|
+
label,
|
|
220
|
+
required = false,
|
|
221
|
+
helperText,
|
|
222
|
+
errorMessage,
|
|
223
|
+
successMessage,
|
|
224
|
+
warningMessage,
|
|
225
|
+
variant = "default",
|
|
226
|
+
size = "md",
|
|
227
|
+
state = "default",
|
|
228
|
+
fullWidth = true,
|
|
229
|
+
leftElement,
|
|
230
|
+
rightElement,
|
|
231
|
+
prefix,
|
|
232
|
+
suffix,
|
|
233
|
+
wrapperClassName,
|
|
234
|
+
inputGroupClassName,
|
|
235
|
+
inputClassName,
|
|
236
|
+
labelClassName,
|
|
237
|
+
helperClassName,
|
|
238
|
+
className,
|
|
239
|
+
clearable,
|
|
240
|
+
isLoading,
|
|
241
|
+
disabled,
|
|
242
|
+
value,
|
|
243
|
+
defaultValue,
|
|
244
|
+
onChange,
|
|
245
|
+
onDateTimeChange,
|
|
246
|
+
placeholder = "Select date & time",
|
|
247
|
+
locale = "en-US",
|
|
248
|
+
minDate,
|
|
249
|
+
maxDate,
|
|
250
|
+
disabledDates,
|
|
251
|
+
minuteStep = 1,
|
|
252
|
+
use12Hour = false,
|
|
253
|
+
id: idProp,
|
|
254
|
+
name,
|
|
255
|
+
"aria-label": ariaLabel,
|
|
256
|
+
"aria-describedby": ariaDescribedby
|
|
257
|
+
}) {
|
|
258
|
+
const genId = useId();
|
|
259
|
+
const inputId = idProp ?? genId;
|
|
260
|
+
const popoverId = `${inputId}-popover`;
|
|
261
|
+
const helperId = `${inputId}-helper`;
|
|
262
|
+
const stateMessageId = `${inputId}-state`;
|
|
263
|
+
const isControlled = value !== void 0;
|
|
264
|
+
const [internalValue, setInternalValue] = useState(defaultValue ?? "");
|
|
265
|
+
const displayValue = isControlled ? value : internalValue;
|
|
266
|
+
const { date: selDateStr, time: selTimeStr } = parseDT(displayValue);
|
|
267
|
+
const selDate = parseISODate(selDateStr);
|
|
268
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
269
|
+
const [tab, setTab] = useState("date");
|
|
270
|
+
const today = useMemo(() => /* @__PURE__ */ new Date(), []);
|
|
271
|
+
const [viewYear, setViewYear] = useState(selDate?.getFullYear() ?? today.getFullYear());
|
|
272
|
+
const [viewMonth, setViewMonth] = useState(selDate?.getMonth() ?? today.getMonth());
|
|
273
|
+
const [viewMode, setViewMode] = useState("day");
|
|
274
|
+
const { hours: sH, minutes: sM } = parseTime(selTimeStr || "00:00");
|
|
275
|
+
const [pickerHour, setPickerHour] = useState(pad(use12Hour ? sH % 12 || 12 : sH));
|
|
276
|
+
const [pickerMinute, setPickerMinute] = useState(pad(sM));
|
|
277
|
+
const [pickerAmpm, setPickerAmpm] = useState(sH >= 12 ? "PM" : "AM");
|
|
278
|
+
const wrapperRef = useRef(null);
|
|
279
|
+
useEffect(() => {
|
|
280
|
+
if (!isOpen) return;
|
|
281
|
+
const h = (e) => {
|
|
282
|
+
if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
|
|
283
|
+
setIsOpen(false);
|
|
284
|
+
setViewMode("day");
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
document.addEventListener("mousedown", h);
|
|
288
|
+
return () => {
|
|
289
|
+
document.removeEventListener("mousedown", h);
|
|
290
|
+
};
|
|
291
|
+
}, [isOpen]);
|
|
292
|
+
const [prevVal, setPrevVal] = useState(displayValue);
|
|
293
|
+
if (displayValue !== prevVal) {
|
|
294
|
+
setPrevVal(displayValue);
|
|
295
|
+
if (selDate) {
|
|
296
|
+
setViewYear(selDate.getFullYear());
|
|
297
|
+
setViewMonth(selDate.getMonth());
|
|
298
|
+
}
|
|
299
|
+
const { hours, minutes } = parseTime(selTimeStr || "00:00");
|
|
300
|
+
setPickerHour(pad(use12Hour ? hours % 12 || 12 : hours));
|
|
301
|
+
setPickerMinute(pad(minutes));
|
|
302
|
+
setPickerAmpm(hours >= 12 ? "PM" : "AM");
|
|
303
|
+
}
|
|
304
|
+
const commit = useCallback(
|
|
305
|
+
(dateStr, timeStr) => {
|
|
306
|
+
const combined = `${dateStr}T${timeStr}`;
|
|
307
|
+
if (!isControlled) setInternalValue(combined);
|
|
308
|
+
onChange?.(combined);
|
|
309
|
+
const d = parseISODate(dateStr);
|
|
310
|
+
if (d) {
|
|
311
|
+
const { hours, minutes } = parseTime(timeStr);
|
|
312
|
+
d.setHours(hours, minutes);
|
|
313
|
+
onDateTimeChange?.(d);
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
[isControlled, onChange, onDateTimeChange]
|
|
317
|
+
);
|
|
318
|
+
const handleDateSelect = (date) => {
|
|
319
|
+
if (isDisabledDate(date, minDate, maxDate, disabledDates)) return;
|
|
320
|
+
const time = selTimeStr || toTimeString(parseInt(pickerHour), parseInt(pickerMinute));
|
|
321
|
+
commit(toISODateString(date), time);
|
|
322
|
+
setTab("time");
|
|
323
|
+
};
|
|
324
|
+
const applyTime = useCallback(
|
|
325
|
+
(h, m, ap) => {
|
|
326
|
+
let hours24 = parseInt(h);
|
|
327
|
+
if (use12Hour) {
|
|
328
|
+
if (ap === "AM" && hours24 === 12) hours24 = 0;
|
|
329
|
+
if (ap === "PM" && hours24 !== 12) hours24 += 12;
|
|
330
|
+
}
|
|
331
|
+
const dateStr = selDateStr || toISODateString(today);
|
|
332
|
+
commit(dateStr, toTimeString(hours24, parseInt(m)));
|
|
333
|
+
},
|
|
334
|
+
[use12Hour, selDateStr, commit, today]
|
|
335
|
+
);
|
|
336
|
+
const handleHour = (h) => {
|
|
337
|
+
setPickerHour(h);
|
|
338
|
+
applyTime(h, pickerMinute, pickerAmpm);
|
|
339
|
+
};
|
|
340
|
+
const handleMinute = (m) => {
|
|
341
|
+
setPickerMinute(m);
|
|
342
|
+
applyTime(pickerHour, m, pickerAmpm);
|
|
343
|
+
};
|
|
344
|
+
const handleAmpm = (ap) => {
|
|
345
|
+
const a = ap;
|
|
346
|
+
setPickerAmpm(a);
|
|
347
|
+
applyTime(pickerHour, pickerMinute, a);
|
|
348
|
+
};
|
|
349
|
+
const handleNow = () => {
|
|
350
|
+
const now = /* @__PURE__ */ new Date();
|
|
351
|
+
const dateStr = toISODateString(now);
|
|
352
|
+
const timeStr = toTimeString(now.getHours(), now.getMinutes());
|
|
353
|
+
if (!isControlled) setInternalValue(`${dateStr}T${timeStr}`);
|
|
354
|
+
onChange?.(`${dateStr}T${timeStr}`);
|
|
355
|
+
onDateTimeChange?.(now);
|
|
356
|
+
setIsOpen(false);
|
|
357
|
+
};
|
|
358
|
+
const handleClear = () => {
|
|
359
|
+
if (!isControlled) setInternalValue("");
|
|
360
|
+
onChange?.("");
|
|
361
|
+
onDateTimeChange?.(null);
|
|
362
|
+
};
|
|
363
|
+
const hourItems = use12Hour ? Array.from({ length: 12 }, (_, i) => pad(i + 1)) : Array.from({ length: 24 }, (_, i) => pad(i));
|
|
364
|
+
const minuteItems = Array.from(
|
|
365
|
+
{ length: Math.ceil(60 / minuteStep) },
|
|
366
|
+
(_, i) => pad(i * minuteStep)
|
|
367
|
+
);
|
|
368
|
+
const showClear = clearable && displayValue.length > 0 && !disabled && !isLoading;
|
|
369
|
+
const rightPad = {
|
|
370
|
+
xs: "pr-6",
|
|
371
|
+
sm: "pr-8",
|
|
372
|
+
md: "pr-9",
|
|
373
|
+
lg: "pr-10",
|
|
374
|
+
xl: "pr-11"
|
|
375
|
+
};
|
|
376
|
+
const calendarGrid = buildCalendarGrid(viewYear, viewMonth);
|
|
377
|
+
const yearRange = getYearRange(viewYear);
|
|
378
|
+
const stateMessage = state === "error" ? errorMessage : state === "success" ? successMessage : state === "warning" ? warningMessage : void 0;
|
|
379
|
+
const describedBy = [helperText ? helperId : null, stateMessage ? stateMessageId : null, ariaDescribedby ?? null].filter(Boolean).join(" ") || void 0;
|
|
380
|
+
const prevMonth = () => {
|
|
381
|
+
if (viewMonth === 0) {
|
|
382
|
+
setViewMonth(11);
|
|
383
|
+
setViewYear((y) => y - 1);
|
|
384
|
+
} else setViewMonth((m) => m - 1);
|
|
385
|
+
};
|
|
386
|
+
const nextMonth = () => {
|
|
387
|
+
if (viewMonth === 11) {
|
|
388
|
+
setViewMonth(0);
|
|
389
|
+
setViewYear((y) => y + 1);
|
|
390
|
+
} else setViewMonth((m) => m + 1);
|
|
391
|
+
};
|
|
392
|
+
return /* @__PURE__ */ jsxs(
|
|
393
|
+
"div",
|
|
394
|
+
{
|
|
395
|
+
ref: wrapperRef,
|
|
396
|
+
className: cn(
|
|
397
|
+
"flex flex-col gap-1 relative",
|
|
398
|
+
fullWidth ? "w-full" : "w-fit",
|
|
399
|
+
wrapperClassName,
|
|
400
|
+
className
|
|
401
|
+
),
|
|
402
|
+
children: [
|
|
403
|
+
label !== void 0 && /* @__PURE__ */ jsxs(
|
|
404
|
+
"label",
|
|
405
|
+
{
|
|
406
|
+
htmlFor: inputId,
|
|
407
|
+
className: cn(
|
|
408
|
+
"font-black leading-none text-text uppercase tracking-widest",
|
|
409
|
+
labelSizeClasses[size],
|
|
410
|
+
labelClassName
|
|
411
|
+
),
|
|
412
|
+
children: [
|
|
413
|
+
label,
|
|
414
|
+
required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ml-1 text-error", children: "*" })
|
|
415
|
+
]
|
|
416
|
+
}
|
|
417
|
+
),
|
|
418
|
+
/* @__PURE__ */ jsxs(
|
|
419
|
+
"div",
|
|
420
|
+
{
|
|
421
|
+
className: cn("flex items-stretch", fullWidth ? "w-full" : "w-fit", inputGroupClassName),
|
|
422
|
+
children: [
|
|
423
|
+
prefix && /* @__PURE__ */ jsx("span", { className: "inline-flex items-center border border-border bg-surface-secondary px-3 text-sm text-text-secondary rounded-l-md border-r-0", children: prefix }),
|
|
424
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex flex-1 items-center", children: [
|
|
425
|
+
/* @__PURE__ */ jsx(AddonIcon, { side: "left", size, children: leftElement ?? /* @__PURE__ */ jsx(CalendarIcon, { className: "w-full h-full" }) }),
|
|
426
|
+
/* @__PURE__ */ jsx(
|
|
427
|
+
"button",
|
|
428
|
+
{
|
|
429
|
+
id: inputId,
|
|
430
|
+
type: "button",
|
|
431
|
+
role: "combobox",
|
|
432
|
+
"aria-expanded": isOpen,
|
|
433
|
+
"aria-haspopup": "dialog",
|
|
434
|
+
"aria-controls": popoverId,
|
|
435
|
+
"aria-label": ariaLabel ?? label ?? "Date time picker",
|
|
436
|
+
"aria-describedby": describedBy,
|
|
437
|
+
"aria-required": required,
|
|
438
|
+
"aria-invalid": state === "error" ? true : void 0,
|
|
439
|
+
disabled: Boolean(disabled) || Boolean(isLoading),
|
|
440
|
+
onClick: () => {
|
|
441
|
+
if (!disabled && !isLoading) setIsOpen((p) => !p);
|
|
442
|
+
},
|
|
443
|
+
name,
|
|
444
|
+
className: cn(
|
|
445
|
+
"w-full flex items-center text-left cursor-pointer disabled:cursor-not-allowed disabled:opacity-50",
|
|
446
|
+
sizeClasses[size],
|
|
447
|
+
variantClasses[variant],
|
|
448
|
+
stateVariantClasses[state][variant],
|
|
449
|
+
"pl-9",
|
|
450
|
+
showClear || rightElement ? rightPad[size] : "",
|
|
451
|
+
prefix && suffix ? "rounded-none" : prefix ? "rounded-l-none" : suffix ? "rounded-r-none" : "",
|
|
452
|
+
inputClassName
|
|
453
|
+
),
|
|
454
|
+
children: displayValue ? /* @__PURE__ */ jsx("span", { className: "text-text truncate", children: formatDTDisplay(displayValue, locale, use12Hour) }) : /* @__PURE__ */ jsx("span", { className: "text-text-muted", children: placeholder })
|
|
455
|
+
}
|
|
456
|
+
),
|
|
457
|
+
isLoading ? /* @__PURE__ */ jsx(AddonIcon, { side: "right", size, children: /* @__PURE__ */ jsxs(
|
|
458
|
+
"svg",
|
|
459
|
+
{
|
|
460
|
+
className: "animate-spin h-full w-full text-text-muted",
|
|
461
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
462
|
+
fill: "none",
|
|
463
|
+
viewBox: "0 0 24 24",
|
|
464
|
+
children: [
|
|
465
|
+
/* @__PURE__ */ jsx(
|
|
466
|
+
"circle",
|
|
467
|
+
{
|
|
468
|
+
className: "opacity-25",
|
|
469
|
+
cx: "12",
|
|
470
|
+
cy: "12",
|
|
471
|
+
r: "10",
|
|
472
|
+
stroke: "currentColor",
|
|
473
|
+
strokeWidth: "4"
|
|
474
|
+
}
|
|
475
|
+
),
|
|
476
|
+
/* @__PURE__ */ jsx(
|
|
477
|
+
"path",
|
|
478
|
+
{
|
|
479
|
+
className: "opacity-75",
|
|
480
|
+
fill: "currentColor",
|
|
481
|
+
d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
482
|
+
}
|
|
483
|
+
)
|
|
484
|
+
]
|
|
485
|
+
}
|
|
486
|
+
) }) : showClear ? /* @__PURE__ */ jsx(
|
|
487
|
+
AddonIcon,
|
|
488
|
+
{
|
|
489
|
+
side: "right",
|
|
490
|
+
size,
|
|
491
|
+
asButton: true,
|
|
492
|
+
onClick: handleClear,
|
|
493
|
+
ariaLabel: "Clear date time",
|
|
494
|
+
children: /* @__PURE__ */ jsx(XMarkIcon, { className: "w-full h-full", strokeWidth: 2.5 })
|
|
495
|
+
}
|
|
496
|
+
) : rightElement ? /* @__PURE__ */ jsx(AddonIcon, { side: "right", size, children: rightElement }) : null
|
|
497
|
+
] }),
|
|
498
|
+
suffix && /* @__PURE__ */ jsx("span", { className: "inline-flex items-center border border-border bg-surface-secondary px-3 text-sm text-text-secondary rounded-r-md border-l-0", children: suffix })
|
|
499
|
+
]
|
|
500
|
+
}
|
|
501
|
+
),
|
|
502
|
+
helperText && /* @__PURE__ */ jsx(
|
|
503
|
+
"p",
|
|
504
|
+
{
|
|
505
|
+
id: helperId,
|
|
506
|
+
className: cn("text-xs leading-tight text-text-muted font-medium", helperClassName),
|
|
507
|
+
children: helperText
|
|
508
|
+
}
|
|
509
|
+
),
|
|
510
|
+
stateMessage && /* @__PURE__ */ jsx(
|
|
511
|
+
"p",
|
|
512
|
+
{
|
|
513
|
+
id: stateMessageId,
|
|
514
|
+
role: state === "error" ? "alert" : void 0,
|
|
515
|
+
className: cn(
|
|
516
|
+
"text-xs leading-tight mt-0.5 font-medium",
|
|
517
|
+
stateMsgClasses[state],
|
|
518
|
+
helperClassName
|
|
519
|
+
),
|
|
520
|
+
children: stateMessage
|
|
521
|
+
}
|
|
522
|
+
),
|
|
523
|
+
/* @__PURE__ */ jsxs(
|
|
524
|
+
"div",
|
|
525
|
+
{
|
|
526
|
+
id: popoverId,
|
|
527
|
+
role: "dialog",
|
|
528
|
+
"aria-label": "Date and time picker",
|
|
529
|
+
"aria-modal": "true",
|
|
530
|
+
className: cn(
|
|
531
|
+
"absolute top-full left-0 z-50 mt-1 w-72 bg-surface border border-border rounded-xl shadow-xl",
|
|
532
|
+
"transition-all duration-200 origin-top",
|
|
533
|
+
isOpen ? "opacity-100 scale-100 pointer-events-auto" : "opacity-0 scale-95 pointer-events-none"
|
|
534
|
+
),
|
|
535
|
+
children: [
|
|
536
|
+
/* @__PURE__ */ jsx("div", { className: "flex border-b border-border", children: ["date", "time"].map((t) => /* @__PURE__ */ jsxs(
|
|
537
|
+
"button",
|
|
538
|
+
{
|
|
539
|
+
type: "button",
|
|
540
|
+
onClick: () => {
|
|
541
|
+
setTab(t);
|
|
542
|
+
},
|
|
543
|
+
className: cn(
|
|
544
|
+
"flex-1 flex items-center justify-center gap-1.5 py-2.5 text-xs font-bold uppercase tracking-wider transition-colors",
|
|
545
|
+
tab === t ? "text-primary border-b-2 border-primary -mb-px" : "text-text-muted hover:text-text"
|
|
546
|
+
),
|
|
547
|
+
children: [
|
|
548
|
+
t === "date" ? /* @__PURE__ */ jsx(CalendarIcon, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ jsx(ClockIcon, { className: "w-3.5 h-3.5" }),
|
|
549
|
+
t
|
|
550
|
+
]
|
|
551
|
+
},
|
|
552
|
+
t
|
|
553
|
+
)) }),
|
|
554
|
+
/* @__PURE__ */ jsxs("div", { className: "p-3", children: [
|
|
555
|
+
tab === "date" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
556
|
+
viewMode === "day" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
557
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
|
|
558
|
+
/* @__PURE__ */ jsx(
|
|
559
|
+
"button",
|
|
560
|
+
{
|
|
561
|
+
type: "button",
|
|
562
|
+
onClick: prevMonth,
|
|
563
|
+
className: "p-1.5 rounded-lg hover:bg-hover text-text-secondary",
|
|
564
|
+
"aria-label": "Previous month",
|
|
565
|
+
children: /* @__PURE__ */ jsx(ChevronLeftIcon, { className: "w-4 h-4" })
|
|
566
|
+
}
|
|
567
|
+
),
|
|
568
|
+
/* @__PURE__ */ jsxs(
|
|
569
|
+
"button",
|
|
570
|
+
{
|
|
571
|
+
type: "button",
|
|
572
|
+
onClick: () => {
|
|
573
|
+
setViewMode("month");
|
|
574
|
+
},
|
|
575
|
+
className: "text-sm font-bold text-text hover:text-primary px-2 py-1 rounded-lg hover:bg-hover",
|
|
576
|
+
children: [
|
|
577
|
+
MONTH_NAMES[viewMonth],
|
|
578
|
+
" ",
|
|
579
|
+
viewYear
|
|
580
|
+
]
|
|
581
|
+
}
|
|
582
|
+
),
|
|
583
|
+
/* @__PURE__ */ jsx(
|
|
584
|
+
"button",
|
|
585
|
+
{
|
|
586
|
+
type: "button",
|
|
587
|
+
onClick: nextMonth,
|
|
588
|
+
className: "p-1.5 rounded-lg hover:bg-hover text-text-secondary",
|
|
589
|
+
"aria-label": "Next month",
|
|
590
|
+
children: /* @__PURE__ */ jsx(ChevronRightIcon, { className: "w-4 h-4" })
|
|
591
|
+
}
|
|
592
|
+
)
|
|
593
|
+
] }),
|
|
594
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 mb-1", children: DAY_NAMES_SHORT.map((d) => /* @__PURE__ */ jsx(
|
|
595
|
+
"div",
|
|
596
|
+
{
|
|
597
|
+
className: "text-center text-xs font-semibold text-text-muted py-1",
|
|
598
|
+
children: d
|
|
599
|
+
},
|
|
600
|
+
d
|
|
601
|
+
)) }),
|
|
602
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-y-0.5", children: calendarGrid.flat().map((date, idx) => {
|
|
603
|
+
if (!date) return /* @__PURE__ */ jsx("div", {}, idx);
|
|
604
|
+
const isSel = selDate ? isSameDay(date, selDate) : false;
|
|
605
|
+
const isToday = isSameDay(date, today);
|
|
606
|
+
const isDis = isDisabledDate(date, minDate, maxDate, disabledDates);
|
|
607
|
+
return /* @__PURE__ */ jsx(
|
|
608
|
+
"button",
|
|
609
|
+
{
|
|
610
|
+
type: "button",
|
|
611
|
+
onClick: () => {
|
|
612
|
+
handleDateSelect(date);
|
|
613
|
+
},
|
|
614
|
+
disabled: isDis,
|
|
615
|
+
className: cn(
|
|
616
|
+
"mx-auto flex h-8 w-8 items-center justify-center rounded-full text-sm font-medium transition-colors",
|
|
617
|
+
isSel ? "bg-primary text-white font-bold" : isToday ? "ring-2 ring-primary text-primary" : "text-text hover:bg-hover",
|
|
618
|
+
isDis && "opacity-30 cursor-not-allowed"
|
|
619
|
+
),
|
|
620
|
+
children: date.getDate()
|
|
621
|
+
},
|
|
622
|
+
idx
|
|
623
|
+
);
|
|
624
|
+
}) })
|
|
625
|
+
] }),
|
|
626
|
+
viewMode === "month" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
627
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
|
|
628
|
+
/* @__PURE__ */ jsx(
|
|
629
|
+
"button",
|
|
630
|
+
{
|
|
631
|
+
type: "button",
|
|
632
|
+
onClick: () => {
|
|
633
|
+
setViewYear((y) => y - 1);
|
|
634
|
+
},
|
|
635
|
+
className: "p-1.5 rounded-lg hover:bg-hover text-text-secondary",
|
|
636
|
+
children: /* @__PURE__ */ jsx(ChevronLeftIcon, { className: "w-4 h-4" })
|
|
637
|
+
}
|
|
638
|
+
),
|
|
639
|
+
/* @__PURE__ */ jsx(
|
|
640
|
+
"button",
|
|
641
|
+
{
|
|
642
|
+
type: "button",
|
|
643
|
+
onClick: () => {
|
|
644
|
+
setViewMode("year");
|
|
645
|
+
},
|
|
646
|
+
className: "text-sm font-bold text-text hover:text-primary px-2 py-1 rounded-lg hover:bg-hover",
|
|
647
|
+
children: viewYear
|
|
648
|
+
}
|
|
649
|
+
),
|
|
650
|
+
/* @__PURE__ */ jsx(
|
|
651
|
+
"button",
|
|
652
|
+
{
|
|
653
|
+
type: "button",
|
|
654
|
+
onClick: () => {
|
|
655
|
+
setViewYear((y) => y + 1);
|
|
656
|
+
},
|
|
657
|
+
className: "p-1.5 rounded-lg hover:bg-hover text-text-secondary",
|
|
658
|
+
children: /* @__PURE__ */ jsx(ChevronRightIcon, { className: "w-4 h-4" })
|
|
659
|
+
}
|
|
660
|
+
)
|
|
661
|
+
] }),
|
|
662
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-1", children: MONTH_NAMES_SHORT.map((m, i) => /* @__PURE__ */ jsx(
|
|
663
|
+
"button",
|
|
664
|
+
{
|
|
665
|
+
type: "button",
|
|
666
|
+
onClick: () => {
|
|
667
|
+
setViewMonth(i);
|
|
668
|
+
setViewMode("day");
|
|
669
|
+
},
|
|
670
|
+
className: cn(
|
|
671
|
+
"py-2 rounded-lg text-sm font-medium transition-colors",
|
|
672
|
+
i === viewMonth ? "bg-primary text-white" : "text-text hover:bg-hover"
|
|
673
|
+
),
|
|
674
|
+
children: m
|
|
675
|
+
},
|
|
676
|
+
m
|
|
677
|
+
)) })
|
|
678
|
+
] }),
|
|
679
|
+
viewMode === "year" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
680
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
|
|
681
|
+
/* @__PURE__ */ jsx(
|
|
682
|
+
"button",
|
|
683
|
+
{
|
|
684
|
+
type: "button",
|
|
685
|
+
onClick: () => {
|
|
686
|
+
setViewYear((y) => y - 12);
|
|
687
|
+
},
|
|
688
|
+
className: "p-1.5 rounded-lg hover:bg-hover text-text-secondary",
|
|
689
|
+
children: /* @__PURE__ */ jsx(ChevronLeftIcon, { className: "w-4 h-4" })
|
|
690
|
+
}
|
|
691
|
+
),
|
|
692
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm font-bold text-text", children: [
|
|
693
|
+
yearRange[0],
|
|
694
|
+
" \u2013 ",
|
|
695
|
+
yearRange[yearRange.length - 1]
|
|
696
|
+
] }),
|
|
697
|
+
/* @__PURE__ */ jsx(
|
|
698
|
+
"button",
|
|
699
|
+
{
|
|
700
|
+
type: "button",
|
|
701
|
+
onClick: () => {
|
|
702
|
+
setViewYear((y) => y + 12);
|
|
703
|
+
},
|
|
704
|
+
className: "p-1.5 rounded-lg hover:bg-hover text-text-secondary",
|
|
705
|
+
children: /* @__PURE__ */ jsx(ChevronRightIcon, { className: "w-4 h-4" })
|
|
706
|
+
}
|
|
707
|
+
)
|
|
708
|
+
] }),
|
|
709
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-1", children: yearRange.map((yr) => /* @__PURE__ */ jsx(
|
|
710
|
+
"button",
|
|
711
|
+
{
|
|
712
|
+
type: "button",
|
|
713
|
+
onClick: () => {
|
|
714
|
+
setViewYear(yr);
|
|
715
|
+
setViewMode("month");
|
|
716
|
+
},
|
|
717
|
+
className: cn(
|
|
718
|
+
"py-2 rounded-lg text-sm font-medium transition-colors",
|
|
719
|
+
yr === selDate?.getFullYear() ? "bg-primary text-white" : "text-text hover:bg-hover",
|
|
720
|
+
yr === today.getFullYear() && yr !== selDate?.getFullYear() ? "ring-1 ring-primary text-primary" : ""
|
|
721
|
+
),
|
|
722
|
+
children: yr
|
|
723
|
+
},
|
|
724
|
+
yr
|
|
725
|
+
)) })
|
|
726
|
+
] })
|
|
727
|
+
] }),
|
|
728
|
+
tab === "time" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
|
|
729
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-bold text-text-muted uppercase tracking-widest mb-3", children: "Select Time" }),
|
|
730
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-1", children: [
|
|
731
|
+
/* @__PURE__ */ jsx(
|
|
732
|
+
ScrollColumn,
|
|
733
|
+
{
|
|
734
|
+
items: hourItems,
|
|
735
|
+
selected: pickerHour,
|
|
736
|
+
onSelect: handleHour,
|
|
737
|
+
label: "Hour"
|
|
738
|
+
}
|
|
739
|
+
),
|
|
740
|
+
/* @__PURE__ */ jsx(
|
|
741
|
+
"div",
|
|
742
|
+
{
|
|
743
|
+
className: "flex items-center self-center text-text-muted font-bold text-lg pb-2",
|
|
744
|
+
style: { height: ITEM_H },
|
|
745
|
+
children: ":"
|
|
746
|
+
}
|
|
747
|
+
),
|
|
748
|
+
/* @__PURE__ */ jsx(
|
|
749
|
+
ScrollColumn,
|
|
750
|
+
{
|
|
751
|
+
items: minuteItems,
|
|
752
|
+
selected: pickerMinute,
|
|
753
|
+
onSelect: handleMinute,
|
|
754
|
+
label: "Minute"
|
|
755
|
+
}
|
|
756
|
+
),
|
|
757
|
+
use12Hour && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
758
|
+
/* @__PURE__ */ jsx("div", { className: "w-px self-stretch bg-border mx-1" }),
|
|
759
|
+
/* @__PURE__ */ jsx(
|
|
760
|
+
ScrollColumn,
|
|
761
|
+
{
|
|
762
|
+
items: ["AM", "PM"],
|
|
763
|
+
selected: pickerAmpm,
|
|
764
|
+
onSelect: handleAmpm,
|
|
765
|
+
label: "AM/PM"
|
|
766
|
+
}
|
|
767
|
+
)
|
|
768
|
+
] })
|
|
769
|
+
] }),
|
|
770
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3 pt-3 border-t border-border w-full text-center", children: /* @__PURE__ */ jsx("span", { className: "text-sm font-bold text-primary font-mono", children: selTimeStr ? formatTimeDisplay(selTimeStr, use12Hour) : "\u2013\u2013:\u2013\u2013" }) })
|
|
771
|
+
] })
|
|
772
|
+
] }),
|
|
773
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-3 pb-3 pt-1 gap-2", children: [
|
|
774
|
+
/* @__PURE__ */ jsx(
|
|
775
|
+
"button",
|
|
776
|
+
{
|
|
777
|
+
type: "button",
|
|
778
|
+
onClick: handleNow,
|
|
779
|
+
className: "flex-1 py-1.5 rounded-lg text-xs font-bold text-primary border border-primary/30 hover:bg-primary/10 transition-colors",
|
|
780
|
+
children: "Now"
|
|
781
|
+
}
|
|
782
|
+
),
|
|
783
|
+
/* @__PURE__ */ jsx(
|
|
784
|
+
"button",
|
|
785
|
+
{
|
|
786
|
+
type: "button",
|
|
787
|
+
onClick: () => {
|
|
788
|
+
setIsOpen(false);
|
|
789
|
+
setViewMode("day");
|
|
790
|
+
},
|
|
791
|
+
className: "flex-1 py-1.5 rounded-lg text-xs font-bold bg-primary text-white hover:bg-primary/90 transition-colors",
|
|
792
|
+
children: "Apply"
|
|
793
|
+
}
|
|
794
|
+
)
|
|
795
|
+
] })
|
|
796
|
+
]
|
|
797
|
+
}
|
|
798
|
+
)
|
|
799
|
+
]
|
|
800
|
+
}
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
export { DateTimePicker };
|