sellmate-design-system-react 9.0.0-beta.10 → 9.0.0-beta.12

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.
Files changed (66) hide show
  1. package/AGENTS.md +3 -3
  2. package/dist/components/SBadge/README.md +24 -0
  3. package/dist/components/SBadge/SBadge.d.ts +1 -1
  4. package/dist/components/SBarcodeInput/README.md +8 -0
  5. package/dist/components/SButton/README.md +34 -0
  6. package/dist/components/SCalendar/README.md +13 -0
  7. package/dist/components/SCallout/README.md +15 -0
  8. package/dist/components/SCheckbox/README.md +8 -0
  9. package/dist/components/SChipFilter/README.md +276 -3
  10. package/dist/components/SChipFilter/SChipFilter.d.ts +78 -37
  11. package/dist/components/SChipFilter/index.d.ts +1 -1
  12. package/dist/components/SChipInput/README.md +14 -0
  13. package/dist/components/SCircleProgress/README.md +8 -0
  14. package/dist/components/SConfirmModal/README.md +16 -0
  15. package/dist/components/SDatePicker/README.md +14 -0
  16. package/dist/components/SDateRangePicker/README.md +14 -0
  17. package/dist/components/SDraggableItem/README.md +36 -0
  18. package/dist/components/SDraggableList/README.md +24 -0
  19. package/dist/components/SDrawer/README.md +8 -0
  20. package/dist/components/SDropdownButton/README.md +19 -0
  21. package/dist/components/SExpansionItem/README.md +36 -0
  22. package/dist/components/SField/README.md +20 -0
  23. package/dist/components/SFilePicker/README.md +14 -0
  24. package/dist/components/SFooter/README.md +21 -0
  25. package/dist/components/SForm/README.md +11 -0
  26. package/dist/components/SGhostButton/README.md +14 -2
  27. package/dist/components/SGnb/README.md +45 -0
  28. package/dist/components/SGuide/README.md +15 -0
  29. package/dist/components/SImage/README.md +14 -0
  30. package/dist/components/SKeyValueTable/README.md +83 -0
  31. package/dist/components/SLayout/README.md +16 -0
  32. package/dist/components/SLinearProgress/README.md +8 -0
  33. package/dist/components/SListItem/README.md +41 -0
  34. package/dist/components/SLoadingModal/README.md +8 -0
  35. package/dist/components/SNumberInput/README.md +8 -0
  36. package/dist/components/SPage/README.md +38 -0
  37. package/dist/components/SPopover/README.md +15 -0
  38. package/dist/components/SPopup/README.md +19 -0
  39. package/dist/components/SPortal/README.md +14 -0
  40. package/dist/components/SRadio/README.md +20 -0
  41. package/dist/components/SRadioButton/README.md +18 -0
  42. package/dist/components/SScrollArea/README.md +14 -0
  43. package/dist/components/SSearchInput/README.md +13 -0
  44. package/dist/components/SSectionHeaderCard/README.md +32 -0
  45. package/dist/components/SSelect/README.md +21 -2
  46. package/dist/components/SSplitter/README.md +15 -0
  47. package/dist/components/SStepper/README.md +26 -0
  48. package/dist/components/STable/README.md +103 -0
  49. package/dist/components/STabs/README.md +12 -0
  50. package/dist/components/STag/README.md +47 -0
  51. package/dist/components/STextLink/README.md +14 -0
  52. package/dist/components/STimePicker/README.md +14 -0
  53. package/dist/components/STimeRangePicker/README.md +26 -0
  54. package/dist/components/SToast/README.md +24 -0
  55. package/dist/components/SToggle/README.md +8 -0
  56. package/dist/components/STooltip/README.md +20 -0
  57. package/dist/components/STree/README.md +38 -0
  58. package/dist/index.cjs +170 -186
  59. package/dist/index.cjs.map +1 -1
  60. package/dist/index.js +170 -186
  61. package/dist/index.js.map +1 -1
  62. package/dist/lib/story-docs.d.ts +19 -3
  63. package/dist/llms-full.txt +1444 -15
  64. package/dist/llms.txt +3 -3
  65. package/dist/styles.css +5 -16
  66. package/package.json +1 -1
