sellmate-design-system-react 9.0.0-beta.77 → 9.0.0-beta.78
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 +20 -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 +176 -106
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +176 -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/AGENTS.md
CHANGED
|
@@ -670,6 +670,7 @@ Tailwind 유틸리티는 **토큰 스케일에 있는 값만** 사용한다.
|
|
|
670
670
|
| **상태·분류를 라벨로 표시 (기본값)** | **`STag`** — `<STag size="sm" color="..." label="판매중" />`. 목록의 상태 컬럼, 상세의 분류 태그 등 대부분이 여기 해당한다 |
|
|
671
671
|
| 라벨 없이 **색 점만**으로 상태를 찍을 때 | `SBadge` — 점(dot)만 그리는 인디케이터. 텍스트가 이미 있고 앞에 점만 붙이는 좁은 경우에만 |
|
|
672
672
|
| 사용자가 입력·삭제·편집하는 **토큰** | `SChip` (단독) / `SChipInput` (입력 필드 안에서) |
|
|
673
|
+
| 목록에서 **여러 개 고른 값**을 칩으로 보여주고 하나씩 빼게 할 때 | `SSelect` `type="multi"` + `valueDisplay="chip"` (§3-7-2) — `SChip` 을 따로 나열하지 않는다 |
|
|
673
674
|
|
|
674
675
|
> 상태 표시는 **`STag size="sm"` 이 기본**이다. 색 점 + 텍스트 조합(`SBadge`)을 기본으로 쓰지 않는다.
|
|
675
676
|
|
|
@@ -1752,6 +1753,14 @@ tableRef.current.scrollToRow(row); // 복원
|
|
|
1752
1753
|
- 카드 안에 상태 배지를 넣으려면 `tag` 슬롯에 `STag` 를 준다. 라벨 문자열에 "(추천)" 처럼 섞어 쓰지 않는다.
|
|
1753
1754
|
- **카드처럼 생겼다고 `SCard`/`SSectionHeaderCard` 로 감싸지 않는다.** `SRadioCard` 자체가 완결된 요소이고, 나열 간격은 `SRadioCardGroup` 의 `direction` 이 맞춘다 (§2-2).
|
|
1754
1755
|
|
|
1756
|
+
##### 여러 개 고른 값을 칩으로 보여줄 때 — `valueDisplay="chip"`
|
|
1757
|
+
|
|
1758
|
+
- **`type="multi"`·`"multi_depth"` 에서 `valueDisplay="chip"` 을 주면** 선택값이 트리거에 칩으로 뜨고, 칩의 × 로 하나씩 뺄 수 있다. 기본(`text`)은 라벨을 쉼표로 이어 한 줄로 말줄임한다. 고른 값 하나하나를 확인하고 바로 빼야 하는 자리면 `chip`, 몇 개 골랐는지만 보이면 되는 조회 필터면 `text` 를 쓴다.
|
|
1759
|
+
- **후보가 정해진 목록에서 고르는 것이면 `SSelect` 의 `chip` 이고, 사용자가 값을 직접 타이핑해 쌓는 것이면 `SChipInput` 이다.** 목록에서 고른 값을 `SChipInput` 에 옮겨 담거나, `SSelect` 옆에 `SChip` 을 따로 나열해 선택값을 흉내 내지 않는다.
|
|
1760
|
+
- **단일 선택 type 에는 주지 않는다.** 무시되고 `text` 로 보인다. 단일 선택의 값 비우기는 `clearable` 이 맡는다.
|
|
1761
|
+
- 칩이 한 줄을 넘으면 줄바꿈하고 트리거가 그만큼 높아진다. 높이·칩 간격은 `SSelect` 가 토큰으로 넣는다 — 직접 주지 않는다.
|
|
1762
|
+
- 전체 선택이면 칩 대신 `allSelectedLabel` 이 뜬다. 비활성 옵션의 칩과 비활성 셀렉트의 칩에는 × 가 없다.
|
|
1763
|
+
|
|
1755
1764
|
##### 옵션을 서버에서 받는 동안 — `loading`
|
|
1756
1765
|
|
|
1757
1766
|
- **받는 동안 `loading` 을 켠다.** 트리거의 펼침 아이콘 자리에 스피너가, 드롭다운에 로딩 행이 뜬다. 첫 조회든 다음 페이지든 같은 prop 이다.
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
| `name?` | `string` | — | 폼 연동용 name 속성 |
|
|
14
14
|
| `options?` | `SSelectOption[]` | `[]` | 옵션 목록 (children으로 계층 표현) |
|
|
15
15
|
| `type?` | `SSelectType` | `'default'` | 타입: default | multi | default_depth | multi_depth |
|
|
16
|
+
| `valueDisplay?` | `SSelectValueDisplay` | `'text'` | 트리거에 선택값을 보여주는 방식. - `text`: 선택 라벨을 쉼표로 이어 한 줄로 보여준다. 넘치면 말줄임한다. - `chip`: 선택값마다 칩을 낸다. 칩의 × 를 누르면 그 값만 선택에서 빠지고, 드롭다운은 열리지 않는다. 칩이 한 줄을 넘으면 줄바꿈하고 트리거가 그만큼 높아진다. `chip` 은 `multi`·`multi_depth` 에서만 동작한다. 단일 선택 type 에서는 무시하고 `text` 로 보여준다. 전체 선택이면 칩 대신 `allSelectedLabel` 을 보여준다. 비활성(select 자체나 해당 옵션)인 칩에는 × 를 내지 않는다. |
|
|
16
17
|
| `showSearch?` | `boolean` | `false` | 검색 입력 사용 |
|
|
17
18
|
| `showSelectAll?` | `boolean` | `false` | 전체선택 옵션 사용 (multi 전용) |
|
|
18
19
|
| `allSelectedLabel?` | `string` | `'전체'` | 전체선택 레이블 |
|
|
@@ -43,6 +44,7 @@
|
|
|
43
44
|
| `hint?` | `string` | — | |
|
|
44
45
|
| `errorMessage?` | `string` | — | |
|
|
45
46
|
| `width?` | `SFieldWidth` | — | 컨트롤 너비 — 폭 등급(`'xs' | 'sm' | 'md' | 'lg' | 'xl'`) · 숫자=px · CSS 길이. 등급은 `--cmp-field-width-*` 토큰으로 풀리므로 토큰이 바뀌면 화면이 따라간다. 값 길이에 상한이 없으면 `"100%"` 로 두어 행 전체를 쓴다. 셀렉트는 `maxLength` 개념이 없어 목록 최장값을 담는 등급으로 고른다. |
|
|
47
|
+
| `size?` | `SFieldSize` | `'sm'` | 트리거 크기 (기본값 `'sm'`). 높이·패딩·간격·글자 크기를 `--cmp-select-{size}-*` 토큰으로 바꾼다. 드롭다운 목록은 크기와 무관하게 같다. `valueDisplay="chip"` 이면 `md` 는 SChip 과 같은 칩을, `sm` 은 28px 트리거에 맞춘 낮은 칩을 낸다. |
|
|
46
48
|
| `className?` | `string` | — | |
|
|
47
49
|
| `style?` | `CSSProperties` | — | |
|
|
48
50
|
|
|
@@ -95,6 +97,13 @@ export interface SSelectOption {
|
|
|
95
97
|
export type SSelectType = 'default' | 'multi' | 'default_depth' | 'multi_depth';
|
|
96
98
|
```
|
|
97
99
|
|
|
100
|
+
### SSelectValueDisplay
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
/** 트리거에 선택값을 보여주는 방식 — 쉼표로 이은 텍스트 | 값마다 칩 */
|
|
104
|
+
export type SSelectValueDisplay = 'text' | 'chip';
|
|
105
|
+
```
|
|
106
|
+
|
|
98
107
|
## Dependencies
|
|
99
108
|
|
|
100
109
|
### Used by
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { type CSSProperties, type ForwardedRef, type ReactElement } from 'react';
|
|
2
2
|
import { type Rule } from '../../lib/form';
|
|
3
|
-
import { type SFieldAddonAlign, type SFieldLabelPosition } from '../SField';
|
|
3
|
+
import { type SFieldAddonAlign, type SFieldLabelPosition, type SFieldSize } from '../SField';
|
|
4
4
|
import { type SIconName } from '../SIcon';
|
|
5
5
|
import { type SColor } from '../../lib/color';
|
|
6
6
|
import { type STooltipProps } from '../STooltip';
|
|
7
|
-
import { type SSelectOption, type SSelectType } from './select.config';
|
|
7
|
+
import { type SSelectOption, type SSelectType, type SSelectValueDisplay } from './select.config';
|
|
8
8
|
import { type SFieldWidth } from '../../lib/field-width';
|
|
9
|
-
export type { SSelectOption, SSelectType } from './select.config';
|
|
9
|
+
export type { SSelectOption, SSelectType, SSelectValueDisplay } from './select.config';
|
|
10
10
|
export interface SSelectHandle {
|
|
11
11
|
/** 트리거 버튼에 포커스 (sdFocus) */
|
|
12
12
|
focus: () => void;
|
|
@@ -44,6 +44,17 @@ export interface SSelectProps<TValue extends SSelectChangeValue = SSelectChangeV
|
|
|
44
44
|
options?: SSelectOption[];
|
|
45
45
|
/** 타입: default | multi | default_depth | multi_depth */
|
|
46
46
|
type?: SSelectType;
|
|
47
|
+
/**
|
|
48
|
+
* 트리거에 선택값을 보여주는 방식.
|
|
49
|
+
* - `text`: 선택 라벨을 쉼표로 이어 한 줄로 보여준다. 넘치면 말줄임한다.
|
|
50
|
+
* - `chip`: 선택값마다 칩을 낸다. 칩의 × 를 누르면 그 값만 선택에서 빠지고, 드롭다운은 열리지 않는다.
|
|
51
|
+
* 칩이 한 줄을 넘으면 줄바꿈하고 트리거가 그만큼 높아진다.
|
|
52
|
+
*
|
|
53
|
+
* `chip` 은 `multi`·`multi_depth` 에서만 동작한다. 단일 선택 type 에서는 무시하고 `text` 로 보여준다.
|
|
54
|
+
* 전체 선택이면 칩 대신 `allSelectedLabel` 을 보여준다.
|
|
55
|
+
* 비활성(select 자체나 해당 옵션)인 칩에는 × 를 내지 않는다.
|
|
56
|
+
*/
|
|
57
|
+
valueDisplay?: SSelectValueDisplay;
|
|
47
58
|
/** 검색 입력 사용 */
|
|
48
59
|
showSearch?: boolean;
|
|
49
60
|
/** 전체선택 옵션 사용 (multi 전용) */
|
|
@@ -158,6 +169,12 @@ export interface SSelectProps<TValue extends SSelectChangeValue = SSelectChangeV
|
|
|
158
169
|
* 셀렉트는 `maxLength` 개념이 없어 목록 최장값을 담는 등급으로 고른다.
|
|
159
170
|
*/
|
|
160
171
|
width?: SFieldWidth;
|
|
172
|
+
/**
|
|
173
|
+
* 트리거 크기 (기본값 `'sm'`). 높이·패딩·간격·글자 크기를 `--cmp-select-{size}-*` 토큰으로 바꾼다.
|
|
174
|
+
* 드롭다운 목록은 크기와 무관하게 같다.
|
|
175
|
+
* `valueDisplay="chip"` 이면 `md` 는 SChip 과 같은 칩을, `sm` 은 28px 트리거에 맞춘 낮은 칩을 낸다.
|
|
176
|
+
*/
|
|
177
|
+
size?: SFieldSize;
|
|
161
178
|
className?: string;
|
|
162
179
|
style?: CSSProperties;
|
|
163
180
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { SSelect, type SSelectHandle, type SSelectProps, type SSelectChangeValue, type SSelectOption, type SSelectType, } from './SSelect';
|
|
1
|
+
export { SSelect, type SSelectHandle, type SSelectProps, type SSelectChangeValue, type SSelectOption, type SSelectType, type SSelectValueDisplay, } from './SSelect';
|
|
@@ -5,6 +5,8 @@ export interface SSelectOption {
|
|
|
5
5
|
children?: SSelectOption[];
|
|
6
6
|
}
|
|
7
7
|
export type SSelectType = 'default' | 'multi' | 'default_depth' | 'multi_depth';
|
|
8
|
+
/** 트리거에 선택값을 보여주는 방식 — 쉼표로 이은 텍스트 | 값마다 칩 */
|
|
9
|
+
export type SSelectValueDisplay = 'text' | 'chip';
|
|
8
10
|
export interface FlatOption {
|
|
9
11
|
value: string;
|
|
10
12
|
label: string;
|
|
@@ -68,6 +68,7 @@ export type STooltipType = 'default' | 'danger' | 'warning' | 'accent';
|
|
|
68
68
|
- [SField](../SField)
|
|
69
69
|
- [SGnbSystem](../SGnbSystem)
|
|
70
70
|
- [SKeyValueTable](../SKeyValueTable)
|
|
71
|
+
- [SRadioButton](../SRadioButton)
|
|
71
72
|
- [SSectionHeaderCard](../SSectionHeaderCard)
|
|
72
73
|
- [SStepper](../SStepper)
|
|
73
74
|
- [STable](../STable)
|
|
@@ -87,6 +88,7 @@ graph TD;
|
|
|
87
88
|
SField --> STooltip
|
|
88
89
|
SGnbSystem --> STooltip
|
|
89
90
|
SKeyValueTable --> STooltip
|
|
91
|
+
SRadioButton --> STooltip
|
|
90
92
|
SSectionHeaderCard --> STooltip
|
|
91
93
|
SStepper --> STooltip
|
|
92
94
|
STable --> STooltip
|
package/dist/index.cjs
CHANGED
|
@@ -15615,6 +15615,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
15615
15615
|
name,
|
|
15616
15616
|
options = [],
|
|
15617
15617
|
type = "default",
|
|
15618
|
+
valueDisplay = "text",
|
|
15618
15619
|
showSearch = false,
|
|
15619
15620
|
showSelectAll = false,
|
|
15620
15621
|
allSelectedLabel = "\uC804\uCCB4",
|
|
@@ -15647,6 +15648,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
15647
15648
|
hint,
|
|
15648
15649
|
errorMessage,
|
|
15649
15650
|
width,
|
|
15651
|
+
size = "sm",
|
|
15650
15652
|
className,
|
|
15651
15653
|
style
|
|
15652
15654
|
}, ref) {
|
|
@@ -15951,6 +15953,16 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
15951
15953
|
}
|
|
15952
15954
|
return labelByValue.get(selected[0]) ?? valueOptions.get(selected[0])?.label ?? selected[0];
|
|
15953
15955
|
})();
|
|
15956
|
+
const showChips = valueDisplay === "chip" && multi && selected.length > 0 && !allSelected;
|
|
15957
|
+
const disabledValues = react.useMemo(
|
|
15958
|
+
() => new Set(flat.filter((o) => !o.isGroup && o.disabled).map((o) => o.value)),
|
|
15959
|
+
[flat]
|
|
15960
|
+
);
|
|
15961
|
+
const chips = showChips ? selected.map((v) => ({
|
|
15962
|
+
value: v,
|
|
15963
|
+
label: labelByValue.get(v) ?? valueOptions.get(v)?.label ?? v,
|
|
15964
|
+
removable: !effectiveDisabled && !disabledValues.has(v)
|
|
15965
|
+
})) : [];
|
|
15954
15966
|
const isPlaceholder = selected.length === 0;
|
|
15955
15967
|
const showTriggerSpinner = loading2 && !effectiveDisabled;
|
|
15956
15968
|
const showClear = clearable && !effectiveDisabled && !isPlaceholder;
|
|
@@ -15958,6 +15970,12 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
15958
15970
|
emit3([]);
|
|
15959
15971
|
if (rules && rules.length > 0) setRuleError(runRules(multi ? [] : "", rules));
|
|
15960
15972
|
};
|
|
15973
|
+
const handleRemoveChip = (target) => {
|
|
15974
|
+
const next = selected.filter((v) => v !== target);
|
|
15975
|
+
emit3(next);
|
|
15976
|
+
if (rules && rules.length > 0) setRuleError(runRules(next, rules));
|
|
15977
|
+
triggerRef.current?.focus();
|
|
15978
|
+
};
|
|
15961
15979
|
const handleSelect = (nextValue, index, extend = false) => {
|
|
15962
15980
|
if (multi) {
|
|
15963
15981
|
const anchor = rangeAnchorRef.current;
|
|
@@ -16113,6 +16131,8 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
16113
16131
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
16114
16132
|
disabled: effectiveDisabled,
|
|
16115
16133
|
width,
|
|
16134
|
+
size,
|
|
16135
|
+
multiline: showChips,
|
|
16116
16136
|
className,
|
|
16117
16137
|
style,
|
|
16118
16138
|
children: [
|
|
@@ -16130,55 +16150,59 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
16130
16150
|
"aria-busy": showTriggerSpinner || void 0,
|
|
16131
16151
|
onClick: () => requestOpen(!open),
|
|
16132
16152
|
onKeyDown: handleKeyDown,
|
|
16133
|
-
className:
|
|
16153
|
+
className: cn(
|
|
16154
|
+
"flex h-full w-full cursor-pointer items-center justify-between bg-transparent text-left outline-none disabled:cursor-not-allowed",
|
|
16155
|
+
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)"
|
|
16156
|
+
),
|
|
16134
16157
|
style: {
|
|
16158
|
+
// 칩 한 줄이 기본 높이 안에서 세로 가운데에 오는 여백. 줄이 늘면 같은 여백을 유지한 채 트리거가 커진다.
|
|
16159
|
+
// sm 칩은 높이가 라벨 줄높이(typo-body-xs-medium)라 남는 높이가 4px 로 떨어진다.
|
|
16160
|
+
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,
|
|
16135
16161
|
color: effectiveDisabled ? "var(--cmp-select-text-disabled)" : isPlaceholder ? "var(--cmp-select-icon-default)" : "var(--cmp-select-text-default)"
|
|
16136
16162
|
},
|
|
16137
16163
|
children: [
|
|
16138
|
-
|
|
16139
|
-
|
|
16140
|
-
|
|
16141
|
-
|
|
16142
|
-
|
|
16143
|
-
|
|
16144
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: triggerText }),
|
|
16145
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-[8px]", children: [
|
|
16146
|
-
showClear && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16164
|
+
showChips ? (
|
|
16165
|
+
// md 는 SChip 과 같은 모양(높이 --cmp-chip-height)이다. SChip 을 그대로 넣지 않는 것은
|
|
16166
|
+
// SChip 의 × 가 <button> 이라 트리거 button 안에 중첩할 수 없어서다 — 모양만 같은 토큰으로 맞춘다.
|
|
16167
|
+
// sm 은 28px 트리거에 들어가도록 낮춘 칩 — 높이를 주지 않고 라벨 줄높이(typo-body-xs-medium)가 정한다.
|
|
16168
|
+
// 두 크기 모두 패딩·라벨↔× 간격은 chip 토큰 그대로.
|
|
16169
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16147
16170
|
"span",
|
|
16148
16171
|
{
|
|
16149
|
-
|
|
16150
|
-
|
|
16151
|
-
|
|
16152
|
-
|
|
16153
|
-
|
|
16154
|
-
|
|
16155
|
-
|
|
16156
|
-
|
|
16157
|
-
|
|
16158
|
-
|
|
16159
|
-
|
|
16160
|
-
|
|
16161
|
-
|
|
16162
|
-
|
|
16163
|
-
|
|
16164
|
-
|
|
16165
|
-
|
|
16166
|
-
|
|
16167
|
-
|
|
16168
|
-
|
|
16169
|
-
|
|
16170
|
-
|
|
16171
|
-
|
|
16172
|
-
|
|
16173
|
-
|
|
16174
|
-
|
|
16175
|
-
|
|
16176
|
-
|
|
16177
|
-
|
|
16178
|
-
/* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
16179
|
-
]
|
|
16172
|
+
className: cn(
|
|
16173
|
+
"flex min-w-0 flex-1 flex-wrap items-center",
|
|
16174
|
+
size === "md" ? "gap-(--cmp-chipInput-chip-gap)" : "gap-sd-6"
|
|
16175
|
+
),
|
|
16176
|
+
children: chips.map((chip) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16177
|
+
"span",
|
|
16178
|
+
{
|
|
16179
|
+
className: cn(
|
|
16180
|
+
"box-border inline-flex min-w-0 max-w-full items-center gap-(--cmp-chip-gap) overflow-hidden whitespace-nowrap px-(--cmp-chip-paddingX)",
|
|
16181
|
+
size === "md" ? "h-(--cmp-chip-height) text-[12px] font-medium leading-[20px]" : "typo-body-xs-medium"
|
|
16182
|
+
),
|
|
16183
|
+
style: {
|
|
16184
|
+
borderRadius: "var(--cmp-chip-radius)",
|
|
16185
|
+
background: chip.removable ? "var(--cmp-chip-bg-default)" : "var(--cmp-chip-bg-disabled)",
|
|
16186
|
+
color: chip.removable ? "var(--cmp-chip-content-default)" : "var(--cmp-chip-content-disabled)"
|
|
16187
|
+
},
|
|
16188
|
+
children: [
|
|
16189
|
+
/* @__PURE__ */ jsxRuntime.jsx(TriggerLabel, { label: chip.label }),
|
|
16190
|
+
chip.removable && /* @__PURE__ */ jsxRuntime.jsx(
|
|
16191
|
+
TriggerRemoveButton,
|
|
16192
|
+
{
|
|
16193
|
+
ariaLabel: `${isHtmlLabel(chip.label) ? extractText(chip.label) : chip.label} \uC120\uD0DD \uD574\uC81C`,
|
|
16194
|
+
onRemove: () => handleRemoveChip(chip.value)
|
|
16195
|
+
}
|
|
16196
|
+
)
|
|
16197
|
+
]
|
|
16198
|
+
},
|
|
16199
|
+
chip.value
|
|
16200
|
+
))
|
|
16180
16201
|
}
|
|
16181
|
-
)
|
|
16202
|
+
)
|
|
16203
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(TriggerLabel, { label: triggerText }),
|
|
16204
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-[8px]", children: [
|
|
16205
|
+
showClear && /* @__PURE__ */ jsxRuntime.jsx(TriggerRemoveButton, { ariaLabel: "\uC120\uD0DD \uC9C0\uC6B0\uAE30", onRemove: handleClear }),
|
|
16182
16206
|
showTriggerSpinner ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "inline-flex shrink-0", "data-select-trigger-spinner": true, children: /* @__PURE__ */ jsxRuntime.jsx(SCircleProgress, { indeterminate: true, type: "neutral", size: 12 }) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
16183
16207
|
SIcon,
|
|
16184
16208
|
{
|
|
@@ -16510,6 +16534,47 @@ function ItemList({
|
|
|
16510
16534
|
bottomSpacer > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, style: { height: bottomSpacer } })
|
|
16511
16535
|
] });
|
|
16512
16536
|
}
|
|
16537
|
+
function TriggerLabel({ label }) {
|
|
16538
|
+
return isHtmlLabel(label) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(label) } }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: label });
|
|
16539
|
+
}
|
|
16540
|
+
function TriggerRemoveButton({ ariaLabel, onRemove }) {
|
|
16541
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16542
|
+
"span",
|
|
16543
|
+
{
|
|
16544
|
+
role: "button",
|
|
16545
|
+
tabIndex: 0,
|
|
16546
|
+
"aria-label": ariaLabel,
|
|
16547
|
+
className: "group/select-remove relative inline-flex shrink-0 cursor-pointer items-center justify-center",
|
|
16548
|
+
style: {
|
|
16549
|
+
width: "var(--cmp-ghostButton-xxs-size)",
|
|
16550
|
+
height: "var(--cmp-ghostButton-xxs-size)",
|
|
16551
|
+
borderRadius: "var(--cmp-ghostButton-radius-sm)"
|
|
16552
|
+
},
|
|
16553
|
+
onClick: (event) => {
|
|
16554
|
+
event.preventDefault();
|
|
16555
|
+
event.stopPropagation();
|
|
16556
|
+
onRemove();
|
|
16557
|
+
},
|
|
16558
|
+
onKeyDown: (event) => {
|
|
16559
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
16560
|
+
event.preventDefault();
|
|
16561
|
+
event.stopPropagation();
|
|
16562
|
+
onRemove();
|
|
16563
|
+
},
|
|
16564
|
+
children: [
|
|
16565
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16566
|
+
"span",
|
|
16567
|
+
{
|
|
16568
|
+
"aria-hidden": true,
|
|
16569
|
+
className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover/select-remove:opacity-5",
|
|
16570
|
+
style: { background: "var(--cmp-ghostButton-default-hover-bg)" }
|
|
16571
|
+
}
|
|
16572
|
+
),
|
|
16573
|
+
/* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
16574
|
+
]
|
|
16575
|
+
}
|
|
16576
|
+
);
|
|
16577
|
+
}
|
|
16513
16578
|
function CheckboxBox({
|
|
16514
16579
|
state: state2,
|
|
16515
16580
|
disabled = false,
|
|
@@ -22573,71 +22638,76 @@ function SRadioButton({
|
|
|
22573
22638
|
}) {
|
|
22574
22639
|
const s = SIZE_CONFIG2[size];
|
|
22575
22640
|
const [hoveredValue, setHoveredValue] = react.useState(null);
|
|
22576
|
-
return
|
|
22577
|
-
|
|
22578
|
-
|
|
22579
|
-
|
|
22580
|
-
|
|
22581
|
-
|
|
22582
|
-
|
|
22583
|
-
|
|
22584
|
-
|
|
22585
|
-
|
|
22586
|
-
|
|
22587
|
-
|
|
22588
|
-
|
|
22589
|
-
|
|
22590
|
-
|
|
22591
|
-
|
|
22592
|
-
|
|
22593
|
-
|
|
22594
|
-
|
|
22595
|
-
|
|
22596
|
-
|
|
22597
|
-
|
|
22598
|
-
|
|
22599
|
-
|
|
22600
|
-
|
|
22601
|
-
|
|
22602
|
-
|
|
22603
|
-
|
|
22604
|
-
|
|
22605
|
-
|
|
22606
|
-
|
|
22607
|
-
|
|
22608
|
-
|
|
22609
|
-
|
|
22610
|
-
|
|
22611
|
-
|
|
22612
|
-
|
|
22613
|
-
|
|
22614
|
-
|
|
22615
|
-
|
|
22616
|
-
|
|
22617
|
-
|
|
22618
|
-
|
|
22619
|
-
|
|
22620
|
-
|
|
22621
|
-
|
|
22622
|
-
|
|
22641
|
+
return (
|
|
22642
|
+
// isolate: 선택·hover 버튼의 z-10 은 겹친 테두리(-ml-px) 위로 올리기 위한 값이라 그룹 안에서
|
|
22643
|
+
// 끝나야 한다. 빼면 상위 컨텍스트까지 올라가 모달 안 floating 밴드(z-2)를 이겨, 위에서 연
|
|
22644
|
+
// SSelect listbox 위로 선택된 버튼만 뚫고 그려진다.
|
|
22645
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
22646
|
+
"div",
|
|
22647
|
+
{
|
|
22648
|
+
role: "radiogroup",
|
|
22649
|
+
"aria-disabled": disabled,
|
|
22650
|
+
className: cn("inline-flex isolate", className),
|
|
22651
|
+
style,
|
|
22652
|
+
children: options.map((o, i) => {
|
|
22653
|
+
const selected = o.value === value;
|
|
22654
|
+
const od = disabled || o.disabled;
|
|
22655
|
+
const first = i === 0;
|
|
22656
|
+
const last = i === options.length - 1;
|
|
22657
|
+
const tooltip = showTooltip && o.tooltip ? o.tooltip : void 0;
|
|
22658
|
+
const button = /* @__PURE__ */ jsxRuntime.jsx(
|
|
22659
|
+
"button",
|
|
22660
|
+
{
|
|
22661
|
+
type: "button",
|
|
22662
|
+
role: "radio",
|
|
22663
|
+
name,
|
|
22664
|
+
"aria-checked": selected,
|
|
22665
|
+
disabled: od,
|
|
22666
|
+
onClick: () => !od && !selected && onValueChange?.(o.value),
|
|
22667
|
+
onMouseEnter: tooltip ? () => setHoveredValue(o.value) : void 0,
|
|
22668
|
+
onMouseLeave: tooltip ? () => setHoveredValue(null) : void 0,
|
|
22669
|
+
onFocus: tooltip ? () => setHoveredValue(o.value) : void 0,
|
|
22670
|
+
onBlur: tooltip ? () => setHoveredValue(null) : void 0,
|
|
22671
|
+
className: cn(
|
|
22672
|
+
"relative box-border grow inline-flex items-center justify-center whitespace-nowrap border border-solid font-medium transition-colors",
|
|
22673
|
+
first ? "" : "-ml-px",
|
|
22674
|
+
selected ? "z-10" : "",
|
|
22675
|
+
!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",
|
|
22676
|
+
od ? "cursor-not-allowed" : "cursor-pointer"
|
|
22677
|
+
),
|
|
22678
|
+
style: {
|
|
22679
|
+
height: `var(--cmp-radioButton-${size}-height)`,
|
|
22680
|
+
padding: `0 var(--cmp-radioButton-${size}-paddingX)`,
|
|
22681
|
+
fontSize: `${s.fontSize}px`,
|
|
22682
|
+
lineHeight: `${s.lineHeight}px`,
|
|
22683
|
+
borderRadius: [
|
|
22684
|
+
first ? s.radius : "0",
|
|
22685
|
+
last ? s.radius : "0",
|
|
22686
|
+
last ? s.radius : "0",
|
|
22687
|
+
first ? s.radius : "0"
|
|
22688
|
+
].join(" "),
|
|
22689
|
+
background: od ? "var(--cmp-radioButton-bg-disabled)" : "var(--cmp-radioButton-bg-default)",
|
|
22690
|
+
borderColor: od ? "var(--cmp-radioButton-border-disabled)" : selected ? "var(--cmp-radioButton-border-select)" : "var(--cmp-radioButton-border-default)",
|
|
22691
|
+
color: od ? "var(--cmp-radioButton-content-disabled)" : selected ? "var(--cmp-radioButton-content-select)" : "var(--cmp-radioButton-content-default)"
|
|
22692
|
+
},
|
|
22693
|
+
children: o.label
|
|
22623
22694
|
},
|
|
22624
|
-
|
|
22625
|
-
|
|
22626
|
-
|
|
22627
|
-
|
|
22628
|
-
|
|
22629
|
-
|
|
22630
|
-
|
|
22631
|
-
|
|
22632
|
-
|
|
22633
|
-
|
|
22634
|
-
|
|
22635
|
-
|
|
22636
|
-
|
|
22637
|
-
|
|
22638
|
-
|
|
22639
|
-
|
|
22640
|
-
}
|
|
22695
|
+
o.value
|
|
22696
|
+
);
|
|
22697
|
+
return tooltip ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
22698
|
+
STooltip2,
|
|
22699
|
+
{
|
|
22700
|
+
trigger: "none",
|
|
22701
|
+
open: hoveredValue === o.value,
|
|
22702
|
+
tooltipType: "accent",
|
|
22703
|
+
message: [tooltip],
|
|
22704
|
+
children: button
|
|
22705
|
+
},
|
|
22706
|
+
o.value
|
|
22707
|
+
) : button;
|
|
22708
|
+
})
|
|
22709
|
+
}
|
|
22710
|
+
)
|
|
22641
22711
|
);
|
|
22642
22712
|
}
|
|
22643
22713
|
function SRadioCard({
|