@underverse-ui/underverse 0.2.102 → 0.2.103
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 +104 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +104 -34
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -8763,6 +8763,8 @@ function CalendarTimeline({
|
|
|
8763
8763
|
enableLayoutResize,
|
|
8764
8764
|
slotMinWidth,
|
|
8765
8765
|
adaptiveSlotWidths,
|
|
8766
|
+
dayEventStyle = "span",
|
|
8767
|
+
dayEventMaxWidth,
|
|
8766
8768
|
dayTimeStepMinutes = 60,
|
|
8767
8769
|
dayRangeMode,
|
|
8768
8770
|
workHours,
|
|
@@ -8961,6 +8963,26 @@ function CalendarTimeline({
|
|
|
8961
8963
|
const normalizedEvents = React28.useMemo(() => {
|
|
8962
8964
|
return normalizeEvents({ events, range, view: activeView, timeZone: resolvedTimeZone });
|
|
8963
8965
|
}, [events, range, activeView, resolvedTimeZone]);
|
|
8966
|
+
const dayHeaderMarks = React28.useMemo(() => {
|
|
8967
|
+
if (activeView !== "day") return null;
|
|
8968
|
+
const n = slots.length;
|
|
8969
|
+
const showTime = new Array(n).fill(false);
|
|
8970
|
+
const showEllipsis = new Array(n).fill(false);
|
|
8971
|
+
for (const ev of normalizedEvents) {
|
|
8972
|
+
const startIdx = binarySearchLastLE(slotStarts, ev._start);
|
|
8973
|
+
const endIdxRaw = binarySearchFirstGE(slotStarts, ev._end);
|
|
8974
|
+
const endIdx = clamp3(endIdxRaw, 0, n - 1);
|
|
8975
|
+
if (startIdx >= 0 && startIdx < n) showTime[startIdx] = true;
|
|
8976
|
+
if (endIdx >= 0 && endIdx < n) showTime[endIdx] = true;
|
|
8977
|
+
const span = endIdx - startIdx;
|
|
8978
|
+
if (span >= 3) {
|
|
8979
|
+
const mid = clamp3(Math.floor((startIdx + endIdx) / 2), 0, n - 1);
|
|
8980
|
+
if (!showTime[mid]) showEllipsis[mid] = true;
|
|
8981
|
+
}
|
|
8982
|
+
}
|
|
8983
|
+
const anchor = showTime.map((v, i) => v || showEllipsis[i]);
|
|
8984
|
+
return { showTime, showEllipsis, anchor };
|
|
8985
|
+
}, [activeView, normalizedEvents, slotStarts, slots.length]);
|
|
8964
8986
|
const slotMetrics = React28.useMemo(() => {
|
|
8965
8987
|
const n = slots.length;
|
|
8966
8988
|
const widths = new Array(n).fill(fixedSlotWidth);
|
|
@@ -8973,12 +8995,38 @@ function CalendarTimeline({
|
|
|
8973
8995
|
for (let i = 0; i < n; i++) lefts2[i + 1] = lefts2[i] + widths[i];
|
|
8974
8996
|
const gridWidth3 = lefts2[n] ?? 0;
|
|
8975
8997
|
const xToSlotIdx3 = (x) => clamp3(Math.floor(x / Math.max(1, fixedSlotWidth)), 0, Math.max(0, n - 1));
|
|
8976
|
-
return { slotWidths: widths, slotLefts: lefts2, gridWidth: gridWidth3, xToSlotIdx: xToSlotIdx3 };
|
|
8998
|
+
return { slotWidths: widths, slotLefts: lefts2, slotHasEvent: null, gridWidth: gridWidth3, xToSlotIdx: xToSlotIdx3 };
|
|
8977
8999
|
}
|
|
8978
9000
|
const cfg = typeof adaptiveCfg === "object" ? adaptiveCfg : {};
|
|
8979
9001
|
const mode = cfg.mode ?? "shrink";
|
|
8980
9002
|
const defaultEmptySlotWidth = Math.max(18, Math.round(effectiveSlotMinWidth * 0.6));
|
|
8981
|
-
const
|
|
9003
|
+
const minEmptySlotWidth = activeView === "month" ? Math.max(24, Math.round(effectiveSlotMinWidth * 0.45)) : 12;
|
|
9004
|
+
const emptySlotWidth = Math.max(minEmptySlotWidth, Math.min(fixedSlotWidth, cfg.emptySlotWidth ?? defaultEmptySlotWidth));
|
|
9005
|
+
const dayAnchorCompression = activeView === "day" && Boolean(dayHeaderMarks?.anchor);
|
|
9006
|
+
if (dayAnchorCompression) {
|
|
9007
|
+
const hasEvent2 = dayHeaderMarks.anchor.slice(0, n);
|
|
9008
|
+
const compressedEmptySlotWidth = clamp3(emptySlotWidth, 12, 20);
|
|
9009
|
+
for (let i = 0; i < n; i++) widths[i] = hasEvent2[i] ? fixedSlotWidth : compressedEmptySlotWidth;
|
|
9010
|
+
const lefts2 = new Array(n + 1);
|
|
9011
|
+
lefts2[0] = 0;
|
|
9012
|
+
for (let i = 0; i < n; i++) lefts2[i + 1] = lefts2[i] + widths[i];
|
|
9013
|
+
const gridWidth3 = lefts2[n] ?? 0;
|
|
9014
|
+
const xToSlotIdx3 = (x) => {
|
|
9015
|
+
const xc = clamp3(x, 0, Math.max(0, gridWidth3 - 1e-3));
|
|
9016
|
+
let lo = 0;
|
|
9017
|
+
let hi = n - 1;
|
|
9018
|
+
while (lo <= hi) {
|
|
9019
|
+
const mid = lo + hi >> 1;
|
|
9020
|
+
const left = lefts2[mid] ?? 0;
|
|
9021
|
+
const right = lefts2[mid + 1] ?? gridWidth3;
|
|
9022
|
+
if (xc < left) hi = mid - 1;
|
|
9023
|
+
else if (xc >= right) lo = mid + 1;
|
|
9024
|
+
else return mid;
|
|
9025
|
+
}
|
|
9026
|
+
return clamp3(lo, 0, Math.max(0, n - 1));
|
|
9027
|
+
};
|
|
9028
|
+
return { slotWidths: widths, slotLefts: lefts2, slotHasEvent: hasEvent2, gridWidth: gridWidth3, xToSlotIdx: xToSlotIdx3 };
|
|
9029
|
+
}
|
|
8982
9030
|
const diff = new Array(n + 1).fill(0);
|
|
8983
9031
|
for (const ev of normalizedEvents) {
|
|
8984
9032
|
const startIdx = binarySearchLastLE(slotStarts, ev._start);
|
|
@@ -9001,7 +9049,7 @@ function CalendarTimeline({
|
|
|
9001
9049
|
for (let i = 0; i < n; i++) lefts2[i + 1] = lefts2[i] + widths[i];
|
|
9002
9050
|
const gridWidth3 = lefts2[n] ?? 0;
|
|
9003
9051
|
const xToSlotIdx3 = (x) => clamp3(Math.floor(x / Math.max(1, fixedSlotWidth)), 0, Math.max(0, n - 1));
|
|
9004
|
-
return { slotWidths: widths, slotLefts: lefts2, gridWidth: gridWidth3, xToSlotIdx: xToSlotIdx3 };
|
|
9052
|
+
return { slotWidths: widths, slotLefts: lefts2, slotHasEvent: null, gridWidth: gridWidth3, xToSlotIdx: xToSlotIdx3 };
|
|
9005
9053
|
}
|
|
9006
9054
|
const emptyCount = n - eventCount;
|
|
9007
9055
|
let eventSlotWidth = fixedSlotWidth;
|
|
@@ -9031,9 +9079,9 @@ function CalendarTimeline({
|
|
|
9031
9079
|
}
|
|
9032
9080
|
return clamp3(lo, 0, Math.max(0, n - 1));
|
|
9033
9081
|
};
|
|
9034
|
-
return { slotWidths: widths, slotLefts: lefts, gridWidth: gridWidth2, xToSlotIdx: xToSlotIdx2 };
|
|
9035
|
-
}, [activeView, adaptiveSlotWidths, effectiveSlotMinWidth, fixedSlotWidth, normalizedEvents, slotStarts, slots.length]);
|
|
9036
|
-
const { slotWidths, slotLefts, gridWidth, xToSlotIdx } = slotMetrics;
|
|
9082
|
+
return { slotWidths: widths, slotLefts: lefts, slotHasEvent: hasEvent, gridWidth: gridWidth2, xToSlotIdx: xToSlotIdx2 };
|
|
9083
|
+
}, [activeView, adaptiveSlotWidths, dayHeaderMarks, effectiveSlotMinWidth, fixedSlotWidth, normalizedEvents, slotStarts, slots.length]);
|
|
9084
|
+
const { slotWidths, slotLefts, slotHasEvent, gridWidth, xToSlotIdx } = slotMetrics;
|
|
9037
9085
|
const eventsByResource = React28.useMemo(() => {
|
|
9038
9086
|
return eventsByResourceId(normalizedEvents);
|
|
9039
9087
|
}, [normalizedEvents]);
|
|
@@ -9625,16 +9673,24 @@ function CalendarTimeline({
|
|
|
9625
9673
|
"div",
|
|
9626
9674
|
{
|
|
9627
9675
|
className: cn(
|
|
9628
|
-
"shrink-0 border-l
|
|
9676
|
+
"shrink-0 border-l flex items-center justify-center transition-colors duration-150 overflow-hidden",
|
|
9677
|
+
activeView === "day" && dayHeaderMarks?.anchor ? dayHeaderMarks.anchor[idx] ? "border-border/30" : "border-border/10" : "border-border/30",
|
|
9629
9678
|
sizeConfig.slotHeaderClass,
|
|
9630
|
-
s.isToday && "bg-primary/8 border-l-primary/40"
|
|
9679
|
+
activeView !== "day" && s.isToday && "bg-primary/8 border-l-primary/40"
|
|
9631
9680
|
),
|
|
9632
9681
|
style: { width: slotWidths[idx], minWidth: slotWidths[idx] },
|
|
9633
9682
|
"aria-label": formatters?.ariaSlotLabel?.(s.start, { view: activeView, locale: resolvedLocale, timeZone: resolvedTimeZone }),
|
|
9634
|
-
children:
|
|
9635
|
-
s.
|
|
9636
|
-
|
|
9637
|
-
|
|
9683
|
+
children: (() => {
|
|
9684
|
+
const label = typeof s.label === "string" || typeof s.label === "number" ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "truncate whitespace-nowrap", children: s.label }) : s.label;
|
|
9685
|
+
if (activeView === "day" && dayHeaderMarks) {
|
|
9686
|
+
if (dayHeaderMarks.showEllipsis[idx]) return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-xs text-muted-foreground/70 select-none", children: "\u2026" });
|
|
9687
|
+
if (!dayHeaderMarks.showTime[idx]) return null;
|
|
9688
|
+
}
|
|
9689
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: cn("flex flex-col items-center min-w-0 overflow-hidden", activeView !== "day" && s.isToday && "relative"), children: [
|
|
9690
|
+
activeView !== "day" && s.isToday && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react20.Dot, { className: "absolute -top-2.5 h-4 w-4 text-primary animate-pulse" }),
|
|
9691
|
+
label
|
|
9692
|
+
] });
|
|
9693
|
+
})()
|
|
9638
9694
|
},
|
|
9639
9695
|
`${s.start.toISOString()}_${idx}`
|
|
9640
9696
|
))
|
|
@@ -9787,8 +9843,9 @@ function CalendarTimeline({
|
|
|
9787
9843
|
"div",
|
|
9788
9844
|
{
|
|
9789
9845
|
className: cn(
|
|
9790
|
-
"h-full border-l
|
|
9791
|
-
|
|
9846
|
+
"h-full border-l transition-colors duration-100",
|
|
9847
|
+
activeView === "day" && dayHeaderMarks?.anchor ? !dayHeaderMarks.anchor[i2] ? "border-border/10" : "border-border/20" : "border-border/20",
|
|
9848
|
+
activeView !== "day" && s.isToday && "bg-primary/5 border-l-primary/30",
|
|
9792
9849
|
"hover:bg-muted/10"
|
|
9793
9850
|
),
|
|
9794
9851
|
style: { width: slotWidths[i2], minWidth: slotWidths[i2] }
|
|
@@ -9835,28 +9892,17 @@ function CalendarTimeline({
|
|
|
9835
9892
|
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "text-xs opacity-80", children: timeText }),
|
|
9836
9893
|
resource?.label ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "text-xs opacity-70", children: resource.label }) : null
|
|
9837
9894
|
] });
|
|
9895
|
+
const shouldCompact = activeView === "day" && dayEventStyle === "compact";
|
|
9896
|
+
const defaultMaxVisual = clamp3(Math.round(fixedSlotWidth * 1.2), 160, 360);
|
|
9897
|
+
const maxVisual = clamp3(Math.round(dayEventMaxWidth ?? defaultMaxVisual), 80, 1200);
|
|
9898
|
+
const visualWidth = shouldCompact ? Math.min(width, maxVisual) : width;
|
|
9899
|
+
const isClipped = shouldCompact && width > visualWidth + 1;
|
|
9838
9900
|
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Tooltip, { content: tooltipContent, placement: "top", delay: { open: 250, close: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
9839
9901
|
"div",
|
|
9840
9902
|
{
|
|
9841
|
-
className: cn(
|
|
9842
|
-
"absolute rounded-lg border select-none cursor-pointer",
|
|
9843
|
-
"shadow-sm hover:shadow-md hover:scale-[1.02] hover:z-10",
|
|
9844
|
-
"transition-all duration-150 ease-out",
|
|
9845
|
-
"backdrop-blur-sm",
|
|
9846
|
-
"overflow-hidden",
|
|
9847
|
-
ev.className,
|
|
9848
|
-
isPreview && "ring-2 ring-primary/50 ring-offset-1 ring-offset-background scale-[1.02] z-10"
|
|
9849
|
-
),
|
|
9903
|
+
className: cn("absolute select-none cursor-pointer", isPreview && "z-10"),
|
|
9850
9904
|
"data-uv-ct-event": true,
|
|
9851
|
-
style: {
|
|
9852
|
-
left,
|
|
9853
|
-
top,
|
|
9854
|
-
width,
|
|
9855
|
-
height: layout.eventHeight,
|
|
9856
|
-
background: bg,
|
|
9857
|
-
borderColor: border,
|
|
9858
|
-
borderLeftWidth: 3
|
|
9859
|
-
},
|
|
9905
|
+
style: { left, top, width, height: layout.eventHeight },
|
|
9860
9906
|
role: "button",
|
|
9861
9907
|
tabIndex: 0,
|
|
9862
9908
|
"aria-label": aria,
|
|
@@ -9884,6 +9930,31 @@ function CalendarTimeline({
|
|
|
9884
9930
|
onDoubleClick: () => onEventDoubleClick?.(ev),
|
|
9885
9931
|
onPointerDown: (e) => onPointerDownEvent(e, ev, "move"),
|
|
9886
9932
|
children: [
|
|
9933
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
9934
|
+
"div",
|
|
9935
|
+
{
|
|
9936
|
+
className: cn(
|
|
9937
|
+
"relative h-full rounded-lg border overflow-hidden",
|
|
9938
|
+
"shadow-sm hover:shadow-md hover:scale-[1.02]",
|
|
9939
|
+
"transition-all duration-150 ease-out",
|
|
9940
|
+
"backdrop-blur-sm",
|
|
9941
|
+
ev.className,
|
|
9942
|
+
isPreview && "ring-2 ring-primary/50 ring-offset-1 ring-offset-background scale-[1.02]"
|
|
9943
|
+
),
|
|
9944
|
+
style: {
|
|
9945
|
+
width: visualWidth,
|
|
9946
|
+
maxWidth: "100%",
|
|
9947
|
+
height: "100%",
|
|
9948
|
+
background: bg,
|
|
9949
|
+
borderColor: border,
|
|
9950
|
+
borderLeftWidth: 3
|
|
9951
|
+
},
|
|
9952
|
+
children: [
|
|
9953
|
+
node,
|
|
9954
|
+
isClipped ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "pointer-events-none absolute inset-y-0 right-0 w-10 bg-linear-to-l from-background/50 to-transparent flex items-center justify-end pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-xs text-muted-foreground/80", children: "\u2026" }) }) : null
|
|
9955
|
+
]
|
|
9956
|
+
}
|
|
9957
|
+
),
|
|
9887
9958
|
!isViewOnly && (interactions?.resizableEvents ?? true) && ev.resizable !== false ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
9888
9959
|
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
9889
9960
|
"div",
|
|
@@ -9899,8 +9970,7 @@ function CalendarTimeline({
|
|
|
9899
9970
|
onPointerDown: (e) => onPointerDownEvent(e, ev, "resize-end")
|
|
9900
9971
|
}
|
|
9901
9972
|
)
|
|
9902
|
-
] }) : null
|
|
9903
|
-
node
|
|
9973
|
+
] }) : null
|
|
9904
9974
|
]
|
|
9905
9975
|
}
|
|
9906
9976
|
) }, ev.id);
|