@underverse-ui/underverse 0.2.84 → 0.2.85

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
@@ -7757,20 +7757,21 @@ var DateTimePicker = ({
7757
7757
  ] });
7758
7758
  };
7759
7759
 
7760
- // ../../components/ui/CalendarTimeline.tsx
7761
- var React27 = __toESM(require("react"), 1);
7760
+ // ../../components/ui/CalendarTimeline/CalendarTimeline.tsx
7761
+ var React28 = __toESM(require("react"), 1);
7762
7762
  var import_lucide_react18 = require("lucide-react");
7763
- var import_jsx_runtime33 = require("react/jsx-runtime");
7763
+
7764
+ // ../../components/ui/CalendarTimeline/date.ts
7764
7765
  function toDate2(input) {
7765
7766
  return input instanceof Date ? input : new Date(input);
7766
7767
  }
7767
- var localeToBCP47 = (l) => {
7768
- if (l === "vi") return "vi-VN";
7769
- if (l === "en") return "en-US";
7770
- if (l === "ko") return "ko-KR";
7771
- if (l === "ja") return "ja-JP";
7772
- return l;
7773
- };
7768
+ function localeToBCP47(locale) {
7769
+ if (locale === "vi") return "vi-VN";
7770
+ if (locale === "en") return "en-US";
7771
+ if (locale === "ko") return "ko-KR";
7772
+ if (locale === "ja") return "ja-JP";
7773
+ return locale;
7774
+ }
7774
7775
  var dtfCache = /* @__PURE__ */ new Map();
7775
7776
  function getDtf(locale, timeZone, options) {
7776
7777
  const key = `${locale}__${timeZone}__${JSON.stringify(options)}`;
@@ -7840,6 +7841,8 @@ function startOfZonedWeek(date, weekStartsOn, timeZone) {
7840
7841
  const diff = (weekday - weekStartsOn + 7) % 7;
7841
7842
  return new Date(zonedTimeToUtcMs({ year: p.year, month: p.month, day: p.day - diff, hour: 0, minute: 0, second: 0 }, timeZone));
7842
7843
  }
7844
+
7845
+ // ../../components/ui/CalendarTimeline/layout.ts
7843
7846
  function clamp3(n, min, max) {
7844
7847
  return Math.max(min, Math.min(max, n));
7845
7848
  }
@@ -7884,6 +7887,80 @@ function intervalPack(items) {
7884
7887
  }
7885
7888
  return { packed: out, laneCount: lanes.length };
7886
7889
  }
7890
+
7891
+ // ../../components/ui/CalendarTimeline/hooks.ts
7892
+ var React27 = __toESM(require("react"), 1);
7893
+ function useHorizontalScrollSync(args) {
7894
+ const { bodyRef, headerRef } = args;
7895
+ React27.useEffect(() => {
7896
+ const body = bodyRef.current;
7897
+ const header = headerRef.current;
7898
+ if (!body || !header) return;
7899
+ let raf = 0;
7900
+ let syncing = false;
7901
+ const syncHeader = () => {
7902
+ if (syncing) return;
7903
+ syncing = true;
7904
+ header.scrollLeft = body.scrollLeft;
7905
+ syncing = false;
7906
+ };
7907
+ const syncBody = () => {
7908
+ if (syncing) return;
7909
+ syncing = true;
7910
+ body.scrollLeft = header.scrollLeft;
7911
+ syncing = false;
7912
+ };
7913
+ const onBodyScroll = () => {
7914
+ cancelAnimationFrame(raf);
7915
+ raf = requestAnimationFrame(syncHeader);
7916
+ };
7917
+ const onHeaderScroll = () => {
7918
+ cancelAnimationFrame(raf);
7919
+ raf = requestAnimationFrame(syncBody);
7920
+ };
7921
+ body.addEventListener("scroll", onBodyScroll, { passive: true });
7922
+ header.addEventListener("scroll", onHeaderScroll, { passive: true });
7923
+ return () => {
7924
+ cancelAnimationFrame(raf);
7925
+ body.removeEventListener("scroll", onBodyScroll);
7926
+ header.removeEventListener("scroll", onHeaderScroll);
7927
+ };
7928
+ }, [bodyRef, headerRef]);
7929
+ }
7930
+ function useVirtualRows(args) {
7931
+ const { enabled, overscan, rowHeight, itemCount, scrollRef } = args;
7932
+ const [viewportHeight, setViewportHeight] = React27.useState(0);
7933
+ const [scrollTop, setScrollTop] = React27.useState(0);
7934
+ React27.useEffect(() => {
7935
+ const el = scrollRef.current;
7936
+ if (!el) return;
7937
+ const update = () => setViewportHeight(el.clientHeight);
7938
+ update();
7939
+ const ro = new ResizeObserver(update);
7940
+ ro.observe(el);
7941
+ return () => ro.disconnect();
7942
+ }, [scrollRef]);
7943
+ React27.useEffect(() => {
7944
+ const el = scrollRef.current;
7945
+ if (!el) return;
7946
+ const onScroll = () => setScrollTop(el.scrollTop);
7947
+ el.addEventListener("scroll", onScroll, { passive: true });
7948
+ return () => el.removeEventListener("scroll", onScroll);
7949
+ }, [scrollRef]);
7950
+ return React27.useMemo(() => {
7951
+ if (!enabled) {
7952
+ return { startIndex: 0, endIndex: itemCount, topSpacer: 0, bottomSpacer: 0 };
7953
+ }
7954
+ const startIndex = clamp3(Math.floor(scrollTop / rowHeight) - overscan, 0, itemCount);
7955
+ const endIndex = clamp3(Math.ceil((scrollTop + viewportHeight) / rowHeight) + overscan, 0, itemCount);
7956
+ const topSpacer = startIndex * rowHeight;
7957
+ const bottomSpacer = (itemCount - endIndex) * rowHeight;
7958
+ return { startIndex, endIndex, topSpacer, bottomSpacer };
7959
+ }, [enabled, itemCount, overscan, rowHeight, scrollTop, viewportHeight]);
7960
+ }
7961
+
7962
+ // ../../components/ui/CalendarTimeline/CalendarTimeline.tsx
7963
+ var import_jsx_runtime33 = require("react/jsx-runtime");
7887
7964
  function defaultMonthTitle(date, locale, timeZone) {
7888
7965
  return getDtf(locale, timeZone, { month: "long", year: "numeric" }).format(date);
7889
7966
  }
@@ -7893,9 +7970,9 @@ function defaultSlotHeader(slotStart, view, locale, timeZone) {
7893
7970
  }
7894
7971
  const weekday = getDtf(locale, timeZone, { weekday: "short" }).format(slotStart);
7895
7972
  const day = getDtf(locale, timeZone, { day: "numeric" }).format(slotStart);
7896
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "inline-flex flex-col leading-tight", children: [
7897
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-[11px] text-muted-foreground", children: weekday }),
7898
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-[12px] font-medium", children: day })
7973
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "inline-flex flex-col items-center leading-tight", children: [
7974
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground/70", children: weekday }),
7975
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-sm font-semibold text-foreground", children: day })
7899
7976
  ] });
7900
7977
  }