@@ -40,6 +40,26 @@
40
40
  | `show` | `() => void` | 툴팁을 표시합니다. |
41
41
  | `hide` | `() => void` | 툴팁을 숨깁니다. |
42
42
 
43
+ ## Types
44
+
45
+ ### STooltipTrigger
46
+
47
+ ```ts
48
+ export type STooltipTrigger = 'hover' | 'click' | 'none';
49
+ ```
50
+
51
+ ### STooltipPlacement
52
+
53
+ ```ts
54
+ export type STooltipPlacement = 'top' | 'bottom' | 'left' | 'right';
55
+ ```
56
+
57
+ ### STooltipType
58
+
59
+ ```ts
60
+ export type STooltipType = 'default' | 'danger' | 'warning' | 'accent';
61
+ ```
62
+
43
63
  ## Dependencies
44
64
 
45
65
  ### Used by
@@ -56,6 +56,44 @@
56
56
  | `onValueChange` | `(value: string[], node: STreeNode) => void` | 선택 변경 |
57
57
  | `onExpandedChange` | `(expandedIds: string[], node: STreeNode) => void` | 펼침 변경 |
58
58
 
59
+ ## Types
60
+
61
+ ### STreeNode
62
+
63
+ ```ts
64
+ export interface STreeNode {
65
+ /** 노드 고유 ID */
66
+ id: string;
67
+ /** 노드 라벨 */
68
+ label: ReactNode;
69
+ /** 하위 노드 */
70
+ children?: STreeNode[];
71
+ /** 비활성 상태 */
72
+ disabled?: boolean;
73
+ }
74
+ ```
75
+
76
+ ### STreeSize
77
+
78
+ ```ts
79
+ export type STreeSize = 'sm' | 'md';
80
+ ```
81
+
82
+ ### STreeItemRenderState
83
+
84
+ ```ts
85
+ export interface STreeItemRenderState {
86
+ node: STreeNode;
87
+ depth: number;
88
+ size: STreeSize;
89
+ expanded: boolean;
90
+ selected: boolean;
91
+ indeterminate: boolean;
92
+ disabled: boolean;
93
+ hasChildren: boolean;
94
+ }
95
+ ```
96
+
59
97
  ## Dependencies
60
98
 
61
99
  ### Depends on
