@ceed/ads 1.41.2 → 1.41.3-next.2

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
@@ -182,7 +182,7 @@ function Alert(inProps) {
182
182
  Alert.displayName = "Alert";
183
183
 
184
184
  // src/components/Autocomplete/Autocomplete.tsx
185
- import React5, { useCallback as useCallback2, useEffect as useEffect2, useMemo, useRef as useRef2 } from "react";
185
+ import React5, { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2 } from "react";
186
186
  import {
187
187
  Autocomplete as JoyAutocomplete,
188
188
  AutocompleteOption as JoyAutocompleteOption,
@@ -284,6 +284,37 @@ function useControlledState(controlledValue, defaultValue, onChange) {
284
284
  return [displayValue, handleChange, isControlled];
285
285
  }
286
286
 
287
+ // src/libs/slot-props.ts
288
+ import { useMemo } from "react";
289
+ function assignRef(ref, value) {
290
+ if (typeof ref === "function") ref(value);
291
+ else if (ref) ref.current = value;
292
+ }
293
+ function mergeRefs(...refs) {
294
+ const live = refs.filter((r) => r != null);
295
+ if (live.length === 0) return void 0;
296
+ if (live.length === 1) return live[0];
297
+ return (value) => live.forEach((r) => assignRef(r, value));
298
+ }
299
+ function useMergedRef(a, b) {
300
+ return useMemo(() => mergeRefs(a, b), [a, b]);
301
+ }
302
+ function useSlotRef(slotProp, ref) {
303
+ const isFunctionForm = typeof slotProp === "function";
304
+ const slotRef = isFunctionForm ? void 0 : slotProp?.ref;
305
+ const mergedRef = useMergedRef(slotRef, ref);
306
+ return useMemo(() => {
307
+ if (isFunctionForm) {
308
+ return ((ownerState) => {
309
+ const resolved = slotProp(ownerState);
310
+ const merged = mergeRefs(resolved.ref, ref);
311
+ return merged ? { ...resolved, ref: merged } : { ...resolved };
312
+ });
313
+ }
314
+ return mergedRef ? { ...slotProp, ref: mergedRef } : { ...slotProp };
315
+ }, [isFunctionForm, slotProp, mergedRef, ref]);
316
+ }
317
+
287
318
  // src/components/Autocomplete/Autocomplete.tsx
288
319
  var AutocompletePopper = styled3(Popper, {
289
320
  name: "Autocomplete",
@@ -308,11 +339,11 @@ var AutocompleteListBox = React5.forwardRef((props, ref) => {
308
339
  } = props;
309
340
  const parentRef = useRef2(null);
310
341
  const isGrouped = children[0].every((child) => child.hasOwnProperty("group"));
311
- const itemHeight = useMemo(() => {
342
+ const itemHeight = useMemo2(() => {
312
343
  const heights = itemHeightMap[fontSize ?? "md"];
313
344
  return hasSecondaryText ? heights.secondary : heights.default;
314
345
  }, [fontSize, hasSecondaryText]);
315
- const renderTargets = useMemo(() => {
346
+ const renderTargets = useMemo2(() => {
316
347
  if (loading) {
317
348
  return [children[1]];
318
349
  }
@@ -404,7 +435,7 @@ var autocompleteFilterOptions = createFilterOptions({
404
435
  }
405
436
  });
406
437
  var getOptionLabel = (option) => `${option.label ?? ""}`;
407
- function Autocomplete(props) {
438
+ function AutocompleteInner(props, ref) {
408
439
  const {
409
440
  label,
410
441
  error,
@@ -434,7 +465,7 @@ function Autocomplete(props) {
434
465
  )
435
466
  );
436
467
  const _value = rawValue ?? (props.multiple ? EMPTY_MULTIPLE_VALUE : "");
437
- const options = useMemo(
468
+ const options = useMemo2(
438
469
  () => props.options.map((option) => {
439
470
  if (typeof option !== "object") {
440
471
  return {
@@ -446,14 +477,14 @@ function Autocomplete(props) {
446
477
  }),
447
478
  [props.options]
448
479
  );
449
- const optionMap = useMemo(() => {
480
+ const optionMap = useMemo2(() => {
450
481
  const map = /* @__PURE__ */ new Map();
451
482
  options.forEach((option) => {
452
483
  map.set(option.value, option);
453
484
  });
454
485
  return map;
455
486
  }, [options]);
456
- const value = useMemo(() => {
487
+ const value = useMemo2(() => {
457
488
  if (props.loading) {
458
489
  return {
459
490
  value: "",
@@ -472,23 +503,25 @@ function Autocomplete(props) {
472
503
  },
473
504
  [size, props.loading]
474
505
  );
475
- const startDecorator = useMemo(
506
+ const startDecorator = useMemo2(
476
507
  () => applySize(value?.startDecorator || props.startDecorator),
477
508
  [value, applySize, props.startDecorator]
478
509
  );
479
- const endDecorator = useMemo(
510
+ const endDecorator = useMemo2(
480
511
  () => applySize(value?.endDecorator || props.endDecorator),
481
512
  [value, applySize, props.endDecorator]
482
513
  );
483
- const slotProps = useMemo(
514
+ const inputSlotProps = useSlotRef(props.slotProps?.input, ref);
515
+ const slotProps = useMemo2(
484
516
  () => ({
485
517
  ...props.slotProps,
486
518
  listbox: {
487
519
  ...props.slotProps?.listbox,
488
520
  hasSecondaryText: options.some((opt) => opt.secondaryText)
489
- }
521
+ },
522
+ input: inputSlotProps
490
523
  }),
491
- [options, props.slotProps]
524
+ [options, props.slotProps, inputSlotProps]
492
525
  );
493
526
  const handleChange = useCallback2(
494
527
  (event, value2) => {
@@ -522,9 +555,9 @@ function Autocomplete(props) {
522
555
  endDecorator,
523
556
  getOptionLabel,
524
557
  renderTags: (tags, getTagProps) => tags.map((tag, index) => {
525
- const { onClick, ...rest } = getTagProps({ index });
558
+ const { onClick, key, ...rest } = getTagProps({ index });
526
559
  return applySize(
527
- /* @__PURE__ */ React5.createElement(Chip_default, { color: "primary", ...rest }, /* @__PURE__ */ React5.createElement(Stack_default, { direction: "row", alignItems: "center", gap: 2, py: 0.5 }, tag.value, applySize(
560
+ /* @__PURE__ */ React5.createElement(Chip_default, { key, color: "primary", ...rest }, /* @__PURE__ */ React5.createElement(Stack_default, { direction: "row", alignItems: "center", gap: 2, py: 0.5 }, tag.value, applySize(
528
561
  /* @__PURE__ */ React5.createElement(AutocompleteTagDelete, { color: "primary", variant: "soft", onClick, size }, /* @__PURE__ */ React5.createElement(CloseIcon, null))
529
562
  )))
530
563
  );
@@ -534,26 +567,29 @@ function Autocomplete(props) {
534
567
  },
535
568
  slotProps,
536
569
  filterOptions: autocompleteFilterOptions,
537
- renderOption: (props2, option) => /* @__PURE__ */ React5.createElement(JoyAutocompleteOption, { ...props2 }, option.startDecorator && /* @__PURE__ */ React5.createElement(
538
- ListItemDecorator,
539
- {
540
- sx: (theme) => ({
541
- marginInlineEnd: `var(--Input-gap, ${theme.spacing(1)})`
542
- })
543
- },
544
- applySize(option.startDecorator)
545
- ), option.secondaryText ? /* @__PURE__ */ React5.createElement(ListItemContent, { sx: { gap: 0.5 } }, /* @__PURE__ */ React5.createElement(Typography2, { level: "inherit" }, applySize(option.label)), /* @__PURE__ */ React5.createElement(Typography2, { level: secondaryTextLevelMap[size ?? "md"], textColor: "text.tertiary" }, option.secondaryText)) : (
546
- // TODO: haulla에서 사용할 때, label을 ReactNode로 넘기면 에러가 발생함....
547
- applySize(option.label)
548
- ), option.endDecorator && /* @__PURE__ */ React5.createElement(
549
- ListItemDecorator,
550
- {
551
- sx: (theme) => ({
552
- marginInlineStart: `var(--Input-gap, ${theme.spacing(1)})`
553
- })
554
- },
555
- applySize(option.endDecorator)
556
- )),
570
+ renderOption: (props2, option) => {
571
+ const { key, ...optionProps } = props2;
572
+ return /* @__PURE__ */ React5.createElement(JoyAutocompleteOption, { key, ...optionProps }, option.startDecorator && /* @__PURE__ */ React5.createElement(
573
+ ListItemDecorator,
574
+ {
575
+ sx: (theme) => ({
576
+ marginInlineEnd: `var(--Input-gap, ${theme.spacing(1)})`
577
+ })
578
+ },
579
+ applySize(option.startDecorator)
580
+ ), option.secondaryText ? /* @__PURE__ */ React5.createElement(ListItemContent, { sx: { gap: 0.5 } }, /* @__PURE__ */ React5.createElement(Typography2, { level: "inherit" }, applySize(option.label)), /* @__PURE__ */ React5.createElement(Typography2, { level: secondaryTextLevelMap[size ?? "md"], textColor: "text.tertiary" }, option.secondaryText)) : (
581
+ // TODO: haulla에서 사용할 때, label을 ReactNode로 넘기면 에러가 발생함....
582
+ applySize(option.label)
583
+ ), option.endDecorator && /* @__PURE__ */ React5.createElement(
584
+ ListItemDecorator,
585
+ {
586
+ sx: (theme) => ({
587
+ marginInlineStart: `var(--Input-gap, ${theme.spacing(1)})`
588
+ })
589
+ },
590
+ applySize(option.endDecorator)
591
+ ));
592
+ },
557
593
  renderGroup: (params) => params
558
594
  }
559
595
  );
@@ -573,13 +609,14 @@ function Autocomplete(props) {
573
609
  helperText && /* @__PURE__ */ React5.createElement(FormHelperText_default, null, helperText)
574
610
  );
575
611
  }
612
+ var Autocomplete = React5.forwardRef(AutocompleteInner);
576
613
  Autocomplete.displayName = "Autocomplete";
577
614
 
578
615
  // src/components/Autocomplete/index.ts
579
616
  var Autocomplete_default = Autocomplete;
580
617
 
581
618
  // src/components/Avatar/Avatar.tsx
582
- import React6, { forwardRef as forwardRef2, useMemo as useMemo2 } from "react";
619
+ import React6, { forwardRef as forwardRef2, useMemo as useMemo3 } from "react";
583
620
  import { Avatar as JoyAvatar, AvatarGroup, styled as styled4, useThemeProps as useThemeProps2 } from "@mui/joy";
584
621
  var StyledAvatar = styled4(JoyAvatar, {
585
622
  name: "Avatar",
@@ -607,7 +644,7 @@ var Avatar = forwardRef2(function Avatar2(inProps, ref) {
607
644
  name: "Avatar"
608
645
  });
609
646
  const { children, getInitial = defaultGetInitial, ...inheritProps } = props;
610
- const calcChildren = useMemo2(() => {
647
+ const calcChildren = useMemo3(() => {
611
648
  if (typeof children === "string") {
612
649
  return getInitial?.(children) ?? "";
613
650
  }
@@ -649,7 +686,7 @@ var MenuItem = JoyMenuItem;
649
686
  var Menu_default = Menu;
650
687
 
651
688
  // src/components/Dropdown/Dropdown.tsx
652
- import React8, { createContext, useCallback as useCallback3, useMemo as useMemo3, useState as useState2 } from "react";
689
+ import React8, { createContext, useCallback as useCallback3, useMemo as useMemo4, useState as useState2 } from "react";
653
690
  import { Dropdown as JoyDropdown } from "@mui/joy";
654
691
  import { MenuButton } from "@mui/joy";
655
692
  import { useMenuButton } from "@mui/base/useMenuButton";
@@ -657,7 +694,7 @@ var DropdownNestedRegistryContext = createContext(null);
657
694
  function Dropdown({ open: openProp, defaultOpen = false, onOpenChange, ...rest }) {
658
695
  const [nestedCount, setNestedCount] = useState2(0);
659
696
  const [open, setOpen] = useControlledState(openProp, defaultOpen);
660
- const registry = useMemo3(
697
+ const registry = useMemo4(
661
698
  () => ({
662
699
  register: () => setNestedCount((c) => c + 1),
663
700
  unregister: () => setNestedCount((c) => Math.max(0, c - 1))
@@ -727,7 +764,7 @@ Button.displayName = "Button";
727
764
  var Button_default = Button;
728
765
 
729
766
  // src/components/Calendar/Calendar.tsx
730
- import React13, { Fragment, forwardRef as forwardRef4, useCallback as useCallback6, useEffect as useEffect3, useMemo as useMemo5, useRef as useRef3, useState as useState5 } from "react";
767
+ import React13, { Fragment, forwardRef as forwardRef4, useCallback as useCallback6, useEffect as useEffect3, useMemo as useMemo6, useRef as useRef3, useState as useState5 } from "react";
731
768
  import { styled as styled5 } from "@mui/joy";
732
769
  import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
733
770
  import ChevronRightIcon from "@mui/icons-material/ChevronRight";
@@ -821,7 +858,7 @@ var isSameMonth = (date1, date2) => {
821
858
  };
822
859
 
823
860
  // src/components/Calendar/hooks/use-calendar-props.ts
824
- import { useCallback as useCallback4, useMemo as useMemo4, useState as useState3 } from "react";
861
+ import { useCallback as useCallback4, useMemo as useMemo5, useState as useState3 } from "react";
825
862
  import { useThemeProps as useThemeProps3 } from "@mui/joy";
826
863
  var resolveView = (view, views) => {
827
864
  return views.includes(view) ? view : views[0];
@@ -841,12 +878,12 @@ var useCalendarProps = (inProps) => {
841
878
  });
842
879
  const [[page, direction], setPage] = useState3([0, 0]);
843
880
  const resolvedView = inProps.view ?? uncontrolledView;
844
- const resolvedMinDate = useMemo4(() => {
881
+ const resolvedMinDate = useMemo5(() => {
845
882
  const minDate = inProps.minDate || /* @__PURE__ */ new Date(0);
846
883
  minDate.setHours(0, 0, 0, 0);
847
884
  return minDate;
848
885
  }, [inProps.minDate]);
849
- const resolvedMaxDate = useMemo4(() => {
886
+ const resolvedMaxDate = useMemo5(() => {
850
887
  const maxDate = inProps.maxDate || /* @__PURE__ */ new Date(864e13);
851
888
  maxDate.setHours(0, 0, 0, 0);
852
889
  return maxDate;
@@ -905,7 +942,7 @@ var useCalendarProps = (inProps) => {
905
942
  },
906
943
  name: "Calendar"
907
944
  });
908
- const ownerState = useMemo4(() => ({ ...props, viewMonth, direction }), [props, viewMonth, direction]);
945
+ const ownerState = useMemo5(() => ({ ...props, viewMonth, direction }), [props, viewMonth, direction]);
909
946
  return [props, ownerState];
910
947
  };
911
948
 
@@ -1337,8 +1374,8 @@ var swipePower = (offset, velocity) => {
1337
1374
  var PickerDays = (props) => {
1338
1375
  const { ownerState } = props;
1339
1376
  const { getPickerDayProps, getDayCellProps } = useCalendar(ownerState);
1340
- const calendarDates = useMemo5(() => getCalendarDates(ownerState.viewMonth), [ownerState.viewMonth]);
1341
- const weekdayNames = useMemo5(() => getWeekdayNames(ownerState.locale || "default"), [ownerState.locale]);
1377
+ const calendarDates = useMemo6(() => getCalendarDates(ownerState.viewMonth), [ownerState.viewMonth]);
1378
+ const weekdayNames = useMemo6(() => getWeekdayNames(ownerState.locale || "default"), [ownerState.locale]);
1342
1379
  return /* @__PURE__ */ React13.createElement(CalendarViewContainer, { calendarType: "datePicker" }, /* @__PURE__ */ React13.createElement(AnimatePresence, { initial: false, custom: ownerState.direction }, /* @__PURE__ */ React13.createElement(
1343
1380
  CalendarViewTable,
1344
1381
  {
@@ -1422,8 +1459,8 @@ var PickerMonths = (props) => {
1422
1459
  };
1423
1460
  var PlainPickerDays = ({ ownerState }) => {
1424
1461
  const { getPickerDayProps, getDayCellProps } = useCalendar(ownerState);
1425
- const calendarDates = useMemo5(() => getCalendarDates(ownerState.viewMonth), [ownerState.viewMonth]);
1426
- const weekdayNames = useMemo5(() => getWeekdayNames(ownerState.locale || "default"), [ownerState.locale]);
1462
+ const calendarDates = useMemo6(() => getCalendarDates(ownerState.viewMonth), [ownerState.viewMonth]);
1463
+ const weekdayNames = useMemo6(() => getWeekdayNames(ownerState.locale || "default"), [ownerState.locale]);
1427
1464
  return /* @__PURE__ */ React13.createElement(StaticCalendarViewTable, null, /* @__PURE__ */ React13.createElement(CalendarWeekHeaderContainer, null, /* @__PURE__ */ React13.createElement("tr", null, weekdayNames.map((name, i) => /* @__PURE__ */ React13.createElement(Fragment, { key: `${ownerState.viewMonth}_${name}_${i}` }, /* @__PURE__ */ React13.createElement("th", null, /* @__PURE__ */ React13.createElement(Typography_default, { level: "body-xs", textAlign: "center" }, name)), i < 6 && /* @__PURE__ */ React13.createElement("th", { style: { width: 4 }, "aria-hidden": "true", "aria-description": "cell-gap" }))))), /* @__PURE__ */ React13.createElement(CalendarDayPickerContainer, null, calendarDates.map((weekDates, rowIndex) => /* @__PURE__ */ React13.createElement(Fragment, { key: `${ownerState.viewMonth}_${rowIndex}` }, /* @__PURE__ */ React13.createElement("tr", null, weekDates.map(
1428
1465
  (date, i) => date ? /* @__PURE__ */ React13.createElement(Fragment, { key: `${ownerState.viewMonth}_${date}_${i}` }, /* @__PURE__ */ React13.createElement(CalendarDayCell, { ...getDayCellProps(date) }, /* @__PURE__ */ React13.createElement(CalendarDay, { size: "sm", variant: "plain", color: "neutral", ...getPickerDayProps(date) }, date)), i < 6 && /* @__PURE__ */ React13.createElement("td", { "aria-hidden": "true", "aria-description": "cell-gap" })) : /* @__PURE__ */ React13.createElement(Fragment, { key: `${ownerState.viewMonth}_${i}` }, /* @__PURE__ */ React13.createElement("td", null), i < 6 && /* @__PURE__ */ React13.createElement("td", { "aria-hidden": "true", "aria-description": "cell-gap" }))
1429
1466
  )), rowIndex < calendarDates.length - 1 && /* @__PURE__ */ React13.createElement("tr", { "aria-hidden": "true", "aria-description": "row-gap" }, /* @__PURE__ */ React13.createElement("td", { colSpan: 13, style: { height: 4 } }))))));
@@ -1802,7 +1839,7 @@ var Container = forwardRef5(function Container2(props, ref) {
1802
1839
  Container.displayName = "Container";
1803
1840
 
1804
1841
  // src/components/CurrencyInput/CurrencyInput.tsx
1805
- import React17, { useCallback as useCallback8, useMemo as useMemo6 } from "react";
1842
+ import React17, { useCallback as useCallback8, useMemo as useMemo7 } from "react";
1806
1843
  import { NumericFormat } from "react-number-format";
1807
1844
 
1808
1845
  // src/components/Input/Input.tsx
@@ -2136,19 +2173,19 @@ var CurrencyInput = React17.forwardRef(function CurrencyInput2(inProps, ref) {
2136
2173
  props.defaultValue ?? null,
2137
2174
  useCallback8((value2) => onChange?.({ target: { name, value: value2 } }), [onChange, name])
2138
2175
  );
2139
- const value = useMemo6(() => {
2176
+ const value = useMemo7(() => {
2140
2177
  if (_value && useMinorUnit) {
2141
2178
  return _value / Math.pow(10, decimalScale);
2142
2179
  }
2143
2180
  return _value;
2144
2181
  }, [_value, useMinorUnit, decimalScale]);
2145
- const max = useMemo6(() => {
2182
+ const max = useMemo7(() => {
2146
2183
  if (props.max && useMinorUnit) {
2147
2184
  return props.max / Math.pow(10, decimalScale);
2148
2185
  }
2149
2186
  return props.max;
2150
2187
  }, [props.max, useMinorUnit, decimalScale]);
2151
- const isOverLimit = useMemo6(() => max != null && value != null && value > max, [max, value]);
2188
+ const isOverLimit = useMemo7(() => max != null && value != null && value > max, [max, value]);
2152
2189
  const handleChange = useCallback8(
2153
2190
  (event) => {
2154
2191
  if (event.target.value === "") {
@@ -2199,7 +2236,7 @@ var CurrencyInput_default = CurrencyInput;
2199
2236
  // src/components/DataTable/DataTable.tsx
2200
2237
  import React26, {
2201
2238
  useCallback as useCallback13,
2202
- useMemo as useMemo11,
2239
+ useMemo as useMemo12,
2203
2240
  useRef as useRef7,
2204
2241
  useId,
2205
2242
  forwardRef as forwardRef7,
@@ -2433,6 +2470,9 @@ function computeAutoFitWidth(params) {
2433
2470
  if (!isNaN(maxPx) && maxPx > 0) finalWidth = Math.min(finalWidth, maxPx);
2434
2471
  return finalWidth;
2435
2472
  }
2473
+ function getHeaderCellId(tableId, columnId) {
2474
+ return `${tableId}_header_${columnId}`.trim();
2475
+ }
2436
2476
 
2437
2477
  // src/components/DataTable/styled.tsx
2438
2478
  import React18 from "react";
@@ -2624,7 +2664,7 @@ import React23, {
2624
2664
  useRef as useRef5,
2625
2665
  useState as useState8,
2626
2666
  useLayoutEffect,
2627
- useMemo as useMemo9,
2667
+ useMemo as useMemo10,
2628
2668
  useCallback as useCallback10,
2629
2669
  useEffect as useEffect5,
2630
2670
  memo,
@@ -2972,7 +3012,7 @@ var DatePicker = forwardRef6((inProps, ref) => {
2972
3012
  },
2973
3013
  [format, minDate, maxDate, disableFuture, disablePast, shouldDisableDate]
2974
3014
  );
2975
- return /* @__PURE__ */ React19.createElement(DatePickerRoot, null, /* @__PURE__ */ React19.createElement(FocusTrap, { open: true }, /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(
3015
+ return /* @__PURE__ */ React19.createElement(DatePickerRoot, { sx, className }, /* @__PURE__ */ React19.createElement(FocusTrap, { open: true }, /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(
2976
3016
  Input_default,
2977
3017
  {
2978
3018
  ...innerProps,
@@ -2998,8 +3038,7 @@ var DatePicker = forwardRef6((inProps, ref) => {
2998
3038
  onClick: handleInputClick
2999
3039
  }
3000
3040
  },
3001
- className,
3002
- sx,
3041
+ sx: { width: "100%" },
3003
3042
  endDecorator: /* @__PURE__ */ React19.createElement(
3004
3043
  CalendarButton,
3005
3044
  {
@@ -3109,7 +3148,7 @@ import React20 from "react";
3109
3148
  import { Textarea as JoyTextarea } from "@mui/joy";
3110
3149
  import { motion as motion19 } from "framer-motion";
3111
3150
  var MotionTextarea = motion19(JoyTextarea);
3112
- var Textarea = (props) => {
3151
+ var TextareaBase = (props) => {
3113
3152
  const {
3114
3153
  label,
3115
3154
  error,
@@ -3153,13 +3192,17 @@ var Textarea = (props) => {
3153
3192
  helperText && /* @__PURE__ */ React20.createElement(FormHelperText_default, null, helperText)
3154
3193
  );
3155
3194
  };
3195
+ var Textarea = React20.forwardRef((props, ref) => {
3196
+ const textareaSlotProps = useSlotRef(props.slotProps?.textarea, ref);
3197
+ return /* @__PURE__ */ React20.createElement(TextareaBase, { ...props, slotProps: { ...props.slotProps, textarea: textareaSlotProps } });
3198
+ });
3156
3199
  Textarea.displayName = "Textarea";
3157
3200
 
3158
3201
  // src/components/Textarea/index.ts
3159
3202
  var Textarea_default = Textarea;
3160
3203
 
3161
3204
  // src/components/Select/Select.tsx
3162
- import React21, { useMemo as useMemo8 } from "react";
3205
+ import React21, { useMemo as useMemo9 } from "react";
3163
3206
  import {
3164
3207
  Select as JoySelect,
3165
3208
  Option as JoyOption,
@@ -3175,7 +3218,7 @@ var secondaryTextLevelMap2 = {
3175
3218
  lg: "body-md"
3176
3219
  };
3177
3220
  Option.displayName = "Option";
3178
- function Select(props) {
3221
+ function SelectInner(props, ref) {
3179
3222
  const {
3180
3223
  label,
3181
3224
  helperText,
@@ -3201,7 +3244,7 @@ function Select(props) {
3201
3244
  formHelperText: formHelperTextProps,
3202
3245
  ...joySlotProps
3203
3246
  } = slotProps ?? {};
3204
- const options = useMemo8(
3247
+ const options = useMemo9(
3205
3248
  () => props.options.map((option) => {
3206
3249
  if (option.hasOwnProperty("value") && option.hasOwnProperty("label")) {
3207
3250
  return option;
@@ -3226,13 +3269,14 @@ function Select(props) {
3226
3269
  };
3227
3270
  onChange?.(newEvent, newValue);
3228
3271
  };
3229
- const optionMap = useMemo8(() => {
3272
+ const optionMap = useMemo9(() => {
3230
3273
  const map = /* @__PURE__ */ new Map();
3231
3274
  options.forEach((option) => {
3232
3275
  map.set(option.value, option);
3233
3276
  });
3234
3277
  return map;
3235
3278
  }, [options]);
3279
+ const buttonSlotProps = useSlotRef(joySlotProps.button, ref);
3236
3280
  const select = /* @__PURE__ */ React21.createElement(
3237
3281
  JoySelect,
3238
3282
  {
@@ -3241,7 +3285,7 @@ function Select(props) {
3241
3285
  disabled,
3242
3286
  size,
3243
3287
  color: error ? "danger" : color,
3244
- slotProps: joySlotProps,
3288
+ slotProps: { ...joySlotProps, button: buttonSlotProps },
3245
3289
  onChange: handleChange,
3246
3290
  renderValue: (selected) => {
3247
3291
  if (!selected) return null;
@@ -3271,6 +3315,7 @@ function Select(props) {
3271
3315
  helperText && /* @__PURE__ */ React21.createElement(FormHelperText_default, { ...formHelperTextProps }, helperText)
3272
3316
  );
3273
3317
  }
3318
+ var Select = React21.forwardRef(SelectInner);
3274
3319
  Select.displayName = "Select";
3275
3320
 
3276
3321
  // src/components/Select/index.ts
@@ -3385,7 +3430,8 @@ var HeadCell = (props) => {
3385
3430
  tableColRef,
3386
3431
  headerClassName,
3387
3432
  headerLineClamp,
3388
- onAutoFit
3433
+ onAutoFit,
3434
+ columnId
3389
3435
  } = props;
3390
3436
  const theme = useTheme();
3391
3437
  const ref = headerRef;
@@ -3396,23 +3442,20 @@ var HeadCell = (props) => {
3396
3442
  }, [ref]);
3397
3443
  const [isHovered, setIsHovered] = useState8(false);
3398
3444
  const sortable = type === "actions" ? false : _sortable;
3399
- const headId = useMemo9(
3400
- () => `${tableId}_header_${headerName ?? field}`.trim(),
3401
- [tableId, headerName, field]
3402
- );
3445
+ const headId = useMemo10(() => getHeaderCellId(tableId, columnId ?? field), [tableId, columnId, field]);
3403
3446
  const isResizingRef = useRef5(false);
3404
- const resizer = useMemo9(
3447
+ const resizer = useMemo10(
3405
3448
  () => resizable ?? true ? Resizer(
3406
3449
  ref,
3407
3450
  colRef,
3408
3451
  (isResizing) => {
3409
3452
  isResizingRef.current = isResizing;
3410
3453
  },
3411
- onAutoFit ? () => onAutoFit(field) : void 0
3454
+ onAutoFit ? () => onAutoFit(columnId ?? String(field)) : void 0
3412
3455
  ) : null,
3413
- [resizable, ref, colRef, onAutoFit, field]
3456
+ [resizable, ref, colRef, onAutoFit, columnId, field]
3414
3457
  );
3415
- const style = useMemo9(
3458
+ const style = useMemo10(
3416
3459
  () => ({
3417
3460
  width,
3418
3461
  minWidth: minWidth ?? "50px",
@@ -3430,7 +3473,7 @@ var HeadCell = (props) => {
3430
3473
  );
3431
3474
  const textAlign = getTextAlign(props);
3432
3475
  const initialSort = sortOrder[0];
3433
- const sortIcon = useMemo9(() => {
3476
+ const sortIcon = useMemo10(() => {
3434
3477
  const isSorted = !!sort;
3435
3478
  const isVisible = sortable && (isSorted || isHovered);
3436
3479
  return /* @__PURE__ */ React23.createElement(AnimatePresence2, { mode: "wait" }, isVisible && /* @__PURE__ */ React23.createElement(
@@ -3461,17 +3504,17 @@ var HeadCell = (props) => {
3461
3504
  }
3462
3505
  ));
3463
3506
  }, [headId, initialSort, sort, sortable, isHovered]);
3464
- const infoSign = useMemo9(
3507
+ const infoSign = useMemo10(
3465
3508
  () => description ? /* @__PURE__ */ React23.createElement(InfoSign_default, { message: description, placement: "bottom" }) : null,
3466
3509
  [description]
3467
3510
  );
3468
- const params = useMemo9(
3511
+ const params = useMemo10(
3469
3512
  () => ({
3470
3513
  field
3471
3514
  }),
3472
3515
  [field]
3473
3516
  );
3474
- const computedHeaderClassName = useMemo9(
3517
+ const computedHeaderClassName = useMemo10(
3475
3518
  () => (typeof headerClassName === "function" ? headerClassName(params) : headerClassName) || void 0,
3476
3519
  [headerClassName, params]
3477
3520
  );
@@ -3525,7 +3568,7 @@ var BodyCell = (props) => {
3525
3568
  const theme = useTheme();
3526
3569
  const [value, setValue] = useState8(row[field]);
3527
3570
  const cellRef = useRef5(null);
3528
- const params = useMemo9(
3571
+ const params = useMemo10(
3529
3572
  () => ({
3530
3573
  row,
3531
3574
  value,
@@ -3534,20 +3577,20 @@ var BodyCell = (props) => {
3534
3577
  }),
3535
3578
  [row, rowId, value, field]
3536
3579
  );
3537
- const editMode = useMemo9(
3580
+ const editMode = useMemo10(
3538
3581
  () => !!(props.editMode && (typeof isCellEditable === "function" ? isCellEditable(params) : isCellEditable ?? true)),
3539
3582
  [props.editMode, isCellEditable, params]
3540
3583
  );
3541
3584
  const propsComponentProps = "componentProps" in props ? props.componentProps : null;
3542
3585
  const hasComponentProps = "componentProps" in props;
3543
- const componentProps = useMemo9(
3586
+ const componentProps = useMemo10(
3544
3587
  () => ({
3545
3588
  ...hasComponentProps && (typeof propsComponentProps === "function" ? propsComponentProps(params) : propsComponentProps || {}),
3546
3589
  size: "sm"
3547
3590
  }),
3548
3591
  [hasComponentProps, propsComponentProps, params]
3549
3592
  );
3550
- const editModeComponentProps = useMemo9(
3593
+ const editModeComponentProps = useMemo10(
3551
3594
  () => ({
3552
3595
  ...componentProps,
3553
3596
  onChange: (e) => {
@@ -3609,9 +3652,9 @@ var BodyCell = (props) => {
3609
3652
  }),
3610
3653
  [params, row, field, value, componentProps, type, onCellEditStop, onCellEditStart]
3611
3654
  );
3612
- const MemoizedRenderEditCell = useMemo9(() => renderEditCell ? memo(renderEditCell) : null, [renderEditCell]);
3613
- const MemoizedRenderCell = useMemo9(() => renderCell ? memo(renderCell) : null, [renderCell]);
3614
- const EditModeComponent = useMemo9(() => {
3655
+ const MemoizedRenderEditCell = useMemo10(() => renderEditCell ? memo(renderEditCell) : null, [renderEditCell]);
3656
+ const MemoizedRenderCell = useMemo10(() => renderCell ? memo(renderCell) : null, [renderCell]);
3657
+ const EditModeComponent = useMemo10(() => {
3615
3658
  if (MemoizedRenderEditCell) {
3616
3659
  return createElement(MemoizedRenderEditCell, params);
3617
3660
  }
@@ -3646,7 +3689,7 @@ var BodyCell = (props) => {
3646
3689
  }[type || "text"];
3647
3690
  }, [value, editModeComponentProps, type, MemoizedRenderEditCell, params]);
3648
3691
  const linkComponentFromProps = props.component;
3649
- const ReadModeComponent = useMemo9(() => {
3692
+ const ReadModeComponent = useMemo10(() => {
3650
3693
  if (MemoizedRenderCell) {
3651
3694
  return createElement(MemoizedRenderCell, params);
3652
3695
  }
@@ -3660,15 +3703,15 @@ var BodyCell = (props) => {
3660
3703
  return typedComponent || innerText;
3661
3704
  }, [value, MemoizedRenderCell, params, type, componentProps, linkComponentFromProps]);
3662
3705
  const getActions = props.getActions;
3663
- const CellComponent = useMemo9(() => {
3706
+ const CellComponent = useMemo10(() => {
3664
3707
  if (type === "actions") {
3665
3708
  return /* @__PURE__ */ React23.createElement(Stack_default, { direction: "row", gap: 1, justifyContent: "center", alignItems: "center" }, getActions?.(params));
3666
3709
  }
3667
3710
  return editMode && EditModeComponent ? EditModeComponent : ReadModeComponent;
3668
3711
  }, [type, getActions, params, editMode, EditModeComponent, ReadModeComponent]);
3669
- const showTooltip = useMemo9(() => noWrap && type === "longText", [noWrap, type]);
3712
+ const showTooltip = useMemo10(() => noWrap && type === "longText", [noWrap, type]);
3670
3713
  const isBoundary = props.isLastStartPinnedColumn || props.isLastEndPinnedColumn;
3671
- const computedCellClassName = useMemo9(
3714
+ const computedCellClassName = useMemo10(
3672
3715
  () => (typeof cellClassName === "function" ? cellClassName(params) : cellClassName) || "",
3673
3716
  [cellClassName, params]
3674
3717
  );
@@ -3680,7 +3723,7 @@ var BodyCell = (props) => {
3680
3723
  {
3681
3724
  ref: cellRef,
3682
3725
  key: field,
3683
- headers: `${tableId}_header_${props.headerName ?? field}`,
3726
+ headers: getHeaderCellId(tableId, props.columnId ?? field),
3684
3727
  sx: {
3685
3728
  textAlign: getTextAlign({ type }),
3686
3729
  verticalAlign: editMode ? "top" : "middle",
@@ -3692,7 +3735,7 @@ var BodyCell = (props) => {
3692
3735
  },
3693
3736
  className: [isLastStartPinnedColumn && "is-last-left", isLastEndPinnedColumn && "is-last-right", computedCellClassName].filter(Boolean).join(" ") || ""
3694
3737
  },
3695
- useMemo9(
3738
+ useMemo10(
3696
3739
  () => showTooltip ? /* @__PURE__ */ React23.createElement(CellTextEllipsis, null, CellComponent) : CellComponent,
3697
3740
  [CellComponent, showTooltip]
3698
3741
  )
@@ -3745,36 +3788,44 @@ var VirtualizedTableRow = memo(StyledTableRow2, (prevProps, nextProps) => {
3745
3788
  });
3746
3789
 
3747
3790
  // src/components/DataTable/hooks.ts
3748
- import { useState as useState9, useLayoutEffect as useLayoutEffect2, useRef as useRef6, useMemo as useMemo10, useCallback as useCallback11, useEffect as useEffect6, createRef } from "react";
3749
- function useColumnWidths(columnsByField) {
3791
+ import { useState as useState9, useLayoutEffect as useLayoutEffect2, useRef as useRef6, useMemo as useMemo11, useCallback as useCallback11, useEffect as useEffect6, createRef } from "react";
3792
+ function useColumnWidths(columnsById) {
3750
3793
  const [widths, setWidths] = useState9({});
3751
3794
  const roRef = useRef6();
3752
3795
  useLayoutEffect2(() => {
3753
3796
  if (roRef.current) roRef.current.disconnect();
3754
3797
  roRef.current = new ResizeObserver((entries) => {
3755
- let changed = false;
3756
3798
  setWidths((prev) => {
3799
+ let changed = false;
3757
3800
  const next = { ...prev };
3758
3801
  entries.forEach((entry) => {
3759
- const field = entry.target.dataset.field;
3802
+ const columnId = entry.target.dataset.hdsColumnId;
3760
3803
  const w = Math.round(entry.target.getBoundingClientRect().width);
3761
- if (next[field] !== w) {
3762
- next[field] = w;
3804
+ if (next[columnId] !== w) {
3805
+ next[columnId] = w;
3763
3806
  changed = true;
3764
3807
  }
3765
3808
  });
3766
3809
  return changed ? next : prev;
3767
3810
  });
3768
3811
  });
3769
- Object.entries(columnsByField).forEach(([field, def]) => {
3812
+ const measured = {};
3813
+ Object.entries(columnsById).forEach(([columnId, def]) => {
3770
3814
  const el = def.headerRef.current;
3771
3815
  if (el) {
3772
- el.dataset.field = field;
3816
+ el.dataset.hdsColumnId = columnId;
3817
+ el.dataset.field = String(def.field);
3818
+ measured[columnId] = Math.round(el.getBoundingClientRect().width);
3773
3819
  roRef.current.observe(el);
3774
3820
  }
3775
3821
  });
3822
+ setWidths((prev) => {
3823
+ const keys = Object.keys(measured);
3824
+ const same = keys.length === Object.keys(prev).length && keys.every((key) => prev[key] === measured[key]);
3825
+ return same ? prev : measured;
3826
+ });
3776
3827
  return () => roRef.current?.disconnect();
3777
- }, [columnsByField]);
3828
+ }, [columnsById]);
3778
3829
  return widths;
3779
3830
  }
3780
3831
  function useDataTableRenderer({
@@ -3823,16 +3874,16 @@ function useDataTableRenderer({
3823
3874
  [onColumnVisibilityModelChange]
3824
3875
  )
3825
3876
  );
3826
- const reorderedColumns = useMemo10(() => {
3877
+ const reorderedColumns = useMemo11(() => {
3827
3878
  if (!columnGroupingModel) return columnsProp;
3828
3879
  return reorderColumnsByGroupingModel(columnsProp, columnGroupingModel);
3829
3880
  }, [columnsProp, columnGroupingModel]);
3830
- const visibleColumns = useMemo10(
3881
+ const visibleColumns = useMemo11(
3831
3882
  () => reorderedColumns.filter((col) => visibilityModel[col.field] !== false),
3832
3883
  [reorderedColumns, visibilityModel]
3833
3884
  );
3834
- const visibleFieldSet = useMemo10(() => new Set(visibleColumns.map((c) => c.field)), [visibleColumns]);
3835
- const tableMinWidth = useMemo10(() => {
3885
+ const visibleFieldSet = useMemo11(() => new Set(visibleColumns.map((c) => c.field)), [visibleColumns]);
3886
+ const tableMinWidth = useMemo11(() => {
3836
3887
  const DEFAULT_MIN = 50;
3837
3888
  let total = checkboxSelection ? 40 : 0;
3838
3889
  for (const col of visibleColumns) {
@@ -3840,7 +3891,7 @@ function useDataTableRenderer({
3840
3891
  }
3841
3892
  return total;
3842
3893
  }, [visibleColumns, checkboxSelection]);
3843
- const allColumnsByField = useMemo10(
3894
+ const allColumnsByField = useMemo11(
3844
3895
  () => reorderedColumns.reduce(
3845
3896
  (acc, curr) => ({
3846
3897
  ...acc,
@@ -3850,19 +3901,34 @@ function useDataTableRenderer({
3850
3901
  ),
3851
3902
  [reorderedColumns]
3852
3903
  );
3853
- const visibleColumnsByField = useMemo10(
3854
- () => visibleColumns.reduce(
3855
- (acc, curr) => ({
3856
- ...acc,
3857
- [curr.field]: {
3858
- ...curr,
3904
+ const columnIds = useMemo11(() => {
3905
+ const taken = new Set(visibleColumns.map((column) => String(column.field)));
3906
+ const ids = [];
3907
+ visibleColumns.forEach((column) => {
3908
+ const field = String(column.field);
3909
+ if (!ids.includes(field)) {
3910
+ ids.push(field);
3911
+ return;
3912
+ }
3913
+ let n = 2;
3914
+ while (taken.has(`${field}__${n}`)) n += 1;
3915
+ taken.add(`${field}__${n}`);
3916
+ ids.push(`${field}__${n}`);
3917
+ });
3918
+ return ids;
3919
+ }, [visibleColumns]);
3920
+ const visibleColumnsById = useMemo11(
3921
+ () => Object.fromEntries(
3922
+ visibleColumns.map((column, index) => [
3923
+ columnIds[index],
3924
+ {
3925
+ ...column,
3859
3926
  headerRef: createRef(),
3860
3927
  tableColRef: createRef()
3861
3928
  }
3862
- }),
3863
- {}
3929
+ ])
3864
3930
  ),
3865
- [visibleColumns]
3931
+ [visibleColumns, columnIds]
3866
3932
  );
3867
3933
  const sortComparator = useCallback11(
3868
3934
  (rowA, rowB) => {
@@ -3893,11 +3959,11 @@ function useDataTableRenderer({
3893
3959
  },
3894
3960
  [sortModel, allColumnsByField]
3895
3961
  );
3896
- const rows = useMemo10(
3962
+ const rows = useMemo11(
3897
3963
  () => sortModel.length ? [..._rows].sort(sortComparator) : _rows,
3898
3964
  [_rows, sortModel, sortComparator]
3899
3965
  );
3900
- const sortOrder = useMemo10(
3966
+ const sortOrder = useMemo11(
3901
3967
  () => Array.from(new Set(_sortOrder || ["asc", "desc", null])),
3902
3968
  [_sortOrder]
3903
3969
  );
@@ -3907,12 +3973,12 @@ function useDataTableRenderer({
3907
3973
  (row, index) => _getId?.(row) ?? row.id ?? `${(index || 0) + (page - 1) * pageSize}`,
3908
3974
  [_getId, page, pageSize]
3909
3975
  );
3910
- const selectedModelSet = useMemo10(() => new Set(selectionModel || []), [selectionModel]);
3911
- const dataInPage = useMemo10(
3976
+ const selectedModelSet = useMemo11(() => new Set(selectionModel || []), [selectionModel]);
3977
+ const dataInPage = useMemo11(
3912
3978
  () => !pagination || paginationMode === "server" ? rows : rows.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize),
3913
3979
  [rows, page, pageSize, paginationMode, pagination]
3914
3980
  );
3915
- const selectableDataInPage = useMemo10(
3981
+ const selectableDataInPage = useMemo11(
3916
3982
  () => dataInPage.filter((row, i) => {
3917
3983
  if (!isRowSelectable) return true;
3918
3984
  return isRowSelectable({ row, id: getId(row, i) });
@@ -3942,51 +4008,60 @@ function useDataTableRenderer({
3942
4008
  },
3943
4009
  [dataInPage, getId, isRowSelectable, selectionModel, onSelectionModelChange]
3944
4010
  );
3945
- const isAllSelected = useMemo10(
4011
+ const isAllSelected = useMemo11(
3946
4012
  () => selectableDataInPage.length > 0 && selectableDataInPage.every((row, i) => selectedModelSet.has(getId(row, i))),
3947
4013
  [selectableDataInPage, selectedModelSet, getId]
3948
4014
  );
3949
4015
  const rowCount = totalRowsProp || rows.length;
3950
- const selectableRowCount = useMemo10(() => {
4016
+ const selectableRowCount = useMemo11(() => {
3951
4017
  if (!isRowSelectable) return rowCount;
3952
4018
  return rows.filter((row, i) => isRowSelectable({ row, id: getId(row, i) })).length;
3953
4019
  }, [rows, isRowSelectable, getId, rowCount]);
3954
- const isTotalSelected = useMemo10(
4020
+ const isTotalSelected = useMemo11(
3955
4021
  () => _isTotalSelected ?? (selectableRowCount > 0 && (selectionModel?.length || 0) === selectableRowCount),
3956
4022
  [_isTotalSelected, selectionModel, selectableRowCount]
3957
4023
  );
3958
- const columnWidths = useColumnWidths(visibleColumnsByField);
4024
+ const columnWidths = useColumnWidths(visibleColumnsById);
4025
+ const measuredWidthByField = useMemo11(
4026
+ () => Object.fromEntries(
4027
+ Object.entries(visibleColumnsById).map(([columnId, column]) => [column.field, columnWidths[columnId]])
4028
+ ),
4029
+ [visibleColumnsById, columnWidths]
4030
+ );
3959
4031
  const getWidth = useCallback11(
3960
- (f) => columnWidths[f] ?? allColumnsByField[f]?.width ?? // Column prop 으로 지정된 width
3961
- allColumnsByField[f]?.minWidth ?? 0,
3962
- [columnWidths, allColumnsByField]
4032
+ // 반환값은 pinned offset으로 더해지므로 반드시 숫자여야 한다. width/minWidth는 '500px' 같은 문자열.
4033
+ (f) => measuredWidthByField[f] ?? parsePxValue(allColumnsByField[f]?.width) ?? // Column prop 으로 지정된 width
4034
+ parsePxValue(allColumnsByField[f]?.minWidth) ?? 0,
4035
+ [measuredWidthByField, allColumnsByField]
3963
4036
  );
3964
- const processedColumnGroups = useMemo10(() => {
4037
+ const processedColumnGroups = useMemo11(() => {
3965
4038
  if (!columnGroupingModel) return null;
3966
4039
  return calculateColumnGroups(columnGroupingModel, visibleColumns, visibleFieldSet);
3967
4040
  }, [columnGroupingModel, visibleColumns, visibleFieldSet]);
3968
- const effectivePinnedLeft = useMemo10(
4041
+ const effectivePinnedLeft = useMemo11(
3969
4042
  () => pinnedColumns?.left?.filter((f) => visibleFieldSet.has(f)),
3970
4043
  [pinnedColumns?.left, visibleFieldSet]
3971
4044
  );
3972
- const effectivePinnedRight = useMemo10(
4045
+ const effectivePinnedRight = useMemo11(
3973
4046
  () => pinnedColumns?.right?.filter((f) => visibleFieldSet.has(f)),
3974
4047
  [pinnedColumns?.right, visibleFieldSet]
3975
4048
  );
3976
4049
  const inferredFieldsKey = JSON.stringify(Object.keys(rows[0] || {}));
3977
- const inferredFields = useMemo10(() => JSON.parse(inferredFieldsKey), [inferredFieldsKey]);
3978
- const columns = useMemo10(() => {
4050
+ const inferredFields = useMemo11(() => JSON.parse(inferredFieldsKey), [inferredFieldsKey]);
4051
+ const columns = useMemo11(() => {
3979
4052
  const baseColumns = visibleColumns.length > 0 ? visibleColumns : reorderedColumns.length > 0 ? [] : inferredFields.map((key) => ({
3980
4053
  field: key
3981
4054
  }));
3982
- return baseColumns.map((column) => {
4055
+ return baseColumns.map((column, index) => {
4056
+ const columnId = columnIds[index] ?? String(column.field);
3983
4057
  const isLeftPinned = effectivePinnedLeft?.includes(column.field);
3984
4058
  const isRightPinned = effectivePinnedRight?.includes(column.field);
3985
4059
  const isPinned = isLeftPinned || isRightPinned;
3986
4060
  return {
3987
4061
  ...column,
3988
- headerRef: visibleColumnsByField[column.field]?.headerRef,
3989
- tableColRef: visibleColumnsByField[column.field]?.tableColRef,
4062
+ columnId,
4063
+ headerRef: visibleColumnsById[columnId]?.headerRef,
4064
+ tableColRef: visibleColumnsById[columnId]?.tableColRef,
3990
4065
  isCellEditable: editMode && (typeof column.isCellEditable === "function" ? column.isCellEditable : column.isCellEditable ?? true),
3991
4066
  sort: sortModel.find((sort) => sort.field === column.field)?.sort,
3992
4067
  sortOrder: allColumnsByField[column.field]?.sortOrder || sortOrder,
@@ -4003,7 +4078,8 @@ function useDataTableRenderer({
4003
4078
  inferredFields,
4004
4079
  effectivePinnedLeft,
4005
4080
  effectivePinnedRight,
4006
- visibleColumnsByField,
4081
+ columnIds,
4082
+ visibleColumnsById,
4007
4083
  allColumnsByField,
4008
4084
  editMode,
4009
4085
  sortModel,
@@ -4063,15 +4139,14 @@ function useDataTableRenderer({
4063
4139
  }
4064
4140
  }, [_rows]);
4065
4141
  const handleAutoFit = useCallback11(
4066
- (field) => {
4067
- const colDef = visibleColumnsByField[field];
4142
+ (columnId) => {
4143
+ const colDef = visibleColumnsById[columnId];
4068
4144
  if (!colDef?.headerRef.current) return;
4069
- const column = allColumnsByField[field];
4070
- const columnType = column && "type" in column ? column.type : void 0;
4145
+ const columnType = "type" in colDef ? colDef.type : void 0;
4071
4146
  if (columnType === "actions") return;
4072
4147
  const optimalWidth = computeAutoFitWidth({
4073
4148
  headerEl: colDef.headerRef.current,
4074
- field,
4149
+ field: colDef.field,
4075
4150
  dataInPage
4076
4151
  });
4077
4152
  if (optimalWidth == null) return;
@@ -4079,7 +4154,7 @@ function useDataTableRenderer({
4079
4154
  colDef.headerRef.current.style.width = widthPx;
4080
4155
  if (colDef.tableColRef.current) colDef.tableColRef.current.style.width = widthPx;
4081
4156
  },
4082
- [visibleColumnsByField, allColumnsByField, dataInPage]
4157
+ [visibleColumnsById, dataInPage]
4083
4158
  );
4084
4159
  return {
4085
4160
  rowCount,
@@ -4554,9 +4629,9 @@ function Component(props, apiRef) {
4554
4629
  measureElement: (element) => element.clientHeight,
4555
4630
  overscan: 10
4556
4631
  });
4557
- const paginationModel = useMemo11(() => ({ page, pageSize }), [page, pageSize]);
4632
+ const paginationModel = useMemo12(() => ({ page, pageSize }), [page, pageSize]);
4558
4633
  const columnsKey = getObjectVersion(columns);
4559
- const headerCheckboxElement = useMemo11(
4634
+ const headerCheckboxElement = useMemo12(
4560
4635
  () => /* @__PURE__ */ React26.createElement(
4561
4636
  RenderCheckbox,
4562
4637
  {
@@ -4766,7 +4841,7 @@ function Component(props, apiRef) {
4766
4841
  "col",
4767
4842
  {
4768
4843
  ref: c.tableColRef,
4769
- key: `${c.field.toString()}_${c.width}`,
4844
+ key: c.columnId,
4770
4845
  style: {
4771
4846
  width: c.width,
4772
4847
  minWidth: c.minWidth ?? "50px"
@@ -4952,7 +5027,7 @@ var DataTable = forwardRef7(Component);
4952
5027
  DataTable.displayName = "DataTable";
4953
5028
 
4954
5029
  // src/components/DateRangePicker/DateRangePicker.tsx
4955
- import React27, { forwardRef as forwardRef8, useCallback as useCallback14, useEffect as useEffect8, useImperativeHandle as useImperativeHandle3, useMemo as useMemo12, useRef as useRef8, useState as useState10 } from "react";
5030
+ import React27, { forwardRef as forwardRef8, useCallback as useCallback14, useEffect as useEffect8, useImperativeHandle as useImperativeHandle3, useMemo as useMemo13, useRef as useRef8, useState as useState10 } from "react";
4956
5031
  import { IMaskInput as IMaskInput2, IMask as IMask2 } from "react-imask";
4957
5032
  import CalendarTodayIcon2 from "@mui/icons-material/CalendarToday";
4958
5033
  import { styled as styled14, useThemeProps as useThemeProps7 } from "@mui/joy";
@@ -5174,7 +5249,7 @@ var DateRangePicker = forwardRef8((inProps, ref) => {
5174
5249
  );
5175
5250
  const [anchorEl, setAnchorEl] = useState10(null);
5176
5251
  const open = Boolean(anchorEl);
5177
- const calendarValue = useMemo12(
5252
+ const calendarValue = useMemo13(
5178
5253
  () => value ? parseDates(value, format) : void 0,
5179
5254
  [value, format]
5180
5255
  );
@@ -5299,7 +5374,7 @@ var DateRangePicker = forwardRef8((inProps, ref) => {
5299
5374
  },
5300
5375
  [format, minDate, maxDate, disableFuture, disablePast]
5301
5376
  );
5302
- return /* @__PURE__ */ React27.createElement(DateRangePickerRoot, null, /* @__PURE__ */ React27.createElement(FocusTrap2, { open: true }, /* @__PURE__ */ React27.createElement(React27.Fragment, null, /* @__PURE__ */ React27.createElement(
5377
+ return /* @__PURE__ */ React27.createElement(DateRangePickerRoot, { sx, className }, /* @__PURE__ */ React27.createElement(FocusTrap2, { open: true }, /* @__PURE__ */ React27.createElement(React27.Fragment, null, /* @__PURE__ */ React27.createElement(
5303
5378
  Input_default,
5304
5379
  {
5305
5380
  ...innerProps,
@@ -5325,8 +5400,7 @@ var DateRangePicker = forwardRef8((inProps, ref) => {
5325
5400
  }
5326
5401
  },
5327
5402
  error,
5328
- className,
5329
- sx,
5403
+ sx: { width: "100%" },
5330
5404
  endDecorator: /* @__PURE__ */ React27.createElement(
5331
5405
  CalendarButton2,
5332
5406
  {
@@ -5469,10 +5543,10 @@ var ModalClose = JoyModalClose;
5469
5543
  var MotionModalOverflow = motion23(JoyModalOverflow);
5470
5544
  var ModalOverflow = MotionModalOverflow;
5471
5545
  ModalOverflow.displayName = "ModalOverflow";
5472
- function ModalFrame(props) {
5546
+ var ModalFrame = React28.forwardRef((props, ref) => {
5473
5547
  const { title, children, titleStartDecorator, onClose, ...innerProps } = props;
5474
- return /* @__PURE__ */ React28.createElement(StyledModalDialog, { ...innerProps }, /* @__PURE__ */ React28.createElement(ModalClose, { onClick: onClose }), /* @__PURE__ */ React28.createElement(DialogTitle_default, null, titleStartDecorator, title), /* @__PURE__ */ React28.createElement(DialogContent_default, null, children));
5475
- }
5548
+ return /* @__PURE__ */ React28.createElement(StyledModalDialog, { ref, ...innerProps }, /* @__PURE__ */ React28.createElement(ModalClose, { onClick: onClose }), /* @__PURE__ */ React28.createElement(DialogTitle_default, null, titleStartDecorator, title), /* @__PURE__ */ React28.createElement(DialogContent_default, null, children));
5549
+ });
5476
5550
  ModalFrame.displayName = "ModalFrame";
5477
5551
 
5478
5552
  // src/components/DialogFrame/DialogFrame.tsx
@@ -5517,7 +5591,7 @@ var InsetDrawer = styled19(JoyDrawer)(({ theme }) => ({
5517
5591
  }));
5518
5592
 
5519
5593
  // src/components/FilterableCheckboxGroup/FilterableCheckboxGroup.tsx
5520
- import React31, { useCallback as useCallback15, useEffect as useEffect9, useMemo as useMemo13, useRef as useRef9, useState as useState11 } from "react";
5594
+ import React31, { useCallback as useCallback15, useEffect as useEffect9, useMemo as useMemo14, useRef as useRef9, useState as useState11 } from "react";
5521
5595
  import SearchIcon from "@mui/icons-material/Search";
5522
5596
  import { useThemeProps as useThemeProps8 } from "@mui/joy";
5523
5597
  import { useVirtualizer as useVirtualizer3 } from "@tanstack/react-virtual";
@@ -5578,11 +5652,11 @@ function FilterableCheckboxGroup(inProps) {
5578
5652
  const parentRef = useRef9(null);
5579
5653
  const isInitialSortRef = useRef9(false);
5580
5654
  const prevOptionsRef = useRef9([...options]);
5581
- const filteredOptions = useMemo13(() => {
5655
+ const filteredOptions = useMemo14(() => {
5582
5656
  if (!searchTerm) return sortedOptions;
5583
5657
  return sortedOptions.filter((option) => option.label.toLowerCase().includes(searchTerm.toLowerCase()));
5584
5658
  }, [sortedOptions, searchTerm]);
5585
- const itemSize = useMemo13(() => {
5659
+ const itemSize = useMemo14(() => {
5586
5660
  switch (size) {
5587
5661
  case "sm":
5588
5662
  return 28;
@@ -5656,7 +5730,7 @@ function FilterableCheckboxGroup(inProps) {
5656
5730
  },
5657
5731
  [filteredOptions, internalValue, setInternalValue]
5658
5732
  );
5659
- const enabledFilteredOptions = useMemo13(() => filteredOptions.filter((option) => !option.disabled), [filteredOptions]);
5733
+ const enabledFilteredOptions = useMemo14(() => filteredOptions.filter((option) => !option.disabled), [filteredOptions]);
5660
5734
  const isAllSelected = enabledFilteredOptions.length > 0 && enabledFilteredOptions.every((option) => internalValue.includes(option.value));
5661
5735
  const isIndeterminate = !isAllSelected && enabledFilteredOptions.some((option) => internalValue.includes(option.value));
5662
5736
  return /* @__PURE__ */ React31.createElement("div", { style: { width: "100%" } }, /* @__PURE__ */ React31.createElement(
@@ -5845,7 +5919,7 @@ function RadioGroup2(props) {
5845
5919
  RadioGroup2.displayName = "RadioGroup";
5846
5920
 
5847
5921
  // src/components/FilterMenu/components/DateRange.tsx
5848
- import React35, { useCallback as useCallback19, useMemo as useMemo14, useState as useState12, useEffect as useEffect10 } from "react";
5922
+ import React35, { useCallback as useCallback19, useMemo as useMemo15, useState as useState12, useEffect as useEffect10 } from "react";
5849
5923
  import { Stack as Stack5 } from "@mui/joy";
5850
5924
  function DateRange(props) {
5851
5925
  const {
@@ -5864,7 +5938,7 @@ function DateRange(props) {
5864
5938
  } = props;
5865
5939
  const [internalValue, setInternalValue] = useControlledState(value, null, onChange);
5866
5940
  const [selectedOption, setSelectedOption] = useState12("all-time");
5867
- const dateRangeOptions = useMemo14(
5941
+ const dateRangeOptions = useMemo15(
5868
5942
  () => [
5869
5943
  { label: "All Time", value: "all-time" },
5870
5944
  { label: "This Month", value: "this-month" },
@@ -5929,7 +6003,7 @@ function DateRange(props) {
5929
6003
  },
5930
6004
  [getDateRangeForOption]
5931
6005
  );
5932
- const customDateRangeValue = useMemo14(() => {
6006
+ const customDateRangeValue = useMemo15(() => {
5933
6007
  if (selectedOption === "custom" && internalValue) {
5934
6008
  return `${internalValue[0]} - ${internalValue[1]}`;
5935
6009
  }
@@ -5988,11 +6062,11 @@ function DateRange(props) {
5988
6062
  DateRange.displayName = "DateRange";
5989
6063
 
5990
6064
  // src/components/FilterMenu/components/MonthRange.tsx
5991
- import React37, { useCallback as useCallback21, useMemo as useMemo16 } from "react";
6065
+ import React37, { useCallback as useCallback21, useMemo as useMemo17 } from "react";
5992
6066
  import { Stack as Stack6 } from "@mui/joy";
5993
6067
 
5994
6068
  // src/components/MonthRangePicker/MonthRangePicker.tsx
5995
- import React36, { forwardRef as forwardRef9, useCallback as useCallback20, useEffect as useEffect11, useImperativeHandle as useImperativeHandle4, useMemo as useMemo15, useRef as useRef10, useState as useState13 } from "react";
6069
+ import React36, { forwardRef as forwardRef9, useCallback as useCallback20, useEffect as useEffect11, useImperativeHandle as useImperativeHandle4, useMemo as useMemo16, useRef as useRef10, useState as useState13 } from "react";
5996
6070
  import { IMaskInput as IMaskInput3, IMask as IMask3 } from "react-imask";
5997
6071
  import CalendarTodayIcon3 from "@mui/icons-material/CalendarToday";
5998
6072
  import { styled as styled20, useThemeProps as useThemeProps9 } from "@mui/joy";
@@ -6123,7 +6197,7 @@ var MonthRangePicker = forwardRef9((inProps, ref) => {
6123
6197
  );
6124
6198
  const [anchorEl, setAnchorEl] = useState13(null);
6125
6199
  const open = Boolean(anchorEl);
6126
- const calendarValue = useMemo15(() => value ? parseDates2(value) : void 0, [value]);
6200
+ const calendarValue = useMemo16(() => value ? parseDates2(value) : void 0, [value]);
6127
6201
  useEffect11(() => {
6128
6202
  if (value) {
6129
6203
  try {
@@ -6298,7 +6372,7 @@ function MonthRange(props) {
6298
6372
  locale
6299
6373
  } = props;
6300
6374
  const [internalValue, setInternalValue] = useControlledState(value, null, onChange);
6301
- const pickerValue = useMemo16(
6375
+ const pickerValue = useMemo17(
6302
6376
  () => internalValue ? `${internalValue[0]} - ${internalValue[1]}` : "",
6303
6377
  [internalValue]
6304
6378
  );
@@ -6441,7 +6515,7 @@ import React41 from "react";
6441
6515
  import { Stack as Stack9, Typography as Typography5 } from "@mui/joy";
6442
6516
 
6443
6517
  // src/components/PercentageInput/PercentageInput.tsx
6444
- import React40, { useCallback as useCallback24, useMemo as useMemo17 } from "react";
6518
+ import React40, { useCallback as useCallback24, useMemo as useMemo18 } from "react";
6445
6519
  import { NumericFormat as NumericFormat2 } from "react-number-format";
6446
6520
  import { styled as styled21, useThemeProps as useThemeProps10 } from "@mui/joy";
6447
6521
  var padDecimal = (value, decimalScale) => {
@@ -6500,13 +6574,13 @@ var PercentageInput = React40.forwardRef(
6500
6574
  props.defaultValue ?? null,
6501
6575
  useCallback24((value2) => onChange?.({ target: { name, value: value2 } }), [onChange, name])
6502
6576
  );
6503
- const value = useMemo17(() => {
6577
+ const value = useMemo18(() => {
6504
6578
  if (_value && useMinorUnit) {
6505
6579
  return _value / Math.pow(10, maxDecimalScale);
6506
6580
  }
6507
6581
  return _value;
6508
6582
  }, [_value, useMinorUnit, maxDecimalScale]);
6509
- const internalError = useMemo17(
6583
+ const internalError = useMemo18(
6510
6584
  () => value != null && (max != null && value > max || min != null && value < min),
6511
6585
  [max, min, value]
6512
6586
  );
@@ -6766,7 +6840,7 @@ function FilterMenu(props) {
6766
6840
  FilterMenu.displayName = "FilterMenu";
6767
6841
 
6768
6842
  // src/components/Uploader/Uploader.tsx
6769
- import React45, { useCallback as useCallback28, useEffect as useEffect13, useMemo as useMemo18, useRef as useRef11, useState as useState14 } from "react";
6843
+ import React45, { useCallback as useCallback28, useEffect as useEffect13, useMemo as useMemo19, useRef as useRef11, useState as useState14 } from "react";
6770
6844
  import { styled as styled22, Input as Input2 } from "@mui/joy";
6771
6845
  import MuiFileUploadIcon from "@mui/icons-material/CloudUploadRounded";
6772
6846
  import MuiUploadFileIcon from "@mui/icons-material/UploadFileRounded";
@@ -6906,8 +6980,8 @@ var Uploader = React45.memo((props) => {
6906
6980
  const [files, setFiles] = useState14([]);
6907
6981
  const [uploaded, setUploaded] = useState14(props.uploaded || []);
6908
6982
  const [previewState, setPreviewState] = useState14("idle");
6909
- const accepts = useMemo18(() => accept.split(",").map((accept2) => accept2.trim()), [accept]);
6910
- const parsedAccepts = useMemo18(
6983
+ const accepts = useMemo19(() => accept.split(",").map((accept2) => accept2.trim()), [accept]);
6984
+ const parsedAccepts = useMemo19(
6911
6985
  () => accepts.flatMap((type) => {
6912
6986
  if (["image/*", "video/*", "audio/*"].includes(type)) {
6913
6987
  return ALL_EXTENSIONS_BY_TYPE[type];
@@ -6916,7 +6990,7 @@ var Uploader = React45.memo((props) => {
6916
6990
  }),
6917
6991
  [accepts]
6918
6992
  );
6919
- const helperText = useMemo18(() => {
6993
+ const helperText = useMemo19(() => {
6920
6994
  if (helperTextProp) {
6921
6995
  return helperTextProp;
6922
6996
  }
@@ -6946,8 +7020,8 @@ var Uploader = React45.memo((props) => {
6946
7020
  }
6947
7021
  return helperTexts.join(", ");
6948
7022
  }, [accepts, maxFileTotalSize, maxCount, helperTextProp]);
6949
- const error = useMemo18(() => !!errorText || errorProp, [errorProp, errorText]);
6950
- const showDropZone = useMemo18(
7023
+ const error = useMemo19(() => !!errorText || errorProp, [errorProp, errorText]);
7024
+ const showDropZone = useMemo19(
6951
7025
  () => !maxCount || maxCount && [...uploaded, ...files].length !== maxCount,
6952
7026
  [files, maxCount, uploaded]
6953
7027
  );
@@ -7109,7 +7183,10 @@ import {
7109
7183
  MenuButton as JoyMenuButton2,
7110
7184
  IconButton as JoyIconButton2
7111
7185
  } from "@mui/joy";
7112
- function IconMenuButton(props) {
7186
+ var MenuButtonRootSlot = React46.forwardRef(function MenuButtonRootSlot2({ as, ...rest }, ref) {
7187
+ return /* @__PURE__ */ React46.createElement(JoyIconButton2, { ...rest, component: as ?? "button", ref });
7188
+ });
7189
+ function IconMenuButtonInner(props, ref) {
7113
7190
  const {
7114
7191
  size,
7115
7192
  icon,
@@ -7120,6 +7197,8 @@ function IconMenuButton(props) {
7120
7197
  variant = "plain",
7121
7198
  placement = "bottom"
7122
7199
  } = props;
7200
+ const { ref: buttonComponentRef, ...buttonComponentProps } = props.buttonComponentProps ?? {};
7201
+ const mergedButtonRef = useMergedRef(buttonComponentRef, ref);
7123
7202
  if (!items.length) {
7124
7203
  return /* @__PURE__ */ React46.createElement(
7125
7204
  JoyIconButton2,
@@ -7130,7 +7209,8 @@ function IconMenuButton(props) {
7130
7209
  color,
7131
7210
  disabled,
7132
7211
  loading,
7133
- ...props.buttonComponentProps ?? {}
7212
+ ...buttonComponentProps,
7213
+ ref: mergedButtonRef
7134
7214
  },
7135
7215
  icon
7136
7216
  );
@@ -7138,7 +7218,7 @@ function IconMenuButton(props) {
7138
7218
  return /* @__PURE__ */ React46.createElement(Dropdown_default, null, /* @__PURE__ */ React46.createElement(
7139
7219
  JoyMenuButton2,
7140
7220
  {
7141
- slots: { root: JoyIconButton2 },
7221
+ slots: { root: MenuButtonRootSlot },
7142
7222
  slotProps: {
7143
7223
  root: {
7144
7224
  component: props.buttonComponent ?? "button",
@@ -7147,13 +7227,16 @@ function IconMenuButton(props) {
7147
7227
  color,
7148
7228
  disabled,
7149
7229
  loading,
7150
- ...props.buttonComponentProps ?? {}
7230
+ ...buttonComponentProps,
7231
+ // Joy의 useSlot이 내부 ref와 이 ref를 합쳐준다. 위 no-items 분기와 같은 경로로 ref를 넘긴다.
7232
+ ref: mergedButtonRef
7151
7233
  }
7152
7234
  }
7153
7235
  },
7154
7236
  icon
7155
7237
  ), /* @__PURE__ */ React46.createElement(Menu, { placement, size }, items.map((i) => /* @__PURE__ */ React46.createElement(MenuItem, { key: i.text, component: i.component, ...i.componentProps ?? {} }, i.text))));
7156
7238
  }
7239
+ var IconMenuButton = React46.forwardRef(IconMenuButtonInner);
7157
7240
  IconMenuButton.displayName = "IconMenuButton";
7158
7241
 
7159
7242
  // src/components/Markdown/Markdown.tsx
@@ -7727,7 +7810,7 @@ function Navigator(props) {
7727
7810
  Navigator.displayName = "Navigator";
7728
7811
 
7729
7812
  // src/components/ProfileMenu/ProfileMenu.tsx
7730
- import React53, { useCallback as useCallback30, useMemo as useMemo19 } from "react";
7813
+ import React53, { useCallback as useCallback30, useMemo as useMemo20 } from "react";
7731
7814
  import { Dropdown as Dropdown2, ListDivider, menuItemClasses, styled as styled26, MenuButton as MenuButton3, useThemeProps as useThemeProps12 } from "@mui/joy";
7732
7815
  import { ClickAwayListener as ClickAwayListener5 } from "@mui/base";
7733
7816
  import DropdownIcon from "@mui/icons-material/ArrowDropDown";
@@ -7737,8 +7820,8 @@ var StyledProfileCard = styled26(Stack, {
7737
7820
  })({});
7738
7821
  function ProfileCard(props) {
7739
7822
  const { children, chip, caption, size } = props;
7740
- const captionLevel = useMemo19(() => size === "sm" ? "body-xs" : "body-sm", [size]);
7741
- const nameLevel = useMemo19(() => size === "sm" ? "body-sm" : "body-md", [size]);
7823
+ const captionLevel = useMemo20(() => size === "sm" ? "body-xs" : "body-sm", [size]);
7824
+ const nameLevel = useMemo20(() => size === "sm" ? "body-sm" : "body-md", [size]);
7742
7825
  return /* @__PURE__ */ React53.createElement(StyledProfileCard, { px: 4, py: 2 }, /* @__PURE__ */ React53.createElement(Stack, { direction: "row", gap: 2 }, /* @__PURE__ */ React53.createElement(Typography, { level: nameLevel, fontWeight: "bold", textColor: "text.primary" }, children), chip && /* @__PURE__ */ React53.createElement(Chip, { size, color: "neutral", variant: "outlined" }, chip)), caption && /* @__PURE__ */ React53.createElement(Typography, { level: captionLevel, textColor: "text.tertiary" }, caption));
7743
7826
  }
7744
7827
  ProfileCard.displayName = "ProfileCard";