@underverse-ui/underverse 0.2.48 → 0.2.51
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/README.md +45 -0
- package/dist/index.cjs +168 -82
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -0
- package/dist/index.d.ts +64 -0
- package/dist/index.js +168 -82
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,6 +49,51 @@ Components use color variables like `primary`, `secondary`, `destructive`, etc.
|
|
|
49
49
|
|
|
50
50
|
---
|
|
51
51
|
|
|
52
|
+
## ⚡ Performance Optimization
|
|
53
|
+
|
|
54
|
+
### Optimize Package Imports (Next.js)
|
|
55
|
+
|
|
56
|
+
For best performance, add `optimizePackageImports` to your Next.js config:
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
// next.config.js
|
|
60
|
+
module.exports = {
|
|
61
|
+
experimental: {
|
|
62
|
+
optimizePackageImports: ["lucide-react", "@underverse-ui/underverse"],
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
This provides:
|
|
68
|
+
|
|
69
|
+
- ✅ 15-70% faster dev boot
|
|
70
|
+
- ✅ 28% faster builds
|
|
71
|
+
- ✅ 40% faster cold starts
|
|
72
|
+
- ✅ Automatic tree-shaking for barrel imports
|
|
73
|
+
|
|
74
|
+
### Dynamic Imports for Heavy Components
|
|
75
|
+
|
|
76
|
+
For pages that conditionally show DataTable or DatePicker:
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
import dynamic from "next/dynamic";
|
|
80
|
+
|
|
81
|
+
const DataTable = dynamic(() => import("@underverse-ui/underverse").then((m) => m.DataTable), { ssr: false, loading: () => <Skeleton /> });
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Web Interface Guidelines Compliant
|
|
85
|
+
|
|
86
|
+
All components follow [Vercel Web Interface Guidelines](https://github.com/vercel-labs/web-interface-guidelines):
|
|
87
|
+
|
|
88
|
+
- ✅ `focus-visible` ring (not `:focus`)
|
|
89
|
+
- ✅ Label `htmlFor` attribute
|
|
90
|
+
- ✅ ARIA attributes for accessibility
|
|
91
|
+
- ✅ `overscroll-behavior: contain` for modals
|
|
92
|
+
- ✅ Proper ellipsis (`…`) typography
|
|
93
|
+
- ✅ Locale-aware date formatting with `Intl.DateTimeFormat`
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
52
97
|
## 🚀 Quick Start
|
|
53
98
|
|
|
54
99
|
### Standalone React (Vite, CRA, etc.)
|
package/dist/index.cjs
CHANGED
|
@@ -259,29 +259,32 @@ var Button = (0, import_react.forwardRef)(
|
|
|
259
259
|
const SpinnerIcon = Spinner ?? import_lucide_react.Activity;
|
|
260
260
|
const [locked, setLocked] = (0, import_react.useState)(false);
|
|
261
261
|
const lockTimer = (0, import_react.useRef)(null);
|
|
262
|
-
const handleClick = (0, import_react.useCallback)(
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
if (
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
262
|
+
const handleClick = (0, import_react.useCallback)(
|
|
263
|
+
async (e) => {
|
|
264
|
+
if (disabled || loading2) return;
|
|
265
|
+
if (preventDoubleClick) {
|
|
266
|
+
if (locked) return;
|
|
267
|
+
setLocked(true);
|
|
268
|
+
try {
|
|
269
|
+
const result = onClick?.(e);
|
|
270
|
+
if (result && typeof result === "object" && typeof result.then === "function") {
|
|
271
|
+
await result;
|
|
272
|
+
setLocked(false);
|
|
273
|
+
} else {
|
|
274
|
+
const ms = lockMs ?? 600;
|
|
275
|
+
if (lockTimer.current) clearTimeout(lockTimer.current);
|
|
276
|
+
lockTimer.current = setTimeout(() => setLocked(false), ms);
|
|
277
|
+
}
|
|
278
|
+
} catch (err) {
|
|
271
279
|
setLocked(false);
|
|
272
|
-
|
|
273
|
-
const ms = lockMs ?? 600;
|
|
274
|
-
if (lockTimer.current) clearTimeout(lockTimer.current);
|
|
275
|
-
lockTimer.current = setTimeout(() => setLocked(false), ms);
|
|
280
|
+
throw err;
|
|
276
281
|
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
throw err;
|
|
282
|
+
} else {
|
|
283
|
+
onClick?.(e);
|
|
280
284
|
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
}, [disabled, loading2, onClick, locked, preventDoubleClick, lockMs]);
|
|
285
|
+
},
|
|
286
|
+
[disabled, loading2, onClick, locked, preventDoubleClick, lockMs]
|
|
287
|
+
);
|
|
285
288
|
const computedDisabled = disabled || loading2 || (preventDoubleClick ? locked : false);
|
|
286
289
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
287
290
|
"button",
|
|
@@ -312,15 +315,15 @@ var Button = (0, import_react.forwardRef)(
|
|
|
312
315
|
"aria-label": rest["aria-label"] || title,
|
|
313
316
|
...rest,
|
|
314
317
|
children: [
|
|
315
|
-
!noHoverOverlay
|
|
318
|
+
!noHoverOverlay ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "absolute inset-0 bg-linear-to-r from-primary-foreground/20 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-200 dark:hidden" }) : null,
|
|
316
319
|
loading2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
317
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SpinnerIcon, { className: "w-4 h-4 animate-spin" }),
|
|
318
|
-
loadingText
|
|
319
|
-
preserveChildrenOnLoading && !loadingText
|
|
320
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SpinnerIcon, { className: "w-4 h-4 animate-spin", "aria-hidden": "true" }),
|
|
321
|
+
loadingText ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ml-2", "aria-live": "polite", children: loadingText }) : null,
|
|
322
|
+
preserveChildrenOnLoading && !loadingText ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ml-2 opacity-70", "aria-hidden": true, children }) : null
|
|
320
323
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
321
|
-
Icon
|
|
324
|
+
Icon ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: cn("transition-transform duration-200", iConClassName ? iConClassName : "w-5 h-5") }) : null,
|
|
322
325
|
children,
|
|
323
|
-
IconRight
|
|
326
|
+
IconRight ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconRight, { className: "w-4 h-4 transition-transform duration-200" }) : null
|
|
324
327
|
] })
|
|
325
328
|
]
|
|
326
329
|
}
|
|
@@ -589,7 +592,7 @@ var Card = ({
|
|
|
589
592
|
"div",
|
|
590
593
|
{
|
|
591
594
|
className: cn(
|
|
592
|
-
"rounded-lg md:rounded-xl bg-card text-card-foreground transition-
|
|
595
|
+
"rounded-lg md:rounded-xl bg-card text-card-foreground transition-[transform,box-shadow,border-color,background-color] duration-300 ease-soft",
|
|
593
596
|
"shadow-sm md:hover:shadow-md mx-2 md:mx-0 border border-border",
|
|
594
597
|
hoverable && "md:hover:-translate-y-0.5 md:hover:border-primary/15",
|
|
595
598
|
clickable && "cursor-pointer active:translate-y-px md:hover:bg-accent/5",
|
|
@@ -1162,6 +1165,7 @@ var Input = (0, import_react3.forwardRef)(
|
|
|
1162
1165
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1163
1166
|
"label",
|
|
1164
1167
|
{
|
|
1168
|
+
htmlFor: resolvedId,
|
|
1165
1169
|
className: cn(
|
|
1166
1170
|
// Label size follows input size
|
|
1167
1171
|
size === "sm" ? "text-xs" : size === "lg" ? "text-base" : "text-sm",
|
|
@@ -1299,10 +1303,10 @@ var Input = (0, import_react3.forwardRef)(
|
|
|
1299
1303
|
}
|
|
1300
1304
|
)
|
|
1301
1305
|
] }),
|
|
1302
|
-
errMsg
|
|
1306
|
+
errMsg ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { id: errorId, className: "flex items-center gap-2 text-sm text-destructive animate-in slide-in-from-top-1 duration-200", children: [
|
|
1303
1307
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react3.AlertCircle, { className: "w-4 h-4 shrink-0" }),
|
|
1304
1308
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: errMsg })
|
|
1305
|
-
] }),
|
|
1309
|
+
] }) : null,
|
|
1306
1310
|
(description || hint) && !errMsg && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1307
1311
|
"p",
|
|
1308
1312
|
{
|
|
@@ -1320,7 +1324,7 @@ var Input = (0, import_react3.forwardRef)(
|
|
|
1320
1324
|
);
|
|
1321
1325
|
Input.displayName = "Input";
|
|
1322
1326
|
var SearchInput = (0, import_react3.forwardRef)(
|
|
1323
|
-
({ onSearch, searchDelay = 300, placeholder = "Search
|
|
1327
|
+
({ onSearch, searchDelay = 300, placeholder = "Search\u2026", ...props }, ref) => {
|
|
1324
1328
|
const [searchValue, setSearchValue] = (0, import_react3.useState)(props.value || "");
|
|
1325
1329
|
import_react3.default.useEffect(() => {
|
|
1326
1330
|
if (!onSearch) return;
|
|
@@ -1567,7 +1571,7 @@ var Textarea = (0, import_react3.forwardRef)(
|
|
|
1567
1571
|
onBlur: () => setIsFocused(false),
|
|
1568
1572
|
className: cn(
|
|
1569
1573
|
"w-full rounded-lg px-4 py-3 text-sm text-foreground transition-all duration-200",
|
|
1570
|
-
"placeholder:text-muted-foreground focus:outline-none min-h-
|
|
1574
|
+
"placeholder:text-muted-foreground focus:outline-none min-h-20",
|
|
1571
1575
|
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
1572
1576
|
variantStyles6[variant],
|
|
1573
1577
|
// DÒNG NÀY ĐÃ ĐƯỢC CẬP NHẬT:
|
|
@@ -1894,7 +1898,7 @@ var Textarea2 = (0, import_react5.forwardRef)(
|
|
|
1894
1898
|
md: "px-4 py-3 text-sm min-h-[100px]",
|
|
1895
1899
|
lg: "px-5 py-4 text-base min-h-[120px]"
|
|
1896
1900
|
};
|
|
1897
|
-
const
|
|
1901
|
+
const variantClasses2 = {
|
|
1898
1902
|
default: cn(
|
|
1899
1903
|
"border border-input bg-background",
|
|
1900
1904
|
"hover:border-accent-foreground/20",
|
|
@@ -1938,7 +1942,7 @@ var Textarea2 = (0, import_react5.forwardRef)(
|
|
|
1938
1942
|
"focus:outline-none shadow-sm focus:shadow-md",
|
|
1939
1943
|
"backdrop-blur-sm",
|
|
1940
1944
|
sizeClasses2[size],
|
|
1941
|
-
error ? "border-destructive focus:ring-destructive/20 focus:border-destructive" :
|
|
1945
|
+
error ? "border-destructive focus:ring-destructive/20 focus:border-destructive" : variantClasses2[variant],
|
|
1942
1946
|
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
1943
1947
|
className
|
|
1944
1948
|
),
|
|
@@ -1993,7 +1997,7 @@ var Switch = ({
|
|
|
1993
1997
|
translate: "translate-x-6"
|
|
1994
1998
|
}
|
|
1995
1999
|
};
|
|
1996
|
-
const
|
|
2000
|
+
const variantClasses2 = {
|
|
1997
2001
|
default: {
|
|
1998
2002
|
active: "bg-primary border-primary",
|
|
1999
2003
|
inactive: "bg-input border-input"
|
|
@@ -2047,7 +2051,7 @@ var Switch = ({
|
|
|
2047
2051
|
{
|
|
2048
2052
|
className: cn(
|
|
2049
2053
|
"block w-full h-full rounded-full transition-colors duration-200 ease-out border",
|
|
2050
|
-
checked ?
|
|
2054
|
+
checked ? variantClasses2[variant].active : variantClasses2[variant].inactive
|
|
2051
2055
|
)
|
|
2052
2056
|
}
|
|
2053
2057
|
),
|
|
@@ -2276,7 +2280,7 @@ var Skeleton = ({
|
|
|
2276
2280
|
animation = "pulse",
|
|
2277
2281
|
lines = 1
|
|
2278
2282
|
}) => {
|
|
2279
|
-
const
|
|
2283
|
+
const variantClasses2 = {
|
|
2280
2284
|
rectangular: "rounded-md",
|
|
2281
2285
|
circular: "rounded-full",
|
|
2282
2286
|
rounded: "rounded-lg",
|
|
@@ -2293,7 +2297,7 @@ var Skeleton = ({
|
|
|
2293
2297
|
{
|
|
2294
2298
|
className: cn(
|
|
2295
2299
|
"h-4 bg-muted",
|
|
2296
|
-
|
|
2300
|
+
variantClasses2[variant],
|
|
2297
2301
|
animationClasses[animation],
|
|
2298
2302
|
index === lines - 1 && "w-3/4"
|
|
2299
2303
|
// Last line is shorter
|
|
@@ -2311,7 +2315,7 @@ var Skeleton = ({
|
|
|
2311
2315
|
{
|
|
2312
2316
|
className: cn(
|
|
2313
2317
|
"bg-muted",
|
|
2314
|
-
|
|
2318
|
+
variantClasses2[variant],
|
|
2315
2319
|
animationClasses[animation],
|
|
2316
2320
|
className
|
|
2317
2321
|
),
|
|
@@ -3025,6 +3029,7 @@ var Modal = ({
|
|
|
3025
3029
|
"div",
|
|
3026
3030
|
{
|
|
3027
3031
|
className: cn("fixed inset-0 z-9999 flex items-center justify-center", overlayClassName),
|
|
3032
|
+
style: { overscrollBehavior: "contain" },
|
|
3028
3033
|
onMouseDown: handleOverlayMouseDown,
|
|
3029
3034
|
onMouseUp: handleOverlayMouseUp,
|
|
3030
3035
|
children: [
|
|
@@ -3067,12 +3072,13 @@ var Modal = ({
|
|
|
3067
3072
|
"button",
|
|
3068
3073
|
{
|
|
3069
3074
|
onClick: onClose,
|
|
3075
|
+
"aria-label": "Close modal",
|
|
3070
3076
|
className: cn(
|
|
3071
3077
|
"rounded-sm opacity-70 ring-offset-background transition-opacity",
|
|
3072
3078
|
"hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
3073
3079
|
"disabled:pointer-events-none "
|
|
3074
3080
|
),
|
|
3075
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react6.X, { className: "h-4 w-4 cursor-pointer" })
|
|
3081
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react6.X, { className: "h-4 w-4 cursor-pointer", "aria-hidden": "true" })
|
|
3076
3082
|
}
|
|
3077
3083
|
)
|
|
3078
3084
|
] }),
|
|
@@ -3366,6 +3372,7 @@ var Tooltip = ({
|
|
|
3366
3372
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3367
3373
|
"div",
|
|
3368
3374
|
{
|
|
3375
|
+
role: "tooltip",
|
|
3369
3376
|
style: {
|
|
3370
3377
|
position: "fixed",
|
|
3371
3378
|
top: position.top,
|
|
@@ -4824,8 +4831,8 @@ var Combobox = ({
|
|
|
4824
4831
|
options,
|
|
4825
4832
|
value,
|
|
4826
4833
|
onChange,
|
|
4827
|
-
placeholder = "Select
|
|
4828
|
-
searchPlaceholder = "Search
|
|
4834
|
+
placeholder = "Select\u2026",
|
|
4835
|
+
searchPlaceholder = "Search\u2026",
|
|
4829
4836
|
emptyText = "No results found",
|
|
4830
4837
|
className,
|
|
4831
4838
|
disabled = false,
|
|
@@ -4987,7 +4994,7 @@ var Combobox = ({
|
|
|
4987
4994
|
] }),
|
|
4988
4995
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "max-h-64 overflow-y-auto overscroll-contain", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("ul", { className: "p-1 space-y-1", children: loading2 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { className: "px-3 py-8 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col items-center gap-2 animate-in fade-in-0 zoom-in-95 duration-300", children: [
|
|
4989
4996
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Loader2, { className: "h-6 w-6 animate-spin text-primary" }),
|
|
4990
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-sm text-muted-foreground", children: loadingText || "Loading
|
|
4997
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-sm text-muted-foreground", children: loadingText || "Loading\u2026" })
|
|
4991
4998
|
] }) }) : filteredOptions.length > 0 ? filteredOptions.map((item, index) => {
|
|
4992
4999
|
const itemValue = getOptionValue(item);
|
|
4993
5000
|
const itemLabel = getOptionLabel(item);
|
|
@@ -5025,7 +5032,7 @@ var Combobox = ({
|
|
|
5025
5032
|
}) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { className: "px-3 py-8 text-center text-muted-foreground text-sm", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col items-center gap-2 animate-in fade-in-0 zoom-in-95 duration-300", children: [
|
|
5026
5033
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.SearchX, { className: "h-8 w-8 opacity-40 text-muted-foreground" }),
|
|
5027
5034
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-sm", children: emptyText }),
|
|
5028
|
-
query && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", onClick: () => setQuery(""), className: "text-xs text-primary hover:underline", children: "Clear
|
|
5035
|
+
query && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", onClick: () => setQuery(""), className: "text-xs text-primary hover:underline", children: "Clear" })
|
|
5029
5036
|
] }) }) }) })
|
|
5030
5037
|
] })
|
|
5031
5038
|
}
|
|
@@ -5044,6 +5051,7 @@ var Combobox = ({
|
|
|
5044
5051
|
"label",
|
|
5045
5052
|
{
|
|
5046
5053
|
id: labelId,
|
|
5054
|
+
htmlFor: resolvedId,
|
|
5047
5055
|
onClick: () => triggerRef.current?.focus(),
|
|
5048
5056
|
className: cn(
|
|
5049
5057
|
labelSize,
|
|
@@ -5467,7 +5475,7 @@ var Section = import_react13.default.forwardRef(
|
|
|
5467
5475
|
gradientDirection = "to-br",
|
|
5468
5476
|
...props
|
|
5469
5477
|
}, ref) => {
|
|
5470
|
-
const
|
|
5478
|
+
const variantClasses2 = {
|
|
5471
5479
|
default: "bg-background",
|
|
5472
5480
|
muted: "bg-muted/30",
|
|
5473
5481
|
primary: "bg-primary/5",
|
|
@@ -5483,7 +5491,7 @@ var Section = import_react13.default.forwardRef(
|
|
|
5483
5491
|
{
|
|
5484
5492
|
ref,
|
|
5485
5493
|
className: cn(
|
|
5486
|
-
variant === "gradient" ? getGradientClasses() :
|
|
5494
|
+
variant === "gradient" ? getGradientClasses() : variantClasses2[variant],
|
|
5487
5495
|
spacingClasses[spacing],
|
|
5488
5496
|
paddingXClasses[paddingX],
|
|
5489
5497
|
outlined && "rounded-lg border border-border/60",
|
|
@@ -5502,9 +5510,43 @@ var Section_default = Section;
|
|
|
5502
5510
|
// ../../components/ui/ScrollArea.tsx
|
|
5503
5511
|
var import_react14 = require("react");
|
|
5504
5512
|
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
5505
|
-
var
|
|
5506
|
-
|
|
5507
|
-
|
|
5513
|
+
var variantClasses = {
|
|
5514
|
+
default: "bg-background",
|
|
5515
|
+
muted: "bg-muted/30",
|
|
5516
|
+
primary: "bg-primary/5",
|
|
5517
|
+
accent: "bg-accent/10"
|
|
5518
|
+
};
|
|
5519
|
+
var spacingClasses2 = {
|
|
5520
|
+
none: "",
|
|
5521
|
+
sm: "p-2",
|
|
5522
|
+
md: "p-4",
|
|
5523
|
+
lg: "p-6",
|
|
5524
|
+
xl: "p-8"
|
|
5525
|
+
};
|
|
5526
|
+
var ScrollArea = (0, import_react14.forwardRef)(
|
|
5527
|
+
({ className, contentClassName, children, variant = "default", spacing = "none", fullWidth = true, outlined = false, ...props }, ref) => {
|
|
5528
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
5529
|
+
"div",
|
|
5530
|
+
{
|
|
5531
|
+
ref,
|
|
5532
|
+
className: cn("relative overflow-hidden", variantClasses[variant], outlined && "rounded-lg border border-border/60", className),
|
|
5533
|
+
...props,
|
|
5534
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
5535
|
+
"div",
|
|
5536
|
+
{
|
|
5537
|
+
className: cn(
|
|
5538
|
+
"h-full w-full overflow-y-auto scroll-area-viewport",
|
|
5539
|
+
spacingClasses2[spacing],
|
|
5540
|
+
!fullWidth && "container mx-auto px-4 md:px-6",
|
|
5541
|
+
contentClassName
|
|
5542
|
+
),
|
|
5543
|
+
children
|
|
5544
|
+
}
|
|
5545
|
+
)
|
|
5546
|
+
}
|
|
5547
|
+
);
|
|
5548
|
+
}
|
|
5549
|
+
);
|
|
5508
5550
|
ScrollArea.displayName = "ScrollArea";
|
|
5509
5551
|
|
|
5510
5552
|
// ../../components/ui/DatePicker.tsx
|
|
@@ -5745,6 +5787,7 @@ var DatePicker = ({
|
|
|
5745
5787
|
"label",
|
|
5746
5788
|
{
|
|
5747
5789
|
id: labelId,
|
|
5790
|
+
htmlFor: resolvedId,
|
|
5748
5791
|
onClick: () => triggerRef.current?.focus(),
|
|
5749
5792
|
className: cn(
|
|
5750
5793
|
labelSize,
|
|
@@ -9182,7 +9225,7 @@ var ListRoot = React33.forwardRef(
|
|
|
9182
9225
|
const Comp = ordered ? "ol" : as;
|
|
9183
9226
|
const childCount = React33.Children.count(children);
|
|
9184
9227
|
const hasChildren = childCount > 0;
|
|
9185
|
-
const
|
|
9228
|
+
const variantClasses2 = {
|
|
9186
9229
|
plain: "",
|
|
9187
9230
|
outlined: "rounded-lg md:rounded-xl bg-card text-card-foreground border border-border shadow-sm",
|
|
9188
9231
|
soft: "rounded-lg bg-muted/40 border border-border/60",
|
|
@@ -9192,10 +9235,10 @@ var ListRoot = React33.forwardRef(
|
|
|
9192
9235
|
striped: "rounded-lg border border-border overflow-hidden"
|
|
9193
9236
|
};
|
|
9194
9237
|
if (loading2) {
|
|
9195
|
-
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Comp, { ref, className: cn("group/list",
|
|
9238
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Comp, { ref, className: cn("group/list", variantClasses2[variant], inset && "p-1.5 md:p-2", divided && "divide-y divide-border/60", className), ...rest, children: Array.from({ length: loadingCount }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ListItemSkeleton, { size }, i)) });
|
|
9196
9239
|
}
|
|
9197
9240
|
if (!hasChildren && emptyText) {
|
|
9198
|
-
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Comp, { ref, className: cn("group/list",
|
|
9241
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Comp, { ref, className: cn("group/list", variantClasses2[variant], inset && "p-1.5 md:p-2", className), ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "text-center py-8 text-muted-foreground text-sm", children: emptyText }) });
|
|
9199
9242
|
}
|
|
9200
9243
|
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
9201
9244
|
Comp,
|
|
@@ -9203,7 +9246,7 @@ var ListRoot = React33.forwardRef(
|
|
|
9203
9246
|
ref,
|
|
9204
9247
|
className: cn(
|
|
9205
9248
|
"group/list",
|
|
9206
|
-
|
|
9249
|
+
variantClasses2[variant],
|
|
9207
9250
|
inset && "p-1.5 md:p-2",
|
|
9208
9251
|
divided && "divide-y divide-border/60",
|
|
9209
9252
|
variant === "striped" && "[&>*:nth-child(even)]:bg-muted/30",
|
|
@@ -9770,7 +9813,7 @@ var TimelineItem = React35.forwardRef(
|
|
|
9770
9813
|
}
|
|
9771
9814
|
};
|
|
9772
9815
|
const padding = ctx.dense ? sz.densePadY : sz.padY;
|
|
9773
|
-
const
|
|
9816
|
+
const variantClasses2 = {
|
|
9774
9817
|
default: "",
|
|
9775
9818
|
outlined: "rounded-lg border border-border bg-card shadow-sm px-4 py-3",
|
|
9776
9819
|
card: "rounded-xl border border-border bg-card shadow-md px-5 py-4",
|
|
@@ -9778,7 +9821,7 @@ var TimelineItem = React35.forwardRef(
|
|
|
9778
9821
|
modern: "rounded-lg bg-linear-to-r from-card to-muted/20 border border-border/50 px-5 py-4 backdrop-blur-sm",
|
|
9779
9822
|
gradient: "rounded-xl bg-linear-to-br from-primary/10 via-card to-accent/10 border border-primary/20 px-5 py-4 shadow-lg"
|
|
9780
9823
|
};
|
|
9781
|
-
const contentBox = /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: cn("min-w-0 flex-1",
|
|
9824
|
+
const contentBox = /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: cn("min-w-0 flex-1", variantClasses2[ctx.variant]), children: [
|
|
9782
9825
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-start justify-between gap-2", children: [
|
|
9783
9826
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
9784
9827
|
title && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
@@ -12099,7 +12142,7 @@ function DataTable({
|
|
|
12099
12142
|
const [curPage, setCurPage] = import_react32.default.useState(page);
|
|
12100
12143
|
const hasMounted = import_react32.default.useRef(false);
|
|
12101
12144
|
const loadedFromStorage = import_react32.default.useRef(false);
|
|
12102
|
-
const
|
|
12145
|
+
const [curPageSize, setCurPageSize] = import_react32.default.useState(() => {
|
|
12103
12146
|
if (typeof window === "undefined" || !storageKey) return pageSize;
|
|
12104
12147
|
try {
|
|
12105
12148
|
const saved = localStorage.getItem(`datatable_${storageKey}_pageSize`);
|
|
@@ -12113,8 +12156,7 @@ function DataTable({
|
|
|
12113
12156
|
} catch {
|
|
12114
12157
|
}
|
|
12115
12158
|
return pageSize;
|
|
12116
|
-
}
|
|
12117
|
-
const [curPageSize, setCurPageSize] = import_react32.default.useState(getInitialPageSize);
|
|
12159
|
+
});
|
|
12118
12160
|
import_react32.default.useEffect(() => {
|
|
12119
12161
|
if (typeof window === "undefined" || !storageKey) return;
|
|
12120
12162
|
if (!hasMounted.current) return;
|
|
@@ -12150,7 +12192,8 @@ function DataTable({
|
|
|
12150
12192
|
}, [debouncedFilters, sort, curPage, curPageSize]);
|
|
12151
12193
|
const densityRowClass = density === "compact" ? "h-9" : density === "comfortable" ? "h-14" : "h-12";
|
|
12152
12194
|
const cellPadding = density === "compact" ? "py-1.5 px-3" : density === "comfortable" ? "py-3 px-4" : "py-2.5 px-4";
|
|
12153
|
-
const
|
|
12195
|
+
const visibleColsSet = import_react32.default.useMemo(() => new Set(visibleCols), [visibleCols]);
|
|
12196
|
+
const visibleColumns = columns.filter((c) => visibleColsSet.has(c.key));
|
|
12154
12197
|
const getRowKey = (row, idx) => {
|
|
12155
12198
|
if (!rowKey) return String(idx);
|
|
12156
12199
|
if (typeof rowKey === "function") return String(rowKey(row));
|
|
@@ -12302,7 +12345,7 @@ function DataTable({
|
|
|
12302
12345
|
});
|
|
12303
12346
|
},
|
|
12304
12347
|
className: "text-xs text-destructive hover:underline",
|
|
12305
|
-
children: "
|
|
12348
|
+
children: t("clearFilter")
|
|
12306
12349
|
}
|
|
12307
12350
|
)
|
|
12308
12351
|
] })
|
|
@@ -12453,27 +12496,42 @@ function DataTable({
|
|
|
12453
12496
|
}
|
|
12454
12497
|
)
|
|
12455
12498
|
] }),
|
|
12456
|
-
/* @__PURE__ */ (0, import_jsx_runtime56.
|
|
12457
|
-
|
|
12499
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "text-sm", children: [
|
|
12500
|
+
t("loading"),
|
|
12501
|
+
"\u2026"
|
|
12502
|
+
] })
|
|
12503
|
+
] }) }) }) : !displayedData || displayedData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(TableCell, { colSpan: visibleColumns.length, className: "text-center py-6 text-muted-foreground", children: t("noData") }) }) : displayedData.map((row, idx) => {
|
|
12458
12504
|
const isLastRow = idx === displayedData.length - 1;
|
|
12459
|
-
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
12460
|
-
|
|
12461
|
-
|
|
12462
|
-
|
|
12463
|
-
{
|
|
12464
|
-
|
|
12465
|
-
|
|
12466
|
-
|
|
12467
|
-
col.align === "center" && "text-center",
|
|
12468
|
-
columnDividers && colIdx > 0 && "border-l border-border/60",
|
|
12469
|
-
isLastRow && col === visibleColumns[0] && "rounded-bl-md",
|
|
12470
|
-
isLastRow && col === visibleColumns[visibleColumns.length - 1] && "rounded-br-md"
|
|
12471
|
-
),
|
|
12472
|
-
children: col.render ? col.render(value, row, idx) : String(value ?? "")
|
|
12505
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
12506
|
+
TableRow,
|
|
12507
|
+
{
|
|
12508
|
+
className: cn(densityRowClass, striped && idx % 2 === 0 && "bg-muted/50"),
|
|
12509
|
+
style: {
|
|
12510
|
+
// content-visibility: auto for rendering performance (skip off-screen rows)
|
|
12511
|
+
contentVisibility: "auto",
|
|
12512
|
+
containIntrinsicSize: density === "compact" ? "0 36px" : density === "comfortable" ? "0 56px" : "0 48px"
|
|
12473
12513
|
},
|
|
12474
|
-
col
|
|
12475
|
-
|
|
12476
|
-
|
|
12514
|
+
children: visibleColumns.map((col, colIdx) => {
|
|
12515
|
+
const value = col.dataIndex ? row[col.dataIndex] : void 0;
|
|
12516
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
12517
|
+
TableCell,
|
|
12518
|
+
{
|
|
12519
|
+
className: cn(
|
|
12520
|
+
cellPadding,
|
|
12521
|
+
col.align === "right" && "text-right",
|
|
12522
|
+
col.align === "center" && "text-center",
|
|
12523
|
+
columnDividers && colIdx > 0 && "border-l border-border/60",
|
|
12524
|
+
isLastRow && col === visibleColumns[0] && "rounded-bl-md",
|
|
12525
|
+
isLastRow && col === visibleColumns[visibleColumns.length - 1] && "rounded-br-md"
|
|
12526
|
+
),
|
|
12527
|
+
children: col.render ? col.render(value, row, idx) : String(value ?? "")
|
|
12528
|
+
},
|
|
12529
|
+
col.key
|
|
12530
|
+
);
|
|
12531
|
+
})
|
|
12532
|
+
},
|
|
12533
|
+
getRowKey(row, idx)
|
|
12534
|
+
);
|
|
12477
12535
|
}) })
|
|
12478
12536
|
]
|
|
12479
12537
|
}
|
|
@@ -13486,7 +13544,14 @@ var en_default = {
|
|
|
13486
13544
|
compact: "Compact",
|
|
13487
13545
|
normal: "Normal",
|
|
13488
13546
|
comfortable: "Comfortable",
|
|
13489
|
-
columns: "Columns"
|
|
13547
|
+
columns: "Columns",
|
|
13548
|
+
loading: "Loading",
|
|
13549
|
+
noData: "No data",
|
|
13550
|
+
clearFilter: "Clear filter",
|
|
13551
|
+
headerAlign: "Header alignment",
|
|
13552
|
+
alignLeft: "Align left",
|
|
13553
|
+
alignCenter: "Align center",
|
|
13554
|
+
alignRight: "Align right"
|
|
13490
13555
|
},
|
|
13491
13556
|
ValidationInput: {
|
|
13492
13557
|
required: "This field is required",
|
|
@@ -13549,7 +13614,14 @@ var vi_default = {
|
|
|
13549
13614
|
compact: "G\u1ECDn",
|
|
13550
13615
|
normal: "Th\u01B0\u1EDDng",
|
|
13551
13616
|
comfortable: "Tho\u1EA3i m\xE1i",
|
|
13552
|
-
columns: "C\u1ED9t"
|
|
13617
|
+
columns: "C\u1ED9t",
|
|
13618
|
+
loading: "\u0110ang t\u1EA3i",
|
|
13619
|
+
noData: "Kh\xF4ng c\xF3 d\u1EEF li\u1EC7u",
|
|
13620
|
+
clearFilter: "X\xF3a b\u1ED9 l\u1ECDc",
|
|
13621
|
+
headerAlign: "C\u0103n ch\u1EC9nh ti\xEAu \u0111\u1EC1",
|
|
13622
|
+
alignLeft: "C\u0103n tr\xE1i",
|
|
13623
|
+
alignCenter: "C\u0103n gi\u1EEFa",
|
|
13624
|
+
alignRight: "C\u0103n ph\u1EA3i"
|
|
13553
13625
|
},
|
|
13554
13626
|
ValidationInput: {
|
|
13555
13627
|
required: "Tr\u01B0\u1EDDng n\xE0y l\xE0 b\u1EAFt bu\u1ED9c",
|
|
@@ -13612,7 +13684,14 @@ var ko_default = {
|
|
|
13612
13684
|
compact: "\uCEF4\uD329\uD2B8",
|
|
13613
13685
|
normal: "\uBCF4\uD1B5",
|
|
13614
13686
|
comfortable: "\uC5EC\uC720",
|
|
13615
|
-
columns: "\uC5F4"
|
|
13687
|
+
columns: "\uC5F4",
|
|
13688
|
+
loading: "\uB85C\uB529 \uC911",
|
|
13689
|
+
noData: "\uB370\uC774\uD130 \uC5C6\uC74C",
|
|
13690
|
+
clearFilter: "\uD544\uD130 \uC9C0\uC6B0\uAE30",
|
|
13691
|
+
headerAlign: "\uD5E4\uB354 \uC815\uB82C",
|
|
13692
|
+
alignLeft: "\uC67C\uCABD \uC815\uB82C",
|
|
13693
|
+
alignCenter: "\uAC00\uC6B4\uB370 \uC815\uB82C",
|
|
13694
|
+
alignRight: "\uC624\uB978\uCABD \uC815\uB82C"
|
|
13616
13695
|
},
|
|
13617
13696
|
ValidationInput: {
|
|
13618
13697
|
required: "\uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4",
|
|
@@ -13675,7 +13754,14 @@ var ja_default = {
|
|
|
13675
13754
|
compact: "\u30B3\u30F3\u30D1\u30AF\u30C8",
|
|
13676
13755
|
normal: "\u901A\u5E38",
|
|
13677
13756
|
comfortable: "\u3086\u3063\u305F\u308A",
|
|
13678
|
-
columns: "\u5217"
|
|
13757
|
+
columns: "\u5217",
|
|
13758
|
+
loading: "\u8AAD\u307F\u8FBC\u307F\u4E2D",
|
|
13759
|
+
noData: "\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093",
|
|
13760
|
+
clearFilter: "\u30D5\u30A3\u30EB\u30BF\u30FC\u3092\u30AF\u30EA\u30A2",
|
|
13761
|
+
headerAlign: "\u30D8\u30C3\u30C0\u30FC\u914D\u7F6E",
|
|
13762
|
+
alignLeft: "\u5DE6\u63C3\u3048",
|
|
13763
|
+
alignCenter: "\u4E2D\u592E\u63C3\u3048",
|
|
13764
|
+
alignRight: "\u53F3\u63C3\u3048"
|
|
13679
13765
|
},
|
|
13680
13766
|
ValidationInput: {
|
|
13681
13767
|
required: "\u3053\u306E\u9805\u76EE\u306F\u5FC5\u9808\u3067\u3059",
|