package/dist/index.cjs CHANGED
@@ -3349,6 +3349,7 @@ var BADGE_COLORS = [
3349
3349
  "orange",
3350
3350
  "yellow",
3351
3351
  "green",
3352
+ "lightblue",
3352
3353
  "blue",
3353
3354
  "darkblue",
3354
3355
  "indigo",
@@ -7010,7 +7011,7 @@ function SModalContainer({
7010
7011
  "div",
7011
7012
  {
7012
7013
  className: cn(
7013
- "relative flex max-h-[85dvh] max-w-[calc(100dvw-48px)] flex-col overflow-hidden rounded-[var(--cmp-modal-radius)] bg-[var(--cmp-modal-bg)] shadow-normal-md",
7014
+ "relative flex max-h-[calc(100dvh-48px)] max-w-[calc(100dvw-48px)] flex-col overflow-hidden rounded-[var(--cmp-modal-radius)] bg-[var(--cmp-modal-bg)] shadow-normal-md",
7014
7015
  shaking && "animate-modal-shake",
7015
7016
  className
7016
7017
  ),
@@ -7267,7 +7268,7 @@ function SActionModal({
7267
7268
  showClose: true,
7268
7269
  width,
7269
7270
  height,
7270
- className: "w-fit min-w-[min(480px,calc(100dvw-48px))] min-h-[min(320px,85dvh)]",
7271
+ className: "w-fit min-w-[min(480px,calc(100dvw-48px))] min-h-[min(320px,calc(100dvh-48px))]",
7271
7272
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-auto flex-col", children: [
7272
7273
  /* @__PURE__ */ jsxRuntime.jsx(SOverlayHeader, { title: modalTitle, description, reserveCloseSpace: true }),
7273
7274
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1 overflow-auto px-[var(--cmp-modal-action-body-paddingX)] pb-[var(--cmp-modal-action-body-paddingBottom)]", children }),
@@ -10208,6 +10209,122 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
10208
10209
  );
10209
10210
  });
10210
10211
 
10212
+ // src/lib/autofill.ts
10213
+ var AUTOFILL_RESET_CLASS = "autofill:[-webkit-text-fill-color:currentColor] autofill:[box-shadow:0_0_0_1000px_var(--sys-color-field-bg-default)_inset] autofill:[transition:background-color_5000s_ease-in-out_0s] [&:-webkit-autofill]:[-webkit-text-fill-color:currentColor] [&:-webkit-autofill]:[box-shadow:0_0_0_1000px_var(--sys-color-field-bg-default)_inset] [&:-webkit-autofill]:[transition:background-color_5000s_ease-in-out_0s]";
10214
+ var FONT = {
10215
+ sm: {
10216
+ fontSize: 12,
10217
+ lineHeight: 20,
10218
+ paddingX: "var(--cmp-textinput-sm-paddingX)",
10219
+ gap: "var(--cmp-textinput-sm-gap)"
10220
+ },
10221
+ md: {
10222
+ fontSize: 14,
10223
+ lineHeight: 24,
10224
+ paddingX: "var(--cmp-textinput-md-paddingX)",
10225
+ gap: "var(--cmp-textinput-md-gap)"
10226
+ }
10227
+ };
10228
+ var SSearchInput = /* @__PURE__ */ react.forwardRef(function SSearchInput2({
10229
+ value,
10230
+ onValueChange,
10231
+ onChange,
10232
+ onSearch,
10233
+ size = "sm",
10234
+ placeholder = "\uACB0\uACFC \uB0B4 \uAC80\uC0C9",
10235
+ clearable = false,
10236
+ disabled = false,
10237
+ width,
10238
+ focused,
10239
+ hovered,
10240
+ inputClass,
10241
+ inputStyle,
10242
+ className,
10243
+ style,
10244
+ onKeyDown,
10245
+ ...rest
10246
+ }, ref) {
10247
+ const f = FONT[size];
10248
+ const hasValue = value !== void 0 && value !== null && String(value) !== "";
10249
+ return /* @__PURE__ */ jsxRuntime.jsx(
10250
+ SField,
10251
+ {
10252
+ size,
10253
+ width,
10254
+ focused,
10255
+ hovered,
10256
+ disabled,
10257
+ className,
10258
+ style,
10259
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
10260
+ "div",
10261
+ {
10262
+ className: "flex h-full w-full items-center",
10263
+ style: {
10264
+ gap: f.gap,
10265
+ padding: `0 ${f.paddingX}`,
10266
+ fontSize: f.fontSize,
10267
+ lineHeight: `${f.lineHeight}px`
10268
+ },
10269
+ children: [
10270
+ /* @__PURE__ */ jsxRuntime.jsx(
10271
+ SIcon,
10272
+ {
10273
+ name: "search",
10274
+ size: 16,
10275
+ color: disabled ? "var(--sys-color-disabled-icon)" : "var(--cmp-textinput-icon-default)",
10276
+ className: "flex-shrink-0"
10277
+ }
10278
+ ),
10279
+ /* @__PURE__ */ jsxRuntime.jsx(
10280
+ "input",
10281
+ {
10282
+ ref,
10283
+ type: "search",
10284
+ value: value ?? "",
10285
+ disabled,
10286
+ placeholder,
10287
+ onChange: (e) => {
10288
+ onChange?.(e);
10289
+ onValueChange?.(e.target.value);
10290
+ },
10291
+ onKeyDown: (e) => {
10292
+ onKeyDown?.(e);
10293
+ if (e.key === "Enter" && !e.nativeEvent.isComposing) {
10294
+ onSearch?.(e.currentTarget.value);
10295
+ }
10296
+ },
10297
+ className: cn(
10298
+ // type="search" 의 브라우저 기본 취소 버튼은 clearable 과 겹치므로 지운다
10299
+ "h-full min-w-0 flex-1 border-0 bg-transparent p-0 outline-none placeholder:text-[color:var(--sys-color-field-text-placeholder)] disabled:cursor-not-allowed [&::-webkit-search-cancel-button]:hidden",
10300
+ AUTOFILL_RESET_CLASS,
10301
+ inputClass
10302
+ ),
10303
+ style: {
10304
+ // fontSize/lineHeight 는 컨테이너에서 상속 (원본 font-size: inherit)
10305
+ color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--sys-color-field-text-default)",
10306
+ ...inputStyle
10307
+ },
10308
+ ...rest
10309
+ }
10310
+ ),
10311
+ clearable && hasValue && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
10312
+ SGhostButton,
10313
+ {
10314
+ icon: "close",
10315
+ size: "xxs",
10316
+ ariaLabel: "\uC9C0\uC6B0\uAE30",
10317
+ className: "flex-shrink-0",
10318
+ onClick: () => onValueChange?.("")
10319
+ }
10320
+ )
10321
+ ]
10322
+ }
10323
+ )
10324
+ }
10325
+ );
10326
+ });
10327
+
10211
10328
  // src/components/SSelect/select.config.ts
