sellmate-design-system-react 2.1.2 → 2.2.0

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
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { clsx } from 'clsx';
3
3
  import { extendTailwindMerge } from 'tailwind-merge';
4
- import { forwardRef, useState, useId, useEffect, useRef, useCallback, createContext, useImperativeHandle, useMemo, useContext, useLayoutEffect, useSyncExternalStore, Fragment as Fragment$1 } from 'react';
4
+ import { forwardRef, useState, useId, useEffect, useRef, useCallback, createContext, useImperativeHandle, useMemo, useContext, Fragment as Fragment$1, useLayoutEffect, useSyncExternalStore } from 'react';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
  import { createPortal } from 'react-dom';
7
7
  import { createRoot } from 'react-dom/client';
@@ -7356,8 +7356,10 @@ var STable = forwardRef(function STable2({
7356
7356
  stickyColumn,
7357
7357
  radius = "default",
7358
7358
  noDataLabel = "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
7359
+ noDataSlot,
7359
7360
  isLoading = false,
7360
7361
  dense = false,
7362
+ noHover = false,
7361
7363
  pagination,
7362
7364
  onPageChange,
7363
7365
  useInternalPagination = false,
@@ -7443,7 +7445,10 @@ var STable = forwardRef(function STable2({
7443
7445
  );
7444
7446
  const handleScroll = useCallback(() => {
7445
7447
  const el = scrollRef.current;
7446
- if (!el) return;
7448
+ if (!el) {
7449
+ setHeaderGutter(0);
7450
+ return;
7451
+ }
7447
7452
  const header = headerScrollRef.current;
7448
7453
  if (header) header.scrollLeft = el.scrollLeft;
7449
7454
  setHeaderGutter(el.offsetWidth - el.clientWidth);
@@ -7575,6 +7580,7 @@ var STable = forwardRef(function STable2({
7575
7580
  bodyRows = rows.slice(pageInfo.startIndex, pageInfo.endIndex);
7576
7581
  }
7577
7582
  const isNoData = rowCount === 0 && !isLoading;
7583
+ const showNoDataSlot = isNoData && noDataSlot != null;
7578
7584
  const showPagination = !useVirtualScroll && (pagination != null || useInternalPagination);
7579
7585
  const lastPage = useInternalPagination ? Math.max(1, Math.ceil(rowCount / (innerRowsPerPage || 1))) : pagination?.lastPage ?? Math.max(1, Math.ceil(rowCount / (pagination?.rowsPerPage ?? 10)));
7580
7586
  const displayPage = useInternalPagination ? currentPage : pagination?.page ?? 1;
@@ -7636,6 +7642,12 @@ var STable = forwardRef(function STable2({
7636
7642
  isRightEdge && scrolledRight && "shadow-[-5px_0_8px_0_rgba(34,34,34,0.1)]"
7637
7643
  );
7638
7644
  };
7645
+ const bodyScrollClass = cn(
7646
+ "min-h-0 flex-1 overflow-auto border-t border-solid border-[color:var(--cmp-table-border-color)]",
7647
+ SCROLLBAR_CLASS,
7648
+ SCROLLBAR_TRACK_BG_CLASS,
7649
+ SCROLLBAR_TRACK_BORDER_CLASS
7650
+ );
7639
7651
  const colgroup = /* @__PURE__ */ jsxs("colgroup", { children: [
7640
7652
  selectable && /* @__PURE__ */ jsx("col", { style: { width: SELECTABLE_COLUMN_WIDTH } }),
7641
7653
  visibleCols.map((col, i) => /* @__PURE__ */ jsx("col", { style: col.autoWidth ? void 0 : { width: columnWidths[i] } }, col.name))
@@ -7757,97 +7769,106 @@ var STable = forwardRef(function STable2({
7757
7769
  )
7758
7770
  }
7759
7771
  ),
7760
- /* @__PURE__ */ jsx(
7761
- "div",
7762
- {
7763
- ref: scrollRef,
7764
- onScroll: handleScroll,
7765
- className: cn(
7766
- // 헤더 하단 구분선은 body 상단 border로 그린다. body 래퍼는 스크롤바를 포함한
7767
- // 전체 폭을 차지하므로(스크롤바는 border 안쪽) 헤더 거터의 border-right와 미터가
7768
- // 생기지 않아 색·길이가 균일한 한 줄이 된다.
7769
- "min-h-0 flex-1 overflow-auto border-t border-solid border-[color:var(--cmp-table-border-color)]",
7770
- SCROLLBAR_CLASS,
7771
- SCROLLBAR_TRACK_BG_CLASS,
7772
- SCROLLBAR_TRACK_BORDER_CLASS,
7773
- // 원본 sd-table__scroll-container--loading/--no-data: 로딩·데이터 없음 시 스크롤 차단
7774
- (isLoading || rowCount === 0) && "overflow-hidden"
7775
- ),
7776
- children: /* @__PURE__ */ jsxs(
7777
- "table",
7778
- {
7779
- className: "w-full table-fixed border-separate border-spacing-0 text-left",
7780
- style: { fontSize: 12 },
7781
- children: [
7782
- colgroup,
7783
- /* @__PURE__ */ jsxs("tbody", { children: [
7784
- useVirtualScroll && topSpacer > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": true, style: { height: topSpacer }, children: /* @__PURE__ */ jsx("td", { colSpan: totalColSpan, className: "p-0" }) }),
7785
- rowCount === 0 ? null : bodyRows.map((row, ri) => {
7786
- const isSel = selectedKeys.has(row[rowKey]);
7787
- const rowBg = "bg-white";
7788
- return /* @__PURE__ */ jsxs(
7789
- "tr",
7790
- {
7791
- onClick: () => onRowClick?.(row),
7792
- className: cn(
7793
- "group/table-row hover:bg-[var(--color-grey-05)]",
7794
- onRowClick && "cursor-pointer"
7795
- ),
7796
- style: { height: useVirtualScroll ? effectiveRowHeight : rowH },
7797
- children: [
7798
- selectable && /* @__PURE__ */ jsx(
7799
- "td",
7800
- {
7801
- className: cn(
7802
- // 원본 .td--selected: 48px 고정폭, 항상 left sticky, 체크박스 중앙정렬
7803
- "sticky left-0 z-[2] border-b border-solid border-[color:var(--cmp-table-border-color)] align-middle group-hover/table-row:bg-[var(--color-grey-05)]",
7804
- rowBg,
7805
- stickyLeft === 0 && scrolledLeft && "shadow-[5px_0_8px_0_rgba(34,34,34,0.1)]"
7806
- ),
7807
- style: {
7808
- width: SELECTABLE_COLUMN_WIDTH,
7809
- minWidth: SELECTABLE_COLUMN_WIDTH,
7810
- maxWidth: SELECTABLE_COLUMN_WIDTH
7811
- },
7812
- onClick: (e) => e.stopPropagation(),
7813
- children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(SCheckbox, { value: isSel, onValueChange: () => toggleRow(row) }) })
7814
- }
7772
+ showNoDataSlot ? /* @__PURE__ */ jsx("div", { className: cn(bodyScrollClass, "pointer-events-auto bg-white"), children: /* @__PURE__ */ jsx("div", { className: "flex h-full min-h-[60px] w-full items-center justify-center", children: noDataSlot }) }) : (
7773
+ /* 바디: 세로 스크롤은 이 컨테이너에만 생긴다 (헤더 제외) */
7774
+ /* @__PURE__ */ jsx(
7775
+ "div",
7776
+ {
7777
+ ref: scrollRef,
7778
+ onScroll: handleScroll,
7779
+ className: cn(
7780
+ bodyScrollClass,
7781
+ // 원본 sd-table__scroll-container--loading/--no-data: 로딩·데이터 없음 스크롤 차단
7782
+ (isLoading || rowCount === 0) && "overflow-hidden"
7783
+ ),
7784
+ children: /* @__PURE__ */ jsxs(
7785
+ "table",
7786
+ {
7787
+ className: "w-full table-fixed border-separate border-spacing-0 text-left",
7788
+ style: { fontSize: 12 },
7789
+ children: [
7790
+ colgroup,
7791
+ /* @__PURE__ */ jsxs("tbody", { children: [
7792
+ useVirtualScroll && topSpacer > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": true, style: { height: topSpacer }, children: /* @__PURE__ */ jsx("td", { colSpan: totalColSpan, className: "p-0" }) }),
7793
+ rowCount === 0 ? null : bodyRows.map((row, ri) => {
7794
+ const isSel = selectedKeys.has(row[rowKey]);
7795
+ const rowBg = "bg-white";
7796
+ return /* @__PURE__ */ jsxs(
7797
+ "tr",
7798
+ {
7799
+ onClick: () => onRowClick?.(row),
7800
+ className: cn(
7801
+ "group/table-row",
7802
+ !noHover && "hover:bg-[var(--color-grey-05)]",
7803
+ onRowClick && "cursor-pointer"
7815
7804
  ),
7816
- visibleCols.map((col, i) => /* @__PURE__ */ jsx(
7817
- "td",
7818
- {
7819
- className: cn(
7805
+ style: { height: useVirtualScroll ? effectiveRowHeight : rowH },
7806
+ children: [
7807
+ selectable && /* @__PURE__ */ jsx(
7808
+ "td",
7809
+ {
7810
+ className: cn(
7811
+ // 원본 .td--selected: 48px 고정폭, 항상 left sticky, 체크박스 중앙정렬
7812
+ "sticky left-0 z-[2] border-b border-solid border-[color:var(--cmp-table-border-color)] align-middle",
7813
+ rowBg,
7814
+ !noHover && "group-hover/table-row:bg-[var(--color-grey-05)]",
7815
+ stickyLeft === 0 && scrolledLeft && "shadow-[5px_0_8px_0_rgba(34,34,34,0.1)]"
7816
+ ),
7817
+ style: {
7818
+ width: SELECTABLE_COLUMN_WIDTH,
7819
+ minWidth: SELECTABLE_COLUMN_WIDTH,
7820
+ maxWidth: SELECTABLE_COLUMN_WIDTH
7821
+ },
7822
+ onClick: (e) => e.stopPropagation(),
7823
+ children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(SCheckbox, { value: isSel, onValueChange: () => toggleRow(row) }) })
7824
+ }
7825
+ ),
7826
+ visibleCols.map((col, i) => {
7827
+ const tdClassName = cn(
7820
7828
  // 원본 .td: 컬럼 폭에 맞춰 내용 말줄임(overflow hidden + ellipsis) + 행 구분선(border-b)
7821
7829
  // 셀 배경은 흰색으로 채워 뒤 배경이 비치지 않게 하고, hover 시 행 배경(grey_05)을 따른다.
7822
7830
  "overflow-hidden text-ellipsis whitespace-nowrap border-b border-solid border-[color:var(--cmp-table-border-color)] text-[12px] leading-[20px] text-[color:var(--sys-color-fg-primary)]",
7823
7831
  rowBg,
7824
- "group-hover/table-row:bg-[var(--color-grey-05)]",
7832
+ !noHover && "group-hover/table-row:bg-[var(--color-grey-05)]",
7825
7833
  stickyShadowClass(i),
7826
7834
  typeof col.tdClass === "function" ? col.tdClass(row) : col.tdClass
7827
- ),
7828
- style: {
7835
+ );
7836
+ const tdStyle = {
7829
7837
  paddingLeft: cellPadX,
7830
7838
  paddingRight: cellPadX,
7831
7839
  paddingTop: cellPadY,
7832
7840
  paddingBottom: cellPadY,
7833
7841
  textAlign: col.align ?? "left",
7834
7842
  ...cellStyle(i)
7835
- },
7836
- children: col.render ? col.render(row, cellValue(col, row)) : cellValue(col, row)
7837
- },
7838
- col.name
7839
- ))
7840
- ]
7841
- },
7842
- row[rowKey] ?? ri
7843
- );
7844
- }),
7845
- useVirtualScroll && bottomSpacer > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": true, style: { height: bottomSpacer }, children: /* @__PURE__ */ jsx("td", { colSpan: totalColSpan, className: "p-0" }) })
7846
- ] })
7847
- ]
7848
- }
7849
- )
7850
- }
7843
+ };
7844
+ if (col.renderCell) {
7845
+ const cell = col.renderCell({
7846
+ row,
7847
+ value: cellValue(col, row),
7848
+ column: col,
7849
+ colIndex: i,
7850
+ rowIndex: ri,
7851
+ isSelected: isSel,
7852
+ className: tdClassName,
7853
+ style: tdStyle
7854
+ });
7855
+ if (cell == null || cell === false) return null;
7856
+ return /* @__PURE__ */ jsx(Fragment$1, { children: cell }, col.name);
7857
+ }
7858
+ return /* @__PURE__ */ jsx("td", { className: tdClassName, style: tdStyle, children: col.render ? col.render(row, cellValue(col, row)) : cellValue(col, row) }, col.name);
7859
+ })
7860
+ ]
7861
+ },
7862
+ row[rowKey] ?? ri
7863
+ );
7864
+ }),
7865
+ useVirtualScroll && bottomSpacer > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": true, style: { height: bottomSpacer }, children: /* @__PURE__ */ jsx("td", { colSpan: totalColSpan, className: "p-0" }) })
7866
+ ] })
7867
+ ]
7868
+ }
7869
+ )
7870
+ }
7871
+ )
7851
7872
  ),
7852
7873
  isNoData && /* @__PURE__ */ jsxs(Fragment, { children: [
7853
7874
  /* @__PURE__ */ jsx(
@@ -7857,7 +7878,7 @@ var STable = forwardRef(function STable2({
7857
7878
  className: "pointer-events-none absolute left-0 right-0 top-0 z-[31] h-[var(--cmp-table-header-height)] bg-white/60"
7858
7879
  }
7859
7880
  ),
7860
- /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute bottom-0 left-0 right-0 top-[var(--cmp-table-header-height)] z-[30] flex items-center justify-center bg-white/60 text-[12px] text-[color:var(--color-grey-65)]", children: /* @__PURE__ */ jsx("div", { className: "flex min-h-[60px] w-full items-center justify-center", children: noDataLabel }) })
7881
+ !showNoDataSlot && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute bottom-0 left-0 right-0 top-[var(--cmp-table-header-height)] z-[30] flex items-center justify-center bg-white/60 text-[12px] text-[color:var(--color-grey-65)]", children: /* @__PURE__ */ jsx("div", { className: "flex min-h-[60px] w-full items-center justify-center", children: noDataLabel }) })
7861
7882
  ] }),
7862
7883
  isLoading && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-white/60", children: /* @__PURE__ */ jsx(SCircleProgress, { indeterminate: true }) })
7863
7884
  ]