7901
7978
  function defaultEventTime(args) {
@@ -7925,9 +8002,9 @@ function CalendarTimeline({
7925
8002
  groupCollapsed,
7926
8003
  defaultGroupCollapsed,
7927
8004
  onGroupCollapsedChange,
7928
- resourceColumnWidth = 220,
7929
- rowHeight = 48,
7930
- slotMinWidth = 56,
8005
+ resourceColumnWidth = 240,
8006
+ rowHeight = 52,
8007
+ slotMinWidth = 64,
7931
8008
  dayTimeStepMinutes = 60,
7932
8009
  maxLanesPerRow = 3,
7933
8010
  now,
@@ -7948,19 +8025,16 @@ function CalendarTimeline({
7948
8025
  }) {
7949
8026
  const t = useTranslations("CalendarTimeline");
7950
8027
  const detectedLocale = useLocale();
7951
- const resolvedLocale = React27.useMemo(() => locale ?? localeToBCP47(detectedLocale), [locale, detectedLocale]);
7952
- const resolvedTimeZone = React27.useMemo(
7953
- () => timeZone ?? Intl.DateTimeFormat().resolvedOptions().timeZone ?? "UTC",
7954
- [timeZone]
7955
- );
8028
+ const resolvedLocale = React28.useMemo(() => localeToBCP47(locale ?? detectedLocale), [locale, detectedLocale]);
8029
+ const resolvedTimeZone = React28.useMemo(() => timeZone ?? Intl.DateTimeFormat().resolvedOptions().timeZone ?? "UTC", [timeZone]);
7956
8030
  const isControlledView = view !== void 0;
7957
- const [internalView, setInternalView] = React27.useState(defaultView);
8031
+ const [internalView, setInternalView] = React28.useState(defaultView);
7958
8032
  const activeView = isControlledView ? view : internalView;
7959
8033
  const isControlledDate = date !== void 0;
7960
- const [internalDate, setInternalDate] = React27.useState(() => defaultDate ?? /* @__PURE__ */ new Date());
8034
+ const [internalDate, setInternalDate] = React28.useState(() => defaultDate ?? /* @__PURE__ */ new Date());
7961
8035
  const activeDate = isControlledDate ? date : internalDate;
7962
8036
  const resolvedNow = now ?? /* @__PURE__ */ new Date();
7963
- const l = React27.useMemo(
8037
+ const l = React28.useMemo(
7964
8038
  () => ({
7965
8039
  today: labels?.today ?? t("today"),
7966
8040
  prev: labels?.prev ?? t("prev"),
@@ -7974,39 +8048,46 @@ function CalendarTimeline({
7974
8048
  }),
7975
8049
  [labels, t]
7976
8050
  );
7977
- const setView = (next) => {
7978
- if (!isControlledView) setInternalView(next);
7979
- onViewChange?.(next);
7980
- };
7981
- const setDate = (next) => {
7982
- if (!isControlledDate) setInternalDate(next);
7983
- onDateChange?.(next);
7984
- };
7985
- const navigate = (dir) => {
7986
- const base = activeDate;
7987
- if (activeView === "month") {
7988
- setDate(addZonedMonths(base, dir, resolvedTimeZone));
7989
- return;
7990
- }
7991
- if (activeView === "week") {
7992
- setDate(addZonedDays(base, dir * 7, resolvedTimeZone));
7993
- return;
7994
- }
7995
- setDate(addZonedDays(base, dir, resolvedTimeZone));
7996
- };
7997
- const goToday = () => setDate(resolvedNow);
7998
- const [internalCollapsed, setInternalCollapsed] = React27.useState(() => defaultGroupCollapsed ?? {});
8051
+ const setView = React28.useCallback(
8052
+ (next) => {
8053
+ if (!isControlledView) setInternalView(next);
8054
+ onViewChange?.(next);
8055
+ },
8056
+ [isControlledView, onViewChange]
8057
+ );
8058
+ const setDate = React28.useCallback(
8059
+ (next) => {
8060
+ if (!isControlledDate) setInternalDate(next);
8061
+ onDateChange?.(next);
8062
+ },
8063
+ [isControlledDate, onDateChange]
8064
+ );
8065
+ const navigate = React28.useCallback(
8066
+ (dir) => {
8067
+ const base = activeDate;
8068
+ if (activeView === "month") {
8069
+ setDate(addZonedMonths(base, dir, resolvedTimeZone));
8070
+ return;
8071
+ }
8072
+ if (activeView === "week") {
8073
+ setDate(addZonedDays(base, dir * 7, resolvedTimeZone));
8074
+ return;
8075
+ }
8076
+ setDate(addZonedDays(base, dir, resolvedTimeZone));
8077
+ },
8078
+ [activeDate, activeView, resolvedTimeZone, setDate]
8079
+ );
8080
+ const goToday = React28.useCallback(() => setDate(resolvedNow), [resolvedNow, setDate]);
8081
+ const [internalCollapsed, setInternalCollapsed] = React28.useState(() => defaultGroupCollapsed ?? {});
7999
8082
  const collapsed = groupCollapsed ?? internalCollapsed;
8000
- const setCollapsed = (next) => {
8001
- if (!groupCollapsed) setInternalCollapsed(next);
8002
- onGroupCollapsedChange?.(next);
8003
- };
8004
- const groupById = React27.useMemo(() => {
8005
- const map = /* @__PURE__ */ new Map();
8006
- for (const g of groups ?? []) map.set(g.id, g);
8007
- return map;
8008
- }, [groups]);
8009
- const rows = React27.useMemo(() => {
8083
+ const setCollapsed = React28.useCallback(
8084
+ (next) => {
8085
+ if (!groupCollapsed) setInternalCollapsed(next);
8086
+ onGroupCollapsedChange?.(next);
8087
+ },
8088
+ [groupCollapsed, onGroupCollapsedChange]
8089
+ );
8090
+ const rows = React28.useMemo(() => {
8010
8091
  if (!groups || groups.length === 0) return resources.map((resource) => ({ kind: "resource", resource }));
8011
8092
  const byGroup = /* @__PURE__ */ new Map();
8012
8093
  for (const r of resources) {
@@ -8037,7 +8118,7 @@ function CalendarTimeline({
8037
8118
  }
8038
8119
  return out;
8039
8120
  }, [resources, groups, collapsed]);
8040
- const { slots, range } = React27.useMemo(() => {
8121
+ const { slots, range } = React28.useMemo(() => {
8041
8122
  const start = activeView === "month" ? startOfZonedMonth(activeDate, resolvedTimeZone) : activeView === "week" ? startOfZonedWeek(activeDate, weekStartsOn, resolvedTimeZone) : startOfZonedDay(activeDate, resolvedTimeZone);
8042
8123
  if (activeView === "day") {
8043
8124
  const step = Math.max(5, Math.min(240, Math.trunc(dayTimeStepMinutes)));
@@ -8071,13 +8152,13 @@ function CalendarTimeline({
8071
8152
  }));
8072
8153
  return { slots: slotItems, range: { start, end } };
8073
8154
  }, [activeView, activeDate, resolvedTimeZone, resolvedLocale, weekStartsOn, dayTimeStepMinutes, resolvedNow, formatters]);
8074
- React27.useEffect(() => {
8155
+ React28.useEffect(() => {
8075
8156
  onRangeChange?.(range);
8076
8157
  }, [range.start, range.end, onRangeChange]);
8077
- const slotStarts = React27.useMemo(() => slots.map((s) => s.start), [slots]);
8158
+ const slotStarts = React28.useMemo(() => slots.map((s) => s.start), [slots]);
8078
8159
  const slotWidth = slotMinWidth;
8079
8160
  const gridWidth = slots.length * slotWidth;
8080
- const normalizedEvents = React27.useMemo(() => {
8161
+ const normalizedEvents = React28.useMemo(() => {
8081
8162
  const rangeStart = range.start.getTime();
8082
8163
  const rangeEnd = range.end.getTime();
8083
8164
  return events.map((e) => {
@@ -8093,7 +8174,7 @@ function CalendarTimeline({
8093
8174
  return { ...e, _start: cs, _end: ce };
8094
8175
  }).filter(Boolean);
8095
8176
  }, [events, range.start, range.end, activeView, resolvedTimeZone]);
8096
- const eventsByResource = React27.useMemo(() => {
8177
+ const eventsByResource = React28.useMemo(() => {
8097
8178
  const map = /* @__PURE__ */ new Map();
8098
8179
  for (const e of normalizedEvents) {
8099
8180
  if (!map.has(e.resourceId)) map.set(e.resourceId, []);
@@ -8101,43 +8182,10 @@ function CalendarTimeline({
8101
8182
  }
8102
8183
  return map;
8103
8184
  }, [normalizedEvents]);
8104
- const bodyRef = React27.useRef(null);
8105
- const headerRef = React27.useRef(null);
8106
- React27.useEffect(() => {
8107
- const body = bodyRef.current;
8108
- const header = headerRef.current;
8109
- if (!body || !header) return;
8110
- let raf = 0;
8111
- let syncing = false;
8112
- const syncHeader = () => {
8113
- if (syncing) return;
8114
- syncing = true;
8115
- header.scrollLeft = body.scrollLeft;
8116
- syncing = false;
8117
- };
8118
- const syncBody = () => {
8119
- if (syncing) return;
8120
- syncing = true;
8121
- body.scrollLeft = header.scrollLeft;
8122
- syncing = false;
8123
- };
8124
- const onBodyScroll = () => {
8125
- cancelAnimationFrame(raf);
8126
- raf = requestAnimationFrame(syncHeader);
8127
- };
8128
- const onHeaderScroll = () => {
8129
- cancelAnimationFrame(raf);
8130
- raf = requestAnimationFrame(syncBody);
8131
- };
8132
- body.addEventListener("scroll", onBodyScroll, { passive: true });
8133
- header.addEventListener("scroll", onHeaderScroll, { passive: true });
8134
- return () => {
8135
- cancelAnimationFrame(raf);
8136
- body.removeEventListener("scroll", onBodyScroll);
8137
- header.removeEventListener("scroll", onHeaderScroll);
8138
- };
8139
- }, []);
8140
- const title = React27.useMemo(() => {
8185
+ const bodyRef = React28.useRef(null);
8186
+ const headerRef = React28.useRef(null);
8187
+ useHorizontalScrollSync({ bodyRef, headerRef });
8188
+ const title = React28.useMemo(() => {
8141
8189
  return formatters?.monthTitle?.(activeDate, { locale: resolvedLocale, timeZone: resolvedTimeZone }) ?? defaultMonthTitle(activeDate, resolvedLocale, resolvedTimeZone);
8142
8190
  }, [activeDate, formatters, resolvedLocale, resolvedTimeZone]);
8143
8191
  const densityClass = "text-sm";
@@ -8146,52 +8194,47 @@ function CalendarTimeline({
8146
8194
  const lanePaddingY = 6;
8147
8195
  const virt = virtualization?.enabled;
8148
8196
  const overscan = virtualization?.overscan ?? 8;
8149
- const [viewportHeight, setViewportHeight] = React27.useState(0);
8150
- const [scrollTop, setScrollTop] = React27.useState(0);
8151
- React27.useEffect(() => {
8152
- const el = bodyRef.current;
8153
- if (!el) return;
8154
- const update = () => setViewportHeight(el.clientHeight);
8155
- update();
8156
- const ro = new ResizeObserver(update);
8157
- ro.observe(el);
8158
- return () => ro.disconnect();
8159
- }, []);
8160
- React27.useEffect(() => {
8161
- const el = bodyRef.current;
8162
- if (!el) return;
8163
- const onScroll = () => setScrollTop(el.scrollTop);
8164
- el.addEventListener("scroll", onScroll, { passive: true });
8165
- return () => el.removeEventListener("scroll", onScroll);
8166
- }, []);
8167
- const totalRows = rows.length;
8168
- const startRow = virt ? clamp3(Math.floor(scrollTop / rowHeight) - overscan, 0, totalRows) : 0;
8169
- const endRow = virt ? clamp3(Math.ceil((scrollTop + viewportHeight) / rowHeight) + overscan, 0, totalRows) : totalRows;
8170
- const topSpacer = startRow * rowHeight;
8171
- const bottomSpacer = (totalRows - endRow) * rowHeight;
8172
- const dragRef = React27.useRef(null);
8173
- const [preview, setPreview] = React27.useState(null);
8174
- const getPointerContext = (clientX, clientY) => {
8175
- const body = bodyRef.current;
8176
- if (!body) return null;
8177
- const el = document.elementFromPoint(clientX, clientY);
8178
- const timelineEl = el?.closest?.("[data-uv-ct-timeline]");
8179
- if (!timelineEl) return null;
8180
- const timelineRect = timelineEl.getBoundingClientRect();
8181
- const x = clientX - timelineRect.left + body.scrollLeft;
8182
- const slotIdx = clamp3(Math.floor(x / slotWidth), 0, Math.max(0, slots.length - 1));
8183
- const rowEl = el?.closest?.("[data-uv-ct-row]");
8184
- const rid = rowEl?.dataset?.uvCtRow ?? null;
8185
- return { slotIdx, resourceId: rid, x };
8186
- };
8187
- const slotToDate = (slotIdx) => {
8188
- const start = slotStarts[clamp3(slotIdx, 0, slotStarts.length - 1)];
8189
- if (activeView === "day") {
8190
- const stepMs = Math.trunc(Math.max(5, Math.min(240, Math.trunc(dayTimeStepMinutes))) * 6e4);
8191
- return { start, end: new Date(start.getTime() + stepMs) };
8192
- }
8193
- return { start, end: addZonedDays(start, 1, resolvedTimeZone) };
8194
- };
8197
+ const {
8198
+ startIndex: startRow,
8199
+ endIndex: endRow,
8200
+ topSpacer,
8201
+ bottomSpacer
8202
+ } = useVirtualRows({
8203
+ enabled: virt,
8204
+ overscan,
8205
+ rowHeight,
8206
+ itemCount: rows.length,
8207
+ scrollRef: bodyRef
8208
+ });
8209
+ const dragRef = React28.useRef(null);
8210
+ const [preview, setPreview] = React28.useState(null);
8211
+ const getPointerContext = React28.useCallback(
8212
+ (clientX, clientY) => {
8213
+ const body = bodyRef.current;
8214
+ if (!body) return null;
8215
+ const el = document.elementFromPoint(clientX, clientY);
8216
+ const timelineEl = el?.closest?.("[data-uv-ct-timeline]");
8217
+ if (!timelineEl) return null;
8218
+ const timelineRect = timelineEl.getBoundingClientRect();
8219
+ const x = clientX - timelineRect.left + body.scrollLeft;
8220
+ const slotIdx = clamp3(Math.floor(x / slotWidth), 0, Math.max(0, slots.length - 1));
8221
+ const rowEl = el?.closest?.("[data-uv-ct-row]");
8222
+ const rid = rowEl?.dataset?.uvCtRow ?? null;
8223
+ return { slotIdx, resourceId: rid, x };
8224
+ },
8225
+ [slotWidth, slots.length]
8226
+ );
8227
+ const slotToDate = React28.useCallback(
8228
+ (slotIdx) => {
8229
+ const start = slotStarts[clamp3(slotIdx, 0, slotStarts.length - 1)];
8230
+ if (activeView === "day") {
8231
+ const stepMs = Math.trunc(Math.max(5, Math.min(240, Math.trunc(dayTimeStepMinutes))) * 6e4);
8232
+ return { start, end: new Date(start.getTime() + stepMs) };
8233
+ }
8234
+ return { start, end: addZonedDays(start, 1, resolvedTimeZone) };
8235
+ },
8236
+ [activeView, dayTimeStepMinutes, resolvedTimeZone, slotStarts]
8237
+ );
8195
8238
  const onPointerDownEvent = (e, ev, mode) => {
8196
8239
  if (ev.resourceId == null) return;
8197
8240
  const allowDrag = interactions?.draggableEvents ?? true;
@@ -8306,14 +8349,28 @@ function CalendarTimeline({
8306
8349
  type: "button",
8307
8350
  onClick: canToggle ? toggle : void 0,
8308
8351
  className: cn(
8309
- "w-full h-full flex items-center gap-2 px-3 text-left",
8310
- "bg-muted/30 border-b border-border/60",
8311
- canToggle ? "cursor-pointer hover:bg-muted/50" : "cursor-default"
8352
+ "w-full h-full flex items-center gap-3 px-4 text-left",
8353
+ "bg-gradient-to-r from-muted/40 to-muted/20 border-b border-border/40",
8354
+ "backdrop-blur-sm",
8355
+ canToggle ? "cursor-pointer hover:from-muted/60 hover:to-muted/30 transition-all duration-200" : "cursor-default"
8312
8356
  ),
8313
8357
  "aria-label": isCollapsed ? l.expandGroup : l.collapseGroup,
8314
8358
  children: [
8315
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: cn("inline-flex transition-transform", isCollapsed ? "" : "rotate-180"), children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.ChevronsUpDown, { className: "h-4 w-4 text-muted-foreground" }) }),
8316
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "font-semibold", children: g.label })
8359
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8360
+ "span",
8361
+ {
8362
+ className: cn(
8363
+ "inline-flex items-center justify-center w-5 h-5 rounded-md bg-background/60 transition-transform duration-200",
8364
+ isCollapsed ? "" : "rotate-180"
8365
+ ),
8366
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })
8367
+ }
8368
+ ),
8369
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "font-semibold text-foreground/90", children: g.label }),
8370
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "ml-auto text-xs text-muted-foreground/60 font-medium", children: [
8371
+ resources.filter((r) => r.groupId === g.id).length,
8372
+ " items"
8373
+ ] })
8317
8374
  ]
8318
8375
  }
8319
8376
  );
@@ -8330,44 +8387,108 @@ function CalendarTimeline({
8330
8387
  "div",
8331
8388
  {
8332
8389
  className: cn(
8333
- "flex-shrink-0 border-l border-border/60 px-2 py-2",
8334
- s.isToday && "bg-primary/5"
8390
+ "flex-shrink-0 border-l border-border/30 px-1 py-3 flex items-center justify-center transition-colors duration-150",
8391
+ s.isToday && "bg-primary/8 border-l-primary/40"
8335
8392
  ),
8336
8393
  style: { width: slotWidth, minWidth: slotWidth },
8337
8394
  "aria-label": formatters?.ariaSlotLabel?.(s.start, { view: activeView, locale: resolvedLocale, timeZone: resolvedTimeZone }),
8338
- children: s.label
8395
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: cn("flex flex-col items-center", s.isToday && "relative"), children: [
8396
+ s.isToday && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.Dot, { className: "absolute -top-2.5 h-4 w-4 text-primary animate-pulse" }),
8397
+ s.label
8398
+ ] })
8339
8399
  },
8340
8400
  `${s.start.toISOString()}_${idx}`
8341
8401
  ))
8342
8402
  }
8343
8403
  );
8344
- const Header = /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "sticky top-0 z-30 bg-background border-b border-border/60", children: [
8345
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between gap-3 px-3 py-2", children: [
8346
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [
8347
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Button_default, { variant: "ghost", size: "sm", onClick: () => navigate(-1), "aria-label": l.prev, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.ChevronLeft, { className: "h-4 w-4" }) }),
8348
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Button_default, { variant: "ghost", size: "sm", onClick: goToday, children: l.today }),
8349
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Button_default, { variant: "ghost", size: "sm", onClick: () => navigate(1), "aria-label": l.next, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.ChevronRight, { className: "h-4 w-4" }) }),
8350
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "ml-2 font-semibold truncate", children: title })
8404
+ const viewIcons = {
8405
+ month: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.CalendarRange, { className: "h-4 w-4" }),
8406
+ week: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.CalendarDays, { className: "h-4 w-4" }),
8407
+ day: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.Calendar, { className: "h-4 w-4" })
8408
+ };
8409
+ const Header = /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "sticky top-0 z-30 bg-gradient-to-b from-background via-background to-background/95 border-b border-border/40 backdrop-blur-xl", children: [
8410
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between gap-4 px-4 py-3", children: [
8411
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center gap-1.5 min-w-0", children: [
8412
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center bg-muted/40 rounded-xl p-1 gap-0.5", children: [
8413
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8414
+ Button_default,
8415
+ {
8416
+ variant: "ghost",
8417
+ size: "icon",
8418
+ onClick: () => navigate(-1),
8419
+ "aria-label": l.prev,
8420
+ className: "h-8 w-8 rounded-lg hover:bg-background/80 transition-all duration-200",
8421
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.ChevronLeft, { className: "h-4 w-4" })
8422
+ }
8423
+ ),
8424
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8425
+ Button_default,
8426
+ {
8427
+ variant: "ghost",
8428
+ size: "sm",
8429
+ onClick: goToday,
8430
+ className: "h-8 px-3 rounded-lg hover:bg-background/80 font-medium transition-all duration-200",
8431
+ children: l.today
8432
+ }
8433
+ ),
8434
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8435
+ Button_default,
8436
+ {
8437
+ variant: "ghost",
8438
+ size: "icon",
8439
+ onClick: () => navigate(1),
8440
+ "aria-label": l.next,
8441
+ className: "h-8 w-8 rounded-lg hover:bg-background/80 transition-all duration-200",
8442
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.ChevronRight, { className: "h-4 w-4" })
8443
+ }
8444
+ )
8445
+ ] }),
8446
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("h2", { className: "ml-3 text-lg font-semibold tracking-tight truncate text-foreground", children: title })
8351
8447
  ] }),