10212
10329
  function flattenOptions(options, depth = 1) {
10213
10330
  const out = [];
@@ -10626,31 +10743,17 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
10626
10743
  {
10627
10744
  ref: searchBarRef,
10628
10745
  className: "sticky top-0 z-[1] bg-[var(--cmp-listBox-bg)] px-[8px] py-[4px]",
10629
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-[6px] rounded-[4px] border border-solid border-[color:var(--color-grey-45)] bg-white px-[8px] py-[4px] focus-within:border-[color:var(--sys-color-field-border-focus)]", children: [
10630
- /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "search", size: 16, color: "var(--color-grey-70)", className: "shrink-0" }),
10631
- /* @__PURE__ */ jsxRuntime.jsx(
10632
- "input",
10633
- {
10634
- ref: searchInputRef,
10635
- value: search,
10636
- onChange: (e) => setSearch(e.target.value),
10637
- onKeyDown: handleKeyDown,
10638
- placeholder: "\uAC80\uC0C9",
10639
- className: "min-w-0 flex-1 border-none bg-transparent text-[12px] leading-[20px] text-[color:var(--cmp-select-text-default)] outline-none placeholder:text-[color:var(--color-grey-55)]"
10640
- }
10641
- ),
10642
- search !== "" && /* @__PURE__ */ jsxRuntime.jsx(
10643
- SGhostButton,
10644
- {
10645
- icon: "close",
10646
- size: "xxs",
10647
- intent: "default",
10648
- ariaLabel: "\uAC80\uC0C9\uC5B4 \uC9C0\uC6B0\uAE30",
10649
- onClick: () => setSearch(""),
10650
- className: "shrink-0"
10651
- }
10652
- )
10653
- ] })
10746
+ children: /* @__PURE__ */ jsxRuntime.jsx(
10747
+ SSearchInput,
10748
+ {
10749
+ ref: searchInputRef,
10750
+ value: search,
10751
+ onValueChange: setSearch,
10752
+ onKeyDown: handleKeyDown,
10753
+ placeholder: "\uAC80\uC0C9",
10754
+ clearable: true
10755
+ }
10756
+ )
10654
10757
  }
10655
10758
  ),
10656
10759
  hasItems ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -11530,9 +11633,6 @@ var STableBar = /* @__PURE__ */ react.forwardRef(function STableBar2({ total, se
11530
11633
  }
11531
11634
  );
11532
11635
  });
