sellmate-design-system-react 9.0.0-beta.78 → 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.
@@ -13,7 +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
+ | `valueDisplay?` | `SSelectValueDisplay` | `'text'` | 트리거에 선택값을 보여주는 방식. - `text`: 선택 라벨을 쉼표로 이어 한 줄로 보여준다. 넘치면 말줄임한다. - `chip`: 선택값마다 칩을 낸다. 칩의 × 를 누르면 그 값만 선택에서 빠지고, 드롭다운은 열리지 않는다. 칩이 한 줄을 넘으면 줄바꿈하고 트리거가 그만큼 높아진다. `chip` 은 `multi`·`multi_depth` 에서만 동작한다. 단일 선택 type 에서는 무시하고 `text` 로 보여준다. 전체 선택이면 칩 대신 `allSelectedLabel` 을 보여준다. `multi_depth` 에서 그룹의 하위 리프를 전부 고르면 리프 칩 대신 그룹명 칩 하나로 묶고, 그 칩의 × 는 그룹의 리프를 한꺼번에 뺀다. 비활성(select 자체나 해당 옵션)인 칩에는 × 를 내지 않는다. |
17
17
  | `showSearch?` | `boolean` | `false` | 검색 입력 사용 |
18
18
  | `showSelectAll?` | `boolean` | `false` | 전체선택 옵션 사용 (multi 전용) |
19
19
  | `allSelectedLabel?` | `string` | `'전체'` | 전체선택 레이블 |
@@ -52,6 +52,8 @@ export interface SSelectProps<TValue extends SSelectChangeValue = SSelectChangeV
52
52
  *
53
53
  * `chip` 은 `multi`·`multi_depth` 에서만 동작한다. 단일 선택 type 에서는 무시하고 `text` 로 보여준다.
54
54
  * 전체 선택이면 칩 대신 `allSelectedLabel` 을 보여준다.
55
+ * `multi_depth` 에서 그룹의 하위 리프를 전부 고르면 리프 칩 대신 그룹명 칩 하나로 묶고,
56
+ * 그 칩의 × 는 그룹의 리프를 한꺼번에 뺀다.
55
57
  * 비활성(select 자체나 해당 옵션)인 칩에는 × 를 내지 않는다.
56
58
  */
57
59
  valueDisplay?: SSelectValueDisplay;
package/dist/index.cjs CHANGED
@@ -15958,11 +15958,46 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
15958
15958
  () => new Set(flat.filter((o) => !o.isGroup && o.disabled).map((o) => o.value)),
15959
15959
  [flat]
15960
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
- })) : [];
15961
+ const fullGroupByLeaf = react.useMemo(() => {
15962
+ const map = /* @__PURE__ */ new Map();
15963
+ if (!showChips || type !== "multi_depth") return map;
15964
+ flat.forEach((o, i) => {
15965
+ if (!o.isGroup) return;
15966
+ const leafValues = collectGroupLeafValues(flat, i);
15967
+ if (leafValues.length === 0 || leafValues.some((v) => !selectedSet.has(v))) return;
15968
+ if (map.has(leafValues[0])) return;
15969
+ const group = { value: o.value, label: o.label, leafValues };
15970
+ for (let j = i + 1; j < flat.length && flat[j].depth > o.depth; j++) {
15971
+ if (!flat[j].isGroup && selectedSet.has(flat[j].value)) map.set(flat[j].value, group);
15972
+ }
15973
+ });
15974
+ return map;
15975
+ }, [flat, selectedSet, showChips, type]);
15976
+ const chips = [];
15977
+ if (showChips) {
15978
+ const placedGroups = /* @__PURE__ */ new Set();
15979
+ for (const v of selected) {
15980
+ const group = fullGroupByLeaf.get(v);
15981
+ if (group != null) {
15982
+ if (placedGroups.has(group.value)) continue;
15983
+ placedGroups.add(group.value);
15984
+ chips.push({
15985
+ // 그룹 value 와 리프 value 가 겹쳐도 key 가 부딪히지 않게 구분한다.
15986
+ key: `__group_${group.value}__`,
15987
+ label: group.label,
15988
+ values: group.leafValues,
15989
+ removable: !effectiveDisabled
15990
+ });
15991
+ continue;
15992
+ }
15993
+ chips.push({
15994
+ key: v,
15995
+ label: labelByValue.get(v) ?? valueOptions.get(v)?.label ?? v,
15996
+ values: [v],
15997
+ removable: !effectiveDisabled && !disabledValues.has(v)
15998
+ });
15999
+ }
16000
+ }
15966
16001
  const isPlaceholder = selected.length === 0;
15967
16002
  const showTriggerSpinner = loading2 && !effectiveDisabled;
15968
16003
  const showClear = clearable && !effectiveDisabled && !isPlaceholder;
@@ -15970,8 +16005,9 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
15970
16005
  emit3([]);
15971
16006
  if (rules && rules.length > 0) setRuleError(runRules(multi ? [] : "", rules));
15972
16007
  };
15973
- const handleRemoveChip = (target) => {
15974
- const next = selected.filter((v) => v !== target);
16008
+ const handleRemoveChip = (targets) => {
16009
+ const remove = new Set(targets);
16010
+ const next = selected.filter((v) => !remove.has(v));
15975
16011
  emit3(next);
15976
16012
  if (rules && rules.length > 0) setRuleError(runRules(next, rules));
15977
16013
  triggerRef.current?.focus();
@@ -16191,12 +16227,12 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
16191
16227
  TriggerRemoveButton,
16192
16228
  {
16193
16229
  ariaLabel: `${isHtmlLabel(chip.label) ? extractText(chip.label) : chip.label} \uC120\uD0DD \uD574\uC81C`,
16194
- onRemove: () => handleRemoveChip(chip.value)
16230
+ onRemove: () => handleRemoveChip(chip.values)
16195
16231
  }
16196
16232
  )
16197
16233
  ]
16198
16234
  },
16199
- chip.value
16235
+ chip.key
16200
16236
  ))
16201
16237
  }
16202
16238
  )