8352
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center gap-1", children: [
8353
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Button_default, { variant: activeView === "month" ? "default" : "ghost", size: "sm", onClick: () => setView("month"), children: l.month }),
8354
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Button_default, { variant: activeView === "week" ? "default" : "ghost", size: "sm", onClick: () => setView("week"), children: l.week }),
8355
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Button_default, { variant: activeView === "day" ? "default" : "ghost", size: "sm", onClick: () => setView("day"), children: l.day })
8356
- ] })
8448
+ /* @__PURE__ */ (0, import_jsx_runtime33.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_runtime33.jsxs)(
8449
+ Button_default,
8450
+ {
8451
+ variant: activeView === v ? "default" : "ghost",
8452
+ size: "sm",
8453
+ onClick: () => setView(v),
8454
+ className: cn(
8455
+ "h-8 px-3 rounded-lg font-medium transition-all duration-200 gap-1.5",
8456
+ activeView === v ? "bg-primary text-primary-foreground shadow-sm shadow-primary/25" : "hover:bg-background/80 text-muted-foreground hover:text-foreground"
8457
+ ),
8458
+ children: [
8459
+ viewIcons[v],
8460
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "hidden sm:inline", children: l[v] })
8461
+ ]
8462
+ },
8463
+ v
8464
+ )) })
8357
8465
  ] }),
