sellmate-design-system-react 9.0.0-beta.88 → 9.0.0-beta.89

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
@@ -16728,6 +16728,7 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
16728
16728
  onContextMenuItemClick,
16729
16729
  isRowSelectable,
16730
16730
  isRowIndeterminate,
16731
+ rowClassName,
16731
16732
  selected = [],
16732
16733
  onSelectedChange,
16733
16734
  sort = null,
@@ -17624,7 +17625,8 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
17624
17625
  "group/table-row",
17625
17626
  rowHover && "hover:bg-[var(--color-grey-05)]",
17626
17627
  (onRowClick || onRowDoubleClick) && "cursor-pointer",
17627
- dragSelectOn && "select-none"
17628
+ dragSelectOn && "select-none",
17629
+ rowClassName?.(row)
17628
17630
  ),
17629
17631
  style: { height: virtualScroll ? effectiveRowHeight : rowH },
17630
17632
  children: [
@@ -17904,6 +17906,8 @@ var STableBar = /* @__PURE__ */ forwardRef(function STableBar2({ title, total, s
17904
17906
  }
17905
17907
  );
17906
17908
  });
17909
+ var NO_KEYS = /* @__PURE__ */ new Set();
17910
+ var ROW_ENTER_MS = 200;
17907
17911
  function STreeTable({
17908
17912
  rows = [],
17909
17913
  columns = [],
@@ -17916,6 +17920,7 @@ function STreeTable({
17916
17920
  onExpandedChange,
17917
17921
  selectable = false,
17918
17922
  isRowSelectable,
17923
+ rowClassName,
17919
17924
  selected = [],
17920
17925
  onSelectedChange,
17921
17926
  ...rest
@@ -17960,6 +17965,21 @@ function STreeTable({
17960
17965
  walk(rows);
17961
17966
  return out;
17962
17967
  }, [rows, expandedSet, rowKey, childrenKey]);
17968
+ const [enteringKeys, setEnteringKeys] = useState(NO_KEYS);
17969
+ const prevVisibleRef = useRef(null);
17970
+ useIsomorphicLayoutEffect(() => {
17971
+ const keys = new Set(visibleRows.map(keyOf));
17972
+ const prev = prevVisibleRef.current;
17973
+ prevVisibleRef.current = { rows, keys };
17974
+ if (!prev || prev.rows !== rows) return;
17975
+ const added = [...keys].filter((key) => !prev.keys.has(key));
17976
+ if (added.length > 0) setEnteringKeys(new Set(added));
17977
+ }, [visibleRows]);
17978
+ useEffect(() => {
17979
+ if (enteringKeys.size === 0) return;
17980
+ const timer = setTimeout(() => setEnteringKeys(NO_KEYS), ROW_ENTER_MS);
17981
+ return () => clearTimeout(timer);
17982
+ }, [enteringKeys]);
17963
17983
  const collectSelectable = (row) => canSelectRow(row) ? [row, ...childrenOf(row).flatMap(collectSelectable)] : [];
17964
17984
  const selectionOf = (keys) => {
17965
17985
  const state2 = /* @__PURE__ */ new Map();
@@ -18018,16 +18038,31 @@ function STreeTable({
18018
18038
  }
18019
18039
  return {
18020
18040
  ...col,
18021
- render: (row, value) => {
18041
+ // 셀 전체를 펼침 영역으로 쓰려면 <td> 에 손을 대야 해서 render 가 아니라 renderCell 로 그린다.
18042
+ // 소비 앱의 render 는 그 안쪽 내용 자리에 그대로 들어간다.
18043
+ renderCell: ({ row, value, className, style }) => {
18022
18044
  const entry = entries4.get(keyOf(row));
18045
+ const hasChildren = (entry?.children.length ?? 0) > 0;
18023
18046
  return /* @__PURE__ */ jsx(
18024
- TreeCell,
18047
+ "td",
18025
18048
  {
18026
- depth: entry?.depth ?? 0,
18027
- hasChildren: (entry?.children.length ?? 0) > 0,
18028
- expanded: expandedSet.has(keyOf(row)),
18029
- onToggle: () => toggleExpanded(row),
18030
- children: col.render ? col.render(row, value) : value
18049
+ className: cn(className, hasChildren && "cursor-pointer"),
18050
+ style,
18051
+ onClick: hasChildren ? (event) => {
18052
+ if (isOwnControl(event.target, event.currentTarget)) return;
18053
+ event.stopPropagation();
18054
+ toggleExpanded(row);
18055
+ } : void 0,
18056
+ onDoubleClick: hasChildren ? (event) => event.stopPropagation() : void 0,
18057
+ children: /* @__PURE__ */ jsx(
18058
+ TreeCell,
18059
+ {
18060
+ depth: entry?.depth ?? 0,
18061
+ hasChildren,
18062
+ expanded: expandedSet.has(keyOf(row)),
18063
+ children: col.render ? col.render(row, value) : value
18064
+ }
18065
+ )
18031
18066
  }
18032
18067
  );
18033
18068
  }
@@ -18047,16 +18082,27 @@ function STreeTable({
18047
18082
  selectable,
18048
18083
  isRowSelectable,
18049
18084
  isRowIndeterminate: selectionState ? (row) => !!selectionState.get(keyOf(row))?.indeterminate : void 0,
18085
+ rowClassName: (row) => cn(
18086
+ rowClassName?.(row),
18087
+ // 위에서 4px 내려오며 나타난다(theme.css --animate-table-row-in). 모션을 줄인 환경에서는 끈다
18088
+ enteringKeys.has(keyOf(row)) && "motion-safe:animate-table-row-in"
18089
+ ) || void 0,
18050
18090
  selected: tableSelected,
18051
18091
  onSelectedChange: handleSelectedChange
18052
18092
  }
18053
18093
  );
18054
18094
  }
18095
+ var OWN_CONTROL_SELECTOR = 'a, button, input, select, textarea, label, [role="button"], [role="checkbox"], [contenteditable="true"]';
18096
+ function isOwnControl(target, cell) {
18097
+ if (!(target instanceof Element)) return false;
18098
+ if (target.closest("[data-tree-toggle]")) return false;
18099
+ const control = target.closest(OWN_CONTROL_SELECTOR);
18100
+ return control != null && cell.contains(control);
18101
+ }
18055
18102
  function TreeCell({
18056
18103
  depth,
18057
18104
  hasChildren,
18058
18105
  expanded,
18059
- onToggle,
18060
18106
  children
18061
18107
  }) {
18062
18108
  return /* @__PURE__ */ jsxs(
@@ -18067,18 +18113,17 @@ function TreeCell({
18067
18113
  paddingLeft: `calc(${depth} * (var(--cmp-ghostButton-xxs-size) + var(--cmp-tree-item-contentGap)))`
18068
18114
  },
18069
18115
  children: [
18070
- hasChildren ? /* @__PURE__ */ jsx(
18071
- SGhostButton,
18072
- {
18073
- icon: expanded ? "caretDown" : "caretRight",
18074
- size: "xxs",
18075
- ariaLabel: expanded ? "collapse row" : "expand row",
18076
- ariaExpanded: expanded,
18077
- onClick: (event) => {
18078
- event.stopPropagation();
18079
- onToggle();
18116
+ hasChildren ? (
18117
+ // 누르면(키보드 Enter·Space 포함) 클릭이 셀로 올라가 셀이 접고 편다 — 버튼은 따로 처리하지 않는다
18118
+ /* @__PURE__ */ jsx("span", { "data-tree-toggle": true, className: "flex shrink-0", children: /* @__PURE__ */ jsx(
18119
+ SGhostButton,
18120
+ {
18121
+ icon: expanded ? "caretDown" : "caretRight",
18122
+ size: "xxs",
18123
+ ariaLabel: expanded ? "collapse row" : "expand row",
18124
+ ariaExpanded: expanded
18080
18125
  }
18081
- }
18126
+ ) })
18082
18127
  ) : (
18083
18128
  // 하위 행이 없는 행도 버튼 자리를 비워 형제끼리 내용의 시작점을 맞춘다
18084
18129
  /* @__PURE__ */ jsx("span", { className: "size-(--cmp-ghostButton-xxs-size) shrink-0", "aria-hidden": "true" })
@@ -23165,7 +23210,8 @@ function SRadioButton({
23165
23210
  ].join(" "),
23166
23211
  background: od ? "var(--cmp-radioButton-bg-disabled)" : ro ? "var(--cmp-radioButton-bg-readOnly)" : "var(--cmp-radioButton-bg-default)",
23167
23212
  borderColor: od ? "var(--cmp-radioButton-border-disabled)" : selected ? ro ? "var(--cmp-radioButton-border-readOnly)" : "var(--cmp-radioButton-border-select)" : "var(--cmp-radioButton-border-default)",
23168
- color: od || ro && !selected ? "var(--cmp-radioButton-content-disabled)" : selected && !ro ? "var(--cmp-radioButton-content-select)" : "var(--cmp-radioButton-content-default)"
23213
+ color: od || ro && !selected ? "var(--cmp-radioButton-content-disabled)" : selected && !ro ? "var(--cmp-radioButton-content-select)" : "var(--cmp-radioButton-content-default)",
23214
+ opacity: ro && !selected ? "var(--opacity-060)" : void 0
23169
23215
  },
23170
23216
  children: o.label
23171
23217
  },