sellmate-design-system-react 9.0.0-beta.25 → 9.0.0-beta.27
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 +15 -10
- package/dist/components/SChipFilter/SChipFilter.d.ts +18 -9
- package/dist/components/SGhostButton/README.md +0 -2
- package/dist/components/SSearchInput/README.md +2 -0
- package/dist/components/SSelect/README.md +1 -1
- package/dist/components/SSelect/SSelect.d.ts +1 -1
- 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 +413 -227
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +413 -227
- package/dist/index.js.map +1 -1
- package/dist/lib/floating-height.d.ts +15 -0
- package/dist/llms-full.txt +32 -11
- package/dist/styles.css +4 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10416,6 +10416,14 @@ var SStepper = /* @__PURE__ */ forwardRef(function SStepper2({
|
|
|
10416
10416
|
}
|
|
10417
10417
|
);
|
|
10418
10418
|
});
|
|
10419
|
+
|
|
10420
|
+
// src/lib/floating-height.ts
|
|
10421
|
+
var POPOVER_AVAILABLE_HEIGHT = "var(--radix-popover-content-available-height)";
|
|
10422
|
+
function clampToAvailableHeight(value, availableHeight) {
|
|
10423
|
+
if (value == null || value === "") return availableHeight;
|
|
10424
|
+
const css = typeof value === "number" ? `${value}px` : value;
|
|
10425
|
+
return `min(${css}, ${availableHeight})`;
|
|
10426
|
+
}
|
|
10419
10427
|
function runRules(value, rules) {
|
|
10420
10428
|
if (!rules || rules.length === 0) return "";
|
|
10421
10429
|
for (const rule of rules) {
|
|
@@ -10813,7 +10821,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
10813
10821
|
error = false,
|
|
10814
10822
|
rules,
|
|
10815
10823
|
labelTooltipProps,
|
|
10816
|
-
dropdownHeight = "
|
|
10824
|
+
dropdownHeight = "640px",
|
|
10817
10825
|
dropdownWidth,
|
|
10818
10826
|
maxDropdownWidth = "640px",
|
|
10819
10827
|
label,
|
|
@@ -11174,6 +11182,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
11174
11182
|
placement: "bottom",
|
|
11175
11183
|
align: "start",
|
|
11176
11184
|
offset: 4,
|
|
11185
|
+
viewportPadding: 24,
|
|
11177
11186
|
fit: !dropdownWidth,
|
|
11178
11187
|
onOpenAutoFocus: (event) => {
|
|
11179
11188
|
if (!showSearch) {
|
|
@@ -11206,7 +11215,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
11206
11215
|
SCROLLBAR_TRACK_BG_CLASS,
|
|
11207
11216
|
SCROLLBAR_TRACK_BORDER_CLASS
|
|
11208
11217
|
),
|
|
11209
|
-
style: { maxHeight: dropdownHeight },
|
|
11218
|
+
style: { maxHeight: clampToAvailableHeight(dropdownHeight, POPOVER_AVAILABLE_HEIGHT) },
|
|
11210
11219
|
onMouseLeave: () => setFocusedIndex(-1),
|
|
11211
11220
|
children: [
|
|
11212
11221
|
showSearch && /* @__PURE__ */ jsx(
|
|
@@ -11478,6 +11487,7 @@ var colWidthFromDef = (c) => {
|
|
|
11478
11487
|
};
|
|
11479
11488
|
var STable = /* @__PURE__ */ forwardRef(function STable2({
|
|
11480
11489
|
columns = [],
|
|
11490
|
+
headerGroups,
|
|
11481
11491
|
rows = [],
|
|
11482
11492
|
rowKey = "id",
|
|
11483
11493
|
selectable = false,
|
|
@@ -11525,6 +11535,49 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
|
|
|
11525
11535
|
onDenseChange?.(next);
|
|
11526
11536
|
};
|
|
11527
11537
|
const visibleCols = useMemo(() => columns.filter((c) => c.visible !== false), [columns]);
|
|
11538
|
+
const headerGroupInfo = useMemo(() => {
|
|
11539
|
+
if (!headerGroups || headerGroups.length === 0) return null;
|
|
11540
|
+
const indexByName = new Map(visibleCols.map((col, index) => [col.name, index]));
|
|
11541
|
+
const covered = /* @__PURE__ */ new Set();
|
|
11542
|
+
let previousLast = -1;
|
|
11543
|
+
const cells = headerGroups.map((group) => {
|
|
11544
|
+
if (group.columnNames.length === 0) {
|
|
11545
|
+
throw new Error("[STable] headerGroups\uC758 columnNames\uB294 \uBE44\uC5B4 \uC788\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
11546
|
+
}
|
|
11547
|
+
const indexes = group.columnNames.map((name) => {
|
|
11548
|
+
const index = indexByName.get(name);
|
|
11549
|
+
if (index == null) {
|
|
11550
|
+
throw new Error(`[STable] headerGroups\uC5D0 \uC874\uC7AC\uD558\uC9C0 \uC54A\uB294 \uCEEC\uB7FC\uC774 \uC9C0\uC815\uB418\uC5C8\uC2B5\uB2C8\uB2E4: ${name}`);
|
|
11551
|
+
}
|
|
11552
|
+
if (covered.has(name)) {
|
|
11553
|
+
throw new Error(`[STable] headerGroups\uC5D0\uC11C \uCEEC\uB7FC\uC774 \uC911\uBCF5 \uC9C0\uC815\uB418\uC5C8\uC2B5\uB2C8\uB2E4: ${name}`);
|
|
11554
|
+
}
|
|
11555
|
+
covered.add(name);
|
|
11556
|
+
return index;
|
|
11557
|
+
});
|
|
11558
|
+
const first = indexes[0];
|
|
11559
|
+
const last = indexes[indexes.length - 1];
|
|
11560
|
+
if (last - first + 1 !== indexes.length || indexes.some((index, i) => index !== first + i)) {
|
|
11561
|
+
throw new Error(
|
|
11562
|
+
"[STable] headerGroups\uC758 columnNames\uB294 \uC778\uC811\uD55C \uCEEC\uB7FC \uC21C\uC11C\uB85C \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4."
|
|
11563
|
+
);
|
|
11564
|
+
}
|
|
11565
|
+
if (first <= previousLast) {
|
|
11566
|
+
throw new Error("[STable] headerGroups\uB294 \uCEEC\uB7FC \uC21C\uC11C\uB300\uB85C \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4.");
|
|
11567
|
+
}
|
|
11568
|
+
previousLast = last;
|
|
11569
|
+
return { ...group, firstIndex: first, colSpan: indexes.length };
|
|
11570
|
+
});
|
|
11571
|
+
if (covered.size !== visibleCols.length) {
|
|
11572
|
+
throw new Error("[STable] headerGroups\uC758 columnNames\uAC00 \uBAA8\uB4E0 visible \uCEEC\uB7FC\uC744 \uD3EC\uD568\uD574\uC57C \uD569\uB2C8\uB2E4.");
|
|
11573
|
+
}
|
|
11574
|
+
return {
|
|
11575
|
+
cells,
|
|
11576
|
+
rowSpanNames: new Set(
|
|
11577
|
+
cells.filter((cell) => cell.rowSpan === 2).flatMap((cell) => cell.columnNames)
|
|
11578
|
+
)
|
|
11579
|
+
};
|
|
11580
|
+
}, [headerGroups, visibleCols]);
|
|
11528
11581
|
const stickyLeft = stickyColumn?.left ?? 0;
|
|
11529
11582
|
const stickyRight = stickyColumn?.right ?? 0;
|
|
11530
11583
|
const effectiveRowHeight = rowHeight ?? (innerDense ? DENSE_ROW_HEIGHT : DEFAULT_ROW_HEIGHT);
|
|
@@ -11787,6 +11840,35 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
|
|
|
11787
11840
|
isRightEdge && scrolledRight && "shadow-[-5px_0_8px_0_rgba(34,34,34,0.1)]"
|
|
11788
11841
|
);
|
|
11789
11842
|
};
|
|
11843
|
+
const headerResizeHitArea = (i, key) => {
|
|
11844
|
+
const col = visibleCols[i];
|
|
11845
|
+
if (!headerGroupInfo || !resizable || !col || col.autoWidth || i >= visibleCols.length - 1) {
|
|
11846
|
+
return null;
|
|
11847
|
+
}
|
|
11848
|
+
return /* @__PURE__ */ jsx(
|
|
11849
|
+
"span",
|
|
11850
|
+
{
|
|
11851
|
+
onMouseDown: (e) => startResize(i, e),
|
|
11852
|
+
className: "absolute inset-y-0 right-0 z-[5] w-[9px] cursor-col-resize",
|
|
11853
|
+
"aria-hidden": true
|
|
11854
|
+
},
|
|
11855
|
+
key
|
|
11856
|
+
);
|
|
11857
|
+
};
|
|
11858
|
+
const headerResizer = (i, key) => {
|
|
11859
|
+
const col = visibleCols[i];
|
|
11860
|
+
if (!resizable || !col || col.autoWidth || i >= visibleCols.length - 1) return null;
|
|
11861
|
+
return /* @__PURE__ */ jsx(
|
|
11862
|
+
"span",
|
|
11863
|
+
{
|
|
11864
|
+
onMouseDown: (e) => startResize(i, e),
|
|
11865
|
+
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",
|
|
11866
|
+
"aria-hidden": true,
|
|
11867
|
+
children: /* @__PURE__ */ jsx("span", { className: "h-full w-[4px] border-x border-solid border-[color:var(--cmp-table-header-resizingBar-color)]" })
|
|
11868
|
+
},
|
|
11869
|
+
key
|
|
11870
|
+
);
|
|
11871
|
+
};
|
|
11790
11872
|
const bodyScrollClass = cn(
|
|
11791
11873
|
"min-h-0 flex-1 overflow-auto border-t border-solid border-[color:var(--cmp-table-border-color)]",
|
|
11792
11874
|
SCROLLBAR_CLASS,
|
|
@@ -11851,145 +11933,179 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
|
|
|
11851
11933
|
style: { fontSize: 12 },
|
|
11852
11934
|
children: [
|
|
11853
11935
|
colgroup,
|
|
11854
|
-
/* @__PURE__ */
|
|
11855
|
-
|
|
11856
|
-
|
|
11857
|
-
|
|
11858
|
-
|
|
11859
|
-
|
|
11860
|
-
|
|
11861
|
-
|
|
11862
|
-
|
|
11863
|
-
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
11936
|
+
/* @__PURE__ */ jsxs("thead", { className: cn(isNoData && "opacity-40"), children: [
|
|
11937
|
+
headerGroupInfo && /* @__PURE__ */ jsxs("tr", { className: "h-[var(--cmp-table-header-height)] bg-[var(--cmp-table-header-bg)]", children: [
|
|
11938
|
+
selectable && /* @__PURE__ */ jsx(
|
|
11939
|
+
"th",
|
|
11940
|
+
{
|
|
11941
|
+
rowSpan: 2,
|
|
11942
|
+
className: cn(
|
|
11943
|
+
"sticky left-0 z-[7] bg-[var(--cmp-table-header-bg)] text-center align-middle",
|
|
11944
|
+
stickyLeft === 0 && scrolledLeft && "shadow-[5px_0_8px_0_rgba(34,34,34,0.1)]"
|
|
11945
|
+
),
|
|
11946
|
+
style: {
|
|
11947
|
+
width: SELECTABLE_COLUMN_WIDTH,
|
|
11948
|
+
minWidth: SELECTABLE_COLUMN_WIDTH,
|
|
11949
|
+
maxWidth: SELECTABLE_COLUMN_WIDTH
|
|
11950
|
+
},
|
|
11951
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(SCheckbox, { value: headerCheck, onValueChange: toggleAll }) })
|
|
11952
|
+
}
|
|
11953
|
+
),
|
|
11954
|
+
headerGroupInfo.cells.map((group) => /* @__PURE__ */ jsxs(
|
|
11955
|
+
"th",
|
|
11956
|
+
{
|
|
11957
|
+
colSpan: group.colSpan,
|
|
11958
|
+
rowSpan: group.rowSpan,
|
|
11959
|
+
className: cn(
|
|
11960
|
+
"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)]",
|
|
11961
|
+
group.firstIndex + group.colSpan === visibleCols.length && "border-r-0",
|
|
11962
|
+
group.rowSpan === 2 && "border-b-0",
|
|
11963
|
+
group.className
|
|
11964
|
+
),
|
|
11965
|
+
style: { textAlign: group.align ?? "left", ...group.style },
|
|
11966
|
+
children: [
|
|
11967
|
+
group.render ? group.render() : group.label,
|
|
11968
|
+
group.rowSpan === 2 && group.colSpan === 1 ? headerResizeHitArea(
|
|
11969
|
+
group.firstIndex,
|
|
11970
|
+
`group-resizer-${group.columnNames[0]}`
|
|
11971
|
+
) : null
|
|
11972
|
+
]
|
|
11868
11973
|
},
|
|
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(
|
|
11974
|
+
group.columnNames.join("|")
|
|
11975
|
+
))
|
|
11976
|
+
] }),
|
|
11977
|
+
/* @__PURE__ */ jsxs("tr", { className: "h-[var(--cmp-table-header-height)] bg-[var(--cmp-table-header-bg)]", children: [
|
|
11978
|
+
selectable && !headerGroupInfo && /* @__PURE__ */ jsxs(
|
|
11885
11979
|
"th",
|
|
11886
11980
|
{
|
|
11887
11981
|
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
|
|
11982
|
+
// 원본 .th--selected: 48px 고정폭, 항상 left sticky, 체크박스 중앙정렬
|
|
11983
|
+
// 하단 border는 헤더 래퍼가 연속으로 그리므로 셀에는 두지 않는다.
|
|
11984
|
+
"sticky left-0 z-[7] bg-[var(--cmp-table-header-bg)] text-center align-middle",
|
|
11985
|
+
stickyLeft === 0 && scrolledLeft && "shadow-[5px_0_8px_0_rgba(34,34,34,0.1)]"
|
|
11897
11986
|
),
|
|
11898
|
-
style: {
|
|
11899
|
-
|
|
11987
|
+
style: {
|
|
11988
|
+
width: SELECTABLE_COLUMN_WIDTH,
|
|
11989
|
+
minWidth: SELECTABLE_COLUMN_WIDTH,
|
|
11990
|
+
maxWidth: SELECTABLE_COLUMN_WIDTH
|
|
11991
|
+
},
|
|
11900
11992
|
children: [
|
|
11993
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(SCheckbox, { value: headerCheck, onValueChange: toggleAll }) }),
|
|
11901
11994
|
/* @__PURE__ */ jsx(
|
|
11902
11995
|
"span",
|
|
11903
11996
|
{
|
|
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
11997
|
"aria-hidden": true,
|
|
11984
|
-
|
|
11998
|
+
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
11999
|
}
|
|
11986
12000
|
)
|
|
11987
12001
|
]
|
|
11988
|
-
}
|
|
11989
|
-
|
|
11990
|
-
)
|
|
11991
|
-
|
|
11992
|
-
|
|
12002
|
+
}
|
|
12003
|
+
),
|
|
12004
|
+
visibleCols.map((col, i) => {
|
|
12005
|
+
if (headerGroupInfo?.rowSpanNames.has(col.name)) return null;
|
|
12006
|
+
const isSortable = !!col.sortable && !col.renderHeader;
|
|
12007
|
+
const sortDir = isSortable && sort?.name === col.name ? sort.dir : void 0;
|
|
12008
|
+
return /* @__PURE__ */ jsxs(
|
|
12009
|
+
"th",
|
|
12010
|
+
{
|
|
12011
|
+
className: cn(
|
|
12012
|
+
// 하단 border는 헤더 래퍼가 연속으로 그린다 (거터 영역까지 이어짐).
|
|
12013
|
+
// leading-[0]: th 의 스트럿(line-height 만큼의 빈 인라인 박스)을 없앤다.
|
|
12014
|
+
// 내용이 inline-flex 라 스트럿이 남아 있으면 라벨보다 큰 컨트롤(정렬 버튼 등)이
|
|
12015
|
+
// 들어올 때 줄 상자가 베이스라인 기준으로 늘어나 헤더 높이를 넘기고
|
|
12016
|
+
// 세로 가운데도 어긋난다. 글자 줄높이는 아래 th__content 가 다시 준다.
|
|
12017
|
+
headerGroupInfo && "border-r border-solid border-[color:var(--cmp-table-border-color)]",
|
|
12018
|
+
headerGroupInfo && i === visibleCols.length - 1 && "border-r-0",
|
|
12019
|
+
"relative bg-[var(--cmp-table-header-bg)] px-[16px] text-[12px] font-medium leading-[0] text-[color:var(--sys-color-fg-primary)]",
|
|
12020
|
+
stickyInfo(i).isSticky && "z-[6]",
|
|
12021
|
+
stickyShadowClass(i),
|
|
12022
|
+
col.thClass
|
|
12023
|
+
),
|
|
12024
|
+
style: { textAlign: col.align ?? "left", ...cellStyle(i), ...col.thStyle },
|
|
12025
|
+
"aria-sort": isSortable ? sortDir === "asc" ? "ascending" : sortDir === "desc" ? "descending" : "none" : void 0,
|
|
12026
|
+
children: [
|
|
12027
|
+
/* @__PURE__ */ jsx(
|
|
12028
|
+
"span",
|
|
12029
|
+
{
|
|
12030
|
+
className: cn(
|
|
12031
|
+
// 원본 th__content: align에 따라 justify-content 적용 (th도 정렬 반영)
|
|
12032
|
+
// th 가 leading-[0] 이므로 글자 줄높이는 여기서 준다 (truncate 가
|
|
12033
|
+
// overflow-hidden 이라 줄높이가 0이면 라벨이 잘려 사라진다).
|
|
12034
|
+
"inline-flex w-full min-w-0 items-center gap-[4px] leading-[20px]",
|
|
12035
|
+
col.align === "center" && "justify-center",
|
|
12036
|
+
col.align === "right" && "justify-end"
|
|
12037
|
+
),
|
|
12038
|
+
children: col.renderHeader ? col.renderHeader(col, i) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
12039
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: col.label }),
|
|
12040
|
+
col.helpText && col.helpText.length > 0 && // 라벨이 좁아져 truncate 되더라도 아이콘까지 함께 줄어들면 안 되므로
|
|
12041
|
+
// shrink-0 래퍼로 감싼다 (STooltip 의 className 은 본문 쪽으로 간다).
|
|
12042
|
+
// 아이콘·크기·색은 SKeyValueTable 헤더 도움말과 동일하게 맞춘다.
|
|
12043
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", children: /* @__PURE__ */ jsx(
|
|
12044
|
+
STooltip2,
|
|
12045
|
+
{
|
|
12046
|
+
trigger: "hover",
|
|
12047
|
+
icon: "helpOutline",
|
|
12048
|
+
iconSize: 12,
|
|
12049
|
+
color: "var(--sys-color-fg-success)",
|
|
12050
|
+
placement: "top",
|
|
12051
|
+
message: col.helpText
|
|
12052
|
+
}
|
|
12053
|
+
) }),
|
|
12054
|
+
col.editable && /* @__PURE__ */ jsx(
|
|
12055
|
+
SIcon,
|
|
12056
|
+
{
|
|
12057
|
+
name: "pageEdit",
|
|
12058
|
+
size: 12,
|
|
12059
|
+
color: "var(--sys-color-link-accent)",
|
|
12060
|
+
label: "\uC218\uC815 \uAC00\uB2A5",
|
|
12061
|
+
className: "shrink-0"
|
|
12062
|
+
}
|
|
12063
|
+
),
|
|
12064
|
+
col.navigable && /* @__PURE__ */ jsx(
|
|
12065
|
+
SIcon,
|
|
12066
|
+
{
|
|
12067
|
+
name: "pageMove",
|
|
12068
|
+
size: 12,
|
|
12069
|
+
color: "var(--sys-color-link-accent)",
|
|
12070
|
+
label: "\uB2E4\uB978 \uD654\uBA74\uC73C\uB85C \uC774\uB3D9",
|
|
12071
|
+
className: "shrink-0"
|
|
12072
|
+
}
|
|
12073
|
+
),
|
|
12074
|
+
col.required && // 라벨이 truncate 돼도 필수 표시는 남아야 하므로 shrink-0.
|
|
12075
|
+
// 아이콘·크기·색은 SKeyValueTable 헤더 필수 표시와 동일하게 맞춘다.
|
|
12076
|
+
/* @__PURE__ */ jsx(
|
|
12077
|
+
SIcon,
|
|
12078
|
+
{
|
|
12079
|
+
name: "asterisk",
|
|
12080
|
+
size: 12,
|
|
12081
|
+
color: "var(--sys-color-fg-accent)",
|
|
12082
|
+
className: "shrink-0"
|
|
12083
|
+
}
|
|
12084
|
+
),
|
|
12085
|
+
isSortable && // 미정렬은 updown 을 default(회색)로 — 정렬할 수 있다는 것 자체가
|
|
12086
|
+
// 헤더에 보여야 한다. 정렬 중이면 action 색으로 올려 활성임을 알린다.
|
|
12087
|
+
// 라벨이 truncate 돼도 버튼은 남도록 shrink-0.
|
|
12088
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", children: /* @__PURE__ */ jsx(
|
|
12089
|
+
SGhostButton,
|
|
12090
|
+
{
|
|
12091
|
+
size: "xxs",
|
|
12092
|
+
intent: sortDir ? "action" : "default",
|
|
12093
|
+
icon: sortDir === "asc" ? "arrowUp" : sortDir === "desc" ? "arrowDown" : "updown",
|
|
12094
|
+
ariaLabel: `${col.label} \uC815\uB82C`,
|
|
12095
|
+
onClick: () => toggleSort(col)
|
|
12096
|
+
}
|
|
12097
|
+
) })
|
|
12098
|
+
] })
|
|
12099
|
+
}
|
|
12100
|
+
),
|
|
12101
|
+
headerGroupInfo ? headerResizeHitArea(i, `resizer-${col.name}`) : headerResizer(i, `resizer-${col.name}`)
|
|
12102
|
+
]
|
|
12103
|
+
},
|
|
12104
|
+
col.name
|
|
12105
|
+
);
|
|
12106
|
+
})
|
|
12107
|
+
] })
|
|
12108
|
+
] })
|
|
11993
12109
|
]
|
|
11994
12110
|
}
|
|
11995
12111
|
)
|
|
@@ -17252,6 +17368,8 @@ var SEditor = /* @__PURE__ */ forwardRef(function SEditor2({
|
|
|
17252
17368
|
});
|
|
17253
17369
|
var CHIPFILTER_LISTBOX_WIDTH = 240;
|
|
17254
17370
|
var CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH = 246;
|
|
17371
|
+
var EDITOR_LISTBOX_MAX_HEIGHT = "min(640px, var(--radix-popover-content-available-height))";
|
|
17372
|
+
var EDITOR_POPOVER_VIEWPORT_PADDING = 24;
|
|
17255
17373
|
var CHIPFILTER = {
|
|
17256
17374
|
barBg: "var(--cmp-chipFilter-bar-bg)",
|
|
17257
17375
|
barBorder: "var(--cmp-chipFilter-bar-border)",
|
|
@@ -17291,6 +17409,7 @@ var CHIPFILTER = {
|
|
|
17291
17409
|
itemTextDefault: "var(--cmp-chipFilter-item-text-default)",
|
|
17292
17410
|
itemTextSelected: "var(--cmp-chipFilter-item-text-selected)"
|
|
17293
17411
|
};
|
|
17412
|
+
var DEFAULT_CUSTOM_MAX_RANGE = 90;
|
|
17294
17413
|
var DEFAULT_PERIOD_PRESETS = [
|
|
17295
17414
|
{ value: "day", label: "\uC77C\uBCC4" },
|
|
17296
17415
|
{ value: "month", label: "\uC6D4\uBCC4" },
|
|
@@ -17299,6 +17418,20 @@ var DEFAULT_PERIOD_PRESETS = [
|
|
|
17299
17418
|
{ value: "year", label: "\uC5F0\uB3C4\uBCC4" },
|
|
17300
17419
|
{ value: "custom", label: "\uC0AC\uC6A9\uC790 \uC9C0\uC815", custom: true }
|
|
17301
17420
|
];
|
|
17421
|
+
var DEFAULT_DATE_RANGE_PRESETS = [
|
|
17422
|
+
{ value: "today", label: "\uC624\uB298", resolve: () => todayIso() },
|
|
17423
|
+
{
|
|
17424
|
+
value: "last7",
|
|
17425
|
+
label: "\uC9C0\uB09C 7\uC77C",
|
|
17426
|
+
resolve: () => [addDaysIso(todayIso(), -7), todayIso()]
|
|
17427
|
+
},
|
|
17428
|
+
{
|
|
17429
|
+
value: "last30",
|
|
17430
|
+
label: "\uC9C0\uB09C 30\uC77C",
|
|
17431
|
+
resolve: () => [addDaysIso(todayIso(), -30), todayIso()]
|
|
17432
|
+
},
|
|
17433
|
+
{ value: "custom", label: "\uC0AC\uC6A9\uC790 \uC9C0\uC815", custom: true }
|
|
17434
|
+
];
|
|
17302
17435
|
var isKeywordValue = (value) => typeof value === "object" && value != null && !Array.isArray(value) && "keywords" in value;
|
|
17303
17436
|
var isPeriodValue = (value) => typeof value === "object" && value != null && !Array.isArray(value) && "unit" in value;
|
|
17304
17437
|
var keywordEntries = (value) => {
|
|
@@ -17323,23 +17456,39 @@ var todayIso = () => {
|
|
|
17323
17456
|
const pad = (n) => String(n).padStart(2, "0");
|
|
17324
17457
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
17325
17458
|
};
|
|
17459
|
+
var addDaysIso = (iso, n) => {
|
|
17460
|
+
const d = /* @__PURE__ */ new Date(`${iso}T00:00:00`);
|
|
17461
|
+
d.setDate(d.getDate() + n);
|
|
17462
|
+
const pad = (v) => String(v).padStart(2, "0");
|
|
17463
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
17464
|
+
};
|
|
17326
17465
|
var isInlineDateField = (field) => field.type === "datepicker-range" && field.radioButton === true && (field.presets?.length ?? 0) > 0;
|
|
17327
17466
|
var getFieldPresets = (field) => {
|
|
17328
17467
|
if (field.type === "datepicker-statistics") return field.presets ?? DEFAULT_PERIOD_PRESETS;
|
|
17329
|
-
return field.presets ??
|
|
17468
|
+
return field.presets ?? DEFAULT_DATE_RANGE_PRESETS;
|
|
17469
|
+
};
|
|
17470
|
+
var getEffectiveMaxRange = (field) => {
|
|
17471
|
+
if (field.maxRange !== void 0) return field.maxRange;
|
|
17472
|
+
const hasCustomPreset = getFieldPresets(field).some((preset) => preset.custom);
|
|
17473
|
+
return hasCustomPreset ? DEFAULT_CUSTOM_MAX_RANGE : void 0;
|
|
17330
17474
|
};
|
|
17331
|
-
var
|
|
17475
|
+
var getPresetLabel = (preset, maxRange) => {
|
|
17476
|
+
if (!preset.custom || !maxRange || preset.label.includes("\uCD5C\uB300")) return preset.label;
|
|
17477
|
+
return `${preset.label} (\uCD5C\uB300 ${maxRange}\uC77C\uC529)`;
|
|
17478
|
+
};
|
|
17479
|
+
var getDefaultPeriodInputValue = (unit, maxRange) => {
|
|
17332
17480
|
const today = todayIso();
|
|
17333
17481
|
if (unit === "day") return today;
|
|
17334
17482
|
if (unit === "month") return today.slice(0, 7);
|
|
17335
17483
|
if (unit === "quarter") return 1;
|
|
17336
17484
|
if (unit === "half") return "first";
|
|
17337
17485
|
if (unit === "year") return today.slice(0, 4);
|
|
17338
|
-
|
|
17486
|
+
const days = maxRange && maxRange > 0 ? maxRange : DEFAULT_CUSTOM_MAX_RANGE;
|
|
17487
|
+
return [addDaysIso(today, -days), today];
|
|
17339
17488
|
};
|
|
17340
|
-
var createPeriodValue = (unit) => ({
|
|
17489
|
+
var createPeriodValue = (unit, maxRange) => ({
|
|
17341
17490
|
unit,
|
|
17342
|
-
value: getDefaultPeriodInputValue(unit)
|
|
17491
|
+
value: getDefaultPeriodInputValue(unit, maxRange)
|
|
17343
17492
|
});
|
|
17344
17493
|
var resolveFieldDefault = (field) => {
|
|
17345
17494
|
if (field.defaultValue !== void 0 && isFixedField(field)) return field.defaultValue;
|
|
@@ -17352,7 +17501,8 @@ var resolveFieldDefault = (field) => {
|
|
|
17352
17501
|
if (field.type === "datepicker-day") return todayIso();
|
|
17353
17502
|
if (field.type === "select") return field.options?.[0]?.value;
|
|
17354
17503
|
if (field.type === "datepicker-statistics") {
|
|
17355
|
-
const
|
|
17504
|
+
const presets = getFieldPresets(field).filter((preset) => !preset.custom);
|
|
17505
|
+
const unit = presets.some((preset) => preset.value === "day") ? "day" : presets[0]?.value;
|
|
17356
17506
|
return unit ? createPeriodValue(unit) : void 0;
|
|
17357
17507
|
}
|
|
17358
17508
|
return void 0;
|
|
@@ -17482,8 +17632,7 @@ var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
|
17482
17632
|
onActiveKeysChange,
|
|
17483
17633
|
onReset,
|
|
17484
17634
|
onAddFilter,
|
|
17485
|
-
label
|
|
17486
|
-
showLabel = false,
|
|
17635
|
+
label,
|
|
17487
17636
|
showReset = true,
|
|
17488
17637
|
disabled = false,
|
|
17489
17638
|
className,
|
|
@@ -17500,6 +17649,7 @@ var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
|
17500
17649
|
const pendingOpenKeyRef = useRef(null);
|
|
17501
17650
|
const triggerRefs = useRef(/* @__PURE__ */ new Map());
|
|
17502
17651
|
const initializedDefaultsRef = useRef(/* @__PURE__ */ new Set());
|
|
17652
|
+
const misuseWarningSignatureRef = useRef(null);
|
|
17503
17653
|
const prevOpenKeyRef = useRef(null);
|
|
17504
17654
|
const valuesRef = useRef(values);
|
|
17505
17655
|
valuesRef.current = values;
|
|
@@ -17515,14 +17665,19 @@ var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
|
17515
17665
|
(current) => groups.every((group) => isGroupSatisfied(group, current)),
|
|
17516
17666
|
[groups]
|
|
17517
17667
|
);
|
|
17668
|
+
const isRequiredSatisfied = useCallback(
|
|
17669
|
+
(current) => fields.every((field) => !field.required || !isEmptyValue(current[field.key])),
|
|
17670
|
+
[fields]
|
|
17671
|
+
);
|
|
17518
17672
|
const runSearch = useCallback(
|
|
17519
17673
|
(next) => {
|
|
17520
17674
|
if (valuesMapEqual(lastSearchedValuesRef.current, next)) return;
|
|
17521
17675
|
if (!isGroupsValid(next)) return;
|
|
17676
|
+
if (!isRequiredSatisfied(next)) return;
|
|
17522
17677
|
lastSearchedValuesRef.current = next;
|
|
17523
17678
|
onSearch?.(next);
|
|
17524
17679
|
},
|
|
17525
|
-
[isGroupsValid, onSearch]
|
|
17680
|
+
[isGroupsValid, isRequiredSatisfied, onSearch]
|
|
17526
17681
|
);
|
|
17527
17682
|
useEffect(() => {
|
|
17528
17683
|
const prevKey = prevOpenKeyRef.current;
|
|
@@ -17557,14 +17712,24 @@ var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
|
17557
17712
|
});
|
|
17558
17713
|
if (changed) onValueChange?.({ ...values, ...patch });
|
|
17559
17714
|
}, [fields, values, onValueChange]);
|
|
17560
|
-
|
|
17561
|
-
|
|
17562
|
-
|
|
17715
|
+
useEffect(() => {
|
|
17716
|
+
if (typeof console === "undefined") return;
|
|
17717
|
+
const misusedKeys = fields.filter((f) => f.defaultValue !== void 0 && !isFixedField(f)).map((f) => f.key);
|
|
17718
|
+
const requiredWithoutDefaultKeys = fields.filter((f) => f.required === true && resolveFieldDefault(f) === void 0).map((f) => f.key);
|
|
17719
|
+
const signature = JSON.stringify([misusedKeys, requiredWithoutDefaultKeys]);
|
|
17720
|
+
if (signature === misuseWarningSignatureRef.current) return;
|
|
17721
|
+
misuseWarningSignatureRef.current = signature;
|
|
17722
|
+
if (misusedKeys.length > 0) {
|
|
17563
17723
|
console.warn(
|
|
17564
|
-
`[SChipFilter] defaultValue \uB294 fixed\xB7required \uD544\uD130\uC5D0\uC11C\uB9CC \uC4F8 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uBB34\uC2DC\uD569\uB2C8\uB2E4. (${
|
|
17724
|
+
`[SChipFilter] defaultValue \uB294 fixed\xB7required \uD544\uD130\uC5D0\uC11C\uB9CC \uC4F8 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uBB34\uC2DC\uD569\uB2C8\uB2E4. (${misusedKeys.join(", ")})`
|
|
17565
17725
|
);
|
|
17566
17726
|
}
|
|
17567
|
-
|
|
17727
|
+
if (requiredWithoutDefaultKeys.length > 0) {
|
|
17728
|
+
console.warn(
|
|
17729
|
+
`[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(", ")})`
|
|
17730
|
+
);
|
|
17731
|
+
}
|
|
17732
|
+
}, [fields]);
|
|
17568
17733
|
const fixedKeys = fields.filter(isFixedField).map((field) => field.key);
|
|
17569
17734
|
const resolvedActiveKeys = Array.from(
|
|
17570
17735
|
/* @__PURE__ */ new Set([...activeKeys ?? internalActiveKeys, ...fixedKeys])
|
|
@@ -17632,7 +17797,10 @@ var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
|
17632
17797
|
},
|
|
17633
17798
|
[fields]
|
|
17634
17799
|
);
|
|
17635
|
-
const validate = useCallback(
|
|
17800
|
+
const validate = useCallback(
|
|
17801
|
+
() => invalidGroups.size === 0 && isRequiredSatisfied(values),
|
|
17802
|
+
[invalidGroups, isRequiredSatisfied, values]
|
|
17803
|
+
);
|
|
17636
17804
|
useImperativeHandle(ref, () => ({ open, reset, validate }), [open, reset, validate]);
|
|
17637
17805
|
const addField = (key) => {
|
|
17638
17806
|
const next = [...resolvedActiveKeys, key];
|
|
@@ -17669,7 +17837,7 @@ var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
|
17669
17837
|
),
|
|
17670
17838
|
style: { ...rootStyle, borderColor: "var(--chipfilter-bar-border)" },
|
|
17671
17839
|
children: [
|
|
17672
|
-
|
|
17840
|
+
label && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
17673
17841
|
/* @__PURE__ */ jsx(STag, { className: "shrink-0", shape: "square", size: "sm", color: "darkblue", label }),
|
|
17674
17842
|
/* @__PURE__ */ jsx(Divider, { top: true })
|
|
17675
17843
|
] }),
|
|
@@ -17869,6 +18037,7 @@ var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
|
17869
18037
|
side: "bottom",
|
|
17870
18038
|
align: "start",
|
|
17871
18039
|
sideOffset: 4,
|
|
18040
|
+
collisionPadding: EDITOR_POPOVER_VIEWPORT_PADDING,
|
|
17872
18041
|
onOpenAutoFocus: (event) => event.preventDefault(),
|
|
17873
18042
|
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
17874
18043
|
style: editorPopoverStyle,
|
|
@@ -18034,6 +18203,7 @@ function EditorPanel({
|
|
|
18034
18203
|
onClose
|
|
18035
18204
|
}) {
|
|
18036
18205
|
const wrapsInPaddedTop = field.type === "datepicker-day" || field.type === "datepicker-range" || field.type === "datepicker-statistics";
|
|
18206
|
+
const isScrollableListField = field.type === "select" || field.type === "select-multi" || field.type === "keyword";
|
|
18037
18207
|
const isMulti = field.type === "select-multi";
|
|
18038
18208
|
const selectableValues = isMulti ? (field.options ?? []).filter((option) => !option.disabled).map((option) => option.value) : [];
|
|
18039
18209
|
const selectedValues = isMulti ? toArrayValue(value) : [];
|
|
@@ -18043,7 +18213,7 @@ function EditorPanel({
|
|
|
18043
18213
|
allSelected ? selectedValues.filter((v) => !selectableValues.includes(v)) : [...selectedValues, ...selectableValues.filter((v) => !selectedValues.includes(v))]
|
|
18044
18214
|
);
|
|
18045
18215
|
};
|
|
18046
|
-
return /* @__PURE__ */ jsxs(ListBox, { children: [
|
|
18216
|
+
return /* @__PURE__ */ jsxs(ListBox, { maxHeight: isScrollableListField ? EDITOR_LISTBOX_MAX_HEIGHT : void 0, children: [
|
|
18047
18217
|
wrapsInPaddedTop ? /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)] px-[var(--cmp-chipFilter-listbox-top-paddingX)] py-[var(--cmp-chipFilter-listbox-top-paddingY)]", children: /* @__PURE__ */ jsx(
|
|
18048
18218
|
FilterEditor,
|
|
18049
18219
|
{
|
|
@@ -18066,7 +18236,7 @@ function EditorPanel({
|
|
|
18066
18236
|
/* @__PURE__ */ jsxs(
|
|
18067
18237
|
"div",
|
|
18068
18238
|
{
|
|
18069
|
-
className: "flex items-center justify-end gap-[var(--cmp-chipFilter-listbox-bottom-gap)] border-t border-solid px-[var(--cmp-chipFilter-listbox-bottom-paddingX)] py-[var(--cmp-chipFilter-listbox-bottom-paddingY)]",
|
|
18239
|
+
className: "flex shrink-0 items-center justify-end gap-[var(--cmp-chipFilter-listbox-bottom-gap)] border-t border-solid px-[var(--cmp-chipFilter-listbox-bottom-paddingX)] py-[var(--cmp-chipFilter-listbox-bottom-paddingY)]",
|
|
18070
18240
|
style: { borderColor: CHIPFILTER.listboxBorder },
|
|
18071
18241
|
children: [
|
|
18072
18242
|
isMulti && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -18181,6 +18351,7 @@ function DatePresetEditor({
|
|
|
18181
18351
|
onValueChange
|
|
18182
18352
|
}) {
|
|
18183
18353
|
const presets = getFieldPresets(field);
|
|
18354
|
+
const maxRange = getEffectiveMaxRange(field);
|
|
18184
18355
|
const [selectedId, setSelectedId] = useState(() => matchPresetId(presets, value));
|
|
18185
18356
|
const syncedInitialValueRef = useRef(!isEmptyValue(value));
|
|
18186
18357
|
useEffect(() => {
|
|
@@ -18191,7 +18362,13 @@ function DatePresetEditor({
|
|
|
18191
18362
|
const selectedPreset = presets.find((preset) => preset.value === selectedId);
|
|
18192
18363
|
const selectPreset = (preset) => {
|
|
18193
18364
|
setSelectedId(preset.value);
|
|
18194
|
-
if (!preset.custom)
|
|
18365
|
+
if (!preset.custom) {
|
|
18366
|
+
onValueChange(preset.resolve ? preset.resolve() : preset.value);
|
|
18367
|
+
return;
|
|
18368
|
+
}
|
|
18369
|
+
const today = todayIso();
|
|
18370
|
+
const days = maxRange && maxRange > 0 ? maxRange : DEFAULT_CUSTOM_MAX_RANGE;
|
|
18371
|
+
onValueChange([addDaysIso(today, -days), today]);
|
|
18195
18372
|
};
|
|
18196
18373
|
if (presets.length === 0) {
|
|
18197
18374
|
return /* @__PURE__ */ jsx(
|
|
@@ -18200,7 +18377,7 @@ function DatePresetEditor({
|
|
|
18200
18377
|
value: Array.isArray(value) && value.length === 2 ? value : null,
|
|
18201
18378
|
onValueChange,
|
|
18202
18379
|
selectable: field.selectable,
|
|
18203
|
-
maxRange
|
|
18380
|
+
maxRange,
|
|
18204
18381
|
disabled,
|
|
18205
18382
|
width: "100%"
|
|
18206
18383
|
}
|
|
@@ -18212,7 +18389,7 @@ function DatePresetEditor({
|
|
|
18212
18389
|
{
|
|
18213
18390
|
val: preset.value,
|
|
18214
18391
|
value: selectedId,
|
|
18215
|
-
label: preset
|
|
18392
|
+
label: getPresetLabel(preset, maxRange),
|
|
18216
18393
|
disabled,
|
|
18217
18394
|
onValueChange: () => selectPreset(preset)
|
|
18218
18395
|
},
|
|
@@ -18224,7 +18401,7 @@ function DatePresetEditor({
|
|
|
18224
18401
|
value: Array.isArray(value) && value.length === 2 ? value : null,
|
|
18225
18402
|
onValueChange,
|
|
18226
18403
|
selectable: field.selectable,
|
|
18227
|
-
maxRange
|
|
18404
|
+
maxRange,
|
|
18228
18405
|
disabled
|
|
18229
18406
|
}
|
|
18230
18407
|
)
|
|
@@ -18237,9 +18414,10 @@ function PeriodPresetEditor({
|
|
|
18237
18414
|
onValueChange
|
|
18238
18415
|
}) {
|
|
18239
18416
|
const presets = getFieldPresets(field);
|
|
18417
|
+
const maxRange = getEffectiveMaxRange(field);
|
|
18240
18418
|
const firstUnit = presets.find((preset) => !preset.custom)?.value ?? "day";
|
|
18241
18419
|
const [selectedId, setSelectedId] = useState(() => matchPresetId(presets, value) ?? firstUnit);
|
|
18242
|
-
const periodValue = isPeriodValue(value) ? value : createPeriodValue(selectedId ?? firstUnit);
|
|
18420
|
+
const periodValue = isPeriodValue(value) ? value : createPeriodValue(selectedId ?? firstUnit, maxRange);
|
|
18243
18421
|
const selectedUnit = selectedId ?? periodValue.unit;
|
|
18244
18422
|
useEffect(() => {
|
|
18245
18423
|
if (isEmptyValue(value)) return;
|
|
@@ -18248,7 +18426,7 @@ function PeriodPresetEditor({
|
|
|
18248
18426
|
const selectPreset = (preset) => {
|
|
18249
18427
|
const nextUnit = preset.value;
|
|
18250
18428
|
setSelectedId(nextUnit);
|
|
18251
|
-
onValueChange(createPeriodValue(nextUnit));
|
|
18429
|
+
onValueChange(createPeriodValue(nextUnit, maxRange));
|
|
18252
18430
|
};
|
|
18253
18431
|
const updateInputValue = (nextValue) => {
|
|
18254
18432
|
onValueChange({ unit: selectedUnit, value: nextValue });
|
|
@@ -18331,7 +18509,7 @@ function PeriodPresetEditor({
|
|
|
18331
18509
|
value: Array.isArray(periodValue.value) && periodValue.value.length === 2 ? periodValue.value : null,
|
|
18332
18510
|
onValueChange: updateInputValue,
|
|
18333
18511
|
selectable: field.selectable,
|
|
18334
|
-
maxRange
|
|
18512
|
+
maxRange,
|
|
18335
18513
|
disabled,
|
|
18336
18514
|
width: "100%"
|
|
18337
18515
|
}
|
|
@@ -18343,7 +18521,7 @@ function PeriodPresetEditor({
|
|
|
18343
18521
|
{
|
|
18344
18522
|
val: preset.value,
|
|
18345
18523
|
value: selectedId,
|
|
18346
|
-
label: preset
|
|
18524
|
+
label: getPresetLabel(preset, maxRange),
|
|
18347
18525
|
disabled,
|
|
18348
18526
|
onValueChange: () => selectPreset(preset)
|
|
18349
18527
|
},
|
|
@@ -18379,6 +18557,10 @@ function InlineDatePresetFilter({
|
|
|
18379
18557
|
setSelectedId(preset.value);
|
|
18380
18558
|
onValueChange(preset.resolve ? preset.resolve() : null);
|
|
18381
18559
|
};
|
|
18560
|
+
const badgeBorder = disabled ? CHIPFILTER.chipDisabledBorder : warning ? CHIPFILTER.chipWarningBorder : CHIPFILTER.chipAppliedBorder;
|
|
18561
|
+
const badgeBackground = disabled ? CHIPFILTER.chipDisabledBg : CHIPFILTER.chipAppliedBg;
|
|
18562
|
+
const badgeLabelColor = disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedLabel;
|
|
18563
|
+
const badgeValueColor = disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedValue;
|
|
18382
18564
|
const badge = applied && /* @__PURE__ */ jsxs(
|
|
18383
18565
|
"span",
|
|
18384
18566
|
{
|
|
@@ -18386,17 +18568,17 @@ function InlineDatePresetFilter({
|
|
|
18386
18568
|
style: {
|
|
18387
18569
|
minHeight: CHIPFILTER.chipHeight,
|
|
18388
18570
|
borderRadius: CHIPFILTER.chipRadius,
|
|
18389
|
-
borderColor:
|
|
18390
|
-
background:
|
|
18391
|
-
color:
|
|
18392
|
-
cursor: rangeValue ? "pointer" : void 0
|
|
18571
|
+
borderColor: badgeBorder,
|
|
18572
|
+
background: badgeBackground,
|
|
18573
|
+
color: badgeLabelColor,
|
|
18574
|
+
cursor: rangeValue && !disabled ? "pointer" : void 0
|
|
18393
18575
|
},
|
|
18394
18576
|
children: [
|
|
18395
18577
|
/* @__PURE__ */ jsxs("span", { className: "font-bold", children: [
|
|
18396
18578
|
field.label,
|
|
18397
18579
|
":"
|
|
18398
18580
|
] }),
|
|
18399
|
-
/* @__PURE__ */ jsx("span", { className: "font-bold", style: { color:
|
|
18581
|
+
/* @__PURE__ */ jsx("span", { className: "font-bold", style: { color: badgeValueColor }, children: displayValue(field, value) }),
|
|
18400
18582
|
!disabled && showClear && /* @__PURE__ */ jsx(
|
|
18401
18583
|
"span",
|
|
18402
18584
|
{
|
|
@@ -18551,7 +18733,7 @@ function KeywordEditor({
|
|
|
18551
18733
|
}
|
|
18552
18734
|
};
|
|
18553
18735
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
18554
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)] px-[var(--cmp-chipFilter-listbox-top-paddingX)] py-[var(--cmp-chipFilter-listbox-top-paddingY)]", children: [
|
|
18736
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)] px-[var(--cmp-chipFilter-listbox-top-paddingX)] py-[var(--cmp-chipFilter-listbox-top-paddingY)]", children: [
|
|
18555
18737
|
field.matchModes && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
18556
18738
|
/* @__PURE__ */ jsx(
|
|
18557
18739
|
"span",
|
|
@@ -18593,7 +18775,7 @@ function KeywordEditor({
|
|
|
18593
18775
|
entries3.length > 0 && /* @__PURE__ */ jsx(
|
|
18594
18776
|
"div",
|
|
18595
18777
|
{
|
|
18596
|
-
className: "
|
|
18778
|
+
className: "min-h-0 flex-1 overflow-auto border-t border-solid py-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
18597
18779
|
style: { borderColor: CHIPFILTER.listboxBorder },
|
|
18598
18780
|
children: entries3.map((entry) => /* @__PURE__ */ jsx(
|
|
18599
18781
|
KeywordEntryRow,
|
|
@@ -18651,6 +18833,7 @@ function OptionList({
|
|
|
18651
18833
|
const selected = multiple ? toArrayValue(value) : [];
|
|
18652
18834
|
const singleValue = !multiple && (typeof value === "string" || typeof value === "number") ? value : null;
|
|
18653
18835
|
const [search, setSearch] = useState("");
|
|
18836
|
+
const searchInputRef = useRef(null);
|
|
18654
18837
|
const options = field.options ?? [];
|
|
18655
18838
|
const showSearch = options.length >= OPTION_SEARCH_THRESHOLD;
|
|
18656
18839
|
const filteredOptions = useMemo(() => {
|
|
@@ -18658,74 +18841,70 @@ function OptionList({
|
|
|
18658
18841
|
const query = search.trim().toLowerCase();
|
|
18659
18842
|
return options.filter((option) => option.label.toLowerCase().includes(query));
|
|
18660
18843
|
}, [options, search, showSearch]);
|
|
18844
|
+
useEffect(() => {
|
|
18845
|
+
if (!showSearch || disabled) return;
|
|
18846
|
+
searchInputRef.current?.focus();
|
|
18847
|
+
}, [showSearch, disabled]);
|
|
18661
18848
|
if (options.length === 0) return /* @__PURE__ */ jsx(EmptyItem, { children: "\uD45C\uC2DC\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." });
|
|
18662
|
-
return /* @__PURE__ */ jsxs(
|
|
18663
|
-
|
|
18664
|
-
|
|
18665
|
-
|
|
18666
|
-
"
|
|
18667
|
-
|
|
18668
|
-
|
|
18669
|
-
|
|
18670
|
-
children: [
|
|
18671
|
-
showSearch && /* @__PURE__ */ jsx(
|
|
18672
|
-
"div",
|
|
18849
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [
|
|
18850
|
+
showSearch && /* @__PURE__ */ jsx(
|
|
18851
|
+
"div",
|
|
18852
|
+
{
|
|
18853
|
+
className: "shrink-0 border-b border-solid px-[8px] pb-[4px] pt-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
18854
|
+
style: { borderColor: CHIPFILTER.listboxBorder },
|
|
18855
|
+
children: /* @__PURE__ */ jsx(
|
|
18856
|
+
SSearchInput,
|
|
18673
18857
|
{
|
|
18674
|
-
|
|
18675
|
-
|
|
18676
|
-
|
|
18677
|
-
|
|
18678
|
-
|
|
18679
|
-
|
|
18680
|
-
|
|
18681
|
-
|
|
18682
|
-
disabled,
|
|
18683
|
-
placeholder: "\uAC80\uC0C9",
|
|
18684
|
-
onChange: (event) => setSearch(event.target.value),
|
|
18685
|
-
className: "min-w-0 flex-1 border-none bg-transparent text-[12px] leading-[20px] text-[color:var(--sys-color-field-text-default)] outline-none placeholder:text-[color:var(--sys-color-field-text-placeholder)] disabled:cursor-not-allowed"
|
|
18686
|
-
}
|
|
18687
|
-
),
|
|
18688
|
-
search !== "" && !disabled && /* @__PURE__ */ jsx(
|
|
18689
|
-
SGhostButton,
|
|
18690
|
-
{
|
|
18691
|
-
icon: "close",
|
|
18692
|
-
size: "xxs",
|
|
18693
|
-
ariaLabel: "\uAC80\uC0C9\uC5B4 \uC9C0\uC6B0\uAE30",
|
|
18694
|
-
className: "flex-shrink-0",
|
|
18695
|
-
onClick: () => setSearch("")
|
|
18696
|
-
}
|
|
18697
|
-
)
|
|
18698
|
-
] })
|
|
18858
|
+
ref: searchInputRef,
|
|
18859
|
+
size: "sm",
|
|
18860
|
+
value: search,
|
|
18861
|
+
onValueChange: setSearch,
|
|
18862
|
+
disabled,
|
|
18863
|
+
placeholder: "\uAC80\uC0C9",
|
|
18864
|
+
clearable: true,
|
|
18865
|
+
width: "100%"
|
|
18699
18866
|
}
|
|
18867
|
+
)
|
|
18868
|
+
}
|
|
18869
|
+
),
|
|
18870
|
+
/* @__PURE__ */ jsxs(
|
|
18871
|
+
"div",
|
|
18872
|
+
{
|
|
18873
|
+
className: cn(
|
|
18874
|
+
"min-h-0 flex-1 overflow-auto",
|
|
18875
|
+
!showSearch && "pt-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
18876
|
+
"pb-[var(--cmp-chipFilter-listbox-list-paddingY)]"
|
|
18700
18877
|
),
|
|
18701
|
-
|
|
18702
|
-
|
|
18703
|
-
|
|
18704
|
-
|
|
18705
|
-
|
|
18706
|
-
|
|
18707
|
-
|
|
18708
|
-
|
|
18709
|
-
|
|
18710
|
-
|
|
18711
|
-
|
|
18712
|
-
|
|
18713
|
-
|
|
18714
|
-
|
|
18715
|
-
|
|
18716
|
-
|
|
18878
|
+
children: [
|
|
18879
|
+
showSearch && filteredOptions.length === 0 && /* @__PURE__ */ jsx(EmptyItem, { children: "\uAC80\uC0C9 \uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4." }),
|
|
18880
|
+
filteredOptions.map((option) => {
|
|
18881
|
+
const checked = multiple ? selected.includes(option.value) : singleValue === option.value;
|
|
18882
|
+
return /* @__PURE__ */ jsxs(
|
|
18883
|
+
MenuItem,
|
|
18884
|
+
{
|
|
18885
|
+
selected: checked,
|
|
18886
|
+
disabled: disabled || option.disabled,
|
|
18887
|
+
multi: multiple,
|
|
18888
|
+
onClick: () => {
|
|
18889
|
+
if (multiple) {
|
|
18890
|
+
const next = checked ? selected.filter((v) => v !== option.value) : [...selected, option.value];
|
|
18891
|
+
onValueChange(next);
|
|
18892
|
+
} else {
|
|
18893
|
+
onValueChange(option.value);
|
|
18894
|
+
}
|
|
18895
|
+
},
|
|
18896
|
+
children: [
|
|
18897
|
+
multiple && /* @__PURE__ */ jsx(OptionCheckbox, { checked }),
|
|
18898
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: option.label })
|
|
18899
|
+
]
|
|
18717
18900
|
},
|
|
18718
|
-
|
|
18719
|
-
|
|
18720
|
-
|
|
18721
|
-
|
|
18722
|
-
|
|
18723
|
-
|
|
18724
|
-
|
|
18725
|
-
})
|
|
18726
|
-
]
|
|
18727
|
-
}
|
|
18728
|
-
);
|
|
18901
|
+
String(option.value)
|
|
18902
|
+
);
|
|
18903
|
+
})
|
|
18904
|
+
]
|
|
18905
|
+
}
|
|
18906
|
+
)
|
|
18907
|
+
] });
|
|
18729
18908
|
}
|
|
18730
18909
|
function OptionCheckbox({ checked }) {
|
|
18731
18910
|
return /* @__PURE__ */ jsx(
|
|
@@ -18739,15 +18918,22 @@ function OptionCheckbox({ checked }) {
|
|
|
18739
18918
|
}
|
|
18740
18919
|
);
|
|
18741
18920
|
}
|
|
18742
|
-
function ListBox({
|
|
18921
|
+
function ListBox({
|
|
18922
|
+
children,
|
|
18923
|
+
maxHeight
|
|
18924
|
+
}) {
|
|
18743
18925
|
return /* @__PURE__ */ jsx(
|
|
18744
18926
|
"div",
|
|
18745
18927
|
{
|
|
18746
|
-
className:
|
|
18928
|
+
className: cn(
|
|
18929
|
+
"overflow-hidden border border-solid shadow-[var(--shadow-overlay)]",
|
|
18930
|
+
maxHeight && "flex flex-col"
|
|
18931
|
+
),
|
|
18747
18932
|
style: {
|
|
18748
18933
|
borderRadius: CHIPFILTER.listboxRadius,
|
|
18749
18934
|
background: CHIPFILTER.listboxBg,
|
|
18750
|
-
borderColor: CHIPFILTER.listboxBorder
|
|
18935
|
+
borderColor: CHIPFILTER.listboxBorder,
|
|
18936
|
+
maxHeight
|
|
18751
18937
|
},
|
|
18752
18938
|
children
|
|
18753
18939
|
}
|