8358
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex", children: [
8466
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex border-t border-border/20", children: [
8359
8467
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8360
8468
  "div",
8361
8469
  {
8362
- className: "flex-shrink-0 border-r border-border/60 bg-background",
8363
- style: { width: resourceColumnWidth, minWidth: resourceColumnWidth }
8470
+ className: "flex-shrink-0 border-r border-border/30 bg-muted/20 flex items-center justify-center",
8471
+ style: { width: resourceColumnWidth, minWidth: resourceColumnWidth },
8472
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-xs font-medium text-muted-foreground/70 uppercase tracking-wider", children: "Resources" })
8364
8473
  }
8365
8474
  ),
8366
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: headerRef, className: "overflow-x-auto overflow-y-hidden", children: slotHeaderNodes })
8475
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: headerRef, className: "overflow-x-auto overflow-y-hidden scrollbar-none", children: slotHeaderNodes })
8367
8476
  ] })
8368
8477
  ] });
8369
- const ResourceCell = (r) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "h-full w-full flex items-center px-3 border-b border-border/60 bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn("truncate", r.disabled && "opacity-50"), children: renderResource ? renderResource(r) : r.label }) });
8370
- const layoutsByResource = React27.useMemo(() => {
8478
+ const ResourceCell = (r) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
8479
+ "div",
8480
+ {
8481
+ className: cn(
8482
+ "h-full w-full flex items-center gap-3 px-4 border-b border-border/30 bg-gradient-to-r from-background to-background/95",
8483
+ "hover:from-muted/30 hover:to-muted/10 transition-all duration-200 group"
8484
+ ),
8485
+ children: [
8486
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-shrink-0 opacity-0 group-hover:opacity-60 transition-opacity cursor-grab", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.GripVertical, { className: "h-4 w-4 text-muted-foreground" }) }),
8487
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn("flex-1 min-w-0", r.disabled && "opacity-50"), children: renderResource ? renderResource(r) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "font-medium text-sm truncate block", children: r.label }) })
8488
+ ]
8489
+ }
8490
+ );
8491
+ const layoutsByResource = React28.useMemo(() => {
8371
8492
  const map = /* @__PURE__ */ new Map();
8372
8493
  for (const [resourceId, list] of eventsByResource.entries()) {
8373
8494
  const mapped = list.map((ev) => {
@@ -8396,7 +8517,12 @@ function CalendarTimeline({
8396
8517
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
8397
8518
  "div",
8398
8519
  {
8399
- className: cn("border border-border/60 rounded-2xl overflow-hidden bg-background", densityClass, className),
8520
+ className: cn(
8521
+ "border border-border/40 rounded-2xl overflow-hidden bg-background/95 backdrop-blur-sm",
8522
+ "shadow-sm hover:shadow-md transition-shadow duration-300",
8523
+ densityClass,
8524
+ className
8525
+ ),
8400
8526
  ...rest,
8401
8527
  children: [
8402
8528
  Header,
@@ -8404,7 +8530,7 @@ function CalendarTimeline({
8404
8530
  "div",
8405
8531
  {
8406
8532
  ref: bodyRef,
8407
- className: "relative overflow-auto",
8533
+ className: "relative overflow-auto scrollbar-thin scrollbar-thumb-muted scrollbar-track-transparent",
8408
8534
  onPointerMove,
8409
8535
  onPointerUp,
8410
8536
  children: [
@@ -8413,15 +8539,8 @@ function CalendarTimeline({
8413
8539
  const rowIndex = startRow + idx;
8414
8540
  if (row.kind === "group") {
8415
8541
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex", style: { height: rowHeight }, children: [
8416
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8417
- "div",
8418
- {
8419
- className: "flex-shrink-0 sticky left-0 z-20",
8420
- style: { width: resourceColumnWidth, minWidth: resourceColumnWidth },
8421
- children: renderGroupRow(row.group)
8422
- }
8423
- ),
8424
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 border-b border-border/60 bg-muted/20", style: { minWidth: gridWidth } })
8542
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-shrink-0 sticky left-0 z-20", style: { width: resourceColumnWidth, minWidth: resourceColumnWidth }, children: renderGroupRow(row.group) }),
8543
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 border-b border-border/30 bg-gradient-to-r from-muted/15 to-muted/5", style: { minWidth: gridWidth } })
8425
8544
  ] }, `g_${row.group.id}_${rowIndex}`);
8426
8545
  }
8427
8546
  const r = row.resource;
@@ -8430,122 +8549,130 @@ function CalendarTimeline({
8430
8549
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
8431
8550
  "div",
8432
8551
  {
8433
- className: "flex",
8552
+ className: "flex group/row hover:bg-muted/5 transition-colors duration-150",
8434
8553
  style: { height: rowHeight },
8435
8554
  "data-uv-ct-row": r.id,
8436
8555
  children: [
8437
8556
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8438
8557
  "div",
8439
8558
  {
8440
- className: "flex-shrink-0 sticky left-0 z-20 border-r border-border/60",
8559
+ className: "flex-shrink-0 sticky left-0 z-20 border-r border-border/30",
8441
8560
  style: { width: resourceColumnWidth, minWidth: resourceColumnWidth },
8442
8561
  children: ResourceCell(r)
8443
8562
  }
8444
8563
  ),
8445
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
8446
- "div",
8447
- {
8448
- className: "relative flex-shrink-0",
8449
- style: { width: gridWidth, minWidth: gridWidth },
8450
- children: [
8451
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8452
- "div",
8453
- {
8454
- className: "absolute inset-0",
8455
- onPointerDown: onPointerDownCell,
8456
- "data-uv-ct-timeline": true,
8457
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "absolute inset-0 flex", children: slots.map((s, i2) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8458
- "div",
8459
- {
8460
- className: cn("h-full border-l border-border/60", s.isToday && "bg-primary/5"),
8461
- style: { width: slotWidth, minWidth: slotWidth }
8462
- },
8463
- `${r.id}_${i2}`
8464
- )) })
8465
- }
8564
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "relative flex-shrink-0", style: { width: gridWidth, minWidth: gridWidth }, children: [
8565
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "absolute inset-0", onPointerDown: onPointerDownCell, "data-uv-ct-timeline": true, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "absolute inset-0 flex", children: slots.map((s, i2) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8566
+ "div",
8567
+ {
8568
+ className: cn(
8569
+ "h-full border-l border-border/20 transition-colors duration-100",
8570
+ s.isToday && "bg-primary/5 border-l-primary/30",
8571
+ "hover:bg-muted/10"
8466
8572
  ),
8467
- layout.visible.map(({ ev, left, width, lane }) => {
8468
- const top = lanePaddingY + lane * (eventHeight + laneGap);
8469
- const isPreview = preview?.eventId === ev.id;
8470
- const bg = ev.color ? ev.color : "var(--primary-soft)";
8471
- const border = ev.color ? ev.color : "var(--primary)";
8472
- const aria = formatters?.ariaEventLabel?.(ev, { locale: resolvedLocale, timeZone: resolvedTimeZone }) ?? (typeof ev.title === "string" ? ev.title : "Event");
8473
- const timeText = formatters?.eventTime?.({ start: ev._start, end: ev._end, locale: resolvedLocale, timeZone: resolvedTimeZone, view: activeView }) ?? defaultEventTime({ start: ev._start, end: ev._end, locale: resolvedLocale, timeZone: resolvedTimeZone, view: activeView });
8474
- const node = renderEvent?.(ev, { left, width, lane }) ?? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "px-2 py-[2px] truncate text-[11px] leading-tight", children: [
8475
- ev.title ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "font-semibold truncate", children: ev.title }) : null,
8476
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "text-[10px] opacity-80 truncate", children: timeText })
8477
- ] });
8478
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
8479
- "div",
8480
- {
8481
- className: cn(
8482
- "absolute rounded-md border shadow-sm select-none",
8483
- "hover:shadow transition-shadow",
8484
- ev.className,
8485
- isPreview && "ring-2 ring-primary/40"
8573
+ style: { width: slotWidth, minWidth: slotWidth }
8574
+ },
8575
+ `${r.id}_${i2}`
8576
+ )) }) }),
8577
+ layout.visible.map(({ ev, left, width, lane }) => {
8578
+ const top = lanePaddingY + lane * (eventHeight + laneGap);
8579
+ const isPreview = preview?.eventId === ev.id;
8580
+ const bg = ev.color ? ev.color : "hsl(var(--primary) / 0.15)";
8581
+ const border = ev.color ? ev.color : "hsl(var(--primary))";
8582
+ const aria = formatters?.ariaEventLabel?.(ev, { locale: resolvedLocale, timeZone: resolvedTimeZone }) ?? (typeof ev.title === "string" ? ev.title : "Event");
8583
+ const timeText = formatters?.eventTime?.({
8584
+ start: ev._start,
8585
+ end: ev._end,
8586
+ locale: resolvedLocale,
8587
+ timeZone: resolvedTimeZone,
8588
+ view: activeView
8589
+ }) ?? defaultEventTime({ start: ev._start, end: ev._end, locale: resolvedLocale, timeZone: resolvedTimeZone, view: activeView });
8590
+ const node = renderEvent?.(ev, { left, width, lane }) ?? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "px-2.5 py-1 truncate flex items-center gap-1.5", children: [
8591
+ ev.title ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "font-semibold text-[11px] truncate leading-tight", children: ev.title }) : null,
8592
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-[10px] opacity-70 truncate ml-auto", children: timeText })
8593
+ ] });
8594
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
8595
+ "div",
8596
+ {
8597
+ className: cn(
8598
+ "absolute rounded-lg border select-none cursor-pointer",
8599
+ "shadow-sm hover:shadow-md hover:scale-[1.02] hover:z-10",
8600
+ "transition-all duration-150 ease-out",
8601
+ "backdrop-blur-sm",
8602
+ ev.className,
8603
+ isPreview && "ring-2 ring-primary/50 ring-offset-1 ring-offset-background scale-[1.02] z-10"
8604
+ ),
8605
+ style: {
8606
+ left,
8607
+ top,
8608
+ width,
8609
+ height: eventHeight,
8610
+ background: bg,
8611
+ borderColor: border,
8612
+ borderLeftWidth: 3
8613
+ },
8614
+ role: "button",
8615
+ tabIndex: 0,
8616
+ "aria-label": aria,
8617
+ onClick: () => onEventClick?.(ev),
8618
+ onDoubleClick: () => onEventDoubleClick?.(ev),
8619
+ onPointerDown: (e) => onPointerDownEvent(e, ev, "move"),
8620
+ children: [
8621
+ (interactions?.resizableEvents ?? true) && ev.resizable !== false ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
8622
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8623
+ "div",
8624
+ {
8625
+ className: "absolute left-0 top-0 h-full w-2 cursor-ew-resize opacity-0 hover:opacity-100 bg-primary/20 rounded-l-lg transition-opacity",
8626
+ onPointerDown: (e) => onPointerDownEvent(e, ev, "resize-start")
8627
+ }
8486
8628
  ),
8487
- style: {
8488
- left,
8489
- top,
8490
- width,
8491
- height: eventHeight,
8492
- background: bg,
8493
- borderColor: border
8494
- },
8495
- role: "button",
8496
- tabIndex: 0,
8497
- "aria-label": aria,
8498
- onClick: () => onEventClick?.(ev),
8499
- onDoubleClick: () => onEventDoubleClick?.(ev),
8500
- onPointerDown: (e) => onPointerDownEvent(e, ev, "move"),
8501
- children: [
8502
- (interactions?.resizableEvents ?? true) && ev.resizable !== false ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
8503
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8504
- "div",
8505
- {
8506
- className: "absolute left-0 top-0 h-full w-2 cursor-ew-resize",
8507
- onPointerDown: (e) => onPointerDownEvent(e, ev, "resize-start")
8508
- }
8509
- ),
8510
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8511
- "div",
8512
- {
8513
- className: "absolute right-0 top-0 h-full w-2 cursor-ew-resize",
8514
- onPointerDown: (e) => onPointerDownEvent(e, ev, "resize-end")
8515
- }
8516
- )
8517
- ] }) : null,
8518
- node
8519
- ]
8520
- },
8521
- ev.id
8522
- );
8523
- }),
8524
- preview && preview.resourceId === r.id && !preview.eventId ? (() => {
8525
- const startIdx = binarySearchLastLE(slotStarts, preview.start);
8526
- const endIdx = clamp3(binarySearchFirstGE(slotStarts, preview.end), startIdx + 1, slots.length);
8527
- const left = startIdx * slotWidth;
8528
- const width = Math.max(1, (endIdx - startIdx) * slotWidth);
8529
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8530
- "div",
8531
- {
8532
- className: "absolute rounded-md border border-primary/60 bg-primary/20",
8533
- style: { left, top: lanePaddingY, width, height: eventHeight }
8534
- }
8535
- );
8536
- })() : null,
8537
- canMore ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8538
- "button",
8539
- {
8540
- type: "button",
8541
- className: "absolute right-2 bottom-1 text-[11px] text-primary hover:underline",
8542
- onClick: () => onMoreClick?.({ resourceId: r.id, hiddenEvents: layout.hidden }),
8543
- children: l.more(layout.hidden.length)
8544
- }
8545
- ) : null
8546
- ]
8547
- }
8548
- )
8629
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8630
+ "div",
8631
+ {
8632
+ className: "absolute right-0 top-0 h-full w-2 cursor-ew-resize opacity-0 hover:opacity-100 bg-primary/20 rounded-r-lg transition-opacity",
8633
+ onPointerDown: (e) => onPointerDownEvent(e, ev, "resize-end")
8634
+ }
8635
+ )
8636
+ ] }) : null,
8637
+ node
8638
+ ]
8639
+ },
8640
+ ev.id
8641
+ );
8642
+ }),
8643
+ preview && preview.resourceId === r.id && !preview.eventId ? (() => {
8644
+ const startIdx = binarySearchLastLE(slotStarts, preview.start);
8645
+ const endIdx = clamp3(binarySearchFirstGE(slotStarts, preview.end), startIdx + 1, slots.length);
8646
+ const left = startIdx * slotWidth;
8647
+ const width = Math.max(1, (endIdx - startIdx) * slotWidth);
8648
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8649
+ "div",
8650
+ {
8651
+ className: "absolute rounded-lg border-2 border-dashed border-primary/60 bg-primary/10 backdrop-blur-sm animate-pulse",
8652
+ style: { left, top: lanePaddingY, width, height: eventHeight }
8653
+ }
8654
+ );
8655
+ })() : null,
8656
+ canMore ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
8657
+ "button",
8658
+ {
8659
+ type: "button",
8660
+ className: cn(
8661
+ "absolute right-2 bottom-1.5 text-[10px] font-semibold",
8662
+ "px-2 py-0.5 rounded-full",
8663
+ "bg-primary/10 text-primary hover:bg-primary/20",
8664
+ "transition-all duration-200 hover:scale-105"
8665
+ ),
8666
+ onClick: () => onMoreClick?.({ resourceId: r.id, hiddenEvents: layout.hidden }),
8667
+ children: [
8668
+ "+",
8669
+ layout.hidden.length,
8670
+ " ",
8671
+ l.more(layout.hidden.length).replace(/^\+?\d+\s*/, "")
8672
+ ]
8673
+ }
8674
+ ) : null
8675
+ ] })
8549
8676
  ]
