@underverse-ui/underverse 0.2.47 → 0.2.50
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 +135 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -2
- package/dist/index.d.ts +62 -2
- package/dist/index.js +135 -73
- 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:
|
|
@@ -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,
|
|
@@ -5439,13 +5447,28 @@ var gradientDirectionMap = {
|
|
|
5439
5447
|
"to-tr": "bg-linear-to-tr",
|
|
5440
5448
|
"to-tl": "bg-linear-to-tl"
|
|
5441
5449
|
};
|
|
5450
|
+
var spacingClasses = {
|
|
5451
|
+
none: "",
|
|
5452
|
+
sm: "py-6",
|
|
5453
|
+
md: "py-8",
|
|
5454
|
+
lg: "py-12",
|
|
5455
|
+
xl: "py-16"
|
|
5456
|
+
};
|
|
5457
|
+
var paddingXClasses = {
|
|
5458
|
+
none: "",
|
|
5459
|
+
sm: "px-2 md:px-4",
|
|
5460
|
+
md: "px-4 md:px-6",
|
|
5461
|
+
lg: "px-6 md:px-8",
|
|
5462
|
+
xl: "px-8 md:px-12"
|
|
5463
|
+
};
|
|
5442
5464
|
var Section = import_react13.default.forwardRef(
|
|
5443
5465
|
({
|
|
5444
5466
|
children,
|
|
5445
5467
|
className,
|
|
5446
5468
|
variant = "default",
|
|
5447
|
-
spacing = "
|
|
5448
|
-
|
|
5469
|
+
spacing = "none",
|
|
5470
|
+
paddingX = "none",
|
|
5471
|
+
contained = false,
|
|
5449
5472
|
outlined = false,
|
|
5450
5473
|
gradientFrom = "from-primary/20",
|
|
5451
5474
|
gradientTo = "to-accent/20",
|
|
@@ -5459,12 +5482,6 @@ var Section = import_react13.default.forwardRef(
|
|
|
5459
5482
|
accent: "bg-accent/10",
|
|
5460
5483
|
gradient: ""
|
|
5461
5484
|
};
|
|
5462
|
-
const spacingClasses = {
|
|
5463
|
-
sm: "py-6",
|
|
5464
|
-
md: "py-8",
|
|
5465
|
-
lg: "py-12",
|
|
5466
|
-
xl: "py-16"
|
|
5467
|
-
};
|
|
5468
5485
|
const getGradientClasses = () => {
|
|
5469
5486
|
if (variant !== "gradient") return "";
|
|
5470
5487
|
return cn(gradientDirectionMap[gradientDirection], gradientFrom, gradientTo);
|
|
@@ -5476,8 +5493,9 @@ var Section = import_react13.default.forwardRef(
|
|
|
5476
5493
|
className: cn(
|
|
5477
5494
|
variant === "gradient" ? getGradientClasses() : variantClasses[variant],
|
|
5478
5495
|
spacingClasses[spacing],
|
|
5496
|
+
paddingXClasses[paddingX],
|
|
5479
5497
|
outlined && "rounded-lg border border-border/60",
|
|
5480
|
-
|
|
5498
|
+
contained && "container mx-auto",
|
|
5481
5499
|
className
|
|
5482
5500
|
),
|
|
5483
5501
|
...props,
|
|
@@ -5735,6 +5753,7 @@ var DatePicker = ({
|
|
|
5735
5753
|
"label",
|
|
5736
5754
|
{
|
|
5737
5755
|
id: labelId,
|
|
5756
|
+
htmlFor: resolvedId,
|
|
5738
5757
|
onClick: () => triggerRef.current?.focus(),
|
|
5739
5758
|
className: cn(
|
|
5740
5759
|
labelSize,
|
|
@@ -12089,7 +12108,7 @@ function DataTable({
|
|
|
12089
12108
|
const [curPage, setCurPage] = import_react32.default.useState(page);
|
|
12090
12109
|
const hasMounted = import_react32.default.useRef(false);
|
|
12091
12110
|
const loadedFromStorage = import_react32.default.useRef(false);
|
|
12092
|
-
const
|
|
12111
|
+
const [curPageSize, setCurPageSize] = import_react32.default.useState(() => {
|
|
12093
12112
|
if (typeof window === "undefined" || !storageKey) return pageSize;
|
|
12094
12113
|
try {
|
|
12095
12114
|
const saved = localStorage.getItem(`datatable_${storageKey}_pageSize`);
|
|
@@ -12103,8 +12122,7 @@ function DataTable({
|
|
|
12103
12122
|
} catch {
|
|
12104
12123
|
}
|
|
12105
12124
|
return pageSize;
|
|
12106
|
-
}
|
|
12107
|
-
const [curPageSize, setCurPageSize] = import_react32.default.useState(getInitialPageSize);
|
|
12125
|
+
});
|
|
12108
12126
|
import_react32.default.useEffect(() => {
|
|
12109
12127
|
if (typeof window === "undefined" || !storageKey) return;
|
|
12110
12128
|
if (!hasMounted.current) return;
|
|
@@ -12140,7 +12158,8 @@ function DataTable({
|
|
|
12140
12158
|
}, [debouncedFilters, sort, curPage, curPageSize]);
|
|
12141
12159
|
const densityRowClass = density === "compact" ? "h-9" : density === "comfortable" ? "h-14" : "h-12";
|
|
12142
12160
|
const cellPadding = density === "compact" ? "py-1.5 px-3" : density === "comfortable" ? "py-3 px-4" : "py-2.5 px-4";
|
|
12143
|
-
const
|
|
12161
|
+
const visibleColsSet = import_react32.default.useMemo(() => new Set(visibleCols), [visibleCols]);
|
|
12162
|
+
const visibleColumns = columns.filter((c) => visibleColsSet.has(c.key));
|
|
12144
12163
|
const getRowKey = (row, idx) => {
|
|
12145
12164
|
if (!rowKey) return String(idx);
|
|
12146
12165
|
if (typeof rowKey === "function") return String(rowKey(row));
|
|
@@ -12292,7 +12311,7 @@ function DataTable({
|
|
|
12292
12311
|
});
|
|
12293
12312
|
},
|
|
12294
12313
|
className: "text-xs text-destructive hover:underline",
|
|
12295
|
-
children: "
|
|
12314
|
+
children: t("clearFilter")
|
|
12296
12315
|
}
|
|
12297
12316
|
)
|
|
12298
12317
|
] })
|
|
@@ -12443,27 +12462,42 @@ function DataTable({
|
|
|
12443
12462
|
}
|
|
12444
12463
|
)
|
|
12445
12464
|
] }),
|
|
12446
|
-
/* @__PURE__ */ (0, import_jsx_runtime56.
|
|
12447
|
-
|
|
12465
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "text-sm", children: [
|
|
12466
|
+
t("loading"),
|
|
12467
|
+
"\u2026"
|
|
12468
|
+
] })
|
|
12469
|
+
] }) }) }) : !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) => {
|
|
12448
12470
|
const isLastRow = idx === displayedData.length - 1;
|
|
12449
|
-
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
12450
|
-
|
|
12451
|
-
|
|
12452
|
-
|
|
12453
|
-
{
|
|
12454
|
-
|
|
12455
|
-
|
|
12456
|
-
|
|
12457
|
-
col.align === "center" && "text-center",
|
|
12458
|
-
columnDividers && colIdx > 0 && "border-l border-border/60",
|
|
12459
|
-
isLastRow && col === visibleColumns[0] && "rounded-bl-md",
|
|
12460
|
-
isLastRow && col === visibleColumns[visibleColumns.length - 1] && "rounded-br-md"
|
|
12461
|
-
),
|
|
12462
|
-
children: col.render ? col.render(value, row, idx) : String(value ?? "")
|
|
12471
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
12472
|
+
TableRow,
|
|
12473
|
+
{
|
|
12474
|
+
className: cn(densityRowClass, striped && idx % 2 === 0 && "bg-muted/50"),
|
|
12475
|
+
style: {
|
|
12476
|
+
// content-visibility: auto for rendering performance (skip off-screen rows)
|
|
12477
|
+
contentVisibility: "auto",
|
|
12478
|
+
containIntrinsicSize: density === "compact" ? "0 36px" : density === "comfortable" ? "0 56px" : "0 48px"
|
|
12463
12479
|
},
|
|
12464
|
-
col
|
|
12465
|
-
|
|
12466
|
-
|
|
12480
|
+
children: visibleColumns.map((col, colIdx) => {
|
|
12481
|
+
const value = col.dataIndex ? row[col.dataIndex] : void 0;
|
|
12482
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
12483
|
+
TableCell,
|
|
12484
|
+
{
|
|
12485
|
+
className: cn(
|
|
12486
|
+
cellPadding,
|
|
12487
|
+
col.align === "right" && "text-right",
|
|
12488
|
+
col.align === "center" && "text-center",
|
|
12489
|
+
columnDividers && colIdx > 0 && "border-l border-border/60",
|
|
12490
|
+
isLastRow && col === visibleColumns[0] && "rounded-bl-md",
|
|
12491
|
+
isLastRow && col === visibleColumns[visibleColumns.length - 1] && "rounded-br-md"
|
|
12492
|
+
),
|
|
12493
|
+
children: col.render ? col.render(value, row, idx) : String(value ?? "")
|
|
12494
|
+
},
|
|
12495
|
+
col.key
|
|
12496
|
+
);
|
|
12497
|
+
})
|
|
12498
|
+
},
|
|
12499
|
+
getRowKey(row, idx)
|
|
12500
|
+
);
|
|
12467
12501
|
}) })
|
|
12468
12502
|
]
|
|
12469
12503
|
}
|
|
@@ -13476,7 +13510,14 @@ var en_default = {
|
|
|
13476
13510
|
compact: "Compact",
|
|
13477
13511
|
normal: "Normal",
|
|
13478
13512
|
comfortable: "Comfortable",
|
|
13479
|
-
columns: "Columns"
|
|
13513
|
+
columns: "Columns",
|
|
13514
|
+
loading: "Loading",
|
|
13515
|
+
noData: "No data",
|
|
13516
|
+
clearFilter: "Clear filter",
|
|
13517
|
+
headerAlign: "Header alignment",
|
|
13518
|
+
alignLeft: "Align left",
|
|
13519
|
+
alignCenter: "Align center",
|
|
13520
|
+
alignRight: "Align right"
|
|
13480
13521
|
},
|
|
13481
13522
|
ValidationInput: {
|
|
13482
13523
|
required: "This field is required",
|
|
@@ -13539,7 +13580,14 @@ var vi_default = {
|
|
|
13539
13580
|
compact: "G\u1ECDn",
|
|
13540
13581
|
normal: "Th\u01B0\u1EDDng",
|
|
13541
13582
|
comfortable: "Tho\u1EA3i m\xE1i",
|
|
13542
|
-
columns: "C\u1ED9t"
|
|
13583
|
+
columns: "C\u1ED9t",
|
|
13584
|
+
loading: "\u0110ang t\u1EA3i",
|
|
13585
|
+
noData: "Kh\xF4ng c\xF3 d\u1EEF li\u1EC7u",
|
|
13586
|
+
clearFilter: "X\xF3a b\u1ED9 l\u1ECDc",
|
|
13587
|
+
headerAlign: "C\u0103n ch\u1EC9nh ti\xEAu \u0111\u1EC1",
|
|
13588
|
+
alignLeft: "C\u0103n tr\xE1i",
|
|
13589
|
+
alignCenter: "C\u0103n gi\u1EEFa",
|
|
13590
|
+
alignRight: "C\u0103n ph\u1EA3i"
|
|
13543
13591
|
},
|
|
13544
13592
|
ValidationInput: {
|
|
13545
13593
|
required: "Tr\u01B0\u1EDDng n\xE0y l\xE0 b\u1EAFt bu\u1ED9c",
|
|
@@ -13602,7 +13650,14 @@ var ko_default = {
|
|
|
13602
13650
|
compact: "\uCEF4\uD329\uD2B8",
|
|
13603
13651
|
normal: "\uBCF4\uD1B5",
|
|
13604
13652
|
comfortable: "\uC5EC\uC720",
|
|
13605
|
-
columns: "\uC5F4"
|
|
13653
|
+
columns: "\uC5F4",
|
|
13654
|
+
loading: "\uB85C\uB529 \uC911",
|
|
13655
|
+
noData: "\uB370\uC774\uD130 \uC5C6\uC74C",
|
|
13656
|
+
clearFilter: "\uD544\uD130 \uC9C0\uC6B0\uAE30",
|
|
13657
|
+
headerAlign: "\uD5E4\uB354 \uC815\uB82C",
|
|
13658
|
+
alignLeft: "\uC67C\uCABD \uC815\uB82C",
|
|
13659
|
+
alignCenter: "\uAC00\uC6B4\uB370 \uC815\uB82C",
|
|
13660
|
+
alignRight: "\uC624\uB978\uCABD \uC815\uB82C"
|
|
13606
13661
|
},
|
|
13607
13662
|
ValidationInput: {
|
|
13608
13663
|
required: "\uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4",
|
|
@@ -13665,7 +13720,14 @@ var ja_default = {
|
|
|
13665
13720
|
compact: "\u30B3\u30F3\u30D1\u30AF\u30C8",
|
|
13666
13721
|
normal: "\u901A\u5E38",
|
|
13667
13722
|
comfortable: "\u3086\u3063\u305F\u308A",
|
|
13668
|
-
columns: "\u5217"
|
|
13723
|
+
columns: "\u5217",
|
|
13724
|
+
loading: "\u8AAD\u307F\u8FBC\u307F\u4E2D",
|
|
13725
|
+
noData: "\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093",
|
|
13726
|
+
clearFilter: "\u30D5\u30A3\u30EB\u30BF\u30FC\u3092\u30AF\u30EA\u30A2",
|
|
13727
|
+
headerAlign: "\u30D8\u30C3\u30C0\u30FC\u914D\u7F6E",
|
|
13728
|
+
alignLeft: "\u5DE6\u63C3\u3048",
|
|
13729
|
+
alignCenter: "\u4E2D\u592E\u63C3\u3048",
|
|
13730
|
+
alignRight: "\u53F3\u63C3\u3048"
|
|
13669
13731
|
},
|
|
13670
13732
|
ValidationInput: {
|
|
13671
13733
|
required: "\u3053\u306E\u9805\u76EE\u306F\u5FC5\u9808\u3067\u3059",
|