@underverse-ui/underverse 0.2.109 → 0.2.111

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -818,6 +818,10 @@ interface TimePickerProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "
818
818
  label: string;
819
819
  time: string;
820
820
  }>;
821
+ /** Alias for minTime (e.g., "09:00") */
822
+ min?: string;
823
+ /** Alias for maxTime (e.g., "18:00") */
824
+ max?: string;
821
825
  /** Minimum allowed time (e.g., "09:00") */
822
826
  minTime?: string;
823
827
  /** Maximum allowed time (e.g., "18:00") */
@@ -837,7 +841,7 @@ interface TimePickerProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "
837
841
  /** Callback when popover closes */
838
842
  onClose?: () => void;
839
843
  }
840
- declare function TimePicker({ value, defaultValue, onChange, placeholder, disabled, size, label, required, format, includeSeconds, minuteStep, secondStep, clearable, variant, matchTriggerWidth, showNow, showPresets, allowManualInput, customPresets, minTime, maxTime, disabledTimes, error, success, helperText, animate, onOpen, onClose, className, ...rest }: TimePickerProps): react_jsx_runtime.JSX.Element;
844
+ declare function TimePicker({ value, defaultValue, onChange, placeholder, disabled, size, label, required, format, includeSeconds, minuteStep, secondStep, clearable, variant, matchTriggerWidth, showNow, showPresets, allowManualInput, customPresets, min, max, minTime, maxTime, disabledTimes, error, success, helperText, animate, onOpen, onClose, className, ...rest }: TimePickerProps): react_jsx_runtime.JSX.Element;
841
845
 
842
846
  type SelectMode = "single" | "multiple" | "range";
843
847
  type Variant$3 = "default" | "bordered" | "card" | "minimal";
package/dist/index.d.ts CHANGED
@@ -818,6 +818,10 @@ interface TimePickerProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "
818
818
  label: string;
819
819
  time: string;
820
820
  }>;
821
+ /** Alias for minTime (e.g., "09:00") */
822
+ min?: string;
823
+ /** Alias for maxTime (e.g., "18:00") */
824
+ max?: string;
821
825
  /** Minimum allowed time (e.g., "09:00") */
822
826
  minTime?: string;
823
827
  /** Maximum allowed time (e.g., "18:00") */
@@ -837,7 +841,7 @@ interface TimePickerProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "
837
841
  /** Callback when popover closes */
838
842
  onClose?: () => void;
839
843
  }
840
- declare function TimePicker({ value, defaultValue, onChange, placeholder, disabled, size, label, required, format, includeSeconds, minuteStep, secondStep, clearable, variant, matchTriggerWidth, showNow, showPresets, allowManualInput, customPresets, minTime, maxTime, disabledTimes, error, success, helperText, animate, onOpen, onClose, className, ...rest }: TimePickerProps): react_jsx_runtime.JSX.Element;
844
+ declare function TimePicker({ value, defaultValue, onChange, placeholder, disabled, size, label, required, format, includeSeconds, minuteStep, secondStep, clearable, variant, matchTriggerWidth, showNow, showPresets, allowManualInput, customPresets, min, max, minTime, maxTime, disabledTimes, error, success, helperText, animate, onOpen, onClose, className, ...rest }: TimePickerProps): react_jsx_runtime.JSX.Element;
841
845
 
842
846
  type SelectMode = "single" | "multiple" | "range";
843
847
  type Variant$3 = "default" | "bordered" | "card" | "minimal";