11533
-
11534
- // src/lib/autofill.ts
11535
- var AUTOFILL_RESET_CLASS = "autofill:[-webkit-text-fill-color:currentColor] autofill:[box-shadow:0_0_0_1000px_var(--sys-color-field-bg-default)_inset] autofill:[transition:background-color_5000s_ease-in-out_0s] [&:-webkit-autofill]:[-webkit-text-fill-color:currentColor] [&:-webkit-autofill]:[box-shadow:0_0_0_1000px_var(--sys-color-field-bg-default)_inset] [&:-webkit-autofill]:[transition:background-color_5000s_ease-in-out_0s]";
11536
11636
  var HIDE_DELAY_MS2 = 100;
11537
11637
  function mergeRefs(...refs) {
11538
11638
  return (node) => {
@@ -11594,7 +11694,7 @@ function useTruncatedValueTooltip({
11594
11694
  ] }) : null
11595
11695
  };
11596
11696
  }
11597
- var FONT = {
11697
+ var FONT2 = {
11598
11698
  sm: { fontSize: 12, lineHeight: 20, paddingX: "var(--cmp-textinput-sm-paddingX)" },
11599
11699
  md: { fontSize: 14, lineHeight: 24, paddingX: "var(--cmp-textinput-md-paddingX)" }
11600
11700
  };
@@ -11635,7 +11735,7 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
11635
11735
  }, ref) {
11636
11736
  const [visible, setVisible] = react.useState(false);
11637
11737
  const [ruleError, setRuleError] = react.useState("");
11638
- const f = FONT[size];
11738
+ const f = FONT2[size];
11639
11739
  const isPassword = type === "password";
11640
11740
  const inputType = isPassword ? visible ? "text" : "password" : type;
11641
11741
  const hasValue = value !== void 0 && value !== null && String(value) !== "";
@@ -14503,119 +14603,6 @@ function SRadioButton({
14503
14603
  }
14504
14604
  );
14505
14605
  }
14506
- var FONT2 = {
14507
- sm: {
14508
- fontSize: 12,
14509
- lineHeight: 20,
14510
- paddingX: "var(--cmp-textinput-sm-paddingX)",
14511
- gap: "var(--cmp-textinput-sm-gap)"
14512
- },
14513
- md: {
14514
- fontSize: 14,
14515
- lineHeight: 24,
14516
- paddingX: "var(--cmp-textinput-md-paddingX)",
14517
- gap: "var(--cmp-textinput-md-gap)"
14518
- }
14519
- };
14520
- var SSearchInput = /* @__PURE__ */ react.forwardRef(function SSearchInput2({
14521
- value,
14522
- onValueChange,
14523
- onChange,
14524
- onSearch,
14525
- size = "sm",
14526
- placeholder = "\uACB0\uACFC \uB0B4 \uAC80\uC0C9",
14527
- clearable = false,
14528
- disabled = false,
14529
- width,
14530
- focused,
14531
- hovered,
14532
- inputClass,
14533
- inputStyle,
14534
- className,
14535
- style,
14536
- onKeyDown,
14537
- ...rest
14538
- }, ref) {
14539
- const f = FONT2[size];
14540
- const hasValue = value !== void 0 && value !== null && String(value) !== "";
14541
- return /* @__PURE__ */ jsxRuntime.jsx(
14542
- SField,
14543
- {
14544
- size,
14545
- width,
14546
- focused,
14547
- hovered,
14548
- disabled,
14549
- className,
14550
- style,
14551
- children: /* @__PURE__ */ jsxRuntime.jsxs(
14552
- "div",
14553
- {
14554
- className: "flex h-full w-full items-center",
14555
- style: {
14556
- gap: f.gap,
14557
- padding: `0 ${f.paddingX}`,
14558
- fontSize: f.fontSize,
14559
- lineHeight: `${f.lineHeight}px`
14560
- },
14561
- children: [
14562
- /* @__PURE__ */ jsxRuntime.jsx(
14563
- SIcon,
14564
- {
14565
- name: "search",
14566
- size: 16,
14567
- color: disabled ? "var(--sys-color-disabled-icon)" : "var(--cmp-textinput-icon-default)",
14568
- className: "flex-shrink-0"
14569
- }
14570
- ),
14571
- /* @__PURE__ */ jsxRuntime.jsx(
14572
- "input",
14573
- {
14574
- ref,
14575
- type: "search",
14576
- value: value ?? "",
14577
- disabled,
14578
- placeholder,
14579
- onChange: (e) => {
14580
- onChange?.(e);
14581
- onValueChange?.(e.target.value);
14582
- },
14583
- onKeyDown: (e) => {
14584
- onKeyDown?.(e);
14585
- if (e.key === "Enter" && !e.nativeEvent.isComposing) {
14586
- onSearch?.(e.currentTarget.value);
14587
- }
14588
- },
14589
- className: cn(
14590
- // type="search" 의 브라우저 기본 취소 버튼은 clearable 과 겹치므로 지운다
14591
- "h-full min-w-0 flex-1 border-0 bg-transparent p-0 outline-none placeholder:text-[color:var(--sys-color-field-text-placeholder)] disabled:cursor-not-allowed [&::-webkit-search-cancel-button]:hidden",
14592
- AUTOFILL_RESET_CLASS,
14593
- inputClass
14594
- ),
14595
- style: {
14596
- // fontSize/lineHeight 는 컨테이너에서 상속 (원본 font-size: inherit)
14597
- color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--sys-color-field-text-default)",
14598
- ...inputStyle
14599
- },
14600
- ...rest
14601
- }
14602
- ),
14603
- clearable && hasValue && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
14604
- SGhostButton,
14605
- {
14606
- icon: "close",
14607
- size: "xxs",
14608
- ariaLabel: "\uC9C0\uC6B0\uAE30",
14609
- className: "flex-shrink-0",
14610
- onClick: () => onValueChange?.("")
14611
- }
14612
- )
14613
- ]
14614
- }
14615
- )
14616
- }
14617
- );
14618
- });
14619
14606
  var CHIPFILTER_LISTBOX_WIDTH = 240;
