sellmate-design-system-react 9.0.0-beta.25 → 9.0.0-beta.26
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/components/SChipFilter/README.md +5 -5
- package/dist/components/SChipFilter/SChipFilter.d.ts +10 -6
- package/dist/components/STable/README.md +16 -0
- package/dist/components/STable/STable.d.ts +12 -0
- package/dist/components/STable/index.d.ts +1 -1
- package/dist/index.cjs +272 -142
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +272 -142
- package/dist/index.js.map +1 -1
- package/dist/llms-full.txt +21 -5
- package/dist/styles.css +4 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11478,6 +11478,7 @@ var colWidthFromDef = (c) => {
|
|
|
11478
11478
|
};
|
|
11479
11479
|
var STable = /* @__PURE__ */ forwardRef(function STable2({
|
|
11480
11480
|
columns = [],
|
|
11481
|
+
headerGroups,
|
|
11481
11482
|
rows = [],
|
|
11482
11483
|
rowKey = "id",
|
|
11483
11484
|
selectable = false,
|
|
@@ -11525,6 +11526,49 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
|
|
|
11525
11526
|
onDenseChange?.(next);
|
|
11526
11527
|
};
|
|
11527
11528
|
const visibleCols = useMemo(() => columns.filter((c) => c.visible !== false), [columns]);
|
|
11529
|
+
const headerGroupInfo = useMemo(() => {
|
|
11530
|
+
if (!headerGroups || headerGroups.length === 0) return null;
|
|
11531
|
+
const indexByName = new Map(visibleCols.map((col, index) => [col.name, index]));
|
|
11532
|
+
const covered = /* @__PURE__ */ new Set();
|
|
11533
|
+
let previousLast = -1;
|
|
11534
|
+
const cells = headerGroups.map((group) => {
|
|
11535
|
+
if (group.columnNames.length === 0) {
|
|
11536
|
+
throw new Error("[STable] headerGroups\uC758 columnNames\uB294 \uBE44\uC5B4 \uC788\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
11537
|
+
}
|
|
11538
|
+
const indexes = group.columnNames.map((name) => {
|
|
11539
|
+
const index = indexByName.get(name);
|
|
11540
|
+
if (index == null) {
|
|
11541
|
+
throw new Error(`[STable] headerGroups\uC5D0 \uC874\uC7AC\uD558\uC9C0 \uC54A\uB294 \uCEEC\uB7FC\uC774 \uC9C0\uC815\uB418\uC5C8\uC2B5\uB2C8\uB2E4: ${name}`);
|
|
11542
|
+
}
|
|
11543
|
+
if (covered.has(name)) {
|
|
11544
|
+
throw new Error(`[STable] headerGroups\uC5D0\uC11C \uCEEC\uB7FC\uC774 \uC911\uBCF5 \uC9C0\uC815\uB418\uC5C8\uC2B5\uB2C8\uB2E4: ${name}`);
|
|
11545
|
+
}
|
|
11546
|
+
covered.add(name);
|
|
11547
|
+
return index;
|
|
11548
|
+
});
|
|
11549
|
+
const first = indexes[0];
|
|
11550
|
+
const last = indexes[indexes.length - 1];
|
|
11551
|
+
if (last - first + 1 !== indexes.length || indexes.some((index, i) => index !== first + i)) {
|
|
11552
|
+
throw new Error(
|
|
11553
|
+
"[STable] headerGroups\uC758 columnNames\uB294 \uC778\uC811\uD55C \uCEEC\uB7FC \uC21C\uC11C\uB85C \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4."
|
|
11554
|
+
);
|
|
11555
|
+
}
|
|
11556
|
+
if (first <= previousLast) {
|
|
11557
|
+
throw new Error("[STable] headerGroups\uB294 \uCEEC\uB7FC \uC21C\uC11C\uB300\uB85C \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4.");
|
|
11558
|
+
}
|
|
11559
|
+
previousLast = last;
|
|
11560
|
+
return { ...group, firstIndex: first, colSpan: indexes.length };
|
|
11561
|
+
});
|
|
11562
|
+
if (covered.size !== visibleCols.length) {
|
|
11563
|
+
throw new Error("[STable] headerGroups\uC758 columnNames\uAC00 \uBAA8\uB4E0 visible \uCEEC\uB7FC\uC744 \uD3EC\uD568\uD574\uC57C \uD569\uB2C8\uB2E4.");
|
|
11564
|
+
}
|
|
11565
|
+
return {
|
|
11566
|
+
cells,
|
|
11567
|
+
rowSpanNames: new Set(
|
|
11568
|
+
cells.filter((cell) => cell.rowSpan === 2).flatMap((cell) => cell.columnNames)
|
|
11569
|
+
)
|
|
11570
|
+
};
|
|
11571
|
+
}, [headerGroups, visibleCols]);
|
|
11528
11572
|
const stickyLeft = stickyColumn?.left ?? 0;
|
|
11529
11573
|
const stickyRight = stickyColumn?.right ?? 0;
|
|
11530
11574
|
const effectiveRowHeight = rowHeight ?? (innerDense ? DENSE_ROW_HEIGHT : DEFAULT_ROW_HEIGHT);
|
|
@@ -11787,6 +11831,35 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
|
|
|
11787
11831
|
isRightEdge && scrolledRight && "shadow-[-5px_0_8px_0_rgba(34,34,34,0.1)]"
|
|
11788
11832
|
);
|
|
11789
11833
|
};
|
|
11834
|
+
const headerResizeHitArea = (i, key) => {
|
|
11835
|
+
const col = visibleCols[i];
|
|
11836
|
+
if (!headerGroupInfo || !resizable || !col || col.autoWidth || i >= visibleCols.length - 1) {
|
|
11837
|
+
return null;
|
|
11838
|
+
}
|
|
11839
|
+
return /* @__PURE__ */ jsx(
|
|
11840
|
+
"span",
|
|
11841
|
+
{
|
|
11842
|
+
onMouseDown: (e) => startResize(i, e),
|
|
11843
|
+
className: "absolute inset-y-0 right-0 z-[5] w-[9px] cursor-col-resize",
|
|
11844
|
+
"aria-hidden": true
|
|
11845
|
+
},
|
|
11846
|
+
key
|
|
11847
|
+
);
|
|
11848
|
+
};
|
|
11849
|
+
const headerResizer = (i, key) => {
|
|
11850
|
+
const col = visibleCols[i];
|
|
11851
|
+
if (!resizable || !col || col.autoWidth || i >= visibleCols.length - 1) return null;
|
|
11852
|
+
return /* @__PURE__ */ jsx(
|
|
11853
|
+
"span",
|
|
11854
|
+
{
|
|
11855
|
+
onMouseDown: (e) => startResize(i, e),
|
|
11856
|
+
className: "absolute right-0 top-1/2 z-[5] flex h-[16px] w-[9px] -translate-y-1/2 cursor-col-resize items-center justify-end",
|
|
11857
|
+
"aria-hidden": true,
|
|
11858
|
+
children: /* @__PURE__ */ jsx("span", { className: "h-full w-[4px] border-x border-solid border-[color:var(--cmp-table-header-resizingBar-color)]" })
|
|
11859
|
+
},
|
|
11860
|
+
key
|
|
11861
|
+
);
|
|
11862
|
+
};
|
|
11790
11863
|
const bodyScrollClass = cn(
|
|
11791
11864
|
"min-h-0 flex-1 overflow-auto border-t border-solid border-[color:var(--cmp-table-border-color)]",
|
|
11792
11865
|
SCROLLBAR_CLASS,
|
|
@@ -11851,145 +11924,179 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
|
|
|
11851
11924
|
style: { fontSize: 12 },
|
|
11852
11925
|
children: [
|
|
11853
11926
|
colgroup,
|
|
11854
|
-
/* @__PURE__ */
|
|
11855
|
-
|
|
11856
|
-
|
|
11857
|
-
|
|
11858
|
-
|
|
11859
|
-
|
|
11860
|
-
|
|
11861
|
-
|
|
11862
|
-
|
|
11863
|
-
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
11927
|
+
/* @__PURE__ */ jsxs("thead", { className: cn(isNoData && "opacity-40"), children: [
|
|
11928
|
+
headerGroupInfo && /* @__PURE__ */ jsxs("tr", { className: "h-[var(--cmp-table-header-height)] bg-[var(--cmp-table-header-bg)]", children: [
|
|
11929
|
+
selectable && /* @__PURE__ */ jsx(
|
|
11930
|
+
"th",
|
|
11931
|
+
{
|
|
11932
|
+
rowSpan: 2,
|
|
11933
|
+
className: cn(
|
|
11934
|
+
"sticky left-0 z-[7] bg-[var(--cmp-table-header-bg)] text-center align-middle",
|
|
11935
|
+
stickyLeft === 0 && scrolledLeft && "shadow-[5px_0_8px_0_rgba(34,34,34,0.1)]"
|
|
11936
|
+
),
|
|
11937
|
+
style: {
|
|
11938
|
+
width: SELECTABLE_COLUMN_WIDTH,
|
|
11939
|
+
minWidth: SELECTABLE_COLUMN_WIDTH,
|
|
11940
|
+
maxWidth: SELECTABLE_COLUMN_WIDTH
|
|
11941
|
+
},
|
|
11942
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(SCheckbox, { value: headerCheck, onValueChange: toggleAll }) })
|
|
11943
|
+
}
|
|
11944
|
+
),
|
|
11945
|
+
headerGroupInfo.cells.map((group) => /* @__PURE__ */ jsxs(
|
|
11946
|
+
"th",
|
|
11947
|
+
{
|
|
11948
|
+
colSpan: group.colSpan,
|
|
11949
|
+
rowSpan: group.rowSpan,
|
|
11950
|
+
className: cn(
|
|
11951
|
+
"relative border-b border-r border-solid border-[color:var(--cmp-table-border-color)] bg-[var(--cmp-table-header-bg)] px-[16px] text-[12px] font-medium leading-[20px] text-[color:var(--sys-color-fg-primary)]",
|
|
11952
|
+
group.firstIndex + group.colSpan === visibleCols.length && "border-r-0",
|
|
11953
|
+
group.rowSpan === 2 && "border-b-0",
|
|
11954
|
+
group.className
|
|
11955
|
+
),
|
|
11956
|
+
style: { textAlign: group.align ?? "left", ...group.style },
|
|
11957
|
+
children: [
|
|
11958
|
+
group.render ? group.render() : group.label,
|
|
11959
|
+
group.rowSpan === 2 && group.colSpan === 1 ? headerResizeHitArea(
|
|
11960
|
+
group.firstIndex,
|
|
11961
|
+
`group-resizer-${group.columnNames[0]}`
|
|
11962
|
+
) : null
|
|
11963
|
+
]
|
|
11868
11964
|
},
|
|
11869
|
-
|
|
11870
|
-
|
|
11871
|
-
|
|
11872
|
-
|
|
11873
|
-
|
|
11874
|
-
"aria-hidden": true,
|
|
11875
|
-
className: "pointer-events-none absolute right-0 top-1/2 h-[16px] w-px -translate-y-1/2 bg-[var(--cmp-table-header-resizingBar-color)]"
|
|
11876
|
-
}
|
|
11877
|
-
)
|
|
11878
|
-
]
|
|
11879
|
-
}
|
|
11880
|
-
),
|
|
11881
|
-
visibleCols.map((col, i) => {
|
|
11882
|
-
const isSortable = !!col.sortable && !col.renderHeader;
|
|
11883
|
-
const sortDir = isSortable && sort?.name === col.name ? sort.dir : void 0;
|
|
11884
|
-
return /* @__PURE__ */ jsxs(
|
|
11965
|
+
group.columnNames.join("|")
|
|
11966
|
+
))
|
|
11967
|
+
] }),
|
|
11968
|
+
/* @__PURE__ */ jsxs("tr", { className: "h-[var(--cmp-table-header-height)] bg-[var(--cmp-table-header-bg)]", children: [
|
|
11969
|
+
selectable && !headerGroupInfo && /* @__PURE__ */ jsxs(
|
|
11885
11970
|
"th",
|
|
11886
11971
|
{
|
|
11887
11972
|
className: cn(
|
|
11888
|
-
//
|
|
11889
|
-
//
|
|
11890
|
-
|
|
11891
|
-
|
|
11892
|
-
// 세로 가운데도 어긋난다. 글자 줄높이는 아래 th__content 가 다시 준다.
|
|
11893
|
-
"relative bg-[var(--cmp-table-header-bg)] px-[16px] text-[12px] font-medium leading-[0] text-[color:var(--sys-color-fg-primary)]",
|
|
11894
|
-
stickyInfo(i).isSticky && "z-[6]",
|
|
11895
|
-
stickyShadowClass(i),
|
|
11896
|
-
col.thClass
|
|
11973
|
+
// 원본 .th--selected: 48px 고정폭, 항상 left sticky, 체크박스 중앙정렬
|
|
11974
|
+
// 하단 border는 헤더 래퍼가 연속으로 그리므로 셀에는 두지 않는다.
|
|
11975
|
+
"sticky left-0 z-[7] bg-[var(--cmp-table-header-bg)] text-center align-middle",
|
|
11976
|
+
stickyLeft === 0 && scrolledLeft && "shadow-[5px_0_8px_0_rgba(34,34,34,0.1)]"
|
|
11897
11977
|
),
|
|
11898
|
-
style: {
|
|
11899
|
-
|
|
11978
|
+
style: {
|
|
11979
|
+
width: SELECTABLE_COLUMN_WIDTH,
|
|
11980
|
+
minWidth: SELECTABLE_COLUMN_WIDTH,
|
|
11981
|
+
maxWidth: SELECTABLE_COLUMN_WIDTH
|
|
11982
|
+
},
|
|
11900
11983
|
children: [
|
|
11984
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(SCheckbox, { value: headerCheck, onValueChange: toggleAll }) }),
|
|
11901
11985
|
/* @__PURE__ */ jsx(
|
|
11902
11986
|
"span",
|
|
11903
11987
|
{
|
|
11904
|
-
className: cn(
|
|
11905
|
-
// 원본 th__content: align에 따라 justify-content 적용 (th도 정렬 반영)
|
|
11906
|
-
// th 가 leading-[0] 이므로 글자 줄높이는 여기서 준다 (truncate 가
|
|
11907
|
-
// overflow-hidden 이라 줄높이가 0이면 라벨이 잘려 사라진다).
|
|
11908
|
-
"inline-flex w-full min-w-0 items-center gap-[4px] leading-[20px]",
|
|
11909
|
-
col.align === "center" && "justify-center",
|
|
11910
|
-
col.align === "right" && "justify-end"
|
|
11911
|
-
),
|
|
11912
|
-
children: col.renderHeader ? col.renderHeader(col, i) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
11913
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: col.label }),
|
|
11914
|
-
col.helpText && col.helpText.length > 0 && // 라벨이 좁아져 truncate 되더라도 아이콘까지 함께 줄어들면 안 되므로
|
|
11915
|
-
// shrink-0 래퍼로 감싼다 (STooltip 의 className 은 본문 쪽으로 간다).
|
|
11916
|
-
// 아이콘·크기·색은 SKeyValueTable 헤더 도움말과 동일하게 맞춘다.
|
|
11917
|
-
/* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", children: /* @__PURE__ */ jsx(
|
|
11918
|
-
STooltip2,
|
|
11919
|
-
{
|
|
11920
|
-
trigger: "hover",
|
|
11921
|
-
icon: "helpOutline",
|
|
11922
|
-
iconSize: 12,
|
|
11923
|
-
color: "var(--sys-color-fg-success)",
|
|
11924
|
-
placement: "top",
|
|
11925
|
-
message: col.helpText
|
|
11926
|
-
}
|
|
11927
|
-
) }),
|
|
11928
|
-
col.editable && /* @__PURE__ */ jsx(
|
|
11929
|
-
SIcon,
|
|
11930
|
-
{
|
|
11931
|
-
name: "pageEdit",
|
|
11932
|
-
size: 12,
|
|
11933
|
-
color: "var(--sys-color-link-accent)",
|
|
11934
|
-
label: "\uC218\uC815 \uAC00\uB2A5",
|
|
11935
|
-
className: "shrink-0"
|
|
11936
|
-
}
|
|
11937
|
-
),
|
|
11938
|
-
col.navigable && /* @__PURE__ */ jsx(
|
|
11939
|
-
SIcon,
|
|
11940
|
-
{
|
|
11941
|
-
name: "pageMove",
|
|
11942
|
-
size: 12,
|
|
11943
|
-
color: "var(--sys-color-link-accent)",
|
|
11944
|
-
label: "\uB2E4\uB978 \uD654\uBA74\uC73C\uB85C \uC774\uB3D9",
|
|
11945
|
-
className: "shrink-0"
|
|
11946
|
-
}
|
|
11947
|
-
),
|
|
11948
|
-
col.required && // 라벨이 truncate 돼도 필수 표시는 남아야 하므로 shrink-0.
|
|
11949
|
-
// 아이콘·크기·색은 SKeyValueTable 헤더 필수 표시와 동일하게 맞춘다.
|
|
11950
|
-
/* @__PURE__ */ jsx(
|
|
11951
|
-
SIcon,
|
|
11952
|
-
{
|
|
11953
|
-
name: "asterisk",
|
|
11954
|
-
size: 12,
|
|
11955
|
-
color: "var(--sys-color-fg-accent)",
|
|
11956
|
-
className: "shrink-0"
|
|
11957
|
-
}
|
|
11958
|
-
),
|
|
11959
|
-
isSortable && // 미정렬은 updown 을 default(회색)로 — 정렬할 수 있다는 것 자체가
|
|
11960
|
-
// 헤더에 보여야 한다. 정렬 중이면 action 색으로 올려 활성임을 알린다.
|
|
11961
|
-
// 라벨이 truncate 돼도 버튼은 남도록 shrink-0.
|
|
11962
|
-
/* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", children: /* @__PURE__ */ jsx(
|
|
11963
|
-
SGhostButton,
|
|
11964
|
-
{
|
|
11965
|
-
size: "xxs",
|
|
11966
|
-
intent: sortDir ? "action" : "default",
|
|
11967
|
-
icon: sortDir === "asc" ? "arrowUp" : sortDir === "desc" ? "arrowDown" : "updown",
|
|
11968
|
-
ariaLabel: `${col.label} \uC815\uB82C`,
|
|
11969
|
-
onClick: () => toggleSort(col)
|
|
11970
|
-
}
|
|
11971
|
-
) })
|
|
11972
|
-
] })
|
|
11973
|
-
}
|
|
11974
|
-
),
|
|
11975
|
-
resizable && !col.autoWidth && i < visibleCols.length - 1 && // 원본 th__resizer: 셀 우측 경계 안쪽 4px 그립(좌우 1px #CCCCCC 라인, 세로 16px).
|
|
11976
|
-
// 셀 밖으로 넘치면 다음 셀에 가려져 클릭이 안 먹으므로 translate 없이 셀 내부에 배치.
|
|
11977
|
-
// 겉보기 그립은 4px(원본과 동일), 클릭 영역은 9px로 넓혀 사용성 확보.
|
|
11978
|
-
/* @__PURE__ */ jsx(
|
|
11979
|
-
"span",
|
|
11980
|
-
{
|
|
11981
|
-
onMouseDown: (e) => startResize(i, e),
|
|
11982
|
-
className: "absolute right-0 top-1/2 z-[5] flex h-[16px] w-[9px] -translate-y-1/2 cursor-col-resize items-center justify-end",
|
|
11983
11988
|
"aria-hidden": true,
|
|
11984
|
-
|
|
11989
|
+
className: "pointer-events-none absolute right-0 top-1/2 h-[16px] w-px -translate-y-1/2 bg-[var(--cmp-table-header-resizingBar-color)]"
|
|
11985
11990
|
}
|
|
11986
11991
|
)
|
|
11987
11992
|
]
|
|
11988
|
-
}
|
|
11989
|
-
|
|
11990
|
-
)
|
|
11991
|
-
|
|
11992
|
-
|
|
11993
|
+
}
|
|
11994
|
+
),
|
|
11995
|
+
visibleCols.map((col, i) => {
|
|
11996
|
+
if (headerGroupInfo?.rowSpanNames.has(col.name)) return null;
|
|
11997
|
+
const isSortable = !!col.sortable && !col.renderHeader;
|
|
11998
|
+
const sortDir = isSortable && sort?.name === col.name ? sort.dir : void 0;
|
|
11999
|
+
return /* @__PURE__ */ jsxs(
|
|
12000
|
+
"th",
|
|
12001
|
+
{
|
|
12002
|
+
className: cn(
|
|
12003
|
+
// 하단 border는 헤더 래퍼가 연속으로 그린다 (거터 영역까지 이어짐).
|
|
12004
|
+
// leading-[0]: th 의 스트럿(line-height 만큼의 빈 인라인 박스)을 없앤다.
|
|
12005
|
+
// 내용이 inline-flex 라 스트럿이 남아 있으면 라벨보다 큰 컨트롤(정렬 버튼 등)이
|
|
12006
|
+
// 들어올 때 줄 상자가 베이스라인 기준으로 늘어나 헤더 높이를 넘기고
|
|
12007
|
+
// 세로 가운데도 어긋난다. 글자 줄높이는 아래 th__content 가 다시 준다.
|
|
12008
|
+
headerGroupInfo && "border-r border-solid border-[color:var(--cmp-table-border-color)]",
|
|
12009
|
+
headerGroupInfo && i === visibleCols.length - 1 && "border-r-0",
|
|
12010
|
+
"relative bg-[var(--cmp-table-header-bg)] px-[16px] text-[12px] font-medium leading-[0] text-[color:var(--sys-color-fg-primary)]",
|
|
12011
|
+
stickyInfo(i).isSticky && "z-[6]",
|
|
12012
|
+
stickyShadowClass(i),
|
|
12013
|
+
col.thClass
|
|
12014
|
+
),
|
|
12015
|
+
style: { textAlign: col.align ?? "left", ...cellStyle(i), ...col.thStyle },
|
|
12016
|
+
"aria-sort": isSortable ? sortDir === "asc" ? "ascending" : sortDir === "desc" ? "descending" : "none" : void 0,
|
|
12017
|
+
children: [
|
|
12018
|
+
/* @__PURE__ */ jsx(
|
|
12019
|
+
"span",
|
|
12020
|
+
{
|
|
12021
|
+
className: cn(
|
|
12022
|
+
// 원본 th__content: align에 따라 justify-content 적용 (th도 정렬 반영)
|
|
12023
|
+
// th 가 leading-[0] 이므로 글자 줄높이는 여기서 준다 (truncate 가
|
|
12024
|
+
// overflow-hidden 이라 줄높이가 0이면 라벨이 잘려 사라진다).
|
|
12025
|
+
"inline-flex w-full min-w-0 items-center gap-[4px] leading-[20px]",
|
|
12026
|
+
col.align === "center" && "justify-center",
|
|
12027
|
+
col.align === "right" && "justify-end"
|
|
12028
|
+
),
|
|
12029
|
+
children: col.renderHeader ? col.renderHeader(col, i) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
12030
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: col.label }),
|
|
12031
|
+
col.helpText && col.helpText.length > 0 && // 라벨이 좁아져 truncate 되더라도 아이콘까지 함께 줄어들면 안 되므로
|
|
12032
|
+
// shrink-0 래퍼로 감싼다 (STooltip 의 className 은 본문 쪽으로 간다).
|
|
12033
|
+
// 아이콘·크기·색은 SKeyValueTable 헤더 도움말과 동일하게 맞춘다.
|
|
12034
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", children: /* @__PURE__ */ jsx(
|
|
12035
|
+
STooltip2,
|
|
12036
|
+
{
|
|
12037
|
+
trigger: "hover",
|
|
12038
|
+
icon: "helpOutline",
|
|
12039
|
+
iconSize: 12,
|
|
12040
|
+
color: "var(--sys-color-fg-success)",
|
|
12041
|
+
placement: "top",
|
|
12042
|
+
message: col.helpText
|
|
12043
|
+
}
|
|
12044
|
+
) }),
|
|
12045
|
+
col.editable && /* @__PURE__ */ jsx(
|
|
12046
|
+
SIcon,
|
|
12047
|
+
{
|
|
12048
|
+
name: "pageEdit",
|
|
12049
|
+
size: 12,
|
|
12050
|
+
color: "var(--sys-color-link-accent)",
|
|
12051
|
+
label: "\uC218\uC815 \uAC00\uB2A5",
|
|
12052
|
+
className: "shrink-0"
|
|
12053
|
+
}
|
|
12054
|
+
),
|
|
12055
|
+
col.navigable && /* @__PURE__ */ jsx(
|
|
12056
|
+
SIcon,
|
|
12057
|
+
{
|
|
12058
|
+
name: "pageMove",
|
|
12059
|
+
size: 12,
|
|
12060
|
+
color: "var(--sys-color-link-accent)",
|
|
12061
|
+
label: "\uB2E4\uB978 \uD654\uBA74\uC73C\uB85C \uC774\uB3D9",
|
|
12062
|
+
className: "shrink-0"
|
|
12063
|
+
}
|
|
12064
|
+
),
|
|
12065
|
+
col.required && // 라벨이 truncate 돼도 필수 표시는 남아야 하므로 shrink-0.
|
|
12066
|
+
// 아이콘·크기·색은 SKeyValueTable 헤더 필수 표시와 동일하게 맞춘다.
|
|
12067
|
+
/* @__PURE__ */ jsx(
|
|
12068
|
+
SIcon,
|
|
12069
|
+
{
|
|
12070
|
+
name: "asterisk",
|
|
12071
|
+
size: 12,
|
|
12072
|
+
color: "var(--sys-color-fg-accent)",
|
|
12073
|
+
className: "shrink-0"
|
|
12074
|
+
}
|
|
12075
|
+
),
|
|
12076
|
+
isSortable && // 미정렬은 updown 을 default(회색)로 — 정렬할 수 있다는 것 자체가
|
|
12077
|
+
// 헤더에 보여야 한다. 정렬 중이면 action 색으로 올려 활성임을 알린다.
|
|
12078
|
+
// 라벨이 truncate 돼도 버튼은 남도록 shrink-0.
|
|
12079
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", children: /* @__PURE__ */ jsx(
|
|
12080
|
+
SGhostButton,
|
|
12081
|
+
{
|
|
12082
|
+
size: "xxs",
|
|
12083
|
+
intent: sortDir ? "action" : "default",
|
|
12084
|
+
icon: sortDir === "asc" ? "arrowUp" : sortDir === "desc" ? "arrowDown" : "updown",
|
|
12085
|
+
ariaLabel: `${col.label} \uC815\uB82C`,
|
|
12086
|
+
onClick: () => toggleSort(col)
|
|
12087
|
+
}
|
|
12088
|
+
) })
|
|
12089
|
+
] })
|
|
12090
|
+
}
|
|
12091
|
+
),
|
|
12092
|
+
headerGroupInfo ? headerResizeHitArea(i, `resizer-${col.name}`) : headerResizer(i, `resizer-${col.name}`)
|
|
12093
|
+
]
|
|
12094
|
+
},
|
|
12095
|
+
col.name
|
|
12096
|
+
);
|
|
12097
|
+
})
|
|
12098
|
+
] })
|
|
12099
|
+
] })
|
|
11993
12100
|
]
|
|
11994
12101
|
}
|
|
11995
12102
|
)
|
|
@@ -17352,7 +17459,8 @@ var resolveFieldDefault = (field) => {
|
|
|
17352
17459
|
if (field.type === "datepicker-day") return todayIso();
|
|
17353
17460
|
if (field.type === "select") return field.options?.[0]?.value;
|
|
17354
17461
|
if (field.type === "datepicker-statistics") {
|
|
17355
|
-
const
|
|
17462
|
+
const presets = getFieldPresets(field).filter((preset) => !preset.custom);
|
|
17463
|
+
const unit = presets.some((preset) => preset.value === "day") ? "day" : presets[0]?.value;
|
|
17356
17464
|
return unit ? createPeriodValue(unit) : void 0;
|
|
17357
17465
|
}
|
|
17358
17466
|
return void 0;
|
|
@@ -17482,8 +17590,7 @@ var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
|
17482
17590
|
onActiveKeysChange,
|
|
17483
17591
|
onReset,
|
|
17484
17592
|
onAddFilter,
|
|
17485
|
-
label
|
|
17486
|
-
showLabel = false,
|
|
17593
|
+
label,
|
|
17487
17594
|
showReset = true,
|
|
17488
17595
|
disabled = false,
|
|
17489
17596
|
className,
|
|
@@ -17500,6 +17607,7 @@ var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
|
17500
17607
|
const pendingOpenKeyRef = useRef(null);
|
|
17501
17608
|
const triggerRefs = useRef(/* @__PURE__ */ new Map());
|
|
17502
17609
|
const initializedDefaultsRef = useRef(/* @__PURE__ */ new Set());
|
|
17610
|
+
const misuseWarningSignatureRef = useRef(null);
|
|
17503
17611
|
const prevOpenKeyRef = useRef(null);
|
|
17504
17612
|
const valuesRef = useRef(values);
|
|
17505
17613
|
valuesRef.current = values;
|
|
@@ -17515,14 +17623,19 @@ var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
|
17515
17623
|
(current) => groups.every((group) => isGroupSatisfied(group, current)),
|
|
17516
17624
|
[groups]
|
|
17517
17625
|
);
|
|
17626
|
+
const isRequiredSatisfied = useCallback(
|
|
17627
|
+
(current) => fields.every((field) => !field.required || !isEmptyValue(current[field.key])),
|
|
17628
|
+
[fields]
|
|
17629
|
+
);
|
|
17518
17630
|
const runSearch = useCallback(
|
|
17519
17631
|
(next) => {
|
|
17520
17632
|
if (valuesMapEqual(lastSearchedValuesRef.current, next)) return;
|
|
17521
17633
|
if (!isGroupsValid(next)) return;
|
|
17634
|
+
if (!isRequiredSatisfied(next)) return;
|
|
17522
17635
|
lastSearchedValuesRef.current = next;
|
|
17523
17636
|
onSearch?.(next);
|
|
17524
17637
|
},
|
|
17525
|
-
[isGroupsValid, onSearch]
|
|
17638
|
+
[isGroupsValid, isRequiredSatisfied, onSearch]
|
|
17526
17639
|
);
|
|
17527
17640
|
useEffect(() => {
|
|
17528
17641
|
const prevKey = prevOpenKeyRef.current;
|
|
@@ -17557,14 +17670,24 @@ var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
|
17557
17670
|
});
|
|
17558
17671
|
if (changed) onValueChange?.({ ...values, ...patch });
|
|
17559
17672
|
}, [fields, values, onValueChange]);
|
|
17560
|
-
|
|
17561
|
-
|
|
17562
|
-
|
|
17673
|
+
useEffect(() => {
|
|
17674
|
+
if (typeof console === "undefined") return;
|
|
17675
|
+
const misusedKeys = fields.filter((f) => f.defaultValue !== void 0 && !isFixedField(f)).map((f) => f.key);
|
|
17676
|
+
const requiredWithoutDefaultKeys = fields.filter((f) => f.required === true && resolveFieldDefault(f) === void 0).map((f) => f.key);
|
|
17677
|
+
const signature = JSON.stringify([misusedKeys, requiredWithoutDefaultKeys]);
|
|
17678
|
+
if (signature === misuseWarningSignatureRef.current) return;
|
|
17679
|
+
misuseWarningSignatureRef.current = signature;
|
|
17680
|
+
if (misusedKeys.length > 0) {
|
|
17563
17681
|
console.warn(
|
|
17564
|
-
`[SChipFilter] defaultValue \uB294 fixed\xB7required \uD544\uD130\uC5D0\uC11C\uB9CC \uC4F8 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uBB34\uC2DC\uD569\uB2C8\uB2E4. (${
|
|
17682
|
+
`[SChipFilter] defaultValue \uB294 fixed\xB7required \uD544\uD130\uC5D0\uC11C\uB9CC \uC4F8 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uBB34\uC2DC\uD569\uB2C8\uB2E4. (${misusedKeys.join(", ")})`
|
|
17565
17683
|
);
|
|
17566
17684
|
}
|
|
17567
|
-
|
|
17685
|
+
if (requiredWithoutDefaultKeys.length > 0) {
|
|
17686
|
+
console.warn(
|
|
17687
|
+
`[SChipFilter] required \uD544\uD130\uC5D0 defaultValue \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uC774 \uD0C0\uC785\uC740 \uB0B4\uC7A5 \uAE30\uBCF8\uAC12\uC774 \uC5C6\uC5B4 "\uAC80\uC0C9 \uCD08\uAE30\uD654" \uC2DC \uAC12\uC774 \uBE44\uC6CC\uC9C0\uACE0 \uAC80\uC0C9\uB3C4 \uB9C9\uD799\uB2C8\uB2E4. defaultValue \uB97C \uC9C0\uC815\uD558\uC138\uC694. (${requiredWithoutDefaultKeys.join(", ")})`
|
|
17688
|
+
);
|
|
17689
|
+
}
|
|
17690
|
+
}, [fields]);
|
|
17568
17691
|
const fixedKeys = fields.filter(isFixedField).map((field) => field.key);
|
|
17569
17692
|
const resolvedActiveKeys = Array.from(
|
|
17570
17693
|
/* @__PURE__ */ new Set([...activeKeys ?? internalActiveKeys, ...fixedKeys])
|
|
@@ -17632,7 +17755,10 @@ var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
|
17632
17755
|
},
|
|
17633
17756
|
[fields]
|
|
17634
17757
|
);
|
|
17635
|
-
const validate = useCallback(
|
|
17758
|
+
const validate = useCallback(
|
|
17759
|
+
() => invalidGroups.size === 0 && isRequiredSatisfied(values),
|
|
17760
|
+
[invalidGroups, isRequiredSatisfied, values]
|
|
17761
|
+
);
|
|
17636
17762
|
useImperativeHandle(ref, () => ({ open, reset, validate }), [open, reset, validate]);
|
|
17637
17763
|
const addField = (key) => {
|
|
17638
17764
|
const next = [...resolvedActiveKeys, key];
|
|
@@ -17669,7 +17795,7 @@ var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
|
17669
17795
|
),
|
|
17670
17796
|
style: { ...rootStyle, borderColor: "var(--chipfilter-bar-border)" },
|
|
17671
17797
|
children: [
|
|
17672
|
-
|
|
17798
|
+
label && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
17673
17799
|
/* @__PURE__ */ jsx(STag, { className: "shrink-0", shape: "square", size: "sm", color: "darkblue", label }),
|
|
17674
17800
|
/* @__PURE__ */ jsx(Divider, { top: true })
|
|
17675
17801
|
] }),
|
|
@@ -18379,6 +18505,10 @@ function InlineDatePresetFilter({
|
|
|
18379
18505
|
setSelectedId(preset.value);
|
|
18380
18506
|
onValueChange(preset.resolve ? preset.resolve() : null);
|
|
18381
18507
|
};
|
|
18508
|
+
const badgeBorder = disabled ? CHIPFILTER.chipDisabledBorder : warning ? CHIPFILTER.chipWarningBorder : CHIPFILTER.chipAppliedBorder;
|
|
18509
|
+
const badgeBackground = disabled ? CHIPFILTER.chipDisabledBg : CHIPFILTER.chipAppliedBg;
|
|
18510
|
+
const badgeLabelColor = disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedLabel;
|
|
18511
|
+
const badgeValueColor = disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedValue;
|
|
18382
18512
|
const badge = applied && /* @__PURE__ */ jsxs(
|
|
18383
18513
|
"span",
|
|
18384
18514
|
{
|
|
@@ -18386,17 +18516,17 @@ function InlineDatePresetFilter({
|
|
|
18386
18516
|
style: {
|
|
18387
18517
|
minHeight: CHIPFILTER.chipHeight,
|
|
18388
18518
|
borderRadius: CHIPFILTER.chipRadius,
|
|
18389
|
-
borderColor:
|
|
18390
|
-
background:
|
|
18391
|
-
color:
|
|
18392
|
-
cursor: rangeValue ? "pointer" : void 0
|
|
18519
|
+
borderColor: badgeBorder,
|
|
18520
|
+
background: badgeBackground,
|
|
18521
|
+
color: badgeLabelColor,
|
|
18522
|
+
cursor: rangeValue && !disabled ? "pointer" : void 0
|
|
18393
18523
|
},
|
|
18394
18524
|
children: [
|
|
18395
18525
|
/* @__PURE__ */ jsxs("span", { className: "font-bold", children: [
|
|
18396
18526
|
field.label,
|
|
18397
18527
|
":"
|
|
18398
18528
|
] }),
|
|
18399
|
-
/* @__PURE__ */ jsx("span", { className: "font-bold", style: { color:
|
|
18529
|
+
/* @__PURE__ */ jsx("span", { className: "font-bold", style: { color: badgeValueColor }, children: displayValue(field, value) }),
|
|
18400
18530
|
!disabled && showClear && /* @__PURE__ */ jsx(
|
|
18401
18531
|
"span",
|
|
18402
18532
|
{
|