@underverse-ui/underverse 0.2.96 → 0.2.98

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 CHANGED
@@ -8308,9 +8308,10 @@ function useClientWidth(ref) {
8308
8308
  var SIZE_CONFIG_BY_SIZE = {
8309
8309
  sm: {
8310
8310
  resourceColumnWidth: 200,
8311
- rowHeight: 44,
8311
+ rowHeight: 84,
8312
+ groupRowHeight: 36,
8312
8313
  slotMinWidth: 52,
8313
- eventHeight: 20,
8314
+ eventHeight: 46,
8314
8315
  laneGap: 3,
8315
8316
  lanePaddingY: 5,
8316
8317
  densityClass: "text-xs",
@@ -8324,9 +8325,10 @@ var SIZE_CONFIG_BY_SIZE = {
8324
8325
  },
8325
8326
  md: {
8326
8327
  resourceColumnWidth: 240,
8327
- rowHeight: 52,
8328
+ rowHeight: 96,
8329
+ groupRowHeight: 40,
8328
8330
  slotMinWidth: 64,
8329
- eventHeight: 24,
8331
+ eventHeight: 54,
8330
8332
  laneGap: 4,
8331
8333
  lanePaddingY: 6,
8332
8334
  densityClass: "text-sm",
@@ -8340,9 +8342,10 @@ var SIZE_CONFIG_BY_SIZE = {
8340
8342
  },
8341
8343
  xl: {
8342
8344
  resourceColumnWidth: 280,
8343
- rowHeight: 60,
8345
+ rowHeight: 112,
8346
+ groupRowHeight: 44,
8344
8347
  slotMinWidth: 76,
8345
- eventHeight: 28,
8348
+ eventHeight: 62,
8346
8349
  laneGap: 5,
8347
8350
  lanePaddingY: 8,
8348
8351
  densityClass: "text-base",
@@ -8546,18 +8549,18 @@ function CalendarTimelineHeader(props) {
8546
8549
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("h2", { className: cn("ml-3 font-semibold tracking-tight truncate text-foreground", sizeConfig.titleClass), children: title })
8547
8550
  ] }),
8548
8551
  /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center gap-2", children: [
8549
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
8552
+ onNewEventClick ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
8550
8553
  Button_default,
8551
8554
  {
8552
8555
  variant: "default",
8553
8556
  size: "sm",
8554
8557
  icon: import_lucide_react18.Plus,
8555
- disabled: newEventDisabled || !onNewEventClick,
8558
+ disabled: newEventDisabled,
8556
8559
  onClick: onNewEventClick,
8557
8560
  className: cn(sizeConfig.controlButtonTextClass, "rounded-lg font-medium transition-all duration-200 gap-1.5"),
8558
8561
  children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "hidden sm:inline", children: newEventLabel })
8559
8562
  }
8560
- ),
8563
+ ) : null,
8561
8564
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex items-center bg-muted/40 rounded-xl p-1 gap-0.5", children: ["month", "week", "day"].map((v) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
8562
8565
  Button_default,
