@underverse-ui/underverse 0.1.25 → 0.1.28

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.js CHANGED
@@ -5758,6 +5758,8 @@ var Slider = React24.forwardRef(
5758
5758
  step = 1,
5759
5759
  onChange,
5760
5760
  onValueChange,
5761
+ onMouseUp,
5762
+ onTouchEnd,
5761
5763
  label,
5762
5764
  labelClassName,
5763
5765
  containerClassName,
@@ -5811,6 +5813,8 @@ var Slider = React24.forwardRef(
5811
5813
  step,
5812
5814
  value: currentValue,
5813
5815
  onChange: handleChange,
5816
+ onMouseUp,
5817
+ onTouchEnd,
5814
5818
  disabled,
5815
5819
  className: cn(
5816
5820
  // Base styles
@@ -5862,10 +5866,441 @@ var Slider = React24.forwardRef(
5862
5866
  );
5863
5867
  Slider.displayName = "Slider";
5864
5868
 
5869
+ // ../../components/ui/OverlayControls.tsx
5870
+ import { Dot, Maximize2, Pause, Play, RotateCcw, RotateCw, Volume2, VolumeX } from "lucide-react";
5871
+ import React25 from "react";
5872
+ import { Fragment as Fragment7, jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
5873
+ function OverlayControls({
5874
+ mode,
5875
+ value,
5876
+ max,
5877
+ step = 0.1,
5878
+ onChange,
5879
+ onCommit,
5880
+ playing = false,
5881
+ onTogglePlay,
5882
+ onGoLive,
5883
+ volume,
5884
+ muted,
5885
+ onVolumeChange,
5886
+ onToggleMute,
5887
+ rate = 1,
5888
+ onChangeRate,
5889
+ onToggleFullscreen,
5890
+ showOnHover = false,
5891
+ className,
5892
+ showTime,
5893
+ skipSeconds = 10,
5894
+ onSkip,
5895
+ onSeekPreview,
5896
+ autoHide = false,
5897
+ autoHideDelay = 3e3,
5898
+ enableKeyboardShortcuts = true
5899
+ }) {
5900
+ const hoverClasses = showOnHover ? "opacity-0 pointer-events-none group-hover:opacity-100 group-hover:pointer-events-auto" : "opacity-100 pointer-events-auto";
5901
+ const showControlsBar = mode === "review";
5902
+ const [rateOpen, setRateOpen] = React25.useState(false);
5903
+ const rateWrapRef = React25.useRef(null);
5904
+ const [controlsVisible, setControlsVisible] = React25.useState(true);
5905
+ const hideTimerRef = React25.useRef(null);
5906
+ const [previewData, setPreviewData] = React25.useState(null);
5907
+ const sliderRef = React25.useRef(null);
5908
+ const [isDragging, setIsDragging] = React25.useState(false);
5909
+ const [dragValue, setDragValue] = React25.useState(value);
5910
+ React25.useEffect(() => {
5911
+ if (!isDragging) {
5912
+ setDragValue(value);
5913
+ }
5914
+ }, [value, isDragging]);
5915
+ const [keyboardFeedback, setKeyboardFeedback] = React25.useState(null);
5916
+ const feedbackTimerRef = React25.useRef(null);
5917
+ const seekAccumulatorRef = React25.useRef(0);
5918
+ const seekAccumulatorTimerRef = React25.useRef(null);
5919
+ React25.useEffect(() => {
5920
+ const onDocDown = (e) => {
5921
+ if (!rateOpen) return;
5922
+ const wrap = rateWrapRef.current;
5923
+ if (wrap && !wrap.contains(e.target)) {
5924
+ setRateOpen(false);
5925
+ }
5926
+ };
5927
+ document.addEventListener("mousedown", onDocDown);
5928
+ return () => document.removeEventListener("mousedown", onDocDown);
5929
+ }, [rateOpen]);
5930
+ React25.useEffect(() => {
5931
+ if (!autoHide || showOnHover) return;
5932
+ const resetTimer = () => {
5933
+ if (hideTimerRef.current) clearTimeout(hideTimerRef.current);
5934
+ setControlsVisible(true);
5935
+ hideTimerRef.current = setTimeout(() => {
5936
+ setControlsVisible(false);
5937
+ }, autoHideDelay);
5938
+ };
5939
+ const handleMouseMove = () => resetTimer();
5940
+ const handleMouseLeave = () => {
5941
+ if (hideTimerRef.current) clearTimeout(hideTimerRef.current);
5942
+ hideTimerRef.current = setTimeout(() => {
5943
+ setControlsVisible(false);
5944
+ }, autoHideDelay);
5945
+ };
5946
+ resetTimer();
5947
+ document.addEventListener("mousemove", handleMouseMove);
5948
+ return () => {
5949
+ if (hideTimerRef.current) clearTimeout(hideTimerRef.current);
5950
+ document.removeEventListener("mousemove", handleMouseMove);
5951
+ };
5952
+ }, [autoHide, autoHideDelay, showOnHover]);
5953
+ const showFeedback = (type, value2) => {
5954
+ if (feedbackTimerRef.current) clearTimeout(feedbackTimerRef.current);
5955
+ setKeyboardFeedback({ type, value: value2 });
5956
+ feedbackTimerRef.current = setTimeout(() => {
5957
+ setKeyboardFeedback(null);
5958
+ }, 800);
5959
+ };
5960
+ const accumulateSeek = (seconds) => {
5961
+ if (seekAccumulatorTimerRef.current) clearTimeout(seekAccumulatorTimerRef.current);
5962
+ seekAccumulatorRef.current += seconds;
5963
+ showFeedback("seek", seekAccumulatorRef.current);
5964
+ seekAccumulatorTimerRef.current = setTimeout(() => {
5965
+ seekAccumulatorRef.current = 0;
5966
+ }, 1e3);
5967
+ };
5968
+ React25.useEffect(() => {
5969
+ if (!enableKeyboardShortcuts) return;
5970
+ const handleKeyDown = (e) => {
5971
+ if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;
5972
+ switch (e.key) {
5973
+ case " ":
5974
+ case "k":
5975
+ e.preventDefault();
5976
+ onTogglePlay?.();
5977
+ showFeedback(playing ? "pause" : "play");
5978
+ break;
5979
+ case "ArrowLeft":
5980
+ e.preventDefault();
5981
+ if (e.shiftKey) {
5982
+ onSkip?.(-skipSeconds);
5983
+ accumulateSeek(-skipSeconds);
5984
+ } else {
5985
+ {
5986
+ const newTime = Math.max(0, value - 5);
5987
+ onChange(newTime);
5988
+ onCommit?.(newTime);
5989
+ }
5990
+ accumulateSeek(-5);
5991
+ }
5992
+ break;
5993
+ case "ArrowRight":
5994
+ e.preventDefault();
5995
+ if (e.shiftKey) {
5996
+ onSkip?.(skipSeconds);
5997
+ accumulateSeek(skipSeconds);
5998
+ } else {
5999
+ {
6000
+ const newTime = Math.min(max, value + 5);
6001
+ onChange(newTime);
6002
+ onCommit?.(newTime);
6003
+ }
6004
+ accumulateSeek(5);
6005
+ }
6006
+ break;
6007
+ case "ArrowUp":
6008
+ e.preventDefault();
6009
+ if (onVolumeChange && volume !== void 0) {
6010
+ const newVolume = Math.min(1, volume + 0.05);
6011
+ onVolumeChange(newVolume);
6012
+ showFeedback("volume", Math.round(newVolume * 100));
6013
+ }
6014
+ break;
6015
+ case "ArrowDown":
6016
+ e.preventDefault();
6017
+ if (onVolumeChange && volume !== void 0) {
6018
+ const newVolume = Math.max(0, volume - 0.05);
6019
+ onVolumeChange(newVolume);
6020
+ showFeedback("volume", Math.round(newVolume * 100));
6021
+ }
6022
+ break;
6023
+ case "f":
6024
+ case "F":
6025
+ e.preventDefault();
6026
+ onToggleFullscreen?.();
6027
+ break;
6028
+ case "m":
6029
+ case "M":
6030
+ e.preventDefault();
6031
+ onToggleMute?.();
6032
+ showFeedback(muted ? "unmute" : "mute");
6033
+ break;
6034
+ case "j":
6035
+ e.preventDefault();
6036
+ onSkip?.(-skipSeconds);
6037
+ accumulateSeek(-skipSeconds);
6038
+ break;
6039
+ case "l":
6040
+ e.preventDefault();
6041
+ onSkip?.(skipSeconds);
6042
+ accumulateSeek(skipSeconds);
6043
+ break;
6044
+ default:
6045
+ if (e.key >= "0" && e.key <= "9") {
6046
+ e.preventDefault();
6047
+ const percent = parseInt(e.key) * 10;
6048
+ const newTime = percent / 100 * max;
6049
+ onChange(newTime);
6050
+ onCommit?.(newTime);
6051
+ }
6052
+ break;
6053
+ }
6054
+ };
6055
+ document.addEventListener("keydown", handleKeyDown);
6056
+ return () => document.removeEventListener("keydown", handleKeyDown);
6057
+ }, [
6058
+ enableKeyboardShortcuts,
6059
+ mode,
6060
+ onTogglePlay,
6061
+ onSkip,
6062
+ skipSeconds,
6063
+ onChange,
6064
+ value,
6065
+ max,
6066
+ onVolumeChange,
6067
+ volume,
6068
+ onToggleFullscreen,
6069
+ onToggleMute,
6070
+ playing,
6071
+ muted
6072
+ ]);
6073
+ const formatTime2 = (sec) => {
6074
+ if (!isFinite(sec) || sec < 0) return "0:00";
6075
+ const h = Math.floor(sec / 3600);
6076
+ const m = Math.floor(sec % 3600 / 60);
6077
+ const s = Math.floor(sec % 60);
6078
+ if (h > 0) return `${h}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
6079
+ return `${m}:${String(s).padStart(2, "0")}`;
6080
+ };
6081
+ const handleSliderMouseMove = (e) => {
6082
+ if (!sliderRef.current) return;
6083
+ const rect = sliderRef.current.getBoundingClientRect();
6084
+ const x = e.clientX - rect.left;
6085
+ const percent = Math.max(0, Math.min(1, x / rect.width));
6086
+ const time = percent * max;
6087
+ const thumbnailUrl = onSeekPreview ? onSeekPreview(time) : void 0;
6088
+ setPreviewData({ time, x: e.clientX - rect.left, url: thumbnailUrl });
6089
+ };
6090
+ const handleSliderMouseLeave = () => {
6091
+ setPreviewData(null);
6092
+ };
6093
+ return /* @__PURE__ */ jsxs27(Fragment7, { children: [
6094
+ keyboardFeedback && /* @__PURE__ */ jsx31(
6095
+ "div",
6096
+ {
6097
+ className: cn(
6098
+ "absolute inset-0 flex items-center pointer-events-none z-50",
6099
+ keyboardFeedback.type === "seek" && (keyboardFeedback.value ?? 0) > 0 ? "justify-end pr-32" : keyboardFeedback.type === "seek" && (keyboardFeedback.value ?? 0) < 0 ? "justify-start pl-32" : "justify-center"
6100
+ ),
6101
+ children: /* @__PURE__ */ jsxs27("div", { className: "bg-black/50 backdrop-blur-sm rounded-xl px-6 py-4 shadow-xl border border-white/10 animate-in fade-in zoom-in duration-200", children: [
6102
+ keyboardFeedback.type === "play" && /* @__PURE__ */ jsx31(Play, { className: "w-16 h-16 text-white", fill: "white" }),
6103
+ keyboardFeedback.type === "pause" && /* @__PURE__ */ jsx31(Pause, { className: "w-16 h-16 text-white", fill: "white" }),
6104
+ keyboardFeedback.type === "seek" && /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-3", children: [
6105
+ (keyboardFeedback.value ?? 0) > 0 ? /* @__PURE__ */ jsx31(RotateCw, { className: "w-12 h-12 text-white" }) : /* @__PURE__ */ jsx31(RotateCcw, { className: "w-12 h-12 text-white" }),
6106
+ /* @__PURE__ */ jsxs27("span", { className: "text-3xl font-bold text-white", children: [
6107
+ keyboardFeedback.value && keyboardFeedback.value > 0 ? "+" : "",
6108
+ keyboardFeedback.value,
6109
+ "s"
6110
+ ] })
6111
+ ] }),
6112
+ keyboardFeedback.type === "volume" && /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-3", children: [
6113
+ /* @__PURE__ */ jsx31(Volume2, { className: "w-12 h-12 text-white" }),
6114
+ /* @__PURE__ */ jsxs27("div", { className: "flex flex-col gap-1.5", children: [
6115
+ /* @__PURE__ */ jsxs27("span", { className: "text-2xl font-bold text-white", children: [
6116
+ keyboardFeedback.value,
6117
+ "%"
6118
+ ] }),
6119
+ /* @__PURE__ */ jsx31("div", { className: "w-32 h-1.5 bg-white/30 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx31("div", { className: "h-full bg-white rounded-full transition-all", style: { width: `${keyboardFeedback.value}%` } }) })
6120
+ ] })
6121
+ ] }),
6122
+ keyboardFeedback.type === "mute" && /* @__PURE__ */ jsx31(VolumeX, { className: "w-16 h-16 text-white" }),
6123
+ keyboardFeedback.type === "unmute" && /* @__PURE__ */ jsx31(Volume2, { className: "w-16 h-16 text-white" })
6124
+ ] })
6125
+ }
6126
+ ),
6127
+ /* @__PURE__ */ jsx31(
6128
+ "div",
6129
+ {
6130
+ className: cn(
6131
+ "absolute bottom-0 left-0 right-0 pb-2 pt-8 bg-gradient-to-t from-black/40 to-transparent z-20 transition-opacity duration-200",
6132
+ hoverClasses,
6133
+ autoHide && !controlsVisible && "opacity-0 pointer-events-none",
6134
+ className
6135
+ ),
6136
+ children: /* @__PURE__ */ jsxs27("div", { className: "px-4", children: [
6137
+ /* @__PURE__ */ jsxs27("div", { ref: sliderRef, onMouseMove: handleSliderMouseMove, onMouseLeave: handleSliderMouseLeave, className: "relative", children: [
6138
+ /* @__PURE__ */ jsx31(
6139
+ Slider,
6140
+ {
6141
+ min: 0,
6142
+ max: max || 0,
6143
+ step,
6144
+ value: dragValue,
6145
+ onValueChange: (v) => {
6146
+ setIsDragging(true);
6147
+ setDragValue(v);
6148
+ onChange(v);
6149
+ },
6150
+ onMouseUp: () => {
6151
+ onCommit?.(dragValue);
6152
+ setIsDragging(false);
6153
+ },
6154
+ onTouchEnd: () => {
6155
+ onCommit?.(dragValue);
6156
+ setIsDragging(false);
6157
+ },
6158
+ trackClassName: "bg-muted",
6159
+ size: "sm",
6160
+ noFocus: true
6161
+ }
6162
+ ),
6163
+ previewData && /* @__PURE__ */ jsx31("div", { className: "absolute bottom-full mb-2 transform -translate-x-1/2 pointer-events-none z-30", style: { left: `${previewData.x}px` }, children: previewData.url ? /* @__PURE__ */ jsxs27("div", { className: "bg-background/95 backdrop-blur rounded-md border border-border shadow-lg overflow-hidden", children: [
6164
+ /* @__PURE__ */ jsx31("img", { src: previewData.url, alt: "Preview", className: "w-40 h-24 object-cover" }),
6165
+ /* @__PURE__ */ jsx31("div", { className: "px-2 py-1 text-xs font-mono text-center bg-background/80", children: formatTime2(previewData.time) })
6166
+ ] }) : /* @__PURE__ */ jsx31("div", { className: "px-3 py-1.5 rounded-md bg-background/90 backdrop-blur border border-border shadow-lg", children: /* @__PURE__ */ jsx31("div", { className: "text-xs font-mono text-center", children: formatTime2(previewData.time) }) }) })
6167
+ ] }),
6168
+ showControlsBar && /* @__PURE__ */ jsxs27("div", { className: "mt-2 flex items-center justify-between gap-2", children: [
6169
+ /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2", children: [
6170
+ /* @__PURE__ */ jsx31(
6171
+ Button_default,
6172
+ {
6173
+ variant: "ghost",
6174
+ size: "icon",
6175
+ onClick: onTogglePlay,
6176
+ title: playing ? "T\u1EA1m d\u1EEBng" : "Ph\xE1t",
6177
+ className: "bg-background/60 hover:bg-background/80 border-transparent shadow-sm outline-none focus:outline-none focus:ring-0",
6178
+ children: playing ? /* @__PURE__ */ jsx31(Pause, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx31(Play, { className: "w-4 h-4" })
6179
+ }
6180
+ ),
6181
+ onSkip && /* @__PURE__ */ jsx31(
6182
+ Button_default,
6183
+ {
6184
+ variant: "ghost",
6185
+ size: "icon",
6186
+ onClick: () => onSkip(-skipSeconds),
6187
+ title: `L\xF9i ${skipSeconds}s`,
6188
+ className: "bg-background/60 hover:bg-background/80 border-transparent shadow-sm outline-none focus:outline-none focus:ring-0",
6189
+ children: /* @__PURE__ */ jsx31(RotateCcw, { className: "w-4 h-4" })
6190
+ }
6191
+ ),
6192
+ onSkip && /* @__PURE__ */ jsx31(
6193
+ Button_default,
6194
+ {
6195
+ variant: "ghost",
6196
+ size: "icon",
6197
+ onClick: () => onSkip(skipSeconds),
6198
+ title: `Tua ${skipSeconds}s`,
6199
+ className: "bg-background/60 hover:bg-background/80 border-transparent shadow-sm outline-none focus:outline-none focus:ring-0",
6200
+ children: /* @__PURE__ */ jsx31(RotateCw, { className: "w-4 h-4" })
6201
+ }
6202
+ ),
6203
+ (showTime ?? true) && /* @__PURE__ */ jsxs27("span", { className: "px-3 py-1 rounded-full text-xs font-mono bg-background/60 text-foreground shadow-sm border border-border whitespace-nowrap", children: [
6204
+ formatTime2(dragValue),
6205
+ " / ",
6206
+ formatTime2(max)
6207
+ ] }),
6208
+ /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2", children: [
6209
+ /* @__PURE__ */ jsx31(
6210
+ Button_default,
6211
+ {
6212
+ variant: "ghost",
6213
+ size: "icon",
6214
+ onClick: onToggleMute,
6215
+ title: muted ? "B\u1EADt ti\u1EBFng" : "T\u1EAFt ti\u1EBFng",
6216
+ className: "bg-background/60 hover:bg-background/80 border-transparent shadow-sm outline-none focus:outline-none focus:ring-0",
6217
+ children: muted || (volume ?? 1) === 0 ? /* @__PURE__ */ jsx31(VolumeX, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx31(Volume2, { className: "w-4 h-4" })
6218
+ }
6219
+ ),
6220
+ /* @__PURE__ */ jsx31("div", { className: "w-24", children: /* @__PURE__ */ jsx31(
6221
+ Slider,
6222
+ {
6223
+ min: 0,
6224
+ max: 1,
6225
+ step: 0.05,
6226
+ value: Math.max(0, Math.min(volume ?? 1, 1)),
6227
+ onValueChange: (v) => onVolumeChange?.(v),
6228
+ trackClassName: "bg-muted",
6229
+ size: "sm",
6230
+ noFocus: true
6231
+ }
6232
+ ) })
6233
+ ] })
6234
+ ] }),
6235
+ /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2 relative", children: [
6236
+ onGoLive && /* @__PURE__ */ jsxs27(
6237
+ Button_default,
6238
+ {
6239
+ variant: "ghost",
6240
+ size: "sm",
6241
+ onClick: onGoLive,
6242
+ title: "Tr\u1EF1c ti\u1EBFp (v\u1EC1 Live)",
6243
+ className: "bg-background/60 hover:bg-background/80 border-transparent shadow-sm outline-none focus:outline-none focus:ring-0",
6244
+ children: [
6245
+ /* @__PURE__ */ jsx31(Dot, { className: "w-10 h-10 text-destructive" }),
6246
+ "Tr\u1EF1c ti\u1EBFp"
6247
+ ]
6248
+ }
6249
+ ),
6250
+ onChangeRate && /* @__PURE__ */ jsxs27("div", { className: "relative", ref: rateWrapRef, children: [
6251
+ /* @__PURE__ */ jsxs27(
6252
+ Button_default,
6253
+ {
6254
+ variant: "ghost",
6255
+ size: "sm",
6256
+ onClick: () => setRateOpen((o) => !o),
6257
+ title: "T\u1ED1c \u0111\u1ED9 ph\xE1t",
6258
+ className: "bg-background/60 hover:bg-background/80 border-transparent shadow-sm outline-none focus:outline-none focus:ring-0",
6259
+ children: [
6260
+ rate,
6261
+ "x"
6262
+ ]
6263
+ }
6264
+ ),
6265
+ rateOpen && /* @__PURE__ */ jsx31("div", { className: "absolute bottom-9 right-0 bg-background/90 backdrop-blur rounded-md border border-border shadow-lg p-1 z-30", children: [0.5, 0.75, 1, 1.25, 1.5].map((r) => /* @__PURE__ */ jsxs27(
6266
+ "button",
6267
+ {
6268
+ onClick: () => {
6269
+ onChangeRate(r);
6270
+ setRateOpen(false);
6271
+ },
6272
+ className: cn("block w-full text-left px-3 py-1 text-sm rounded hover:bg-accent", rate === r && "bg-accent"),
6273
+ children: [
6274
+ r,
6275
+ "x"
6276
+ ]
6277
+ },
6278
+ r
6279
+ )) })
6280
+ ] }),
6281
+ onToggleFullscreen && /* @__PURE__ */ jsx31(
6282
+ Button_default,
6283
+ {
6284
+ variant: "ghost",
6285
+ size: "sm",
6286
+ onClick: onToggleFullscreen,
6287
+ title: "To\xE0n m\xE0n h\xECnh",
6288
+ className: "px-3 bg-background/60 hover:bg-background/80 border-transparent shadow-sm outline-none focus:outline-none focus:ring-0",
6289
+ children: /* @__PURE__ */ jsx31(Maximize2, { className: "w-4 h-4" })
6290
+ }
6291
+ )
6292
+ ] })
6293
+ ] })
6294
+ ] })
6295
+ }
6296
+ )
6297
+ ] });
6298
+ }
6299
+
5865
6300
  // ../../components/ui/CategoryTreeSelect.tsx
5866
6301
  import { useState as useState23 } from "react";
5867
6302
  import { ChevronRight as ChevronRight4, ChevronDown as ChevronDown3, Check as Check5 } from "lucide-react";
5868
- import { Fragment as Fragment7, jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
6303
+ import { Fragment as Fragment8, jsx as jsx32, jsxs as jsxs28 } from "react/jsx-runtime";
5869
6304
  function CategoryTreeSelect({ categories, value, onChange, placeholder = "Ch\u1ECDn danh m\u1EE5c", disabled }) {
5870
6305
  const [isOpen, setIsOpen] = useState23(false);
5871
6306
  const [expandedNodes, setExpandedNodes] = useState23(/* @__PURE__ */ new Set());
@@ -5907,8 +6342,8 @@ function CategoryTreeSelect({ categories, value, onChange, placeholder = "Ch\u1E
5907
6342
  const hasChildren = children.length > 0;
5908
6343
  const isExpanded = expandedNodes.has(category.id);
5909
6344
  const isSelected = value.includes(category.id);
5910
- return /* @__PURE__ */ jsxs27("div", { children: [
5911
- /* @__PURE__ */ jsxs27(
6345
+ return /* @__PURE__ */ jsxs28("div", { children: [
6346
+ /* @__PURE__ */ jsxs28(
5912
6347
  "div",
5913
6348
  {
5914
6349
  className: cn(
@@ -5918,7 +6353,7 @@ function CategoryTreeSelect({ categories, value, onChange, placeholder = "Ch\u1E
5918
6353
  ),
5919
6354
  style: { paddingLeft: `${level * 1.5 + 0.75}rem` },
5920
6355
  children: [
5921
- hasChildren ? /* @__PURE__ */ jsx31(
6356
+ hasChildren ? /* @__PURE__ */ jsx32(
5922
6357
  "button",
5923
6358
  {
5924
6359
  type: "button",
@@ -5927,39 +6362,39 @@ function CategoryTreeSelect({ categories, value, onChange, placeholder = "Ch\u1E
5927
6362
  toggleExpand(category.id);
5928
6363
  },
5929
6364
  className: "p-0.5 hover:bg-accent rounded",
5930
- children: isExpanded ? /* @__PURE__ */ jsx31(ChevronDown3, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx31(ChevronRight4, { className: "w-4 h-4" })
6365
+ children: isExpanded ? /* @__PURE__ */ jsx32(ChevronDown3, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx32(ChevronRight4, { className: "w-4 h-4" })
5931
6366
  }
5932
- ) : /* @__PURE__ */ jsx31("span", { className: "w-5" }),
5933
- /* @__PURE__ */ jsxs27(
6367
+ ) : /* @__PURE__ */ jsx32("span", { className: "w-5" }),
6368
+ /* @__PURE__ */ jsxs28(
5934
6369
  "div",
5935
6370
  {
5936
6371
  onClick: () => handleSelect(category.id, category),
5937
6372
  className: "flex items-center gap-2 flex-1",
5938
6373
  children: [
5939
- /* @__PURE__ */ jsx31(
6374
+ /* @__PURE__ */ jsx32(
5940
6375
  "div",
5941
6376
  {
5942
6377
  className: cn(
5943
6378
  "w-4 h-4 border-2 rounded flex items-center justify-center transition-colors",
5944
6379
  isSelected ? "bg-primary border-primary" : "border-muted-foreground/30"
5945
6380
  ),
5946
- children: isSelected && /* @__PURE__ */ jsx31(Check5, { className: "w-3 h-3 text-primary-foreground" })
6381
+ children: isSelected && /* @__PURE__ */ jsx32(Check5, { className: "w-3 h-3 text-primary-foreground" })
5947
6382
  }
5948
6383
  ),
5949
- /* @__PURE__ */ jsx31("span", { className: cn("text-sm", isSelected && "font-medium text-primary"), children: category.name })
6384
+ /* @__PURE__ */ jsx32("span", { className: cn("text-sm", isSelected && "font-medium text-primary"), children: category.name })
5950
6385
  ]
5951
6386
  }
5952
6387
  )
5953
6388
  ]
5954
6389
  }
5955
6390
  ),
5956
- hasChildren && isExpanded && /* @__PURE__ */ jsx31("div", { children: children.map((child) => renderCategory(child, level + 1)) })
6391
+ hasChildren && isExpanded && /* @__PURE__ */ jsx32("div", { children: children.map((child) => renderCategory(child, level + 1)) })
5957
6392
  ] }, category.id);
5958
6393
  };
5959
6394
  const selectedCount = value.length;
5960
6395
  const displayText = selectedCount > 0 ? `\u0110\xE3 ch\u1ECDn ${selectedCount} danh m\u1EE5c` : placeholder;
5961
- return /* @__PURE__ */ jsxs27("div", { className: "relative", children: [
5962
- /* @__PURE__ */ jsxs27(
6396
+ return /* @__PURE__ */ jsxs28("div", { className: "relative", children: [
6397
+ /* @__PURE__ */ jsxs28(
5963
6398
  "button",
5964
6399
  {
5965
6400
  type: "button",
@@ -5972,22 +6407,22 @@ function CategoryTreeSelect({ categories, value, onChange, placeholder = "Ch\u1E
5972
6407
  isOpen && "border-primary ring-1 ring-primary"
5973
6408
  ),
5974
6409
  children: [
5975
- /* @__PURE__ */ jsx31("span", { className: cn("text-sm", selectedCount === 0 && "text-muted-foreground"), children: displayText }),
5976
- /* @__PURE__ */ jsx31(ChevronDown3, { className: cn("w-4 h-4 transition-transform", isOpen && "transform rotate-180") })
6410
+ /* @__PURE__ */ jsx32("span", { className: cn("text-sm", selectedCount === 0 && "text-muted-foreground"), children: displayText }),
6411
+ /* @__PURE__ */ jsx32(ChevronDown3, { className: cn("w-4 h-4 transition-transform", isOpen && "transform rotate-180") })
5977
6412
  ]
5978
6413
  }
5979
6414
  ),
5980
- isOpen && !disabled && /* @__PURE__ */ jsxs27(Fragment7, { children: [
5981
- /* @__PURE__ */ jsx31("div", { className: "fixed inset-0 z-10", onClick: () => setIsOpen(false) }),
5982
- /* @__PURE__ */ jsx31("div", { className: "absolute z-20 mt-1 w-full max-h-80 overflow-auto bg-background border rounded-md shadow-lg", children: /* @__PURE__ */ jsx31("div", { className: "p-1", children: parentCategories.length === 0 ? /* @__PURE__ */ jsx31("div", { className: "px-3 py-2 text-sm text-muted-foreground", children: "Kh\xF4ng c\xF3 danh m\u1EE5c n\xE0o" }) : parentCategories.map((cat) => renderCategory(cat)) }) })
6415
+ isOpen && !disabled && /* @__PURE__ */ jsxs28(Fragment8, { children: [
6416
+ /* @__PURE__ */ jsx32("div", { className: "fixed inset-0 z-10", onClick: () => setIsOpen(false) }),
6417
+ /* @__PURE__ */ jsx32("div", { className: "absolute z-20 mt-1 w-full max-h-80 overflow-auto bg-background border rounded-md shadow-lg", children: /* @__PURE__ */ jsx32("div", { className: "p-1", children: parentCategories.length === 0 ? /* @__PURE__ */ jsx32("div", { className: "px-3 py-2 text-sm text-muted-foreground", children: "Kh\xF4ng c\xF3 danh m\u1EE5c n\xE0o" }) : parentCategories.map((cat) => renderCategory(cat)) }) })
5983
6418
  ] })
5984
6419
  ] });
5985
6420
  }
5986
6421
 
5987
6422
  // ../../components/ui/SmartImage.tsx
5988
6423
  import Image from "next/image";
5989
- import React26 from "react";
5990
- import { jsx as jsx32 } from "react/jsx-runtime";
6424
+ import React27 from "react";
6425
+ import { jsx as jsx33 } from "react/jsx-runtime";
5991
6426
  var DEFAULT_FALLBACK = "/images/products/hoa-hong-do.png";
5992
6427
  function SmartImage({
5993
6428
  src,
@@ -6011,7 +6446,7 @@ function SmartImage({
6011
6446
  }
6012
6447
  return input;
6013
6448
  };
6014
- const [resolvedSrc, setResolvedSrc] = React26.useState(() => normalize(src));
6449
+ const [resolvedSrc, setResolvedSrc] = React27.useState(() => normalize(src));
6015
6450
  const handleError = () => {
6016
6451
  if (resolvedSrc.endsWith(".jpg")) {
6017
6452
  setResolvedSrc(resolvedSrc.replace(/\.jpg($|\?)/, ".png$1"));
@@ -6019,9 +6454,9 @@ function SmartImage({
6019
6454
  setResolvedSrc(fallbackSrc);
6020
6455
  }
6021
6456
  };
6022
- const Wrapper = ({ children }) => /* @__PURE__ */ jsx32("div", { className: cn("relative overflow-hidden bg-muted/30", ratioClass, roundedClass, className), children });
6457
+ const Wrapper = ({ children }) => /* @__PURE__ */ jsx33("div", { className: cn("relative overflow-hidden bg-muted/30", ratioClass, roundedClass, className), children });
6023
6458
  if (fill) {
6024
- return /* @__PURE__ */ jsx32(Wrapper, { children: /* @__PURE__ */ jsx32(
6459
+ return /* @__PURE__ */ jsx33(Wrapper, { children: /* @__PURE__ */ jsx33(
6025
6460
  Image,
6026
6461
  {
6027
6462
  src: resolvedSrc,
@@ -6035,7 +6470,7 @@ function SmartImage({
6035
6470
  }
6036
6471
  ) });
6037
6472
  }
6038
- return /* @__PURE__ */ jsx32("div", { className: cn("relative overflow-hidden bg-muted/30", roundedClass, className), children: /* @__PURE__ */ jsx32(
6473
+ return /* @__PURE__ */ jsx33("div", { className: cn("relative overflow-hidden bg-muted/30", roundedClass, className), children: /* @__PURE__ */ jsx33(
6039
6474
  Image,
6040
6475
  {
6041
6476
  src: resolvedSrc,
@@ -6055,7 +6490,7 @@ function SmartImage({
6055
6490
  import { useState as useState24, useRef as useRef9, useCallback as useCallback7 } from "react";
6056
6491
  import { Upload, X as X8, Image as ImageIcon, Loader2 as Loader22, Check as Check6 } from "lucide-react";
6057
6492
  import { useTranslations as useTranslations6 } from "next-intl";
6058
- import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
6493
+ import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
6059
6494
  function ImageUpload({
6060
6495
  onUpload,
6061
6496
  onRemove,
@@ -6177,8 +6612,8 @@ function ImageUpload({
6177
6612
  const handleBrowseClick = () => {
6178
6613
  fileInputRef.current?.click();
6179
6614
  };
6180
- return /* @__PURE__ */ jsxs28("div", { className: cn("space-y-4", className), children: [
6181
- /* @__PURE__ */ jsxs28(
6615
+ return /* @__PURE__ */ jsxs29("div", { className: cn("space-y-4", className), children: [
6616
+ /* @__PURE__ */ jsxs29(
6182
6617
  "div",
6183
6618
  {
6184
6619
  className: cn(
@@ -6191,15 +6626,15 @@ function ImageUpload({
6191
6626
  onDragLeave: handleDragLeave,
6192
6627
  onDrop: handleDrop,
6193
6628
  children: [
6194
- uploading && /* @__PURE__ */ jsx33("div", { className: "absolute inset-0 bg-background/80 flex items-center justify-center rounded-lg", children: /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-3", children: [
6195
- /* @__PURE__ */ jsx33(Loader22, { className: "w-6 h-6 animate-spin text-primary" }),
6196
- /* @__PURE__ */ jsx33("span", { className: "text-sm font-medium", children: "Uploading..." })
6629
+ uploading && /* @__PURE__ */ jsx34("div", { className: "absolute inset-0 bg-background/80 flex items-center justify-center rounded-lg", children: /* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-3", children: [
6630
+ /* @__PURE__ */ jsx34(Loader22, { className: "w-6 h-6 animate-spin text-primary" }),
6631
+ /* @__PURE__ */ jsx34("span", { className: "text-sm font-medium", children: "Uploading..." })
6197
6632
  ] }) }),
6198
- /* @__PURE__ */ jsxs28("div", { className: "space-y-4", children: [
6199
- /* @__PURE__ */ jsx33("div", { className: "mx-auto w-12 h-12 bg-primary/10 rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx33(Upload, { className: "w-6 h-6 text-primary" }) }),
6200
- /* @__PURE__ */ jsxs28("div", { className: "space-y-2", children: [
6201
- /* @__PURE__ */ jsx33("p", { className: "text-muted-foreground", children: dragDropText || t("dragDropText") }),
6202
- /* @__PURE__ */ jsx33(
6633
+ /* @__PURE__ */ jsxs29("div", { className: "space-y-4", children: [
6634
+ /* @__PURE__ */ jsx34("div", { className: "mx-auto w-12 h-12 bg-primary/10 rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx34(Upload, { className: "w-6 h-6 text-primary" }) }),
6635
+ /* @__PURE__ */ jsxs29("div", { className: "space-y-2", children: [
6636
+ /* @__PURE__ */ jsx34("p", { className: "text-muted-foreground", children: dragDropText || t("dragDropText") }),
6637
+ /* @__PURE__ */ jsx34(
6203
6638
  Button_default,
6204
6639
  {
6205
6640
  type: "button",
@@ -6211,9 +6646,9 @@ function ImageUpload({
6211
6646
  }
6212
6647
  )
6213
6648
  ] }),
6214
- /* @__PURE__ */ jsx33("p", { className: "text-xs text-muted-foreground", children: supportedFormatsText || t("supportedFormats") })
6649
+ /* @__PURE__ */ jsx34("p", { className: "text-xs text-muted-foreground", children: supportedFormatsText || t("supportedFormats") })
6215
6650
  ] }),
6216
- /* @__PURE__ */ jsx33(
6651
+ /* @__PURE__ */ jsx34(
6217
6652
  "input",
6218
6653
  {
6219
6654
  ref: fileInputRef,
@@ -6228,25 +6663,25 @@ function ImageUpload({
6228
6663
  ]
6229
6664
  }
6230
6665
  ),
6231
- showPreview && uploadedImages.length > 0 && /* @__PURE__ */ jsxs28("div", { className: "space-y-3", children: [
6232
- /* @__PURE__ */ jsx33("h4", { className: "text-sm font-medium", children: "Uploaded Images" }),
6233
- /* @__PURE__ */ jsx33("div", { className: "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4", children: uploadedImages.map((image) => /* @__PURE__ */ jsxs28(
6666
+ showPreview && uploadedImages.length > 0 && /* @__PURE__ */ jsxs29("div", { className: "space-y-3", children: [
6667
+ /* @__PURE__ */ jsx34("h4", { className: "text-sm font-medium", children: "Uploaded Images" }),
6668
+ /* @__PURE__ */ jsx34("div", { className: "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4", children: uploadedImages.map((image) => /* @__PURE__ */ jsxs29(
6234
6669
  "div",
6235
6670
  {
6236
6671
  className: "relative group bg-card border border-border rounded-lg p-3",
6237
6672
  children: [
6238
- /* @__PURE__ */ jsx33(
6673
+ /* @__PURE__ */ jsx34(
6239
6674
  Button_default,
6240
6675
  {
6241
6676
  variant: "danger",
6242
6677
  size: "icon",
6243
6678
  className: "absolute -top-2 -right-2 w-6 h-6 opacity-0 group-hover:opacity-100 transition-opacity z-10",
6244
6679
  onClick: () => handleRemoveImage(image.id),
6245
- children: /* @__PURE__ */ jsx33(X8, { className: "w-3 h-3" })
6680
+ children: /* @__PURE__ */ jsx34(X8, { className: "w-3 h-3" })
6246
6681
  }
6247
6682
  ),
6248
- /* @__PURE__ */ jsxs28("div", { className: cn("mx-auto mb-2 overflow-hidden rounded-md", previewSizes[previewSize]), children: [
6249
- /* @__PURE__ */ jsx33(
6683
+ /* @__PURE__ */ jsxs29("div", { className: cn("mx-auto mb-2 overflow-hidden rounded-md", previewSizes[previewSize]), children: [
6684
+ /* @__PURE__ */ jsx34(
6250
6685
  "img",
6251
6686
  {
6252
6687
  src: image.url,
@@ -6259,18 +6694,18 @@ function ImageUpload({
6259
6694
  }
6260
6695
  }
6261
6696
  ),
6262
- /* @__PURE__ */ jsx33("div", { className: "hidden w-full h-full bg-muted flex items-center justify-center", children: /* @__PURE__ */ jsx33(ImageIcon, { className: "w-8 h-8 text-muted-foreground" }) })
6697
+ /* @__PURE__ */ jsx34("div", { className: "hidden w-full h-full bg-muted flex items-center justify-center", children: /* @__PURE__ */ jsx34(ImageIcon, { className: "w-8 h-8 text-muted-foreground" }) })
6263
6698
  ] }),
6264
- /* @__PURE__ */ jsxs28("div", { className: "space-y-1", children: [
6265
- /* @__PURE__ */ jsx33("p", { className: "text-xs font-medium truncate", title: image.originalName, children: image.originalName }),
6266
- /* @__PURE__ */ jsx33("p", { className: "text-xs text-muted-foreground", children: image.formattedSize }),
6267
- image.width && image.height && /* @__PURE__ */ jsxs28("p", { className: "text-xs text-muted-foreground", children: [
6699
+ /* @__PURE__ */ jsxs29("div", { className: "space-y-1", children: [
6700
+ /* @__PURE__ */ jsx34("p", { className: "text-xs font-medium truncate", title: image.originalName, children: image.originalName }),
6701
+ /* @__PURE__ */ jsx34("p", { className: "text-xs text-muted-foreground", children: image.formattedSize }),
6702
+ image.width && image.height && /* @__PURE__ */ jsxs29("p", { className: "text-xs text-muted-foreground", children: [
6268
6703
  image.width,
6269
6704
  " \xD7 ",
6270
6705
  image.height
6271
6706
  ] })
6272
6707
  ] }),
6273
- /* @__PURE__ */ jsx33("div", { className: "absolute top-1 left-1 w-5 h-5 bg-success rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx33(Check6, { className: "w-3 h-3 text-success-foreground" }) })
6708
+ /* @__PURE__ */ jsx34("div", { className: "absolute top-1 left-1 w-5 h-5 bg-success rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx34(Check6, { className: "w-3 h-3 text-success-foreground" }) })
6274
6709
  ]
6275
6710
  },
6276
6711
  image.id
@@ -6280,30 +6715,30 @@ function ImageUpload({
6280
6715
  }
6281
6716
 
6282
6717
  // ../../components/ui/Carousel.tsx
6283
- import * as React27 from "react";
6718
+ import * as React28 from "react";
6284
6719
  import { ArrowLeft, ArrowRight } from "lucide-react";
6285
- import { Fragment as Fragment8, jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
6720
+ import { Fragment as Fragment9, jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
6286
6721
  function Carousel({ children, autoScroll = true, autoScrollInterval = 5e3 }) {
6287
- const [currentIndex, setCurrentIndex] = React27.useState(0);
6288
- const totalSlides = React27.Children.count(children);
6289
- const [isPaused, setIsPaused] = React27.useState(false);
6290
- const scrollPrev = React27.useCallback(() => {
6722
+ const [currentIndex, setCurrentIndex] = React28.useState(0);
6723
+ const totalSlides = React28.Children.count(children);
6724
+ const [isPaused, setIsPaused] = React28.useState(false);
6725
+ const scrollPrev = React28.useCallback(() => {
6291
6726
  setCurrentIndex((prev) => prev > 0 ? prev - 1 : totalSlides - 1);
6292
6727
  }, [totalSlides]);
6293
- const scrollNext = React27.useCallback(() => {
6728
+ const scrollNext = React28.useCallback(() => {
6294
6729
  setCurrentIndex((prev) => prev < totalSlides - 1 ? prev + 1 : 0);
6295
6730
  }, [totalSlides]);
6296
- React27.useEffect(() => {
6731
+ React28.useEffect(() => {
6297
6732
  if (!autoScroll || isPaused || totalSlides <= 1) return;
6298
6733
  const interval = setInterval(() => {
6299
6734
  scrollNext();
6300
6735
  }, autoScrollInterval);
6301
6736
  return () => clearInterval(interval);
6302
6737
  }, [autoScroll, isPaused, totalSlides, autoScrollInterval, scrollNext]);
6303
- return /* @__PURE__ */ jsxs29("div", { className: "relative w-full overflow-hidden", onMouseEnter: () => setIsPaused(true), onMouseLeave: () => setIsPaused(false), children: [
6304
- /* @__PURE__ */ jsx34("div", { className: "flex transition-transform duration-500 ease-in-out", style: { transform: `translateX(-${currentIndex * 100}%)` }, children: React27.Children.map(children, (child, idx) => /* @__PURE__ */ jsx34("div", { className: "flex-shrink-0 w-full h-full", children: child }, idx)) }),
6305
- totalSlides > 1 && /* @__PURE__ */ jsxs29(Fragment8, { children: [
6306
- /* @__PURE__ */ jsx34(
6738
+ return /* @__PURE__ */ jsxs30("div", { className: "relative w-full overflow-hidden", onMouseEnter: () => setIsPaused(true), onMouseLeave: () => setIsPaused(false), children: [
6739
+ /* @__PURE__ */ jsx35("div", { className: "flex transition-transform duration-500 ease-in-out", style: { transform: `translateX(-${currentIndex * 100}%)` }, children: React28.Children.map(children, (child, idx) => /* @__PURE__ */ jsx35("div", { className: "flex-shrink-0 w-full h-full", children: child }, idx)) }),
6740
+ totalSlides > 1 && /* @__PURE__ */ jsxs30(Fragment9, { children: [
6741
+ /* @__PURE__ */ jsx35(
6307
6742
  Button_default,
6308
6743
  {
6309
6744
  onClick: scrollPrev,
@@ -6313,7 +6748,7 @@ function Carousel({ children, autoScroll = true, autoScrollInterval = 5e3 }) {
6313
6748
  className: "absolute left-4 top-1/2 -translate-y-1/2 hover:-translate-y-1/2 z-10 rounded-full will-change-transform bg-background/80 hover:bg-background border-border/50 hover:border-border text-foreground"
6314
6749
  }
6315
6750
  ),
6316
- /* @__PURE__ */ jsx34(
6751
+ /* @__PURE__ */ jsx35(
6317
6752
  Button_default,
6318
6753
  {
6319
6754
  onClick: scrollNext,
@@ -6324,7 +6759,7 @@ function Carousel({ children, autoScroll = true, autoScrollInterval = 5e3 }) {
6324
6759
  }
6325
6760
  )
6326
6761
  ] }),
6327
- totalSlides > 1 && /* @__PURE__ */ jsx34("div", { className: "absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-2", children: Array.from({ length: totalSlides }, (_, idx) => /* @__PURE__ */ jsx34(
6762
+ totalSlides > 1 && /* @__PURE__ */ jsx35("div", { className: "absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-2", children: Array.from({ length: totalSlides }, (_, idx) => /* @__PURE__ */ jsx35(
6328
6763
  "button",
6329
6764
  {
6330
6765
  onClick: () => setCurrentIndex(idx),
@@ -6338,21 +6773,21 @@ function Carousel({ children, autoScroll = true, autoScrollInterval = 5e3 }) {
6338
6773
 
6339
6774
  // ../../components/ui/ClientOnly.tsx
6340
6775
  import { useEffect as useEffect15, useState as useState26 } from "react";
6341
- import { Fragment as Fragment9, jsx as jsx35 } from "react/jsx-runtime";
6776
+ import { Fragment as Fragment10, jsx as jsx36 } from "react/jsx-runtime";
6342
6777
  function ClientOnly({ children, fallback = null }) {
6343
6778
  const [hasMounted, setHasMounted] = useState26(false);
6344
6779
  useEffect15(() => {
6345
6780
  setHasMounted(true);
6346
6781
  }, []);
6347
6782
  if (!hasMounted) {
6348
- return /* @__PURE__ */ jsx35(Fragment9, { children: fallback });
6783
+ return /* @__PURE__ */ jsx36(Fragment10, { children: fallback });
6349
6784
  }
6350
- return /* @__PURE__ */ jsx35(Fragment9, { children });
6785
+ return /* @__PURE__ */ jsx36(Fragment10, { children });
6351
6786
  }
6352
6787
 
6353
6788
  // ../../components/ui/Loading.tsx
6354
6789
  import { Activity as Activity3 } from "lucide-react";
6355
- import { jsx as jsx36, jsxs as jsxs30 } from "react/jsx-runtime";
6790
+ import { jsx as jsx37, jsxs as jsxs31 } from "react/jsx-runtime";
6356
6791
  var LoadingSpinner = ({
6357
6792
  size = "md",
6358
6793
  className,
@@ -6368,7 +6803,7 @@ var LoadingSpinner = ({
6368
6803
  foreground: "text-foreground",
6369
6804
  muted: "text-muted-foreground"
6370
6805
  };
6371
- return /* @__PURE__ */ jsx36(
6806
+ return /* @__PURE__ */ jsx37(
6372
6807
  Activity3,
6373
6808
  {
6374
6809
  className: cn(
@@ -6389,7 +6824,7 @@ var LoadingDots = ({
6389
6824
  foreground: "bg-foreground",
6390
6825
  muted: "bg-muted-foreground"
6391
6826
  };
6392
- return /* @__PURE__ */ jsx36("div", { className: cn("flex items-center space-x-1", className), children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx36(
6827
+ return /* @__PURE__ */ jsx37("div", { className: cn("flex items-center space-x-1", className), children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx37(
6393
6828
  "div",
6394
6829
  {
6395
6830
  className: cn(
@@ -6411,7 +6846,7 @@ var LoadingBar = ({
6411
6846
  label
6412
6847
  }) => {
6413
6848
  const pct = progress ? Math.min(Math.max(progress, 0), 100) : void 0;
6414
- return /* @__PURE__ */ jsx36(
6849
+ return /* @__PURE__ */ jsx37(
6415
6850
  "div",
6416
6851
  {
6417
6852
  className: cn("w-full bg-muted rounded-full h-2", className),
@@ -6420,7 +6855,7 @@ var LoadingBar = ({
6420
6855
  "aria-valuemax": pct === void 0 ? void 0 : 100,
6421
6856
  "aria-valuenow": pct === void 0 ? void 0 : Math.round(pct),
6422
6857
  "aria-label": label || "Loading",
6423
- children: /* @__PURE__ */ jsx36(
6858
+ children: /* @__PURE__ */ jsx37(
6424
6859
  "div",
6425
6860
  {
6426
6861
  className: cn(
@@ -6437,10 +6872,10 @@ var LoadingBar = ({
6437
6872
  };
6438
6873
 
6439
6874
  // ../../components/ui/Table.tsx
6440
- import React28 from "react";
6441
- import { jsx as jsx37, jsxs as jsxs31 } from "react/jsx-runtime";
6442
- var Table = React28.forwardRef(
6443
- ({ className, containerClassName, ...props }, ref) => /* @__PURE__ */ jsx37(
6875
+ import React29 from "react";
6876
+ import { jsx as jsx38, jsxs as jsxs32 } from "react/jsx-runtime";
6877
+ var Table = React29.forwardRef(
6878
+ ({ className, containerClassName, ...props }, ref) => /* @__PURE__ */ jsx38(
6444
6879
  "div",
6445
6880
  {
6446
6881
  className: cn(
@@ -6450,7 +6885,7 @@ var Table = React28.forwardRef(
6450
6885
  "backdrop-blur-sm transition-all duration-300",
6451
6886
  containerClassName
6452
6887
  ),
6453
- children: /* @__PURE__ */ jsx37(
6888
+ children: /* @__PURE__ */ jsx38(
6454
6889
  "table",
6455
6890
  {
6456
6891
  ref,
@@ -6462,8 +6897,8 @@ var Table = React28.forwardRef(
6462
6897
  )
6463
6898
  );
6464
6899
  Table.displayName = "Table";
6465
- var TableHeader = React28.forwardRef(
6466
- ({ className, children, filterRow, ...props }, ref) => /* @__PURE__ */ jsxs31(
6900
+ var TableHeader = React29.forwardRef(
6901
+ ({ className, children, filterRow, ...props }, ref) => /* @__PURE__ */ jsxs32(
6467
6902
  "thead",
6468
6903
  {
6469
6904
  ref,
@@ -6481,7 +6916,7 @@ var TableHeader = React28.forwardRef(
6481
6916
  )
6482
6917
  );
6483
6918
  TableHeader.displayName = "TableHeader";
6484
- var TableBody = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx37(
6919
+ var TableBody = React29.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx38(
6485
6920
  "tbody",
6486
6921
  {
6487
6922
  ref,
@@ -6490,7 +6925,7 @@ var TableBody = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE_
6490
6925
  }
6491
6926
  ));
6492
6927
  TableBody.displayName = "TableBody";
6493
- var TableFooter = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx37(
6928
+ var TableFooter = React29.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx38(
6494
6929
  "tfoot",
6495
6930
  {
6496
6931
  ref,
@@ -6502,7 +6937,7 @@ var TableFooter = React28.forwardRef(({ className, ...props }, ref) => /* @__PUR
6502
6937
  }
6503
6938
  ));
6504
6939
  TableFooter.displayName = "TableFooter";
6505
- var TableRow = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx37(
6940
+ var TableRow = React29.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx38(
6506
6941
  "tr",
6507
6942
  {
6508
6943
  ref,
@@ -6516,7 +6951,7 @@ var TableRow = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__
6516
6951
  }
6517
6952
  ));
6518
6953
  TableRow.displayName = "TableRow";
6519
- var TableHead = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx37(
6954
+ var TableHead = React29.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx38(
6520
6955
  "th",
6521
6956
  {
6522
6957
  ref,
@@ -6528,7 +6963,7 @@ var TableHead = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE_
6528
6963
  }
6529
6964
  ));
6530
6965
  TableHead.displayName = "TableHead";
6531
- var TableCell = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx37(
6966
+ var TableCell = React29.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx38(
6532
6967
  "td",
6533
6968
  {
6534
6969
  ref,
@@ -6537,7 +6972,7 @@ var TableCell = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE_
6537
6972
  }
6538
6973
  ));
6539
6974
  TableCell.displayName = "TableCell";
6540
- var TableCaption = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx37(
6975
+ var TableCaption = React29.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx38(
6541
6976
  "caption",
6542
6977
  {
6543
6978
  ref,
@@ -6549,12 +6984,12 @@ TableCaption.displayName = "TableCaption";
6549
6984
 
6550
6985
  // ../../components/ui/DataTable.tsx
6551
6986
  import { Filter as FilterIcon } from "lucide-react";
6552
- import React29 from "react";
6987
+ import React30 from "react";
6553
6988
  import { useTranslations as useTranslations7 } from "next-intl";
6554
- import { jsx as jsx38, jsxs as jsxs32 } from "react/jsx-runtime";
6989
+ import { jsx as jsx39, jsxs as jsxs33 } from "react/jsx-runtime";
6555
6990
  function useDebounced(value, delay = 300) {
6556
- const [debounced, setDebounced] = React29.useState(value);
6557
- React29.useEffect(() => {
6991
+ const [debounced, setDebounced] = React30.useState(value);
6992
+ React30.useEffect(() => {
6558
6993
  const id = setTimeout(() => setDebounced(value), delay);
6559
6994
  return () => clearTimeout(id);
6560
6995
  }, [value, delay]);
@@ -6568,6 +7003,7 @@ function DataTable({
6568
7003
  total = 0,
6569
7004
  page = 1,
6570
7005
  pageSize = 20,
7006
+ pageSizeOptions,
6571
7007
  onQueryChange,
6572
7008
  caption,
6573
7009
  toolbar,
@@ -6579,14 +7015,20 @@ function DataTable({
6579
7015
  labels
6580
7016
  }) {
6581
7017
  const t = useTranslations7("Common");
6582
- const [visibleCols, setVisibleCols] = React29.useState(() => columns.filter((c) => c.visible !== false).map((c) => c.key));
6583
- const [filters, setFilters] = React29.useState({});
6584
- const [sort, setSort] = React29.useState(null);
6585
- const [density, setDensity] = React29.useState("normal");
6586
- const [curPage, setCurPage] = React29.useState(page);
6587
- const [curPageSize, setCurPageSize] = React29.useState(pageSize);
7018
+ const [visibleCols, setVisibleCols] = React30.useState(() => columns.filter((c) => c.visible !== false).map((c) => c.key));
7019
+ const [filters, setFilters] = React30.useState({});
7020
+ const [sort, setSort] = React30.useState(null);
7021
+ const [density, setDensity] = React30.useState("normal");
7022
+ const [curPage, setCurPage] = React30.useState(page);
7023
+ const [curPageSize, setCurPageSize] = React30.useState(pageSize);
6588
7024
  const debouncedFilters = useDebounced(filters, 350);
6589
- React29.useEffect(() => {
7025
+ React30.useEffect(() => {
7026
+ setCurPage(page);
7027
+ }, [page]);
7028
+ React30.useEffect(() => {
7029
+ setCurPageSize(pageSize);
7030
+ }, [pageSize]);
7031
+ React30.useEffect(() => {
6590
7032
  if (!onQueryChange) return;
6591
7033
  onQueryChange({ filters: debouncedFilters, sort, page: curPage, pageSize: curPageSize });
6592
7034
  }, [debouncedFilters, sort, curPage, curPageSize]);
@@ -6605,7 +7047,7 @@ function DataTable({
6605
7047
  className: "h-8 w-full text-sm"
6606
7048
  };
6607
7049
  if (col.filter.type === "text") {
6608
- return /* @__PURE__ */ jsx38(
7050
+ return /* @__PURE__ */ jsx39(
6609
7051
  Input_default,
6610
7052
  {
6611
7053
  ...commonProps,
@@ -6620,7 +7062,7 @@ function DataTable({
6620
7062
  }
6621
7063
  if (col.filter.type === "select") {
6622
7064
  const options = col.filter.options || [];
6623
- return /* @__PURE__ */ jsx38(
7065
+ return /* @__PURE__ */ jsx39(
6624
7066
  Combobox,
6625
7067
  {
6626
7068
  options: ["", ...options],
@@ -6636,7 +7078,7 @@ function DataTable({
6636
7078
  );
6637
7079
  }
6638
7080
  if (col.filter.type === "date") {
6639
- return /* @__PURE__ */ jsx38(
7081
+ return /* @__PURE__ */ jsx39(
6640
7082
  DatePicker,
6641
7083
  {
6642
7084
  placeholder: col.filter.placeholder || `Select ${String(col.title)}`,
@@ -6650,15 +7092,15 @@ function DataTable({
6650
7092
  }
6651
7093
  return null;
6652
7094
  };
6653
- const renderHeader = /* @__PURE__ */ jsx38(TableRow, { children: visibleColumns.map((col) => /* @__PURE__ */ jsx38(
7095
+ const renderHeader = /* @__PURE__ */ jsx39(TableRow, { children: visibleColumns.map((col) => /* @__PURE__ */ jsx39(
6654
7096
  TableHead,
6655
7097
  {
6656
7098
  style: { width: col.width },
6657
7099
  className: cn(col.align === "right" && "text-right", col.align === "center" && "text-center"),
6658
- children: /* @__PURE__ */ jsxs32("div", { className: "flex items-center justify-between gap-2 select-none min-h-[2.5rem]", children: [
6659
- /* @__PURE__ */ jsxs32("div", { className: "flex items-center gap-1 min-w-0 flex-1", children: [
6660
- /* @__PURE__ */ jsx38("span", { className: "truncate font-medium text-sm", children: col.title }),
6661
- col.sortable && /* @__PURE__ */ jsx38(
7100
+ children: /* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-between gap-2 select-none min-h-[2.5rem]", children: [
7101
+ /* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-1 min-w-0 flex-1", children: [
7102
+ /* @__PURE__ */ jsx39("span", { className: "truncate font-medium text-sm", children: col.title }),
7103
+ col.sortable && /* @__PURE__ */ jsx39(
6662
7104
  "button",
6663
7105
  {
6664
7106
  className: cn(
@@ -6675,8 +7117,8 @@ function DataTable({
6675
7117
  },
6676
7118
  "aria-label": "Sort",
6677
7119
  title: `Sort by ${String(col.title)}`,
6678
- children: /* @__PURE__ */ jsxs32("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", className: "inline-block", children: [
6679
- /* @__PURE__ */ jsx38(
7120
+ children: /* @__PURE__ */ jsxs33("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", className: "inline-block", children: [
7121
+ /* @__PURE__ */ jsx39(
6680
7122
  "path",
6681
7123
  {
6682
7124
  d: "M7 8l3-3 3 3",
@@ -6687,7 +7129,7 @@ function DataTable({
6687
7129
  opacity: sort?.key === col.key && sort.order === "asc" ? 1 : 0.4
6688
7130
  }
6689
7131
  ),
6690
- /* @__PURE__ */ jsx38(
7132
+ /* @__PURE__ */ jsx39(
6691
7133
  "path",
6692
7134
  {
6693
7135
  d: "M7 12l3 3 3-3",
@@ -6702,11 +7144,11 @@ function DataTable({
6702
7144
  }
6703
7145
  )
6704
7146
  ] }),
6705
- col.filter && /* @__PURE__ */ jsx38(
7147
+ col.filter && /* @__PURE__ */ jsx39(
6706
7148
  Popover,
6707
7149
  {
6708
7150
  placement: "bottom-start",
6709
- trigger: /* @__PURE__ */ jsx38(
7151
+ trigger: /* @__PURE__ */ jsx39(
6710
7152
  "button",
6711
7153
  {
6712
7154
  className: cn(
@@ -6716,16 +7158,16 @@ function DataTable({
6716
7158
  ),
6717
7159
  "aria-label": "Filter",
6718
7160
  title: "Filter",
6719
- children: /* @__PURE__ */ jsx38(FilterIcon, { className: "h-4 w-4" })
7161
+ children: /* @__PURE__ */ jsx39(FilterIcon, { className: "h-4 w-4" })
6720
7162
  }
6721
7163
  ),
6722
- children: /* @__PURE__ */ jsxs32("div", { className: "w-48 p-2 space-y-2", children: [
6723
- /* @__PURE__ */ jsxs32("div", { className: "text-xs font-medium text-muted-foreground mb-2", children: [
7164
+ children: /* @__PURE__ */ jsxs33("div", { className: "w-48 p-2 space-y-2", children: [
7165
+ /* @__PURE__ */ jsxs33("div", { className: "text-xs font-medium text-muted-foreground mb-2", children: [
6724
7166
  "Filter ",
6725
7167
  col.title
6726
7168
  ] }),
6727
7169
  renderFilterControl(col),
6728
- filters[col.key] && /* @__PURE__ */ jsx38(
7170
+ filters[col.key] && /* @__PURE__ */ jsx39(
6729
7171
  "button",
6730
7172
  {
6731
7173
  onClick: () => {
@@ -6747,15 +7189,21 @@ function DataTable({
6747
7189
  },
6748
7190
  col.key
6749
7191
  )) });
6750
- return /* @__PURE__ */ jsxs32("div", { className: cn("space-y-2", className), children: [
6751
- /* @__PURE__ */ jsxs32("div", { className: "flex items-center justify-between gap-4 mb-1", children: [
6752
- /* @__PURE__ */ jsx38("div", { className: "text-sm text-muted-foreground", children: caption }),
6753
- /* @__PURE__ */ jsxs32("div", { className: "flex items-center gap-2", children: [
6754
- enableDensityToggle && /* @__PURE__ */ jsx38(
7192
+ const isServerMode = Boolean(onQueryChange);
7193
+ const displayedData = isServerMode ? data : React30.useMemo(() => {
7194
+ const start = (curPage - 1) * curPageSize;
7195
+ return data.slice(start, start + curPageSize);
7196
+ }, [data, curPage, curPageSize]);
7197
+ const totalItems = isServerMode ? total : data.length;
7198
+ return /* @__PURE__ */ jsxs33("div", { className: cn("space-y-2", className), children: [
7199
+ /* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-between gap-4 mb-1", children: [
7200
+ /* @__PURE__ */ jsx39("div", { className: "text-sm text-muted-foreground", children: caption }),
7201
+ /* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-2", children: [
7202
+ enableDensityToggle && /* @__PURE__ */ jsx39(
6755
7203
  DropdownMenu_default,
6756
7204
  {
6757
- trigger: /* @__PURE__ */ jsxs32(Button_default, { variant: "ghost", size: "sm", className: "h-8 px-2", children: [
6758
- /* @__PURE__ */ jsx38("svg", { className: "w-4 h-4 mr-1", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx38("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
7205
+ trigger: /* @__PURE__ */ jsxs33(Button_default, { variant: "ghost", size: "sm", className: "h-8 px-2", children: [
7206
+ /* @__PURE__ */ jsx39("svg", { className: "w-4 h-4 mr-1", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx39("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
6759
7207
  labels?.density || t("density")
6760
7208
  ] }),
6761
7209
  items: [
@@ -6765,11 +7213,11 @@ function DataTable({
6765
7213
  ]
6766
7214
  }
6767
7215
  ),
6768
- enableColumnVisibilityToggle && /* @__PURE__ */ jsx38(
7216
+ enableColumnVisibilityToggle && /* @__PURE__ */ jsx39(
6769
7217
  DropdownMenu_default,
6770
7218
  {
6771
- trigger: /* @__PURE__ */ jsxs32(Button_default, { variant: "ghost", size: "sm", className: "h-8 px-2", children: [
6772
- /* @__PURE__ */ jsx38("svg", { className: "w-4 h-4 mr-1", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx38(
7219
+ trigger: /* @__PURE__ */ jsxs33(Button_default, { variant: "ghost", size: "sm", className: "h-8 px-2", children: [
7220
+ /* @__PURE__ */ jsx39("svg", { className: "w-4 h-4 mr-1", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx39(
6773
7221
  "path",
6774
7222
  {
6775
7223
  strokeLinecap: "round",
@@ -6780,15 +7228,15 @@ function DataTable({
6780
7228
  ) }),
6781
7229
  labels?.columns || t("columns")
6782
7230
  ] }),
6783
- children: columns.map((c) => /* @__PURE__ */ jsxs32(
7231
+ children: columns.map((c) => /* @__PURE__ */ jsxs33(
6784
7232
  DropdownMenuItem,
6785
7233
  {
6786
7234
  onClick: () => {
6787
7235
  setVisibleCols((prev) => prev.includes(c.key) ? prev.filter((k) => k !== c.key) : [...prev, c.key]);
6788
7236
  },
6789
7237
  children: [
6790
- /* @__PURE__ */ jsx38("input", { type: "checkbox", className: "mr-2 rounded border-border", readOnly: true, checked: visibleCols.includes(c.key) }),
6791
- /* @__PURE__ */ jsx38("span", { className: "truncate", children: c.title })
7238
+ /* @__PURE__ */ jsx39("input", { type: "checkbox", className: "mr-2 rounded border-border", readOnly: true, checked: visibleCols.includes(c.key) }),
7239
+ /* @__PURE__ */ jsx39("span", { className: "truncate", children: c.title })
6792
7240
  ]
6793
7241
  },
6794
7242
  c.key
@@ -6798,17 +7246,17 @@ function DataTable({
6798
7246
  toolbar
6799
7247
  ] })
6800
7248
  ] }),
6801
- /* @__PURE__ */ jsx38("div", { className: cn("relative rounded-lg border border-border/50 overflow-hidden", loading2 && "opacity-60 pointer-events-none"), children: /* @__PURE__ */ jsxs32(
7249
+ /* @__PURE__ */ jsx39("div", { className: cn("relative rounded-lg border border-border/50 overflow-hidden", loading2 && "opacity-60 pointer-events-none"), children: /* @__PURE__ */ jsxs33(
6802
7250
  Table,
6803
7251
  {
6804
7252
  containerClassName: "border-0 rounded-none shadow-none",
6805
7253
  className: "[&_thead]:sticky [&_thead]:top-0 [&_thead]:z-[5] [&_thead]:bg-background [&_thead]:backdrop-blur-sm",
6806
7254
  children: [
6807
- /* @__PURE__ */ jsx38(TableHeader, { children: renderHeader }),
6808
- /* @__PURE__ */ jsx38(TableBody, { children: loading2 ? /* @__PURE__ */ jsx38(TableRow, { children: /* @__PURE__ */ jsx38(TableCell, { colSpan: visibleColumns.length, className: "text-center py-8", children: /* @__PURE__ */ jsxs32("div", { className: "flex items-center justify-center gap-2 text-muted-foreground", children: [
6809
- /* @__PURE__ */ jsxs32("svg", { className: "animate-spin h-4 w-4", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
6810
- /* @__PURE__ */ jsx38("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
6811
- /* @__PURE__ */ jsx38(
7255
+ /* @__PURE__ */ jsx39(TableHeader, { children: renderHeader }),
7256
+ /* @__PURE__ */ jsx39(TableBody, { children: loading2 ? /* @__PURE__ */ jsx39(TableRow, { children: /* @__PURE__ */ jsx39(TableCell, { colSpan: visibleColumns.length, className: "text-center py-8", children: /* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-center gap-2 text-muted-foreground", children: [
7257
+ /* @__PURE__ */ jsxs33("svg", { className: "animate-spin h-4 w-4", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
7258
+ /* @__PURE__ */ jsx39("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
7259
+ /* @__PURE__ */ jsx39(
6812
7260
  "path",
6813
7261
  {
6814
7262
  className: "opacity-75",
@@ -6817,10 +7265,10 @@ function DataTable({
6817
7265
  }
6818
7266
  )
6819
7267
  ] }),
6820
- /* @__PURE__ */ jsx38("span", { className: "text-sm", children: "Loading..." })
6821
- ] }) }) }) : !data || data.length === 0 ? /* @__PURE__ */ jsx38(TableRow, { children: /* @__PURE__ */ jsx38(TableCell, { colSpan: visibleColumns.length, className: "text-center py-6 text-muted-foreground", children: "No data" }) }) : data.map((row, idx) => /* @__PURE__ */ jsx38(TableRow, { className: cn(densityRowClass, striped && idx % 2 === 0 && "bg-muted/30"), children: visibleColumns.map((col) => {
7268
+ /* @__PURE__ */ jsx39("span", { className: "text-sm", children: "Loading..." })
7269
+ ] }) }) }) : !displayedData || displayedData.length === 0 ? /* @__PURE__ */ jsx39(TableRow, { children: /* @__PURE__ */ jsx39(TableCell, { colSpan: visibleColumns.length, className: "text-center py-6 text-muted-foreground", children: "No data" }) }) : displayedData.map((row, idx) => /* @__PURE__ */ jsx39(TableRow, { className: cn(densityRowClass, striped && idx % 2 === 0 && "bg-muted/30"), children: visibleColumns.map((col) => {
6822
7270
  const value = col.dataIndex ? row[col.dataIndex] : void 0;
6823
- return /* @__PURE__ */ jsx38(
7271
+ return /* @__PURE__ */ jsx39(
6824
7272
  TableCell,
6825
7273
  {
6826
7274
  className: cn(
@@ -6838,16 +7286,21 @@ function DataTable({
6838
7286
  ]
6839
7287
  }
6840
7288
  ) }),
6841
- total > 0 && /* @__PURE__ */ jsx38("div", { className: "border-t bg-muted/30 p-4 rounded-b-lg", children: /* @__PURE__ */ jsx38(
7289
+ totalItems > 0 && /* @__PURE__ */ jsx39("div", { className: "border-t bg-muted/30 p-4 rounded-b-lg", children: /* @__PURE__ */ jsx39(
6842
7290
  Pagination,
6843
7291
  {
6844
7292
  page: curPage,
6845
- totalPages: Math.ceil(total / curPageSize),
7293
+ totalPages: Math.ceil(totalItems / curPageSize),
6846
7294
  onChange: (p) => setCurPage(p),
6847
7295
  className: "",
6848
7296
  showInfo: true,
6849
- totalItems: total,
6850
- pageSize: curPageSize
7297
+ totalItems,
7298
+ pageSize: curPageSize,
7299
+ pageSizeOptions,
7300
+ onPageSizeChange: (s) => {
7301
+ setCurPage(1);
7302
+ setCurPageSize(s);
7303
+ }
6851
7304
  }
6852
7305
  ) })
6853
7306
  ] });
@@ -6855,10 +7308,10 @@ function DataTable({
6855
7308
  var DataTable_default = DataTable;
6856
7309
 
6857
7310
  // ../../components/ui/Form.tsx
6858
- import * as React31 from "react";
7311
+ import * as React32 from "react";
6859
7312
 
6860
7313
  // ../../node_modules/react-hook-form/dist/index.esm.mjs
6861
- import React30 from "react";
7314
+ import React31 from "react";
6862
7315
  var isCheckBoxInput = (element) => element.type === "checkbox";
6863
7316
  var isDateObject = (value) => value instanceof Date;
6864
7317
  var isNullOrUndefined = (value) => value == null;
@@ -6946,12 +7399,12 @@ var INPUT_VALIDATION_RULES = {
6946
7399
  required: "required",
6947
7400
  validate: "validate"
6948
7401
  };
6949
- var HookFormContext = React30.createContext(null);
7402
+ var HookFormContext = React31.createContext(null);
6950
7403
  HookFormContext.displayName = "HookFormContext";
6951
- var useFormContext = () => React30.useContext(HookFormContext);
7404
+ var useFormContext = () => React31.useContext(HookFormContext);
6952
7405
  var FormProvider = (props) => {
6953
7406
  const { children, ...data } = props;
6954
- return React30.createElement(HookFormContext.Provider, { value: data }, children);
7407
+ return React31.createElement(HookFormContext.Provider, { value: data }, children);
6955
7408
  };
6956
7409
  var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
6957
7410
  const result = {
@@ -6971,12 +7424,12 @@ var getProxyFormState = (formState, control, localProxyFormState, isRoot = true)
6971
7424
  }
6972
7425
  return result;
6973
7426
  };
6974
- var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React30.useLayoutEffect : React30.useEffect;
7427
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React31.useLayoutEffect : React31.useEffect;
6975
7428
  function useFormState(props) {
6976
7429
  const methods = useFormContext();
6977
7430
  const { control = methods.control, disabled, name, exact } = props || {};
6978
- const [formState, updateFormState] = React30.useState(control._formState);
6979
- const _localProxyFormState = React30.useRef({
7431
+ const [formState, updateFormState] = React31.useState(control._formState);
7432
+ const _localProxyFormState = React31.useRef({
6980
7433
  isDirty: false,
6981
7434
  isLoading: false,
6982
7435
  dirtyFields: false,
@@ -6997,10 +7450,10 @@ function useFormState(props) {
6997
7450
  });
6998
7451
  }
6999
7452
  }), [name, disabled, exact]);
7000
- React30.useEffect(() => {
7453
+ React31.useEffect(() => {
7001
7454
  _localProxyFormState.current.isValid && control._setValid(true);
7002
7455
  }, [control]);
7003
- return React30.useMemo(() => getProxyFormState(formState, control, _localProxyFormState.current, false), [formState, control]);
7456
+ return React31.useMemo(() => getProxyFormState(formState, control, _localProxyFormState.current, false), [formState, control]);
7004
7457
  }
7005
7458
  var isString = (value) => typeof value === "string";
7006
7459
  var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) => {
@@ -7049,12 +7502,12 @@ function deepEqual(object1, object2, _internal_visited = /* @__PURE__ */ new Wea
7049
7502
  function useWatch(props) {
7050
7503
  const methods = useFormContext();
7051
7504
  const { control = methods.control, name, defaultValue, disabled, exact, compute } = props || {};
7052
- const _defaultValue = React30.useRef(defaultValue);
7053
- const _compute = React30.useRef(compute);
7054
- const _computeFormValues = React30.useRef(void 0);
7505
+ const _defaultValue = React31.useRef(defaultValue);
7506
+ const _compute = React31.useRef(compute);
7507
+ const _computeFormValues = React31.useRef(void 0);
7055
7508
  _compute.current = compute;
7056
- const defaultValueMemo = React30.useMemo(() => control._getWatch(name, _defaultValue.current), [control, name]);
7057
- const [value, updateValue] = React30.useState(_compute.current ? _compute.current(defaultValueMemo) : defaultValueMemo);
7509
+ const defaultValueMemo = React31.useMemo(() => control._getWatch(name, _defaultValue.current), [control, name]);
7510
+ const [value, updateValue] = React31.useState(_compute.current ? _compute.current(defaultValueMemo) : defaultValueMemo);
7058
7511
  useIsomorphicLayoutEffect(() => control._subscribe({
7059
7512
  name,
7060
7513
  formState: {
@@ -7076,14 +7529,14 @@ function useWatch(props) {
7076
7529
  }
7077
7530
  }
7078
7531
  }), [control, disabled, name, exact]);
7079
- React30.useEffect(() => control._removeUnmounted());
7532
+ React31.useEffect(() => control._removeUnmounted());
7080
7533
  return value;
7081
7534
  }
7082
7535
  function useController(props) {
7083
7536
  const methods = useFormContext();
7084
7537
  const { name, disabled, control = methods.control, shouldUnregister, defaultValue } = props;
7085
7538
  const isArrayField = isNameInFieldArray(control._names.array, name);
7086
- const defaultValueMemo = React30.useMemo(() => get(control._formValues, name, get(control._defaultValues, name, defaultValue)), [control, name, defaultValue]);
7539
+ const defaultValueMemo = React31.useMemo(() => get(control._formValues, name, get(control._defaultValues, name, defaultValue)), [control, name, defaultValue]);
7087
7540
  const value = useWatch({
7088
7541
  control,
7089
7542
  name,
@@ -7095,15 +7548,15 @@ function useController(props) {
7095
7548
  name,
7096
7549
  exact: true
7097
7550
  });
7098
- const _props = React30.useRef(props);
7099
- const _previousNameRef = React30.useRef(void 0);
7100
- const _registerProps = React30.useRef(control.register(name, {
7551
+ const _props = React31.useRef(props);
7552
+ const _previousNameRef = React31.useRef(void 0);
7553
+ const _registerProps = React31.useRef(control.register(name, {
7101
7554
  ...props.rules,
7102
7555
  value,
7103
7556
  ...isBoolean(props.disabled) ? { disabled: props.disabled } : {}
7104
7557
  }));
7105
7558
  _props.current = props;
7106
- const fieldState = React30.useMemo(() => Object.defineProperties({}, {
7559
+ const fieldState = React31.useMemo(() => Object.defineProperties({}, {
7107
7560
  invalid: {
7108
7561
  enumerable: true,
7109
7562
  get: () => !!get(formState.errors, name)
@@ -7125,21 +7578,21 @@ function useController(props) {
7125
7578
  get: () => get(formState.errors, name)
7126
7579
  }
7127
7580
  }), [formState, name]);
7128
- const onChange = React30.useCallback((event) => _registerProps.current.onChange({
7581
+ const onChange = React31.useCallback((event) => _registerProps.current.onChange({
7129
7582
  target: {
7130
7583
  value: getEventValue(event),
7131
7584
  name
7132
7585
  },
7133
7586
  type: EVENTS.CHANGE
7134
7587
  }), [name]);
7135
- const onBlur = React30.useCallback(() => _registerProps.current.onBlur({
7588
+ const onBlur = React31.useCallback(() => _registerProps.current.onBlur({
7136
7589
  target: {
7137
7590
  value: get(control._formValues, name),
7138
7591
  name
7139
7592
  },
7140
7593
  type: EVENTS.BLUR
7141
7594
  }), [name, control._formValues]);
7142
- const ref = React30.useCallback((elm) => {
7595
+ const ref = React31.useCallback((elm) => {
7143
7596
  const field2 = get(control._fields, name);
7144
7597
  if (field2 && elm) {
7145
7598
  field2._f.ref = {
@@ -7150,7 +7603,7 @@ function useController(props) {
7150
7603
  };
7151
7604
  }
7152
7605
  }, [control._fields, name]);
7153
- const field = React30.useMemo(() => ({
7606
+ const field = React31.useMemo(() => ({
7154
7607
  name,
7155
7608
  value,
7156
7609
  ...isBoolean(disabled) || formState.disabled ? { disabled: formState.disabled || disabled } : {},
@@ -7158,7 +7611,7 @@ function useController(props) {
7158
7611
  onBlur,
7159
7612
  ref
7160
7613
  }), [name, disabled, formState.disabled, onChange, onBlur, ref, value]);
7161
- React30.useEffect(() => {
7614
+ React31.useEffect(() => {
7162
7615
  const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
7163
7616
  const previousName = _previousNameRef.current;
7164
7617
  if (previousName && previousName !== name && !isArrayField) {
@@ -7188,13 +7641,13 @@ function useController(props) {
7188
7641
  (isArrayField ? _shouldUnregisterField && !control._state.action : _shouldUnregisterField) ? control.unregister(name) : updateMounted(name, false);
7189
7642
  };
7190
7643
  }, [name, control, isArrayField, shouldUnregister]);
7191
- React30.useEffect(() => {
7644
+ React31.useEffect(() => {
7192
7645
  control._setDisabledField({
7193
7646
  disabled,
7194
7647
  name
7195
7648
  });
7196
7649
  }, [disabled, name, control]);
7197
- return React30.useMemo(() => ({
7650
+ return React31.useMemo(() => ({
7198
7651
  field,
7199
7652
  formState,
7200
7653
  fieldState
@@ -8513,9 +8966,9 @@ function createFormControl(props = {}) {
8513
8966
  };
8514
8967
  }
8515
8968
  function useForm(props = {}) {
8516
- const _formControl = React30.useRef(void 0);
8517
- const _values = React30.useRef(void 0);
8518
- const [formState, updateFormState] = React30.useState({
8969
+ const _formControl = React31.useRef(void 0);
8970
+ const _values = React31.useRef(void 0);
8971
+ const [formState, updateFormState] = React31.useState({
8519
8972
  isDirty: false,
8520
8973
  isValidating: false,
8521
8974
  isLoading: isFunction(props.defaultValues),
@@ -8564,8 +9017,8 @@ function useForm(props = {}) {
8564
9017
  control._formState.isReady = true;
8565
9018
  return sub;
8566
9019
  }, [control]);
8567
- React30.useEffect(() => control._disableForm(props.disabled), [control, props.disabled]);
8568
- React30.useEffect(() => {
9020
+ React31.useEffect(() => control._disableForm(props.disabled), [control, props.disabled]);
9021
+ React31.useEffect(() => {
8569
9022
  if (props.mode) {
8570
9023
  control._options.mode = props.mode;
8571
9024
  }
@@ -8573,18 +9026,18 @@ function useForm(props = {}) {
8573
9026
  control._options.reValidateMode = props.reValidateMode;
8574
9027
  }
8575
9028
  }, [control, props.mode, props.reValidateMode]);
8576
- React30.useEffect(() => {
9029
+ React31.useEffect(() => {
8577
9030
  if (props.errors) {
8578
9031
  control._setErrors(props.errors);
8579
9032
  control._focusError();
8580
9033
  }
8581
9034
  }, [control, props.errors]);
8582
- React30.useEffect(() => {
9035
+ React31.useEffect(() => {
8583
9036
  props.shouldUnregister && control._subjects.state.next({
8584
9037
  values: control._getWatch()
8585
9038
  });
8586
9039
  }, [control, props.shouldUnregister]);
8587
- React30.useEffect(() => {
9040
+ React31.useEffect(() => {
8588
9041
  if (control._proxyFormState.isDirty) {
8589
9042
  const isDirty = control._getDirty();
8590
9043
  if (isDirty !== formState.isDirty) {
@@ -8594,7 +9047,7 @@ function useForm(props = {}) {
8594
9047
  }
8595
9048
  }
8596
9049
  }, [control, formState.isDirty]);
8597
- React30.useEffect(() => {
9050
+ React31.useEffect(() => {
8598
9051
  if (props.values && !deepEqual(props.values, _values.current)) {
8599
9052
  control._reset(props.values, {
8600
9053
  keepFieldsRef: true,
@@ -8606,7 +9059,7 @@ function useForm(props = {}) {
8606
9059
  control._resetDefaultValues();
8607
9060
  }
8608
9061
  }, [control, props.values]);
8609
- React30.useEffect(() => {
9062
+ React31.useEffect(() => {
8610
9063
  if (!control._state.mount) {
8611
9064
  control._setValid();
8612
9065
  control._state.mount = true;
@@ -8623,8 +9076,8 @@ function useForm(props = {}) {
8623
9076
 
8624
9077
  // ../../components/ui/Form.tsx
8625
9078
  import { useTranslations as useTranslations8 } from "next-intl";
8626
- import { jsx as jsx39, jsxs as jsxs33 } from "react/jsx-runtime";
8627
- var FormConfigContext = React31.createContext({ size: "md" });
9079
+ import { jsx as jsx40, jsxs as jsxs34 } from "react/jsx-runtime";
9080
+ var FormConfigContext = React32.createContext({ size: "md" });
8628
9081
  var FormWrapper = ({
8629
9082
  children,
8630
9083
  onSubmit,
@@ -8637,24 +9090,24 @@ var FormWrapper = ({
8637
9090
  const methods = useForm({
8638
9091
  defaultValues: initialValues
8639
9092
  });
8640
- React31.useEffect(() => {
9093
+ React32.useEffect(() => {
8641
9094
  if (initialValues) {
8642
9095
  methods.reset(initialValues);
8643
9096
  }
8644
9097
  }, [JSON.stringify(initialValues)]);
8645
9098
  const { validationSchema: _, ...formProps } = props;
8646
- return /* @__PURE__ */ jsx39(FormProvider, { ...methods, children: /* @__PURE__ */ jsx39(FormConfigContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx39("form", { onSubmit: methods.handleSubmit(onSubmit), className, ...formProps, children }) }) });
9099
+ return /* @__PURE__ */ jsx40(FormProvider, { ...methods, children: /* @__PURE__ */ jsx40(FormConfigContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx40("form", { onSubmit: methods.handleSubmit(onSubmit), className, ...formProps, children }) }) });
8647
9100
  };
8648
9101
  var Form = FormWrapper;
8649
- var FormFieldContext = React31.createContext({});
9102
+ var FormFieldContext = React32.createContext({});
8650
9103
  var FormField = ({
8651
9104
  ...props
8652
9105
  }) => {
8653
- return /* @__PURE__ */ jsx39(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx39(Controller, { ...props }) });
9106
+ return /* @__PURE__ */ jsx40(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx40(Controller, { ...props }) });
8654
9107
  };
8655
9108
  var useFormField = () => {
8656
- const fieldContext = React31.useContext(FormFieldContext);
8657
- const itemContext = React31.useContext(FormItemContext);
9109
+ const fieldContext = React32.useContext(FormFieldContext);
9110
+ const itemContext = React32.useContext(FormItemContext);
8658
9111
  const { getFieldState, formState } = useFormContext();
8659
9112
  if (!fieldContext) {
8660
9113
  try {
@@ -8675,22 +9128,22 @@ var useFormField = () => {
8675
9128
  ...fieldState
8676
9129
  };
8677
9130
  };
8678
- var FormItemContext = React31.createContext({});
8679
- var FormItem = React31.forwardRef(({ className, ...props }, ref) => {
8680
- const id = React31.useId();
8681
- return /* @__PURE__ */ jsx39(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx39("div", { ref, className: cn("space-y-2", className), ...props }) });
9131
+ var FormItemContext = React32.createContext({});
9132
+ var FormItem = React32.forwardRef(({ className, ...props }, ref) => {
9133
+ const id = React32.useId();
9134
+ return /* @__PURE__ */ jsx40(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx40("div", { ref, className: cn("space-y-2", className), ...props }) });
8682
9135
  });
8683
9136
  FormItem.displayName = "FormItem";
8684
- var FormLabel = React31.forwardRef(({ className, ...props }, ref) => {
9137
+ var FormLabel = React32.forwardRef(({ className, ...props }, ref) => {
8685
9138
  const { error, formItemId } = useFormField();
8686
- const config = React31.useContext(FormConfigContext);
9139
+ const config = React32.useContext(FormConfigContext);
8687
9140
  const sizeClass = config.size === "sm" ? "text-xs" : config.size === "lg" ? "text-base" : "text-sm";
8688
- return /* @__PURE__ */ jsx39(Label, { ref, className: cn(sizeClass, error && "text-destructive", className), htmlFor: formItemId, ...props });
9141
+ return /* @__PURE__ */ jsx40(Label, { ref, className: cn(sizeClass, error && "text-destructive", className), htmlFor: formItemId, ...props });
8689
9142
  });
8690
9143
  FormLabel.displayName = "FormLabel";
8691
- var FormControl = React31.forwardRef(({ ...props }, ref) => {
9144
+ var FormControl = React32.forwardRef(({ ...props }, ref) => {
8692
9145
  const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
8693
- return /* @__PURE__ */ jsx39(
9146
+ return /* @__PURE__ */ jsx40(
8694
9147
  "div",
8695
9148
  {
8696
9149
  ref,
@@ -8702,37 +9155,37 @@ var FormControl = React31.forwardRef(({ ...props }, ref) => {
8702
9155
  );
8703
9156
  });
8704
9157
  FormControl.displayName = "FormControl";
8705
- var FormDescription = React31.forwardRef(({ className, ...props }, ref) => {
9158
+ var FormDescription = React32.forwardRef(({ className, ...props }, ref) => {
8706
9159
  const { formDescriptionId } = useFormField();
8707
- return /* @__PURE__ */ jsx39("p", { ref, id: formDescriptionId, className: cn("text-sm text-muted-foreground", className), ...props });
9160
+ return /* @__PURE__ */ jsx40("p", { ref, id: formDescriptionId, className: cn("text-sm text-muted-foreground", className), ...props });
8708
9161
  });
8709
9162
  FormDescription.displayName = "FormDescription";
8710
- var FormMessage = React31.forwardRef(({ className, children, ...props }, ref) => {
9163
+ var FormMessage = React32.forwardRef(({ className, children, ...props }, ref) => {
8711
9164
  const { error, formMessageId } = useFormField();
8712
9165
  const body = error ? String(error?.message) : children;
8713
9166
  if (!body) {
8714
9167
  return null;
8715
9168
  }
8716
- return /* @__PURE__ */ jsx39("p", { ref, id: formMessageId, className: cn("text-sm font-medium text-destructive", className), ...props, children: body });
9169
+ return /* @__PURE__ */ jsx40("p", { ref, id: formMessageId, className: cn("text-sm font-medium text-destructive", className), ...props, children: body });
8717
9170
  });
8718
9171
  FormMessage.displayName = "FormMessage";
8719
- var FormInput = React31.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ jsx39(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ jsx39(
9172
+ var FormInput = React32.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ jsx40(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ jsx40(
8720
9173
  FormField,
8721
9174
  {
8722
9175
  name,
8723
- render: ({ field }) => /* @__PURE__ */ jsxs33(FormItem, { children: [
8724
- /* @__PURE__ */ jsx39(FormControl, { children: /* @__PURE__ */ jsx39(Input_default, { size: props.size ?? size, ...field, ...props }) }),
8725
- /* @__PURE__ */ jsx39(FormMessage, {})
9176
+ render: ({ field }) => /* @__PURE__ */ jsxs34(FormItem, { children: [
9177
+ /* @__PURE__ */ jsx40(FormControl, { children: /* @__PURE__ */ jsx40(Input_default, { size: props.size ?? size, ...field, ...props }) }),
9178
+ /* @__PURE__ */ jsx40(FormMessage, {})
8726
9179
  ] })
8727
9180
  }
8728
9181
  ) }));
8729
9182
  FormInput.displayName = "FormInput";
8730
- var FormCheckbox = React31.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ jsx39(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ jsx39(
9183
+ var FormCheckbox = React32.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ jsx40(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ jsx40(
8731
9184
  FormField,
8732
9185
  {
8733
9186
  name,
8734
- render: ({ field }) => /* @__PURE__ */ jsxs33(FormItem, { children: [
8735
- /* @__PURE__ */ jsx39(FormControl, { children: /* @__PURE__ */ jsx39(
9187
+ render: ({ field }) => /* @__PURE__ */ jsxs34(FormItem, { children: [
9188
+ /* @__PURE__ */ jsx40(FormControl, { children: /* @__PURE__ */ jsx40(
8736
9189
  Checkbox,
8737
9190
  {
8738
9191
  ref,
@@ -8746,20 +9199,20 @@ var FormCheckbox = React31.forwardRef(({ name, ...props }, ref) => /* @__PURE__
8746
9199
  ...props
8747
9200
  }
8748
9201
  ) }),
8749
- /* @__PURE__ */ jsx39(FormMessage, {})
9202
+ /* @__PURE__ */ jsx40(FormMessage, {})
8750
9203
  ] })
8751
9204
  }
8752
9205
  ) }));
8753
9206
  FormCheckbox.displayName = "FormCheckbox";
8754
- var FormActions = React31.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx39("div", { ref, className: cn("flex gap-2 justify-end", className), ...props }));
9207
+ var FormActions = React32.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx40("div", { ref, className: cn("flex gap-2 justify-end", className), ...props }));
8755
9208
  FormActions.displayName = "FormActions";
8756
- var FormSubmitButton = React31.forwardRef(({ children, loading: loading2, ...props }, ref) => /* @__PURE__ */ jsx39(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ jsx39(Button_default, { ref, type: "submit", size: props.size ?? size, disabled: loading2, ...props, children }) }));
9209
+ var FormSubmitButton = React32.forwardRef(({ children, loading: loading2, ...props }, ref) => /* @__PURE__ */ jsx40(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ jsx40(Button_default, { ref, type: "submit", size: props.size ?? size, disabled: loading2, ...props, children }) }));
8757
9210
  FormSubmitButton.displayName = "FormSubmitButton";
8758
9211
 
8759
9212
  // ../../components/ui/NotificationModal.tsx
8760
9213
  import { ExternalLink } from "lucide-react";
8761
9214
  import { useTranslations as useTranslations9 } from "next-intl";
8762
- import { jsx as jsx40, jsxs as jsxs34 } from "react/jsx-runtime";
9215
+ import { jsx as jsx41, jsxs as jsxs35 } from "react/jsx-runtime";
8763
9216
  function NotificationModal({ isOpen, onClose, notification, titleText, openLinkText, closeText }) {
8764
9217
  const t = useTranslations9("Common");
8765
9218
  if (!notification) return null;
@@ -8780,26 +9233,26 @@ function NotificationModal({ isOpen, onClose, notification, titleText, openLinkT
8780
9233
  onClose();
8781
9234
  }
8782
9235
  };
8783
- return /* @__PURE__ */ jsx40(
9236
+ return /* @__PURE__ */ jsx41(
8784
9237
  Modal_default,
8785
9238
  {
8786
9239
  isOpen,
8787
9240
  onClose,
8788
9241
  title: titleText || t("notifications"),
8789
9242
  size: "md",
8790
- children: /* @__PURE__ */ jsxs34("div", { className: "space-y-4", children: [
8791
- /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-2 pb-2 border-b border-border", children: [
8792
- /* @__PURE__ */ jsx40("div", { className: cn(
9243
+ children: /* @__PURE__ */ jsxs35("div", { className: "space-y-4", children: [
9244
+ /* @__PURE__ */ jsxs35("div", { className: "flex items-center gap-2 pb-2 border-b border-border", children: [
9245
+ /* @__PURE__ */ jsx41("div", { className: cn(
8793
9246
  "w-2 h-2 rounded-full",
8794
9247
  !notification.is_read ? "bg-primary" : "bg-border"
8795
9248
  ) }),
8796
- /* @__PURE__ */ jsx40("span", { className: "text-xs text-muted-foreground", children: !notification.is_read ? t("newNotification") : t("readStatus") })
9249
+ /* @__PURE__ */ jsx41("span", { className: "text-xs text-muted-foreground", children: !notification.is_read ? t("newNotification") : t("readStatus") })
8797
9250
  ] }),
8798
- notification.title && /* @__PURE__ */ jsx40("h3", { className: "text-lg font-semibold text-foreground", children: notification.title }),
8799
- notification.body && /* @__PURE__ */ jsx40("div", { className: "text-sm text-muted-foreground whitespace-pre-wrap leading-relaxed", children: notification.body }),
8800
- /* @__PURE__ */ jsx40("div", { className: "text-xs text-muted-foreground border-t border-border pt-2", children: formatTime2(notification.created_at) }),
8801
- /* @__PURE__ */ jsxs34("div", { className: "flex gap-2 justify-end pt-2", children: [
8802
- hasLink && /* @__PURE__ */ jsxs34(
9251
+ notification.title && /* @__PURE__ */ jsx41("h3", { className: "text-lg font-semibold text-foreground", children: notification.title }),
9252
+ notification.body && /* @__PURE__ */ jsx41("div", { className: "text-sm text-muted-foreground whitespace-pre-wrap leading-relaxed", children: notification.body }),
9253
+ /* @__PURE__ */ jsx41("div", { className: "text-xs text-muted-foreground border-t border-border pt-2", children: formatTime2(notification.created_at) }),
9254
+ /* @__PURE__ */ jsxs35("div", { className: "flex gap-2 justify-end pt-2", children: [
9255
+ hasLink && /* @__PURE__ */ jsxs35(
8803
9256
  Button_default,
8804
9257
  {
8805
9258
  variant: "primary",
@@ -8807,12 +9260,12 @@ function NotificationModal({ isOpen, onClose, notification, titleText, openLinkT
8807
9260
  onClick: handleLinkClick,
8808
9261
  className: "gap-2",
8809
9262
  children: [
8810
- /* @__PURE__ */ jsx40(ExternalLink, { className: "w-4 h-4" }),
9263
+ /* @__PURE__ */ jsx41(ExternalLink, { className: "w-4 h-4" }),
8811
9264
  openLinkText || t("openLink")
8812
9265
  ]
8813
9266
  }
8814
9267
  ),
8815
- /* @__PURE__ */ jsx40(
9268
+ /* @__PURE__ */ jsx41(
8816
9269
  Button_default,
8817
9270
  {
8818
9271
  variant: "ghost",
@@ -8834,10 +9287,10 @@ import { usePathname } from "next/navigation";
8834
9287
  import { Phone } from "lucide-react";
8835
9288
 
8836
9289
  // ../../node_modules/react-icons/lib/iconBase.mjs
8837
- import React33 from "react";
9290
+ import React34 from "react";
8838
9291
 
8839
9292
  // ../../node_modules/react-icons/lib/iconContext.mjs
8840
- import React32 from "react";
9293
+ import React33 from "react";
8841
9294
  var DefaultContext = {
8842
9295
  color: void 0,
8843
9296
  size: void 0,
@@ -8845,7 +9298,7 @@ var DefaultContext = {
8845
9298
  style: void 0,
8846
9299
  attr: void 0
8847
9300
  };
8848
- var IconContext = React32.createContext && /* @__PURE__ */ React32.createContext(DefaultContext);
9301
+ var IconContext = React33.createContext && /* @__PURE__ */ React33.createContext(DefaultContext);
8849
9302
 
8850
9303
  // ../../node_modules/react-icons/lib/iconBase.mjs
8851
9304
  var _excluded = ["attr", "size", "title"];
@@ -8934,12 +9387,12 @@ function _toPrimitive(t, r) {
8934
9387
  return ("string" === r ? String : Number)(t);
8935
9388
  }
8936
9389
  function Tree2Element(tree) {
8937
- return tree && tree.map((node, i) => /* @__PURE__ */ React33.createElement(node.tag, _objectSpread({
9390
+ return tree && tree.map((node, i) => /* @__PURE__ */ React34.createElement(node.tag, _objectSpread({
8938
9391
  key: i
8939
9392
  }, node.attr), Tree2Element(node.child)));
8940
9393
  }
8941
9394
  function GenIcon(data) {
8942
- return (props) => /* @__PURE__ */ React33.createElement(IconBase, _extends({
9395
+ return (props) => /* @__PURE__ */ React34.createElement(IconBase, _extends({
8943
9396
  attr: _objectSpread({}, data.attr)
8944
9397
  }, props), Tree2Element(data.child));
8945
9398
  }
@@ -8954,7 +9407,7 @@ function IconBase(props) {
8954
9407
  var className;
8955
9408
  if (conf.className) className = conf.className;
8956
9409
  if (props.className) className = (className ? className + " " : "") + props.className;
8957
- return /* @__PURE__ */ React33.createElement("svg", _extends({
9410
+ return /* @__PURE__ */ React34.createElement("svg", _extends({
8958
9411
  stroke: "currentColor",
8959
9412
  fill: "currentColor",
8960
9413
  strokeWidth: "0"
@@ -8966,9 +9419,9 @@ function IconBase(props) {
8966
9419
  height: computedSize,
8967
9420
  width: computedSize,
8968
9421
  xmlns: "http://www.w3.org/2000/svg"
8969
- }), title && /* @__PURE__ */ React33.createElement("title", null, title), props.children);
9422
+ }), title && /* @__PURE__ */ React34.createElement("title", null, title), props.children);
8970
9423
  };
8971
- return IconContext !== void 0 ? /* @__PURE__ */ React33.createElement(IconContext.Consumer, null, (conf) => elem(conf)) : elem(DefaultContext);
9424
+ return IconContext !== void 0 ? /* @__PURE__ */ React34.createElement(IconContext.Consumer, null, (conf) => elem(conf)) : elem(DefaultContext);
8972
9425
  }
8973
9426
 
8974
9427
  // ../../node_modules/react-icons/fa/index.mjs
@@ -8982,9 +9435,9 @@ function SiZalo(props) {
8982
9435
  }
8983
9436
 
8984
9437
  // ../../components/ui/FloatingContacts.tsx
8985
- import { jsx as jsx41, jsxs as jsxs35 } from "react/jsx-runtime";
9438
+ import { jsx as jsx42, jsxs as jsxs36 } from "react/jsx-runtime";
8986
9439
  function MessengerIcon(props) {
8987
- return /* @__PURE__ */ jsx41("svg", { viewBox: "0 0 24 24", width: 24, height: 24, "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx41(
9440
+ return /* @__PURE__ */ jsx42("svg", { viewBox: "0 0 24 24", width: 24, height: 24, "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx42(
8988
9441
  "path",
8989
9442
  {
8990
9443
  d: "M12 2C6.477 2 2 6.145 2 11.235c0 2.93 1.35 5.542 3.464 7.25v3.515l3.344-1.836c.894.247 1.843.375 2.192.375 5.523 0 10-4.145 10-9.235S17.523 2 12 2zm.994 12.444l-2.563-2.73-5.004 2.73 5.507-5.84 2.626 2.729 4.942-2.729-5.508 5.84z",
@@ -8993,10 +9446,10 @@ function MessengerIcon(props) {
8993
9446
  ) });
8994
9447
  }
8995
9448
  function ZaloIcon(props) {
8996
- return /* @__PURE__ */ jsx41(SiZalo, { size: 20, ...props });
9449
+ return /* @__PURE__ */ jsx42(SiZalo, { size: 20, ...props });
8997
9450
  }
8998
9451
  function InstagramIcon(props) {
8999
- return /* @__PURE__ */ jsx41(FaInstagram, { size: 20, ...props });
9452
+ return /* @__PURE__ */ jsx42(FaInstagram, { size: 20, ...props });
9000
9453
  }
9001
9454
  function FloatingContacts({ className }) {
9002
9455
  const pathname = usePathname();
@@ -9031,8 +9484,8 @@ function FloatingContacts({ className }) {
9031
9484
  external: true
9032
9485
  }
9033
9486
  ];
9034
- return /* @__PURE__ */ jsxs35("div", { className: cn("fixed bottom-6 right-4 z-[100000]", "flex flex-col items-end gap-3", className), "aria-label": "Quick contacts", children: [
9035
- /* @__PURE__ */ jsx41(
9487
+ return /* @__PURE__ */ jsxs36("div", { className: cn("fixed bottom-6 right-4 z-[100000]", "flex flex-col items-end gap-3", className), "aria-label": "Quick contacts", children: [
9488
+ /* @__PURE__ */ jsx42(
9036
9489
  Link2,
9037
9490
  {
9038
9491
  href: `tel:${hotline.replace(/\D/g, "")}`,
@@ -9043,10 +9496,10 @@ function FloatingContacts({ className }) {
9043
9496
  "hover:scale-105 active:scale-95 transition-transform",
9044
9497
  "bg-[#22c55e]"
9045
9498
  ),
9046
- children: /* @__PURE__ */ jsx41(Phone, { className: "w-6 h-6" })
9499
+ children: /* @__PURE__ */ jsx42(Phone, { className: "w-6 h-6" })
9047
9500
  }
9048
9501
  ),
9049
- moreItems.map(({ key, href, label, bg, Icon, external }) => /* @__PURE__ */ jsx41(
9502
+ moreItems.map(({ key, href, label, bg, Icon, external }) => /* @__PURE__ */ jsx42(
9050
9503
  Link2,
9051
9504
  {
9052
9505
  href,
@@ -9058,7 +9511,7 @@ function FloatingContacts({ className }) {
9058
9511
  "hover:scale-105 active:scale-95 transition-transform",
9059
9512
  bg
9060
9513
  ),
9061
- children: /* @__PURE__ */ jsx41(Icon, { className: "w-6 h-6" })
9514
+ children: /* @__PURE__ */ jsx42(Icon, { className: "w-6 h-6" })
9062
9515
  },
9063
9516
  key
9064
9517
  ))
@@ -9067,7 +9520,7 @@ function FloatingContacts({ className }) {
9067
9520
 
9068
9521
  // ../../components/ui/AccessDenied.tsx
9069
9522
  import { Lock, ShieldAlert, Ban } from "lucide-react";
9070
- import { jsx as jsx42, jsxs as jsxs36 } from "react/jsx-runtime";
9523
+ import { jsx as jsx43, jsxs as jsxs37 } from "react/jsx-runtime";
9071
9524
  var VARIANT_STYLES = {
9072
9525
  destructive: { bg: "bg-destructive/5", border: "border-destructive/20", text: "text-destructive" },
9073
9526
  warning: { bg: "bg-warning/5", border: "border-warning/20", text: "text-warning" },
@@ -9088,13 +9541,13 @@ function AccessDenied({
9088
9541
  }) {
9089
9542
  const styles = VARIANT_STYLES[variant];
9090
9543
  const UsedIcon = Icon || DEFAULT_ICONS[variant];
9091
- return /* @__PURE__ */ jsx42(Card_default, { className: cn("p-8 text-center shadow-sm", styles.bg, styles.border, className), children: /* @__PURE__ */ jsxs36("div", { className: "flex flex-col items-center gap-4", children: [
9092
- /* @__PURE__ */ jsx42("div", { className: cn("p-3 rounded-lg", styles.bg.replace("/5", "/10")), children: /* @__PURE__ */ jsx42(UsedIcon, { className: cn("w-8 h-8", styles.text) }) }),
9093
- /* @__PURE__ */ jsxs36("div", { children: [
9094
- /* @__PURE__ */ jsx42("h3", { className: cn("font-semibold mb-2", styles.text), children: title }),
9095
- /* @__PURE__ */ jsx42("p", { className: cn(styles.text.replace("text-", "text-") + "/80", "text-sm"), children: description })
9544
+ return /* @__PURE__ */ jsx43(Card_default, { className: cn("p-8 text-center shadow-sm", styles.bg, styles.border, className), children: /* @__PURE__ */ jsxs37("div", { className: "flex flex-col items-center gap-4", children: [
9545
+ /* @__PURE__ */ jsx43("div", { className: cn("p-3 rounded-lg", styles.bg.replace("/5", "/10")), children: /* @__PURE__ */ jsx43(UsedIcon, { className: cn("w-8 h-8", styles.text) }) }),
9546
+ /* @__PURE__ */ jsxs37("div", { children: [
9547
+ /* @__PURE__ */ jsx43("h3", { className: cn("font-semibold mb-2", styles.text), children: title }),
9548
+ /* @__PURE__ */ jsx43("p", { className: cn(styles.text.replace("text-", "text-") + "/80", "text-sm"), children: description })
9096
9549
  ] }),
9097
- children && /* @__PURE__ */ jsx42("div", { className: "mt-2 flex flex-wrap gap-2 justify-center", children })
9550
+ children && /* @__PURE__ */ jsx43("div", { className: "mt-2 flex flex-wrap gap-2 justify-center", children })
9098
9551
  ] }) });
9099
9552
  }
9100
9553
 
@@ -9102,7 +9555,7 @@ function AccessDenied({
9102
9555
  import { Moon, Sun, Monitor } from "lucide-react";
9103
9556
  import { useEffect as useEffect17, useRef as useRef10, useState as useState27 } from "react";
9104
9557
  import { createPortal as createPortal9 } from "react-dom";
9105
- import { Fragment as Fragment10, jsx as jsx43, jsxs as jsxs37 } from "react/jsx-runtime";
9558
+ import { Fragment as Fragment11, jsx as jsx44, jsxs as jsxs38 } from "react/jsx-runtime";
9106
9559
  function ThemeToggleHeadless({
9107
9560
  theme,
9108
9561
  onChange,
@@ -9131,8 +9584,8 @@ function ThemeToggleHeadless({
9131
9584
  const top = rect.bottom + scrollTop + 8;
9132
9585
  return { top, left, width };
9133
9586
  };
9134
- return /* @__PURE__ */ jsxs37("div", { className: cn("relative", className), children: [
9135
- /* @__PURE__ */ jsx43(
9587
+ return /* @__PURE__ */ jsxs38("div", { className: cn("relative", className), children: [
9588
+ /* @__PURE__ */ jsx44(
9136
9589
  Button_default,
9137
9590
  {
9138
9591
  variant: "ghost",
@@ -9150,25 +9603,25 @@ function ThemeToggleHeadless({
9150
9603
  "aria-haspopup": "menu",
9151
9604
  "aria-expanded": isOpen,
9152
9605
  "aria-label": labels?.heading ?? "Theme",
9153
- children: /* @__PURE__ */ jsx43(CurrentIcon, { className: "h-5 w-5" })
9606
+ children: /* @__PURE__ */ jsx44(CurrentIcon, { className: "h-5 w-5" })
9154
9607
  }
9155
9608
  ),
9156
- isOpen && /* @__PURE__ */ jsxs37(Fragment10, { children: [
9157
- typeof window !== "undefined" && createPortal9(/* @__PURE__ */ jsx43("div", { className: "fixed inset-0 z-[9998]", onClick: () => setIsOpen(false) }), document.body),
9609
+ isOpen && /* @__PURE__ */ jsxs38(Fragment11, { children: [
9610
+ typeof window !== "undefined" && createPortal9(/* @__PURE__ */ jsx44("div", { className: "fixed inset-0 z-[9998]", onClick: () => setIsOpen(false) }), document.body),
9158
9611
  typeof window !== "undefined" && dropdownPosition && createPortal9(
9159
- /* @__PURE__ */ jsx43(
9612
+ /* @__PURE__ */ jsx44(
9160
9613
  "div",
9161
9614
  {
9162
9615
  className: "z-[9999] bg-card border border-border rounded-lg shadow-lg overflow-hidden",
9163
9616
  style: { position: "absolute", top: dropdownPosition.top, left: dropdownPosition.left, width: dropdownPosition.width },
9164
9617
  onMouseDown: (e) => e.stopPropagation(),
9165
9618
  role: "menu",
9166
- children: /* @__PURE__ */ jsxs37("div", { className: "p-2", children: [
9167
- /* @__PURE__ */ jsx43("div", { className: "px-3 py-2 text-sm font-medium text-muted-foreground border-b border-border mb-2", children: labels?.heading ?? "Theme" }),
9619
+ children: /* @__PURE__ */ jsxs38("div", { className: "p-2", children: [
9620
+ /* @__PURE__ */ jsx44("div", { className: "px-3 py-2 text-sm font-medium text-muted-foreground border-b border-border mb-2", children: labels?.heading ?? "Theme" }),
9168
9621
  themes.map((opt) => {
9169
9622
  const Icon = opt.icon;
9170
9623
  const active = theme === opt.value;
9171
- return /* @__PURE__ */ jsxs37(
9624
+ return /* @__PURE__ */ jsxs38(
9172
9625
  Button_default,
9173
9626
  {
9174
9627
  variant: "ghost",
@@ -9184,9 +9637,9 @@ function ThemeToggleHeadless({
9184
9637
  role: "menuitemradio",
9185
9638
  "aria-checked": active,
9186
9639
  children: [
9187
- /* @__PURE__ */ jsx43(Icon, { className: "h-4 w-4" }),
9188
- /* @__PURE__ */ jsx43("span", { className: "flex-1 text-left", children: opt.label }),
9189
- active && /* @__PURE__ */ jsx43("div", { className: "w-2 h-2 rounded-full bg-primary" })
9640
+ /* @__PURE__ */ jsx44(Icon, { className: "h-4 w-4" }),
9641
+ /* @__PURE__ */ jsx44("span", { className: "flex-1 text-left", children: opt.label }),
9642
+ active && /* @__PURE__ */ jsx44("div", { className: "w-2 h-2 rounded-full bg-primary" })
9190
9643
  ]
9191
9644
  },
9192
9645
  opt.value
@@ -9205,7 +9658,7 @@ function ThemeToggleHeadless({
9205
9658
  import { useRef as useRef11, useState as useState28 } from "react";
9206
9659
  import { createPortal as createPortal10 } from "react-dom";
9207
9660
  import { Globe } from "lucide-react";
9208
- import { Fragment as Fragment11, jsx as jsx44, jsxs as jsxs38 } from "react/jsx-runtime";
9661
+ import { Fragment as Fragment12, jsx as jsx45, jsxs as jsxs39 } from "react/jsx-runtime";
9209
9662
  function LanguageSwitcherHeadless({
9210
9663
  locales,
9211
9664
  currentLocale,
@@ -9227,8 +9680,8 @@ function LanguageSwitcherHeadless({
9227
9680
  const top = rect.bottom + scrollTop + 8;
9228
9681
  return { top, left, width };
9229
9682
  };
9230
- return /* @__PURE__ */ jsxs38("div", { className: cn("relative", className), children: [
9231
- /* @__PURE__ */ jsx44(
9683
+ return /* @__PURE__ */ jsxs39("div", { className: cn("relative", className), children: [
9684
+ /* @__PURE__ */ jsx45(
9232
9685
  Button_default,
9233
9686
  {
9234
9687
  variant: "ghost",
@@ -9247,22 +9700,22 @@ function LanguageSwitcherHeadless({
9247
9700
  "aria-expanded": isOpen,
9248
9701
  "aria-label": labels?.heading ?? "Language",
9249
9702
  title: labels?.heading ?? "Language",
9250
- children: /* @__PURE__ */ jsx44(Globe, { className: "h-5 w-5" })
9703
+ children: /* @__PURE__ */ jsx45(Globe, { className: "h-5 w-5" })
9251
9704
  }
9252
9705
  ),
9253
- isOpen && /* @__PURE__ */ jsxs38(Fragment11, { children: [
9254
- typeof window !== "undefined" && createPortal10(/* @__PURE__ */ jsx44("div", { className: "fixed inset-0 z-[9998]", onClick: () => setIsOpen(false) }), document.body),
9706
+ isOpen && /* @__PURE__ */ jsxs39(Fragment12, { children: [
9707
+ typeof window !== "undefined" && createPortal10(/* @__PURE__ */ jsx45("div", { className: "fixed inset-0 z-[9998]", onClick: () => setIsOpen(false) }), document.body),
9255
9708
  typeof window !== "undefined" && dropdownPosition && createPortal10(
9256
- /* @__PURE__ */ jsx44(
9709
+ /* @__PURE__ */ jsx45(
9257
9710
  "div",
9258
9711
  {
9259
9712
  className: "z-[9999] bg-card border border-border rounded-lg shadow-lg overflow-hidden",
9260
9713
  style: { position: "absolute", top: dropdownPosition.top, left: dropdownPosition.left, width: dropdownPosition.width },
9261
9714
  onMouseDown: (e) => e.stopPropagation(),
9262
9715
  role: "menu",
9263
- children: /* @__PURE__ */ jsxs38("div", { className: "p-2", children: [
9264
- /* @__PURE__ */ jsx44("div", { className: "px-3 py-2 text-sm font-medium text-muted-foreground border-b border-border mb-2", children: labels?.heading ?? "Language" }),
9265
- locales.map((language) => /* @__PURE__ */ jsxs38(
9716
+ children: /* @__PURE__ */ jsxs39("div", { className: "p-2", children: [
9717
+ /* @__PURE__ */ jsx45("div", { className: "px-3 py-2 text-sm font-medium text-muted-foreground border-b border-border mb-2", children: labels?.heading ?? "Language" }),
9718
+ locales.map((language) => /* @__PURE__ */ jsxs39(
9266
9719
  Button_default,
9267
9720
  {
9268
9721
  variant: "ghost",
@@ -9275,9 +9728,9 @@ function LanguageSwitcherHeadless({
9275
9728
  role: "menuitemradio",
9276
9729
  "aria-checked": currentLocale === language.code,
9277
9730
  children: [
9278
- language.flag && /* @__PURE__ */ jsx44("span", { className: "text-lg", children: language.flag }),
9279
- /* @__PURE__ */ jsx44("span", { className: "flex-1 text-left", children: language.name }),
9280
- currentLocale === language.code && /* @__PURE__ */ jsx44("div", { className: "w-2 h-2 rounded-full bg-primary" })
9731
+ language.flag && /* @__PURE__ */ jsx45("span", { className: "text-lg", children: language.flag }),
9732
+ /* @__PURE__ */ jsx45("span", { className: "flex-1 text-left", children: language.name }),
9733
+ currentLocale === language.code && /* @__PURE__ */ jsx45("div", { className: "w-2 h-2 rounded-full bg-primary" })
9281
9734
  ]
9282
9735
  },
9283
9736
  language.code
@@ -9480,6 +9933,7 @@ export {
9480
9933
  NotificationBadge,
9481
9934
  NotificationModal_default as NotificationModal,
9482
9935
  NumberInput,
9936
+ OverlayControls,
9483
9937
  PageLoading,
9484
9938
  Pagination,
9485
9939
  PasswordInput,