@underverse-ui/underverse 1.0.91 → 1.0.93

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
@@ -780,6 +780,8 @@ interface OverlayScrollbarBehavior {
780
780
  autoHideDelay: number;
781
781
  dragScroll: boolean;
782
782
  clickScroll: boolean;
783
+ overflowX: "hidden" | "visible" | "scroll" | "visible-hidden" | "visible-scroll";
784
+ overflowY: "hidden" | "visible" | "scroll" | "visible-hidden" | "visible-scroll";
783
785
  exclude: string;
784
786
  }
785
787
 
@@ -790,7 +792,7 @@ interface OverlayScrollbarProviderProps extends Partial<OverlayScrollbarBehavior
790
792
  }
791
793
  interface UseOverlayScrollbarTargetOptions extends Partial<OverlayScrollbarBehavior> {
792
794
  }
793
- declare function OverlayScrollbarProvider({ enabled, theme, visibility, autoHide, autoHideDelay, dragScroll, clickScroll, exclude, selector, children, }?: OverlayScrollbarProviderProps): react_jsx_runtime.JSX.Element;
795
+ declare function OverlayScrollbarProvider({ enabled, theme, visibility, autoHide, autoHideDelay, dragScroll, clickScroll, overflowX, overflowY, exclude, selector, children, }?: OverlayScrollbarProviderProps): react_jsx_runtime.JSX.Element;
794
796
  declare function useOverlayScrollbarTarget<T extends HTMLElement>(targetRef: React__default.RefObject<T | null>, options?: UseOverlayScrollbarTargetOptions): void;
795
797
 
