@farmzone/fz-react-ui 1.0.2 → 1.0.4

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
@@ -44,9 +44,10 @@ var buttonVariants = cva(
44
44
  delete: "bg-white border border-sub-red text-main-red hover:bg-red-50 disabled:bg-light-gray disabled:border-sub-lightgray-2 disabled:text-sub-lightgray-2 font-bold min-w-22",
45
45
  reset: "bg-white border border-sub-lightgray-2 text-sub-darkgray hover:bg-gray-100 hover:text-black",
46
46
  search: "bg-main-blue border-none text-white hover:bg-main-blue/90",
47
- file: "bg-sub-darkgray text-white hover:bg-sub-darkgray/80",
47
+ file: "bg-btn-file text-white hover:bg-btn-file/90",
48
48
  carousel: "bg-white border border-gray-300 hover:bg-gray-100 hover:text-black rounded-full",
49
49
  accent: "btn-grad text-white rounded-full",
50
+ metal: "btn-metal text-white min-w-22",
50
51
  ghost: "p-1 h-auto rounded-sm bg-transparent hover:bg-sub-lightgray text-sub-darkgray hover:bg-inherit",
51
52
  link: "bg-transparent border-none text-main-blue underline-offset-4 hover:underline h-auto p-0"
52
53
  },
@@ -208,6 +209,32 @@ function TooltipContent({
208
209
  }
209
210
  ) });
210
211
  }