8563
8566
  {
@@ -8760,6 +8763,7 @@ function CalendarTimeline({
8760
8763
  const resolvedLocale = React28.useMemo(() => localeToBCP47(locale ?? detectedLocale), [locale, detectedLocale]);
8761
8764
  const resolvedTimeZone = React28.useMemo(() => timeZone ?? Intl.DateTimeFormat().resolvedOptions().timeZone ?? "UTC", [timeZone]);
8762
8765
  const effectiveEnableEventSheet = enableEventSheet ?? Boolean(renderEventSheet);
8766
+ const isViewOnly = interactions?.mode === "view";
8763
8767
  const isControlledSelectedEventId = selectedEventId !== void 0;
8764
8768
  const [internalSelectedEventId, setInternalSelectedEventId] = React28.useState(defaultSelectedEventId ?? null);
8765
8769
  const activeSelectedEventId = isControlledSelectedEventId ? selectedEventId : internalSelectedEventId;
@@ -8785,15 +8789,17 @@ function CalendarTimeline({
8785
8789
  const canResizeColumn = React28.useMemo(() => {
8786
8790
  const cfg = enableLayoutResize;
8787
8791
  if (!cfg) return false;
8792
+ if (isViewOnly) return false;
8788
8793
  if (cfg === true) return true;
8789
8794
  return cfg.column !== false;
8790
- }, [enableLayoutResize]);
8795
+ }, [enableLayoutResize, isViewOnly]);
8791
8796
  const canResizeRow = React28.useMemo(() => {
8792
8797
  const cfg = enableLayoutResize;
8793
8798
  if (!cfg) return false;
8799
+ if (isViewOnly) return false;
8794
8800
  if (cfg === true) return true;
8795
8801
  return cfg.row !== false;
8796
- }, [enableLayoutResize]);
8802
+ }, [enableLayoutResize, isViewOnly]);
8797
8803
  const isControlledResourceColumnWidth = resourceColumnWidth !== void 0;
8798
8804
  const [internalResourceColumnWidth, setInternalResourceColumnWidth] = React28.useState(() => {
8799
8805
  const init = defaultResourceColumnWidth ?? sizeConfig.resourceColumnWidth;
@@ -8913,10 +8919,11 @@ function CalendarTimeline({
8913
8919
  const bodyClientWidth = useClientWidth(bodyRef);
8914
8920
  const slotStarts = React28.useMemo(() => slots.map((s) => s.start), [slots]);
8915
8921
  const slotWidth = React28.useMemo(() => {
8916
- if (activeView !== "week") return effectiveSlotMinWidth;
8917
- if (bodyClientWidth <= 0) return effectiveSlotMinWidth;
8918
- if (slots.length <= 0) return effectiveSlotMinWidth;
8919
- return Math.max(effectiveSlotMinWidth, bodyClientWidth / slots.length);
8922
+ const baseSlotWidth = activeView === "month" ? effectiveSlotMinWidth * 3 : effectiveSlotMinWidth;
8923
+ if (activeView !== "week") return baseSlotWidth;
8924
+ if (bodyClientWidth <= 0) return baseSlotWidth;
8925
+ if (slots.length <= 0) return baseSlotWidth;
8926
+ return Math.max(baseSlotWidth, bodyClientWidth / slots.length);
8920
8927
  }, [activeView, bodyClientWidth, effectiveSlotMinWidth, slots.length]);
8921
8928
  const gridWidth = slots.length * slotWidth;
8922
8929
  const normalizedEvents = React28.useMemo(() => {
@@ -8992,9 +8999,9 @@ function CalendarTimeline({
8992
8999
  const rowHeightsArray = React28.useMemo(() => {
8993
9000
  return rows.map((r) => {
8994
9001
  if (r.kind === "resource") return getResourceRowHeight(r.resource.id);
8995
- return effectiveRowHeight;
9002
+ return sizeConfig.groupRowHeight;
8996
9003
  });
8997
- }, [effectiveRowHeight, getResourceRowHeight, rows]);
9004
+ }, [getResourceRowHeight, rows, sizeConfig.groupRowHeight]);
8998
9005
  const virtualResult = useVirtualVariableRows({
8999
9006
  enabled: virt,
9000
9007
  overscan,
@@ -9108,7 +9115,7 @@ function CalendarTimeline({
9108
9115
  const laneGap = sizeConfig.laneGap;
9109
9116
  const lanePaddingY = sizeConfig.lanePaddingY;
9110
9117
  const createMode = interactions?.createMode ?? "drag";
9111
- const canCreate = (interactions?.creatable ?? false) && !!onCreateEvent;
9118
+ const canCreate = !isViewOnly && (interactions?.creatable ?? false) && !!onCreateEvent;
9112
9119
  const [createOpen, setCreateOpen] = React28.useState(false);
9113
9120
  const [createResourceId, setCreateResourceId] = React28.useState(null);
9114
9121
  const [createStartIdx, setCreateStartIdx] = React28.useState(0);
@@ -9202,6 +9209,7 @@ function CalendarTimeline({
9202
9209
  );
9203
9210
  const onPointerDownEvent = (e, ev, mode) => {
9204
9211
  if (e.button !== 0 || e.ctrlKey) return;
9212
+ if (isViewOnly) return;
9205
9213
  if (ev.resourceId == null) return;
9206
9214
  const allowDrag = interactions?.draggableEvents ?? true;
9207
9215
  const allowResize = interactions?.resizableEvents ?? true;
@@ -9229,6 +9237,7 @@ function CalendarTimeline({
9229
9237
  };
9230
9238
  const onPointerDownCell = (e) => {
9231
9239
  if (e.button !== 0 || e.ctrlKey) return;
9240
+ if (isViewOnly) return;
9232
9241
  if (!(interactions?.creatable ?? false) || !onCreateEvent) return;
9233
9242
  if (createMode === "click") return;
9234
9243
  const ctx = getPointerContext(e.clientX, e.clientY, { biasLeft: true });
@@ -9253,6 +9262,7 @@ function CalendarTimeline({
9253
9262
  };
9254
9263
  const onClickCell = (e) => {
9255
9264
  if (e.button !== 0 || e.ctrlKey) return;
9265
+ if (isViewOnly) return;
9256
9266
  if (!(interactions?.creatable ?? false)) return;
9257
9267
  if (createMode !== "click") return;
9258
9268
  if (!onCreateEventClick) return;
@@ -9384,8 +9394,8 @@ function CalendarTimeline({
9384
9394
  resourcesHeaderLabel: t("resourcesHeader"),
9385
9395
  labels: { today: l.today, prev: l.prev, next: l.next, month: l.month, week: l.week, day: l.day },
9386
9396
  newEventLabel: l.newEvent,
9387
- newEventDisabled: !canCreate || resources.length === 0,
9388
- onNewEventClick: openCreate,
9397
+ newEventDisabled: isViewOnly || !canCreate || resources.length === 0,
9398
+ onNewEventClick: isViewOnly ? void 0 : openCreate,
9389
9399
  activeView,
9390
9400
  sizeConfig,
9391
9401
  navigate,
@@ -9526,10 +9536,26 @@ function CalendarTimeline({
9526
9536
  timeZone: resolvedTimeZone,
9527
9537
  view: activeView
9528
9538
  }) ?? defaultEventTime({ start: ev._start, end: ev._end, locale: resolvedLocale, timeZone: resolvedTimeZone, view: activeView });
9529
- const node = renderEvent?.(ev, { left, width, lane }) ?? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "h-full px-2.5 truncate flex items-center gap-1.5", children: [
9530
- ev.title ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "font-semibold text-xs truncate leading-none", children: ev.title }) : null,
9531
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-[11px] opacity-70 truncate ml-auto leading-none", children: timeText })
9532
- ] });
9539
+ const node = renderEvent?.(ev, { left, width, lane, height: layout.eventHeight, timeText }) ?? (() => {
9540
+ const showTime = layout.eventHeight >= 24;
9541
+ const titleMaxLines = showTime ? layout.eventHeight >= 34 ? 2 : 1 : 1;
9542
+ const isPlainTitle = typeof ev.title === "string" || typeof ev.title === "number";
9543
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "h-full px-2.5 flex items-center min-w-0 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "w-full grid grid-cols-[1fr_auto] gap-x-2 items-start min-w-0 overflow-hidden", children: [
9544
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9545
+ "div",
9546
+ {
9547
+ className: cn("text-xs font-semibold leading-snug min-w-0 overflow-hidden", isPlainTitle ? "break-words" : ""),
9548
+ style: isPlainTitle ? {
9549
+ display: "-webkit-box",
9550
+ WebkitBoxOrient: "vertical",
9551
+ WebkitLineClamp: titleMaxLines
9552
+ } : void 0,
9553
+ children: ev.title ?? null
9554
+ }
9555
+ ),
9556
+ showTime ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "text-[11px] opacity-70 leading-snug whitespace-nowrap", children: timeText }) : null
9557
+ ] }) });
9558
+ })();
9533
9559
  const resource = resourceById.get(ev.resourceId);
9534
9560
  const tooltipTitle = ev.title || ev.id;
9535
9561
  const tooltipContent = /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
@@ -9545,6 +9571,7 @@ function CalendarTimeline({
9545
9571
  "shadow-sm hover:shadow-md hover:scale-[1.02] hover:z-10",
9546
9572
  "transition-all duration-150 ease-out",
9547
9573
  "backdrop-blur-sm",
9574
+ "overflow-hidden",
9548
9575
  ev.className,
9549
9576
  isPreview && "ring-2 ring-primary/50 ring-offset-1 ring-offset-background scale-[1.02] z-10"
9550
9577
  ),
@@ -9561,6 +9588,7 @@ function CalendarTimeline({
9561
9588
  tabIndex: 0,
9562
9589
  "aria-label": aria,
9563
9590
  onContextMenu: (e) => {
9591
+ if (isViewOnly) return;
9564
9592
  if (!onEventDelete) return;
9565
9593
  if (interactions?.deletableEvents === false) return;
9566
9594
  e.preventDefault();
@@ -9583,7 +9611,7 @@ function CalendarTimeline({
9583
9611
  onDoubleClick: () => onEventDoubleClick?.(ev),
9584
9612
  onPointerDown: (e) => onPointerDownEvent(e, ev, "move"),
9585
9613
  children: [
9586
- (interactions?.resizableEvents ?? true) && ev.resizable !== false ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
9614
+ !isViewOnly && (interactions?.resizableEvents ?? true) && ev.resizable !== false ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
9587
9615
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9588
9616
  "div",
9589
9617
  {