796
798
  interface OverlayScrollAreaProps extends React__default.HTMLAttributes<HTMLDivElement> {
@@ -2249,6 +2251,7 @@ declare const loading: LoadingManager;
2249
2251
  type FilterType = "text" | "select" | "date";
2250
2252
  type DataTableSize = "sm" | "md" | "lg";
2251
2253
  type DataTableDensity = "compact" | "normal" | "comfortable";
2254
+ type DataTableHorizontalMode = "auto" | "scroll" | "fit";
2252
2255
  type DataTableColumn<T> = {
2253
2256
  key: string;
2254
2257
  title: React__default.ReactNode;
@@ -2324,6 +2327,13 @@ interface DataTableProps<T> {
2324
2327
  stickyHeader?: boolean;
2325
2328
  /** Chiều cao tối đa của bảng khi bật stickyHeader (mặc định: 500px) */
2326
2329
  maxHeight?: number | string;
2330
+ /**
2331
+ * Horizontal sizing strategy for the table viewport.
2332
+ * - "auto": default, prefer fitting the container and only scroll when content truly overflows
2333
+ * - "scroll": preserve explicit column widths and force horizontal scrolling via min-width aggregation
2334
+ * - "fit": use fixed table layout and suppress horizontal scrolling
2335
+ */
2336
+ horizontalMode?: DataTableHorizontalMode;
2327
2337
  /** Clip overflow của outer wrapper. Tắt khi cần cho phép shadow/focus ring tràn ra ngoài. */
2328
2338
  overflowHidden?: boolean;
2329
2339
  /** Enable OverlayScrollbars on table viewport. Default: false */
@@ -2333,7 +2343,7 @@ interface DataTableProps<T> {
2333
2343
  labels?: DataTableLabels;
2334
2344
  }
2335
2345
 
2336
- declare function DataTable<T extends Record<string, any>>({ columns, data, rowKey, loading, total, page, pageSize, pageSizeOptions, onQueryChange, caption, toolbar, size, enableColumnVisibilityToggle, enableDensityToggle, enableHeaderAlignToggle, striped, columnDividers, className, storageKey, stickyHeader, maxHeight, overflowHidden, useOverlayScrollbar, enableHeaderAutoFit, labels, }: DataTableProps<T>): react_jsx_runtime.JSX.Element;
2346
+ declare function DataTable<T extends Record<string, any>>({ columns, data, rowKey, loading, total, page, pageSize, pageSizeOptions, onQueryChange, caption, toolbar, size, enableColumnVisibilityToggle, enableDensityToggle, enableHeaderAlignToggle, striped, columnDividers, className, storageKey, stickyHeader, maxHeight, horizontalMode, overflowHidden, useOverlayScrollbar, enableHeaderAutoFit, labels, }: DataTableProps<T>): react_jsx_runtime.JSX.Element;
2337
2347
 
2338
2348
  interface TableProps extends React__default.HTMLAttributes<HTMLTableElement> {
2339
2349
  containerClassName?: string;
package/dist/index.d.ts CHANGED
@@ -780,6 +780,8 @@ interface OverlayScrollbarBehavior {
780
780
  autoHideDelay: number;
781
781
  dragScroll: boolean;
782
782
  clickScroll: boolean;
783
+ overflowX: "hidden" | "visible" | "scroll" | "visible-hidden" | "visible-scroll";
784
+ overflowY: "hidden" | "visible" | "scroll" | "visible-hidden" | "visible-scroll";
783
785
  exclude: string;
784
786
  }
785
787
 
@@ -790,7 +792,7 @@ interface OverlayScrollbarProviderProps extends Partial<OverlayScrollbarBehavior
790
792
  }
791
793
  interface UseOverlayScrollbarTargetOptions extends Partial<OverlayScrollbarBehavior> {
792
794
  }
793
- declare function OverlayScrollbarProvider({ enabled, theme, visibility, autoHide, autoHideDelay, dragScroll, clickScroll, exclude, selector, children, }?: OverlayScrollbarProviderProps): react_jsx_runtime.JSX.Element;
795
+ declare function OverlayScrollbarProvider({ enabled, theme, visibility, autoHide, autoHideDelay, dragScroll, clickScroll, overflowX, overflowY, exclude, selector, children, }?: OverlayScrollbarProviderProps): react_jsx_runtime.JSX.Element;
794
796
  declare function useOverlayScrollbarTarget<T extends HTMLElement>(targetRef: React__default.RefObject<T | null>, options?: UseOverlayScrollbarTargetOptions): void;
795
797
 
796
798
  interface OverlayScrollAreaProps extends React__default.HTMLAttributes<HTMLDivElement> {
@@ -2249,6 +2251,7 @@ declare const loading: LoadingManager;
2249
2251
  type FilterType = "text" | "select" | "date";
2250
2252
  type DataTableSize = "sm" | "md" | "lg";
2251
2253
  type DataTableDensity = "compact" | "normal" | "comfortable";
2254
+ type DataTableHorizontalMode = "auto" | "scroll" | "fit";
2252
2255
  type DataTableColumn<T> = {
2253
2256
  key: string;
2254
2257
  title: React__default.ReactNode;
@@ -2324,6 +2327,13 @@ interface DataTableProps<T> {
2324
2327
  stickyHeader?: boolean;
2325
2328
  /** Chiều cao tối đa của bảng khi bật stickyHeader (mặc định: 500px) */
2326
2329
  maxHeight?: number | string;
2330
+ /**
2331
+ * Horizontal sizing strategy for the table viewport.
2332
+ * - "auto": default, prefer fitting the container and only scroll when content truly overflows
2333
+ * - "scroll": preserve explicit column widths and force horizontal scrolling via min-width aggregation
2334
+ * - "fit": use fixed table layout and suppress horizontal scrolling
2335
+ */
2336
+ horizontalMode?: DataTableHorizontalMode;
2327
2337
  /** Clip overflow của outer wrapper. Tắt khi cần cho phép shadow/focus ring tràn ra ngoài. */
2328
2338
  overflowHidden?: boolean;
2329
2339
  /** Enable OverlayScrollbars on table viewport. Default: false */
@@ -2333,7 +2343,7 @@ interface DataTableProps<T> {
2333
2343
  labels?: DataTableLabels;
2334
2344
  }
2335
2345
 
2336
- declare function DataTable<T extends Record<string, any>>({ columns, data, rowKey, loading, total, page, pageSize, pageSizeOptions, onQueryChange, caption, toolbar, size, enableColumnVisibilityToggle, enableDensityToggle, enableHeaderAlignToggle, striped, columnDividers, className, storageKey, stickyHeader, maxHeight, overflowHidden, useOverlayScrollbar, enableHeaderAutoFit, labels, }: DataTableProps<T>): react_jsx_runtime.JSX.Element;
2346
+ declare function DataTable<T extends Record<string, any>>({ columns, data, rowKey, loading, total, page, pageSize, pageSizeOptions, onQueryChange, caption, toolbar, size, enableColumnVisibilityToggle, enableDensityToggle, enableHeaderAlignToggle, striped, columnDividers, className, storageKey, stickyHeader, maxHeight, horizontalMode, overflowHidden, useOverlayScrollbar, enableHeaderAutoFit, labels, }: DataTableProps<T>): react_jsx_runtime.JSX.Element;
2337
2347
 
2338
2348
  interface TableProps extends React__default.HTMLAttributes<HTMLTableElement> {
2339
2349
  containerClassName?: string;
package/dist/index.js CHANGED
@@ -1879,6 +1879,8 @@ var DEFAULT_OVERLAY_SCROLLBAR_BEHAVIOR = {
1879
1879
  autoHideDelay: 600,
1880
1880
  dragScroll: true,
1881
1881
  clickScroll: false,
1882
+ overflowX: "scroll",
1883
+ overflowY: "scroll",
1882
1884
  exclude: DEFAULT_OVERLAY_SCROLLBAR_EXCLUDE
1883
1885
  };
1884
1886
  function resolveOverlayScrollbarBehavior(overrides = {}) {
@@ -1889,6 +1891,10 @@ function resolveOverlayScrollbarBehavior(overrides = {}) {
1889
1891
  }
1890
1892
  function buildOverlayScrollbarOptions(config) {
1891
1893
  return {
1894
+ overflow: {
1895
+ x: config.overflowX,
1896
+ y: config.overflowY
1897
+ },
1892
1898
  scrollbars: {
1893
1899
  theme: config.theme,
1894
1900
  visibility: config.visibility,
@@ -2033,6 +2039,8 @@ function OverlayScrollbarProvider({
2033
2039
  autoHideDelay = DEFAULT_OVERLAY_SCROLLBAR_BEHAVIOR.autoHideDelay,
2034
2040
  dragScroll = DEFAULT_OVERLAY_SCROLLBAR_BEHAVIOR.dragScroll,
2035
2041
  clickScroll = DEFAULT_OVERLAY_SCROLLBAR_BEHAVIOR.clickScroll,
2042
+ overflowX = DEFAULT_OVERLAY_SCROLLBAR_BEHAVIOR.overflowX,
2043
+ overflowY = DEFAULT_OVERLAY_SCROLLBAR_BEHAVIOR.overflowY,
2036
2044
  exclude = DEFAULT_OVERLAY_SCROLLBAR_BEHAVIOR.exclude,
2037
2045
  selector,
2038
2046
  children
@@ -2046,9 +2054,11 @@ function OverlayScrollbarProvider({
2046
2054
  autoHideDelay,
2047
2055
  dragScroll,
2048
2056
  clickScroll,
2057
+ overflowX,
2058
+ overflowY,
2049
2059
  exclude
2050
2060
  }),
2051
- [enabled, theme, visibility, autoHide, autoHideDelay, dragScroll, clickScroll, exclude]
2061
+ [enabled, theme, visibility, autoHide, autoHideDelay, dragScroll, clickScroll, overflowX, overflowY, exclude]
2052
2062
  );
2053
2063
  void selector;
2054
2064
  return /* @__PURE__ */ jsx8(OverlayScrollbarConfigContext.Provider, { value, children: children ?? null });
@@ -2062,6 +2072,8 @@ function useOverlayScrollbarTarget(targetRef, options = {}) {
2062
2072
  const autoHideDelay = options.autoHideDelay ?? inherited.autoHideDelay;
2063
2073
  const dragScroll = options.dragScroll ?? inherited.dragScroll;
2064
2074
  const clickScroll = options.clickScroll ?? inherited.clickScroll;
2075
+ const overflowX = options.overflowX ?? inherited.overflowX;
2076
+ const overflowY = options.overflowY ?? inherited.overflowY;
2065
2077
  const exclude = options.exclude ?? inherited.exclude;
2066
2078
  const resolved = useMemo2(
2067
2079
  () => resolveOverlayScrollbarBehavior({
@@ -2072,9 +2084,11 @@ function useOverlayScrollbarTarget(targetRef, options = {}) {
2072
2084
  autoHideDelay,
2073
2085
  dragScroll,
2074
2086
  clickScroll,
2087
+ overflowX,
2088
+ overflowY,
2075
2089
  exclude
2076
2090
  }),
2077
- [enabled, theme, visibility, autoHide, autoHideDelay, dragScroll, clickScroll, exclude]
2091
+ [enabled, theme, visibility, autoHide, autoHideDelay, dragScroll, clickScroll, overflowX, overflowY, exclude]
2078
2092
  );
2079
2093
  useEffect2(() => {
2080
2094
  if (typeof window === "undefined") return;
@@ -2099,6 +2113,8 @@ function useOverlayScrollbarTarget(targetRef, options = {}) {
2099
2113
  resolved.autoHideDelay,
2100
2114
  resolved.dragScroll,
2101
2115
  resolved.clickScroll,
2116
+ resolved.overflowX,
2117
+ resolved.overflowY,
2102
2118
  resolved.exclude
2103
2119
  ]);
2104
2120
  }
@@ -9553,7 +9569,7 @@ function WheelColumn({
9553
9569
  ref: scrollRef,
9554
9570
  className: cn(
9555
9571
  "h-full overflow-y-auto overscroll-contain snap-y snap-mandatory",
9556
- "select-none cursor-grab active:cursor-grabbing",
9572
+ "select-none",
9557
9573
  "focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-xl",
9558
9574
  "[scrollbar-width:none] [-ms-overflow-style:none]",
9559
9575
  "[&::-webkit-scrollbar]:hidden"
@@ -9564,15 +9580,7 @@ function WheelColumn({
9564
9580
  tabIndex: focused ? 0 : -1,
9565
9581
  onKeyDown: (e) => onKeyDown(e, column),
9566
9582
  onFocus: () => setFocusedColumn(column),
9567
- onScroll: () => {
9568
- if (draggingRef.current) return;
9569
- if (inertialRef.current) return;
9570
- handleScroll();
9571
- },
9572
- onPointerDown,
9573
- onPointerMove,
9574
- onPointerUp: (e) => endDrag(e.pointerId),
9575
- onPointerCancel: (e) => endDrag(e.pointerId),
9583
+ onScroll: handleScroll,
9576
9584
  children: /* @__PURE__ */ jsx35("div", { children: extendedItems.map((n, index) => {
9577
9585
  const dist = Math.abs(index - currentVirtual);
9578
9586
  const distForVisual = Math.min(dist, 2);
@@ -11035,7 +11043,7 @@ function WheelColumn2({
11035
11043
  ref: scrollRef,
11036
11044
  className: cn(
11037
11045
  "h-full overflow-y-auto overscroll-contain snap-y snap-mandatory",
11038
- "select-none cursor-grab active:cursor-grabbing",
11046
+ "select-none",
11039
11047
  "focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-xl",
11040
11048
  "[scrollbar-width:none] [-ms-overflow-style:none]",
11041
11049
  "[&::-webkit-scrollbar]:hidden"
@@ -11046,15 +11054,7 @@ function WheelColumn2({
11046
11054
  tabIndex: focused ? 0 : -1,
11047
11055
  onKeyDown: (e) => onKeyDown(e, column),
11048
11056
  onFocus: () => setFocusedColumn(column),
11049
- onScroll: () => {
11050
- if (draggingRef.current) return;
11051
- if (inertialRef.current) return;
11052
- handleScroll();
11053
- },
11054
- onPointerDown,
11055
- onPointerMove,
11056
- onPointerUp: (e) => endDrag(e.pointerId),
11057
- onPointerCancel: (e) => endDrag(e.pointerId),
11057
+ onScroll: handleScroll,
11058
11058
  children: /* @__PURE__ */ jsx37("div", { children: extendedItems.map((n, index) => {
11059
11059
  const dist = Math.abs(index - currentVirtual);
11060
11060
  const distForVisual = Math.min(dist, 2);
@@ -11129,6 +11129,14 @@ function formatTime2({ h, m, s, p }, fmt, includeSeconds) {
11129
11129
  const base2 = `${pad(h)}:${pad(m)}`;
11130
11130
  return includeSeconds ? `${base2}:${pad(s)}` : base2;
11131
11131
  }
11132
+ function isCompleteTimeInput(input, fmt, includeSeconds) {
11133
+ const trimmed = input.trim().toUpperCase();
11134
+ if (!trimmed) return false;
11135
+ if (fmt === "12") {
11136
+ return includeSeconds ? /^\d{1,2}:\d{2}:\d{2}\s?(AM|PM)$/.test(trimmed) : /^\d{1,2}:\d{2}\s?(AM|PM)$/.test(trimmed);
11137
+ }
11138
+ return includeSeconds ? /^\d{1,2}:\d{2}:\d{2}$/.test(trimmed) : /^\d{1,2}:\d{2}$/.test(trimmed);
11139
+ }
11132
11140
  var PRESETS = {
11133
11141
  morning: { h: 9, m: 0, s: 0, icon: Coffee, label: "Morning", color: "from-amber-400 to-orange-400" },
11134
11142
  afternoon: { h: 14, m: 0, s: 0, icon: Sun, label: "Afternoon", color: "from-yellow-400 to-amber-400" },
@@ -11170,24 +11178,38 @@ function TimePicker({
11170
11178
  ...rest
11171
11179
  }) {
11172
11180
  const tv = useSmartTranslations("ValidationInput");
11181
+ const autoId = React31.useId();
11173
11182
  const isControlled = value !== void 0;
11174
11183
  const now = /* @__PURE__ */ new Date();
11175
11184
  const initial = parseTime(isControlled ? value : defaultValue, format, includeSeconds) || (format === "12" ? { h: now.getHours() % 12 || 12, m: now.getMinutes(), s: now.getSeconds(), p: now.getHours() >= 12 ? "PM" : "AM" } : { h: now.getHours(), m: now.getMinutes(), s: now.getSeconds() });
11176
11185
  const [open, setOpen] = React31.useState(false);
11177
11186
  const [parts, setParts] = React31.useState(initial);
11178
- const [manualInput, setManualInput] = React31.useState("");
11187
+ const [manualInput, setManualInput] = React31.useState(formatTime2(initial, format, includeSeconds));
11188
+ const [isDirectEditing, setIsDirectEditing] = React31.useState(false);
11179
11189
  const [focusedColumn, setFocusedColumn] = React31.useState(null);
11180
11190
  const [localRequiredError, setLocalRequiredError] = React31.useState();
11181
11191
  const [hasCommittedValue, setHasCommittedValue] = React31.useState(Boolean(isControlled ? value : defaultValue));
11182
11192
  const hourScrollRef = React31.useRef(null);
11183
11193
  const minuteScrollRef = React31.useRef(null);
11184
11194
  const secondScrollRef = React31.useRef(null);
11195
+ const periodRef = React31.useRef(null);
11196
+ const directEditInputRef = React31.useRef(null);
11197
+ const triggerId = `time-picker-trigger-${autoId}`;
11198
+ const labelId = label ? `time-picker-label-${autoId}` : void 0;
11185
11199
  React31.useEffect(() => {
11186
11200
  if (isControlled) {
11187
11201
  const parsed = parseTime(value, format, includeSeconds);
11188
11202
  if (parsed) setParts(parsed);
11189
11203
  }
11190
11204
  }, [value, isControlled, format, includeSeconds]);
11205
+ React31.useEffect(() => {
11206
+ setManualInput(formatTime2(parts, format, includeSeconds));
11207
+ }, [format, includeSeconds, parts]);
11208
+ React31.useEffect(() => {
11209
+ if (!isDirectEditing) return;
11210
+ directEditInputRef.current?.focus();
11211
+ directEditInputRef.current?.select();
11212
+ }, [isDirectEditing]);
11191
11213
  React31.useEffect(() => {
11192
11214
  if (isControlled) {
11193
11215
  setHasCommittedValue(Boolean(value));
@@ -11278,6 +11300,15 @@ function TimePicker({
11278
11300
  setLocalRequiredError(void 0);
11279
11301
  }
11280
11302
  }, [disabled, hasCommittedValue, required]);
11303
+ const focusColumn = React31.useCallback((column) => {
11304
+ if (!column) return;
11305
+ const target = column === "hour" ? hourScrollRef.current : column === "minute" ? minuteScrollRef.current : column === "second" ? secondScrollRef.current : periodRef.current;
11306
+ target?.focus({ preventScroll: true });
11307
+ }, []);
11308
+ React31.useEffect(() => {
11309
+ if (variant !== "inline" && !open) return;
11310
+ focusColumn(focusedColumn);
11311
+ }, [focusColumn, focusedColumn, open, variant]);
11281
11312
  const handleKeyDown2 = (e, column) => {
11282
11313
  if (!["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End", "PageUp", "PageDown"].includes(e.key)) return;
11283
11314
  e.preventDefault();
@@ -11321,6 +11352,7 @@ function TimePicker({
11321
11352
  }
11322
11353
  tryUpdate(newParts);
11323
11354
  };
11355
+ const display = formatTime2(parts, format, includeSeconds);
11324
11356
  const setNow = () => {
11325
11357
  const now2 = /* @__PURE__ */ new Date();
11326
11358
  const h = now2.getHours();
@@ -11346,6 +11378,7 @@ function TimePicker({
11346
11378
  };
11347
11379
  const handleManualInput = (input) => {
11348
11380
  setManualInput(input);
11381
+ if (!isCompleteTimeInput(input, format, includeSeconds)) return;
11349
11382
  const parsed = parseTime(input, format, includeSeconds);
11350
11383
  if (parsed) {
11351
11384
  const timeStr = formatTime2(parsed, format, includeSeconds);
@@ -11354,6 +11387,53 @@ function TimePicker({
11354
11387
  }
11355
11388
  }
11356
11389
  };
11390
+ const commitManualInput = React31.useCallback(
11391
+ (input) => {
11392
+ const trimmed = input.trim();
11393
+ if (!trimmed) {
11394
+ setManualInput(display);
11395
+ return false;
11396
+ }
11397
+ if (!isCompleteTimeInput(trimmed, format, includeSeconds)) {
11398
+ setManualInput(display);
11399
+ return false;
11400
+ }
11401
+ const parsed = parseTime(trimmed, format, includeSeconds);
11402
+ if (!parsed) {
11403
+ setManualInput(display);
11404
+ return false;
11405
+ }
11406
+ const timeStr = formatTime2(parsed, format, includeSeconds);
11407
+ if (!isTimeInRange(timeStr) || isTimeDisabled(timeStr)) {
11408
+ setManualInput(display);
11409
+ return false;
11410
+ }
11411
+ const updated = tryUpdate(parsed);
11412
+ if (!updated) {
11413
+ setManualInput(display);
11414
+ return false;
11415
+ }
11416
+ setManualInput(timeStr);
11417
+ return true;
11418
+ },
11419
+ [display, format, includeSeconds, isTimeDisabled, isTimeInRange, tryUpdate]
11420
+ );
11421
+ const startDirectEdit = React31.useCallback(() => {
11422
+ if (disabled) return;
11423
+ setManualInput(display);
11424
+ setIsDirectEditing(true);
11425
+ }, [disabled, display]);
11426
+ const stopDirectEdit = React31.useCallback(
11427
+ (mode) => {
11428
+ if (mode === "commit") {
11429
+ commitManualInput(manualInput);
11430
+ } else {
11431
+ setManualInput(display);
11432
+ }
11433
+ setIsDirectEditing(false);
11434
+ },
11435
+ [commitManualInput, display, manualInput]
11436
+ );
11357
11437
  const handleCustomPreset = (time) => {
11358
11438
  const parsed = parseTime(time, format, includeSeconds);
11359
11439
  if (parsed) {
@@ -11421,13 +11501,14 @@ function TimePicker({
11421
11501
  const shouldMatchTriggerWidth = matchTriggerWidth ?? variant !== "compact";
11422
11502
  const compactPanel = variant === "compact";
11423
11503
  const effectiveError = error ?? localRequiredError;
11424
- const display = formatTime2(parts, format, includeSeconds);
11425
11504
  const trigger = variant === "inline" ? null : /* @__PURE__ */ jsxs27(
11426
11505
  "button",
11427
11506
  {
11507
+ id: triggerId,
11428
11508
  type: "button",
11429
11509
  disabled,
11430
11510
  "aria-label": "Select time",
11511
+ "aria-labelledby": labelId,
11431
11512
  "aria-haspopup": "dialog",
11432
11513
  "aria-expanded": open,
11433
11514
  "aria-required": required,
@@ -11464,10 +11545,10 @@ function TimePicker({
11464
11545
  {
11465
11546
  className: cn(
11466
11547
  "truncate font-medium transition-colors duration-200",
11467
- !value && !defaultValue && "text-muted-foreground",
11468
- value || defaultValue ? "text-foreground" : ""
11548
+ !hasCommittedValue && "text-muted-foreground",
11549
+ hasCommittedValue ? "text-foreground" : ""
11469
11550
  ),
11470
- children: value || defaultValue ? display : placeholder
11551
+ children: hasCommittedValue ? display : placeholder
11471
11552
  }
11472
11553
  )
11473
11554
  ] }),
@@ -11487,13 +11568,51 @@ function TimePicker({
11487
11568
  tryUpdate(next);
11488
11569
  };
11489
11570
  const timePickerContent = /* @__PURE__ */ jsxs27("div", { className: cn(panelSz.stackGap, compactPanel && "space-y-2.5"), children: [
11490
- /* @__PURE__ */ jsx37("div", { className: cn("flex items-center justify-center py-1", compactPanel && "py-0.5"), children: /* @__PURE__ */ jsx37("span", { className: cn(panelSz.timeText, "font-bold tabular-nums tracking-wide text-foreground underline underline-offset-8 decoration-primary/60"), children: display }) }),
11571
+ /* @__PURE__ */ jsx37("div", { className: cn("flex items-center justify-center py-1", compactPanel && "py-0.5"), children: isDirectEditing ? /* @__PURE__ */ jsx37(
11572
+ "input",
11573
+ {
11574
+ ref: directEditInputRef,
11575
+ type: "text",
11576
+ value: manualInput,
11577
+ onChange: (e) => setManualInput(e.target.value),
11578
+ onBlur: () => stopDirectEdit("commit"),
11579
+ onKeyDown: (e) => {
11580
+ if (e.key === "Enter") {
11581
+ e.preventDefault();
11582
+ stopDirectEdit("commit");
11583
+ }
11584
+ if (e.key === "Escape") {
11585
+ e.preventDefault();
11586
+ stopDirectEdit("cancel");
11587
+ }
11588
+ },
11589
+ "aria-label": "Edit time value",
11590
+ className: cn(
11591
+ panelSz.timeText,
11592
+ "min-w-0 w-36 bg-transparent border-b border-primary/60 text-center font-bold tabular-nums tracking-wide text-foreground",
11593
+ "focus:outline-none focus:border-primary"
11594
+ )
11595
+ }
11596
+ ) : /* @__PURE__ */ jsx37(
11597
+ "button",
11598
+ {
11599
+ type: "button",
11600
+ onClick: startDirectEdit,
11601
+ className: cn(
11602
+ panelSz.timeText,
11603
+ "font-bold tabular-nums tracking-wide text-foreground underline underline-offset-8 decoration-primary/60",
11604
+ "rounded-md px-2 transition-colors hover:text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50"
11605
+ ),
11606
+ "aria-label": "Edit selected time",
11607
+ children: display
11608
+ }
11609
+ ) }),
11491
11610
  allowManualInput && /* @__PURE__ */ jsxs27("div", { className: "relative", children: [
11492
11611
  /* @__PURE__ */ jsx37(
11493
11612
  Input_default,
11494
11613
  {
11495
11614
  placeholder: format === "12" ? "02:30 PM" : "14:30",
11496
- value: manualInput || display,
11615
+ value: manualInput,
11497
11616
  onChange: (e) => handleManualInput(e.target.value),
11498
11617
  size: panelSz.inputSize,
11499
11618
  variant: "outlined",
@@ -11643,9 +11762,11 @@ function TimePicker({
11643
11762
  /* @__PURE__ */ jsx37(
11644
11763
  "div",
11645
11764
  {
11765
+ ref: periodRef,
11646
11766
  className: cn("flex flex-col p-1 rounded-xl bg-muted/30", panelSz.periodGap),
11647
11767
  role: "radiogroup",
11648
11768
  "aria-label": "Select AM or PM",
11769
+ "aria-labelledby": labelId,
11649
11770
  tabIndex: focusedColumn === "period" ? 0 : -1,
11650
11771
  onKeyDown: (e) => handleKeyDown2(e, "period"),
11651
11772
  onFocus: () => setFocusedColumn("period"),
@@ -11741,10 +11862,17 @@ function TimePicker({
11741
11862
  ] });
11742
11863
  if (variant === "inline") {
11743
11864
  return /* @__PURE__ */ jsxs27("div", { className: "w-fit max-w-full", ...rest, children: [
11744
- label && /* @__PURE__ */ jsx37("div", { className: "flex items-center justify-between mb-3", children: /* @__PURE__ */ jsxs27("label", { className: cn(sz.label, "font-semibold", disabled ? "text-muted-foreground" : "text-foreground", effectiveError && "text-destructive"), children: [
11745
- label,
11746
- required && /* @__PURE__ */ jsx37("span", { className: "text-destructive ml-1", children: "*" })
11747
- ] }) }),
11865
+ label && /* @__PURE__ */ jsx37("div", { className: "flex items-center justify-between mb-3", children: /* @__PURE__ */ jsxs27(
11866
+ "label",
11867
+ {
11868
+ id: labelId,
11869
+ className: cn(sz.label, "font-semibold", disabled ? "text-muted-foreground" : "text-foreground", effectiveError && "text-destructive"),
11870
+ children: [
11871
+ label,
11872
+ required && /* @__PURE__ */ jsx37("span", { className: "text-destructive ml-1", children: "*" })
11873
+ ]
11874
+ }
11875
+ ) }),
11748
11876
  /* @__PURE__ */ jsx37(
11749
11877
  "input",
11750
11878
  {
@@ -11781,6 +11909,8 @@ function TimePicker({
11781
11909
  label && /* @__PURE__ */ jsx37("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ jsxs27(
11782
11910
  "label",
11783
11911
  {
11912
+ id: labelId,
11913
+ htmlFor: triggerId,
11784
11914
  className: cn(
11785
11915
  sz.label,
11786
11916
  "font-semibold",
@@ -15046,7 +15176,7 @@ function CalendarTimeline({
15046
15176
 
15047
15177
  // src/components/MultiCombobox.tsx
15048
15178
  import * as React39 from "react";
15049
- import { useId as useId7 } from "react";
15179
+ import { useId as useId8 } from "react";
15050
15180
  import { ChevronDown as ChevronDown4, Search as Search5, Check as Check6, SearchX as SearchX2, Loader2 as Loader24, X as X13, Sparkles as Sparkles3 } from "lucide-react";
15051
15181
  import { Fragment as Fragment13, jsx as jsx45, jsxs as jsxs35 } from "react/jsx-runtime";
15052
15182
  var MultiCombobox = ({
@@ -15184,7 +15314,7 @@ var MultiCombobox = ({
15184
15314
  outline: "border-2 border-input bg-transparent hover:border-primary",
15185
15315
  ghost: "border border-transparent bg-muted/50 hover:bg-muted"
15186
15316
  };
15187
- const autoId = useId7();
15317
+ const autoId = useId8();
15188
15318
  const resolvedId = id ? String(id) : `multicombobox-${autoId}`;
15189
15319
  const labelId = label ? `${resolvedId}-label` : void 0;
15190
15320
  const labelSize = size === "sm" ? "text-xs" : size === "lg" ? "text-base" : "text-sm";
@@ -16688,7 +16818,7 @@ function OverlayControls({
16688
16818
  }
16689
16819
 
16690
16820
  // src/components/CategoryTreeSelect.tsx
16691
- import { useEffect as useEffect25, useId as useId9, useMemo as useMemo19, useRef as useRef19, useState as useState31 } from "react";
16821
+ import { useEffect as useEffect25, useId as useId10, useMemo as useMemo19, useRef as useRef19, useState as useState31 } from "react";
16692
16822
  import { ChevronRight as ChevronRight6, ChevronDown as ChevronDown5, FolderTree, Layers, Search as Search6, SearchX as SearchX3, X as X14 } from "lucide-react";
16693
16823
  import { jsx as jsx49, jsxs as jsxs39 } from "react/jsx-runtime";
16694
16824
  var defaultLabels = {
@@ -16745,7 +16875,7 @@ function CategoryTreeSelect(props) {
16745
16875
  const searchInputRef = useRef19(null);
16746
16876
  const dropdownViewportRef = useRef19(null);
16747
16877
  useOverlayScrollbarTarget(dropdownViewportRef, { enabled: useOverlayScrollbar });
16748
- const autoId = useId9();
16878
+ const autoId = useId10();
16749
16879
  const resolvedId = id ? String(id) : `category-tree-select-${autoId}`;
16750
16880
  const labelId = label ? `${resolvedId}-label` : void 0;
16751
16881
  const effectiveError = error ?? localRequiredError;
@@ -20507,7 +20637,7 @@ var MusicPlayer = ({
20507
20637
  var MusicPlayer_default = MusicPlayer;
20508
20638
 
20509
20639
  // src/components/Grid.tsx
20510
- import React51, { useId as useId10 } from "react";
20640
+ import React51, { useId as useId11 } from "react";
20511
20641
  import { Fragment as Fragment20, jsx as jsx59, jsxs as jsxs49 } from "react/jsx-runtime";
20512
20642
  var BP_MIN = {
20513
20643
  sm: 640,
@@ -20572,7 +20702,7 @@ var GridRoot = React51.forwardRef(
20572
20702
  children,
20573
20703
  ...rest
20574
20704
  }, ref) => {
20575
- const id = useId10().replace(/[:]/g, "");
20705
+ const id = useId11().replace(/[:]/g, "");
20576
20706
  const baseClass = `uv-grid-${id}`;
20577
20707
  const baseCols = toTemplateCols(columns, minColumnWidth);
20578
20708
  const baseRows = toTemplateRows(rows);
@@ -20793,7 +20923,7 @@ var LoadingBar = ({
20793
20923
  // src/components/Table.tsx
20794
20924
  import React52 from "react";
20795
20925
  import { jsx as jsx62, jsxs as jsxs51 } from "react/jsx-runtime";
20796
- var TABLE_BASE_CLASS = "w-full caption-bottom text-sm";
20926
+ var TABLE_BASE_CLASS = "w-full border-collapse caption-bottom text-sm";
20797
20927
  var TABLE_CONTAINER_BASE_CLASS = [
20798
20928
  "relative w-full overflow-auto",
20799
20929
  "rounded-2xl md:rounded-3xl border border-border/50",
@@ -21228,6 +21358,7 @@ function DataTableHeader({
21228
21358
  const prevCol = prevCell?.column;
21229
21359
  const isAfterFixedLeft = prevCol?.fixed === "left";
21230
21360
  const showBorderLeft = columnDividers && cellIndex > 0 && !isAfterFixedLeft && !col.fixed;
21361
+ const isLastCell = cellIndex === row.length - 1;
21231
21362
  return /* @__PURE__ */ jsxs53(
21232
21363
  TableHead,
21233
21364
  {
@@ -21267,7 +21398,8 @@ function DataTableHeader({
21267
21398
  onAutoFitColumn?.(col.key);
21268
21399
  },
21269
21400
  className: cn(
21270
- "absolute inset-y-0 right-0 z-10 w-3 -mr-1",
21401
+ "absolute inset-y-0 right-0 z-10 w-3",
21402
+ !isLastCell && "-mr-1",
21271
21403
  "cursor-col-resize select-none bg-transparent",
21272
21404
  "after:absolute after:inset-y-2 after:right-0.8 after:w-px after:bg-border/0 after:transition-colors",
21273
21405
  "hover:after:bg-primary/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary"
@@ -22038,6 +22170,7 @@ function DataTable({
22038
22170
  storageKey,
22039
22171
  stickyHeader = true,
22040
22172
  maxHeight = 500,
22173
+ horizontalMode = "auto",
22041
22174
  overflowHidden = true,
22042
22175
  useOverlayScrollbar = false,
22043
22176
  enableHeaderAutoFit = true,
@@ -22111,6 +22244,10 @@ function DataTable({
22111
22244
  total
22112
22245
  });
22113
22246
  const { getStickyCellClass, getStickyColumnStyle, getStickyHeaderClass, getStickyHeaderCellStyle } = useStickyColumns(visibleColumns);
22247
+ const shouldForceHorizontalScroll = horizontalMode === "scroll";
22248
+ const shouldUseFixedLayout = horizontalMode !== "auto";
22249
+ const viewportOverflowXClass = horizontalMode === "fit" ? "overflow-x-hidden" : "overflow-x-auto";
22250
+ const overlayOverflowX = horizontalMode === "fit" ? "hidden" : "scroll";
22114
22251
  const getRowKey = (row, idx) => {
22115
22252
  if (!rowKey) return String(idx);
22116
22253
  if (typeof rowKey === "function") return String(rowKey(row));
@@ -22118,7 +22255,10 @@ function DataTable({
22118
22255
  };
22119
22256
  const viewportRef = React62.useRef(null);
22120
22257
  const tableRef = React62.useRef(null);
22121
- useOverlayScrollbarTarget(viewportRef, { enabled: useOverlayScrollbar });
22258
+ useOverlayScrollbarTarget(viewportRef, {
22259
+ enabled: useOverlayScrollbar,
22260
+ overflowX: overlayOverflowX
22261
+ });
22122
22262
  const autoFitColumn = React62.useCallback((columnKey) => {
22123
22263
  const tableElement = tableRef.current;
22124
22264
  if (!tableElement) return;
@@ -22180,7 +22320,7 @@ function DataTable({
22180
22320
  "div",
22181
22321
  {
22182
22322
  ref: viewportRef,
22183
- className: cn("w-full overflow-x-auto", stickyHeader && "overflow-y-auto"),
22323
+ className: cn("w-full", viewportOverflowXClass, stickyHeader && "overflow-y-auto"),
22184
22324
  style: stickyHeader ? { maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight } : void 0,
22185
22325
  children: /* @__PURE__ */ jsxs56(
22186
22326
  Table,
@@ -22188,10 +22328,10 @@ function DataTable({
22188
22328
  ref: tableRef,
22189
22329
  disableContainer: true,
22190
22330
  className: cn(
22191
- "table-fixed",
22331
+ shouldUseFixedLayout ? "table-fixed" : "table-auto",
22192
22332
  stickyHeader && ["[&_thead]:sticky", "[&_thead]:top-0", "[&_thead]:z-20", "[&_thead]:shadow-[0_1px_3px_rgba(0,0,0,0.1)]"]
22193
22333
  ),
22194
- style: { minWidth: totalColumnsWidth > 0 ? `${totalColumnsWidth}px` : void 0 },
22334
+ style: { minWidth: shouldForceHorizontalScroll && totalColumnsWidth > 0 ? `${totalColumnsWidth}px` : void 0 },
22195
22335
  children: [
22196
22336
  /* @__PURE__ */ jsx67(TableHeader, { children: /* @__PURE__ */ jsx67(
22197
22337
  DataTableHeader,