@underverse-ui/underverse 0.2.109 → 0.2.111
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/index.cjs +86 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +86 -57
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6196,8 +6196,8 @@ var DatePicker = ({
|
|
|
6196
6196
|
"div",
|
|
6197
6197
|
{
|
|
6198
6198
|
className: cn(
|
|
6199
|
-
"flex items-center justify-center
|
|
6200
|
-
isOpen ? "
|
|
6199
|
+
"flex items-center justify-center transition-colors duration-300",
|
|
6200
|
+
isOpen ? "text-primary" : "text-muted-foreground group-hover:text-primary"
|
|
6201
6201
|
),
|
|
6202
6202
|
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.Calendar, { className: cn(size === "sm" ? "h-3.5 w-3.5" : "h-4 w-4", "transition-transform duration-300", isOpen && "scale-110") })
|
|
6203
6203
|
}
|
|
@@ -6492,9 +6492,8 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
|
|
|
6492
6492
|
"div",
|
|
6493
6493
|
{
|
|
6494
6494
|
className: cn(
|
|
6495
|
-
"flex items-center justify-center
|
|
6496
|
-
|
|
6497
|
-
isOpen ? "bg-primary/15 text-primary" : "bg-muted/50 text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary"
|
|
6495
|
+
"flex items-center justify-center transition-colors duration-300",
|
|
6496
|
+
isOpen ? "text-primary" : "text-muted-foreground group-hover:text-primary"
|
|
6498
6497
|
),
|
|
6499
6498
|
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react14.Calendar, { className: cn("transition-transform duration-300", size === "sm" ? "h-3 w-3" : "h-4 w-4", isOpen && "scale-110") })
|
|
6500
6499
|
}
|
|
@@ -7568,6 +7567,8 @@ function TimePicker({
|
|
|
7568
7567
|
showPresets = false,
|
|
7569
7568
|
allowManualInput = false,
|
|
7570
7569
|
customPresets = [],
|
|
7570
|
+
min,
|
|
7571
|
+
max,
|
|
7571
7572
|
minTime,
|
|
7572
7573
|
maxTime,
|
|
7573
7574
|
disabledTimes,
|
|
@@ -7604,37 +7605,65 @@ function TimePicker({
|
|
|
7604
7605
|
},
|
|
7605
7606
|
[disabledTimes]
|
|
7606
7607
|
);
|
|
7608
|
+
const resolvedMinTime = minTime ?? min;
|
|
7609
|
+
const resolvedMaxTime = maxTime ?? max;
|
|
7610
|
+
const toSeconds = React25.useCallback(
|
|
7611
|
+
(p) => {
|
|
7612
|
+
let h = p.h;
|
|
7613
|
+
if (format === "12") {
|
|
7614
|
+
const period = p.p ?? (h >= 12 ? "PM" : "AM");
|
|
7615
|
+
const base = h % 12;
|
|
7616
|
+
h = period === "PM" ? base + 12 : base;
|
|
7617
|
+
}
|
|
7618
|
+
return h * 3600 + p.m * 60 + (includeSeconds ? p.s : 0);
|
|
7619
|
+
},
|
|
7620
|
+
[format, includeSeconds]
|
|
7621
|
+
);
|
|
7607
7622
|
const isTimeInRange = React25.useCallback(
|
|
7608
7623
|
(timeStr) => {
|
|
7609
|
-
if (!
|
|
7624
|
+
if (!resolvedMinTime && !resolvedMaxTime) return true;
|
|
7610
7625
|
const parsed = parseTime(timeStr, format, includeSeconds);
|
|
7611
7626
|
if (!parsed) return true;
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
const minMinutes = min.h * 60 + min.m;
|
|
7617
|
-
if (currentMinutes < minMinutes) return false;
|
|
7618
|
-
}
|
|
7627
|
+
const current = toSeconds(parsed);
|
|
7628
|
+
if (resolvedMinTime) {
|
|
7629
|
+
const minParsed = parseTime(resolvedMinTime, format, includeSeconds);
|
|
7630
|
+
if (minParsed && current < toSeconds(minParsed)) return false;
|
|
7619
7631
|
}
|
|
7620
|
-
if (
|
|
7621
|
-
const
|
|
7622
|
-
if (
|
|
7623
|
-
const currentMinutes = parsed.h * 60 + parsed.m;
|
|
7624
|
-
const maxMinutes = max.h * 60 + max.m;
|
|
7625
|
-
if (currentMinutes > maxMinutes) return false;
|
|
7626
|
-
}
|
|
7632
|
+
if (resolvedMaxTime) {
|
|
7633
|
+
const maxParsed = parseTime(resolvedMaxTime, format, includeSeconds);
|
|
7634
|
+
if (maxParsed && current > toSeconds(maxParsed)) return false;
|
|
7627
7635
|
}
|
|
7628
7636
|
return true;
|
|
7629
7637
|
},
|
|
7630
|
-
[
|
|
7638
|
+
[format, includeSeconds, resolvedMaxTime, resolvedMinTime, toSeconds]
|
|
7639
|
+
);
|
|
7640
|
+
const canEmit = React25.useCallback(
|
|
7641
|
+
(next) => {
|
|
7642
|
+
const timeStr = next ? formatTime(next, format, includeSeconds) : void 0;
|
|
7643
|
+
if (!timeStr) return true;
|
|
7644
|
+
if (!isTimeInRange(timeStr)) return false;
|
|
7645
|
+
if (isTimeDisabled(timeStr)) return false;
|
|
7646
|
+
return true;
|
|
7647
|
+
},
|
|
7648
|
+
[format, includeSeconds, isTimeDisabled, isTimeInRange]
|
|
7649
|
+
);
|
|
7650
|
+
const emit = React25.useCallback(
|
|
7651
|
+
(next) => {
|
|
7652
|
+
const timeStr = next ? formatTime(next, format, includeSeconds) : void 0;
|
|
7653
|
+
if (!canEmit(next)) return;
|
|
7654
|
+
onChange?.(timeStr);
|
|
7655
|
+
},
|
|
7656
|
+
[canEmit, format, includeSeconds, onChange]
|
|
7657
|
+
);
|
|
7658
|
+
const tryUpdate = React25.useCallback(
|
|
7659
|
+
(next) => {
|
|
7660
|
+
if (!canEmit(next)) return false;
|
|
7661
|
+
setParts(next);
|
|
7662
|
+
emit(next);
|
|
7663
|
+
return true;
|
|
7664
|
+
},
|
|
7665
|
+
[canEmit, emit]
|
|
7631
7666
|
);
|
|
7632
|
-
const emit = (next) => {
|
|
7633
|
-
const timeStr = next ? formatTime(next, format, includeSeconds) : void 0;
|
|
7634
|
-
if (timeStr && !isTimeInRange(timeStr)) return;
|
|
7635
|
-
if (timeStr && isTimeDisabled(timeStr)) return;
|
|
7636
|
-
onChange?.(timeStr);
|
|
7637
|
-
};
|
|
7638
7667
|
const handleOpenChange = (newOpen) => {
|
|
7639
7668
|
setOpen(newOpen);
|
|
7640
7669
|
if (newOpen) {
|
|
@@ -7685,8 +7714,7 @@ function TimePicker({
|
|
|
7685
7714
|
if (e.key === "ArrowLeft") setFocusedColumn(includeSeconds ? "second" : "minute");
|
|
7686
7715
|
break;
|
|
7687
7716
|
}
|
|
7688
|
-
|
|
7689
|
-
emit(newParts);
|
|
7717
|
+
tryUpdate(newParts);
|
|
7690
7718
|
};
|
|
7691
7719
|
const setNow = () => {
|
|
7692
7720
|
const now2 = /* @__PURE__ */ new Date();
|
|
@@ -7699,8 +7727,7 @@ function TimePicker({
|
|
|
7699
7727
|
} else {
|
|
7700
7728
|
next = { h, m, s };
|
|
7701
7729
|
}
|
|
7702
|
-
|
|
7703
|
-
emit(next);
|
|
7730
|
+
tryUpdate(next);
|
|
7704
7731
|
};
|
|
7705
7732
|
const setPreset = (preset) => {
|
|
7706
7733
|
const { h, m, s } = PRESETS[preset];
|
|
@@ -7710,8 +7737,7 @@ function TimePicker({
|
|
|
7710
7737
|
} else {
|
|
7711
7738
|
next = { h, m, s };
|
|
7712
7739
|
}
|
|
7713
|
-
|
|
7714
|
-
emit(next);
|
|
7740
|
+
tryUpdate(next);
|
|
7715
7741
|
};
|
|
7716
7742
|
const handleManualInput = (input) => {
|
|
7717
7743
|
setManualInput(input);
|
|
@@ -7719,16 +7745,14 @@ function TimePicker({
|
|
|
7719
7745
|
if (parsed) {
|
|
7720
7746
|
const timeStr = formatTime(parsed, format, includeSeconds);
|
|
7721
7747
|
if (isTimeInRange(timeStr) && !isTimeDisabled(timeStr)) {
|
|
7722
|
-
|
|
7723
|
-
emit(parsed);
|
|
7748
|
+
tryUpdate(parsed);
|
|
7724
7749
|
}
|
|
7725
7750
|
}
|
|
7726
7751
|
};
|
|
7727
7752
|
const handleCustomPreset = (time) => {
|
|
7728
7753
|
const parsed = parseTime(time, format, includeSeconds);
|
|
7729
7754
|
if (parsed) {
|
|
7730
|
-
|
|
7731
|
-
emit(parsed);
|
|
7755
|
+
tryUpdate(parsed);
|
|
7732
7756
|
}
|
|
7733
7757
|
};
|
|
7734
7758
|
const hours = format === "24" ? Array.from({ length: 24 }, (_, i) => i) : Array.from({ length: 12 }, (_, i) => i + 1);
|
|
@@ -7849,8 +7873,7 @@ function TimePicker({
|
|
|
7849
7873
|
return period === "PM" ? base + 12 : base;
|
|
7850
7874
|
})();
|
|
7851
7875
|
const next = { ...parts, h: nextH, p: format === "12" ? period : parts.p };
|
|
7852
|
-
|
|
7853
|
-
emit(next);
|
|
7876
|
+
tryUpdate(next);
|
|
7854
7877
|
};
|
|
7855
7878
|
const timePickerContent = /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: panelSz.stackGap, children: [
|
|
7856
7879
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex items-center justify-center py-1", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: cn(panelSz.timeText, "font-bold tabular-nums tracking-wide text-foreground underline underline-offset-8 decoration-primary/60"), children: display }) }),
|
|
@@ -7956,8 +7979,7 @@ function TimePicker({
|
|
|
7956
7979
|
valueIndex: minuteIndex,
|
|
7957
7980
|
onSelect: (m) => {
|
|
7958
7981
|
const next = { ...parts, m };
|
|
7959
|
-
|
|
7960
|
-
emit(next);
|
|
7982
|
+
tryUpdate(next);
|
|
7961
7983
|
},
|
|
7962
7984
|
scrollRef: minuteScrollRef,
|
|
7963
7985
|
itemHeight,
|
|
@@ -7985,8 +8007,7 @@ function TimePicker({
|
|
|
7985
8007
|
valueIndex: secondIndex,
|
|
7986
8008
|
onSelect: (s) => {
|
|
7987
8009
|
const next = { ...parts, s };
|
|
7988
|
-
|
|
7989
|
-
emit(next);
|
|
8010
|
+
tryUpdate(next);
|
|
7990
8011
|
},
|
|
7991
8012
|
scrollRef: secondScrollRef,
|
|
7992
8013
|
itemHeight,
|
|
@@ -8039,8 +8060,7 @@ function TimePicker({
|
|
|
8039
8060
|
if (pVal === "AM" && hour >= 12) hour -= 12;
|
|
8040
8061
|
if (pVal === "PM" && hour < 12) hour += 12;
|
|
8041
8062
|
const next = { ...parts, p: pVal, h: hour };
|
|
8042
|
-
|
|
8043
|
-
emit(next);
|
|
8063
|
+
tryUpdate(next);
|
|
8044
8064
|
},
|
|
8045
8065
|
children: [
|
|
8046
8066
|
isSelected && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "absolute inset-0 bg-linear-to-tr from-white/20 to-transparent" }),
|
|
@@ -8877,7 +8897,7 @@ function CalendarTimelineHeader(props) {
|
|
|
8877
8897
|
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "sticky top-0 z-30 bg-linear-to-b from-background via-background to-background/95 border-b border-border/40 backdrop-blur-xl", children: [
|
|
8878
8898
|
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: cn("flex items-center justify-between gap-4", sizeConfig.headerPaddingClass), children: [
|
|
8879
8899
|
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center gap-1.5 min-w-0", children: [
|
|
8880
|
-
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center bg-muted/40 rounded-
|
|
8900
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center bg-muted/40 rounded-full p-1 gap-0.5", children: [
|
|
8881
8901
|
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
8882
8902
|
Button_default,
|
|
8883
8903
|
{
|
|
@@ -8885,7 +8905,7 @@ function CalendarTimelineHeader(props) {
|
|
|
8885
8905
|
size: "icon",
|
|
8886
8906
|
onClick: () => navigate(-1),
|
|
8887
8907
|
"aria-label": labels.prev,
|
|
8888
|
-
className: cn(sizeConfig.controlButtonIconClass, "rounded-
|
|
8908
|
+
className: cn(sizeConfig.controlButtonIconClass, "rounded-full hover:bg-background/80 transition-all duration-200"),
|
|
8889
8909
|
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.ChevronLeft, { className: "h-4 w-4" })
|
|
8890
8910
|
}
|
|
8891
8911
|
),
|
|
@@ -8895,7 +8915,7 @@ function CalendarTimelineHeader(props) {
|
|
|
8895
8915
|
variant: "ghost",
|
|
8896
8916
|
size: "sm",
|
|
8897
8917
|
onClick: goToday,
|
|
8898
|
-
className: cn(sizeConfig.controlButtonTextClass, "rounded-
|
|
8918
|
+
className: cn(sizeConfig.controlButtonTextClass, "rounded-full hover:bg-background/80 font-medium transition-all duration-200"),
|
|
8899
8919
|
children: labels.today
|
|
8900
8920
|
}
|
|
8901
8921
|
),
|
|
@@ -8906,7 +8926,7 @@ function CalendarTimelineHeader(props) {
|
|
|
8906
8926
|
size: "icon",
|
|
8907
8927
|
onClick: () => navigate(1),
|
|
8908
8928
|
"aria-label": labels.next,
|
|
8909
|
-
className: cn(sizeConfig.controlButtonIconClass, "rounded-
|
|
8929
|
+
className: cn(sizeConfig.controlButtonIconClass, "rounded-full hover:bg-background/80 transition-all duration-200"),
|
|
8910
8930
|
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.ChevronRight, { className: "h-4 w-4" })
|
|
8911
8931
|
}
|
|
8912
8932
|
)
|
|
@@ -8922,11 +8942,11 @@ function CalendarTimelineHeader(props) {
|
|
|
8922
8942
|
icon: import_lucide_react18.Plus,
|
|
8923
8943
|
disabled: newEventDisabled,
|
|
8924
8944
|
onClick: onNewEventClick,
|
|
8925
|
-
className: cn(sizeConfig.controlButtonTextClass, "rounded-
|
|
8945
|
+
className: cn(sizeConfig.controlButtonTextClass, "rounded-full font-medium transition-all duration-200 gap-1.5"),
|
|
8926
8946
|
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "hidden sm:inline", children: newEventLabel })
|
|
8927
8947
|
}
|
|
8928
8948
|
) : null,
|
|
8929
|
-
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex items-center bg-muted/40 rounded-
|
|
8949
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex items-center bg-muted/40 rounded-full p-1 gap-0.5", children: ["month", "week", "day"].map((v) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
8930
8950
|
Button_default,
|
|
8931
8951
|
{
|
|
8932
8952
|
variant: activeView === v ? "default" : "ghost",
|
|
@@ -8934,7 +8954,7 @@ function CalendarTimelineHeader(props) {
|
|
|
8934
8954
|
onClick: () => setView(v),
|
|
8935
8955
|
className: cn(
|
|
8936
8956
|
sizeConfig.controlButtonTextClass,
|
|
8937
|
-
"rounded-
|
|
8957
|
+
"rounded-full font-medium transition-all duration-200 gap-1.5",
|
|
8938
8958
|
activeView === v ? "bg-primary text-primary-foreground shadow-sm shadow-primary/25" : "hover:bg-background/80 text-muted-foreground hover:text-foreground"
|
|
8939
8959
|
),
|
|
8940
8960
|
children: [
|
|
@@ -10369,7 +10389,7 @@ function CalendarTimeline({
|
|
|
10369
10389
|
"div",
|
|
10370
10390
|
{
|
|
10371
10391
|
className: cn(
|
|
10372
|
-
"border border-border/40 rounded-2xl overflow-hidden bg-background/95 backdrop-blur-sm",
|
|
10392
|
+
"border border-border/40 rounded-2xl md:rounded-3xl overflow-hidden bg-background/95 backdrop-blur-sm",
|
|
10373
10393
|
"shadow-sm hover:shadow-md transition-shadow duration-300",
|
|
10374
10394
|
densityClass,
|
|
10375
10395
|
className
|
|
@@ -10511,16 +10531,19 @@ function CalendarTimeline({
|
|
|
10511
10531
|
const resource = resourceById.get(ev.resourceId);
|
|
10512
10532
|
const tooltipTitle = ev.title || ev.id;
|
|
10513
10533
|
const shouldCompact = activeView === "day" && dayEventStyle === "compact";
|
|
10534
|
+
const eventInsetX = 2;
|
|
10535
|
+
const leftInset = left + eventInsetX;
|
|
10536
|
+
const widthInset = Math.max(1, width - eventInsetX * 2);
|
|
10514
10537
|
const defaultMaxVisual = clamp4(Math.round(fixedSlotWidth * 1.2), 160, 360);
|
|
10515
10538
|
const maxVisual = clamp4(Math.round(dayEventMaxWidth ?? defaultMaxVisual), 80, 1200);
|
|
10516
|
-
const visualWidth = shouldCompact ? Math.min(
|
|
10517
|
-
const isClipped = shouldCompact &&
|
|
10539
|
+
const visualWidth = shouldCompact ? Math.min(widthInset, maxVisual) : widthInset;
|
|
10540
|
+
const isClipped = shouldCompact && widthInset > visualWidth + 1;
|
|
10518
10541
|
const block = /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
10519
10542
|
"div",
|
|
10520
10543
|
{
|
|
10521
10544
|
className: cn("absolute select-none cursor-pointer", isPreview && "z-10"),
|
|
10522
10545
|
"data-uv-ct-event": true,
|
|
10523
|
-
style: { left, top, width, height: layout.eventHeight },
|
|
10546
|
+
style: { left: leftInset, top, width: widthInset, height: layout.eventHeight },
|
|
10524
10547
|
role: "button",
|
|
10525
10548
|
tabIndex: 0,
|
|
10526
10549
|
"aria-label": aria,
|
|
@@ -10605,11 +10628,17 @@ function CalendarTimeline({
|
|
|
10605
10628
|
const endIdx = clamp4(binarySearchFirstGE(slotStarts, preview.end), startIdx + 1, slots.length);
|
|
10606
10629
|
const left = slotLefts[startIdx] ?? 0;
|
|
10607
10630
|
const width = Math.max(1, (slotLefts[endIdx] ?? 0) - (slotLefts[startIdx] ?? 0));
|
|
10631
|
+
const eventInsetX = 2;
|
|
10608
10632
|
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
10609
10633
|
"div",
|
|
10610
10634
|
{
|
|
10611
10635
|
className: "absolute rounded-lg border-2 border-dashed border-primary/60 bg-primary/10 backdrop-blur-sm animate-pulse",
|
|
10612
|
-
style: {
|
|
10636
|
+
style: {
|
|
10637
|
+
left: left + eventInsetX,
|
|
10638
|
+
top: layout.baseTop,
|
|
10639
|
+
width: Math.max(1, width - eventInsetX * 2),
|
|
10640
|
+
height: layout.eventHeight
|
|
10641
|
+
}
|
|
10613
10642
|
}
|
|
10614
10643
|
);
|
|
10615
10644
|
})() : null,
|