sellmate-design-system-react 0.8.3 → 0.9.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/components/SBarcodeInput/SBarcodeInput.cjs +78 -2
- package/dist/components/SBarcodeInput/SBarcodeInput.cjs.map +1 -1
- package/dist/components/SBarcodeInput/SBarcodeInput.js +78 -2
- package/dist/components/SBarcodeInput/SBarcodeInput.js.map +1 -1
- package/dist/components/SChipInput/SChipInput.cjs +78 -2
- package/dist/components/SChipInput/SChipInput.cjs.map +1 -1
- package/dist/components/SChipInput/SChipInput.js +78 -2
- package/dist/components/SChipInput/SChipInput.js.map +1 -1
- package/dist/components/SDatePicker/SDatePicker.cjs +78 -2
- package/dist/components/SDatePicker/SDatePicker.cjs.map +1 -1
- package/dist/components/SDatePicker/SDatePicker.js +78 -2
- package/dist/components/SDatePicker/SDatePicker.js.map +1 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.cjs +78 -2
- package/dist/components/SDateRangePicker/SDateRangePicker.cjs.map +1 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.js +78 -2
- package/dist/components/SDateRangePicker/SDateRangePicker.js.map +1 -1
- package/dist/components/SField/SField.cjs +78 -2
- package/dist/components/SField/SField.cjs.map +1 -1
- package/dist/components/SField/SField.js +78 -2
- package/dist/components/SField/SField.js.map +1 -1
- package/dist/components/SFilePicker/SFilePicker.cjs +78 -2
- package/dist/components/SFilePicker/SFilePicker.cjs.map +1 -1
- package/dist/components/SFilePicker/SFilePicker.js +78 -2
- package/dist/components/SFilePicker/SFilePicker.js.map +1 -1
- package/dist/components/SGnb/SGnb.cjs +58 -16
- package/dist/components/SGnb/SGnb.cjs.map +1 -1
- package/dist/components/SGnb/SGnb.d.ts +15 -0
- package/dist/components/SGnb/SGnb.js +58 -16
- package/dist/components/SGnb/SGnb.js.map +1 -1
- package/dist/components/SInput/SInput.cjs +78 -2
- package/dist/components/SInput/SInput.cjs.map +1 -1
- package/dist/components/SInput/SInput.js +78 -2
- package/dist/components/SInput/SInput.js.map +1 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.cjs +224 -118
- package/dist/components/SKeyValueTable/SKeyValueTable.cjs.map +1 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.js +224 -118
- package/dist/components/SKeyValueTable/SKeyValueTable.js.map +1 -1
- package/dist/components/SNumberInput/SNumberInput.cjs +78 -2
- package/dist/components/SNumberInput/SNumberInput.cjs.map +1 -1
- package/dist/components/SNumberInput/SNumberInput.js +78 -2
- package/dist/components/SNumberInput/SNumberInput.js.map +1 -1
- package/dist/components/SSelect/SSelect.cjs +155 -49
- package/dist/components/SSelect/SSelect.cjs.map +1 -1
- package/dist/components/SSelect/SSelect.js +155 -49
- package/dist/components/SSelect/SSelect.js.map +1 -1
- package/dist/components/SSelect/select.config.d.ts +7 -0
- package/dist/components/STable/STable.cjs +155 -49
- package/dist/components/STable/STable.cjs.map +1 -1
- package/dist/components/STable/STable.js +155 -49
- package/dist/components/STable/STable.js.map +1 -1
- package/dist/components/STextarea/STextarea.cjs +78 -2
- package/dist/components/STextarea/STextarea.cjs.map +1 -1
- package/dist/components/STextarea/STextarea.js +78 -2
- package/dist/components/STextarea/STextarea.js.map +1 -1
- package/dist/components/STimePicker/STimePicker.cjs +78 -2
- package/dist/components/STimePicker/STimePicker.cjs.map +1 -1
- package/dist/components/STimePicker/STimePicker.js +78 -2
- package/dist/components/STimePicker/STimePicker.js.map +1 -1
- package/dist/components/STimeRangePicker/STimeRangePicker.cjs +78 -2
- package/dist/components/STimeRangePicker/STimeRangePicker.cjs.map +1 -1
- package/dist/components/STimeRangePicker/STimeRangePicker.js +78 -2
- package/dist/components/STimeRangePicker/STimeRangePicker.js.map +1 -1
- package/dist/components/STooltip/STooltip.cjs +78 -2
- package/dist/components/STooltip/STooltip.cjs.map +1 -1
- package/dist/components/STooltip/STooltip.d.ts +1 -1
- package/dist/components/STooltip/STooltip.js +78 -2
- package/dist/components/STooltip/STooltip.js.map +1 -1
- package/dist/index.cjs +209 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +209 -65
- package/dist/index.js.map +1 -1
- package/dist/styles.css +35 -8
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4175,7 +4175,14 @@ function useBody(content, message = []) {
|
|
|
4175
4175
|
if (content != null) return content;
|
|
4176
4176
|
if (message.length === 0) return null;
|
|
4177
4177
|
const singleLine = message.length === 1;
|
|
4178
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: message.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4178
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: message.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4179
|
+
"div",
|
|
4180
|
+
{
|
|
4181
|
+
className: singleLine ? "leading-[24px]" : void 0,
|
|
4182
|
+
dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(line) }
|
|
4183
|
+
},
|
|
4184
|
+
i
|
|
4185
|
+
)) });
|
|
4179
4186
|
}
|
|
4180
4187
|
var STooltip = react.forwardRef(function STooltip2({
|
|
4181
4188
|
content,
|
|
@@ -4233,7 +4240,7 @@ var STooltip = react.forwardRef(function STooltip2({
|
|
|
4233
4240
|
if (disabled || body == null) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: triggerNode });
|
|
4234
4241
|
const isHover = trigger === "hover";
|
|
4235
4242
|
const contentClass = cn(
|
|
4236
|
-
"z-50
|
|
4243
|
+
"z-50 w-fit whitespace-nowrap rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px]",
|
|
4237
4244
|
FLOATING_SLIDE_ANIM,
|
|
4238
4245
|
className
|
|
4239
4246
|
);
|
|
@@ -5188,6 +5195,9 @@ var SGnb = react.forwardRef(function SGnb2({
|
|
|
5188
5195
|
onFoldChange,
|
|
5189
5196
|
onLauncherClick,
|
|
5190
5197
|
logo,
|
|
5198
|
+
railFooter,
|
|
5199
|
+
menuFooter,
|
|
5200
|
+
foldedFooter,
|
|
5191
5201
|
ariaLabel = "global navigation",
|
|
5192
5202
|
className,
|
|
5193
5203
|
style,
|
|
@@ -5341,7 +5351,7 @@ var SGnb = react.forwardRef(function SGnb2({
|
|
|
5341
5351
|
className: "shrink-0"
|
|
5342
5352
|
}
|
|
5343
5353
|
),
|
|
5344
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap flex
|
|
5354
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap flex items-center", children: [
|
|
5345
5355
|
depth > 1 && iconBranch ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5346
5356
|
"div",
|
|
5347
5357
|
{
|
|
@@ -5552,42 +5562,77 @@ var SGnb = react.forwardRef(function SGnb2({
|
|
|
5552
5562
|
transition: `transform ${GNB_FOLD_MS}ms ease-out, ${hideAfterSlide(folded)}`
|
|
5553
5563
|
},
|
|
5554
5564
|
children: [
|
|
5555
|
-
useRail && //
|
|
5556
|
-
//
|
|
5557
|
-
|
|
5558
|
-
|
|
5565
|
+
useRail && // 레일 컬럼 — 스크롤되는 아이템 목록(nav)과 하단 고정 footer 를 한 컬럼에 담는다.
|
|
5566
|
+
// footer 는 내비게이션이 아니므로 nav(landmark) 밖에 두고, 컬럼 폭·구분선·배경은 이 래퍼가
|
|
5567
|
+
// 전체 높이에 걸쳐 책임진다(그래야 footer 자리까지 배경·오른쪽 선이 이어진다).
|
|
5568
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5569
|
+
"div",
|
|
5559
5570
|
{
|
|
5560
|
-
"
|
|
5561
|
-
className: "flex shrink-0 flex-col overflow-y-auto",
|
|
5571
|
+
className: "flex shrink-0 flex-col overflow-hidden",
|
|
5562
5572
|
style: {
|
|
5563
5573
|
width: GNB_RAIL_WIDTH,
|
|
5564
|
-
padding: GNB_RAIL.padding,
|
|
5565
5574
|
borderRight: `1px solid ${C.topBorder}`,
|
|
5566
5575
|
backgroundColor: C.panelBg,
|
|
5567
5576
|
pointerEvents: "auto"
|
|
5568
5577
|
},
|
|
5569
|
-
children:
|
|
5578
|
+
children: [
|
|
5579
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5580
|
+
"nav",
|
|
5581
|
+
{
|
|
5582
|
+
"aria-label": `${ariaLabel} rail`,
|
|
5583
|
+
className: cn(
|
|
5584
|
+
"flex min-h-0 flex-1 flex-col overflow-x-hidden overflow-y-auto",
|
|
5585
|
+
SCROLLBAR_CLASS
|
|
5586
|
+
),
|
|
5587
|
+
style: { padding: GNB_RAIL.padding },
|
|
5588
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "m-0 flex list-none flex-col p-0", style: { gap: GNB_RAIL.gap }, children: railItems.map(renderRailItem) })
|
|
5589
|
+
}
|
|
5590
|
+
),
|
|
5591
|
+
railFooter && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: railFooter })
|
|
5592
|
+
]
|
|
5570
5593
|
}
|
|
5571
5594
|
),
|
|
5572
|
-
showMenu && /* @__PURE__ */ jsxRuntime.
|
|
5573
|
-
"
|
|
5595
|
+
showMenu && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5596
|
+
"div",
|
|
5574
5597
|
{
|
|
5575
|
-
"
|
|
5576
|
-
className: "flex shrink-0 flex-col overflow-y-auto",
|
|
5598
|
+
className: "flex shrink-0 flex-col overflow-hidden",
|
|
5577
5599
|
style: {
|
|
5578
5600
|
width: GNB_MENU_WIDTH,
|
|
5579
|
-
paddingTop: M.bodyPaddingY,
|
|
5580
|
-
paddingBottom: M.bodyPaddingY,
|
|
5581
5601
|
backgroundColor: C.panelBg,
|
|
5582
5602
|
// full 은 상단바가 전폭이라 루트가 오른쪽 선을 못 그린다 → 메뉴 오른쪽(페이지 경계)이 대신 그린다.
|
|
5583
5603
|
borderRight: header === "full" ? rightBorder : void 0,
|
|
5584
5604
|
pointerEvents: "auto"
|
|
5585
5605
|
},
|
|
5586
|
-
children:
|
|
5606
|
+
children: [
|
|
5607
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5608
|
+
"nav",
|
|
5609
|
+
{
|
|
5610
|
+
"aria-label": ariaLabel,
|
|
5611
|
+
className: cn(
|
|
5612
|
+
"flex min-h-0 flex-1 flex-col overflow-x-hidden overflow-y-auto",
|
|
5613
|
+
SCROLLBAR_CLASS
|
|
5614
|
+
),
|
|
5615
|
+
style: {
|
|
5616
|
+
paddingTop: M.bodyPaddingY,
|
|
5617
|
+
paddingBottom: M.bodyPaddingY
|
|
5618
|
+
},
|
|
5619
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "m-0 flex list-none flex-col p-0", children: menuItems.map((item) => renderItem(item, 1)) })
|
|
5620
|
+
}
|
|
5621
|
+
),
|
|
5622
|
+
menuFooter && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: menuFooter })
|
|
5623
|
+
]
|
|
5587
5624
|
}
|
|
5588
5625
|
)
|
|
5589
5626
|
]
|
|
5590
5627
|
}
|
|
5628
|
+
),
|
|
5629
|
+
railFolded && foldedFooter && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5630
|
+
"div",
|
|
5631
|
+
{
|
|
5632
|
+
className: "flex shrink-0 items-center justify-center mb-[24px]",
|
|
5633
|
+
style: { pointerEvents: "auto" },
|
|
5634
|
+
children: foldedFooter
|
|
5635
|
+
}
|
|
5591
5636
|
)
|
|
5592
5637
|
]
|
|
5593
5638
|
}
|
|
@@ -6316,6 +6361,16 @@ function flattenOptions(options, depth = 1) {
|
|
|
6316
6361
|
return out;
|
|
6317
6362
|
}
|
|
6318
6363
|
var selectableOptions = (flat) => flat.filter((o) => !o.isGroup && !o.disabled);
|
|
6364
|
+
function collectGroupLeafValues(flat, groupIndex) {
|
|
6365
|
+
const group = flat[groupIndex];
|
|
6366
|
+
if (group == null || !group.isGroup) return [];
|
|
6367
|
+
const values = [];
|
|
6368
|
+
for (let i = groupIndex + 1; i < flat.length; i++) {
|
|
6369
|
+
if (flat[i].depth <= group.depth) break;
|
|
6370
|
+
if (!flat[i].isGroup && !flat[i].disabled) values.push(flat[i].value);
|
|
6371
|
+
}
|
|
6372
|
+
return values;
|
|
6373
|
+
}
|
|
6319
6374
|
var isHtmlLabel = (label) => /<[a-z][\s\S]*>/i.test(label);
|
|
6320
6375
|
var extractText = (html) => html.replace(/<[^>]*>/g, "");
|
|
6321
6376
|
var SEARCH_THRESHOLD = 11;
|
|
@@ -6441,16 +6496,31 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
6441
6496
|
const allValues = selectable.map((o) => o.value);
|
|
6442
6497
|
const allSelected = allValues.length > 0 && allValues.every((v) => selected.includes(v));
|
|
6443
6498
|
const hasItems = filtered.some((o) => !o.isGroup);
|
|
6499
|
+
const groupLeafValues = react.useMemo(() => {
|
|
6500
|
+
const map = /* @__PURE__ */ new Map();
|
|
6501
|
+
filtered.forEach((o, i) => {
|
|
6502
|
+
if (o.isGroup) map.set(i, collectGroupLeafValues(filtered, i));
|
|
6503
|
+
});
|
|
6504
|
+
return map;
|
|
6505
|
+
}, [filtered]);
|
|
6444
6506
|
const navigableItems = react.useMemo(() => {
|
|
6445
6507
|
const items = [];
|
|
6446
6508
|
if (multi && useSelectAll && allValues.length > 0) {
|
|
6447
|
-
items.push({
|
|
6509
|
+
items.push({ key: "__select_all__", isSelectAll: true });
|
|
6448
6510
|
}
|
|
6449
|
-
filtered.forEach((o) => {
|
|
6450
|
-
if (
|
|
6511
|
+
filtered.forEach((o, i) => {
|
|
6512
|
+
if (o.disabled) return;
|
|
6513
|
+
if (o.isGroup) {
|
|
6514
|
+
if (!multi) return;
|
|
6515
|
+
const leafValues = groupLeafValues.get(i) ?? [];
|
|
6516
|
+
if (leafValues.length === 0) return;
|
|
6517
|
+
items.push({ key: `__group_${i}__`, isGroup: true, leafValues });
|
|
6518
|
+
} else {
|
|
6519
|
+
items.push({ key: o.value, value: o.value });
|
|
6520
|
+
}
|
|
6451
6521
|
});
|
|
6452
6522
|
return items;
|
|
6453
|
-
}, [allValues.length, filtered, multi, useSelectAll]);
|
|
6523
|
+
}, [allValues.length, filtered, groupLeafValues, multi, useSelectAll]);
|
|
6454
6524
|
const triggerText = (() => {
|
|
6455
6525
|
if (selected.length === 0) return placeholder;
|
|
6456
6526
|
if (multi) {
|
|
@@ -6472,6 +6542,17 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
6472
6542
|
const handleSelectAll = () => {
|
|
6473
6543
|
emit2(allSelected ? [] : allValues);
|
|
6474
6544
|
};
|
|
6545
|
+
const handleToggleGroup = (leafValues) => {
|
|
6546
|
+
if (leafValues.length === 0) return;
|
|
6547
|
+
const selectedSet = new Set(selected);
|
|
6548
|
+
const allSelectedInGroup = leafValues.every((v) => selectedSet.has(v));
|
|
6549
|
+
if (allSelectedInGroup) {
|
|
6550
|
+
const remove = new Set(leafValues);
|
|
6551
|
+
emit2(selected.filter((v) => !remove.has(v)));
|
|
6552
|
+
} else {
|
|
6553
|
+
emit2([...selected, ...leafValues.filter((v) => !selectedSet.has(v))]);
|
|
6554
|
+
}
|
|
6555
|
+
};
|
|
6475
6556
|
react.useEffect(() => {
|
|
6476
6557
|
if (!open) {
|
|
6477
6558
|
setFocusedIndex(-1);
|
|
@@ -6512,6 +6593,10 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
6512
6593
|
handleSelectAll();
|
|
6513
6594
|
return;
|
|
6514
6595
|
}
|
|
6596
|
+
if (focused.isGroup) {
|
|
6597
|
+
handleToggleGroup(focused.leafValues ?? []);
|
|
6598
|
+
return;
|
|
6599
|
+
}
|
|
6515
6600
|
handleSelect(focused.value);
|
|
6516
6601
|
};
|
|
6517
6602
|
const handleKeyDown = (event) => {
|
|
@@ -6675,20 +6760,20 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
6675
6760
|
items: filtered,
|
|
6676
6761
|
multi,
|
|
6677
6762
|
selected,
|
|
6678
|
-
|
|
6763
|
+
groupLeafValues,
|
|
6764
|
+
focusedValue: navigableItems[focusedIndex]?.key,
|
|
6679
6765
|
showSelectAll: multi && useSelectAll && allValues.length > 0,
|
|
6680
6766
|
selectAllLabel: allSelectedLabel,
|
|
6681
6767
|
selectAllSelected: allSelected,
|
|
6682
6768
|
onSelectAll: handleSelectAll,
|
|
6683
6769
|
onSelect: handleSelect,
|
|
6684
|
-
|
|
6685
|
-
|
|
6770
|
+
onToggleGroup: handleToggleGroup,
|
|
6771
|
+
onHoverValue: (key) => {
|
|
6772
|
+
if (key == null) {
|
|
6686
6773
|
setFocusedIndex(-1);
|
|
6687
6774
|
return;
|
|
6688
6775
|
}
|
|
6689
|
-
const index = navigableItems.findIndex(
|
|
6690
|
-
(item) => item.isSelectAll ? value2 === "__select_all__" : item.value === value2
|
|
6691
|
-
);
|
|
6776
|
+
const index = navigableItems.findIndex((item) => item.key === key);
|
|
6692
6777
|
if (index >= 0) setFocusedIndex(index);
|
|
6693
6778
|
}
|
|
6694
6779
|
}
|
|
@@ -6707,20 +6792,23 @@ function ItemList({
|
|
|
6707
6792
|
items,
|
|
6708
6793
|
multi,
|
|
6709
6794
|
selected,
|
|
6795
|
+
groupLeafValues,
|
|
6710
6796
|
focusedValue,
|
|
6711
6797
|
showSelectAll,
|
|
6712
6798
|
selectAllLabel,
|
|
6713
6799
|
selectAllSelected,
|
|
6714
6800
|
onSelectAll,
|
|
6715
6801
|
onSelect,
|
|
6802
|
+
onToggleGroup,
|
|
6716
6803
|
onHoverValue
|
|
6717
6804
|
}) {
|
|
6805
|
+
const selectedSet = react.useMemo(() => new Set(selected), [selected]);
|
|
6718
6806
|
const itemBase = cn(
|
|
6719
6807
|
"group flex w-full cursor-pointer select-none items-center gap-[8px] border-none bg-transparent text-left text-[12px] leading-[20px] outline-none",
|
|
6720
6808
|
"text-[color:var(--cmp-listItem-content-default)]",
|
|
6721
6809
|
"disabled:cursor-not-allowed disabled:text-[color:var(--cmp-listItem-content-disabled)]"
|
|
6722
6810
|
);
|
|
6723
|
-
const activeClass = "hover:bg-[var(--cmp-listItem-bg-hover)] hover:text-[color:var(--cmp-listItem-content-hover)] focus:bg-[var(--cmp-listItem-bg-hover)] focus:text-[color:var(--cmp-listItem-content-hover)]";
|
|
6811
|
+
const activeClass = "hover:bg-[var(--cmp-listItem-bg-hover)] hover:text-[color:var(--cmp-listItem-content-hover)] focus-visible:bg-[var(--cmp-listItem-bg-hover)] focus-visible:text-[color:var(--cmp-listItem-content-hover)]";
|
|
6724
6812
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "listbox", "aria-multiselectable": multi || void 0, children: [
|
|
6725
6813
|
showSelectAll && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6726
6814
|
"button",
|
|
@@ -6737,23 +6825,7 @@ function ItemList({
|
|
|
6737
6825
|
onMouseLeave: () => onHoverValue(null),
|
|
6738
6826
|
onClick: onSelectAll,
|
|
6739
6827
|
children: [
|
|
6740
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6741
|
-
"span",
|
|
6742
|
-
{
|
|
6743
|
-
className: cn(
|
|
6744
|
-
"flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid",
|
|
6745
|
-
selectAllSelected ? focusedValue === "__select_all__" ? "border-[color:var(--cmp-checkbox-checked-border-inverse)] bg-[var(--cmp-checkbox-checked-bg-default)]" : "border-[color:var(--cmp-checkbox-checked-bg-default)] bg-[var(--cmp-checkbox-checked-bg-default)]" : "border-[color:var(--cmp-checkbox-unchecked-border-default)] bg-[var(--cmp-checkbox-unchecked-bg-default)]"
|
|
6746
|
-
),
|
|
6747
|
-
children: selectAllSelected && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6748
|
-
SIcon,
|
|
6749
|
-
{
|
|
6750
|
-
name: "checkboxCheck",
|
|
6751
|
-
size: 12,
|
|
6752
|
-
color: "var(--cmp-checkbox-checked-icon-default)"
|
|
6753
|
-
}
|
|
6754
|
-
)
|
|
6755
|
-
}
|
|
6756
|
-
),
|
|
6828
|
+
/* @__PURE__ */ jsxRuntime.jsx(CheckboxBox, { state: selectAllSelected, focused: focusedValue === "__select_all__" }),
|
|
6757
6829
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: selectAllLabel })
|
|
6758
6830
|
]
|
|
6759
6831
|
}
|
|
@@ -6763,12 +6835,71 @@ function ItemList({
|
|
|
6763
6835
|
const rowKey = `${o.value}-${idx}`;
|
|
6764
6836
|
if (o.isGroup) {
|
|
6765
6837
|
const isDepth1 = o.depth === 1;
|
|
6838
|
+
const groupTone = isDepth1 ? "border-t border-solid border-[color:var(--cmp-listItem-depth1-border-color)] bg-[var(--cmp-listItem-depth1-bg-default)] font-bold" : "bg-[var(--cmp-listItem-depth2-middle-bg)] font-medium";
|
|
6839
|
+
if (multi) {
|
|
6840
|
+
const leafValues = groupLeafValues.get(idx) ?? [];
|
|
6841
|
+
const total = leafValues.length;
|
|
6842
|
+
const selectedCount = leafValues.reduce((n, v) => selectedSet.has(v) ? n + 1 : n, 0);
|
|
6843
|
+
const groupState = total === 0 || selectedCount === 0 ? false : selectedCount === total ? true : null;
|
|
6844
|
+
const groupDisabled = o.disabled || total === 0;
|
|
6845
|
+
const groupFocused = focusedValue === `__group_${idx}__`;
|
|
6846
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6847
|
+
"button",
|
|
6848
|
+
{
|
|
6849
|
+
type: "button",
|
|
6850
|
+
role: "option",
|
|
6851
|
+
"aria-selected": groupState === true,
|
|
6852
|
+
disabled: groupDisabled,
|
|
6853
|
+
"data-select-focused": groupFocused ? "true" : void 0,
|
|
6854
|
+
"data-select-active": groupFocused ? "true" : void 0,
|
|
6855
|
+
className: cn(
|
|
6856
|
+
"flex w-full select-none items-center gap-[8px] border-none py-[4px] pr-[12px] text-left text-[12px] leading-[20px] text-[color:var(--cmp-listItem-content-default)]",
|
|
6857
|
+
groupTone,
|
|
6858
|
+
groupDisabled ? "cursor-not-allowed text-[color:var(--cmp-listItem-content-disabled)]" : "cursor-pointer",
|
|
6859
|
+
groupDisabled && isDepth1 && "bg-[var(--cmp-listItem-depth1-bg-disabled)]",
|
|
6860
|
+
// 포커스 하이라이트는 depth 배경보다 뒤에 둬 tailwind-merge 로 이기게 한다.
|
|
6861
|
+
groupFocused && !groupDisabled && "bg-[var(--cmp-listItem-bg-hover)] text-[color:var(--cmp-listItem-content-hover)]"
|
|
6862
|
+
),
|
|
6863
|
+
style: { paddingLeft: padLeft },
|
|
6864
|
+
onMouseEnter: () => onHoverValue(`__group_${idx}__`),
|
|
6865
|
+
onMouseLeave: () => onHoverValue(null),
|
|
6866
|
+
onClick: () => onToggleGroup(leafValues),
|
|
6867
|
+
children: [
|
|
6868
|
+
/* @__PURE__ */ jsxRuntime.jsx(CheckboxBox, { state: groupState, disabled: groupDisabled, focused: groupFocused }),
|
|
6869
|
+
isHtmlLabel(o.label) ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
6870
|
+
"span",
|
|
6871
|
+
{
|
|
6872
|
+
className: "min-w-0 truncate",
|
|
6873
|
+
dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(o.label) }
|
|
6874
|
+
}
|
|
6875
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: o.label }),
|
|
6876
|
+
total > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6877
|
+
"span",
|
|
6878
|
+
{
|
|
6879
|
+
className: cn(
|
|
6880
|
+
"shrink-0 font-medium",
|
|
6881
|
+
groupFocused ? "text-white" : "text-[color:var(--cmp-listItem-content-disabled)]"
|
|
6882
|
+
),
|
|
6883
|
+
children: [
|
|
6884
|
+
"(",
|
|
6885
|
+
selectedCount,
|
|
6886
|
+
"/",
|
|
6887
|
+
total,
|
|
6888
|
+
")"
|
|
6889
|
+
]
|
|
6890
|
+
}
|
|
6891
|
+
)
|
|
6892
|
+
]
|
|
6893
|
+
},
|
|
6894
|
+
rowKey
|
|
6895
|
+
);
|
|
6896
|
+
}
|
|
6766
6897
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6767
6898
|
"div",
|
|
6768
6899
|
{
|
|
6769
6900
|
className: cn(
|
|
6770
6901
|
"select-none py-[4px] pr-[12px] text-[12px] leading-[20px] text-[color:var(--cmp-listItem-content-default)]",
|
|
6771
|
-
|
|
6902
|
+
groupTone,
|
|
6772
6903
|
// 하위가 전부 비활성이면(select.config 에서 bubble-up) 어미 그룹도 비활성 처리:
|
|
6773
6904
|
// 텍스트는 회색(#888), depth1 그룹은 파란 배경 대신 회색(#EEE)으로 (depth2 는 #F6F6F6 유지)
|
|
6774
6905
|
o.disabled && "cursor-not-allowed text-[color:var(--cmp-listItem-content-disabled)]",
|
|
@@ -6804,25 +6935,11 @@ function ItemList({
|
|
|
6804
6935
|
onClick: () => onSelect(o.value),
|
|
6805
6936
|
children: [
|
|
6806
6937
|
multi && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6807
|
-
|
|
6938
|
+
CheckboxBox,
|
|
6808
6939
|
{
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
// 비활성: 회색 채움(#E1E1E1) + 회색 테두리(#CCCCCC)
|
|
6813
|
-
"cursor-not-allowed border-[color:var(--cmp-checkbox-border-disabled)] bg-[var(--cmp-checkbox-bg-disabled)]"
|
|
6814
|
-
) : cn(
|
|
6815
|
-
isSelected ? focusedValue === o.value ? "border-[color:var(--cmp-checkbox-checked-border-inverse)] bg-[var(--cmp-checkbox-checked-bg-default)]" : "border-[color:var(--cmp-checkbox-checked-bg-default)] bg-[var(--cmp-checkbox-checked-bg-default)]" : "border-[color:var(--cmp-checkbox-unchecked-border-default)] bg-[var(--cmp-checkbox-unchecked-bg-default)]"
|
|
6816
|
-
)
|
|
6817
|
-
),
|
|
6818
|
-
children: isSelected && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6819
|
-
SIcon,
|
|
6820
|
-
{
|
|
6821
|
-
name: "checkboxCheck",
|
|
6822
|
-
size: 12,
|
|
6823
|
-
color: o.disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : "var(--cmp-checkbox-checked-icon-default)"
|
|
6824
|
-
}
|
|
6825
|
-
)
|
|
6940
|
+
state: isSelected,
|
|
6941
|
+
disabled: o.disabled,
|
|
6942
|
+
focused: focusedValue === o.value
|
|
6826
6943
|
}
|
|
6827
6944
|
),
|
|
6828
6945
|
isHtmlLabel(o.label) ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -6839,6 +6956,33 @@ function ItemList({
|
|
|
6839
6956
|
})
|
|
6840
6957
|
] });
|
|
6841
6958
|
}
|
|
6959
|
+
function CheckboxBox({
|
|
6960
|
+
state: state2,
|
|
6961
|
+
disabled = false,
|
|
6962
|
+
focused = false
|
|
6963
|
+
}) {
|
|
6964
|
+
const filled = state2 === true || state2 === null;
|
|
6965
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6966
|
+
"span",
|
|
6967
|
+
{
|
|
6968
|
+
className: cn(
|
|
6969
|
+
"flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid",
|
|
6970
|
+
disabled ? (
|
|
6971
|
+
// 비활성: 회색 채움(#E1E1E1) + 회색 테두리(#CCCCCC)
|
|
6972
|
+
"cursor-not-allowed border-[color:var(--cmp-checkbox-border-disabled)] bg-[var(--cmp-checkbox-bg-disabled)]"
|
|
6973
|
+
) : filled ? focused ? "border-[color:var(--cmp-checkbox-checked-border-inverse)] bg-[var(--cmp-checkbox-checked-bg-default)]" : "border-[color:var(--cmp-checkbox-checked-bg-default)] bg-[var(--cmp-checkbox-checked-bg-default)]" : "border-[color:var(--cmp-checkbox-unchecked-border-default)] bg-[var(--cmp-checkbox-unchecked-bg-default)]"
|
|
6974
|
+
),
|
|
6975
|
+
children: filled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6976
|
+
SIcon,
|
|
6977
|
+
{
|
|
6978
|
+
name: state2 === null ? "checkboxIndeterminate" : "checkboxCheck",
|
|
6979
|
+
size: 12,
|
|
6980
|
+
color: disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : "var(--cmp-checkbox-checked-icon-default)"
|
|
6981
|
+
}
|
|
6982
|
+
)
|
|
6983
|
+
}
|
|
6984
|
+
);
|
|
6985
|
+
}
|
|
6842
6986
|
var DEFAULT_ROW_HEIGHT = 44;
|
|
6843
6987
|
var DENSE_ROW_HEIGHT = 32;
|
|
6844
6988
|
var SELECTABLE_COLUMN_WIDTH = 48;
|