8550
8677
  },
8551
8678
  `r_${r.id}_${rowIndex}`
@@ -8561,7 +8688,7 @@ function CalendarTimeline({
8561
8688
  }
8562
8689
 
8563
8690
  // ../../components/ui/MultiCombobox.tsx
8564
- var React28 = __toESM(require("react"), 1);
8691
+ var React29 = __toESM(require("react"), 1);
8565
8692
  var import_react16 = require("react");
8566
8693
  var import_lucide_react19 = require("lucide-react");
8567
8694
  var import_jsx_runtime34 = require("react/jsx-runtime");
@@ -8596,27 +8723,27 @@ var MultiCombobox = ({
8596
8723
  helperText,
8597
8724
  maxTagsVisible = 3
8598
8725
  }) => {
8599
- const [query, setQuery] = React28.useState("");
8600
- const [open, setOpen] = React28.useState(false);
8601
- const [activeIndex, setActiveIndex] = React28.useState(null);
8602
- const inputRef = React28.useRef(null);
8603
- const listRef = React28.useRef([]);
8604
- const triggerRef = React28.useRef(null);
8726
+ const [query, setQuery] = React29.useState("");
8727
+ const [open, setOpen] = React29.useState(false);
8728
+ const [activeIndex, setActiveIndex] = React29.useState(null);
8729
+ const inputRef = React29.useRef(null);
8730
+ const listRef = React29.useRef([]);
8731
+ const triggerRef = React29.useRef(null);
8605
8732
  useShadCNAnimations();
8606
- const normalizedOptions = React28.useMemo(
8733
+ const normalizedOptions = React29.useMemo(
8607
8734
  () => options.map(
8608
8735
  (o) => typeof o === "string" ? { value: o, label: o } : { value: o.value, label: o.label, icon: o.icon, description: o.description, disabled: o.disabled, group: o.group }
8609
8736
  ),
8610
8737
  [options]
8611
8738
  );
8612
8739
  const enableSearch = normalizedOptions.length > 10;
8613
- const filtered = React28.useMemo(
8740
+ const filtered = React29.useMemo(
8614
8741
  () => enableSearch ? normalizedOptions.filter(
8615
8742
  (opt) => opt.label.toLowerCase().includes(query.toLowerCase()) || opt.description?.toLowerCase().includes(query.toLowerCase())
8616
8743
  ) : normalizedOptions,
8617
8744
  [normalizedOptions, query, enableSearch]
8618
8745
  );
8619
- const groupedOptions = React28.useMemo(() => {
8746
+ const groupedOptions = React29.useMemo(() => {
8620
8747
  if (!groupBy) return null;
8621
8748
  const groups = /* @__PURE__ */ new Map();
8622
8749
  filtered.forEach((opt) => {
@@ -8652,7 +8779,7 @@ var MultiCombobox = ({
8652
8779
  const handleClearAll = () => {
8653
8780
  onChange([]);
8654
8781
  };
8655
- React28.useEffect(() => {
8782
+ React29.useEffect(() => {
8656
8783
  if (open && enableSearch) {
8657
8784
  setTimeout(() => {
8658
8785
  inputRef.current?.focus();
@@ -8877,7 +9004,7 @@ var MultiCombobox = ({
8877
9004
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex items-center gap-1.5 flex-wrap min-h-6 flex-1", children: value.length > 0 ? showTags ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
8878
9005
  visibleTags.map((option) => {
8879
9006
  if (renderTag) {
8880
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(React28.Fragment, { children: renderTag(option, () => handleRemove(option.value)) }, option.value);
9007
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(React29.Fragment, { children: renderTag(option, () => handleRemove(option.value)) }, option.value);
8881
9008
  }
8882
9009
  return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
8883
9010
  "span",
@@ -9018,17 +9145,17 @@ var MultiCombobox = ({
9018
9145
  };
9019
9146
 
9020
9147
  // ../../components/ui/RadioGroup.tsx
9021
- var React29 = __toESM(require("react"), 1);
9148
+ var React30 = __toESM(require("react"), 1);
9022
9149
  var import_jsx_runtime35 = require("react/jsx-runtime");
9023
- var RadioGroupContext = React29.createContext(void 0);
9150
+ var RadioGroupContext = React30.createContext(void 0);
9024
9151
  var useRadioGroup = () => {
9025
- const context = React29.useContext(RadioGroupContext);
9152
+ const context = React30.useContext(RadioGroupContext);
9026
9153
  if (!context) {
9027
9154
  throw new Error("RadioGroupItem must be used within a RadioGroup");
9028
9155
  }
9029
9156
  return context;
9030
9157
  };
9031
- var RadioGroup = React29.forwardRef(
9158
+ var RadioGroup = React30.forwardRef(
9032
9159
  ({
9033
9160
  value,
9034
9161
  defaultValue,
@@ -9044,7 +9171,7 @@ var RadioGroup = React29.forwardRef(
9044
9171
  error = false,
9045
9172
  errorMessage
9046
9173
  }, ref) => {
9047
- const [internalValue, setInternalValue] = React29.useState(defaultValue || "");
9174
+ const [internalValue, setInternalValue] = React30.useState(defaultValue || "");
9048
9175
  const isControlled = value !== void 0;
9049
9176
  const currentValue = isControlled ? value : internalValue;
9050
9177
  const handleValueChange = (newValue) => {
@@ -9055,7 +9182,7 @@ var RadioGroup = React29.forwardRef(
9055
9182
  onValueChange?.(newValue);
9056
9183
  }
9057
9184
  };
9058
- const uniqueId = React29.useId();
9185
+ const uniqueId = React30.useId();
9059
9186
  const radioName = name || `radio-group-${uniqueId}`;
9060
9187
  return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
9061
9188
  RadioGroupContext.Provider,
@@ -9113,7 +9240,7 @@ var sizeStyles7 = {
9113
9240
  padding: "p-4"
9114
9241
  }
9115
9242
  };
9116
- var RadioGroupItem = React29.forwardRef(
9243
+ var RadioGroupItem = React30.forwardRef(
9117
9244
  ({ value, id, disabled, className, children, label, description, icon }, ref) => {
9118
9245
  const { value: selectedValue, onValueChange, name, disabled: groupDisabled, size = "md", variant = "default" } = useRadioGroup();
9119
9246
  const isDisabled = disabled || groupDisabled;
@@ -9290,7 +9417,7 @@ var RadioGroupItem = React29.forwardRef(
9290
9417
  RadioGroupItem.displayName = "RadioGroupItem";
9291
9418
 
9292
9419
  // ../../components/ui/Slider.tsx
9293
- var React30 = __toESM(require("react"), 1);
9420
+ var React31 = __toESM(require("react"), 1);
9294
9421
  var import_jsx_runtime36 = require("react/jsx-runtime");
9295
9422
  var SIZE_STYLES = {
9296
9423
  sm: {
@@ -9309,7 +9436,7 @@ var SIZE_STYLES = {
9309
9436
  container: "py-3"
9310
9437
  }
9311
9438
  };
9312
- var Slider = React30.forwardRef(
9439
+ var Slider = React31.forwardRef(
9313
9440
  ({
9314
9441
  className,
9315
9442
  value,
@@ -9335,7 +9462,7 @@ var Slider = React30.forwardRef(
9335
9462
  noFocus = true,
9336
9463
  ...props
9337
9464
  }, ref) => {
9338
- const [internalValue, setInternalValue] = React30.useState(defaultValue);
9465
+ const [internalValue, setInternalValue] = React31.useState(defaultValue);
9339
9466
  const isControlled = value !== void 0;
9340
9467
  const currentValue = isControlled ? value : internalValue;
9341
9468
  const handleChange = (e) => {
@@ -10336,7 +10463,7 @@ function ImageUpload({
10336
10463
  }
10337
10464
 
10338
10465
  // ../../components/ui/Carousel.tsx
10339
- var React33 = __toESM(require("react"), 1);
10466
+ var React34 = __toESM(require("react"), 1);
10340
10467
  var import_lucide_react23 = require("lucide-react");
10341
10468
  var import_jsx_runtime40 = require("react/jsx-runtime");
10342
10469
  function Carousel({
@@ -10359,19 +10486,19 @@ function Carousel({
10359
10486
  thumbnailRenderer,
10360
10487
  ariaLabel = "Carousel"
10361
10488
  }) {
10362
- const [currentIndex, setCurrentIndex] = React33.useState(0);
10363
- const [isPaused, setIsPaused] = React33.useState(false);
10364
- const [isDragging, setIsDragging] = React33.useState(false);
10365
- const [startPos, setStartPos] = React33.useState(0);
10366
- const [currentTranslate, setCurrentTranslate] = React33.useState(0);
10367
- const [prevTranslate, setPrevTranslate] = React33.useState(0);
10368
- const progressElRef = React33.useRef(null);
10369
- const carouselRef = React33.useRef(null);
10370
- const rafRef = React33.useRef(null);
10371
- const totalSlides = React33.Children.count(children);
10489
+ const [currentIndex, setCurrentIndex] = React34.useState(0);
10490
+ const [isPaused, setIsPaused] = React34.useState(false);
10491
+ const [isDragging, setIsDragging] = React34.useState(false);
10492
+ const [startPos, setStartPos] = React34.useState(0);
10493
+ const [currentTranslate, setCurrentTranslate] = React34.useState(0);
10494
+ const [prevTranslate, setPrevTranslate] = React34.useState(0);
10495
+ const progressElRef = React34.useRef(null);
10496
+ const carouselRef = React34.useRef(null);
10497
+ const rafRef = React34.useRef(null);
10498
+ const totalSlides = React34.Children.count(children);
10372
10499
  const maxIndex = Math.max(0, totalSlides - slidesToShow);
10373
10500
  const isHorizontal = orientation === "horizontal";
10374
- const scrollPrev = React33.useCallback(() => {
10501
+ const scrollPrev = React34.useCallback(() => {
10375
10502
  setCurrentIndex((prev) => {
10376
10503
  if (prev === 0) {
10377
10504
  return loop ? maxIndex : 0;
@@ -10379,7 +10506,7 @@ function Carousel({
10379
10506
  return Math.max(0, prev - slidesToScroll);
10380
10507
  });
10381
10508
  }, [loop, maxIndex, slidesToScroll]);
10382
- const scrollNext = React33.useCallback(() => {
10509
+ const scrollNext = React34.useCallback(() => {
10383
10510
  setCurrentIndex((prev) => {
10384
10511
  if (prev >= maxIndex) {
10385
10512
  return loop ? 0 : maxIndex;
@@ -10387,13 +10514,13 @@ function Carousel({
10387
10514
  return Math.min(maxIndex, prev + slidesToScroll);
10388
10515
  });
10389
10516
  }, [loop, maxIndex, slidesToScroll]);
10390
- const scrollTo = React33.useCallback(
10517
+ const scrollTo = React34.useCallback(
10391
10518
  (index) => {
10392
10519
  setCurrentIndex(Math.min(maxIndex, Math.max(0, index)));
10393
10520
  },
10394
10521
  [maxIndex]
10395
10522
  );
10396
- React33.useEffect(() => {
10523
+ React34.useEffect(() => {
10397
10524
  const handleKeyDown = (e) => {
10398
10525
  if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
10399
10526
  e.preventDefault();
@@ -10415,7 +10542,7 @@ function Carousel({
10415
10542
  return () => carousel.removeEventListener("keydown", handleKeyDown);
10416
10543
  }
10417
10544
  }, [scrollPrev, scrollNext, scrollTo, maxIndex]);
10418
- React33.useEffect(() => {
10545
+ React34.useEffect(() => {
10419
10546
  const stop = () => {
10420
10547
  if (rafRef.current != null) {
10421
10548
  cancelAnimationFrame(rafRef.current);
@@ -10474,7 +10601,7 @@ function Carousel({
10474
10601
  setCurrentTranslate(0);
10475
10602
  setPrevTranslate(0);
10476
10603
  };
10477
- React33.useEffect(() => {
10604
+ React34.useEffect(() => {
10478
10605
  onSlideChange?.(currentIndex);
10479
10606
  }, [currentIndex, onSlideChange]);
10480
10607
  const getAnimationStyles2 = () => {
@@ -10527,7 +10654,7 @@ function Carousel({
10527
10654
  role: "group",
10528
10655
  "aria-atomic": "false",
10529
10656
  "aria-live": autoScroll ? "off" : "polite",
10530
- children: React33.Children.map(children, (child, idx) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10657
+ children: React34.Children.map(children, (child, idx) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10531
10658
  "div",
10532
10659
  {
10533
10660
  className: cn(
@@ -10617,7 +10744,7 @@ function Carousel({
10617
10744
  "absolute bottom-0 left-0 right-0 flex gap-2 p-4 bg-linear-to-t from-black/50 to-transparent overflow-x-auto",
10618
10745
  isHorizontal ? "flex-row" : "flex-col"
10619
10746
  ),
10620
- children: React33.Children.map(children, (child, idx) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10747
+ children: React34.Children.map(children, (child, idx) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10621
10748
  "button",
10622
10749
  {
10623
10750
  onClick: () => scrollTo(idx),
@@ -10910,7 +11037,7 @@ function FallingIcons({
10910
11037
  }
10911
11038
 
10912
11039
  // ../../components/ui/List.tsx
10913
- var React35 = __toESM(require("react"), 1);
11040
+ var React36 = __toESM(require("react"), 1);
10914
11041
  var import_lucide_react24 = require("lucide-react");
10915
11042
  var import_jsx_runtime42 = require("react/jsx-runtime");
10916
11043
  var SIZE_STYLES2 = {
@@ -10936,7 +11063,7 @@ var ListItemSkeleton = ({ size }) => {
10936
11063
  ] })
10937
11064
  ] });
10938
11065
  };
10939
- var ListRoot = React35.forwardRef(
11066
+ var ListRoot = React36.forwardRef(
10940
11067
  ({
10941
11068
  as = "ul",
10942
11069
  ordered,
@@ -10956,7 +11083,7 @@ var ListRoot = React35.forwardRef(
10956
11083
  ...rest
10957
11084
  }, ref) => {
10958
11085
  const Comp = ordered ? "ol" : as;
10959
- const childCount = React35.Children.count(children);
11086
+ const childCount = React36.Children.count(children);
10960
11087
  const hasChildren = childCount > 0;
10961
11088
  const variantClasses2 = {
10962
11089
  plain: "",
@@ -10994,14 +11121,14 @@ var ListRoot = React35.forwardRef(
10994
11121
  className
10995
11122
  ),
10996
11123
  ...rest,
10997
- children: React35.Children.map(children, (child, idx) => {
10998
- if (!React35.isValidElement(child)) return child;
11124
+ children: React36.Children.map(children, (child, idx) => {
11125
+ if (!React36.isValidElement(child)) return child;
10999
11126
  const childClass = cn(
11000
11127
  child.props?.className,
11001
11128
  hoverable && variant !== "flush" && "hover:bg-accent/50 focus:bg-accent/60 focus:outline-none transition-colors",
11002
11129
  variant === "flush" && "hover:bg-accent/30"
11003
11130
  );
11004
- return React35.cloneElement(child, {
11131
+ return React36.cloneElement(child, {
11005
11132
  className: childClass,
11006
11133
  // Pass global item class to contentClassName of ListItem
11007
11134
  contentClassName: cn(itemClassName, child.props?.contentClassName),
@@ -11016,7 +11143,7 @@ var ListRoot = React35.forwardRef(
11016
11143
  }
11017
11144
  );
11018
11145
  ListRoot.displayName = "List";
11019
- var ListItem = React35.forwardRef(
11146
+ var ListItem = React36.forwardRef(
11020
11147
  ({
11021
11148
  as = "li",
11022
11149
  selected = false,
@@ -11039,7 +11166,7 @@ var ListItem = React35.forwardRef(
11039
11166
  children,
11040
11167
  ...rest
11041
11168
  }, ref) => {
11042
- const [internalExpanded, setInternalExpanded] = React35.useState(false);
11169
+ const [internalExpanded, setInternalExpanded] = React36.useState(false);
11043
11170
  const isExpanded = controlledExpanded !== void 0 ? controlledExpanded : internalExpanded;
11044
11171
  const sizeAttr = rest["data-size"];
11045
11172
  const resolvedSize = sizeAttr && ["xs", "sm", "md", "lg"].includes(sizeAttr) ? sizeAttr : "md";
@@ -11107,7 +11234,7 @@ var List = Object.assign(ListRoot, { Item: ListItem });
11107
11234
  var List_default = List;
11108
11235
 
11109
11236
  // ../../components/ui/Watermark.tsx
11110
- var React36 = __toESM(require("react"), 1);
11237
+ var React37 = __toESM(require("react"), 1);
11111
11238
  var import_react_dom5 = require("react-dom");
11112
11239
  var import_jsx_runtime43 = require("react/jsx-runtime");
11113
11240
  var PRESETS2 = {
@@ -11119,8 +11246,8 @@ var PRESETS2 = {
11119
11246
  internal: { text: "INTERNAL USE ONLY", color: "rgba(156, 163, 175, 0.15)", rotate: -22, fontSize: 13, fontWeight: "600" }
11120
11247
  };
11121
11248
  function useWatermarkDataURL(opts) {
11122
- const [url, setUrl] = React36.useState(null);
11123
- React36.useEffect(() => {
11249
+ const [url, setUrl] = React37.useState(null);
11250
+ React37.useEffect(() => {
11124
11251
  let cancelled = false;
11125
11252
  const text = opts.text;
11126
11253
  const image = opts.image;
@@ -11297,9 +11424,9 @@ var Watermark = ({
11297
11424
  children,
11298
11425
  ...rest
11299
11426
  }) => {
11300
- const [visible, setVisible] = React36.useState(true);
11301
- const [isDark, setIsDark] = React36.useState(false);
11302
- React36.useEffect(() => {
11427
+ const [visible, setVisible] = React37.useState(true);
11428
+ const [isDark, setIsDark] = React37.useState(false);
11429
+ React37.useEffect(() => {
11303
11430
  if (!darkMode) return;
11304
11431
  const checkDarkMode = () => {
11305
11432
  const isDarkMode = document.documentElement.classList.contains("dark") || window.matchMedia("(prefers-color-scheme: dark)").matches;
@@ -11401,7 +11528,7 @@ var Watermark = ({
11401
11528
  var Watermark_default = Watermark;
11402
11529
 
11403
11530
  // ../../components/ui/Timeline.tsx
11404
- var React37 = __toESM(require("react"), 1);
11531
+ var React38 = __toESM(require("react"), 1);
11405
11532
  var import_lucide_react25 = require("lucide-react");
11406
11533
  var import_jsx_runtime44 = require("react/jsx-runtime");
11407
11534
  var SIZE_STYLE = {
@@ -11454,7 +11581,7 @@ var STATUS_COLOR = {
11454
11581
  error: "bg-destructive",
11455
11582
  info: "bg-info"
11456
11583
  };
11457
- var TimelineContext = React37.createContext(null);
11584
+ var TimelineContext = React38.createContext(null);
11458
11585
  var LINE_STYLE_MAP = {
11459
11586
  solid: "border-solid",
11460
11587
  dashed: "border-dashed",
@@ -11482,7 +11609,7 @@ var Marker = ({ index, last, size, color, status = "default", lineColor, lineSty
11482
11609
  !last && showLine && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: cn("flex-1 border-l-2", LINE_STYLE_MAP[lineStyle]), style: { borderColor: lineColor || "hsl(var(--border))" } })
11483
11610
  ] });
11484
11611
  };
11485
- var TimelineRoot = React37.forwardRef(
11612
+ var TimelineRoot = React38.forwardRef(
11486
11613
  ({
11487
11614
  align = "left",
11488
11615
  variant = "default",
@@ -11512,7 +11639,7 @@ var TimelineRoot = React37.forwardRef(
11512
11639
  }
11513
11640
  );
11514
11641
  TimelineRoot.displayName = "Timeline";
11515
- var TimelineItem = React37.forwardRef(
11642
+ var TimelineItem = React38.forwardRef(
11516
11643
  ({
11517
11644
  title,
11518
11645
  description,
@@ -11531,11 +11658,11 @@ var TimelineItem = React37.forwardRef(
11531
11658
  children,
11532
11659
  ...rest
11533
11660
  }, ref) => {
11534
- const ctx = React37.useContext(TimelineContext);
11661
+ const ctx = React38.useContext(TimelineContext);
11535
11662
  const idx = rest["data-index"];
11536
11663
  const isLast = Boolean(rest["data-last"]);
11537
11664
  const sz = SIZE_STYLE[ctx.size];
11538
- const [internalExpanded, setInternalExpanded] = React37.useState(false);
11665
+ const [internalExpanded, setInternalExpanded] = React38.useState(false);
11539
11666
  const isExpanded = controlledExpanded !== void 0 ? controlledExpanded : internalExpanded;
11540
11667
  const toggleExpanded = () => {
11541
11668
  const newExpanded = !isExpanded;
@@ -11677,7 +11804,7 @@ var Timeline = Object.assign(TimelineRoot, { Item: TimelineItem });
11677
11804
  var Timeline_default = Timeline;
11678
11805
 
11679
11806
  // ../../components/ui/ColorPicker.tsx
11680
- var React38 = __toESM(require("react"), 1);
11807
+ var React39 = __toESM(require("react"), 1);
11681
11808
  var import_lucide_react26 = require("lucide-react");
11682
11809
  var import_jsx_runtime45 = require("react/jsx-runtime");
11683
11810
  var clamp4 = (n, min, max) => Math.max(min, Math.min(max, n));
@@ -11871,12 +11998,12 @@ function ColorPicker({
11871
11998
  }) {
11872
11999
  const isControlled = value !== void 0;
11873
12000
  const initial = parseAnyColor(isControlled ? value : defaultValue) || { r: 79, g: 70, b: 229, a: 1 };
11874
- const [rgba, setRgba] = React38.useState(initial);
11875
- const [open, setOpen] = React38.useState(false);
11876
- const [text, setText] = React38.useState(() => formatOutput(initial, withAlpha, format));
11877
- const [copied, setCopied] = React38.useState(false);
11878
- const [recentColors, setRecentColors] = React38.useState([]);
11879
- React38.useEffect(() => {
12001
+ const [rgba, setRgba] = React39.useState(initial);
12002
+ const [open, setOpen] = React39.useState(false);
12003
+ const [text, setText] = React39.useState(() => formatOutput(initial, withAlpha, format));
12004
+ const [copied, setCopied] = React39.useState(false);
12005
+ const [recentColors, setRecentColors] = React39.useState([]);
12006
+ React39.useEffect(() => {
11880
12007
  if (isControlled) {
11881
12008
  const parsed = parseAnyColor(value);
11882
12009
  if (parsed) {
@@ -14828,10 +14955,10 @@ function DataTable({
14828
14955
  var DataTable_default = DataTable;
14829
14956
 
14830
14957
  // ../../components/ui/Form.tsx
14831
- var React53 = __toESM(require("react"), 1);
14958
+ var React54 = __toESM(require("react"), 1);
14832
14959
  var import_react_hook_form = require("react-hook-form");
14833
14960
  var import_jsx_runtime61 = require("react/jsx-runtime");
14834
- var FormConfigContext = React53.createContext({ size: "md" });
14961
+ var FormConfigContext = React54.createContext({ size: "md" });
14835
14962
  var FormWrapper = ({
14836
14963
  children,
14837
14964
  onSubmit,
@@ -14844,7 +14971,7 @@ var FormWrapper = ({
14844
14971
  const methods = (0, import_react_hook_form.useForm)({
14845
14972
  defaultValues: initialValues
14846
14973
  });
14847
- React53.useEffect(() => {
14974
+ React54.useEffect(() => {
14848
14975
  if (initialValues) {
14849
14976
  methods.reset(initialValues);
14850
14977
  }
@@ -14853,15 +14980,15 @@ var FormWrapper = ({
14853
14980
  return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_react_hook_form.FormProvider, { ...methods, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(FormConfigContext.Provider, { value: { size }, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("form", { onSubmit: methods.handleSubmit(onSubmit), className, ...formProps, children }) }) });
14854
14981
  };
14855
14982
  var Form = FormWrapper;
14856
- var FormFieldContext = React53.createContext({});
14983
+ var FormFieldContext = React54.createContext({});
14857
14984
  var FormField = ({
14858
14985
  ...props
14859
14986
  }) => {
14860
14987
  return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_react_hook_form.Controller, { ...props }) });
14861
14988
  };
14862
14989
  var useFormField = () => {
14863
- const fieldContext = React53.useContext(FormFieldContext);
14864
- const itemContext = React53.useContext(FormItemContext);
14990
+ const fieldContext = React54.useContext(FormFieldContext);
14991
+ const itemContext = React54.useContext(FormItemContext);
14865
14992
  const { getFieldState, formState } = (0, import_react_hook_form.useFormContext)();
14866
14993
  if (!fieldContext) {
14867
14994
  try {
@@ -14882,16 +15009,16 @@ var useFormField = () => {
14882
15009
  ...fieldState
14883
15010
  };
14884
15011
  };
14885
- var FormItemContext = React53.createContext({});
14886
- var FormItem = React53.forwardRef(({ className, ...props }, ref) => {
14887
- const id = React53.useId();
15012
+ var FormItemContext = React54.createContext({});
15013
+ var FormItem = React54.forwardRef(({ className, ...props }, ref) => {
15014
+ const id = React54.useId();
14888
15015
  return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { ref, className: cn("space-y-2", className), ...props }) });
14889
15016
  });
14890
15017
  FormItem.displayName = "FormItem";
14891
- var FormLabel = React53.forwardRef(
15018
+ var FormLabel = React54.forwardRef(
14892
15019
  ({ className, children, required, ...props }, ref) => {
14893
15020
  const { error, formItemId } = useFormField();
14894
- const config = React53.useContext(FormConfigContext);
15021
+ const config = React54.useContext(FormConfigContext);
14895
15022
  const sizeClass = config.size === "sm" ? "text-xs" : config.size === "lg" ? "text-base" : "text-sm";
14896
15023
  return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(Label, { ref, className: cn(sizeClass, error && "text-destructive", className), htmlFor: formItemId, ...props, children: [
14897
15024
  children,
@@ -14900,7 +15027,7 @@ var FormLabel = React53.forwardRef(
14900
15027
  }
14901
15028
  );
14902
15029
  FormLabel.displayName = "FormLabel";
14903
- var FormControl = React53.forwardRef(({ ...props }, ref) => {
15030
+ var FormControl = React54.forwardRef(({ ...props }, ref) => {
14904
15031
  const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
14905
15032
  return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
14906
15033
  "div",
@@ -14914,12 +15041,12 @@ var FormControl = React53.forwardRef(({ ...props }, ref) => {
14914
15041
  );
14915
15042
  });
14916
15043
  FormControl.displayName = "FormControl";
14917
- var FormDescription = React53.forwardRef(({ className, ...props }, ref) => {
15044
+ var FormDescription = React54.forwardRef(({ className, ...props }, ref) => {
14918
15045
  const { formDescriptionId } = useFormField();
14919
15046
  return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { ref, id: formDescriptionId, className: cn("text-sm text-muted-foreground", className), ...props });
14920
15047
  });
14921
15048
  FormDescription.displayName = "FormDescription";
14922
- var FormMessage = React53.forwardRef(({ className, children, ...props }, ref) => {
15049
+ var FormMessage = React54.forwardRef(({ className, children, ...props }, ref) => {
14923
15050
  const { error, formMessageId } = useFormField();
14924
15051
  const body = error ? String(error?.message) : children;
14925
15052
  if (!body) {
@@ -14928,7 +15055,7 @@ var FormMessage = React53.forwardRef(({ className, children, ...props }, ref) =>
14928
15055
  return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { ref, id: formMessageId, className: cn("text-sm font-medium text-destructive", className), ...props, children: body });
14929
15056
  });
14930
15057
  FormMessage.displayName = "FormMessage";
14931
- var FormInput = React53.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
15058
+ var FormInput = React54.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
14932
15059
  FormField,
14933
15060
  {
14934
15061
  name,
@@ -14939,7 +15066,7 @@ var FormInput = React53.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */
14939
15066
  }
14940
15067
  ) }));
14941
15068
  FormInput.displayName = "FormInput";
14942
- var FormCheckbox = React53.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
15069
+ var FormCheckbox = React54.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
14943
15070
  FormField,
14944
15071
  {
14945
15072
  name,
@@ -14963,9 +15090,9 @@ var FormCheckbox = React53.forwardRef(({ name, ...props }, ref) => /* @__PURE__
14963
15090
  }
14964
15091
  ) }));
14965
15092
  FormCheckbox.displayName = "FormCheckbox";
14966
- var FormActions = React53.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { ref, className: cn("flex gap-2 justify-end", className), ...props }));
15093
+ var FormActions = React54.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { ref, className: cn("flex gap-2 justify-end", className), ...props }));
14967
15094
  FormActions.displayName = "FormActions";
14968
- var FormSubmitButton = React53.forwardRef(
15095
+ var FormSubmitButton = React54.forwardRef(
14969
15096
  ({ children, loading: loading2, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Button_default, { ref, type: "submit", size: props.size ?? size, disabled: loading2, ...props, children }) })
14970
15097
  );
14971
15098
  FormSubmitButton.displayName = "FormSubmitButton";
@@ -15747,7 +15874,7 @@ var VARIANT_STYLES_ALERT = {
15747
15874
  };
15748
15875
 
15749
15876
  // src/contexts/TranslationContext.tsx
15750
- var React55 = __toESM(require("react"), 1);
15877
+ var React56 = __toESM(require("react"), 1);
15751
15878
 
15752
15879
  // locales/en.json
15753
15880
  var en_default = {
@@ -16101,9 +16228,9 @@ var defaultTranslations2 = {
16101
16228
  ko: ko_default,
16102
16229
  ja: ja_default
16103
16230
  };
16104
- var TranslationContext2 = React55.createContext(null);
16231
+ var TranslationContext2 = React56.createContext(null);
16105
16232
  var TranslationProvider = ({ children, locale = "en", translations }) => {
16106
- const t = React55.useCallback(
16233
+ const t = React56.useCallback(
16107
16234
  (namespace) => {
16108
16235
  return (key) => {
16109
16236
  const mergedTranslations = {
@@ -16131,7 +16258,7 @@ var TranslationProvider = ({ children, locale = "en", translations }) => {
16131
16258
  return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(TranslationContext2.Provider, { value: { locale, t }, children });
16132
16259
  };
16133
16260
  var useUnderverseTranslations = (namespace) => {
16134
- const context = React55.useContext(TranslationContext2);
16261
+ const context = React56.useContext(TranslationContext2);
16135
16262
  if (!context) {
16136
16263
  return (key) => {
16137
16264
  const parts = namespace.split(".");
@@ -16153,12 +16280,12 @@ var useUnderverseTranslations = (namespace) => {
16153
16280
  return context.t(namespace);
16154
16281
  };
16155
16282
  var useUnderverseLocale = () => {
16156
- const context = React55.useContext(TranslationContext2);
16283
+ const context = React56.useContext(TranslationContext2);
16157
16284
  return context?.locale || "en";
16158
16285
  };
16159
16286
 
16160
16287
  // src/hooks/useSmartTranslations.tsx
16161
- var React56 = __toESM(require("react"), 1);
16288
+ var React57 = __toESM(require("react"), 1);
16162
16289
  var import_jsx_runtime68 = require("react/jsx-runtime");
16163
16290
  var nextIntlHooks = null;
16164
16291
  try {
@@ -16170,12 +16297,12 @@ try {
16170
16297
  } catch {
16171
16298
  nextIntlHooks = null;
16172
16299
  }
16173
- var ForceInternalContext = React56.createContext(false);
16300
+ var ForceInternalContext = React57.createContext(false);
16174
16301
  var ForceInternalTranslationsProvider = ({ children }) => {
16175
16302
  return /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(ForceInternalContext.Provider, { value: true, children });
16176
16303
  };
16177
16304
  function useSmartTranslations(namespace) {
16178
- const forceInternal = React56.useContext(ForceInternalContext);
16305
+ const forceInternal = React57.useContext(ForceInternalContext);
16179
16306
  const internalT = useUnderverseTranslations(namespace);
16180
16307
  if (forceInternal || !nextIntlHooks?.useTranslations) {
16181
16308
  return internalT;
@@ -16188,7 +16315,7 @@ function useSmartTranslations(namespace) {
16188
16315
  }
16189
16316
  }
16190
16317
  function useSmartLocale() {
16191
- const forceInternal = React56.useContext(ForceInternalContext);
16318
+ const forceInternal = React57.useContext(ForceInternalContext);
16192
16319
  const internalLocale = useUnderverseLocale();
16193
16320
  if (forceInternal || !nextIntlHooks?.useLocale) {
16194
16321
  return internalLocale;