212
+
213
+ // src/config/zIndex.ts
214
+ var Z_INDEX = {
215
+ TABLE_COL_STICKY: 1,
216
+ TABLE_FIXED_CELL: 5,
217
+ TABLE_FIXED_HEADER_CELL: 10,
218
+ LOCAL_OVERLAY: 10,
219
+ LAYOUT_HEADER: 20,
220
+ DROPDOWN_LOCAL: 20,
221
+ SIDEBAR_CONTAINER: 30,
222
+ SIDEBAR_BACKDROP: 40,
223
+ SIDEBAR: 50,
224
+ DROPDOWN: 50,
225
+ CALENDAR_ANCHORED: 50,
226
+ LOADING_OVERLAY_DEFAULT: 50,
227
+ DRAWING_CANVAS_1: 51,
228
+ DRAWING_CANVAS_2: 52,
229
+ DRAWING: 53,
230
+ MODAL_OVERLAY: 54,
231
+ MODAL: 55,
232
+ CALENDAR_PORTAL: 60,
233
+ TOOLTIP: 70,
234
+ SELECT_CONTENT: 100,
235
+ TOP: 9999,
236
+ MODAL_Z_STEP: 10
237
+ };
211
238
  function Tooltip2(props) {
212
239
  const {
213
240
  children,
@@ -219,6 +246,7 @@ function Tooltip2(props) {
219
246
  arrowClassName = "",
220
247
  contentClassName = "",
221
248
  contentStyle = {},
249
+ containerStyle,
222
250
  offsetX = 0,
223
251
  offsetY = 2,
224
252
  delayDuration = 0,
@@ -238,7 +266,9 @@ function Tooltip2(props) {
238
266
  sideOffset,
239
267
  collisionPadding: 8,
240
268
  style: {
241
- transform: `translateX(${offsetX}px) translateY(${translateY}px)`
269
+ zIndex: Z_INDEX.TOOLTIP,
270
+ transform: `translateX(${offsetX}px) translateY(${translateY}px)`,
271
+ ...containerStyle
242
272
  },
243
273
  children: /* @__PURE__ */ jsx("div", { className: "px-3 py-[5px] break-words whitespace-normal", style: contentStyle, children: /* @__PURE__ */ jsxs("p", { className: contentClassName, children: [
244
274
  content && /* @__PURE__ */ jsx("span", { children: content }),
@@ -1285,31 +1315,6 @@ function Spinner(props) {
1285
1315
  }
1286
1316
  );
1287
1317
  }
1288
-
1289
- // src/config/zIndex.ts
1290
- var Z_INDEX = {
1291
- TABLE_COL_STICKY: 1,
1292
- TABLE_FIXED_CELL: 5,
1293
- TABLE_FIXED_HEADER_CELL: 10,
1294
- LOCAL_OVERLAY: 10,
1295
- LAYOUT_HEADER: 20,
1296
- DROPDOWN_LOCAL: 20,
1297
- SIDEBAR_CONTAINER: 30,
1298
- SIDEBAR_BACKDROP: 40,
1299
- SIDEBAR: 50,
1300
- DROPDOWN: 50,
1301
- CALENDAR_ANCHORED: 50,
1302
- LOADING_OVERLAY_DEFAULT: 50,
1303
- DRAWING_CANVAS_1: 51,
1304
- DRAWING_CANVAS_2: 52,
1305
- DRAWING: 53,
1306
- MODAL_OVERLAY: 54,
1307
- MODAL: 55,
1308
- CALENDAR_PORTAL: 60,
1309
- SELECT_CONTENT: 100,
1310
- TOP: 9999,
1311
- MODAL_Z_STEP: 10
1312
- };
1313
1318
  function LoadingOverlay(props) {
1314
1319
  const {
1315
1320
  isVisible,
@@ -1924,13 +1929,18 @@ function ToastProvider() {
1924
1929
  }
1925
1930
 
1926
1931
  // src/components/DatePicker/config/utils.ts
1932
+ function makeLocalDate(year, monthIndex, day) {
1933
+ const d = /* @__PURE__ */ new Date(0);
1934
+ d.setFullYear(year, monthIndex, day);
1935
+ return d;
1936
+ }
1927
1937
  function parseLocalYmd(ymd) {
1928
1938
  const m = ymd.trim().match(/^(\d{4})-(\d{2})-(\d{2})$/);
1929
1939
  if (!m) return null;
1930
1940
  const y = Number(m[1]);
1931
1941
  const mo = Number(m[2]) - 1;
1932
1942
  const d = Number(m[3]);
1933
- const dt = new Date(y, mo, d);
1943
+ const dt = makeLocalDate(y, mo, d);
1934
1944
  if (dt.getFullYear() !== y || dt.getMonth() !== mo || dt.getDate() !== d) return null;
1935
1945
  return dt;
1936
1946
  }
@@ -1964,7 +1974,7 @@ function isCalendarDayAfterMax(date, maxYmd) {
1964
1974
  return ax > bx;
1965
1975
  }
1966
1976
  function formatDate(date) {
1967
- const year = date.getFullYear();
1977
+ const year = String(date.getFullYear()).padStart(4, "0");
1968
1978
  const month = String(date.getMonth() + 1).padStart(2, "0");
1969
1979
  const day = String(date.getDate()).padStart(2, "0");
1970
1980
  return `${year}-${month}-${day}`;
@@ -1983,7 +1993,6 @@ function validateAndFormatInput(input) {
1983
1993
  if (numbers.length === 0) return "";
1984
1994
  const clampYear = (raw) => {
1985
1995
  const n = parseInt(raw, 10);
1986
- if (n < 1) return "0001";
1987
1996
  if (n > 9999) return "9999";
1988
1997
  return raw;
1989
1998
  };
@@ -2006,7 +2015,7 @@ function validateAndFormatInput(input) {
2006
2015
  let day = dayRaw;
2007
2016
  if (day.length === 2) {
2008
2017
  const dayNum = parseInt(day, 10);
2009
- const lastDayOfMonth = new Date(parseInt(year, 10), parseInt(month, 10), 0).getDate();
2018
+ const lastDayOfMonth = makeLocalDate(parseInt(year, 10), parseInt(month, 10), 0).getDate();
2010
2019
  if (dayNum < 1) day = "01";
2011
2020
  else if (dayNum > lastDayOfMonth) day = lastDayOfMonth.toString().padStart(2, "0");
2012
2021
  }
@@ -2014,7 +2023,7 @@ function validateAndFormatInput(input) {
2014
2023
  }
2015
2024
 
2016
2025
  // src/components/DatePicker/calendar/config/default.ts
2017
- var DEFAULT_CALENDAR_YEAR_HALF_SPAN = 25;
2026
+ var DEFAULT_CALENDAR_YEAR_HALF_SPAN = 50;
2018
2027
  var CALENDAR_WEEKDAY_LABELS = ["\uC77C", "\uC6D4", "\uD654", "\uC218", "\uBAA9", "\uAE08", "\uD1A0"];
2019
2028
  var CALENDAR_RANGE_HINT = {
2020
2029
  start: "\uC2DC\uC791 \uB0A0\uC9DC\uB97C \uC120\uD0DD\uD558\uC138\uC694",
@@ -2038,7 +2047,7 @@ function parseYmdDateString(value) {
2038
2047
  return parseLocalYmd(value);
2039
2048
  }
2040
2049
  function resolveCalendarYearBounds(anchorYear, calendarYearRange) {
2041
- const fallbackMin = anchorYear - DEFAULT_CALENDAR_YEAR_HALF_SPAN;
2050
+ const fallbackMin = Math.max(0, anchorYear - DEFAULT_CALENDAR_YEAR_HALF_SPAN);
2042
2051
  const fallbackMax = anchorYear + DEFAULT_CALENDAR_YEAR_HALF_SPAN;
2043
2052
  const rawMin = calendarYearRange?.minYear?.trim();
2044
2053
  const rawMax = calendarYearRange?.maxYear?.trim();
@@ -2050,7 +2059,7 @@ function resolveCalendarYearBounds(anchorYear, calendarYearRange) {
2050
2059
  if (Number.isNaN(minParsed) || Number.isNaN(maxParsed) || minParsed > maxParsed) {
2051
2060
  return { minYear: fallbackMin, maxYear: fallbackMax };
2052
2061
  }
2053
- return { minYear: minParsed, maxYear: maxParsed };
2062
+ return { minYear: Math.max(0, minParsed), maxYear: maxParsed };
2054
2063
  }
2055
2064
  function buildCalendarYearSelectOptions(maxDate, anchorYear = (/* @__PURE__ */ new Date()).getFullYear(), calendarYearRange) {
2056
2065
  const { minYear, maxYear } = resolveCalendarYearBounds(anchorYear, calendarYearRange);
@@ -2059,7 +2068,7 @@ function buildCalendarYearSelectOptions(maxDate, anchorYear = (/* @__PURE__ */ n
2059
2068
  for (let y = maxYear; y >= minYear; y--) {
2060
2069
  options.push({
2061
2070
  value: String(y),
2062
- label: `${y}\uB144`,
2071
+ label: `${String(y).padStart(4, "0")}\uB144`,
2063
2072
  disabled: maxSelectableYear !== null && y > maxSelectableYear
2064
2073
  });
2065
2074
  }
@@ -2081,8 +2090,8 @@ function buildCalendarMonthSelectOptions(viewYear, maxDate) {
2081
2090
  return options;
2082
2091
  }
2083
2092
  function getCalendarMonthGrid(year, monthIndex) {
2084
- const firstDay = new Date(year, monthIndex, 1);
2085
- const daysInMonth = new Date(year, monthIndex + 1, 0).getDate();
2093
+ const firstDay = makeLocalDate(year, monthIndex, 1);
2094
+ const daysInMonth = makeLocalDate(year, monthIndex + 1, 0).getDate();
2086
2095
  const leadingEmpty = firstDay.getDay();
2087
2096
  const totalCells = leadingEmpty + daysInMonth;
2088
2097
  const trailingEmpty = totalCells % 7 === 0 ? 0 : 7 - totalCells % 7;
@@ -2090,7 +2099,7 @@ function getCalendarMonthGrid(year, monthIndex) {
2090
2099
  }
2091
2100
  function disableNextCalendarMonth(year, monthIndex, maxDate) {
2092
2101
  if (maxDate === void 0) return false;
2093
- return isCalendarDayAfterMax(new Date(year, monthIndex + 1, 1), maxDate);
2102
+ return isCalendarDayAfterMax(makeLocalDate(year, monthIndex + 1, 1), maxDate);
2094
2103
  }
2095
2104
  function scrollOpenYearSelectCheckedIntoView() {
2096
2105
  requestAnimationFrame(() => {
@@ -2136,7 +2145,7 @@ function RenderCalendar(props) {
2136
2145
  } = props;
2137
2146
  const year = currentDate.getFullYear();
2138
2147
  const monthIndex = currentDate.getMonth();
2139
- const anchorYear = (/* @__PURE__ */ new Date()).getFullYear();
2148
+ const anchorYear = year;
2140
2149
  const disableNextMonth = disableNextCalendarMonth(year, monthIndex, maxDate);
2141
2150
  const { leadingEmpty, daysInMonth, trailingEmpty } = getCalendarMonthGrid(year, monthIndex);
2142
2151
  const yearOptions = buildCalendarYearSelectOptions(maxDate, anchorYear, calendarYearRange);
@@ -2150,7 +2159,7 @@ function RenderCalendar(props) {
2150
2159
  days.push(/* @__PURE__ */ jsx("div", { className: "size-8", "aria-hidden": true }, `lead-${i}`));
2151
2160
  }
2152
2161
  for (let d = 1; d <= daysInMonth; d++) {
2153
- const date = new Date(year, monthIndex, d);
2162
+ const date = makeLocalDate(year, monthIndex, d);
2154
2163
  const dateFormatted = formatDate(date);
2155
2164
  const isToday = dateFormatted === todayFormatted;
2156
2165
  const isSelected = dateFormatted === selectedSingleYmd;
@@ -2249,7 +2258,7 @@ function RenderCalendar(props) {
2249
2258
  ]
2250
2259
  }
2251
2260
  ) : /* @__PURE__ */ jsxs("h3", { className: "text-lg font-semibold", children: [
2252
- year,
2261
+ String(year).padStart(4, "0"),
2253
2262
  "\uB144 ",
2254
2263
  monthIndex + 1,
2255
2264
  "\uC6D4"
@@ -2330,16 +2339,16 @@ function useCalendarState(props) {
2330
2339
  setIsCalendarOpen(false);
2331
2340
  };
2332
2341
  const goToPreviousMonth = () => {
2333
- setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, 1));
2342
+ setCurrentDate(makeLocalDate(currentDate.getFullYear(), currentDate.getMonth() - 1, 1));
2334
2343
  };
2335
2344
  const goToNextMonth = () => {
2336
- setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1));
2345
+ setCurrentDate(makeLocalDate(currentDate.getFullYear(), currentDate.getMonth() + 1, 1));
2337
2346
  };
2338
2347
  const handleYearChange = (year) => {
2339
- setCurrentDate(new Date(year, currentDate.getMonth(), 1));
2348
+ setCurrentDate(makeLocalDate(year, currentDate.getMonth(), 1));
2340
2349
  };
2341
2350
  const handleMonthChange = (month) => {
2342
- setCurrentDate(new Date(currentDate.getFullYear(), month, 1));
2351
+ setCurrentDate(makeLocalDate(currentDate.getFullYear(), month, 1));
2343
2352
  };
2344
2353
  return {
2345
2354
  isCalendarOpen,
@@ -2466,6 +2475,7 @@ function DatePickerRange(props) {
2466
2475
  return;
2467
2476
  }
2468
2477
  onRangeChange?.(formatted, endInputValue);
2478
+ if (isCalendarOpen && calendarPosition === "start") navigateToDateValue(formatted);
2469
2479
  } else if (formatted.length === 0) {
2470
2480
  onRangeChange?.(formatted, endInputValue);
2471
2481
  }
@@ -2479,6 +2489,7 @@ function DatePickerRange(props) {
2479
2489
  return;
2480
2490
  }
2481
2491
  onRangeChange?.(startInputValue, formatted);
2492
+ if (isCalendarOpen && calendarPosition === "end") navigateToDateValue(formatted);
2482
2493
  } else if (formatted.length === 0) {
2483
2494
  onRangeChange?.(startInputValue, formatted);
2484
2495
  }
@@ -2653,6 +2664,7 @@ function DatePickerSingle(props) {
2653
2664
  autoDatePosition,
2654
2665
  containerRef,
2655
2666
  toggleCalendar,
2667
+ navigateToDateValue,
2656
2668
  closeCalendar,
2657
2669
  goToPreviousMonth,
2658
2670
  goToNextMonth,
@@ -2670,7 +2682,7 @@ function DatePickerSingle(props) {
2670
2682
  const dateMatch = formatted.match(/^(\d{4})-(\d{2})-(\d{2})$/);
2671
2683
  if (dateMatch) {
2672
2684
  const [, year, month, day] = dateMatch;
2673
- const date = new Date(
2685
+ const date = makeLocalDate(
2674
2686
  Number.parseInt(year, 10),
2675
2687
  Number.parseInt(month, 10) - 1,
2676
2688
  Number.parseInt(day, 10)
@@ -2682,6 +2694,7 @@ function DatePickerSingle(props) {
2682
2694
  return;
2683
2695
  }
2684
2696
  onChange?.(formatted);
2697
+ if (isCalendarOpen) navigateToDateValue(formatted);
2685
2698
  }
2686
2699
  }
2687
2700
  } else {
@@ -3350,8 +3363,7 @@ function ModalContent(props) {
3350
3363
  {
3351
3364
  ref,
3352
3365
  className: cn(
3353
- "fixed left-[50%] top-[50%] max-h-[85vh] z-55 flex flex-col w-full max-w-lg translate-x-[-50%] translate-y-[-50%] bg-white rounded-lg overflow-hidden shadow-xl duration-200",
3354
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
3366
+ "fixed left-[50%] top-[50%] max-h-[85vh] z-55 flex flex-col w-full max-w-lg translate-x-[-50%] translate-y-[-50%] bg-white rounded-lg overflow-hidden shadow-xl",
3355
3367
  className
3356
3368
  ),
3357
3369
  style: zIndex !== void 0 ? { zIndex } : void 0,
@@ -3362,7 +3374,7 @@ function ModalContent(props) {
3362
3374
  );
3363
3375
  }
3364
3376
  function ModalOverlay(props) {
3365
- const { isOpen: isOpen2, onClose, className, closeOnOverlayClick = true, zIndex } = props;
3377
+ const { ref, isOpen: isOpen2, onClose, className, closeOnOverlayClick = true, zIndex } = props;
3366
3378
  if (!isOpen2) return null;
3367
3379
  const handleOverlayClick = (e) => {
3368
3380
  if (closeOnOverlayClick && e.target === e.currentTarget) {
@@ -3372,9 +3384,10 @@ function ModalOverlay(props) {
3372
3384
  return /* @__PURE__ */ jsx(
3373
3385
  "div",
3374
3386
  {
3387
+ ref,
3375
3388
  className: cn(
3376
3389
  "fixed inset-0 z-54 bg-black/50",
3377
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
3390
+ "animate-in fade-in-0 duration-150",
3378
3391
  className
3379
3392
  ),
3380
3393
  style: zIndex !== void 0 ? { zIndex } : void 0,
@@ -3476,7 +3489,7 @@ function Modal(props) {
3476
3489
  } = props;
3477
3490
  const idRef = useRef(/* @__PURE__ */ Symbol("modal"));
3478
3491
  const [depth, setDepth] = useState(0);
3479
- useEffect(() => {
3492
+ useLayoutEffect(() => {
3480
3493
  if (!isOpen2) return;
3481
3494
  const id = idRef.current;
3482
3495
  const d = modalStack.push(id);
@@ -3513,12 +3526,22 @@ function Modal(props) {
3513
3526
  {
3514
3527
  isOpen: isOpen2,
3515
3528
  onClose,
3516
- className: overlayClassName,
3529
+ className: cn(overlayClassName, depth > 1 && "bg-black/20"),
3517
3530
  closeOnOverlayClick,
3518
3531
  zIndex: overlayZ
3519
3532
  }
3520
3533
  ),
3521
- /* @__PURE__ */ jsx(ModalContent, { className: contentClassName, zIndex: contentZ, children })
3534
+ /* @__PURE__ */ jsx(
3535
+ ModalContent,
3536
+ {
3537
+ className: cn(
3538
+ contentClassName,
3539
+ depth > 1 && "shadow-[0_0_0_1px_rgba(255,255,255,0.12),0_20px_50px_-5px_rgba(0,0,0,0.4)]"
3540
+ ),
3541
+ zIndex: contentZ,
3542
+ children
3543
+ }
3544
+ )
3522
3545
  ] });
3523
3546
  }
3524
3547
  function ConfirmModal(props) {
@@ -3618,9 +3641,10 @@ function ConfirmModal(props) {
3618
3641
  ] }),
3619
3642
  /* @__PURE__ */ jsxs("div", { className: "flex h-8 items-center justify-end gap-2", children: [
3620
3643
  !isHideOkButton && /* @__PURE__ */ jsx(
3621
- Button,
3644
+ DebouncedButton,
3622
3645
  {
3623
3646
  ref: okButtonRef,
3647
+ debounceDelay: 500,
3624
3648
  variant: "outline",
3625
3649
  onClick: handleOkClick,
3626
3650
  className: "focus-visible:ring-2 focus-visible:ring-blue-400 focus-visible:ring-offset-1",
@@ -4018,7 +4042,7 @@ function TableHeader(props) {
4018
4042
  const subTitleClasses = column.key === "subTitle" ? "inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800" : "";
4019
4043
  if (column.align === "left") {
4020
4044
  return /* @__PURE__ */ jsxs("div", { className: "flex item-center w-full", children: [
4021
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: `pl-2 truncate ${baseClasses} ${isClickableHead} ${subTitleClasses}`, children: column.title }) }),
4045
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: `pl-3 truncate ${baseClasses} ${isClickableHead} ${subTitleClasses}`, children: column.title }) }),
4022
4046
  column.sortable && /* @__PURE__ */ jsx(
4023
4047
  "div",
4024
4048
  {
@@ -4049,7 +4073,7 @@ function TableHeader(props) {
4049
4073
  children: renderSortIcon(column.key)
4050
4074
  }
4051
4075
  ),
4052
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: `pr-2 truncate ${baseClasses} ${isClickableHead} ${subTitleClasses}`, children: column.title }) })
4076
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: `pr-3 truncate ${baseClasses} ${isClickableHead} ${subTitleClasses}`, children: column.title }) })
4053
4077
  ] });
4054
4078
  }
4055
4079
  return /* @__PURE__ */ jsx("span", { className: `px-1.5 truncate ${baseClasses} ${isClickableHead} ${subTitleClasses}`, children: column.title });
@@ -4420,7 +4444,7 @@ function SkeletonTd(props) {
4420
4444
  return /* @__PURE__ */ jsx(
4421
4445
  "td",
4422
4446
  {
4423
- className: `${col.key === "__checkbox__" ? "p-0" : "px-2 py-[6.8px]"} whitespace-nowrap text-sm border-r border-b border-gray-200/70 last:border-r-0`,
4447
+ className: `${col.key === "__checkbox__" ? "p-0" : "px-2 py-4"} whitespace-nowrap text-sm border-r border-b border-gray-200/70 last:border-r-0`,
4424
4448
  style: {
4425
4449
  width: col.width,
4426
4450
  minWidth: col.minWidth || col.width,
@@ -4492,7 +4516,7 @@ function TableCellContent(props) {
4492
4516
  "div",
4493
4517
  {
4494
4518
  ref: textRef,
4495
- className: "ellipsis-1-line table-item hover:text-main cursor-pointer w-full min-w-0",
4519
+ className: `ellipsis-1-line table-item w-full min-w-0 ${onCellClick ? "hover:text-main cursor-pointer" : "cursor-default"}`,
4496
4520
  style: { textAlign },
4497
4521
  onClick: onCellClick,
4498
4522
  children: shouldShowTooltip ? /* @__PURE__ */ jsx(Tooltip2, { content: tooltipText, position: "bottom", asChild: true, children: /* @__PURE__ */ jsx("span", { children: cellContent }) }) : cellContent
@@ -4961,7 +4985,7 @@ function Table(props) {
4961
4985
  id: `${col.key}-body`,
4962
4986
  "data-row-cell": "true",
4963
4987
  "data-col-key": col.key,
4964
- className: `${isCheckbox ? "p-0" : "px-2 py-[6.8px]"} whitespace-nowrap text-sm text-gray-900 border-r border-b border-gray-200 last:border-r-0 bg-inherit group-hover:bg-gray-100 transition-all`,
4988
+ className: `${isCheckbox ? "p-0" : "px-2 py-4"} whitespace-nowrap text-sm text-gray-900 border-r border-b border-gray-200 last:border-r-0 bg-inherit group-hover:bg-gray-100 transition-all`,
4965
4989
  style: {
4966
4990
  width,
4967
4991
  minWidth: minWidth || width,
@@ -4978,7 +5002,7 @@ function Table(props) {
4978
5002
  tooltipText: String(record[col.key] ?? ""),
4979
5003
  align: align ?? "",
4980
5004
  tooltipConfig: col.key === "__checkbox__" ? false : tooltipConfig,
4981
- onCellClick: col.key !== "__checkbox__" ? () => onRowClickRef.current?.(record, rowIdx) : void 0
5005
+ onCellClick: col.key !== "__checkbox__" && onRowClickRef.current ? () => onRowClickRef.current?.(record, rowIdx) : void 0
4982
5006
  }
4983
5007
  ) })
4984
5008
  },
@@ -5053,7 +5077,7 @@ function Table(props) {
5053
5077
  const rest = baseRows.filter((row) => !effectiveRowOrder.includes(String(getRowKey(row.original, row.index))));
5054
5078
  return [...ordered, ...rest];
5055
5079
  }, [baseRows, effectiveRowOrder, getRowKey]);
5056
- return /* @__PURE__ */ jsxs("div", { className: "bg-white rounded table-shadow", children: [
5080
+ return /* @__PURE__ */ jsxs("div", { className: "bg-white rounded shadow-panel", children: [
5057
5081
  /* @__PURE__ */ jsx(
5058
5082
  "div",
5059
5083
  {
@@ -5077,7 +5101,7 @@ function Table(props) {
5077
5101
  isColumnDraggable
5078
5102
  }
5079
5103
  ),
5080
- /* @__PURE__ */ jsx("tbody", { className: "w-full h-full", children: showSkeleton ? Array.from({ length: 15 }).map((_, rowIdx) => /* @__PURE__ */ jsxs("tr", { className: "hover:bg-gray-50", children: [
5104
+ /* @__PURE__ */ jsx("tbody", { className: "w-full h-full", children: showSkeleton ? Array.from({ length: 3 }).map((_, rowIdx) => /* @__PURE__ */ jsxs("tr", { className: "hover:bg-gray-50", children: [
5081
5105
  leadingPinnedCols.map((col, idx) => /* @__PURE__ */ jsx(SkeletonTd, { col, showSquare: idx === 0 && !!checkboxInfo }, `leading-${idx}`)),
5082
5106
  leftColspan > 0 && /* @__PURE__ */ jsx("td", { colSpan: leftColspan, style: { padding: 0, border: "none" } }),
5083
5107
  virtualItems.map((vc) => /* @__PURE__ */ jsx(SkeletonTd, { col: groupCols[vc.index] }, `group-${vc.index}`)),
@@ -6791,7 +6815,8 @@ function InputField(props) {
6791
6815
  maxLength,
6792
6816
  className = "",
6793
6817
  type = "input",
6794
- numbersOnly = false
6818
+ numbersOnly = false,
6819
+ autoComplete
6795
6820
  } = config;
6796
6821
  const inputType = type === "email" ? "email" : type === "password" ? "password" : "text";
6797
6822
  if (readOnly) {
@@ -6816,6 +6841,7 @@ function InputField(props) {
6816
6841
  maxLength,
6817
6842
  status: "default",
6818
6843
  className: formControlClass(hasError),
6844
+ autoComplete,
6819
6845
  bare: true,
6820
6846
  onChange: handleChange
6821
6847
  }
@@ -7521,7 +7547,8 @@ function SubmitFormRoot(props) {
7521
7547
  className = "",
7522
7548
  formClassName,
7523
7549
  gridClassName = "grid-cols-12",
7524
- mode = "onSubmit"
7550
+ mode = "onSubmit",
7551
+ autoComplete
7525
7552
  } = props;
7526
7553
  const methods = useForm({
7527
7554
  resolver: zodResolver(schema),
@@ -7544,6 +7571,7 @@ function SubmitFormRoot(props) {
7544
7571
  id: formId,
7545
7572
  onSubmit: handleSubmit,
7546
7573
  className: cn2(SUBMIT_FORM_CLASS, formClassName, className),
7574
+ autoComplete,
7547
7575
  noValidate: true,
7548
7576
  children: /* @__PURE__ */ jsx("div", { className: `grid ${gridClassName} items-stretch gap-0`, children })
7549
7577
  }
@@ -7571,7 +7599,8 @@ function PageFilter(props) {
7571
7599
  colGap = 0,
7572
7600
  submitButtonText = "\uAC80\uC0C9",
7573
7601
  resetButtonText = "\uCD08\uAE30\uD654",
7574
- values
7602
+ values,
7603
+ primaryColor
7575
7604
  } = props;
7576
7605
  const [localValues, setLocalValues] = useState(values);
7577
7606
  const initialValuesRef = useRef(values);
@@ -7610,7 +7639,17 @@ function PageFilter(props) {
7610
7639
  const rowGap2 = index !== 0 ? option.label ? gap : 5 : 0;
7611
7640
  switch (option.type) {
7612
7641
  case "input":
7613
- return /* @__PURE__ */ jsx(LabeledFilterOption, { label: option.label, gap: rowGap2, children: /* @__PURE__ */ jsx(Input2, { placeholder: option.placeholder, value: currentValue, onChange: handleInputChange(optionKey) }) }, String(optionKey));
7642
+ return /* @__PURE__ */ jsx(LabeledFilterOption, { label: option.label, gap: rowGap2, children: /* @__PURE__ */ jsx(
7643
+ Input2,
7644
+ {
7645
+ placeholder: option.placeholder,
7646
+ value: currentValue,
7647
+ onChange: handleInputChange(optionKey),
7648
+ onKeyDown: (e) => {
7649
+ if (e.key === "Enter") handleSubmit();
7650
+ }
7651
+ }
7652
+ ) }, String(optionKey));
7614
7653
  case "select":
7615
7654
  return /* @__PURE__ */ jsx(LabeledFilterOption, { label: option.label, gap: rowGap2, children: /* @__PURE__ */ jsx(
7616
7655
  Select2,
@@ -7619,6 +7658,7 @@ function PageFilter(props) {
7619
7658
  onChange: handleSelectChange(optionKey),
7620
7659
  options: option.options,
7621
7660
  placeholder: "\uC120\uD0DD",
7661
+ canReset: true,
7622
7662
  containerClassName: option.containerClassName ?? "w-30"
7623
7663
  }
7624
7664
  ) }, String(optionKey));
@@ -7671,22 +7711,109 @@ function PageFilter(props) {
7671
7711
  "div",
7672
7712
  {
7673
7713
  className: cn(
7674
- "flex flex-col gap-3 bg-white py-3 px-5 border-t-main border-t-1 shadow-page-filter",
7714
+ "flex flex-col gap-3 bg-white py-3 px-5 border-t-main border-t-1 shadow-panel",
7675
7715
  containerClassName
7676
7716
  ),
7677
- children: /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col", style: { gap: `${colGap}px` }, children: [
7678
- rows.map((row) => /* @__PURE__ */ jsx("div", { className: "flex flex-row min-h-12", children: row.options.map((option, index) => renderFilterOption(option, rowGap, index)) }, row.options.map((opt) => String(opt.key)).join("_"))),
7679
- /* @__PURE__ */ jsxs("div", { className: "absolute right-2 bottom-2 flex justify-end gap-2 pt-2", children: [
7680
- /* @__PURE__ */ jsx(Button, { variant: "search", onClick: handleSubmit, children: submitButtonText }),
7681
- onReset && /* @__PURE__ */ jsx(Button, { variant: "reset", onClick: handleReset, children: resetButtonText })
7682
- ] })
7683
- ] })
7717
+ style: primaryColor ? { borderTopColor: primaryColor } : void 0,
7718
+ children: /* @__PURE__ */ jsx("div", { className: "relative flex flex-col", style: { gap: `${colGap}px` }, children: rows.map((row, ix) => {
7719
+ const isLastRow = rows.length - 1 === ix;
7720
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-row min-h-12", children: [
7721
+ row.options.map((option, index) => renderFilterOption(option, rowGap, index)),
7722
+ isLastRow && /* @__PURE__ */ jsxs("div", { className: "ml-4 flex flex-row items-center gap-2", children: [
7723
+ /* @__PURE__ */ jsx(Button, { variant: "search", onClick: handleSubmit, children: submitButtonText }),
7724
+ onReset && /* @__PURE__ */ jsx(Button, { variant: "reset", onClick: handleReset, children: resetButtonText })
7725
+ ] })
7726
+ ] }, row.options.map((opt) => String(opt.key)).join("_"));
7727
+ }) })
7684
7728
  }
7685
7729
  );
7686
7730
  }
7731
+ var VARIANT_STYLES = {
7732
+ light: {
7733
+ container: "bg-white border-b border-gray-200",
7734
+ activeTab: "bg-gray-50 border-gray-200 text-gray-800 shadow-sm",
7735
+ inactiveTab: "bg-white border-gray-100 text-gray-400 hover:text-gray-600 hover:border-gray-200 hover:bg-gray-50",
7736
+ activeText: "font-semibold text-gray-800",
7737
+ inactiveText: "font-normal",
7738
+ indicator: "bg-blue-500",
7739
+ closeBtn: "rounded hover:bg-gray-300/60",
7740
+ closeBtnWH: "w-3.5 h-3.5",
7741
+ closeBtnSize: 10,
7742
+ plusBtnArea: "border-l border-gray-100 bg-white",
7743
+ plusBtn: "text-gray-400 hover:text-gray-600 hover:bg-gray-100",
7744
+ fadeOpacity: 0.12,
7745
+ tabPy: "py-1.5",
7746
+ tabPx: "px-3",
7747
+ tabTextSize: "text-xs",
7748
+ scrollPadding: "px-3 pt-1.5",
7749
+ rounded: "rounded-t-md"
7750
+ },
7751
+ dark: {
7752
+ container: "bg-gray-900 border-b border-gray-700",
7753
+ activeTab: "bg-gray-800 border-gray-600 text-white shadow-sm",
7754
+ inactiveTab: "bg-gray-900 border-gray-700/50 text-gray-500 hover:text-gray-300 hover:border-gray-600 hover:bg-gray-800",
7755
+ activeText: "font-semibold text-white",
7756
+ inactiveText: "font-normal",
7757
+ indicator: "bg-indigo-400",
7758
+ closeBtn: "rounded hover:bg-gray-600/60",
7759
+ closeBtnWH: "w-3.5 h-3.5",
7760
+ closeBtnSize: 10,
7761
+ plusBtnArea: "border-l border-gray-700 bg-gray-900",
7762
+ plusBtn: "text-gray-500 hover:text-gray-300 hover:bg-gray-700",
7763
+ fadeOpacity: 0.4,
7764
+ tabPy: "py-1.5",
7765
+ tabPx: "px-3",
7766
+ tabTextSize: "text-xs",
7767
+ scrollPadding: "px-3 pt-1.5",
7768
+ rounded: "rounded-t-md"
7769
+ },
7770
+ "system-light": {
7771
+ container: "bg-gray-200 border-b border-gray-300",
7772
+ activeTab: "bg-white border-gray-300 text-slate-800 shadow-sm",
7773
+ inactiveTab: "bg-transparent border-gray-300/80 text-slate-500 hover:text-slate-700 hover:bg-[#efefef] hover:border-gray-300",
7774
+ activeText: "font-semibold text-slate-800",
7775
+ inactiveText: "font-medium",
7776
+ indicator: "bg-[#2b2b2b]",
7777
+ closeBtn: "ml-auto text-slate-400 hover:text-slate-700",
7778
+ closeBtnWH: "w-4 h-4",
7779
+ closeBtnSize: 13,
7780
+ plusBtnArea: "border-l border-gray-300 bg-gray-200",
7781
+ plusBtn: "text-slate-400 hover:text-slate-600 hover:bg-gray-300",
7782
+ fadeOpacity: 0.15,
7783
+ tabPy: "py-2.5",
7784
+ tabPx: "px-5",
7785
+ tabTextSize: "text-sm",
7786
+ scrollPadding: "px-3 pt-2",
7787
+ rounded: "rounded-t-none"
7788
+ },
7789
+ "system-dark": {
7790
+ container: "bg-slate-900 border-b border-slate-700",
7791
+ activeTab: "bg-slate-800 border-slate-600 text-slate-100 shadow-sm",
7792
+ inactiveTab: "bg-transparent border-slate-700/50 text-slate-400 hover:text-slate-200 hover:bg-slate-800/60 hover:border-slate-700",
7793
+ activeText: "font-semibold text-slate-100",
7794
+ inactiveText: "font-medium",
7795
+ indicator: "bg-indigo-400",
7796
+ closeBtn: "ml-auto text-slate-500 hover:text-slate-200",
7797
+ closeBtnWH: "w-4 h-4",
7798
+ closeBtnSize: 13,
7799
+ plusBtnArea: "border-l border-slate-700 bg-slate-900",
7800
+ plusBtn: "text-slate-400 hover:text-slate-200 hover:bg-slate-700",
7801
+ fadeOpacity: 0.45,
7802
+ tabPy: "py-2.5",
7803
+ tabPx: "px-5",
7804
+ tabTextSize: "text-sm",
7805
+ scrollPadding: "px-4 pt-2",
7806
+ rounded: "rounded-t-none"
7807
+ }
7808
+ };
7687
7809
  var PLUS_BTN_WIDTH = 36;
7810
+ function easedFade(dir, opacity) {
7811
+ const c = (t) => `rgba(0,0,0,${(opacity * t).toFixed(3)})`;
7812
+ return `linear-gradient(${dir}, ${c(1)} 0%, ${c(0.72)} 20%, ${c(0.38)} 45%, ${c(0.1)} 70%, transparent 100%)`;
7813
+ }
7688
7814
  function MultiTabBar(props) {
7689
- const { tabs, activeTabId, onTabClick, onTabClose, onTabAdd } = props;
7815
+ const { tabs, activeTabId, onTabClick, onTabClose, onTabAdd, variant = "light", primaryColor } = props;
7816
+ const s = VARIANT_STYLES[variant];
7690
7817
  const scrollRef = useRef(null);
7691
7818
  const tabRefs = useRef(/* @__PURE__ */ new Map());
7692
7819
  const [showLeftFade, setShowLeftFade] = useState(false);
@@ -7739,13 +7866,23 @@ function MultiTabBar(props) {
7739
7866
  const handleStopDrag = () => {
7740
7867
  isDragging.current = false;
7741
7868
  };
7869
+ useEffect(() => {
7870
+ const el = scrollRef.current;
7871
+ if (!el) return;
7872
+ const onWheel = (e) => {
7873
+ e.preventDefault();
7874
+ el.scrollLeft += e.deltaY || e.deltaX;
7875
+ };
7876
+ el.addEventListener("wheel", onWheel, { passive: false });
7877
+ return () => el.removeEventListener("wheel", onWheel);
7878
+ }, []);
7742
7879
  if (tabs.length === 0) return null;
7743
- return /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 w-full overflow-hidden bg-white border-b border-gray-200", children: /* @__PURE__ */ jsxs("div", { className: "relative flex items-stretch", children: [
7880
+ return /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 w-full overflow-hidden ${s.container}`, children: /* @__PURE__ */ jsxs("div", { className: "relative flex items-stretch", children: [
7744
7881
  showLeftFade && /* @__PURE__ */ jsx(
7745
7882
  "div",
7746
7883
  {
7747
7884
  className: "absolute left-0 top-0 bottom-0 w-10 pointer-events-none z-10",
7748
- style: { background: "linear-gradient(to right, white 30%, transparent)" }
7885
+ style: { background: easedFade("to right", s.fadeOpacity) }
7749
7886
  }
7750
7887
  ),
7751
7888
  showRightFade && /* @__PURE__ */ jsx(
@@ -7754,7 +7891,7 @@ function MultiTabBar(props) {
7754
7891
  className: "absolute top-0 bottom-0 w-10 pointer-events-none z-10",
7755
7892
  style: {
7756
7893
  right: PLUS_BTN_WIDTH,
7757
- background: "linear-gradient(to left, white 30%, transparent)"
7894
+ background: easedFade("to left", s.fadeOpacity)
7758
7895
  }
7759
7896
  }
7760
7897
  ),
@@ -7762,7 +7899,7 @@ function MultiTabBar(props) {
7762
7899
  "div",
7763
7900
  {
7764
7901
  ref: scrollRef,
7765
- className: "flex-1 min-w-0 flex items-end gap-0.5 px-3 pt-1.5 overflow-x-auto [&::-webkit-scrollbar]:hidden",
7902
+ className: `flex-1 min-w-0 flex items-end gap-0.5 ${s.scrollPadding} overflow-x-auto [&::-webkit-scrollbar]:hidden`,
7766
7903
  style: { scrollbarWidth: "none" },
7767
7904
  onScroll: updateFades,
7768
7905
  onMouseDown: handleMouseDown,
@@ -7783,17 +7920,23 @@ function MultiTabBar(props) {
7783
7920
  if (!isActive) onTabClick(tab.id);
7784
7921
  },
7785
7922
  className: `
7786
- group relative flex items-center gap-1.5 px-3 py-1.5 flex-shrink-0
7787
- rounded-t-md border border-b-0 cursor-pointer select-none
7923
+ group relative flex items-center gap-1.5 ${s.tabPx} ${s.tabPy} flex-shrink-0
7924
+ ${s.rounded} border border-b-0 cursor-pointer select-none
7788
7925
  transition-colors duration-100
7789
- ${isActive ? "bg-gray-50 border-gray-200 text-gray-800 shadow-sm" : "bg-white border-gray-100 text-gray-400 hover:text-gray-600 hover:border-gray-200 hover:bg-gray-50"}
7926
+ ${isActive ? s.activeTab : s.inactiveTab}
7790
7927
  `,
7791
7928
  children: [
7792
- isActive && /* @__PURE__ */ jsx("div", { className: "absolute top-0 left-0 right-0 h-0.5 rounded-t-md bg-blue-500" }),
7929
+ isActive && /* @__PURE__ */ jsx(
7930
+ "div",
7931
+ {
7932
+ className: `absolute top-0 left-0 right-0 h-0.5 ${s.rounded} ${s.indicator}`,
7933
+ style: primaryColor ? { backgroundColor: primaryColor } : void 0
7934
+ }
7935
+ ),
7793
7936
  /* @__PURE__ */ jsx(
7794
7937
  "span",
7795
7938
  {
7796
- className: `text-xs max-w-35 truncate leading-none ${isActive ? "font-semibold text-gray-800" : "font-normal"}`,
7939
+ className: `${s.tabTextSize} max-w-35 truncate leading-none ${isActive ? s.activeText : s.inactiveText}`,
7797
7940
  children: tab.label
7798
7941
  }
7799
7942
  ),
@@ -7805,11 +7948,12 @@ function MultiTabBar(props) {
7805
7948
  onTabClose(tab.id);
7806
7949
  },
7807
7950
  className: `
7808
- flex-shrink-0 w-3.5 h-3.5 flex items-center justify-center
7809
- rounded hover:bg-gray-300/60 transition-all duration-100 cursor-pointer
7951
+ flex-shrink-0 ${s.closeBtnWH} flex items-center justify-center
7952
+ transition-all duration-100 cursor-pointer
7953
+ ${s.closeBtn}
7810
7954
  ${isActive ? "opacity-100" : "opacity-40 group-hover:opacity-60"}
7811
7955
  `,
7812
- children: /* @__PURE__ */ jsx(X, { size: 10, strokeWidth: 2.5 })
7956
+ children: /* @__PURE__ */ jsx(X, { size: s.closeBtnSize, strokeWidth: 2.5 })
7813
7957
  }
7814
7958
  )
7815
7959
  ]
@@ -7822,14 +7966,14 @@ function MultiTabBar(props) {
7822
7966
  onTabAdd && /* @__PURE__ */ jsx(
7823
7967
  "div",
7824
7968
  {
7825
- className: "flex-shrink-0 flex items-center justify-center border-l border-gray-100 bg-white",
7969
+ className: `flex-shrink-0 flex items-center justify-center ${s.plusBtnArea}`,
7826
7970
  style: { width: PLUS_BTN_WIDTH },
7827
7971
  children: /* @__PURE__ */ jsx(
7828
7972
  "button",
7829
7973
  {
7830
7974
  onClick: onTabAdd,
7831
7975
  title: "\uD604\uC7AC \uD398\uC774\uC9C0\uB97C \uC0C8 \uD0ED\uC73C\uB85C \uC5F4\uAE30",
7832
- className: "w-6 h-6 flex items-center justify-center rounded text-gray-400 cursor-pointer hover:text-gray-600 hover:bg-gray-100 transition-colors",
7976
+ className: `w-6 h-6 flex items-center justify-center rounded cursor-pointer transition-colors ${s.plusBtn}`,
7833
7977
  children: /* @__PURE__ */ jsx(Plus, { size: 13, strokeWidth: 2 })
7834
7978
  }
7835
7979
  )
@@ -8614,19 +8758,226 @@ function FileUploader(props) {
8614
8758
  /* @__PURE__ */ jsx(FilePreviewViewer, { ...viewer.viewerProps, fileTypes, fileNames: files.map((f) => f.name) })
8615
8759
  ] });
8616
8760
  }
8761
+ var VARIANT_STYLES2 = {
8762
+ light: {
8763
+ aside: "bg-white border-r border-gray-200",
8764
+ sectionTitle: "text-xs font-semibold text-gray-500 tracking-wider mb-3",
8765
+ itemActive: "bg-blue-50 text-blue-600",
8766
+ itemInactive: "text-gray-700 hover:bg-gray-100",
8767
+ subItemActive: "text-blue-600 font-medium",
8768
+ subItemInactive: "text-gray-600 hover:bg-gray-50 hover:text-gray-900",
8769
+ childGroupBorder: "border-gray-100",
8770
+ childActive: "bg-blue-50 text-blue-600 font-medium",
8771
+ childInactive: "text-gray-600 hover:bg-gray-50 hover:text-gray-900",
8772
+ grandchildActive: "bg-blue-50 text-blue-600 font-medium",
8773
+ grandchildInactive: "text-gray-500 hover:bg-gray-50 hover:text-gray-900",
8774
+ collapseBtn: "bg-gray-50 hover:bg-gray-100",
8775
+ collapseIcon: "var(--color-sub-darkgray)",
8776
+ rounded: "rounded-lg",
8777
+ itemPy: "py-2",
8778
+ childPy: "py-1.5",
8779
+ grandchildPy: "py-1",
8780
+ itemFont: "font-semibold",
8781
+ itemTextSize: "text-sm",
8782
+ grandchildTextSize: "text-xs",
8783
+ iconClass: "w-4 h-4 flex-shrink-0",
8784
+ activeItemStyle: {},
8785
+ activeChildStyle: {},
8786
+ activeGrandchildStyle: {},
8787
+ footerBorder: "border-t border-gray-200"
8788
+ },
8789
+ dark: {
8790
+ aside: "bg-gray-900 border-r border-gray-700",
8791
+ sectionTitle: "text-xs font-semibold text-gray-400 tracking-wider mb-3",
8792
+ itemActive: "bg-gray-700 text-white",
8793
+ itemInactive: "text-gray-300 hover:bg-gray-800",
8794
+ subItemActive: "text-blue-400 font-medium",
8795
+ subItemInactive: "text-gray-400 hover:bg-gray-800 hover:text-gray-100",
8796
+ childGroupBorder: "border-gray-700",
8797
+ childActive: "bg-gray-700 text-white font-medium",
8798
+ childInactive: "text-gray-400 hover:bg-gray-800 hover:text-gray-100",
8799
+ grandchildActive: "bg-gray-700 text-blue-400 font-medium",
8800
+ grandchildInactive: "text-gray-500 hover:bg-gray-800 hover:text-gray-100",
8801
+ collapseBtn: "bg-gray-800 hover:bg-gray-700",
8802
+ collapseIcon: "#9ca3af",
8803
+ rounded: "rounded-lg",
8804
+ itemPy: "py-2",
8805
+ childPy: "py-1.5",
8806
+ grandchildPy: "py-1",
8807
+ itemFont: "font-semibold",
8808
+ itemTextSize: "text-sm",
8809
+ grandchildTextSize: "text-xs",
8810
+ iconClass: "w-4 h-4 flex-shrink-0",
8811
+ activeItemStyle: {},
8812
+ activeChildStyle: {},
8813
+ activeGrandchildStyle: {},
8814
+ footerBorder: "border-t border-gray-700"
8815
+ },
8816
+ "system-dark": {
8817
+ aside: "bg-slate-900 border-r border-slate-700",
8818
+ sectionTitle: "text-[10px] font-bold text-slate-500 uppercase tracking-[0.12em] mb-2 pb-2 border-b border-slate-700/70",
8819
+ itemActive: "bg-slate-800 text-white",
8820
+ itemInactive: "text-slate-300 hover:bg-slate-800/60 hover:text-white",
8821
+ subItemActive: "text-slate-100 font-medium",
8822
+ subItemInactive: "text-slate-400 hover:bg-slate-800/50 hover:text-slate-200",
8823
+ childGroupBorder: "border-slate-700/60",
8824
+ childActive: "bg-slate-800/70 text-slate-100 font-medium",
8825
+ childInactive: "text-slate-400 hover:bg-slate-800/50 hover:text-slate-200",
8826
+ grandchildActive: "text-slate-100 font-medium",
8827
+ grandchildInactive: "text-slate-500 hover:bg-slate-800/50 hover:text-slate-200",
8828
+ collapseBtn: "bg-slate-800 hover:bg-slate-700",
8829
+ collapseIcon: "#94a3b8",
8830
+ rounded: "rounded-none",
8831
+ itemPy: "py-3",
8832
+ childPy: "py-[10px]",
8833
+ grandchildPy: "py-2",
8834
+ itemFont: "font-medium",
8835
+ itemTextSize: "text-sm",
8836
+ grandchildTextSize: "text-xs",
8837
+ iconClass: "w-4.5 h-4.5 flex-shrink-0",
8838
+ activeItemStyle: { borderLeft: "3px solid #818cf8", paddingLeft: "9px" },
8839
+ activeChildStyle: { borderLeft: "2px solid #818cf8", paddingLeft: "14px" },
8840
+ activeGrandchildStyle: { borderLeft: "2px solid #818cf8", paddingLeft: "10px" },
8841
+ footerBorder: "border-t border-slate-700"
8842
+ },
8843
+ "system-light": {
8844
+ aside: "bg-gray-50 border-r border-gray-200",
8845
+ sectionTitle: "text-[10px] font-bold text-slate-400 uppercase tracking-[0.12em] mb-2 pb-2 border-b border-gray-200",
8846
+ itemActive: "font-medium",
8847
+ itemInactive: "text-slate-700 hover:bg-gray-100",
8848
+ subItemActive: "text-[#2b2b2b] font-medium",
8849
+ subItemInactive: "text-slate-500 hover:bg-gray-100 hover:text-slate-800",
8850
+ childGroupBorder: "border-gray-200",
8851
+ childActive: "font-medium",
8852
+ childInactive: "text-slate-500 hover:bg-gray-100 hover:text-slate-800",
8853
+ grandchildActive: "text-[#2b2b2b] font-medium",
8854
+ grandchildInactive: "text-slate-500 hover:bg-gray-100 hover:text-slate-800",
8855
+ collapseBtn: "bg-gray-100 hover:bg-gray-200",
8856
+ collapseIcon: "#64748b",
8857
+ rounded: "rounded-none",
8858
+ itemPy: "py-3",
8859
+ childPy: "py-[10px]",
8860
+ grandchildPy: "py-2",
8861
+ itemFont: "font-medium",
8862
+ itemTextSize: "text-[15px]",
8863
+ grandchildTextSize: "text-sm",
8864
+ iconClass: "w-4.5 h-4.5 flex-shrink-0",
8865
+ activeItemStyle: {
8866
+ color: "#2b2b2b",
8867
+ backgroundColor: "color-mix(in srgb, #2b2b2b 10%, transparent)",
8868
+ borderLeft: "3px solid #2b2b2b",
8869
+ paddingLeft: "9px"
8870
+ },
8871
+ activeChildStyle: {
8872
+ color: "#2b2b2b",
8873
+ backgroundColor: "color-mix(in srgb, #2b2b2b 10%, transparent)",
8874
+ borderLeft: "2px solid #2b2b2b",
8875
+ paddingLeft: "14px"
8876
+ },
8877
+ activeGrandchildStyle: {
8878
+ color: "#2b2b2b",
8879
+ backgroundColor: "color-mix(in srgb, #2b2b2b 10%, transparent)",
8880
+ borderLeft: "2px solid #2b2b2b",
8881
+ paddingLeft: "10px"
8882
+ },
8883
+ footerBorder: "border-t border-gray-200"
8884
+ }
8885
+ };
8886
+ function tintedStyle(color) {
8887
+ return {
8888
+ color,
8889
+ backgroundColor: `color-mix(in srgb, ${color} 12%, transparent)`
8890
+ };
8891
+ }
8892
+ function textStyle(color) {
8893
+ return { color };
8894
+ }
8895
+ function solidStyle(color) {
8896
+ return {
8897
+ backgroundColor: `color-mix(in srgb, ${color} 25%, transparent)`,
8898
+ color: "#ffffff",
8899
+ boxShadow: `inset 3px 0 0 ${color}`
8900
+ };
8901
+ }
8902
+ var ACCENT_APPLIERS = {
8903
+ light: {
8904
+ itemActive: tintedStyle,
8905
+ subItemActive: textStyle,
8906
+ childActive: tintedStyle,
8907
+ grandchildActive: textStyle
8908
+ },
8909
+ dark: {
8910
+ itemActive: textStyle,
8911
+ subItemActive: textStyle,
8912
+ childActive: textStyle,
8913
+ grandchildActive: textStyle
8914
+ },
8915
+ "system-dark": {
8916
+ itemActive: (c) => ({
8917
+ ...solidStyle(c),
8918
+ boxShadow: void 0,
8919
+ borderLeft: `3px solid ${c}`,
8920
+ paddingLeft: "9px"
8921
+ }),
8922
+ subItemActive: textStyle,
8923
+ childActive: (c) => ({
8924
+ ...solidStyle(c),
8925
+ boxShadow: void 0,
8926
+ borderLeft: `2px solid ${c}`,
8927
+ paddingLeft: "14px"
8928
+ }),
8929
+ grandchildActive: (c) => ({
8930
+ ...textStyle(c),
8931
+ borderLeft: `2px solid ${c}`,
8932
+ paddingLeft: "10px"
8933
+ })
8934
+ },
8935
+ "system-light": {
8936
+ itemActive: (c) => ({
8937
+ ...tintedStyle(c),
8938
+ borderLeft: `3px solid ${c}`,
8939
+ paddingLeft: "9px"
8940
+ }),
8941
+ subItemActive: textStyle,
8942
+ childActive: (c) => ({
8943
+ ...tintedStyle(c),
8944
+ borderLeft: `2px solid ${c}`,
8945
+ paddingLeft: "14px"
8946
+ }),
8947
+ grandchildActive: (c) => ({
8948
+ ...tintedStyle(c),
8949
+ borderLeft: `2px solid ${c}`,
8950
+ paddingLeft: "10px"
8951
+ })
8952
+ }
8953
+ };
8617
8954
  function Sidebar(props) {
8618
8955
  const navigate = useNavigate();
8619
- const { isOpen: isOpen2, onClose, menuSections, header, className, showCollapseButton = false } = props;
8956
+ const {
8957
+ onClose,
8958
+ menuSections,
8959
+ header,
8960
+ footer,
8961
+ className,
8962
+ showCollapseButton = false,
8963
+ variant = "light",
8964
+ primaryColor
8965
+ } = props;
8620
8966
  const { pathname } = useLocation();
8621
8967
  const [isCollapsed, setIsCollapsed] = useState(false);
8622
- const [isContentVisible, setIsContentVisible] = useState(true);
8968
+ const [overflowVisible, setOverflowVisible] = useState(true);
8623
8969
  const [expandedItems, setExpandedItems] = useState(/* @__PURE__ */ new Set());
8624
8970
  const [expandedSubItems, setExpandedSubItems] = useState(/* @__PURE__ */ new Set());
8625
8971
  useEffect(() => {
8626
- if (isCollapsed) return;
8627
- const timer = setTimeout(() => setIsContentVisible(true), 300);
8972
+ if (isCollapsed) {
8973
+ setOverflowVisible(false);
8974
+ return;
8975
+ }
8976
+ const timer = setTimeout(() => setOverflowVisible(true), 300);
8628
8977
  return () => clearTimeout(timer);
8629
8978
  }, [isCollapsed]);
8979
+ const s = VARIANT_STYLES2[variant];
8980
+ const applier = ACCENT_APPLIERS[variant];
8630
8981
  useEffect(() => {
8631
8982
  menuSections.forEach((section) => {
8632
8983
  section.items.forEach((item) => {
@@ -8677,167 +9028,186 @@ function Sidebar(props) {
8677
9028
  window.open(path, "_blank", "noopener,noreferrer");
8678
9029
  } else if (path !== "") {
8679
9030
  navigate(path);
8680
- onClose();
9031
+ onClose?.();
8681
9032
  }
8682
9033
  };
8683
- return /* @__PURE__ */ jsxs(Fragment, { children: [
8684
- isOpen2 && /* @__PURE__ */ jsx("div", { className: "fixed inset-0 bg-black/10 bg-opacity-50 z-40 lg:hidden", onClick: onClose }),
8685
- /* @__PURE__ */ jsxs(
8686
- "aside",
8687
- {
8688
- className: `
8689
- ${isCollapsed ? "w-11 min-w-11" : "min-w-60 w-62"}
8690
- ${isOpen2 ? "translate-x-0" : "-translate-x-full lg:translate-x-0"}
8691
- hide-scrollbar fixed lg:relative top-0 left-0 h-screen bg-white border-r border-gray-200 z-50 shrink-0 overflow-y-auto
8692
- transition-transform duration-300 ease-in-out
8693
- ${className ?? ""}
8694
- `,
8695
- children: [
8696
- showCollapseButton && /* @__PURE__ */ jsx(
8697
- "button",
8698
- {
8699
- onClick: () => {
8700
- if (!isCollapsed) setIsContentVisible(false);
8701
- setIsCollapsed((prev) => !prev);
8702
- },
8703
- className: "absolute top-4 right-2 z-20 w-6.5 h-6.5 bg-gray-50 rounded-full flex items-center justify-center hover:bg-gray-50 transition-colors cursor-pointer hover:bg-gray-100",
8704
- children: isCollapsed ? /* @__PURE__ */ jsx(PanelRightClose, { size: 18, color: "var(--color-sub-darkgray)" }) : /* @__PURE__ */ jsx(PanelLeftClose, { size: 18, color: "var(--color-sub-darkgray)" })
8705
- }
8706
- ),
8707
- isContentVisible && /* @__PURE__ */ jsxs("div", { className: "py-6 pl-6 pr-4", children: [
8708
- /* @__PURE__ */ jsx(
8709
- "button",
8710
- {
8711
- onClick: onClose,
8712
- className: "lg:hidden absolute top-4 right-4 p-2 hover:bg-gray-100 rounded-lg transition-colors text-2xl leading-none",
8713
- "aria-label": "Close menu",
8714
- children: "x"
8715
- }
8716
- ),
8717
- header && /* @__PURE__ */ jsx("div", { className: "mb-10 mt-2", children: header }),
8718
- /* @__PURE__ */ jsx("nav", { className: "space-y-6", children: menuSections.map((section, sectionIndex) => /* @__PURE__ */ jsxs("div", { children: [
8719
- section.title && /* @__PURE__ */ jsx("div", { className: "text-xs font-semibold text-gray-500 tracking-wider mb-3", children: section.title }),
8720
- /* @__PURE__ */ jsx("div", { className: "space-y-1", children: section.items.map((item) => /* @__PURE__ */ jsxs("div", { children: [
8721
- /* @__PURE__ */ jsxs(
8722
- "button",
8723
- {
8724
- onClick: () => {
8725
- if (item.children) {
8726
- toggleExpand(item.label);
8727
- } else if (item.path) {
8728
- handleItemClick(item.path);
8729
- }
8730
- },
8731
- className: `
8732
- w-full text-left flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium transition-colors
8733
- ${!item.children && pathname === item.path ? "bg-blue-50 text-blue-600" : "text-gray-700 hover:bg-gray-100"}
8734
- cursor-pointer
8735
- `,
8736
- children: [
8737
- /* @__PURE__ */ jsx(item.icon, { className: "w-4 h-4 flex-shrink-0" }),
8738
- /* @__PURE__ */ jsx("span", { className: "flex-1", children: item.label }),
8739
- item.children && /* @__PURE__ */ jsx(
8740
- "svg",
8741
- {
8742
- className: `w-4 h-4 transition-transform ${expandedItems.has(item.label) ? "rotate-90" : ""}`,
8743
- fill: "none",
8744
- stroke: "currentColor",
8745
- viewBox: "0 0 24 24",
8746
- children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" })
8747
- }
8748
- ),
8749
- item.path?.includes("https") && /* @__PURE__ */ jsx(
8750
- "svg",
8751
- {
8752
- className: "w-4 h-4 flex-shrink-0 text-gray-400",
8753
- fill: "none",
8754
- stroke: "currentColor",
8755
- viewBox: "0 0 24 24",
8756
- children: /* @__PURE__ */ jsx(
8757
- "path",
9034
+ return /* @__PURE__ */ jsxs(
9035
+ "aside",
9036
+ {
9037
+ className: `
9038
+ ${isCollapsed ? "w-11 min-w-11" : "min-w-60 w-62"}
9039
+ transition-[width,min-width] duration-300 ease-in-out
9040
+ relative h-screen shrink-0 overflow-x-hidden flex flex-col
9041
+ ${s.aside}
9042
+ ${className ?? ""}
9043
+ `,
9044
+ children: [
9045
+ showCollapseButton && /* @__PURE__ */ jsx(
9046
+ "button",
9047
+ {
9048
+ onClick: () => setIsCollapsed((prev) => !prev),
9049
+ className: `absolute top-4 right-2 z-20 w-6.5 h-6.5 rounded-full flex items-center justify-center transition-colors cursor-pointer ${s.collapseBtn}`,
9050
+ children: isCollapsed ? /* @__PURE__ */ jsx(PanelRightClose, { size: 18, color: primaryColor ?? s.collapseIcon }) : /* @__PURE__ */ jsx(PanelLeftClose, { size: 18, color: primaryColor ?? s.collapseIcon })
9051
+ }
9052
+ ),
9053
+ /* @__PURE__ */ jsx("div", { className: `flex-1 min-h-0 hide-scrollbar ${overflowVisible ? "overflow-y-auto" : "overflow-hidden"}`, children: /* @__PURE__ */ jsxs(
9054
+ "div",
9055
+ {
9056
+ className: `transition-opacity duration-200 ease-in-out ${isCollapsed ? "opacity-0 pointer-events-none select-none" : "opacity-100"} ${variant === "system-dark" || variant === "system-light" ? "pb-6" : "px-4 pb-6"}`,
9057
+ style: { transitionDelay: isCollapsed ? "0ms" : "150ms" },
9058
+ children: [
9059
+ header && header,
9060
+ /* @__PURE__ */ jsx("nav", { className: `space-y-6 ${variant === "system-dark" || variant === "system-light" ? "px-1" : ""}`, children: menuSections.map((section, sectionIndex) => /* @__PURE__ */ jsxs("div", { children: [
9061
+ section.title && /* @__PURE__ */ jsx("div", { className: s.sectionTitle, children: section.title }),
9062
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: section.items.map((item) => {
9063
+ const isActive = !item.children && pathname === item.path;
9064
+ return /* @__PURE__ */ jsxs("div", { children: [
9065
+ /* @__PURE__ */ jsxs(
9066
+ "button",
9067
+ {
9068
+ onClick: () => {
9069
+ if (item.children) {
9070
+ toggleExpand(item.label);
9071
+ } else if (item.path) {
9072
+ handleItemClick(item.path);
9073
+ }
9074
+ },
9075
+ className: `
9076
+ w-full text-left flex items-center gap-2 px-3 ${s.itemPy} ${s.rounded} ${s.itemTextSize} ${s.itemFont} transition-colors cursor-pointer
9077
+ ${isActive ? s.itemActive : s.itemInactive}
9078
+ `,
9079
+ style: {
9080
+ ...isActive ? s.activeItemStyle : {},
9081
+ ...isActive && primaryColor ? applier.itemActive(primaryColor) : {}
9082
+ },
9083
+ children: [
9084
+ /* @__PURE__ */ jsx(item.icon, { className: s.iconClass }),
9085
+ /* @__PURE__ */ jsx("span", { className: "flex-1", children: item.label }),
9086
+ item.children && /* @__PURE__ */ jsx(
9087
+ "svg",
9088
+ {
9089
+ className: `w-4 h-4 transition-transform ${expandedItems.has(item.label) ? "rotate-90" : ""}`,
9090
+ fill: "none",
9091
+ stroke: "currentColor",
9092
+ viewBox: "0 0 24 24",
9093
+ children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" })
9094
+ }
9095
+ ),
9096
+ item.path?.includes("https") && /* @__PURE__ */ jsx(
9097
+ "svg",
8758
9098
  {
8759
- strokeLinecap: "round",
8760
- strokeLinejoin: "round",
8761
- strokeWidth: 2,
8762
- d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
9099
+ className: "w-4 h-4 flex-shrink-0 opacity-50",
9100
+ fill: "none",
9101
+ stroke: "currentColor",
9102
+ viewBox: "0 0 24 24",
9103
+ children: /* @__PURE__ */ jsx(
9104
+ "path",
9105
+ {
9106
+ strokeLinecap: "round",
9107
+ strokeLinejoin: "round",
9108
+ strokeWidth: 2,
9109
+ d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
9110
+ }
9111
+ )
8763
9112
  }
8764
9113
  )
8765
- }
8766
- )
8767
- ]
8768
- }
8769
- ),
8770
- item.children && expandedItems.has(item.label) && /* @__PURE__ */ jsx("div", { className: "ml-[25px] mt-1 space-y-1", children: item.children.map((child, childIndex) => {
8771
- if (child.children && child.children.length > 0) {
8772
- const subKey = `${item.label}::${child.label}`;
8773
- const isSubExpanded = expandedSubItems.has(subKey);
8774
- const isSubActive = child.children.some((gc) => gc.path === pathname);
8775
- return /* @__PURE__ */ jsxs("div", { children: [
8776
- /* @__PURE__ */ jsxs(
8777
- "button",
8778
- {
8779
- onClick: () => toggleSubExpand(subKey),
8780
- className: `
8781
- w-full text-left flex items-center justify-between px-3 py-1.5 rounded-lg text-sm transition-colors cursor-pointer
8782
- ${isSubActive ? "text-blue-600 font-medium" : "text-gray-600 hover:bg-gray-50 hover:text-gray-900"}
8783
- `,
8784
- children: [
8785
- /* @__PURE__ */ jsx("span", { children: child.label }),
8786
- /* @__PURE__ */ jsx(
8787
- "svg",
8788
- {
8789
- className: `w-3 h-3 transition-transform ${isSubExpanded ? "rotate-90" : ""}`,
8790
- fill: "none",
8791
- stroke: "currentColor",
8792
- viewBox: "0 0 24 24",
8793
- children: /* @__PURE__ */ jsx(
8794
- "path",
9114
+ ]
9115
+ }
9116
+ ),
9117
+ item.children && expandedItems.has(item.label) && /* @__PURE__ */ jsx("div", { className: `ml-5 mt-0.5 space-y-0.5 border-l ${s.childGroupBorder}`, children: item.children.map((child, childIndex) => {
9118
+ if (child.children && child.children.length > 0) {
9119
+ const subKey = `${item.label}::${child.label}`;
9120
+ const isSubExpanded = expandedSubItems.has(subKey);
9121
+ const isSubActive = child.children.some((gc) => gc.path === pathname);
9122
+ return /* @__PURE__ */ jsxs("div", { children: [
9123
+ /* @__PURE__ */ jsxs(
9124
+ "button",
9125
+ {
9126
+ onClick: () => toggleSubExpand(subKey),
9127
+ className: `
9128
+ w-full text-left flex items-center justify-between pl-4 pr-3 ${s.childPy} ${s.rounded} ${s.itemTextSize} transition-colors cursor-pointer
9129
+ ${isSubActive ? s.subItemActive : s.subItemInactive}
9130
+ `,
9131
+ style: isSubActive && primaryColor ? applier.subItemActive(primaryColor) : void 0,
9132
+ children: [
9133
+ /* @__PURE__ */ jsx("span", { children: child.label }),
9134
+ /* @__PURE__ */ jsx(
9135
+ "svg",
8795
9136
  {
8796
- strokeLinecap: "round",
8797
- strokeLinejoin: "round",
8798
- strokeWidth: 2,
8799
- d: "M9 5l7 7-7 7"
9137
+ className: `w-3 h-3 transition-transform ${isSubExpanded ? "rotate-90" : ""}`,
9138
+ fill: "none",
9139
+ stroke: "currentColor",
9140
+ viewBox: "0 0 24 24",
9141
+ children: /* @__PURE__ */ jsx(
9142
+ "path",
9143
+ {
9144
+ strokeLinecap: "round",
9145
+ strokeLinejoin: "round",
9146
+ strokeWidth: 2,
9147
+ d: "M9 5l7 7-7 7"
9148
+ }
9149
+ )
8800
9150
  }
8801
9151
  )
8802
- }
8803
- )
8804
- ]
8805
- }
8806
- ),
8807
- isSubExpanded && /* @__PURE__ */ jsx("div", { className: "ml-3 mt-0.5 space-y-0.5 border-l border-gray-200 pl-2", children: child.children.map((grandchild) => /* @__PURE__ */ jsx(
9152
+ ]
9153
+ }
9154
+ ),
9155
+ isSubExpanded && /* @__PURE__ */ jsx("div", { className: "ml-3 mt-0.5 space-y-0.5 pl-2", children: child.children.map((grandchild) => {
9156
+ const isGrandchildActive = pathname === grandchild.path;
9157
+ return /* @__PURE__ */ jsx(
9158
+ "button",
9159
+ {
9160
+ onClick: () => handleItemClick(grandchild.path),
9161
+ className: `
9162
+ w-full text-left px-3 ${s.grandchildPy} ${s.rounded} ${s.grandchildTextSize} transition-colors cursor-pointer
9163
+ ${isGrandchildActive ? s.grandchildActive : s.grandchildInactive}
9164
+ `,
9165
+ style: {
9166
+ ...isGrandchildActive ? s.activeGrandchildStyle : {},
9167
+ ...isGrandchildActive && primaryColor ? applier.grandchildActive(primaryColor) : {}
9168
+ },
9169
+ children: grandchild.label
9170
+ },
9171
+ grandchild.path
9172
+ );
9173
+ }) })
9174
+ ] }, child.label);
9175
+ }
9176
+ const isChildActive = pathname === child.path;
9177
+ return /* @__PURE__ */ jsx(
8808
9178
  "button",
8809
9179
  {
8810
- onClick: () => handleItemClick(grandchild.path),
9180
+ onClick: () => handleItemClick(child.path ?? ""),
8811
9181
  className: `
8812
- w-full text-left px-3 py-1 rounded-lg text-sm transition-colors cursor-pointer
8813
- ${pathname === grandchild.path ? "text-blue-600 font-medium" : "text-gray-500 hover:bg-gray-50 hover:text-gray-900"}
8814
- `,
8815
- children: grandchild.label
9182
+ w-full text-left pl-4 pr-3 ${s.childPy} ${s.rounded} ${s.itemTextSize} transition-colors cursor-pointer
9183
+ ${isChildActive ? s.childActive : s.childInactive}
9184
+ `,
9185
+ style: {
9186
+ ...isChildActive ? s.activeChildStyle : {},
9187
+ ...isChildActive && primaryColor ? applier.childActive(primaryColor) : {}
9188
+ },
9189
+ children: child.label
8816
9190
  },
8817
- grandchild.path
8818
- )) })
8819
- ] }, child.label);
8820
- }
8821
- return /* @__PURE__ */ jsx(
8822
- "button",
8823
- {
8824
- onClick: () => handleItemClick(child.path ?? ""),
8825
- className: `
8826
- w-full text-left px-3 py-1.5 rounded-lg text-sm transition-colors cursor-pointer
8827
- ${pathname === child.path ? "bg-blue-50 text-blue-600 font-medium" : "text-gray-600 hover:bg-gray-50 hover:text-gray-900"}
8828
- `,
8829
- children: child.label
8830
- },
8831
- childIndex
8832
- );
9191
+ childIndex
9192
+ );
9193
+ }) })
9194
+ ] }, item.label);
8833
9195
  }) })
8834
- ] }, item.label)) })
8835
- ] }, section.title ?? sectionIndex)) })
8836
- ] })
8837
- ]
8838
- }
8839
- )
8840
- ] });
9196
+ ] }, section.title ?? sectionIndex)) })
9197
+ ]
9198
+ }
9199
+ ) }),
9200
+ footer && /* @__PURE__ */ jsx(
9201
+ "div",
9202
+ {
9203
+ className: `flex-shrink-0 transition-opacity duration-200 ease-in-out ${isCollapsed ? "opacity-0 pointer-events-none select-none" : "opacity-100"} ${s.footerBorder}`,
9204
+ style: { transitionDelay: isCollapsed ? "0ms" : "150ms" },
9205
+ children: footer
9206
+ }
9207
+ )
9208
+ ]
9209
+ }
9210
+ );
8841
9211
  }
