@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/api-reference.json +1 -1
- package/dist/index.cjs +179 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +185 -45
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
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
|
-
!
|
|
11468
|
-
|
|
11548
|
+
!hasCommittedValue && "text-muted-foreground",
|
|
11549
|
+
hasCommittedValue ? "text-foreground" : ""
|
|
11469
11550
|
),
|
|
11470
|
-
children:
|
|
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(
|
|
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
|
|
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(
|
|
11745
|
-
label,
|
|
11746
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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, {
|
|
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
|
|
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,
|