sellmate-design-system-react 9.0.0-beta.77 → 9.0.0-beta.79
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/AGENTS.md +9 -0
- package/dist/components/SSelect/README.md +9 -0
- package/dist/components/SSelect/SSelect.d.ts +22 -3
- package/dist/components/SSelect/index.d.ts +1 -1
- package/dist/components/SSelect/select.config.d.ts +2 -0
- package/dist/components/STooltip/README.md +2 -0
- package/dist/index.cjs +212 -106
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +212 -106
- package/dist/index.js.map +1 -1
- package/dist/llms-full.txt +19 -0
- package/dist/llms.txt +9 -0
- package/dist/styles.css +35 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15587,6 +15587,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
15587
15587
|
name,
|
|
15588
15588
|
options = [],
|
|
15589
15589
|
type = "default",
|
|
15590
|
+
valueDisplay = "text",
|
|
15590
15591
|
showSearch = false,
|
|
15591
15592
|
showSelectAll = false,
|
|
15592
15593
|
allSelectedLabel = "\uC804\uCCB4",
|
|
@@ -15619,6 +15620,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
15619
15620
|
hint,
|
|
15620
15621
|
errorMessage,
|
|
15621
15622
|
width,
|
|
15623
|
+
size = "sm",
|
|
15622
15624
|
className,
|
|
15623
15625
|
style
|
|
15624
15626
|
}, ref) {
|
|
@@ -15923,6 +15925,51 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
15923
15925
|
}
|
|
15924
15926
|
return labelByValue.get(selected[0]) ?? valueOptions.get(selected[0])?.label ?? selected[0];
|
|
15925
15927
|
})();
|
|
15928
|
+
const showChips = valueDisplay === "chip" && multi && selected.length > 0 && !allSelected;
|
|
15929
|
+
const disabledValues = useMemo(
|
|
15930
|
+
() => new Set(flat.filter((o) => !o.isGroup && o.disabled).map((o) => o.value)),
|
|
15931
|
+
[flat]
|
|
15932
|
+
);
|
|
15933
|
+
const fullGroupByLeaf = useMemo(() => {
|
|
15934
|
+
const map = /* @__PURE__ */ new Map();
|
|
15935
|
+
if (!showChips || type !== "multi_depth") return map;
|
|
15936
|
+
flat.forEach((o, i) => {
|
|
15937
|
+
if (!o.isGroup) return;
|
|
15938
|
+
const leafValues = collectGroupLeafValues(flat, i);
|
|
15939
|
+
if (leafValues.length === 0 || leafValues.some((v) => !selectedSet.has(v))) return;
|
|
15940
|
+
if (map.has(leafValues[0])) return;
|
|
15941
|
+
const group = { value: o.value, label: o.label, leafValues };
|
|
15942
|
+
for (let j = i + 1; j < flat.length && flat[j].depth > o.depth; j++) {
|
|
15943
|
+
if (!flat[j].isGroup && selectedSet.has(flat[j].value)) map.set(flat[j].value, group);
|
|
15944
|
+
}
|
|
15945
|
+
});
|
|
15946
|
+
return map;
|
|
15947
|
+
}, [flat, selectedSet, showChips, type]);
|
|
15948
|
+
const chips = [];
|
|
15949
|
+
if (showChips) {
|
|
15950
|
+
const placedGroups = /* @__PURE__ */ new Set();
|
|
15951
|
+
for (const v of selected) {
|
|
15952
|
+
const group = fullGroupByLeaf.get(v);
|
|
15953
|
+
if (group != null) {
|
|
15954
|
+
if (placedGroups.has(group.value)) continue;
|
|
15955
|
+
placedGroups.add(group.value);
|
|
15956
|
+
chips.push({
|
|
15957
|
+
// 그룹 value 와 리프 value 가 겹쳐도 key 가 부딪히지 않게 구분한다.
|
|
15958
|
+
key: `__group_${group.value}__`,
|
|
15959
|
+
label: group.label,
|
|
15960
|
+
values: group.leafValues,
|
|
15961
|
+
removable: !effectiveDisabled
|
|
15962
|
+
});
|
|
15963
|
+
continue;
|
|
15964
|
+
}
|
|
15965
|
+
chips.push({
|
|
15966
|
+
key: v,
|
|
15967
|
+
label: labelByValue.get(v) ?? valueOptions.get(v)?.label ?? v,
|
|
15968
|
+
values: [v],
|
|
15969
|
+
removable: !effectiveDisabled && !disabledValues.has(v)
|
|
15970
|
+
});
|
|
15971
|
+
}
|
|
15972
|
+
}
|
|
15926
15973
|
const isPlaceholder = selected.length === 0;
|
|
15927
15974
|
const showTriggerSpinner = loading2 && !effectiveDisabled;
|
|
15928
15975
|
const showClear = clearable && !effectiveDisabled && !isPlaceholder;
|
|
@@ -15930,6 +15977,13 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
15930
15977
|
emit3([]);
|
|
15931
15978
|
if (rules && rules.length > 0) setRuleError(runRules(multi ? [] : "", rules));
|
|
15932
15979
|
};
|
|
15980
|
+
const handleRemoveChip = (targets) => {
|
|
15981
|
+
const remove = new Set(targets);
|
|
15982
|
+
const next = selected.filter((v) => !remove.has(v));
|
|
15983
|
+
emit3(next);
|
|
15984
|
+
if (rules && rules.length > 0) setRuleError(runRules(next, rules));
|
|
15985
|
+
triggerRef.current?.focus();
|
|
15986
|
+
};
|
|
15933
15987
|
const handleSelect = (nextValue, index, extend = false) => {
|
|
15934
15988
|
if (multi) {
|
|
15935
15989
|
const anchor = rangeAnchorRef.current;
|
|
@@ -16085,6 +16139,8 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
16085
16139
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
16086
16140
|
disabled: effectiveDisabled,
|
|
16087
16141
|
width,
|
|
16142
|
+
size,
|
|
16143
|
+
multiline: showChips,
|
|
16088
16144
|
className,
|
|
16089
16145
|
style,
|
|
16090
16146
|
children: [
|
|
@@ -16102,55 +16158,59 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
16102
16158
|
"aria-busy": showTriggerSpinner || void 0,
|
|
16103
16159
|
onClick: () => requestOpen(!open),
|
|
16104
16160
|
onKeyDown: handleKeyDown,
|
|
16105
|
-
className:
|
|
16161
|
+
className: cn(
|
|
16162
|
+
"flex h-full w-full cursor-pointer items-center justify-between bg-transparent text-left outline-none disabled:cursor-not-allowed",
|
|
16163
|
+
size === "md" ? "typo-body-md-default gap-(--cmp-select-md-gap) px-(--cmp-select-md-paddingX)" : "typo-body-sm-default gap-(--cmp-select-sm-gap) px-(--cmp-select-sm-paddingX)"
|
|
16164
|
+
),
|
|
16106
16165
|
style: {
|
|
16166
|
+
// 칩 한 줄이 기본 높이 안에서 세로 가운데에 오는 여백. 줄이 늘면 같은 여백을 유지한 채 트리거가 커진다.
|
|
16167
|
+
// sm 칩은 높이가 라벨 줄높이(typo-body-xs-medium)라 남는 높이가 4px 로 떨어진다.
|
|
16168
|
+
paddingBlock: showChips ? size === "md" ? "calc((var(--cmp-select-md-height) - var(--cmp-select-md-borderWidth) * 2 - var(--cmp-chip-height)) / 2)" : "var(--spacing-sd-4)" : void 0,
|
|
16107
16169
|
color: effectiveDisabled ? "var(--cmp-select-text-disabled)" : isPlaceholder ? "var(--cmp-select-icon-default)" : "var(--cmp-select-text-default)"
|
|
16108
16170
|
},
|
|
16109
16171
|
children: [
|
|
16110
|
-
|
|
16111
|
-
|
|
16112
|
-
|
|
16113
|
-
|
|
16114
|
-
|
|
16115
|
-
|
|
16116
|
-
) : /* @__PURE__ */ jsx("span", { className: "truncate", children: triggerText }),
|
|
16117
|
-
/* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-[8px]", children: [
|
|
16118
|
-
showClear && /* @__PURE__ */ jsxs(
|
|
16172
|
+
showChips ? (
|
|
16173
|
+
// md 는 SChip 과 같은 모양(높이 --cmp-chip-height)이다. SChip 을 그대로 넣지 않는 것은
|
|
16174
|
+
// SChip 의 × 가 <button> 이라 트리거 button 안에 중첩할 수 없어서다 — 모양만 같은 토큰으로 맞춘다.
|
|
16175
|
+
// sm 은 28px 트리거에 들어가도록 낮춘 칩 — 높이를 주지 않고 라벨 줄높이(typo-body-xs-medium)가 정한다.
|
|
16176
|
+
// 두 크기 모두 패딩·라벨↔× 간격은 chip 토큰 그대로.
|
|
16177
|
+
/* @__PURE__ */ jsx(
|
|
16119
16178
|
"span",
|
|
16120
16179
|
{
|
|
16121
|
-
|
|
16122
|
-
|
|
16123
|
-
|
|
16124
|
-
|
|
16125
|
-
|
|
16126
|
-
|
|
16127
|
-
|
|
16128
|
-
|
|
16129
|
-
|
|
16130
|
-
|
|
16131
|
-
|
|
16132
|
-
|
|
16133
|
-
|
|
16134
|
-
|
|
16135
|
-
|
|
16136
|
-
|
|
16137
|
-
|
|
16138
|
-
|
|
16139
|
-
|
|
16140
|
-
|
|
16141
|
-
|
|
16142
|
-
|
|
16143
|
-
|
|
16144
|
-
|
|
16145
|
-
|
|
16146
|
-
|
|
16147
|
-
|
|
16148
|
-
|
|
16149
|
-
|
|
16150
|
-
/* @__PURE__ */ jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
16151
|
-
]
|
|
16180
|
+
className: cn(
|
|
16181
|
+
"flex min-w-0 flex-1 flex-wrap items-center",
|
|
16182
|
+
size === "md" ? "gap-(--cmp-chipInput-chip-gap)" : "gap-sd-6"
|
|
16183
|
+
),
|
|
16184
|
+
children: chips.map((chip) => /* @__PURE__ */ jsxs(
|
|
16185
|
+
"span",
|
|
16186
|
+
{
|
|
16187
|
+
className: cn(
|
|
16188
|
+
"box-border inline-flex min-w-0 max-w-full items-center gap-(--cmp-chip-gap) overflow-hidden whitespace-nowrap px-(--cmp-chip-paddingX)",
|
|
16189
|
+
size === "md" ? "h-(--cmp-chip-height) text-[12px] font-medium leading-[20px]" : "typo-body-xs-medium"
|
|
16190
|
+
),
|
|
16191
|
+
style: {
|
|
16192
|
+
borderRadius: "var(--cmp-chip-radius)",
|
|
16193
|
+
background: chip.removable ? "var(--cmp-chip-bg-default)" : "var(--cmp-chip-bg-disabled)",
|
|
16194
|
+
color: chip.removable ? "var(--cmp-chip-content-default)" : "var(--cmp-chip-content-disabled)"
|
|
16195
|
+
},
|
|
16196
|
+
children: [
|
|
16197
|
+
/* @__PURE__ */ jsx(TriggerLabel, { label: chip.label }),
|
|
16198
|
+
chip.removable && /* @__PURE__ */ jsx(
|
|
16199
|
+
TriggerRemoveButton,
|
|
16200
|
+
{
|
|
16201
|
+
ariaLabel: `${isHtmlLabel(chip.label) ? extractText(chip.label) : chip.label} \uC120\uD0DD \uD574\uC81C`,
|
|
16202
|
+
onRemove: () => handleRemoveChip(chip.values)
|
|
16203
|
+
}
|
|
16204
|
+
)
|
|
16205
|
+
]
|
|
16206
|
+
},
|
|
16207
|
+
chip.key
|
|
16208
|
+
))
|
|
16152
16209
|
}
|
|
16153
|
-
)
|
|
16210
|
+
)
|
|
16211
|
+
) : /* @__PURE__ */ jsx(TriggerLabel, { label: triggerText }),
|
|
16212
|
+
/* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-[8px]", children: [
|
|
16213
|
+
showClear && /* @__PURE__ */ jsx(TriggerRemoveButton, { ariaLabel: "\uC120\uD0DD \uC9C0\uC6B0\uAE30", onRemove: handleClear }),
|
|
16154
16214
|
showTriggerSpinner ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "inline-flex shrink-0", "data-select-trigger-spinner": true, children: /* @__PURE__ */ jsx(SCircleProgress, { indeterminate: true, type: "neutral", size: 12 }) }) : /* @__PURE__ */ jsx(
|
|
16155
16215
|
SIcon,
|
|
16156
16216
|
{
|
|
@@ -16482,6 +16542,47 @@ function ItemList({
|
|
|
16482
16542
|
bottomSpacer > 0 && /* @__PURE__ */ jsx("div", { "aria-hidden": true, style: { height: bottomSpacer } })
|
|
16483
16543
|
] });
|
|
16484
16544
|
}
|
|
16545
|
+
function TriggerLabel({ label }) {
|
|
16546
|
+
return isHtmlLabel(label) ? /* @__PURE__ */ jsx("span", { className: "truncate", dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(label) } }) : /* @__PURE__ */ jsx("span", { className: "truncate", children: label });
|
|
16547
|
+
}
|
|
16548
|
+
function TriggerRemoveButton({ ariaLabel, onRemove }) {
|
|
16549
|
+
return /* @__PURE__ */ jsxs(
|
|
16550
|
+
"span",
|
|
16551
|
+
{
|
|
16552
|
+
role: "button",
|
|
16553
|
+
tabIndex: 0,
|
|
16554
|
+
"aria-label": ariaLabel,
|
|
16555
|
+
className: "group/select-remove relative inline-flex shrink-0 cursor-pointer items-center justify-center",
|
|
16556
|
+
style: {
|
|
16557
|
+
width: "var(--cmp-ghostButton-xxs-size)",
|
|
16558
|
+
height: "var(--cmp-ghostButton-xxs-size)",
|
|
16559
|
+
borderRadius: "var(--cmp-ghostButton-radius-sm)"
|
|
16560
|
+
},
|
|
16561
|
+
onClick: (event) => {
|
|
16562
|
+
event.preventDefault();
|
|
16563
|
+
event.stopPropagation();
|
|
16564
|
+
onRemove();
|
|
16565
|
+
},
|
|
16566
|
+
onKeyDown: (event) => {
|
|
16567
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
16568
|
+
event.preventDefault();
|
|
16569
|
+
event.stopPropagation();
|
|
16570
|
+
onRemove();
|
|
16571
|
+
},
|
|
16572
|
+
children: [
|
|
16573
|
+
/* @__PURE__ */ jsx(
|
|
16574
|
+
"span",
|
|
16575
|
+
{
|
|
16576
|
+
"aria-hidden": true,
|
|
16577
|
+
className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover/select-remove:opacity-5",
|
|
16578
|
+
style: { background: "var(--cmp-ghostButton-default-hover-bg)" }
|
|
16579
|
+
}
|
|
16580
|
+
),
|
|
16581
|
+
/* @__PURE__ */ jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
16582
|
+
]
|
|
16583
|
+
}
|
|
16584
|
+
);
|
|
16585
|
+
}
|
|
16485
16586
|
function CheckboxBox({
|
|
16486
16587
|
state: state2,
|
|
16487
16588
|
disabled = false,
|
|
@@ -22545,71 +22646,76 @@ function SRadioButton({
|
|
|
22545
22646
|
}) {
|
|
22546
22647
|
const s = SIZE_CONFIG2[size];
|
|
22547
22648
|
const [hoveredValue, setHoveredValue] = useState(null);
|
|
22548
|
-
return
|
|
22549
|
-
|
|
22550
|
-
|
|
22551
|
-
|
|
22552
|
-
|
|
22553
|
-
|
|
22554
|
-
|
|
22555
|
-
|
|
22556
|
-
|
|
22557
|
-
|
|
22558
|
-
|
|
22559
|
-
|
|
22560
|
-
|
|
22561
|
-
|
|
22562
|
-
|
|
22563
|
-
|
|
22564
|
-
|
|
22565
|
-
|
|
22566
|
-
|
|
22567
|
-
|
|
22568
|
-
|
|
22569
|
-
|
|
22570
|
-
|
|
22571
|
-
|
|
22572
|
-
|
|
22573
|
-
|
|
22574
|
-
|
|
22575
|
-
|
|
22576
|
-
|
|
22577
|
-
|
|
22578
|
-
|
|
22579
|
-
|
|
22580
|
-
|
|
22581
|
-
|
|
22582
|
-
|
|
22583
|
-
|
|
22584
|
-
|
|
22585
|
-
|
|
22586
|
-
|
|
22587
|
-
|
|
22588
|
-
|
|
22589
|
-
|
|
22590
|
-
|
|
22591
|
-
|
|
22592
|
-
|
|
22593
|
-
|
|
22594
|
-
|
|
22649
|
+
return (
|
|
22650
|
+
// isolate: 선택·hover 버튼의 z-10 은 겹친 테두리(-ml-px) 위로 올리기 위한 값이라 그룹 안에서
|
|
22651
|
+
// 끝나야 한다. 빼면 상위 컨텍스트까지 올라가 모달 안 floating 밴드(z-2)를 이겨, 위에서 연
|
|
22652
|
+
// SSelect listbox 위로 선택된 버튼만 뚫고 그려진다.
|
|
22653
|
+
/* @__PURE__ */ jsx(
|
|
22654
|
+
"div",
|
|
22655
|
+
{
|
|
22656
|
+
role: "radiogroup",
|
|
22657
|
+
"aria-disabled": disabled,
|
|
22658
|
+
className: cn("inline-flex isolate", className),
|
|
22659
|
+
style,
|
|
22660
|
+
children: options.map((o, i) => {
|
|
22661
|
+
const selected = o.value === value;
|
|
22662
|
+
const od = disabled || o.disabled;
|
|
22663
|
+
const first = i === 0;
|
|
22664
|
+
const last = i === options.length - 1;
|
|
22665
|
+
const tooltip = showTooltip && o.tooltip ? o.tooltip : void 0;
|
|
22666
|
+
const button = /* @__PURE__ */ jsx(
|
|
22667
|
+
"button",
|
|
22668
|
+
{
|
|
22669
|
+
type: "button",
|
|
22670
|
+
role: "radio",
|
|
22671
|
+
name,
|
|
22672
|
+
"aria-checked": selected,
|
|
22673
|
+
disabled: od,
|
|
22674
|
+
onClick: () => !od && !selected && onValueChange?.(o.value),
|
|
22675
|
+
onMouseEnter: tooltip ? () => setHoveredValue(o.value) : void 0,
|
|
22676
|
+
onMouseLeave: tooltip ? () => setHoveredValue(null) : void 0,
|
|
22677
|
+
onFocus: tooltip ? () => setHoveredValue(o.value) : void 0,
|
|
22678
|
+
onBlur: tooltip ? () => setHoveredValue(null) : void 0,
|
|
22679
|
+
className: cn(
|
|
22680
|
+
"relative box-border grow inline-flex items-center justify-center whitespace-nowrap border border-solid font-medium transition-colors",
|
|
22681
|
+
first ? "" : "-ml-px",
|
|
22682
|
+
selected ? "z-10" : "",
|
|
22683
|
+
!od && !selected && "hover:!bg-[var(--cmp-radioButton-bg-hover)] hover:!text-[color:var(--cmp-radioButton-content-hover)] hover:!border-[color:var(--cmp-radioButton-bg-hover)] hover:z-10",
|
|
22684
|
+
od ? "cursor-not-allowed" : "cursor-pointer"
|
|
22685
|
+
),
|
|
22686
|
+
style: {
|
|
22687
|
+
height: `var(--cmp-radioButton-${size}-height)`,
|
|
22688
|
+
padding: `0 var(--cmp-radioButton-${size}-paddingX)`,
|
|
22689
|
+
fontSize: `${s.fontSize}px`,
|
|
22690
|
+
lineHeight: `${s.lineHeight}px`,
|
|
22691
|
+
borderRadius: [
|
|
22692
|
+
first ? s.radius : "0",
|
|
22693
|
+
last ? s.radius : "0",
|
|
22694
|
+
last ? s.radius : "0",
|
|
22695
|
+
first ? s.radius : "0"
|
|
22696
|
+
].join(" "),
|
|
22697
|
+
background: od ? "var(--cmp-radioButton-bg-disabled)" : "var(--cmp-radioButton-bg-default)",
|
|
22698
|
+
borderColor: od ? "var(--cmp-radioButton-border-disabled)" : selected ? "var(--cmp-radioButton-border-select)" : "var(--cmp-radioButton-border-default)",
|
|
22699
|
+
color: od ? "var(--cmp-radioButton-content-disabled)" : selected ? "var(--cmp-radioButton-content-select)" : "var(--cmp-radioButton-content-default)"
|
|
22700
|
+
},
|
|
22701
|
+
children: o.label
|
|
22595
22702
|
},
|
|
22596
|
-
|
|
22597
|
-
|
|
22598
|
-
|
|
22599
|
-
|
|
22600
|
-
|
|
22601
|
-
|
|
22602
|
-
|
|
22603
|
-
|
|
22604
|
-
|
|
22605
|
-
|
|
22606
|
-
|
|
22607
|
-
|
|
22608
|
-
|
|
22609
|
-
|
|
22610
|
-
|
|
22611
|
-
|
|
22612
|
-
}
|
|
22703
|
+
o.value
|
|
22704
|
+
);
|
|
22705
|
+
return tooltip ? /* @__PURE__ */ jsx(
|
|
22706
|
+
STooltip2,
|
|
22707
|
+
{
|
|
22708
|
+
trigger: "none",
|
|
22709
|
+
open: hoveredValue === o.value,
|
|
22710
|
+
tooltipType: "accent",
|
|
22711
|
+
message: [tooltip],
|
|
22712
|
+
children: button
|
|
22713
|
+
},
|
|
22714
|
+
o.value
|
|
22715
|
+
) : button;
|
|
22716
|
+
})
|
|
22717
|
+
}
|
|
22718
|
+
)
|
|
22613
22719
|
);
|
|
22614
22720
|
}
|
|
22615
22721
|
function SRadioCard({
|