@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/dist/index.d.cts CHANGED
@@ -685,8 +685,12 @@ interface SectionProps extends React__default.HTMLAttributes<HTMLElement> {
685
685
  children: React__default.ReactNode;
686
686
  className?: string;
687
687
  variant?: "default" | "muted" | "primary" | "accent" | "gradient";
688
- spacing?: "sm" | "md" | "lg" | "xl";
689
- fullWidth?: boolean;
688
+ /** Vertical padding (py). Default: "none" - không thêm padding dọc */
689
+ spacing?: "none" | "sm" | "md" | "lg" | "xl";
690
+ /** Horizontal padding (px). Default: "none" - không thêm padding ngang */
691
+ paddingX?: "none" | "sm" | "md" | "lg" | "xl";
692
+ /** Thêm container wrapper với mx-auto. Default: false */
693
+ contained?: boolean;
690
694
  /** Hiển thị viền mỏng xám nhạt giống Card */
691
695
  outlined?: boolean;
692
696
  /** Gradient start color (Tailwind class like 'from-purple-500') */
@@ -2096,6 +2100,13 @@ declare const underverseMessages: {
2096
2100
  normal: string;
2097
2101
  comfortable: string;
2098
2102
  columns: string;
2103
+ loading: string;
2104
+ noData: string;
2105
+ clearFilter: string;
2106
+ headerAlign: string;
2107
+ alignLeft: string;
2108
+ alignCenter: string;
2109
+ alignRight: string;
2099
2110
  };
2100
2111
  ValidationInput: {
2101
2112
  required: string;
@@ -2157,6 +2168,13 @@ declare const underverseMessages: {
2157
2168
  normal: string;
2158
2169
  comfortable: string;
2159
2170
  columns: string;
2171
+ loading: string;
2172
+ noData: string;
2173
+ clearFilter: string;
2174
+ headerAlign: string;
2175
+ alignLeft: string;
2176
+ alignCenter: string;
2177
+ alignRight: string;
2160
2178
  };
2161
2179
  ValidationInput: {
2162
2180
  required: string;
@@ -2218,6 +2236,13 @@ declare const underverseMessages: {
2218
2236
  normal: string;
2219
2237
  comfortable: string;
2220
2238
  columns: string;
2239
+ loading: string;
2240
+ noData: string;
2241
+ clearFilter: string;
2242
+ headerAlign: string;
2243
+ alignLeft: string;
2244
+ alignCenter: string;
2245
+ alignRight: string;
2221
2246
  };
2222
2247
  ValidationInput: {
2223
2248
  required: string;
@@ -2279,6 +2304,13 @@ declare const underverseMessages: {
2279
2304
  normal: string;
2280
2305
  comfortable: string;
2281
2306
  columns: string;
2307
+ loading: string;
2308
+ noData: string;
2309
+ clearFilter: string;
2310
+ headerAlign: string;
2311
+ alignLeft: string;
2312
+ alignCenter: string;
2313
+ alignRight: string;
2282
2314
  };
2283
2315
  ValidationInput: {
2284
2316
  required: string;
@@ -2342,6 +2374,13 @@ declare function getUnderverseMessages(locale?: UnderverseLocale): {
2342
2374
  normal: string;
2343
2375
  comfortable: string;
2344
2376
  columns: string;
2377
+ loading: string;
2378
+ noData: string;
2379
+ clearFilter: string;
2380
+ headerAlign: string;
2381
+ alignLeft: string;
2382
+ alignCenter: string;
2383
+ alignRight: string;
2345
2384
  };
2346
2385
  ValidationInput: {
2347
2386
  required: string;
@@ -2402,6 +2441,13 @@ declare function getUnderverseMessages(locale?: UnderverseLocale): {
2402
2441
  normal: string;
2403
2442
  comfortable: string;
2404
2443
  columns: string;
2444
+ loading: string;
2445
+ noData: string;
2446
+ clearFilter: string;
2447
+ headerAlign: string;
2448
+ alignLeft: string;
2449
+ alignCenter: string;
2450
+ alignRight: string;
2405
2451
  };
2406
2452
  ValidationInput: {
2407
2453
  required: string;
@@ -2462,6 +2508,13 @@ declare function getUnderverseMessages(locale?: UnderverseLocale): {
2462
2508
  normal: string;
2463
2509
  comfortable: string;
2464
2510
  columns: string;
2511
+ loading: string;
2512
+ noData: string;
2513
+ clearFilter: string;
2514
+ headerAlign: string;
2515
+ alignLeft: string;
2516
+ alignCenter: string;
2517
+ alignRight: string;
2465
2518
  };
2466
2519
  ValidationInput: {
2467
2520
  required: string;
@@ -2522,6 +2575,13 @@ declare function getUnderverseMessages(locale?: UnderverseLocale): {
2522
2575
  normal: string;
2523
2576
  comfortable: string;
2524
2577
  columns: string;
2578
+ loading: string;
2579
+ noData: string;
2580
+ clearFilter: string;
2581
+ headerAlign: string;
2582
+ alignLeft: string;
2583
+ alignCenter: string;
2584
+ alignRight: string;
2525
2585
  };
2526
2586
  ValidationInput: {
2527
2587
  required: string;
package/dist/index.d.ts CHANGED
@@ -685,8 +685,12 @@ interface SectionProps extends React__default.HTMLAttributes<HTMLElement> {
685
685
  children: React__default.ReactNode;
686
686
  className?: string;
687
687
  variant?: "default" | "muted" | "primary" | "accent" | "gradient";
688
- spacing?: "sm" | "md" | "lg" | "xl";
689
- fullWidth?: boolean;
688
+ /** Vertical padding (py). Default: "none" - không thêm padding dọc */
689
+ spacing?: "none" | "sm" | "md" | "lg" | "xl";
690
+ /** Horizontal padding (px). Default: "none" - không thêm padding ngang */
691
+ paddingX?: "none" | "sm" | "md" | "lg" | "xl";
692
+ /** Thêm container wrapper với mx-auto. Default: false */
693
+ contained?: boolean;
690
694
  /** Hiển thị viền mỏng xám nhạt giống Card */
691
695
  outlined?: boolean;
692
696
  /** Gradient start color (Tailwind class like 'from-purple-500') */
@@ -2096,6 +2100,13 @@ declare const underverseMessages: {
2096
2100
  normal: string;
2097
2101
  comfortable: string;
2098
2102
  columns: string;
2103
+ loading: string;
2104
+ noData: string;
2105
+ clearFilter: string;
2106
+ headerAlign: string;
2107
+ alignLeft: string;
2108
+ alignCenter: string;
2109
+ alignRight: string;
2099
2110
  };
2100
2111
  ValidationInput: {
2101
2112
  required: string;
@@ -2157,6 +2168,13 @@ declare const underverseMessages: {
2157
2168
  normal: string;
2158
2169
  comfortable: string;
2159
2170
  columns: string;
2171
+ loading: string;
2172
+ noData: string;
2173
+ clearFilter: string;
2174
+ headerAlign: string;
2175
+ alignLeft: string;
2176
+ alignCenter: string;
2177
+ alignRight: string;
2160
2178
  };
2161
2179
  ValidationInput: {
2162
2180
  required: string;
@@ -2218,6 +2236,13 @@ declare const underverseMessages: {
2218
2236
  normal: string;
2219
2237
  comfortable: string;
2220
2238
  columns: string;
2239
+ loading: string;
2240
+ noData: string;
2241
+ clearFilter: string;
2242
+ headerAlign: string;
2243
+ alignLeft: string;
2244
+ alignCenter: string;
2245
+ alignRight: string;
2221
2246
  };
2222
2247
  ValidationInput: {
2223
2248
  required: string;
@@ -2279,6 +2304,13 @@ declare const underverseMessages: {
2279
2304
  normal: string;
2280
2305
  comfortable: string;
2281
2306
  columns: string;
2307
+ loading: string;
2308
+ noData: string;
2309
+ clearFilter: string;
2310
+ headerAlign: string;
2311
+ alignLeft: string;
2312
+ alignCenter: string;
2313
+ alignRight: string;
2282
2314
  };
2283
2315
  ValidationInput: {
2284
2316
  required: string;
@@ -2342,6 +2374,13 @@ declare function getUnderverseMessages(locale?: UnderverseLocale): {
2342
2374
  normal: string;
2343
2375
  comfortable: string;
2344
2376
  columns: string;
2377
+ loading: string;
2378
+ noData: string;
2379
+ clearFilter: string;
2380
+ headerAlign: string;
2381
+ alignLeft: string;
2382
+ alignCenter: string;
2383
+ alignRight: string;
2345
2384
  };
2346
2385
  ValidationInput: {
2347
2386
  required: string;
@@ -2402,6 +2441,13 @@ declare function getUnderverseMessages(locale?: UnderverseLocale): {
2402
2441
  normal: string;
2403
2442
  comfortable: string;
2404
2443
  columns: string;
2444
+ loading: string;
2445
+ noData: string;
2446
+ clearFilter: string;
2447
+ headerAlign: string;
2448
+ alignLeft: string;
2449
+ alignCenter: string;
2450
+ alignRight: string;
2405
2451
  };
2406
2452
  ValidationInput: {
2407
2453
  required: string;
@@ -2462,6 +2508,13 @@ declare function getUnderverseMessages(locale?: UnderverseLocale): {
2462
2508
  normal: string;
2463
2509
  comfortable: string;
2464
2510
  columns: string;
2511
+ loading: string;
2512
+ noData: string;
2513
+ clearFilter: string;
2514
+ headerAlign: string;
2515
+ alignLeft: string;
2516
+ alignCenter: string;
2517
+ alignRight: string;
2465
2518
  };
2466
2519
  ValidationInput: {
2467
2520
  required: string;
@@ -2522,6 +2575,13 @@ declare function getUnderverseMessages(locale?: UnderverseLocale): {
2522
2575
  normal: string;
2523
2576
  comfortable: string;
2524
2577
  columns: string;
2578
+ loading: string;
2579
+ noData: string;
2580
+ clearFilter: string;
2581
+ headerAlign: string;
2582
+ alignLeft: string;
2583
+ alignCenter: string;
2584
+ alignRight: string;
2525
2585
  };
2526
2586
  ValidationInput: {
2527
2587
  required: string;
package/dist/index.js CHANGED
@@ -87,29 +87,32 @@ var Button = forwardRef(
87
87
  const SpinnerIcon = Spinner ?? Activity;
88
88
  const [locked, setLocked] = useState(false);
89
89
  const lockTimer = useRef(null);
90
- const handleClick = useCallback(async (e) => {
91
- if (disabled || loading2) return;
92
- if (preventDoubleClick) {
93
- if (locked) return;
94
- setLocked(true);
95
- try {
96
- const result = onClick?.(e);
97
- if (result && typeof result === "object" && typeof result.then === "function") {
98
- await result;
90
+ const handleClick = useCallback(
91
+ async (e) => {
92
+ if (disabled || loading2) return;
93
+ if (preventDoubleClick) {
94
+ if (locked) return;
95
+ setLocked(true);
96
+ try {
97
+ const result = onClick?.(e);
98
+ if (result && typeof result === "object" && typeof result.then === "function") {
99
+ await result;
100
+ setLocked(false);
101
+ } else {
102
+ const ms = lockMs ?? 600;
103
+ if (lockTimer.current) clearTimeout(lockTimer.current);
104
+ lockTimer.current = setTimeout(() => setLocked(false), ms);
105
+ }
106
+ } catch (err) {
99
107
  setLocked(false);
100
- } else {
101
- const ms = lockMs ?? 600;
102
- if (lockTimer.current) clearTimeout(lockTimer.current);
103
- lockTimer.current = setTimeout(() => setLocked(false), ms);
108
+ throw err;
104
109
  }
105
- } catch (err) {
106
- setLocked(false);
107
- throw err;
110
+ } else {
111
+ onClick?.(e);
108
112
  }
109
- } else {
110
- onClick?.(e);
111
- }
112
- }, [disabled, loading2, onClick, locked, preventDoubleClick, lockMs]);
113
+ },
114
+ [disabled, loading2, onClick, locked, preventDoubleClick, lockMs]
115
+ );
113
116
  const computedDisabled = disabled || loading2 || (preventDoubleClick ? locked : false);
114
117
  return /* @__PURE__ */ jsxs(
115
118
  "button",
@@ -140,15 +143,15 @@ var Button = forwardRef(
140
143
  "aria-label": rest["aria-label"] || title,
141
144
  ...rest,
142
145
  children: [
143
- !noHoverOverlay && /* @__PURE__ */ 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" }),
146
+ !noHoverOverlay ? /* @__PURE__ */ 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,
144
147
  loading2 ? /* @__PURE__ */ jsxs(Fragment, { children: [
145
- /* @__PURE__ */ jsx(SpinnerIcon, { className: "w-4 h-4 animate-spin" }),
146
- loadingText && /* @__PURE__ */ jsx("span", { className: "ml-2", "aria-live": "polite", children: loadingText }),
147
- preserveChildrenOnLoading && !loadingText && /* @__PURE__ */ jsx("span", { className: "ml-2 opacity-70", "aria-hidden": true, children })
148
+ /* @__PURE__ */ jsx(SpinnerIcon, { className: "w-4 h-4 animate-spin", "aria-hidden": "true" }),
149
+ loadingText ? /* @__PURE__ */ jsx("span", { className: "ml-2", "aria-live": "polite", children: loadingText }) : null,
150
+ preserveChildrenOnLoading && !loadingText ? /* @__PURE__ */ jsx("span", { className: "ml-2 opacity-70", "aria-hidden": true, children }) : null
148
151
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
149
- Icon && /* @__PURE__ */ jsx(Icon, { className: cn("transition-transform duration-200", iConClassName ? iConClassName : "w-5 h-5") }),
152
+ Icon ? /* @__PURE__ */ jsx(Icon, { className: cn("transition-transform duration-200", iConClassName ? iConClassName : "w-5 h-5") }) : null,
150
153
  children,
151
- IconRight && /* @__PURE__ */ jsx(IconRight, { className: "w-4 h-4 transition-transform duration-200" })
154
+ IconRight ? /* @__PURE__ */ jsx(IconRight, { className: "w-4 h-4 transition-transform duration-200" }) : null
152
155
  ] })
153
156
  ]
154
157
  }
@@ -417,7 +420,7 @@ var Card = ({
417
420
  "div",
418
421
  {
419
422
  className: cn(
420
- "rounded-lg md:rounded-xl bg-card text-card-foreground transition-all duration-300 ease-soft",
423
+ "rounded-lg md:rounded-xl bg-card text-card-foreground transition-[transform,box-shadow,border-color,background-color] duration-300 ease-soft",
421
424
  "shadow-sm md:hover:shadow-md mx-2 md:mx-0 border border-border",
422
425
  hoverable && "md:hover:-translate-y-0.5 md:hover:border-primary/15",
423
426
  clickable && "cursor-pointer active:translate-y-px md:hover:bg-accent/5",
@@ -990,6 +993,7 @@ var Input = forwardRef3(
990
993
  /* @__PURE__ */ jsxs5(
991
994
  "label",
992
995
  {
996
+ htmlFor: resolvedId,
993
997
  className: cn(
994
998
  // Label size follows input size
995
999
  size === "sm" ? "text-xs" : size === "lg" ? "text-base" : "text-sm",
@@ -1127,10 +1131,10 @@ var Input = forwardRef3(
1127
1131
  }
1128
1132
  )
1129
1133
  ] }),
1130
- errMsg && /* @__PURE__ */ jsxs5("div", { id: errorId, className: "flex items-center gap-2 text-sm text-destructive animate-in slide-in-from-top-1 duration-200", children: [
1134
+ errMsg ? /* @__PURE__ */ jsxs5("div", { id: errorId, className: "flex items-center gap-2 text-sm text-destructive animate-in slide-in-from-top-1 duration-200", children: [
1131
1135
  /* @__PURE__ */ jsx6(AlertCircle, { className: "w-4 h-4 shrink-0" }),
1132
1136
  /* @__PURE__ */ jsx6("span", { children: errMsg })
1133
- ] }),
1137
+ ] }) : null,
1134
1138
  (description || hint) && !errMsg && /* @__PURE__ */ jsx6(
1135
1139
  "p",
1136
1140
  {
@@ -1148,7 +1152,7 @@ var Input = forwardRef3(
1148
1152
  );
1149
1153
  Input.displayName = "Input";
1150
1154
  var SearchInput = forwardRef3(
1151
- ({ onSearch, searchDelay = 300, placeholder = "Search...", ...props }, ref) => {
1155
+ ({ onSearch, searchDelay = 300, placeholder = "Search\u2026", ...props }, ref) => {
1152
1156
  const [searchValue, setSearchValue] = useState4(props.value || "");
1153
1157
  React5.useEffect(() => {
1154
1158
  if (!onSearch) return;
@@ -1395,7 +1399,7 @@ var Textarea = forwardRef3(
1395
1399
  onBlur: () => setIsFocused(false),
1396
1400
  className: cn(
1397
1401
  "w-full rounded-lg px-4 py-3 text-sm text-foreground transition-all duration-200",
1398
- "placeholder:text-muted-foreground focus:outline-none min-h-[80px]",
1402
+ "placeholder:text-muted-foreground focus:outline-none min-h-20",
1399
1403
  "disabled:cursor-not-allowed disabled:opacity-50",
1400
1404
  variantStyles6[variant],
1401
1405
  // DÒNG NÀY ĐÃ ĐƯỢC CẬP NHẬT:
@@ -2853,6 +2857,7 @@ var Modal = ({
2853
2857
  "div",
2854
2858
  {
2855
2859
  className: cn("fixed inset-0 z-9999 flex items-center justify-center", overlayClassName),
2860
+ style: { overscrollBehavior: "contain" },
2856
2861
  onMouseDown: handleOverlayMouseDown,
2857
2862
  onMouseUp: handleOverlayMouseUp,
2858
2863
  children: [
@@ -2895,12 +2900,13 @@ var Modal = ({
2895
2900
  "button",
2896
2901
  {
2897
2902
  onClick: onClose,
2903
+ "aria-label": "Close modal",
2898
2904
  className: cn(
2899
2905
  "rounded-sm opacity-70 ring-offset-background transition-opacity",
2900
2906
  "hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
2901
2907
  "disabled:pointer-events-none "
2902
2908
  ),
2903
- children: /* @__PURE__ */ jsx15(X4, { className: "h-4 w-4 cursor-pointer" })
2909
+ children: /* @__PURE__ */ jsx15(X4, { className: "h-4 w-4 cursor-pointer", "aria-hidden": "true" })
2904
2910
  }
2905
2911
  )
2906
2912
  ] }),
@@ -3194,6 +3200,7 @@ var Tooltip = ({
3194
3200
  /* @__PURE__ */ jsx17(
3195
3201
  "div",
3196
3202
  {
3203
+ role: "tooltip",
3197
3204
  style: {
3198
3205
  position: "fixed",
3199
3206
  top: position.top,
@@ -4652,8 +4659,8 @@ var Combobox = ({
4652
4659
  options,
4653
4660
  value,
4654
4661
  onChange,
4655
- placeholder = "Select...",
4656
- searchPlaceholder = "Search...",
4662
+ placeholder = "Select\u2026",
4663
+ searchPlaceholder = "Search\u2026",
4657
4664
  emptyText = "No results found",
4658
4665
  className,
4659
4666
  disabled = false,
@@ -4815,7 +4822,7 @@ var Combobox = ({
4815
4822
  ] }),
4816
4823
  /* @__PURE__ */ jsx25("div", { className: "max-h-64 overflow-y-auto overscroll-contain", children: /* @__PURE__ */ jsx25("ul", { className: "p-1 space-y-1", children: loading2 ? /* @__PURE__ */ jsx25("li", { className: "px-3 py-8 text-center", children: /* @__PURE__ */ jsxs22("div", { className: "flex flex-col items-center gap-2 animate-in fade-in-0 zoom-in-95 duration-300", children: [
4817
4824
  /* @__PURE__ */ jsx25(Loader23, { className: "h-6 w-6 animate-spin text-primary" }),
4818
- /* @__PURE__ */ jsx25("span", { className: "text-sm text-muted-foreground", children: loadingText || "Loading..." })
4825
+ /* @__PURE__ */ jsx25("span", { className: "text-sm text-muted-foreground", children: loadingText || "Loading\u2026" })
4819
4826
  ] }) }) : filteredOptions.length > 0 ? filteredOptions.map((item, index) => {
4820
4827
  const itemValue = getOptionValue(item);
4821
4828
  const itemLabel = getOptionLabel(item);
@@ -4853,7 +4860,7 @@ var Combobox = ({
4853
4860
  }) : /* @__PURE__ */ jsx25("li", { className: "px-3 py-8 text-center text-muted-foreground text-sm", children: /* @__PURE__ */ jsxs22("div", { className: "flex flex-col items-center gap-2 animate-in fade-in-0 zoom-in-95 duration-300", children: [
4854
4861
  /* @__PURE__ */ jsx25(SearchX, { className: "h-8 w-8 opacity-40 text-muted-foreground" }),
4855
4862
  /* @__PURE__ */ jsx25("span", { className: "text-sm", children: emptyText }),
4856
- query && /* @__PURE__ */ jsx25("button", { type: "button", onClick: () => setQuery(""), className: "text-xs text-primary hover:underline", children: "Clear search" })
4863
+ query && /* @__PURE__ */ jsx25("button", { type: "button", onClick: () => setQuery(""), className: "text-xs text-primary hover:underline", children: "Clear" })
4857
4864
  ] }) }) }) })
4858
4865
  ] })
4859
4866
  }
@@ -4872,6 +4879,7 @@ var Combobox = ({
4872
4879
  "label",
4873
4880
  {
4874
4881
  id: labelId,
4882
+ htmlFor: resolvedId,
4875
4883
  onClick: () => triggerRef.current?.focus(),
4876
4884
  className: cn(
4877
4885
  labelSize,
@@ -5267,13 +5275,28 @@ var gradientDirectionMap = {
5267
5275
  "to-tr": "bg-linear-to-tr",
5268
5276
  "to-tl": "bg-linear-to-tl"
5269
5277
  };
5278
+ var spacingClasses = {
5279
+ none: "",
5280
+ sm: "py-6",
5281
+ md: "py-8",
5282
+ lg: "py-12",
5283
+ xl: "py-16"
5284
+ };
5285
+ var paddingXClasses = {
5286
+ none: "",
5287
+ sm: "px-2 md:px-4",
5288
+ md: "px-4 md:px-6",
5289
+ lg: "px-6 md:px-8",
5290
+ xl: "px-8 md:px-12"
5291
+ };
5270
5292
  var Section = React22.forwardRef(
5271
5293
  ({
5272
5294
  children,
5273
5295
  className,
5274
5296
  variant = "default",
5275
- spacing = "lg",
5276
- fullWidth = false,
5297
+ spacing = "none",
5298
+ paddingX = "none",
5299
+ contained = false,
5277
5300
  outlined = false,
5278
5301
  gradientFrom = "from-primary/20",
5279
5302
  gradientTo = "to-accent/20",
@@ -5287,12 +5310,6 @@ var Section = React22.forwardRef(
5287
5310
  accent: "bg-accent/10",
5288
5311
  gradient: ""
5289
5312
  };
5290
- const spacingClasses = {
5291
- sm: "py-6",
5292
- md: "py-8",
5293
- lg: "py-12",
5294
- xl: "py-16"
5295
- };
5296
5313
  const getGradientClasses = () => {
5297
5314
  if (variant !== "gradient") return "";
5298
5315
  return cn(gradientDirectionMap[gradientDirection], gradientFrom, gradientTo);
@@ -5304,8 +5321,9 @@ var Section = React22.forwardRef(
5304
5321
  className: cn(
5305
5322
  variant === "gradient" ? getGradientClasses() : variantClasses[variant],
5306
5323
  spacingClasses[spacing],
5324
+ paddingXClasses[paddingX],
5307
5325
  outlined && "rounded-lg border border-border/60",
5308
- !fullWidth && "container mx-auto px-4 md:px-6",
5326
+ contained && "container mx-auto",
5309
5327
  className
5310
5328
  ),
5311
5329
  ...props,
@@ -5563,6 +5581,7 @@ var DatePicker = ({
5563
5581
  "label",
5564
5582
  {
5565
5583
  id: labelId,
5584
+ htmlFor: resolvedId,
5566
5585
  onClick: () => triggerRef.current?.focus(),
5567
5586
  className: cn(
5568
5587
  labelSize,
@@ -11917,7 +11936,7 @@ function DataTable({
11917
11936
  const [curPage, setCurPage] = React47.useState(page);
11918
11937
  const hasMounted = React47.useRef(false);
11919
11938
  const loadedFromStorage = React47.useRef(false);
11920
- const getInitialPageSize = React47.useCallback(() => {
11939
+ const [curPageSize, setCurPageSize] = React47.useState(() => {
11921
11940
  if (typeof window === "undefined" || !storageKey) return pageSize;
11922
11941
  try {
11923
11942
  const saved = localStorage.getItem(`datatable_${storageKey}_pageSize`);
@@ -11931,8 +11950,7 @@ function DataTable({
11931
11950
  } catch {
11932
11951
  }
11933
11952
  return pageSize;
11934
- }, [storageKey, pageSize]);
11935
- const [curPageSize, setCurPageSize] = React47.useState(getInitialPageSize);
11953
+ });
11936
11954
  React47.useEffect(() => {
11937
11955
  if (typeof window === "undefined" || !storageKey) return;
11938
11956
  if (!hasMounted.current) return;
@@ -11968,7 +11986,8 @@ function DataTable({
11968
11986
  }, [debouncedFilters, sort, curPage, curPageSize]);
11969
11987
  const densityRowClass = density === "compact" ? "h-9" : density === "comfortable" ? "h-14" : "h-12";
11970
11988
  const cellPadding = density === "compact" ? "py-1.5 px-3" : density === "comfortable" ? "py-3 px-4" : "py-2.5 px-4";
11971
- const visibleColumns = columns.filter((c) => visibleCols.includes(c.key));
11989
+ const visibleColsSet = React47.useMemo(() => new Set(visibleCols), [visibleCols]);
11990
+ const visibleColumns = columns.filter((c) => visibleColsSet.has(c.key));
11972
11991
  const getRowKey = (row, idx) => {
11973
11992
  if (!rowKey) return String(idx);
11974
11993
  if (typeof rowKey === "function") return String(rowKey(row));
@@ -12120,7 +12139,7 @@ function DataTable({
12120
12139
  });
12121
12140
  },
12122
12141
  className: "text-xs text-destructive hover:underline",
12123
- children: "Clear filter"
12142
+ children: t("clearFilter")
12124
12143
  }
12125
12144
  )
12126
12145
  ] })
@@ -12271,27 +12290,42 @@ function DataTable({
12271
12290
  }
12272
12291
  )
12273
12292
  ] }),
12274
- /* @__PURE__ */ jsx56("span", { className: "text-sm", children: "Loading..." })
12275
- ] }) }) }) : !displayedData || displayedData.length === 0 ? /* @__PURE__ */ jsx56(TableRow, { children: /* @__PURE__ */ jsx56(TableCell, { colSpan: visibleColumns.length, className: "text-center py-6 text-muted-foreground", children: "No data" }) }) : displayedData.map((row, idx) => {
12293
+ /* @__PURE__ */ jsxs50("span", { className: "text-sm", children: [
12294
+ t("loading"),
12295
+ "\u2026"
12296
+ ] })
12297
+ ] }) }) }) : !displayedData || displayedData.length === 0 ? /* @__PURE__ */ jsx56(TableRow, { children: /* @__PURE__ */ jsx56(TableCell, { colSpan: visibleColumns.length, className: "text-center py-6 text-muted-foreground", children: t("noData") }) }) : displayedData.map((row, idx) => {
12276
12298
  const isLastRow = idx === displayedData.length - 1;
12277
- return /* @__PURE__ */ jsx56(TableRow, { className: cn(densityRowClass, striped && idx % 2 === 0 && "bg-muted/50"), children: visibleColumns.map((col, colIdx) => {
12278
- const value = col.dataIndex ? row[col.dataIndex] : void 0;
12279
- return /* @__PURE__ */ jsx56(
12280
- TableCell,
12281
- {
12282
- className: cn(
12283
- cellPadding,
12284
- col.align === "right" && "text-right",
12285
- col.align === "center" && "text-center",
12286
- columnDividers && colIdx > 0 && "border-l border-border/60",
12287
- isLastRow && col === visibleColumns[0] && "rounded-bl-md",
12288
- isLastRow && col === visibleColumns[visibleColumns.length - 1] && "rounded-br-md"
12289
- ),
12290
- children: col.render ? col.render(value, row, idx) : String(value ?? "")
12299
+ return /* @__PURE__ */ jsx56(
12300
+ TableRow,
12301
+ {
12302
+ className: cn(densityRowClass, striped && idx % 2 === 0 && "bg-muted/50"),
12303
+ style: {
12304
+ // content-visibility: auto for rendering performance (skip off-screen rows)
12305
+ contentVisibility: "auto",
12306
+ containIntrinsicSize: density === "compact" ? "0 36px" : density === "comfortable" ? "0 56px" : "0 48px"
12291
12307
  },
12292
- col.key
12293
- );
12294
- }) }, getRowKey(row, idx));
12308
+ children: visibleColumns.map((col, colIdx) => {
12309
+ const value = col.dataIndex ? row[col.dataIndex] : void 0;
12310
+ return /* @__PURE__ */ jsx56(
12311
+ TableCell,
12312
+ {
12313
+ className: cn(
12314
+ cellPadding,
12315
+ col.align === "right" && "text-right",
12316
+ col.align === "center" && "text-center",
12317
+ columnDividers && colIdx > 0 && "border-l border-border/60",
12318
+ isLastRow && col === visibleColumns[0] && "rounded-bl-md",
12319
+ isLastRow && col === visibleColumns[visibleColumns.length - 1] && "rounded-br-md"
12320
+ ),
12321
+ children: col.render ? col.render(value, row, idx) : String(value ?? "")
12322
+ },
12323
+ col.key
12324
+ );
12325
+ })
12326
+ },
12327
+ getRowKey(row, idx)
12328
+ );
12295
12329
  }) })
12296
12330
  ]
12297
12331
  }
@@ -13304,7 +13338,14 @@ var en_default = {
13304
13338
  compact: "Compact",
13305
13339
  normal: "Normal",
13306
13340
  comfortable: "Comfortable",
13307
- columns: "Columns"
13341
+ columns: "Columns",
13342
+ loading: "Loading",
13343
+ noData: "No data",
13344
+ clearFilter: "Clear filter",
13345
+ headerAlign: "Header alignment",
13346
+ alignLeft: "Align left",
13347
+ alignCenter: "Align center",
13348
+ alignRight: "Align right"
13308
13349
  },
13309
13350
  ValidationInput: {
13310
13351
  required: "This field is required",
@@ -13367,7 +13408,14 @@ var vi_default = {
13367
13408
  compact: "G\u1ECDn",
13368
13409
  normal: "Th\u01B0\u1EDDng",
13369
13410
  comfortable: "Tho\u1EA3i m\xE1i",
13370
- columns: "C\u1ED9t"
13411
+ columns: "C\u1ED9t",
13412
+ loading: "\u0110ang t\u1EA3i",
13413
+ noData: "Kh\xF4ng c\xF3 d\u1EEF li\u1EC7u",
13414
+ clearFilter: "X\xF3a b\u1ED9 l\u1ECDc",
13415
+ headerAlign: "C\u0103n ch\u1EC9nh ti\xEAu \u0111\u1EC1",
13416
+ alignLeft: "C\u0103n tr\xE1i",
13417
+ alignCenter: "C\u0103n gi\u1EEFa",
13418
+ alignRight: "C\u0103n ph\u1EA3i"
13371
13419
  },
13372
13420
  ValidationInput: {
13373
13421
  required: "Tr\u01B0\u1EDDng n\xE0y l\xE0 b\u1EAFt bu\u1ED9c",
@@ -13430,7 +13478,14 @@ var ko_default = {
13430
13478
  compact: "\uCEF4\uD329\uD2B8",
13431
13479
  normal: "\uBCF4\uD1B5",
13432
13480
  comfortable: "\uC5EC\uC720",
13433
- columns: "\uC5F4"
13481
+ columns: "\uC5F4",
13482
+ loading: "\uB85C\uB529 \uC911",
13483
+ noData: "\uB370\uC774\uD130 \uC5C6\uC74C",
13484
+ clearFilter: "\uD544\uD130 \uC9C0\uC6B0\uAE30",
13485
+ headerAlign: "\uD5E4\uB354 \uC815\uB82C",
13486
+ alignLeft: "\uC67C\uCABD \uC815\uB82C",
13487
+ alignCenter: "\uAC00\uC6B4\uB370 \uC815\uB82C",
13488
+ alignRight: "\uC624\uB978\uCABD \uC815\uB82C"
13434
13489
  },
13435
13490
  ValidationInput: {
13436
13491
  required: "\uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4",
@@ -13493,7 +13548,14 @@ var ja_default = {
13493
13548
  compact: "\u30B3\u30F3\u30D1\u30AF\u30C8",
13494
13549
  normal: "\u901A\u5E38",
13495
13550
  comfortable: "\u3086\u3063\u305F\u308A",
13496
- columns: "\u5217"
13551
+ columns: "\u5217",
13552
+ loading: "\u8AAD\u307F\u8FBC\u307F\u4E2D",
13553
+ noData: "\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093",
13554
+ clearFilter: "\u30D5\u30A3\u30EB\u30BF\u30FC\u3092\u30AF\u30EA\u30A2",
13555
+ headerAlign: "\u30D8\u30C3\u30C0\u30FC\u914D\u7F6E",
13556
+ alignLeft: "\u5DE6\u63C3\u3048",
13557
+ alignCenter: "\u4E2D\u592E\u63C3\u3048",
13558
+ alignRight: "\u53F3\u63C3\u3048"
13497
13559
  },
13498
13560
  ValidationInput: {
13499
13561
  required: "\u3053\u306E\u9805\u76EE\u306F\u5FC5\u9808\u3067\u3059",