8842
9212
  function useDetailController(params = {}) {
8843
9213
  const { mode: controlledMode, onModeChange } = params;
@@ -9134,10 +9504,7 @@ function DetailModalFrame(props) {
9134
9504
  const isEditMode = controller.mode === "edit";
9135
9505
  const canEdit = Boolean(editSchema && (editFields || renderEditBody));
9136
9506
  return /* @__PURE__ */ jsxs(Modal, { isOpen: open, onClose: handleClose, contentClassName: cn("max-w-2xl", contentClassName), children: [
9137
- /* @__PURE__ */ jsxs(ModalHeader, { className: "flex flex-row items-center justify-between", children: [
9138
- /* @__PURE__ */ jsx("span", { className: "text-base font-semibold text-gray-900", children: title }),
9139
- !isEditMode && canEdit && /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: handleEdit, children: "\uC218\uC815" })
9140
- ] }),
9507
+ /* @__PURE__ */ jsx(ModalHeader, { className: "flex flex-row items-center justify-between", children: /* @__PURE__ */ jsx("span", { className: "text-base font-semibold text-gray-900", children: title }) }),
9141
9508
  /* @__PURE__ */ jsxs(ModalBody, { className: "flex-1 min-h-0 overflow-hidden p-0 flex flex-col", children: [
9142
9509
  /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-y-auto", children: /* @__PURE__ */ jsx(
9143
9510
  DetailContent,
@@ -9155,10 +9522,11 @@ function DetailModalFrame(props) {
9155
9522
  ) }),
9156
9523
  renderExtraContent?.({ isEditMode })
9157
9524
  ] }),
9158
- /* @__PURE__ */ jsx(ModalFooter, { className: "flex justify-end gap-2", children: isEditMode ? /* @__PURE__ */ jsxs(Fragment, { children: [
9525
+ /* @__PURE__ */ jsx(ModalFooter, { className: "flex justify-end", children: isEditMode ? /* @__PURE__ */ jsxs(Fragment, { children: [
9159
9526
  /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleCancelEdit, disabled: controller.isSaving, children: "\uCDE8\uC18C" }),
9160
- /* @__PURE__ */ jsx(Button, { type: "submit", form: controller.formId, variant: "save", disabled: controller.isSaving, children: controller.isSaving ? "\uC800\uC7A5 \uC911..." : "\uC800\uC7A5" })
9527
+ /* @__PURE__ */ jsx(Button, { type: "submit", form: controller.formId, variant: "save", disabled: controller.isSaving, children: "\uC800\uC7A5" })
9161
9528
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
9529
+ canEdit && /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleEdit, children: "\uC218\uC815" }),
9162
9530
  renderFooterExtra,
9163
9531
  /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleClose, children: "\uB2EB\uAE30" })
9164
9532
  ] }) })