14620
14607
  var CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH = 246;
14621
14608
  var CHIPFILTER = {
@@ -14708,10 +14695,10 @@ var createPeriodValue = (unit) => ({
14708
14695
  });
14709
14696
  var resolveFieldDefault = (field) => {
14710
14697
  if (field.defaultValue !== void 0) return field.defaultValue;
14711
- if (isInlineDateField(field)) return todayIso();
14698
+ if (field.type === "date")
14699
+ return isInlineDateField(field) || field.required ? todayIso() : void 0;
14712
14700
  if (!field.required) return void 0;
14713
14701
  if (field.type === "single") return field.options?.[0]?.value;
14714
- if (field.type === "date") return todayIso();
14715
14702
  if (field.type === "period") {
14716
14703
  const unit = getFieldPresets(field).find((preset) => !preset.custom)?.value;
14717
14704
  return unit ? createPeriodValue(unit) : void 0;
@@ -14738,10 +14725,18 @@ var isAtDefaultValue = (field, value) => {
14738
14725
  const def = resolveFieldDefault(field);
14739
14726
  return def !== void 0 && valuesEqual(value, def);
14740
14727
  };
14728
+ var resetTargetValue = (field) => {
14729
+ const def = resolveFieldDefault(field);
14730
+ return def !== void 0 ? def : null;
14731
+ };
14732
+ var isAtResetTarget = (field, value) => {
14733
+ const target = resetTargetValue(field);
14734
+ if (isEmptyValue(value) && isEmptyValue(target)) return true;
14735
+ return valuesEqual(value, target);
14736
+ };
14741
14737
  var isInlineField = (field) => isInlineDateField(field) || field.type === "custom";
14742
- var isFixedField = (field) => field.fix === true || field.required === true;
14738
+ var isFixedField = (field) => field.fixed === true || field.required === true;
14743
14739
  var isAddableField = (field) => !isFixedField(field);
14744
- var isGroupedFields = (fields) => fields.length > 0 && "fields" in fields[0];
14745
14740
  var isGroupSatisfied = (group, values) => {
14746
14741
  if (!group.rule) return true;
14747
14742
  const keys = group.fields.map((f) => f.key);
@@ -14821,7 +14816,7 @@ var chipDisplayValue = (field, value) => {
14821
14816
  return preset && !preset.custom ? `${preset.label}(${text})` : text;
14822
14817
  };
14823
14818
  var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
14824
- fields: fieldsProp = [],
14819
+ fields: groups = [],
14825
14820
  value,
14826
14821
  onValueChange,
14827
14822
  onFilterChange,
@@ -14837,16 +14832,11 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
14837
14832
  className,
14838
14833
  style
14839
14834
  }, ref) {
14840
- const usingGroupedFields = isGroupedFields(fieldsProp);
14841
- const groups = react.useMemo(
14842
- () => usingGroupedFields ? fieldsProp : [{ fields: fieldsProp }],
14843
- [usingGroupedFields, fieldsProp]
14844
- );
14845
14835
  const fields = react.useMemo(() => groups.flatMap((group) => group.fields), [groups]);
14846
14836
  const values = normalizeValues(value);
14847
14837
  const portalContainer = usePortalContainer();
14848
14838
  const [internalActiveKeys, setInternalActiveKeys] = react.useState(
14849
- () => fields.filter((field) => isFixedField(field) || field.defaultActive !== false).map((field) => field.key)
14839
+ () => fields.filter(isFixedField).map((field) => field.key)
14850
14840
  );
14851
14841
  const [openKey, setOpenKey] = react.useState(null);
14852
14842
  const [addOpen, setAddOpen] = react.useState(false);
@@ -14888,9 +14878,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
14888
14878
  setInternalActiveKeys((current) => {
14889
14879
  const known = new Set(fields.map((field) => field.key));
14890
14880
  const kept = current.filter((key) => known.has(key));
14891
- const additions = fields.filter(
14892
- (field) => (isFixedField(field) || field.defaultActive !== false) && !kept.includes(field.key)
14893
- ).map((field) => field.key);
14881
+ const additions = fields.filter((field) => isFixedField(field) && !kept.includes(field.key)).map((field) => field.key);
14894
14882
  return [...kept, ...additions];
14895
14883
  });
14896
14884
  }, [activeKeys, fields]);
@@ -14923,7 +14911,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
14923
14911
  groups.forEach((group, groupIndex) => {
14924
14912
  group.fields.forEach((field) => groupIndexByKey.set(field.key, groupIndex));
14925
14913
  });
14926
- const hasValue = fields.some((field) => !isEmptyValue(values[field.key]));
14914
+ const canReset = fields.some((field) => !isAtResetTarget(field, values[field.key]));
14927
14915
  const hasAddButton = fields.some(isAddableField);
14928
14916
  const hasRightActions = hasAddButton || showReset;
14929
14917
  const currentOpenField = fields.find((field) => field.key === openKey);
@@ -14962,8 +14950,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
14962
14950
  };
