@ceed/ads 1.41.3-next.1 → 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,
@@ -3108,7 +3148,7 @@ import React20 from "react";
3108
3148
  import { Textarea as JoyTextarea } from "@mui/joy";
3109
3149
  import { motion as motion19 } from "framer-motion";
3110
3150
  var MotionTextarea = motion19(JoyTextarea);
3111
- var Textarea = (props) => {
3151
+ var TextareaBase = (props) => {
3112
3152
  const {
3113
3153
  label,
3114
3154
  error,
@@ -3152,13 +3192,17 @@ var Textarea = (props) => {
3152
3192
  helperText && /* @__PURE__ */ React20.createElement(FormHelperText_default, null, helperText)
3153
3193
  );
3154
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
+ });
3155
3199
  Textarea.displayName = "Textarea";
3156
3200
 
3157
3201
  // src/components/Textarea/index.ts
3158
3202
  var Textarea_default = Textarea;
3159
3203
 
3160
3204
  // src/components/Select/Select.tsx
3161
- import React21, { useMemo as useMemo8 } from "react";
3205
+ import React21, { useMemo as useMemo9 } from "react";
3162
3206
  import {
3163
3207
  Select as JoySelect,
3164
3208
  Option as JoyOption,
@@ -3174,7 +3218,7 @@ var secondaryTextLevelMap2 = {
3174
3218
  lg: "body-md"
3175
3219
  };
3176
3220
  Option.displayName = "Option";
3177
- function Select(props) {
3221
+ function SelectInner(props, ref) {
3178
3222
  const {
3179
3223
  label,
3180
3224
  helperText,
@@ -3200,7 +3244,7 @@ function Select(props) {
3200
3244
  formHelperText: formHelperTextProps,
3201
3245
  ...joySlotProps
3202
3246
  } = slotProps ?? {};
3203
- const options = useMemo8(
3247
+ const options = useMemo9(
3204
3248
  () => props.options.map((option) => {
3205
3249
  if (option.hasOwnProperty("value") && option.hasOwnProperty("label")) {
3206
3250
  return option;
@@ -3225,13 +3269,14 @@ function Select(props) {
3225
3269
  };
3226
3270
  onChange?.(newEvent, newValue);
3227
3271
  };
3228
- const optionMap = useMemo8(() => {
3272
+ const optionMap = useMemo9(() => {
3229
3273
  const map = /* @__PURE__ */ new Map();
3230
3274
  options.forEach((option) => {
3231
3275
  map.set(option.value, option);
3232
3276
  });
3233
3277
  return map;
3234
3278
  }, [options]);
3279
+ const buttonSlotProps = useSlotRef(joySlotProps.button, ref);
3235
3280
  const select = /* @__PURE__ */ React21.createElement(
3236
3281
  JoySelect,
3237
3282
  {
@@ -3240,7 +3285,7 @@ function Select(props) {
3240
3285
  disabled,
3241
3286
  size,
3242
3287
  color: error ? "danger" : color,
3243
- slotProps: joySlotProps,
3288
+ slotProps: { ...joySlotProps, button: buttonSlotProps },
3244
3289
  onChange: handleChange,
3245
3290
  renderValue: (selected) => {
3246
3291
  if (!selected) return null;
@@ -3270,6 +3315,7 @@ function Select(props) {
3270
3315
  helperText && /* @__PURE__ */ React21.createElement(FormHelperText_default, { ...formHelperTextProps }, helperText)
3271
3316
  );
3272
3317
  }
3318
+ var Select = React21.forwardRef(SelectInner);
3273
3319
  Select.displayName = "Select";
3274
3320
 
3275
3321
  // src/components/Select/index.ts
@@ -3384,7 +3430,8 @@ var HeadCell = (props) => {
3384
3430
  tableColRef,
3385
3431
  headerClassName,
3386
3432
  headerLineClamp,
3387
- onAutoFit
3433
+ onAutoFit,
3434
+ columnId
3388
3435
  } = props;
3389
3436
  const theme = useTheme();
3390
3437
  const ref = headerRef;
@@ -3395,23 +3442,20 @@ var HeadCell = (props) => {
3395
3442
  }, [ref]);
3396
3443
  const [isHovered, setIsHovered] = useState8(false);
3397
3444
  const sortable = type === "actions" ? false : _sortable;
3398
- const headId = useMemo9(
3399
- () => `${tableId}_header_${headerName ?? field}`.trim(),
3400
- [tableId, headerName, field]
3401
- );
3445
+ const headId = useMemo10(() => getHeaderCellId(tableId, columnId ?? field), [tableId, columnId, field]);
3402
3446
  const isResizingRef = useRef5(false);
3403
- const resizer = useMemo9(
3447
+ const resizer = useMemo10(
3404
3448
  () => resizable ?? true ? Resizer(
3405
3449
  ref,
3406
3450
  colRef,
3407
3451
  (isResizing) => {
3408
3452
  isResizingRef.current = isResizing;
3409
3453
  },
3410
- onAutoFit ? () => onAutoFit(field) : void 0
3454
+ onAutoFit ? () => onAutoFit(columnId ?? String(field)) : void 0
3411
3455
  ) : null,
3412
- [resizable, ref, colRef, onAutoFit, field]
3456
+ [resizable, ref, colRef, onAutoFit, columnId, field]
3413
3457
  );
3414
- const style = useMemo9(
3458
+ const style = useMemo10(
3415
3459
  () => ({
3416
3460
  width,
3417
3461
  minWidth: minWidth ?? "50px",
@@ -3429,7 +3473,7 @@ var HeadCell = (props) => {
3429
3473
  );
3430
3474
  const textAlign = getTextAlign(props);
3431
3475
  const initialSort = sortOrder[0];
3432
- const sortIcon = useMemo9(() => {
3476
+ const sortIcon = useMemo10(() => {
3433
3477
  const isSorted = !!sort;
3434
3478
  const isVisible = sortable && (isSorted || isHovered);
3435
3479
  return /* @__PURE__ */ React23.createElement(AnimatePresence2, { mode: "wait" }, isVisible && /* @__PURE__ */ React23.createElement(
@@ -3460,17 +3504,17 @@ var HeadCell = (props) => {
3460
3504
  }
3461
3505
  ));
3462
3506
  }, [headId, initialSort, sort, sortable, isHovered]);
3463
- const infoSign = useMemo9(
3507
+ const infoSign = useMemo10(
3464
3508
  () => description ? /* @__PURE__ */ React23.createElement(InfoSign_default, { message: description, placement: "bottom" }) : null,
3465
3509
  [description]
3466
3510
  );
3467
- const params = useMemo9(
3511
+ const params = useMemo10(
3468
3512
  () => ({
3469
3513
  field
3470
3514
  }),
3471
3515
  [field]
3472
3516
  );
3473
- const computedHeaderClassName = useMemo9(
3517
+ const computedHeaderClassName = useMemo10(
3474
3518
  () => (typeof headerClassName === "function" ? headerClassName(params) : headerClassName) || void 0,
3475
3519
  [headerClassName, params]
3476
3520
  );
@@ -3524,7 +3568,7 @@ var BodyCell = (props) => {
3524
3568
  const theme = useTheme();
3525
3569
  const [value, setValue] = useState8(row[field]);
3526
3570
  const cellRef = useRef5(null);
3527
- const params = useMemo9(
3571
+ const params = useMemo10(
3528
3572
  () => ({
3529
3573
  row,
3530
3574
  value,
@@ -3533,20 +3577,20 @@ var BodyCell = (props) => {
3533
3577
  }),
3534
3578
  [row, rowId, value, field]
3535
3579
  );
3536
- const editMode = useMemo9(
3580
+ const editMode = useMemo10(
3537
3581
  () => !!(props.editMode && (typeof isCellEditable === "function" ? isCellEditable(params) : isCellEditable ?? true)),
3538
3582
  [props.editMode, isCellEditable, params]
3539
3583
  );
3540
3584
  const propsComponentProps = "componentProps" in props ? props.componentProps : null;
3541
3585
  const hasComponentProps = "componentProps" in props;
3542
- const componentProps = useMemo9(
3586
+ const componentProps = useMemo10(
3543
3587
  () => ({
3544
3588
  ...hasComponentProps && (typeof propsComponentProps === "function" ? propsComponentProps(params) : propsComponentProps || {}),
3545
3589
  size: "sm"
3546
3590
  }),
3547
3591
  [hasComponentProps, propsComponentProps, params]
3548
3592
  );
3549
- const editModeComponentProps = useMemo9(
3593
+ const editModeComponentProps = useMemo10(
3550
3594
  () => ({
3551
3595
  ...componentProps,
3552
3596
  onChange: (e) => {
@@ -3608,9 +3652,9 @@ var BodyCell = (props) => {
3608
3652
  }),
3609
3653
  [params, row, field, value, componentProps, type, onCellEditStop, onCellEditStart]
3610
3654
  );
3611
- const MemoizedRenderEditCell = useMemo9(() => renderEditCell ? memo(renderEditCell) : null, [renderEditCell]);
3612
- const MemoizedRenderCell = useMemo9(() => renderCell ? memo(renderCell) : null, [renderCell]);
3613
- 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(() => {
3614
3658
  if (MemoizedRenderEditCell) {
3615
3659
  return createElement(MemoizedRenderEditCell, params);
3616
3660
  }
@@ -3645,7 +3689,7 @@ var BodyCell = (props) => {
3645
3689
  }[type || "text"];
3646
3690
  }, [value, editModeComponentProps, type, MemoizedRenderEditCell, params]);
3647
3691
  const linkComponentFromProps = props.component;
3648
- const ReadModeComponent = useMemo9(() => {
3692
+ const ReadModeComponent = useMemo10(() => {
3649
3693
  if (MemoizedRenderCell) {
3650
3694
  return createElement(MemoizedRenderCell, params);
3651
3695
  }
@@ -3659,15 +3703,15 @@ var BodyCell = (props) => {
3659
3703
  return typedComponent || innerText;
3660
3704
  }, [value, MemoizedRenderCell, params, type, componentProps, linkComponentFromProps]);
3661
3705
  const getActions = props.getActions;
3662
- const CellComponent = useMemo9(() => {
3706
+ const CellComponent = useMemo10(() => {
3663
3707
  if (type === "actions") {
3664
3708
  return /* @__PURE__ */ React23.createElement(Stack_default, { direction: "row", gap: 1, justifyContent: "center", alignItems: "center" }, getActions?.(params));
3665
3709
  }
3666
3710
  return editMode && EditModeComponent ? EditModeComponent : ReadModeComponent;
3667
3711
  }, [type, getActions, params, editMode, EditModeComponent, ReadModeComponent]);
3668
- const showTooltip = useMemo9(() => noWrap && type === "longText", [noWrap, type]);
3712
+ const showTooltip = useMemo10(() => noWrap && type === "longText", [noWrap, type]);
3669
3713
  const isBoundary = props.isLastStartPinnedColumn || props.isLastEndPinnedColumn;
3670
- const computedCellClassName = useMemo9(
3714
+ const computedCellClassName = useMemo10(
3671
3715
  () => (typeof cellClassName === "function" ? cellClassName(params) : cellClassName) || "",
3672
3716
  [cellClassName, params]
3673
3717
  );
@@ -3679,7 +3723,7 @@ var BodyCell = (props) => {
3679
3723
  {
3680
3724
  ref: cellRef,
3681
3725
  key: field,
3682
- headers: `${tableId}_header_${props.headerName ?? field}`,
3726
+ headers: getHeaderCellId(tableId, props.columnId ?? field),
3683
3727
  sx: {
3684
3728
  textAlign: getTextAlign({ type }),
3685
3729
  verticalAlign: editMode ? "top" : "middle",
@@ -3691,7 +3735,7 @@ var BodyCell = (props) => {
3691
3735
  },
3692
3736
  className: [isLastStartPinnedColumn && "is-last-left", isLastEndPinnedColumn && "is-last-right", computedCellClassName].filter(Boolean).join(" ") || ""
3693
3737
  },
3694
- useMemo9(
3738
+ useMemo10(
3695
3739
  () => showTooltip ? /* @__PURE__ */ React23.createElement(CellTextEllipsis, null, CellComponent) : CellComponent,
3696
3740
  [CellComponent, showTooltip]
3697
3741
  )
@@ -3744,36 +3788,44 @@ var VirtualizedTableRow = memo(StyledTableRow2, (prevProps, nextProps) => {
3744
3788
  });
3745
3789
 
3746
3790
  // src/components/DataTable/hooks.ts
3747
- import { useState as useState9, useLayoutEffect as useLayoutEffect2, useRef as useRef6, useMemo as useMemo10, useCallback as useCallback11, useEffect as useEffect6, createRef } from "react";
3748
- 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) {
3749
3793
  const [widths, setWidths] = useState9({});
3750
3794
  const roRef = useRef6();
3751
3795
  useLayoutEffect2(() => {
3752
3796
  if (roRef.current) roRef.current.disconnect();
3753
3797
  roRef.current = new ResizeObserver((entries) => {
3754
- let changed = false;
3755
3798
  setWidths((prev) => {
3799
+ let changed = false;
3756
3800
  const next = { ...prev };
3757
3801
  entries.forEach((entry) => {
3758
- const field = entry.target.dataset.field;
3802
+ const columnId = entry.target.dataset.hdsColumnId;
3759
3803
  const w = Math.round(entry.target.getBoundingClientRect().width);
3760
- if (next[field] !== w) {
3761
- next[field] = w;
3804
+ if (next[columnId] !== w) {
3805
+ next[columnId] = w;
3762
3806
  changed = true;
3763
3807
  }
3764
3808
  });
3765
3809
  return changed ? next : prev;
3766
3810
  });
3767
3811
  });
3768
- Object.entries(columnsByField).forEach(([field, def]) => {
3812
+ const measured = {};
3813
+ Object.entries(columnsById).forEach(([columnId, def]) => {
3769
3814
  const el = def.headerRef.current;
3770
3815
  if (el) {
3771
- el.dataset.field = field;
3816
+ el.dataset.hdsColumnId = columnId;
3817
+ el.dataset.field = String(def.field);
3818
+ measured[columnId] = Math.round(el.getBoundingClientRect().width);
3772
3819
  roRef.current.observe(el);
3773
3820
  }
3774
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
+ });
3775
3827
  return () => roRef.current?.disconnect();
3776
- }, [columnsByField]);
3828
+ }, [columnsById]);
3777
3829
  return widths;
3778
3830
  }
3779
3831
  function useDataTableRenderer({
@@ -3822,16 +3874,16 @@ function useDataTableRenderer({
3822
3874
  [onColumnVisibilityModelChange]
3823
3875
  )
3824
3876
  );
3825
- const reorderedColumns = useMemo10(() => {
3877
+ const reorderedColumns = useMemo11(() => {
3826
3878
  if (!columnGroupingModel) return columnsProp;
3827
3879
  return reorderColumnsByGroupingModel(columnsProp, columnGroupingModel);
3828
3880
  }, [columnsProp, columnGroupingModel]);
3829
- const visibleColumns = useMemo10(
3881
+ const visibleColumns = useMemo11(
3830
3882
  () => reorderedColumns.filter((col) => visibilityModel[col.field] !== false),
3831
3883
  [reorderedColumns, visibilityModel]
3832
3884
  );
3833
- const visibleFieldSet = useMemo10(() => new Set(visibleColumns.map((c) => c.field)), [visibleColumns]);
3834
- const tableMinWidth = useMemo10(() => {
3885
+ const visibleFieldSet = useMemo11(() => new Set(visibleColumns.map((c) => c.field)), [visibleColumns]);
3886
+ const tableMinWidth = useMemo11(() => {
3835
3887
  const DEFAULT_MIN = 50;
3836
3888
  let total = checkboxSelection ? 40 : 0;
3837
3889
  for (const col of visibleColumns) {
@@ -3839,7 +3891,7 @@ function useDataTableRenderer({
3839
3891
  }
3840
3892
  return total;
3841
3893
  }, [visibleColumns, checkboxSelection]);
3842
- const allColumnsByField = useMemo10(
3894
+ const allColumnsByField = useMemo11(
3843
3895
  () => reorderedColumns.reduce(
3844
3896
  (acc, curr) => ({
3845
3897
  ...acc,
@@ -3849,19 +3901,34 @@ function useDataTableRenderer({
3849
3901
  ),
3850
3902
  [reorderedColumns]
3851
3903
  );
3852
- const visibleColumnsByField = useMemo10(
3853
- () => visibleColumns.reduce(
3854
- (acc, curr) => ({
3855
- ...acc,
3856
- [curr.field]: {
3857
- ...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,
3858
3926
  headerRef: createRef(),
3859
3927
  tableColRef: createRef()
3860
3928
  }
3861
- }),
3862
- {}
3929
+ ])
3863
3930
  ),
3864
- [visibleColumns]
3931
+ [visibleColumns, columnIds]
3865
3932
  );
3866
3933
  const sortComparator = useCallback11(
3867
3934
  (rowA, rowB) => {
@@ -3892,11 +3959,11 @@ function useDataTableRenderer({
3892
3959
  },
3893
3960
  [sortModel, allColumnsByField]
3894
3961
  );
3895
- const rows = useMemo10(
3962
+ const rows = useMemo11(
3896
3963
  () => sortModel.length ? [..._rows].sort(sortComparator) : _rows,
3897
3964
  [_rows, sortModel, sortComparator]
3898
3965
  );
3899
- const sortOrder = useMemo10(
3966
+ const sortOrder = useMemo11(
3900
3967
  () => Array.from(new Set(_sortOrder || ["asc", "desc", null])),
3901
3968
  [_sortOrder]
3902
3969
  );
@@ -3906,12 +3973,12 @@ function useDataTableRenderer({
3906
3973
  (row, index) => _getId?.(row) ?? row.id ?? `${(index || 0) + (page - 1) * pageSize}`,
3907
3974
  [_getId, page, pageSize]
3908
3975
  );
3909
- const selectedModelSet = useMemo10(() => new Set(selectionModel || []), [selectionModel]);
3910
- const dataInPage = useMemo10(
3976
+ const selectedModelSet = useMemo11(() => new Set(selectionModel || []), [selectionModel]);
3977
+ const dataInPage = useMemo11(
3911
3978
  () => !pagination || paginationMode === "server" ? rows : rows.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize),
3912
3979
  [rows, page, pageSize, paginationMode, pagination]
3913
3980
  );
3914
- const selectableDataInPage = useMemo10(
3981
+ const selectableDataInPage = useMemo11(
3915
3982
  () => dataInPage.filter((row, i) => {
3916
3983
  if (!isRowSelectable) return true;
3917
3984
  return isRowSelectable({ row, id: getId(row, i) });
@@ -3941,51 +4008,60 @@ function useDataTableRenderer({
3941
4008
  },
3942
4009
  [dataInPage, getId, isRowSelectable, selectionModel, onSelectionModelChange]
3943
4010
  );
3944
- const isAllSelected = useMemo10(
4011
+ const isAllSelected = useMemo11(
3945
4012
  () => selectableDataInPage.length > 0 && selectableDataInPage.every((row, i) => selectedModelSet.has(getId(row, i))),
3946
4013
  [selectableDataInPage, selectedModelSet, getId]
3947
4014
  );
3948
4015
  const rowCount = totalRowsProp || rows.length;
3949
- const selectableRowCount = useMemo10(() => {
4016
+ const selectableRowCount = useMemo11(() => {
3950
4017
  if (!isRowSelectable) return rowCount;
3951
4018
  return rows.filter((row, i) => isRowSelectable({ row, id: getId(row, i) })).length;
3952
4019
  }, [rows, isRowSelectable, getId, rowCount]);
3953
- const isTotalSelected = useMemo10(
4020
+ const isTotalSelected = useMemo11(
3954
4021
  () => _isTotalSelected ?? (selectableRowCount > 0 && (selectionModel?.length || 0) === selectableRowCount),
3955
4022
  [_isTotalSelected, selectionModel, selectableRowCount]
3956
4023
  );
3957
- 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
+ );
3958
4031
  const getWidth = useCallback11(
3959
- (f) => columnWidths[f] ?? allColumnsByField[f]?.width ?? // Column prop 으로 지정된 width
3960
- allColumnsByField[f]?.minWidth ?? 0,
3961
- [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]
3962
4036
  );
3963
- const processedColumnGroups = useMemo10(() => {
4037
+ const processedColumnGroups = useMemo11(() => {
3964
4038
  if (!columnGroupingModel) return null;
3965
4039
  return calculateColumnGroups(columnGroupingModel, visibleColumns, visibleFieldSet);
3966
4040
  }, [columnGroupingModel, visibleColumns, visibleFieldSet]);
3967
- const effectivePinnedLeft = useMemo10(
4041
+ const effectivePinnedLeft = useMemo11(
3968
4042
  () => pinnedColumns?.left?.filter((f) => visibleFieldSet.has(f)),
3969
4043
  [pinnedColumns?.left, visibleFieldSet]
3970
4044
  );
3971
- const effectivePinnedRight = useMemo10(
4045
+ const effectivePinnedRight = useMemo11(
3972
4046
  () => pinnedColumns?.right?.filter((f) => visibleFieldSet.has(f)),
3973
4047
  [pinnedColumns?.right, visibleFieldSet]
3974
4048
  );
3975
4049
  const inferredFieldsKey = JSON.stringify(Object.keys(rows[0] || {}));
3976
- const inferredFields = useMemo10(() => JSON.parse(inferredFieldsKey), [inferredFieldsKey]);
3977
- const columns = useMemo10(() => {
4050
+ const inferredFields = useMemo11(() => JSON.parse(inferredFieldsKey), [inferredFieldsKey]);
4051
+ const columns = useMemo11(() => {
3978
4052
  const baseColumns = visibleColumns.length > 0 ? visibleColumns : reorderedColumns.length > 0 ? [] : inferredFields.map((key) => ({
3979
4053
  field: key
3980
4054
  }));
3981
- return baseColumns.map((column) => {
4055
+ return baseColumns.map((column, index) => {
4056
+ const columnId = columnIds[index] ?? String(column.field);
3982
4057
  const isLeftPinned = effectivePinnedLeft?.includes(column.field);
3983
4058
  const isRightPinned = effectivePinnedRight?.includes(column.field);
3984
4059
  const isPinned = isLeftPinned || isRightPinned;
3985
4060
  return {
3986
4061
  ...column,
3987
- headerRef: visibleColumnsByField[column.field]?.headerRef,
3988
- tableColRef: visibleColumnsByField[column.field]?.tableColRef,
4062
+ columnId,
4063
+ headerRef: visibleColumnsById[columnId]?.headerRef,
4064
+ tableColRef: visibleColumnsById[columnId]?.tableColRef,
3989
4065
  isCellEditable: editMode && (typeof column.isCellEditable === "function" ? column.isCellEditable : column.isCellEditable ?? true),
3990
4066
  sort: sortModel.find((sort) => sort.field === column.field)?.sort,
3991
4067
  sortOrder: allColumnsByField[column.field]?.sortOrder || sortOrder,
@@ -4002,7 +4078,8 @@ function useDataTableRenderer({
4002
4078
  inferredFields,
4003
4079
  effectivePinnedLeft,
4004
4080
  effectivePinnedRight,
4005
- visibleColumnsByField,
4081
+ columnIds,
4082
+ visibleColumnsById,
4006
4083
  allColumnsByField,
4007
4084
  editMode,
4008
4085
  sortModel,
@@ -4062,15 +4139,14 @@ function useDataTableRenderer({
4062
4139
  }
4063
4140
  }, [_rows]);
4064
4141
  const handleAutoFit = useCallback11(
4065
- (field) => {
4066
- const colDef = visibleColumnsByField[field];
4142
+ (columnId) => {
4143
+ const colDef = visibleColumnsById[columnId];
4067
4144
  if (!colDef?.headerRef.current) return;
4068
- const column = allColumnsByField[field];
4069
- const columnType = column && "type" in column ? column.type : void 0;
4145
+ const columnType = "type" in colDef ? colDef.type : void 0;
4070
4146
  if (columnType === "actions") return;
4071
4147
  const optimalWidth = computeAutoFitWidth({
4072
4148
  headerEl: colDef.headerRef.current,
4073
- field,
4149
+ field: colDef.field,
4074
4150
  dataInPage
4075
4151
  });
4076
4152
  if (optimalWidth == null) return;
@@ -4078,7 +4154,7 @@ function useDataTableRenderer({
4078
4154
  colDef.headerRef.current.style.width = widthPx;
4079
4155
  if (colDef.tableColRef.current) colDef.tableColRef.current.style.width = widthPx;
4080
4156
  },
4081
- [visibleColumnsByField, allColumnsByField, dataInPage]
4157
+ [visibleColumnsById, dataInPage]
4082
4158
  );
4083
4159
  return {
4084
4160
  rowCount,
@@ -4553,9 +4629,9 @@ function Component(props, apiRef) {
4553
4629
  measureElement: (element) => element.clientHeight,
4554
4630
  overscan: 10
4555
4631
  });
4556
- const paginationModel = useMemo11(() => ({ page, pageSize }), [page, pageSize]);
4632
+ const paginationModel = useMemo12(() => ({ page, pageSize }), [page, pageSize]);
4557
4633
  const columnsKey = getObjectVersion(columns);
4558
- const headerCheckboxElement = useMemo11(
4634
+ const headerCheckboxElement = useMemo12(
4559
4635
  () => /* @__PURE__ */ React26.createElement(
4560
4636
  RenderCheckbox,
4561
4637
  {
@@ -4765,7 +4841,7 @@ function Component(props, apiRef) {
4765
4841
  "col",
4766
4842
  {
4767
4843
  ref: c.tableColRef,
4768
- key: `${c.field.toString()}_${c.width}`,
4844
+ key: c.columnId,
4769
4845
  style: {
4770
4846
  width: c.width,
4771
4847
  minWidth: c.minWidth ?? "50px"
@@ -4951,7 +5027,7 @@ var DataTable = forwardRef7(Component);
4951
5027
  DataTable.displayName = "DataTable";
4952
5028
 
4953
5029
  // src/components/DateRangePicker/DateRangePicker.tsx
4954
- 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";
4955
5031
  import { IMaskInput as IMaskInput2, IMask as IMask2 } from "react-imask";
4956
5032
  import CalendarTodayIcon2 from "@mui/icons-material/CalendarToday";
4957
5033
  import { styled as styled14, useThemeProps as useThemeProps7 } from "@mui/joy";
@@ -5173,7 +5249,7 @@ var DateRangePicker = forwardRef8((inProps, ref) => {
5173
5249
  );
5174
5250
  const [anchorEl, setAnchorEl] = useState10(null);
5175
5251
  const open = Boolean(anchorEl);
5176
- const calendarValue = useMemo12(
5252
+ const calendarValue = useMemo13(
5177
5253
  () => value ? parseDates(value, format) : void 0,
5178
5254
  [value, format]
5179
5255
  );
@@ -5467,10 +5543,10 @@ var ModalClose = JoyModalClose;
5467
5543
  var MotionModalOverflow = motion23(JoyModalOverflow);
5468
5544
  var ModalOverflow = MotionModalOverflow;
5469
5545
  ModalOverflow.displayName = "ModalOverflow";
5470
- function ModalFrame(props) {
5546
+ var ModalFrame = React28.forwardRef((props, ref) => {
5471
5547
  const { title, children, titleStartDecorator, onClose, ...innerProps } = props;
5472
- 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));
5473
- }
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
+ });
5474
5550
  ModalFrame.displayName = "ModalFrame";
5475
5551
 
5476
5552
  // src/components/DialogFrame/DialogFrame.tsx
@@ -5515,7 +5591,7 @@ var InsetDrawer = styled19(JoyDrawer)(({ theme }) => ({
5515
5591
  }));
5516
5592
 
5517
5593
  // src/components/FilterableCheckboxGroup/FilterableCheckboxGroup.tsx
5518
- 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";
5519
5595
  import SearchIcon from "@mui/icons-material/Search";
5520
5596
  import { useThemeProps as useThemeProps8 } from "@mui/joy";
5521
5597
  import { useVirtualizer as useVirtualizer3 } from "@tanstack/react-virtual";
@@ -5576,11 +5652,11 @@ function FilterableCheckboxGroup(inProps) {
5576
5652
  const parentRef = useRef9(null);
5577
5653
  const isInitialSortRef = useRef9(false);
5578
5654
  const prevOptionsRef = useRef9([...options]);
5579
- const filteredOptions = useMemo13(() => {
5655
+ const filteredOptions = useMemo14(() => {
5580
5656
  if (!searchTerm) return sortedOptions;
5581
5657
  return sortedOptions.filter((option) => option.label.toLowerCase().includes(searchTerm.toLowerCase()));
5582
5658
  }, [sortedOptions, searchTerm]);
5583
- const itemSize = useMemo13(() => {
5659
+ const itemSize = useMemo14(() => {
5584
5660
  switch (size) {
5585
5661
  case "sm":
5586
5662
  return 28;
@@ -5654,7 +5730,7 @@ function FilterableCheckboxGroup(inProps) {
5654
5730
  },
5655
5731
  [filteredOptions, internalValue, setInternalValue]
5656
5732
  );
5657
- const enabledFilteredOptions = useMemo13(() => filteredOptions.filter((option) => !option.disabled), [filteredOptions]);
5733
+ const enabledFilteredOptions = useMemo14(() => filteredOptions.filter((option) => !option.disabled), [filteredOptions]);
5658
5734
  const isAllSelected = enabledFilteredOptions.length > 0 && enabledFilteredOptions.every((option) => internalValue.includes(option.value));
5659
5735
  const isIndeterminate = !isAllSelected && enabledFilteredOptions.some((option) => internalValue.includes(option.value));
5660
5736
  return /* @__PURE__ */ React31.createElement("div", { style: { width: "100%" } }, /* @__PURE__ */ React31.createElement(
@@ -5843,7 +5919,7 @@ function RadioGroup2(props) {
5843
5919
  RadioGroup2.displayName = "RadioGroup";
5844
5920
 
5845
5921
  // src/components/FilterMenu/components/DateRange.tsx
5846
- 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";
5847
5923
  import { Stack as Stack5 } from "@mui/joy";
5848
5924
  function DateRange(props) {
5849
5925
  const {
@@ -5862,7 +5938,7 @@ function DateRange(props) {
5862
5938
  } = props;
5863
5939
  const [internalValue, setInternalValue] = useControlledState(value, null, onChange);
5864
5940
  const [selectedOption, setSelectedOption] = useState12("all-time");
5865
- const dateRangeOptions = useMemo14(
5941
+ const dateRangeOptions = useMemo15(
5866
5942
  () => [
5867
5943
  { label: "All Time", value: "all-time" },
5868
5944
  { label: "This Month", value: "this-month" },
@@ -5927,7 +6003,7 @@ function DateRange(props) {
5927
6003
  },
5928
6004
  [getDateRangeForOption]
5929
6005
  );
5930
- const customDateRangeValue = useMemo14(() => {
6006
+ const customDateRangeValue = useMemo15(() => {
5931
6007
  if (selectedOption === "custom" && internalValue) {
5932
6008
  return `${internalValue[0]} - ${internalValue[1]}`;
5933
6009
  }
@@ -5986,11 +6062,11 @@ function DateRange(props) {
5986
6062
  DateRange.displayName = "DateRange";
5987
6063
 
5988
6064
  // src/components/FilterMenu/components/MonthRange.tsx
5989
- import React37, { useCallback as useCallback21, useMemo as useMemo16 } from "react";
6065
+ import React37, { useCallback as useCallback21, useMemo as useMemo17 } from "react";
5990
6066
  import { Stack as Stack6 } from "@mui/joy";
5991
6067
 
5992
6068
  // src/components/MonthRangePicker/MonthRangePicker.tsx
5993
- 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";
5994
6070
  import { IMaskInput as IMaskInput3, IMask as IMask3 } from "react-imask";
5995
6071
  import CalendarTodayIcon3 from "@mui/icons-material/CalendarToday";
5996
6072
  import { styled as styled20, useThemeProps as useThemeProps9 } from "@mui/joy";
@@ -6121,7 +6197,7 @@ var MonthRangePicker = forwardRef9((inProps, ref) => {
6121
6197
  );
6122
6198
  const [anchorEl, setAnchorEl] = useState13(null);
6123
6199
  const open = Boolean(anchorEl);
6124
- const calendarValue = useMemo15(() => value ? parseDates2(value) : void 0, [value]);
6200
+ const calendarValue = useMemo16(() => value ? parseDates2(value) : void 0, [value]);
6125
6201
  useEffect11(() => {
6126
6202
  if (value) {
6127
6203
  try {
@@ -6296,7 +6372,7 @@ function MonthRange(props) {
6296
6372
  locale
6297
6373
  } = props;
6298
6374
  const [internalValue, setInternalValue] = useControlledState(value, null, onChange);
6299
- const pickerValue = useMemo16(
6375
+ const pickerValue = useMemo17(
6300
6376
  () => internalValue ? `${internalValue[0]} - ${internalValue[1]}` : "",
6301
6377
  [internalValue]
6302
6378
  );
@@ -6439,7 +6515,7 @@ import React41 from "react";
6439
6515
  import { Stack as Stack9, Typography as Typography5 } from "@mui/joy";
6440
6516
 
6441
6517
  // src/components/PercentageInput/PercentageInput.tsx
6442
- import React40, { useCallback as useCallback24, useMemo as useMemo17 } from "react";
6518
+ import React40, { useCallback as useCallback24, useMemo as useMemo18 } from "react";
6443
6519
  import { NumericFormat as NumericFormat2 } from "react-number-format";
6444
6520
  import { styled as styled21, useThemeProps as useThemeProps10 } from "@mui/joy";
6445
6521
  var padDecimal = (value, decimalScale) => {
@@ -6498,13 +6574,13 @@ var PercentageInput = React40.forwardRef(
6498
6574
  props.defaultValue ?? null,
6499
6575
  useCallback24((value2) => onChange?.({ target: { name, value: value2 } }), [onChange, name])
6500
6576
  );
6501
- const value = useMemo17(() => {
6577
+ const value = useMemo18(() => {
6502
6578
  if (_value && useMinorUnit) {
6503
6579
  return _value / Math.pow(10, maxDecimalScale);
6504
6580
  }
6505
6581
  return _value;
6506
6582
  }, [_value, useMinorUnit, maxDecimalScale]);
6507
- const internalError = useMemo17(
6583
+ const internalError = useMemo18(
6508
6584
  () => value != null && (max != null && value > max || min != null && value < min),
6509
6585
  [max, min, value]
6510
6586
  );
@@ -6764,7 +6840,7 @@ function FilterMenu(props) {
6764
6840
  FilterMenu.displayName = "FilterMenu";
6765
6841
 
6766
6842
  // src/components/Uploader/Uploader.tsx
6767
- 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";
6768
6844
  import { styled as styled22, Input as Input2 } from "@mui/joy";
6769
6845
  import MuiFileUploadIcon from "@mui/icons-material/CloudUploadRounded";
6770
6846
  import MuiUploadFileIcon from "@mui/icons-material/UploadFileRounded";
@@ -6904,8 +6980,8 @@ var Uploader = React45.memo((props) => {
6904
6980
  const [files, setFiles] = useState14([]);
6905
6981
  const [uploaded, setUploaded] = useState14(props.uploaded || []);
6906
6982
  const [previewState, setPreviewState] = useState14("idle");
6907
- const accepts = useMemo18(() => accept.split(",").map((accept2) => accept2.trim()), [accept]);
6908
- const parsedAccepts = useMemo18(
6983
+ const accepts = useMemo19(() => accept.split(",").map((accept2) => accept2.trim()), [accept]);
6984
+ const parsedAccepts = useMemo19(
6909
6985
  () => accepts.flatMap((type) => {
6910
6986
  if (["image/*", "video/*", "audio/*"].includes(type)) {
6911
6987
  return ALL_EXTENSIONS_BY_TYPE[type];
@@ -6914,7 +6990,7 @@ var Uploader = React45.memo((props) => {
6914
6990
  }),
6915
6991
  [accepts]
6916
6992
  );
6917
- const helperText = useMemo18(() => {
6993
+ const helperText = useMemo19(() => {
6918
6994
  if (helperTextProp) {
6919
6995
  return helperTextProp;
6920
6996
  }
@@ -6944,8 +7020,8 @@ var Uploader = React45.memo((props) => {
6944
7020
  }
6945
7021
  return helperTexts.join(", ");
6946
7022
  }, [accepts, maxFileTotalSize, maxCount, helperTextProp]);
6947
- const error = useMemo18(() => !!errorText || errorProp, [errorProp, errorText]);
6948
- const showDropZone = useMemo18(
7023
+ const error = useMemo19(() => !!errorText || errorProp, [errorProp, errorText]);
7024
+ const showDropZone = useMemo19(
6949
7025
  () => !maxCount || maxCount && [...uploaded, ...files].length !== maxCount,
6950
7026
  [files, maxCount, uploaded]
6951
7027
  );
@@ -7107,7 +7183,10 @@ import {
7107
7183
  MenuButton as JoyMenuButton2,
7108
7184
  IconButton as JoyIconButton2
7109
7185
  } from "@mui/joy";
7110
- 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) {
7111
7190
  const {
7112
7191
  size,
7113
7192
  icon,
@@ -7118,6 +7197,8 @@ function IconMenuButton(props) {
7118
7197
  variant = "plain",
7119
7198
  placement = "bottom"
7120
7199
  } = props;
7200
+ const { ref: buttonComponentRef, ...buttonComponentProps } = props.buttonComponentProps ?? {};
7201
+ const mergedButtonRef = useMergedRef(buttonComponentRef, ref);
7121
7202
  if (!items.length) {
7122
7203
  return /* @__PURE__ */ React46.createElement(
7123
7204
  JoyIconButton2,
@@ -7128,7 +7209,8 @@ function IconMenuButton(props) {
7128
7209
  color,
7129
7210
  disabled,
7130
7211
  loading,
7131
- ...props.buttonComponentProps ?? {}
7212
+ ...buttonComponentProps,
7213
+ ref: mergedButtonRef
7132
7214
  },
7133
7215
  icon
7134
7216
  );
@@ -7136,7 +7218,7 @@ function IconMenuButton(props) {
7136
7218
  return /* @__PURE__ */ React46.createElement(Dropdown_default, null, /* @__PURE__ */ React46.createElement(
7137
7219
  JoyMenuButton2,
7138
7220
  {
7139
- slots: { root: JoyIconButton2 },
7221
+ slots: { root: MenuButtonRootSlot },
7140
7222
  slotProps: {
7141
7223
  root: {
7142
7224
  component: props.buttonComponent ?? "button",
@@ -7145,13 +7227,16 @@ function IconMenuButton(props) {
7145
7227
  color,
7146
7228
  disabled,
7147
7229
  loading,
7148
- ...props.buttonComponentProps ?? {}
7230
+ ...buttonComponentProps,
7231
+ // Joy의 useSlot이 내부 ref와 이 ref를 합쳐준다. 위 no-items 분기와 같은 경로로 ref를 넘긴다.
7232
+ ref: mergedButtonRef
7149
7233
  }
7150
7234
  }
7151
7235
  },
7152
7236
  icon
7153
7237
  ), /* @__PURE__ */ React46.createElement(Menu, { placement, size }, items.map((i) => /* @__PURE__ */ React46.createElement(MenuItem, { key: i.text, component: i.component, ...i.componentProps ?? {} }, i.text))));
7154
7238
  }
7239
+ var IconMenuButton = React46.forwardRef(IconMenuButtonInner);
7155
7240
  IconMenuButton.displayName = "IconMenuButton";
7156
7241
 
7157
7242
  // src/components/Markdown/Markdown.tsx
@@ -7725,7 +7810,7 @@ function Navigator(props) {
7725
7810
  Navigator.displayName = "Navigator";
7726
7811
 
7727
7812
  // src/components/ProfileMenu/ProfileMenu.tsx
7728
- import React53, { useCallback as useCallback30, useMemo as useMemo19 } from "react";
7813
+ import React53, { useCallback as useCallback30, useMemo as useMemo20 } from "react";
7729
7814
  import { Dropdown as Dropdown2, ListDivider, menuItemClasses, styled as styled26, MenuButton as MenuButton3, useThemeProps as useThemeProps12 } from "@mui/joy";
7730
7815
  import { ClickAwayListener as ClickAwayListener5 } from "@mui/base";
7731
7816
  import DropdownIcon from "@mui/icons-material/ArrowDropDown";
@@ -7735,8 +7820,8 @@ var StyledProfileCard = styled26(Stack, {
7735
7820
  })({});
7736
7821
  function ProfileCard(props) {
7737
7822
  const { children, chip, caption, size } = props;
7738
- const captionLevel = useMemo19(() => size === "sm" ? "body-xs" : "body-sm", [size]);
7739
- 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]);
7740
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));
7741
7826
  }
7742
7827
  ProfileCard.displayName = "ProfileCard";