package/dist/index.js CHANGED
@@ -6021,8 +6021,8 @@ var DatePicker = ({
6021
6021
  "div",
6022
6022
  {
6023
6023
  className: cn(
6024
- "flex items-center justify-center rounded-lg p-1.5 transition-all duration-300",
6025
- isOpen ? "bg-primary/15 text-primary" : "bg-muted/50 text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary"
6024
+ "flex items-center justify-center transition-colors duration-300",
6025
+ isOpen ? "text-primary" : "text-muted-foreground group-hover:text-primary"
6026
6026
  ),
6027
6027
  children: /* @__PURE__ */ jsx29(Calendar, { className: cn(size === "sm" ? "h-3.5 w-3.5" : "h-4 w-4", "transition-transform duration-300", isOpen && "scale-110") })
6028
6028
  }
@@ -6317,9 +6317,8 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
6317
6317
  "div",
6318
6318
  {
6319
6319
  className: cn(
6320
- "flex items-center justify-center rounded-lg transition-all duration-300",
6321
- size === "sm" ? "p-1" : "p-1.5",
6322
- isOpen ? "bg-primary/15 text-primary" : "bg-muted/50 text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary"
6320
+ "flex items-center justify-center transition-colors duration-300",
6321
+ isOpen ? "text-primary" : "text-muted-foreground group-hover:text-primary"
6323
6322
  ),
6324
6323
  children: /* @__PURE__ */ jsx29(Calendar, { className: cn("transition-transform duration-300", size === "sm" ? "h-3 w-3" : "h-4 w-4", isOpen && "scale-110") })
6325
6324
  }
@@ -7393,6 +7392,8 @@ function TimePicker({
7393
7392
  showPresets = false,
7394
7393
  allowManualInput = false,
7395
7394
  customPresets = [],
7395
+ min,
7396
+ max,
7396
7397
  minTime,
7397
7398
  maxTime,
7398
7399
  disabledTimes,
@@ -7429,37 +7430,65 @@ function TimePicker({
7429
7430
  },
7430
7431
  [disabledTimes]
7431
7432
  );
7433
+ const resolvedMinTime = minTime ?? min;
7434
+ const resolvedMaxTime = maxTime ?? max;
7435
+ const toSeconds = React25.useCallback(
7436
+ (p) => {
7437
+ let h = p.h;
7438
+ if (format === "12") {
7439
+ const period = p.p ?? (h >= 12 ? "PM" : "AM");
7440
+ const base = h % 12;
7441
+ h = period === "PM" ? base + 12 : base;
7442
+ }
7443
+ return h * 3600 + p.m * 60 + (includeSeconds ? p.s : 0);
7444
+ },
7445
+ [format, includeSeconds]
7446
+ );
7432
7447
  const isTimeInRange = React25.useCallback(
7433
7448
  (timeStr) => {
7434
- if (!minTime && !maxTime) return true;
7449
+ if (!resolvedMinTime && !resolvedMaxTime) return true;
7435
7450
  const parsed = parseTime(timeStr, format, includeSeconds);
7436
7451
  if (!parsed) return true;
7437
- if (minTime) {
7438
- const min = parseTime(minTime, format, includeSeconds);
7439
- if (min) {
7440
- const currentMinutes = parsed.h * 60 + parsed.m;
7441
- const minMinutes = min.h * 60 + min.m;
7442
- if (currentMinutes < minMinutes) return false;
7443
- }
7452
+ const current = toSeconds(parsed);
7453
+ if (resolvedMinTime) {
7454
+ const minParsed = parseTime(resolvedMinTime, format, includeSeconds);
7455
+ if (minParsed && current < toSeconds(minParsed)) return false;
7444
7456
  }
7445
- if (maxTime) {
7446
- const max = parseTime(maxTime, format, includeSeconds);
7447
- if (max) {
7448
- const currentMinutes = parsed.h * 60 + parsed.m;
7449
- const maxMinutes = max.h * 60 + max.m;
7450
- if (currentMinutes > maxMinutes) return false;
7451
- }
7457
+ if (resolvedMaxTime) {
7458
+ const maxParsed = parseTime(resolvedMaxTime, format, includeSeconds);
7459
+ if (maxParsed && current > toSeconds(maxParsed)) return false;
7452
7460
  }
7453
7461
  return true;
7454
7462
  },
7455
- [minTime, maxTime, format, includeSeconds]
7463
+ [format, includeSeconds, resolvedMaxTime, resolvedMinTime, toSeconds]
7464
+ );
7465
+ const canEmit = React25.useCallback(
7466
+ (next) => {
7467
+ const timeStr = next ? formatTime(next, format, includeSeconds) : void 0;
7468
+ if (!timeStr) return true;
7469
+ if (!isTimeInRange(timeStr)) return false;
7470
+ if (isTimeDisabled(timeStr)) return false;
7471
+ return true;
7472
+ },
7473
+ [format, includeSeconds, isTimeDisabled, isTimeInRange]
7474
+ );
7475
+ const emit = React25.useCallback(
7476
+ (next) => {
7477
+ const timeStr = next ? formatTime(next, format, includeSeconds) : void 0;
7478
+ if (!canEmit(next)) return;
7479
+ onChange?.(timeStr);
7480
+ },
7481
+ [canEmit, format, includeSeconds, onChange]
7482
+ );
7483
+ const tryUpdate = React25.useCallback(
7484
+ (next) => {
7485
+ if (!canEmit(next)) return false;
7486
+ setParts(next);
7487
+ emit(next);
7488
+ return true;
7489
+ },
7490
+ [canEmit, emit]
7456
7491
  );
7457
- const emit = (next) => {
7458
- const timeStr = next ? formatTime(next, format, includeSeconds) : void 0;
7459
- if (timeStr && !isTimeInRange(timeStr)) return;
7460
- if (timeStr && isTimeDisabled(timeStr)) return;
7461
- onChange?.(timeStr);
7462
- };
7463
7492
  const handleOpenChange = (newOpen) => {
7464
7493
  setOpen(newOpen);
7465
7494
  if (newOpen) {
@@ -7510,8 +7539,7 @@ function TimePicker({
7510
7539
  if (e.key === "ArrowLeft") setFocusedColumn(includeSeconds ? "second" : "minute");
7511
7540
  break;
7512
7541
  }
7513
- setParts(newParts);
7514
- emit(newParts);
7542
+ tryUpdate(newParts);
7515
7543
  };
7516
7544
  const setNow = () => {
7517
7545
  const now2 = /* @__PURE__ */ new Date();
@@ -7524,8 +7552,7 @@ function TimePicker({
7524
7552
  } else {
7525
7553
  next = { h, m, s };
7526
7554
  }
7527
- setParts(next);
7528
- emit(next);
7555
+ tryUpdate(next);
7529
7556
  };
7530
7557
  const setPreset = (preset) => {
7531
7558
  const { h, m, s } = PRESETS[preset];
@@ -7535,8 +7562,7 @@ function TimePicker({
7535
7562
  } else {
7536
7563
  next = { h, m, s };
7537
7564
  }
7538
- setParts(next);
7539
- emit(next);
7565
+ tryUpdate(next);
7540
7566
  };
7541
7567
  const handleManualInput = (input) => {
7542
7568
  setManualInput(input);
@@ -7544,16 +7570,14 @@ function TimePicker({
7544
7570
  if (parsed) {
7545
7571
  const timeStr = formatTime(parsed, format, includeSeconds);
7546
7572
  if (isTimeInRange(timeStr) && !isTimeDisabled(timeStr)) {
7547
- setParts(parsed);
7548
- emit(parsed);
7573
+ tryUpdate(parsed);
7549
7574
  }
7550
7575
  }
7551
7576
  };
7552
7577
  const handleCustomPreset = (time) => {
7553
7578
  const parsed = parseTime(time, format, includeSeconds);
7554
7579
  if (parsed) {
7555
- setParts(parsed);
7556
- emit(parsed);
7580
+ tryUpdate(parsed);
7557
7581
  }
7558
7582
  };
7559
7583
  const hours = format === "24" ? Array.from({ length: 24 }, (_, i) => i) : Array.from({ length: 12 }, (_, i) => i + 1);
@@ -7674,8 +7698,7 @@ function TimePicker({
7674
7698
  return period === "PM" ? base + 12 : base;
7675
7699
  })();
7676
7700
  const next = { ...parts, h: nextH, p: format === "12" ? period : parts.p };
7677
- setParts(next);
7678
- emit(next);
7701
+ tryUpdate(next);
7679
7702
  };
7680
7703
  const timePickerContent = /* @__PURE__ */ jsxs26("div", { className: panelSz.stackGap, children: [
7681
7704
  /* @__PURE__ */ jsx31("div", { className: "flex items-center justify-center py-1", children: /* @__PURE__ */ jsx31("span", { className: cn(panelSz.timeText, "font-bold tabular-nums tracking-wide text-foreground underline underline-offset-8 decoration-primary/60"), children: display }) }),
@@ -7781,8 +7804,7 @@ function TimePicker({
7781
7804
  valueIndex: minuteIndex,
7782
7805
  onSelect: (m) => {
7783
7806
  const next = { ...parts, m };
7784
- setParts(next);
7785
- emit(next);
7807
+ tryUpdate(next);
7786
7808
  },
7787
7809
  scrollRef: minuteScrollRef,
7788
7810
  itemHeight,
@@ -7810,8 +7832,7 @@ function TimePicker({
7810
7832
  valueIndex: secondIndex,
7811
7833
  onSelect: (s) => {
7812
7834
  const next = { ...parts, s };
7813
- setParts(next);
7814
- emit(next);
7835
+ tryUpdate(next);
7815
7836
  },
7816
7837
  scrollRef: secondScrollRef,
7817
7838
  itemHeight,
@@ -7864,8 +7885,7 @@ function TimePicker({
7864
7885
  if (pVal === "AM" && hour >= 12) hour -= 12;
7865
7886
  if (pVal === "PM" && hour < 12) hour += 12;
7866
7887
  const next = { ...parts, p: pVal, h: hour };
7867
- setParts(next);
7868
- emit(next);
7888
+ tryUpdate(next);
7869
7889
  },
7870
7890
  children: [
7871
7891
  isSelected && /* @__PURE__ */ jsx31("div", { className: "absolute inset-0 bg-linear-to-tr from-white/20 to-transparent" }),
@@ -8702,7 +8722,7 @@ function CalendarTimelineHeader(props) {
8702
8722
  return /* @__PURE__ */ jsxs29("div", { className: "sticky top-0 z-30 bg-linear-to-b from-background via-background to-background/95 border-b border-border/40 backdrop-blur-xl", children: [
8703
8723
  /* @__PURE__ */ jsxs29("div", { className: cn("flex items-center justify-between gap-4", sizeConfig.headerPaddingClass), children: [
8704
8724
  /* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-1.5 min-w-0", children: [
8705
- /* @__PURE__ */ jsxs29("div", { className: "flex items-center bg-muted/40 rounded-xl p-1 gap-0.5", children: [
8725
+ /* @__PURE__ */ jsxs29("div", { className: "flex items-center bg-muted/40 rounded-full p-1 gap-0.5", children: [
8706
8726
  /* @__PURE__ */ jsx34(
8707
8727
  Button_default,
8708
8728
  {
@@ -8710,7 +8730,7 @@ function CalendarTimelineHeader(props) {
8710
8730
  size: "icon",
8711
8731
  onClick: () => navigate(-1),
8712
8732
  "aria-label": labels.prev,
8713
- className: cn(sizeConfig.controlButtonIconClass, "rounded-lg hover:bg-background/80 transition-all duration-200"),
8733
+ className: cn(sizeConfig.controlButtonIconClass, "rounded-full hover:bg-background/80 transition-all duration-200"),
8714
8734
  children: /* @__PURE__ */ jsx34(ChevronLeft4, { className: "h-4 w-4" })
8715
8735
  }
8716
8736
  ),
@@ -8720,7 +8740,7 @@ function CalendarTimelineHeader(props) {
8720
8740
  variant: "ghost",
8721
8741
  size: "sm",
8722
8742
  onClick: goToday,
8723
- className: cn(sizeConfig.controlButtonTextClass, "rounded-lg hover:bg-background/80 font-medium transition-all duration-200"),
8743
+ className: cn(sizeConfig.controlButtonTextClass, "rounded-full hover:bg-background/80 font-medium transition-all duration-200"),
8724
8744
  children: labels.today
8725
8745
  }
8726
8746
  ),
@@ -8731,7 +8751,7 @@ function CalendarTimelineHeader(props) {
8731
8751
  size: "icon",
8732
8752
  onClick: () => navigate(1),
8733
8753
  "aria-label": labels.next,
8734
- className: cn(sizeConfig.controlButtonIconClass, "rounded-lg hover:bg-background/80 transition-all duration-200"),
8754
+ className: cn(sizeConfig.controlButtonIconClass, "rounded-full hover:bg-background/80 transition-all duration-200"),
8735
8755
  children: /* @__PURE__ */ jsx34(ChevronRight5, { className: "h-4 w-4" })
8736
8756
  }
8737
8757
  )
@@ -8747,11 +8767,11 @@ function CalendarTimelineHeader(props) {
8747
8767
  icon: Plus,
8748
8768
  disabled: newEventDisabled,
8749
8769
  onClick: onNewEventClick,
8750
- className: cn(sizeConfig.controlButtonTextClass, "rounded-lg font-medium transition-all duration-200 gap-1.5"),
8770
+ className: cn(sizeConfig.controlButtonTextClass, "rounded-full font-medium transition-all duration-200 gap-1.5"),
8751
8771
  children: /* @__PURE__ */ jsx34("span", { className: "hidden sm:inline", children: newEventLabel })
8752
8772
  }
8753
8773
  ) : null,
8754
- /* @__PURE__ */ jsx34("div", { className: "flex items-center bg-muted/40 rounded-xl p-1 gap-0.5", children: ["month", "week", "day"].map((v) => /* @__PURE__ */ jsxs29(
8774
+ /* @__PURE__ */ jsx34("div", { className: "flex items-center bg-muted/40 rounded-full p-1 gap-0.5", children: ["month", "week", "day"].map((v) => /* @__PURE__ */ jsxs29(
8755
8775
  Button_default,
8756
8776
  {
8757
8777
  variant: activeView === v ? "default" : "ghost",
@@ -8759,7 +8779,7 @@ function CalendarTimelineHeader(props) {
8759
8779
  onClick: () => setView(v),
8760
8780
  className: cn(
8761
8781
  sizeConfig.controlButtonTextClass,
8762
- "rounded-lg font-medium transition-all duration-200 gap-1.5",
8782
+ "rounded-full font-medium transition-all duration-200 gap-1.5",
8763
8783
  activeView === v ? "bg-primary text-primary-foreground shadow-sm shadow-primary/25" : "hover:bg-background/80 text-muted-foreground hover:text-foreground"
8764
8784
  ),
8765
8785
  children: [
@@ -10194,7 +10214,7 @@ function CalendarTimeline({
10194
10214
  "div",
10195
10215
  {
10196
10216
  className: cn(
10197
- "border border-border/40 rounded-2xl overflow-hidden bg-background/95 backdrop-blur-sm",
10217
+ "border border-border/40 rounded-2xl md:rounded-3xl overflow-hidden bg-background/95 backdrop-blur-sm",
10198
10218
  "shadow-sm hover:shadow-md transition-shadow duration-300",
10199
10219
  densityClass,
10200
10220
  className
@@ -10336,16 +10356,19 @@ function CalendarTimeline({
10336
10356
  const resource = resourceById.get(ev.resourceId);
10337
10357
  const tooltipTitle = ev.title || ev.id;
10338
10358
  const shouldCompact = activeView === "day" && dayEventStyle === "compact";
10359
+ const eventInsetX = 2;
10360
+ const leftInset = left + eventInsetX;
10361
+ const widthInset = Math.max(1, width - eventInsetX * 2);
10339
10362
  const defaultMaxVisual = clamp4(Math.round(fixedSlotWidth * 1.2), 160, 360);
10340
10363
  const maxVisual = clamp4(Math.round(dayEventMaxWidth ?? defaultMaxVisual), 80, 1200);
10341
- const visualWidth = shouldCompact ? Math.min(width, maxVisual) : width;
10342
- const isClipped = shouldCompact && width > visualWidth + 1;
10364
+ const visualWidth = shouldCompact ? Math.min(widthInset, maxVisual) : widthInset;
10365
+ const isClipped = shouldCompact && widthInset > visualWidth + 1;
10343
10366
  const block = /* @__PURE__ */ jsxs33(
10344
10367
  "div",
10345
10368
  {
10346
10369
  className: cn("absolute select-none cursor-pointer", isPreview && "z-10"),
10347
10370
  "data-uv-ct-event": true,
10348
- style: { left, top, width, height: layout.eventHeight },
10371
+ style: { left: leftInset, top, width: widthInset, height: layout.eventHeight },
10349
10372
  role: "button",
10350
10373
  tabIndex: 0,
10351
10374
  "aria-label": aria,
@@ -10430,11 +10453,17 @@ function CalendarTimeline({
10430
10453
  const endIdx = clamp4(binarySearchFirstGE(slotStarts, preview.end), startIdx + 1, slots.length);
10431
10454
  const left = slotLefts[startIdx] ?? 0;
10432
10455
  const width = Math.max(1, (slotLefts[endIdx] ?? 0) - (slotLefts[startIdx] ?? 0));
10456
+ const eventInsetX = 2;
10433
10457
  return /* @__PURE__ */ jsx38(
10434
10458
  "div",
10435
10459
  {
10436
10460
  className: "absolute rounded-lg border-2 border-dashed border-primary/60 bg-primary/10 backdrop-blur-sm animate-pulse",
10437
- style: { left, top: layout.baseTop, width, height: layout.eventHeight }
10461
+ style: {
10462
+ left: left + eventInsetX,
10463
+ top: layout.baseTop,
10464
+ width: Math.max(1, width - eventInsetX * 2),
10465
+ height: layout.eventHeight
10466
+ }
10438
10467
  }
10439
10468
  );
10440
10469
  })() : null,