14963
14951
  const reset = react.useCallback(() => {
14964
14952
  const next = fields.reduce((acc, field) => {
14965
- const def = resolveFieldDefault(field);
14966
- acc[field.key] = def !== void 0 ? def : null;
14953
+ acc[field.key] = resetTargetValue(field);
14967
14954
  return acc;
14968
14955
  }, {});
14969
14956
  onValueChange?.(next);
@@ -15021,7 +15008,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
15021
15008
  const flushRun = () => {
15022
15009
  if (runBuffer.length === 0) return;
15023
15010
  const group = runGroupIndex != null ? groups[runGroupIndex] : void 0;
15024
- const message = usingGroupedFields && group?.rule ? group.tooltipMessage ?? defaultGroupTooltipMessage(group.rule, group.fields) : void 0;
15011
+ const message = group?.rule ? group.tooltipMessage ?? defaultGroupTooltipMessage(group.rule, group.fields) : void 0;
15025
15012
  if (message) {
15026
15013
  nodes.push(
15027
15014
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -15045,7 +15032,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
15045
15032
  const warning = field.warning || invalidGroups.has(groupIndex);
15046
15033
  const prevField = index > 0 ? activeFields[index - 1] : null;
15047
15034
  const prevGroupIndex = prevField ? groupIndexByKey.get(prevField.key) ?? 0 : null;
15048
- const needsLeadingDivider = index === 0 ? false : inline || prevField != null && isInlineField(prevField) || groupIndex !== prevGroupIndex;
15035
+ const needsLeadingDivider = index === 0 ? false : inline || prevField != null && isInlineField(prevField) || groupIndex !== prevGroupIndex && groups[groupIndex]?.divider === true;
15049
15036
  if (groupIndex !== runGroupIndex) {
15050
15037
  flushRun();
15051
15038
  runGroupIndex = groupIndex;
@@ -15059,7 +15046,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
15059
15046
  }
15060
15047
  clearValue(field.key);
15061
15048
  };
15062
- const node = isInlineDateField(field) ? /* @__PURE__ */ jsxRuntime.jsx(
15049
+ const node = field.type === "date" && isInlineDateField(field) ? /* @__PURE__ */ jsxRuntime.jsx(
15063
15050
  InlineDatePresetFilter,
15064
15051
  {
15065
15052
  field,
@@ -15085,7 +15072,14 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
15085
15072
  "aria-label": `${field.label} \uD544\uD130 \uC81C\uAC70`,
15086
15073
  className: "inline-flex size-[16px] shrink-0 items-center justify-center rounded-[var(--cmp-ghostButton-radius-sm)] border-none bg-transparent p-0",
15087
15074
  onClick: handleClear,
15088
- children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
15075
+ children: /* @__PURE__ */ jsxRuntime.jsx(
15076
+ SIcon,
15077
+ {
15078
+ name: "close",
15079
+ size: 12,
15080
+ color: "var(--cmp-ghostButton-default-content)"
15081
+ }
15082
+ )
15089
15083
  }
15090
15084
  )
15091
15085
  ] }, field.key) : /* @__PURE__ */ jsxRuntime.jsx(
@@ -15159,32 +15153,22 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
15159
15153
  }
15160
15154
  ) })
15161
15155
  ] }),
15162
- showReset && /* @__PURE__ */ jsxRuntime.jsxs(
15163
- "button",
15156
+ showReset && /* @__PURE__ */ jsxRuntime.jsx(
15157
+ STextLink,
15164
15158
  {
15165
- type: "button",
15166
- disabled: disabled || !hasValue,
15159
+ size: "sm",
15160
+ icon: "reset",
15161
+ iconColor: "grey_80",
15162
+ label: "\uAC80\uC0C9 \uCD08\uAE30\uD654",
15163
+ labelClass: "text-grey-80",
15164
+ disabled: disabled || !canReset,
15167
15165
  onClick: reset,
15168
15166
  className: cn(
15169
- "inline-flex shrink-0 cursor-pointer items-center gap-[4px] border-none bg-transparent p-0 text-[12px] font-medium leading-[20px] disabled:cursor-not-allowed",
15167
+ "shrink-0",
15170
15168
  // 부모 flex gap(6px)은 칩 사이 간격 기준이라, 필터 추가 버튼과의 12px 간격을 맞추려면
15171
15169
  // 부족한 만큼(12px - gap)을 추가로 띄운다. 필터 추가가 없을 땐 divider와 이미 12px이라 불필요.
15172
15170
  hasAddButton && "ml-[calc(12px-var(--cmp-chipFilter-chip-group))]"
15173
- ),
15174
- style: {
15175
- color: disabled || !hasValue ? "var(--cmp-textLink-content-disabled)" : "var(--cmp-textLink-content-default)"
15176
- },
15177
- children: [
15178
- /* @__PURE__ */ jsxRuntime.jsx(
15179
- SIcon,
15180
- {
15181
- name: "reset",
15182
- size: 16,
15183
- color: disabled || !hasValue ? "var(--cmp-textLink-icon-disabled)" : "var(--cmp-textLink-icon-default)"
15184
- }
15185
- ),
15186
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\uAC80\uC0C9 \uCD08\uAE30\uD654" })
15187
- ]
15171
+ )
15188
15172
  }
15189
15173
  )
15190
15174
  ] })