sellmate-design-system-react 9.0.0-beta.93 → 9.0.0-beta.95

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 (31) hide show
  1. package/AGENTS.md +1 -0
  2. package/dist/components/SButton/button.config.d.ts +2 -1
  3. package/dist/components/SChatAttachedFile/chatAttachedFile.config.d.ts +2 -2
  4. package/dist/components/SChatFile/chatFile.config.d.ts +2 -2
  5. package/dist/components/SChipFilter/README.md +2 -0
  6. package/dist/components/SGhostButton/README.md +2 -0
  7. package/dist/components/SGnb/gnb.config.d.ts +6 -0
  8. package/dist/components/SIcon/README.md +3 -1
  9. package/dist/components/SIcon/SIcon.d.ts +1 -1
  10. package/dist/components/SLauncherListBox/launcherListBox.config.d.ts +2 -7
  11. package/dist/components/SLoadingModal/README.md +2 -2
  12. package/dist/components/SRadioCard/README.md +3 -0
  13. package/dist/components/SRadioCard/SRadioCard.d.ts +7 -2
  14. package/dist/components/SRadioCard/SRadioCardGroup.d.ts +3 -1
  15. package/dist/components/SSelect/README.md +1 -1
  16. package/dist/components/SSelect/SSelect.d.ts +1 -1
  17. package/dist/components/SStepper/stepper.config.d.ts +9 -3
  18. package/dist/components/STabs/tabs.config.d.ts +3 -8
  19. package/dist/components/STag/tag.config.d.ts +10 -9
  20. package/dist/components/STimePicker/timepicker.config.d.ts +3 -0
  21. package/dist/components/STree/README.md +2 -0
  22. package/dist/index.cjs +1101 -854
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.js +1101 -854
  25. package/dist/index.js.map +1 -1
  26. package/dist/lib/list-box-item.d.ts +16 -0
  27. package/dist/lib/tree-row.d.ts +31 -2
  28. package/dist/llms-full.txt +12 -4
  29. package/dist/llms.txt +1 -0
  30. package/dist/styles.css +228 -80
  31. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -3724,16 +3724,21 @@ var SIcon = /* @__PURE__ */ react.forwardRef(function SIcon2({ name, size = 24,
3724
3724
  const Svg = ICONS[name];
3725
3725
  if (!Svg) return null;
3726
3726
  const rotateClass = rotate ? { 90: "rotate-90", 180: "rotate-180", 270: "-rotate-90" }[rotate] : void 0;
3727
+ const cssSize = typeof size === "string" && /var\(|calc\(/.test(size);
3727
3728
  return /* @__PURE__ */ jsxRuntime.jsx(
3728
3729
  "span",
3729
3730
  {
3730
3731
  ref,
3731
3732
  className: cn("inline-flex items-center justify-center", rotateClass, className),
3732
- style: { color: resolveColor(color), ...style },
3733
+ style: {
3734
+ color: resolveColor(color),
3735
+ ...cssSize && { width: size, height: size },
3736
+ ...style
3737
+ },
3733
3738
  role: label ? "img" : void 0,
3734
3739
  "aria-label": label,
3735
3740
  "aria-hidden": label ? void 0 : true,
3736
- children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { size })
3741
+ children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { size: cssSize ? "100%" : size })
3737
3742
  }
3738
3743
  );
3739
3744
  });
@@ -4136,7 +4141,7 @@ var SBadge = /* @__PURE__ */ react.forwardRef(function SBadge2({ color = "blue",
4136
4141
  return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn("inline-flex items-center justify-center", className), ...rest, children: /* @__PURE__ */ jsxRuntime.jsx(
4137
4142
  "span",
4138
4143
  {
4139
- className: "rounded-full",
4144
+ className: "rounded-(--cmp-badge-radius)",
4140
4145
  style: {
4141
4146
  width: "var(--cmp-badge-size, 6px)",
4142
4147
  height: "var(--cmp-badge-size, 6px)",
@@ -4203,7 +4208,8 @@ var BUTTON_SIZE_CONFIG = {
4203
4208
  height: "var(--cmp-button-xs-height)",
4204
4209
  paddingX: "var(--cmp-button-xs-paddingX)",
4205
4210
  gap: "var(--cmp-button-xs-gap)",
4206
- iconSize: 12,
4211
+ iconSize: "var(--cmp-button-xs-icon)",
4212
+ iconOnlyWidth: "var(--cmp-button-iconOnly-xs-width)",
4207
4213
  fontSize: 12,
4208
4214
  fontWeight: 500,
4209
4215
  radius: "var(--cmp-button-radius-sm)",
@@ -4213,7 +4219,8 @@ var BUTTON_SIZE_CONFIG = {
4213
4219
  height: "var(--cmp-button-sm-height)",
4214
4220
  paddingX: "var(--cmp-button-sm-paddingX)",
4215
4221
  gap: "var(--cmp-button-sm-gap)",
4216
- iconSize: 16,
4222
+ iconSize: "var(--cmp-button-sm-icon)",
4223
+ iconOnlyWidth: "var(--cmp-button-iconOnly-sm-width)",
4217
4224
  fontSize: 12,
4218
4225
  fontWeight: 500,
4219
4226
  radius: "var(--cmp-button-radius-sm)",
@@ -4223,7 +4230,8 @@ var BUTTON_SIZE_CONFIG = {
4223
4230
  height: "var(--cmp-button-md-height)",
4224
4231
  paddingX: "var(--cmp-button-md-paddingX)",
4225
4232
  gap: "var(--cmp-button-md-gap)",
4226
- iconSize: 20,
4233
+ iconSize: "var(--cmp-button-md-icon)",
4234
+ iconOnlyWidth: "var(--cmp-button-iconOnly-md-width)",
4227
4235
  fontSize: 16,
4228
4236
  fontWeight: 500,
4229
4237
  radius: "var(--cmp-button-radius-md)",
@@ -4233,7 +4241,8 @@ var BUTTON_SIZE_CONFIG = {
4233
4241
  height: "var(--cmp-button-lg-height)",
4234
4242
  paddingX: "var(--cmp-button-lg-paddingX)",
4235
4243
  gap: "var(--cmp-button-lg-gap)",
4236
- iconSize: 24,
4244
+ iconSize: "var(--cmp-button-lg-icon)",
4245
+ iconOnlyWidth: "var(--cmp-button-iconOnly-lg-width)",
4237
4246
  fontSize: 18,
4238
4247
  fontWeight: 500,
4239
4248
  radius: "var(--cmp-button-radius-md)",
@@ -4280,7 +4289,7 @@ var SButton = /* @__PURE__ */ react.forwardRef(function SButton2({
4280
4289
  "--btn-border": disabled ? BUTTON_DISABLED_BORDER : preset.border,
4281
4290
  "--btn-ring": BUTTON_FOCUS_RING,
4282
4291
  "minHeight": s.height,
4283
- "minWidth": iconOnly ? s.height : hasLabel ? s.minWidth : void 0,
4292
+ "minWidth": iconOnly ? s.iconOnlyWidth : hasLabel ? s.minWidth : void 0,
4284
4293
  "padding": iconOnly ? 0 : `0 ${s.paddingX}`,
4285
4294
  "borderRadius": s.radius,
4286
4295
  "gap": s.gap,
@@ -4297,7 +4306,7 @@ var SButton = /* @__PURE__ */ react.forwardRef(function SButton2({
4297
4306
  disabled,
4298
4307
  "aria-label": ariaLabel,
4299
4308
  className: cn(
4300
- "inline-flex items-center justify-center whitespace-nowrap border border-solid leading-none transition-colors",
4309
+ "inline-flex items-center justify-center whitespace-nowrap border-[length:var(--cmp-button-border-width-default)] border-solid leading-none transition-colors",
4301
4310
  "border-[color:var(--btn-border)] bg-[var(--btn-bg)]",
4302
4311
  "outline-none focus-visible:shadow-[0_0_0_2px_var(--btn-ring)]",
4303
4312
  disabled ? "cursor-not-allowed" : "cursor-pointer hover:bg-[var(--btn-bg-hover)]",
@@ -4415,34 +4424,28 @@ var TAG_COLORS = [
4415
4424
  ];
4416
4425
  var TAG_SIZE_CONFIG = {
4417
4426
  xs: {
4418
- height: 20,
4419
- paddingX: 8,
4420
- gap: 4,
4421
- radius: 6,
4422
- iconSize: 12,
4423
- fontSize: 11,
4424
- fontWeight: 500,
4425
- lineHeight: 18
4427
+ height: "var(--cmp-tag-xs-height)",
4428
+ paddingX: "var(--cmp-tag-xs-paddingX)",
4429
+ gap: "var(--cmp-tag-xs-gap)",
4430
+ radius: "var(--cmp-tag-xs-radius)",
4431
+ iconSize: "var(--cmp-tag-xs-icon)",
4432
+ typography: "typo-feedback-xs"
4426
4433
  },
4427
4434
  sm: {
4428
- height: 24,
4429
- paddingX: 8,
4430
- gap: 4,
4431
- radius: 6,
4432
- iconSize: 16,
4433
- fontSize: 12,
4434
- fontWeight: 600,
4435
- lineHeight: 20
4435
+ height: "var(--cmp-tag-sm-height)",
4436
+ paddingX: "var(--cmp-tag-sm-paddingX)",
4437
+ gap: "var(--cmp-tag-sm-gap)",
4438
+ radius: "var(--cmp-tag-sm-radius)",
4439
+ iconSize: "var(--cmp-tag-sm-icon)",
4440
+ typography: "typo-feedback-sm-semibold"
4436
4441
  },
4437
4442
  md: {
4438
- height: 28,
4439
- paddingX: 12,
4440
- gap: 6,
4441
- radius: 8,
4442
- iconSize: 16,
4443
- fontSize: 14,
4444
- fontWeight: 700,
4445
- lineHeight: 24
4443
+ height: "var(--cmp-tag-md-height)",
4444
+ paddingX: "var(--cmp-tag-md-paddingX)",
4445
+ gap: "var(--cmp-tag-md-gap)",
4446
+ radius: "var(--cmp-tag-md-radius)",
4447
+ iconSize: "var(--cmp-tag-md-icon)",
4448
+ typography: "typo-feedback-md-bold"
4446
4449
  }
4447
4450
  };
4448
4451
  var STag = /* @__PURE__ */ react.forwardRef(function STag2({
@@ -4470,16 +4473,14 @@ var STag = /* @__PURE__ */ react.forwardRef(function STag2({
4470
4473
  "aria-label": label || "tag",
4471
4474
  className: cn(
4472
4475
  "box-border inline-flex w-fit select-none items-center justify-center whitespace-nowrap",
4476
+ s.typography,
4473
4477
  className
4474
4478
  ),
4475
4479
  style: {
4476
4480
  minHeight: s.height,
4477
- padding: `0 ${s.paddingX}px`,
4481
+ padding: `0 ${s.paddingX}`,
4478
4482
  gap: s.gap,
4479
4483
  borderRadius: shape === "pill" ? 999 : s.radius,
4480
- fontSize: s.fontSize,
4481
- fontWeight: s.fontWeight,
4482
- lineHeight: `${s.lineHeight}px`,
4483
4484
  background: bgColor,
4484
4485
  color: contentColor,
4485
4486
  ...resolvedWidth != null ? { width: resolvedWidth } : {},
@@ -4499,11 +4500,11 @@ var STag = /* @__PURE__ */ react.forwardRef(function STag2({
4499
4500
  );
4500
4501
  });
4501
4502
  var SIZE = {
4502
- xxs: { icon: 12, radius: "sm" },
4503
- xs: { icon: 16, radius: "sm" },
4504
- sm: { icon: 20, radius: "sm" },
4505
- md: { icon: 24, radius: "md" },
4506
- lg: { icon: 32, radius: "md" }
4503
+ xxs: { icon: "var(--cmp-ghostButton-xxs-icon)", radius: "sm" },
4504
+ xs: { icon: "var(--cmp-ghostButton-xs-icon)", radius: "sm" },
4505
+ sm: { icon: "var(--cmp-ghostButton-sm-icon)", radius: "sm" },
4506
+ md: { icon: "var(--cmp-ghostButton-md-icon)", radius: "md" },
4507
+ lg: { icon: "var(--cmp-ghostButton-lg-icon)", radius: "md" }
4507
4508
  };
4508
4509
  var TOOLTIP_HIDE_DELAY_MS = 100;
4509
4510
  var SGhostButton = /* @__PURE__ */ react.forwardRef(function SGhostButton2({
@@ -4578,7 +4579,7 @@ var SGhostButton = /* @__PURE__ */ react.forwardRef(function SGhostButton2({
4578
4579
  "span",
4579
4580
  {
4580
4581
  "aria-hidden": true,
4581
- className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover/ghost-button:opacity-5",
4582
+ className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover/ghost-button:opacity-(--cmp-ghostButton-hover-opacity)",
4582
4583
  style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
4583
4584
  }
4584
4585
  ),
@@ -4802,7 +4803,9 @@ var STooltipImpl = /* @__PURE__ */ react.forwardRef(function STooltip({
4802
4803
  ...restContentProps
4803
4804
  } = contentProps ?? {};
4804
4805
  const contentClass = cn(
4805
- "z-50 w-fit max-w-[var(--radix-popover-content-available-width)] rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px] shadow-normal-sm",
4806
+ "z-50 w-fit max-w-[var(--radix-popover-content-available-width)] rounded-(--cmp-tooltip-radius) px-(--cmp-tooltip-paddingX) py-(--cmp-tooltip-paddingY) shadow-normal-sm",
4807
+ // default 500, danger/warning/accent 700 — tooltip.<type>.typography
4808
+ tooltipType === "default" ? "typo-feedback-sm-medium" : "typo-feedback-sm-bold",
4806
4809
  FLOATING_SLIDE_ANIM,
4807
4810
  className,
4808
4811
  contentPropsClassName
@@ -4810,7 +4813,6 @@ var STooltipImpl = /* @__PURE__ */ react.forwardRef(function STooltip({
4810
4813
  const contentStyle = {
4811
4814
  background: bg,
4812
4815
  color: fg,
4813
- fontWeight: tooltipType === "default" ? 500 : 700,
4814
4816
  ...style,
4815
4817
  ...contentPropsStyle
4816
4818
  };
@@ -4851,7 +4853,7 @@ var STooltipImpl = /* @__PURE__ */ react.forwardRef(function STooltip({
4851
4853
  onMouseLeave: isHover ? startHide : void 0,
4852
4854
  ...restContentProps,
4853
4855
  children: [
4854
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-[12px]", children: [
4856
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-(--cmp-tooltip-gap)", children: [
4855
4857
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: body }),
4856
4858
  showClose && !isNone && /* @__PURE__ */ jsxRuntime.jsx(
4857
4859
  SGhostButton,
@@ -4906,16 +4908,20 @@ var FIELD_SIZE = {
4906
4908
  height: 28,
4907
4909
  radius: 4,
4908
4910
  fieldGap: 12,
4909
- labelGap: 6,
4911
+ labelHeight: "var(--cmp-field-label-sm-height)",
4912
+ labelGap: "var(--cmp-field-label-sm-gap)",
4910
4913
  labelTypo: "typo-field-sm-bold",
4914
+ labelIcon: "var(--cmp-field-label-sm-icon)",
4911
4915
  icon: 16
4912
4916
  },
4913
4917
  md: {
4914
4918
  height: 36,
4915
4919
  radius: 6,
4916
4920
  fieldGap: 16,
4917
- labelGap: 8,
4921
+ labelHeight: "var(--cmp-field-label-md-height)",
4922
+ labelGap: "var(--cmp-field-label-md-gap)",
4918
4923
  labelTypo: "typo-field-md-bold",
4924
+ labelIcon: "var(--cmp-field-label-md-icon)",
4919
4925
  icon: 16
4920
4926
  }
4921
4927
  };
@@ -5042,7 +5048,7 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
5042
5048
  // 라벨과 컨트롤 사이가 간격 토큰보다 넓어진다. 줄 세우기용 labelWidth 도
5043
5049
  // 뜻이 없다(아래에 컨트롤이 제 폭으로 선다).
5044
5050
  ...labelOnTop ? {} : {
5045
- height: cssLen(labelHeight) ?? s.height,
5051
+ height: cssLen(labelHeight) ?? s.labelHeight,
5046
5052
  marginRight: s.fieldGap,
5047
5053
  width: cssLen(labelWidth)
5048
5054
  }
@@ -5052,7 +5058,7 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
5052
5058
  SIcon,
5053
5059
  {
5054
5060
  name: icon,
5055
- size: s.icon,
5061
+ size: s.labelIcon,
5056
5062
  color: iconColor,
5057
5063
  style: { marginRight: s.labelGap }
5058
5064
  }
@@ -5132,7 +5138,7 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
5132
5138
  effectiveAddonLabel !== "" && /* @__PURE__ */ jsxRuntime.jsxs(
5133
5139
  "div",
5134
5140
  {
5135
- className: "flex shrink-0 items-center gap-(--cmp-field-addonLabel-gap) whitespace-nowrap border-r border-solid px-(--cmp-field-addonLabel-paddingX) text-12 font-medium leading-sd-20",
5141
+ className: "flex shrink-0 items-center gap-(--cmp-field-addonLabel-gap) whitespace-nowrap border-r-(length:--cmp-field-addonLabel-border-width) border-solid px-(--cmp-field-addonLabel-paddingX) typo-field-sm-medium",
5136
5142
  style: {
5137
5143
  // 원본 sd-field: labelWidth가 addon 폭(--sd-field-addon-width)에도 적용됨
5138
5144
  width: cssLen(labelWidth),
@@ -5152,7 +5158,7 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
5152
5158
  ]
5153
5159
  }
5154
5160
  ),
5155
- showError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-(--cmp-field-contents-gap) px-(--cmp-field-message-paddingX) text-12 font-normal leading-sd-20 text-(--cmp-field-errorMessage-color)", children: errorMessage }) : hint !== "" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-(--cmp-field-contents-gap) px-(--cmp-field-message-paddingX) text-12 font-normal leading-sd-20 text-(--cmp-field-hint-color)", children: hint }) : null
5161
+ showError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-(--cmp-field-contents-gap) px-(--cmp-field-message-paddingX) typo-field-sm-default text-(--cmp-field-errorMessage-color)", children: errorMessage }) : hint !== "" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-(--cmp-field-contents-gap) px-(--cmp-field-message-paddingX) typo-field-sm-default text-(--cmp-field-hint-color)", children: hint }) : null
5156
5162
  ]
5157
5163
  }
5158
5164
  )
@@ -5479,8 +5485,8 @@ var CHAT_ATTACHED_FILE_CONFIG = {
5479
5485
  contentGap: "gap-(--cmp-chatAttachedFile-content-gap)",
5480
5486
  /** 클립 아이콘이 앉는 칩 — 내부 패딩·면·라운드 (높이는 아이콘+패딩이 정한다) */
5481
5487
  tile: "p-(--cmp-chatAttachedFile-icon-wrapper-padding) rounded-(--cmp-chatAttachedFile-icon-wrapper-radius) bg-(--cmp-chatAttachedFile-icon-wrapper-bg)",
5482
- /** 칩 안 클립 아이콘 크기(px). SVG width/height 는 속성값이라 CSS 변수를 못 받아 값으로 둔다 (토큰 값과 동일) */
5483
- iconSize: 16,
5488
+ /** 칩 안 클립 아이콘 크기 */
5489
+ iconSize: "var(--cmp-chatAttachedFile-icon-size)",
5484
5490
  /** 파일명 타이포 프리셋 */
5485
5491
  nameTypo: "typo-body-sm-default",
5486
5492
  /** 파일명 텍스트색 */
@@ -5558,8 +5564,8 @@ var CHAT_FILE_CONFIG = {
5558
5564
  * 디자인팀에 `icon.wrapper.bg.hover` 를 요청해 나오는 대로 갈아끼운다.
5559
5565
  */
5560
5566
  tile: "p-(--cmp-chatFile-icon-wrapper-padding) rounded-(--cmp-chatFile-icon-wrapper-radius) bg-(--cmp-chatFile-icon-wrapper-bg) group-hover/chat-file:bg-(--sys-color-bg-frame)",
5561
- /** 칩 안 클립 아이콘 크기(px). SVG width/height 는 속성값이라 CSS 변수를 못 받아 값으로 둔다 (토큰 값과 동일) */
5562
- iconSize: 20,
5567
+ /** 칩 안 클립 아이콘 크기 */
5568
+ iconSize: "var(--cmp-chatFile-icon-size)",
5563
5569
  /** 파일명 타이포 프리셋 */
5564
5570
  nameTypo: "typo-body-md-bold",
5565
5571
  /** 파일명·부가정보 텍스트색 */
@@ -5912,7 +5918,7 @@ var SDraggableItemView = /* @__PURE__ */ react.forwardRef(
5912
5918
  paddingYClass,
5913
5919
  // 항목 사이 구분선은 리스트가 그린다.
5914
5920
  bordered && cn(
5915
- "rounded-(--cmp-listDraggableItem-radius-bordered) border border-(--cmp-listDraggableItem-border-default)",
5921
+ "rounded-(--cmp-listDraggableItem-radius-bordered) border-(length:--cmp-listDraggableItem-border-width-default) border-(--cmp-listDraggableItem-border-default)",
5916
5922
  !disabled && !selected && !dragging && cn(
5917
5923
  "hover:border-(--cmp-listDraggableItem-bordered-border-hover)",
5918
5924
  "[[data-drag-active]_&]:hover:border-(--cmp-listDraggableItem-border-default)"
@@ -6784,7 +6790,7 @@ var SExpansionItem = /* @__PURE__ */ react.forwardRef(
6784
6790
  "gap-(--cmp-listExpansionItem-title-gap)",
6785
6791
  // 헤더 액션이 있으면 오른쪽 끝 여백은 액션 칸이 갖고, 버튼은 액션과의 간격만 남긴다
6786
6792
  hasHeaderAction ? "pr-(--cmp-listExpansionItem-title-gap)" : "pr-(--cmp-listExpansionItem-title-paddingX)",
6787
- depth === 2 ? "pl-[36px]" : depth === 3 ? "pl-[56px]" : "pl-[16px]",
6793
+ depth === 2 ? "pl-[36px]" : depth === 3 ? "pl-[56px]" : "pl-(--cmp-listExpansionItem-title-paddingX)",
6788
6794
  isExpanded && "text-(--cmp-listExpansionItem-title-text-expanded)"
6789
6795
  ),
6790
6796
  children: [
@@ -6795,7 +6801,14 @@ var SExpansionItem = /* @__PURE__ */ react.forwardRef(
6795
6801
  "flex transition-transform duration-200 ease-out motion-reduce:transition-none",
6796
6802
  isExpanded && "rotate-180"
6797
6803
  ),
6798
- children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "caretDown", size: 12, color: "var(--sys-color-fg-quaternary)" })
6804
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6805
+ SIcon,
6806
+ {
6807
+ name: "caretDown",
6808
+ size: "var(--cmp-listExpansionItem-title-icon)",
6809
+ color: "var(--sys-color-fg-quaternary)"
6810
+ }
6811
+ )
6799
6812
  }
6800
6813
  ),
6801
6814
  leadingNode,
@@ -6833,10 +6846,9 @@ var SExpansionItem = /* @__PURE__ */ react.forwardRef(
6833
6846
  className: cn(
6834
6847
  "group/expansion-item relative overflow-hidden bg-(--cmp-listExpansionItem-title-bg-default)",
6835
6848
  // 항목 사이 구분선은 리스트가 그린다.
6836
- // 보더 색은 시맨틱 토큰(border-default → hover strong → 펼침 accentLight)을 쓴다.
6837
- // TODO: expansionItem/bordered/radius 토큰 생성 후 rounded 고정값도 토큰으로 교체한다.
6838
- bordered && "rounded-[8px] border border-border-default hover:border-border-strong [&:has(>button:hover)]:border-border-strong",
6839
- bordered && isExpanded && "!border-border-accentLight",
6849
+ // 보더 색: 기본 → hover → 펼침 순으로 listExpansionItem.border 토큰을 쓴다.
6850
+ bordered && "rounded-(--cmp-listExpansionItem-bordered-radius) border border-(--cmp-listExpansionItem-border-default) hover:border-(--cmp-listExpansionItem-border-hover) [&:has(>button:hover)]:border-(--cmp-listExpansionItem-border-hover)",
6851
+ bordered && isExpanded && "!border-(--cmp-listExpansionItem-border-expanded)",
6840
6852
  className
6841
6853
  ),
6842
6854
  ...rest,
@@ -6845,7 +6857,7 @@ var SExpansionItem = /* @__PURE__ */ react.forwardRef(
6845
6857
  "span",
6846
6858
  {
6847
6859
  "aria-hidden": "true",
6848
- className: "pointer-events-none absolute bottom-[-1px] left-0 top-0 z-[1] w-(--cmp-listItem-accentStripe-width) bg-(--cmp-listItem-accentStripe-color)"
6860
+ className: "pointer-events-none absolute bottom-[-1px] left-0 top-0 z-[1] w-(--cmp-listExpansionItem-accentStripe-width) bg-(--cmp-listExpansionItem-accentStripe-color)"
6849
6861
  }
6850
6862
  ),
6851
6863
  hasHeaderAction ? (
@@ -6952,9 +6964,9 @@ var SListItemImpl = /* @__PURE__ */ react.forwardRef(function SListItem({
6952
6964
  dense ? "py-(--cmp-listItem-paddingY-dense)" : "py-(--cmp-listItem-paddingY-normal)",
6953
6965
  "gap-(--cmp-listItem-gap)",
6954
6966
  "pr-(--cmp-listItem-paddingX)",
6955
- depth === 2 ? "pl-[36px]" : depth === 3 ? "pl-[56px]" : "pl-[16px]",
6967
+ depth === 2 ? "pl-[36px]" : depth === 3 ? "pl-[56px]" : "pl-(--cmp-listItem-paddingX)",
6956
6968
  bordered && cn(
6957
- "overflow-hidden rounded-(--cmp-listItem-radius-bordered) border border-(--cmp-listItem-border-default)",
6969
+ "overflow-hidden rounded-(--cmp-listItem-radius-bordered) border-(length:--cmp-listItem-border-width-default) border-(--cmp-listItem-border-default)",
6958
6970
  isSelected ? "border-(--cmp-listItem-bordered-border-selected)" : isInteractive && "hover:border-(--cmp-listItem-bordered-border-hover)"
6959
6971
  ),
6960
6972
  className
@@ -7644,7 +7656,7 @@ function SCheckbox({
7644
7656
  };
7645
7657
  const boxBg = disabled ? "var(--cmp-checkbox-bg-disabled)" : inverse ? "transparent" : isChecked ? "var(--cmp-checkbox-checked-bg-default)" : "var(--cmp-checkbox-unchecked-bg-default)";
7646
7658
  const boxBorder = disabled ? "var(--cmp-checkbox-border-disabled)" : inverse ? "var(--cmp-checkbox-checked-border-inverse)" : isChecked ? "var(--cmp-checkbox-checked-bg-default)" : "var(--cmp-checkbox-unchecked-border-default)";
7647
- const iconColor = disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : "var(--cmp-checkbox-checked-icon-default)";
7659
+ const iconColor = disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : inverse ? "var(--cmp-checkbox-checked-icon-inverse)" : "var(--cmp-checkbox-checked-icon-default)";
7648
7660
  const labelColor = disabled ? "var(--cmp-checkbox-label-disabled)" : inverse ? "var(--cmp-checkbox-label-inverse)" : "var(--cmp-checkbox-label-default)";
7649
7661
  return /* @__PURE__ */ jsxRuntime.jsxs(
7650
7662
  "label",
@@ -7673,7 +7685,7 @@ function SCheckbox({
7673
7685
  SIcon,
7674
7686
  {
7675
7687
  name: state2 === "indeterminate" ? "checkboxIndeterminate" : "checkboxCheck",
7676
- size: 12,
7688
+ size: "var(--cmp-checkbox-icon)",
7677
7689
  color: iconColor
7678
7690
  }
7679
7691
  ) })
@@ -7685,11 +7697,19 @@ function SCheckbox({
7685
7697
  // 찌그러진다 — 띄어쓰기에서만 끊고, 끊을 자리가 없는 긴 토큰만 흘려보낸다
7686
7698
  // (SRadio·SSwitch 라벨과 같은 규칙). 두 사본에 함께 걸려야 하므로 바깥 grid 에 준다.
7687
7699
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "grid break-keep wrap-break-word", style: { color: labelColor }, children: [
7688
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "typo-body-sm-medium invisible", style: { gridArea: "1 / 1" }, children: label }),
7689
7700
  /* @__PURE__ */ jsxRuntime.jsx(
7690
7701
  "span",
7691
7702
  {
7692
- className: isChecked ? "typo-body-sm-medium" : "typo-body-sm-default",
7703
+ "aria-hidden": true,
7704
+ className: "typo-field-sm-medium invisible",
7705
+ style: { gridArea: "1 / 1" },
7706
+ children: label
7707
+ }
7708
+ ),
7709
+ /* @__PURE__ */ jsxRuntime.jsx(
7710
+ "span",
7711
+ {
7712
+ className: isChecked ? "typo-field-sm-medium" : "typo-field-sm-default",
7693
7713
  style: { gridArea: "1 / 1" },
7694
7714
  children: label
7695
7715
  }
@@ -7701,18 +7721,25 @@ function SCheckbox({
7701
7721
  }
7702
7722
  var TREE_LABEL_TYPOGRAPHY = {
7703
7723
  sm: {
7704
- default: "typo-body-sm-medium",
7705
- selected: "typo-body-sm-bold",
7724
+ default: "typo-item-sm-default",
7725
+ selected: "typo-item-sm-selected",
7706
7726
  rowHeight: "h-[28px]"
7707
7727
  },
7708
7728
  md: {
7709
- default: "typo-body-md-medium",
7710
- selected: "typo-body-md-bold",
7729
+ default: "typo-item-md-default",
7730
+ selected: "typo-item-md-selected",
7711
7731
  rowHeight: "h-[32px]"
7712
7732
  }
7713
7733
  };
7734
+ var TREE_BRANCH_MOTION = { duration: 200, easing: "cubic-bezier(0, 0, 0.2, 1)" };
7735
+ function canAnimateTreeBranch() {
7736
+ if (typeof window === "undefined" || typeof HTMLElement.prototype.animate !== "function") {
7737
+ return false;
7738
+ }
7739
+ return !window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
7740
+ }
7714
7741
  var TREE_ROW_CLASS = "group/tree-item box-border flex w-full items-center gap-(--cmp-tree-item-rowGap) overflow-hidden bg-(--cmp-tree-item-bg-default) px-(--cmp-tree-item-paddingX) text-left hover:bg-(--cmp-tree-item-bg-hover)";
7715
- var TREE_ROW_BORDER_CLASS = "border-b border-(--cmp-tree-item-border-default)";
7742
+ var TREE_ROW_BORDER_CLASS = "border-b-(length:--cmp-tree-item-border-width-default) border-(--cmp-tree-item-border-default)";
7716
7743
  var TREE_ROW_ACTIVE_CLASS = "bg-(--cmp-tree-item-bg-hover)";
7717
7744
  var TREE_CONTENT_CLASS = "box-border flex min-w-0 flex-1 items-center gap-(--cmp-tree-item-contentGap)";
7718
7745
  function treeLabelClass(size, {
@@ -7722,12 +7749,49 @@ function treeLabelClass(size, {
7722
7749
  }) {
7723
7750
  const typography = TREE_LABEL_TYPOGRAPHY[size];
7724
7751
  return cn(
7725
- "block min-w-0 flex-1 truncate py-(--cmp-tree-item-paddingY) text-(--cmp-tree-item-text-default)",
7752
+ "block min-w-0 truncate py-(--cmp-tree-item-paddingY) text-(--cmp-tree-item-text-default)",
7726
7753
  emphasized ? typography.selected : typography.default,
7727
7754
  disabled && "opacity-60",
7728
- disabled ? "cursor-not-allowed" : selectable ? "cursor-pointer" : void 0
7755
+ disabled ? "cursor-not-allowed" : selectable ? "cursor-pointer" : void 0,
7756
+ selectable && !disabled && "group-hover/tree-label:underline"
7757
+ );
7758
+ }
7759
+ function TreeSelectZone({
7760
+ selectable,
7761
+ disabled = false,
7762
+ control,
7763
+ children
7764
+ }) {
7765
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7766
+ "span",
7767
+ {
7768
+ "data-tree-label": true,
7769
+ className: cn(
7770
+ "flex min-w-0 items-center gap-(--cmp-tree-item-contentGap)",
7771
+ selectable && (disabled ? "cursor-not-allowed" : "group/tree-label cursor-pointer")
7772
+ ),
7773
+ children: [
7774
+ control,
7775
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-sd-8", children: [
7776
+ children,
7777
+ selectable && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
7778
+ SIcon,
7779
+ {
7780
+ name: "chevronRight",
7781
+ size: 12,
7782
+ color: "var(--sys-color-fg-quaternary)",
7783
+ className: "hidden shrink-0 group-hover/tree-label:inline-flex"
7784
+ }
7785
+ )
7786
+ ] })
7787
+ ]
7788
+ }
7729
7789
  );
7730
7790
  }
7791
+ function isRowSelectClick(event) {
7792
+ const zone = event.target.closest("[data-tree-label]");
7793
+ return zone != null && event.currentTarget.contains(zone);
7794
+ }
7731
7795
  function isRowControlClick(event) {
7732
7796
  const control = event.target.closest("[data-tree-control]");
7733
7797
  return control != null && event.currentTarget.contains(control);
@@ -7961,7 +8025,7 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
7961
8025
  };
7962
8026
  const handleRowClick = (event) => {
7963
8027
  if (isRowControlClick(event)) return;
7964
- if (selectable && event.target.closest("[data-tree-label]")) {
8028
+ if (selectable && isRowSelectClick(event)) {
7965
8029
  handleSelect(event);
7966
8030
  return;
7967
8031
  }
@@ -8002,35 +8066,41 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
8002
8066
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: TREE_CONTENT_CLASS, children: [
8003
8067
  hasChildren ? /* @__PURE__ */ jsxRuntime.jsx(TreeCaret, { expanded, onToggle: (event) => onToggle?.(node, event) }) : /* @__PURE__ */ jsxRuntime.jsx(TreeCaretSpacer, {}),
8004
8068
  leadingNode,
8005
- selectable && /* @__PURE__ */ jsxRuntime.jsx(
8006
- "span",
8069
+ /* @__PURE__ */ jsxRuntime.jsx(
8070
+ TreeSelectZone,
8007
8071
  {
8008
- "data-tree-control": true,
8009
- className: "flex shrink-0",
8010
- "aria-hidden": node.disabled ? "true" : void 0,
8072
+ selectable,
8073
+ disabled: node.disabled,
8074
+ control: selectable && /* @__PURE__ */ jsxRuntime.jsx(
8075
+ "span",
8076
+ {
8077
+ "data-tree-control": true,
8078
+ className: "flex shrink-0",
8079
+ "aria-hidden": node.disabled ? "true" : void 0,
8080
+ children: /* @__PURE__ */ jsxRuntime.jsx(
8081
+ SCheckbox,
8082
+ {
8083
+ value: checkboxValue,
8084
+ disabled: node.disabled,
8085
+ onValueChange: () => handleSelect()
8086
+ }
8087
+ )
8088
+ }
8089
+ ),
8011
8090
  children: /* @__PURE__ */ jsxRuntime.jsx(
8012
- SCheckbox,
8091
+ "span",
8013
8092
  {
8014
- value: checkboxValue,
8015
- disabled: node.disabled,
8016
- onValueChange: () => handleSelect()
8093
+ className: treeLabelClass(size, {
8094
+ emphasized: selected || indeterminate,
8095
+ disabled: Boolean(node.disabled),
8096
+ selectable
8097
+ }),
8098
+ children: node.label
8017
8099
  }
8018
8100
  )
8019
8101
  }
8020
8102
  ),
8021
- /* @__PURE__ */ jsxRuntime.jsx(
8022
- "span",
8023
- {
8024
- "data-tree-label": true,
8025
- className: treeLabelClass(size, {
8026
- emphasized: selected || indeterminate,
8027
- disabled: Boolean(node.disabled),
8028
- selectable
8029
- }),
8030
- children: node.label
8031
- }
8032
- ),
8033
- trailingNode
8103
+ trailingNode != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto flex shrink-0", children: trailingNode })
8034
8104
  ] })
8035
8105
  ]
8036
8106
  }
@@ -8308,7 +8378,7 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
8308
8378
  "span",
8309
8379
  {
8310
8380
  className: cn(
8311
- "min-w-0 truncate text-(--sys-color-fg-brand)",
8381
+ "min-w-0 truncate text-(--cmp-sectionHeaderCard-title-color)",
8312
8382
  titleSizeClass[titleSize]
8313
8383
  ),
8314
8384
  children: title
@@ -8318,7 +8388,7 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
8318
8388
  SIcon,
8319
8389
  {
8320
8390
  name: "asterisk",
8321
- size: 16,
8391
+ size: "var(--cmp-sectionHeaderCard-required-icon)",
8322
8392
  color: "var(--sys-color-fg-accent)",
8323
8393
  className: "shrink-0"
8324
8394
  }
@@ -8335,7 +8405,7 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
8335
8405
  }
8336
8406
  )
8337
8407
  ] }),
8338
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate text-[12px] font-normal leading-[20px] text-(--sys-color-fg-secondary)", children: subtitle }),
8408
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate typo-body-sm-default text-(--cmp-sectionHeaderCard-subtitle-color)", children: subtitle }),
8339
8409
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto flex min-h-sd-6 min-w-0 flex-1 items-center justify-end", children: slot })
8340
8410
  ]
8341
8411
  }
@@ -8371,7 +8441,7 @@ var SSectionHeaderCardRootImpl = /* @__PURE__ */ react.forwardRef(
8371
8441
  {
8372
8442
  ref,
8373
8443
  className: cn(
8374
- "box-border flex w-full flex-col items-stretch overflow-hidden rounded-[8px] border border-(--sys-color-border-default) bg-(--sys-color-bg-frame)",
8444
+ "box-border flex w-full flex-col items-stretch overflow-hidden rounded-(--cmp-sectionHeaderCard-radius) border border-(--cmp-sectionHeaderCard-border) bg-(--cmp-sectionHeaderCard-body-bg)",
8375
8445
  className
8376
8446
  ),
8377
8447
  ...rest,
@@ -8923,18 +8993,25 @@ var SCallout = /* @__PURE__ */ react.forwardRef(function SCallout2({ type = "def
8923
8993
  hasDangerTitle && /* @__PURE__ */ jsxRuntime.jsxs(
8924
8994
  "div",
8925
8995
  {
8926
- className: "flex shrink-0 flex-col items-center justify-center gap-[var(--cmp-callout-danger-title-gap)] px-[var(--cmp-callout-danger-title-paddingX)] py-[8px] text-[16px] font-bold leading-[26px]",
8996
+ className: "typo-heading-md flex shrink-0 flex-col items-center justify-center gap-[var(--cmp-callout-danger-title-gap)] px-[var(--cmp-callout-danger-title-paddingX)] py-[8px]",
8927
8997
  style: {
8928
8998
  background: "var(--cmp-callout-danger-title-bg)",
8929
8999
  color: "var(--cmp-callout-danger-title-color)"
8930
9000
  },
8931
9001
  children: [
8932
- /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "warningFill", size: 24, color: "var(--cmp-callout-danger-title-color)" }),
9002
+ /* @__PURE__ */ jsxRuntime.jsx(
9003
+ SIcon,
9004
+ {
9005
+ name: "warningFill",
9006
+ size: "var(--cmp-callout-danger-title-icon)",
9007
+ color: "var(--cmp-callout-danger-title-color)"
9008
+ }
9009
+ ),
8933
9010
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap", children: DANGER_TITLE_LABEL })
8934
9011
  ]
8935
9012
  }
8936
9013
  ),
8937
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-[var(--cmp-callout-body-gap)] px-[var(--cmp-callout-body-paddingX)] py-[var(--cmp-callout-body-paddingY)] text-[12px] font-normal leading-[20px]", children: children ?? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "m-0 flex list-none flex-col justify-center gap-[var(--cmp-callout-body-gap)] p-0", children: renderItems(message) }) })
9014
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-[var(--cmp-callout-body-gap)] px-[var(--cmp-callout-body-paddingX)] py-[var(--cmp-callout-body-paddingY)] typo-feedback-sm-regular", children: children ?? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "m-0 flex list-none flex-col justify-center gap-[var(--cmp-callout-body-gap)] p-0", children: renderItems(message) }) })
8938
9015
  ]
8939
9016
  }
8940
9017
  );
@@ -9005,7 +9082,7 @@ var SContextAlert = /* @__PURE__ */ react.forwardRef(function SContextAlert2({ i
9005
9082
  className: "shrink-0"
9006
9083
  }
9007
9084
  ),
9008
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 flex-1 flex-col text-[12px] font-normal leading-[20px] text-[color:var(--cmp-contextAlert-content)]", children: messages.map((m, i) => (
9085
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 flex-1 flex-col typo-feedback-sm-regular text-[color:var(--cmp-contextAlert-content)]", children: messages.map((m, i) => (
9009
9086
  // 메시지는 HTML 문자열을 허용하되, sanitizeInlineHtml 로 살균 후 innerHTML 렌더 (XSS 방어)
9010
9087
  /* @__PURE__ */ jsxRuntime.jsx(
9011
9088
  "p",
@@ -9250,20 +9327,20 @@ var loading = {
9250
9327
  };
9251
9328
  var SIZE_CONFIG = {
9252
9329
  sm: {
9253
- gap: 4,
9254
- iconSize: 16,
9330
+ gap: "var(--cmp-textLink-sm-gap)",
9331
+ iconSize: "var(--cmp-textLink-sm-icon)",
9255
9332
  typo: "typo-control-xs-medium",
9256
9333
  underlineTypo: "typo-control-xs-underline"
9257
9334
  },
9258
9335
  md: {
9259
- gap: 8,
9260
- iconSize: 16,
9336
+ gap: "var(--cmp-textLink-md-gap)",
9337
+ iconSize: "var(--cmp-textLink-md-icon)",
9261
9338
  typo: "typo-control-sm-default",
9262
9339
  underlineTypo: "typo-control-sm-underline"
9263
9340
  },
9264
9341
  lg: {
9265
- gap: 8,
9266
- iconSize: 20,
9342
+ gap: "var(--cmp-textLink-lg-gap)",
9343
+ iconSize: "var(--cmp-textLink-lg-icon)",
9267
9344
  typo: "typo-control-md-default",
9268
9345
  underlineTypo: "typo-control-md-underline"
9269
9346
  }
@@ -9325,15 +9402,23 @@ var STextLink = /* @__PURE__ */ react.forwardRef(function STextLink2({
9325
9402
  children: label || children
9326
9403
  }
9327
9404
  ),
9328
- rightArrow !== "none" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex h-[16px] w-[16px] items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
9329
- SIcon,
9405
+ rightArrow !== "none" && // 화살표 칸은 좌측 아이콘과 같은 크기다(textLink.<size>.icon 이 leadingIcon·trailingArrow 공유)
9406
+ /* @__PURE__ */ jsxRuntime.jsx(
9407
+ "span",
9330
9408
  {
9331
- name: rightArrow === "chevron" ? "chevronRight" : "caretRight",
9332
- size: 12,
9333
- color: disabled ? "var(--cmp-textLink-icon-disabled)" : "var(--color-grey-65)",
9334
- rotate: rightArrowRotate
9409
+ className: "inline-flex items-center justify-center",
9410
+ style: { width: s.iconSize, height: s.iconSize },
9411
+ children: /* @__PURE__ */ jsxRuntime.jsx(
9412
+ SIcon,
9413
+ {
9414
+ name: rightArrow === "chevron" ? "chevronRight" : "caretRight",
9415
+ size: 12,
9416
+ color: disabled ? "var(--cmp-textLink-icon-disabled)" : "var(--color-grey-65)",
9417
+ rotate: rightArrowRotate
9418
+ }
9419
+ )
9335
9420
  }
9336
- ) })
9421
+ )
9337
9422
  ]
9338
9423
  }
9339
9424
  );
@@ -9406,24 +9491,38 @@ function DropdownMenuContent({
9406
9491
  ) });
9407
9492
  }
9408
9493
  var SIZE2 = {
9409
- xs: { height: 24, paddingX: 8, gap: 6, arrow: 12, fontSize: 12, minWidth: 64, splitMinWidth: 72 },
9494
+ xs: {
9495
+ height: "var(--cmp-button-xs-height)",
9496
+ paddingX: "var(--cmp-button-xs-paddingX)",
9497
+ gap: "var(--cmp-button-dropdown-xs-gap)",
9498
+ arrow: "var(--cmp-button-dropdown-xs-arrow)",
9499
+ toggleWidth: "var(--cmp-button-iconOnly-xs-width)",
9500
+ fontSize: 12,
9501
+ minWidth: 64,
9502
+ splitMinWidth: 72,
9503
+ radius: "var(--cmp-button-radius-sm)"
9504
+ },
9410
9505
  sm: {
9411
- height: 28,
9412
- paddingX: 12,
9413
- gap: 8,
9414
- arrow: 12,
9506
+ height: "var(--cmp-button-sm-height)",
9507
+ paddingX: "var(--cmp-button-sm-paddingX)",
9508
+ gap: "var(--cmp-button-dropdown-sm-gap)",
9509
+ arrow: "var(--cmp-button-dropdown-sm-arrow)",
9510
+ toggleWidth: "var(--cmp-button-iconOnly-sm-width)",
9415
9511
  fontSize: 12,
9416
9512
  minWidth: 72,
9417
- splitMinWidth: 88
9513
+ splitMinWidth: 88,
9514
+ radius: "var(--cmp-button-radius-sm)"
9418
9515
  },
9419
9516
  md: {
9420
- height: 36,
9421
- paddingX: 20,
9422
- gap: 16,
9423
- arrow: 16,
9517
+ height: "var(--cmp-button-md-height)",
9518
+ paddingX: "var(--cmp-button-md-paddingX)",
9519
+ gap: "var(--cmp-button-dropdown-md-gap)",
9520
+ arrow: "var(--cmp-button-dropdown-md-arrow)",
9521
+ toggleWidth: "var(--cmp-button-iconOnly-md-width)",
9424
9522
  fontSize: 16,
9425
9523
  minWidth: 100,
9426
- splitMinWidth: 106
9524
+ splitMinWidth: 106,
9525
+ radius: "var(--cmp-button-radius-md)"
9427
9526
  }
9428
9527
  };
9429
9528
  function splitDivider(color, outline) {
@@ -9505,7 +9604,7 @@ var SDropdownButtonImpl = /* @__PURE__ */ react.forwardRef(
9505
9604
  );
9506
9605
  const splitIcon = /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "etc", size: s.arrow, color: "var(--dd-icon)" });
9507
9606
  const triggerBase = cn(
9508
- "box-border inline-flex items-center whitespace-nowrap border border-solid outline-none transition-colors",
9607
+ "box-border inline-flex items-center whitespace-nowrap border-[length:var(--cmp-button-border-width-default)] border-solid outline-none transition-colors",
9509
9608
  "border-[color:var(--dd-border)] bg-[var(--dd-bg)] text-[color:var(--dd-text)]",
9510
9609
  disabled ? "cursor-not-allowed" : "cursor-pointer hover:bg-[var(--dd-bg-hover)]"
9511
9610
  );
@@ -9544,10 +9643,12 @@ var SDropdownButtonImpl = /* @__PURE__ */ react.forwardRef(
9544
9643
  type: "button",
9545
9644
  disabled,
9546
9645
  onClick: onLabelClick,
9547
- className: cn(triggerBase, "flex-1 justify-center rounded-l-[4px] border-r-0"),
9646
+ className: cn(triggerBase, "flex-1 justify-center border-r-0"),
9548
9647
  style: {
9648
+ borderTopLeftRadius: s.radius,
9649
+ borderBottomLeftRadius: s.radius,
9549
9650
  minHeight: s.height,
9550
- padding: `0 ${s.paddingX}px`,
9651
+ padding: `0 ${s.paddingX}`,
9551
9652
  fontSize: s.fontSize,
9552
9653
  ...colorVars
9553
9654
  },
@@ -9561,10 +9662,15 @@ var SDropdownButtonImpl = /* @__PURE__ */ react.forwardRef(
9561
9662
  type: "button",
9562
9663
  disabled,
9563
9664
  "aria-label": "\uBA54\uB274 \uC5F4\uAE30",
9564
- className: cn(triggerBase, "justify-center rounded-r-[4px] border-l"),
9665
+ className: cn(
9666
+ triggerBase,
9667
+ "justify-center border-l-[length:var(--cmp-button-border-width-default)]"
9668
+ ),
9565
9669
  style: {
9670
+ borderTopRightRadius: s.radius,
9671
+ borderBottomRightRadius: s.radius,
9566
9672
  minHeight: s.height,
9567
- minWidth: s.height,
9673
+ minWidth: s.toggleWidth,
9568
9674
  borderLeftColor: disabled ? "var(--cmp-button-border-disabled)" : splitDivider(color, outline),
9569
9675
  ...colorVars
9570
9676
  },
@@ -9578,11 +9684,12 @@ var SDropdownButtonImpl = /* @__PURE__ */ react.forwardRef(
9578
9684
  {
9579
9685
  type: "button",
9580
9686
  disabled,
9581
- className: cn(triggerBase, "justify-between rounded-[4px]", className),
9687
+ className: cn(triggerBase, "justify-between rounded-(--dd-radius)", className),
9582
9688
  style: {
9689
+ ...{ "--dd-radius": s.radius },
9583
9690
  minWidth: s.minWidth,
9584
9691
  minHeight: s.height,
9585
- padding: `0 ${s.paddingX}px`,
9692
+ padding: `0 ${s.paddingX}`,
9586
9693
  gap: s.gap,
9587
9694
  fontSize: s.fontSize,
9588
9695
  ...colorVars,
@@ -9692,13 +9799,13 @@ function SSwitch({
9692
9799
  style
9693
9800
  }) {
9694
9801
  const right = rightLabel;
9695
- const renderLabel = (text) => text ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-body-sm-medium break-keep wrap-break-word", children: text }) : null;
9802
+ const renderLabel = (text) => text ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-field-sm-medium break-keep wrap-break-word", children: text }) : null;
9696
9803
  const trackBg = disabled ? value ? "var(--cmp-switch-bg-disabled-on)" : "var(--cmp-switch-bg-disabled-off)" : value ? "var(--cmp-switch-bg-on)" : "var(--cmp-switch-bg-off)";
9697
9804
  return /* @__PURE__ */ jsxRuntime.jsxs(
9698
9805
  "label",
9699
9806
  {
9700
9807
  className: cn(
9701
- "inline-flex items-center gap-[6px]",
9808
+ "inline-flex items-center gap-(--cmp-switch-gap)",
9702
9809
  disabled ? "cursor-not-allowed" : "cursor-pointer",
9703
9810
  className
9704
9811
  ),
@@ -9712,14 +9819,14 @@ function SSwitch({
9712
9819
  disabled,
9713
9820
  onCheckedChange: (v) => onValueChange?.(v),
9714
9821
  className: cn(
9715
- "relative h-[20px] w-[32px] flex-shrink-0 rounded-full p-[2px] outline-none transition-colors duration-200",
9822
+ "relative h-(--cmp-switch-height) w-(--cmp-switch-width) flex-shrink-0 rounded-(--cmp-switch-radius) p-(--cmp-switch-paddingXY) outline-none transition-colors duration-200",
9716
9823
  disabled ? "cursor-not-allowed" : "cursor-pointer"
9717
9824
  ),
9718
9825
  style: { background: trackBg },
9719
9826
  children: /* @__PURE__ */ jsxRuntime.jsx(
9720
9827
  RSwitch__namespace.Thumb,
9721
9828
  {
9722
- className: "block h-[16px] w-[16px] rounded-full shadow-[0_2px_4px_rgba(0,0,0,0.16)] transition-transform duration-200 data-[state=checked]:translate-x-[12px]",
9829
+ className: "block h-(--cmp-switch-knob-size) w-(--cmp-switch-knob-size) rounded-full shadow-[0_2px_4px_rgba(0,0,0,0.16)] transition-transform duration-200 data-[state=checked]:translate-x-[calc(var(--cmp-switch-width)_-_var(--cmp-switch-knob-size)_-_var(--cmp-switch-paddingXY)_*_2)]",
9723
9830
  style: {
9724
9831
  background: disabled ? "var(--cmp-switch-knob-disabled)" : "var(--cmp-switch-knob-default)"
9725
9832
  }
@@ -10447,8 +10554,8 @@ var SSystemActionButton = /* @__PURE__ */ react.forwardRef(
10447
10554
  }
10448
10555
  );
10449
10556
  var SIZE_CLASSES = {
10450
- xs: "h-[24px] px-[8px] text-[12px] font-normal leading-[20px]",
10451
- sm: "h-[28px] px-[12px] text-[14px] font-medium leading-[24px]"
10557
+ xs: "h-(--cmp-toggle-xs-height) px-(--cmp-toggle-xs-paddingX) typo-control-xs-default",
10558
+ sm: "h-(--cmp-toggle-sm-height) px-(--cmp-toggle-sm-paddingX) typo-control-sm-default"
10452
10559
  };
10453
10560
  function SToggle({
10454
10561
  value = false,
@@ -10470,7 +10577,7 @@ function SToggle({
10470
10577
  "aria-pressed": value,
10471
10578
  onClick: () => !disabled && onValueChange?.(!value),
10472
10579
  className: cn(
10473
- "box-border inline-flex items-center justify-center whitespace-nowrap rounded-full border border-solid transition-colors",
10580
+ "box-border inline-flex items-center justify-center whitespace-nowrap rounded-(--cmp-toggle-radius) border-(length:--cmp-toggle-border-width) border-solid transition-colors",
10474
10581
  SIZE_CLASSES[size],
10475
10582
  disabled ? "cursor-not-allowed" : "cursor-pointer",
10476
10583
  // 미선택(off) hover 시 파란 채움 + 흰 글자
@@ -10556,10 +10663,17 @@ function SPopover({
10556
10663
  menuTitle && /* @__PURE__ */ jsxRuntime.jsxs(
10557
10664
  "div",
10558
10665
  {
10559
- className: "flex items-center gap-[var(--cmp-popover-title-gap)] text-[14px] font-bold leading-[24px]",
10666
+ className: "typo-feedback-md-bold flex items-center gap-[var(--cmp-popover-title-gap)]",
10560
10667
  style: { color: titleColor },
10561
10668
  children: [
10562
- titleIcon && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: titleIcon, size: 16, color: titleColor }),
10669
+ titleIcon && /* @__PURE__ */ jsxRuntime.jsx(
10670
+ SIcon,
10671
+ {
10672
+ name: titleIcon,
10673
+ size: "var(--cmp-popover-title-leadingIcon)",
10674
+ color: titleColor
10675
+ }
10676
+ ),
10563
10677
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0", children: menuTitle })
10564
10678
  ]
10565
10679
  }
@@ -10696,14 +10810,14 @@ function SGuide({
10696
10810
  }
10697
10811
  setOpen((o) => !o);
10698
10812
  },
10699
- className: "inline-flex h-[var(--cmp-guide-button-height)] cursor-pointer items-center gap-[var(--cmp-guide-button-gap)] whitespace-nowrap rounded-[var(--cmp-guide-button-radius)] border-[length:var(--cmp-guide-button-border-width)] border-solid px-[var(--cmp-guide-button-paddingX)] text-[12px] font-medium leading-[20px] transition-colors",
10813
+ className: "inline-flex h-[var(--cmp-guide-button-height)] cursor-pointer items-center gap-[var(--cmp-guide-button-gap)] whitespace-nowrap rounded-[var(--cmp-guide-button-radius)] border-[length:var(--cmp-guide-button-border-width)] border-solid px-[var(--cmp-guide-button-paddingX)] typo-control-xs-medium transition-colors",
10700
10814
  style: {
10701
10815
  borderColor: active ? activeBg : "var(--cmp-guide-button-border-default)",
10702
10816
  background: active ? activeBg : "var(--cmp-guide-button-bg-default)",
10703
10817
  color: active ? "var(--cmp-guide-button-text-active)" : "var(--cmp-guide-button-text-default)"
10704
10818
  },
10705
10819
  children: [
10706
- /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: iconName, size: 16, color: iconColor }),
10820
+ /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: iconName, size: "var(--cmp-guide-button-icon-size)", color: iconColor }),
10707
10821
  label || defaultLabel
10708
10822
  ]
10709
10823
  }
@@ -10753,11 +10867,11 @@ function SGuide({
10753
10867
  color: isNotion ? "var(--sys-color-fg-primary)" : "var(--cmp-guide-contents-icon)"
10754
10868
  }
10755
10869
  ),
10756
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "m-0 break-keep text-[16px] font-bold leading-[26px] text-[color:var(--cmp-guide-contents-typography-color)]", children: popupTitle || defaultLabel })
10870
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "typo-heading-md m-0 break-keep text-[color:var(--cmp-guide-contents-typography-color)]", children: popupTitle || defaultLabel })
10757
10871
  ]
10758
10872
  }
10759
10873
  ),
10760
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "m-0 mt-[var(--cmp-guide-contents-gap)] flex w-full list-none flex-col gap-[var(--cmp-guide-contents-body-gap)] p-0 text-[12px] leading-[20px] text-[color:var(--cmp-guide-contents-typography-color)]", children: messages.map((m, i) => /* @__PURE__ */ jsxRuntime.jsx(
10874
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "m-0 mt-[var(--cmp-guide-contents-gap)] flex w-full list-none flex-col gap-[var(--cmp-guide-contents-body-gap)] p-0 typo-field-sm-default text-[color:var(--cmp-guide-contents-typography-color)]", children: messages.map((m, i) => /* @__PURE__ */ jsxRuntime.jsx(
10761
10875
  "li",
10762
10876
  {
10763
10877
  className: cn(
@@ -11028,15 +11142,22 @@ function SConfirmModal({
11028
11142
  showClose: true,
11029
11143
  onClose: () => settle(onClose),
11030
11144
  className: "w-fit min-w-[min(520px,calc(100dvw-48px))]",
11031
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-auto flex-col items-center gap-[40px] px-[32px] py-[40px]", children: [
11032
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full min-h-0 flex-col items-center gap-[20px] overflow-y-auto", children: [
11033
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-[12px]", children: [
11034
- iconName && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: iconName, size: 32, color: TYPE_ICON_COLOR[type] }),
11145
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-auto flex-col items-center gap-(--cmp-modal-confirm-gap) px-(--cmp-modal-confirm-paddingX) py-(--cmp-modal-confirm-paddingY)", children: [
11146
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full min-h-0 flex-col items-center gap-(--cmp-modal-confirm-body-gap) overflow-y-auto", children: [
11147
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-(--cmp-modal-confirm-title-gap)", children: [
11148
+ iconName && /* @__PURE__ */ jsxRuntime.jsx(
11149
+ SIcon,
11150
+ {
11151
+ name: iconName,
11152
+ size: "var(--cmp-modal-confirm-title-icon)",
11153
+ color: TYPE_ICON_COLOR[type]
11154
+ }
11155
+ ),
11035
11156
  /* @__PURE__ */ jsxRuntime.jsx(
11036
11157
  "h2",
11037
11158
  {
11038
11159
  className: cn(
11039
- "text-center text-[18px] font-bold leading-[30px] text-[color:var(--cmp-modal-confirm-title-color)]",
11160
+ "typo-heading-lg text-center text-[color:var(--cmp-modal-confirm-title-color)]",
11040
11161
  titleClassName
11041
11162
  ),
11042
11163
  children: modalTitle
@@ -11125,7 +11246,7 @@ function SOverlayHeader({
11125
11246
  {
11126
11247
  className: cn(
11127
11248
  "m-0 overflow-hidden text-ellipsis whitespace-nowrap",
11128
- "text-[16px] font-bold leading-[26px]",
11249
+ "typo-heading-md",
11129
11250
  titleClassName
11130
11251
  ),
11131
11252
  style: { color: "var(--cmp-overlay-header-title-color)" },
@@ -11220,8 +11341,8 @@ function SLoadingModal({
11220
11341
  showButton = false,
11221
11342
  buttonLabel,
11222
11343
  onButtonClick,
11223
- width = 520,
11224
- height = 320
11344
+ width = "var(--cmp-modal-loading-width)",
11345
+ height = "var(--cmp-modal-loading-height)"
11225
11346
  }) {
11226
11347
  const resolvedMessage = message ?? DEFAULT_MESSAGE[state2];
11227
11348
  const lines = Array.isArray(resolvedMessage) ? resolvedMessage : resolvedMessage ? [resolvedMessage] : [];
@@ -11237,8 +11358,15 @@ function SLoadingModal({
11237
11358
  ariaTitle: lines[0] || "\uB85C\uB529 \uC911",
11238
11359
  width,
11239
11360
  height,
11240
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-0 flex-auto flex-col overflow-y-auto px-[32px]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "m-auto flex flex-col items-center gap-[20px]", children: [
11241
- state2 === "loading" ? progress !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(SCircleProgress, { value: progress }) : /* @__PURE__ */ jsxRuntime.jsx(SCircleProgress, { indeterminate: true }) : /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "warningOutline", size: 80, color: "var(--cmp-modal-confirm-negative-icon)" }),
11361
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-0 flex-auto flex-col overflow-y-auto px-[32px]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "m-auto flex flex-col items-center gap-(--cmp-modal-loading-gap)", children: [
11362
+ state2 === "loading" ? progress !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(SCircleProgress, { value: progress }) : /* @__PURE__ */ jsxRuntime.jsx(SCircleProgress, { indeterminate: true }) : /* @__PURE__ */ jsxRuntime.jsx(
11363
+ SIcon,
11364
+ {
11365
+ name: "warningOutline",
11366
+ size: "var(--cmp-modal-loading-content)",
11367
+ color: "var(--cmp-modal-confirm-negative-icon)"
11368
+ }
11369
+ ),
11242
11370
  lines.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-[2px]", children: lines.map((m, i) => /* @__PURE__ */ jsxRuntime.jsx(
11243
11371
  "p",
11244
11372
  {
@@ -12026,13 +12154,8 @@ var LAUNCHER_LIST_BOX_LAYOUT = {
12026
12154
  radius: gnb("launcher-listBox-radius"),
12027
12155
  /** 패널 상하좌우 여백 */
12028
12156
  padding: gnb("launcher-listBox-paddingAll"),
12029
- /**
12030
- * 패널 그림자.
12031
- * 토큰(`component.gnb.launcher.listBox.shadow` = `{shadow.floating}`)은 값이 배열이라
12032
- * `--cmp-*` 로 나오지 않는다 — 생성기가 스칼라만 내보내기 때문이다. 그래서 그 별칭이
12033
- * 가리키는 스케일 토큰을 직접 쓴다(같은 값이다).
12034
- */
12035
- shadow: "var(--shadow-floating)",
12157
+ /** 패널 그림자 */
12158
+ shadow: gnb("launcher-listBox-shadow"),
12036
12159
  /** 줄 왼쪽 여백 */
12037
12160
  itemPaddingLeft: gnb("launcher-button-paddingLeft"),
12038
12161
  /** 줄 오른쪽 여백 — 왼쪽보다 좁다(오른쪽 끝은 hover 아이콘 자리다) */
@@ -12403,20 +12526,19 @@ var GNB_MENU = {
12403
12526
  depth3PaddingLeft: box2("item-depth3-paddingLeft"),
12404
12527
  depth1Icon: box2("item-depth1-icon"),
12405
12528
  // box 는 depth1 전용 타이포 토큰이 없어 depth1 도 selected 타이포를 따른다
12529
+ depth1Typo: "typo-navigation-lg-semibold",
12530
+ // token: gnb.box.item.typography.selected
12531
+ itemTypo: "typo-navigation-lg-medium",
12532
+ // token: gnb.box.item.typography.default
12533
+ itemTypoSelected: "typo-navigation-lg-semibold",
12534
+ // token: gnb.box.item.typography.selected
12406
12535
  depth1FontSize: 14,
12407
- // token: gnb.box.item.typography.selected.fontSize
12408
12536
  depth1LineHeight: 24,
12409
- // token: gnb.box.item.typography.selected.lineHeight
12410
12537
  depth1FontWeight: 600,
12411
- // token: gnb.box.item.typography.selected.fontWeight
12412
12538
  itemFontSize: 14,
12413
- // token: gnb.box.item.typography.default.fontSize
12414
12539
  itemLineHeight: 24,
12415
- // token: gnb.box.item.typography.default.lineHeight
12416
12540
  itemFontWeight: 500,
12417
- // token: gnb.box.item.typography.default.fontWeight
12418
12541
  itemFontWeightSelected: 600
12419
- // token: gnb.box.item.typography.selected.fontWeight
12420
12542
  },
12421
12543
  belt: {
12422
12544
  bodyPaddingY: gnb2("body-padding"),
@@ -12433,20 +12555,19 @@ var GNB_MENU = {
12433
12555
  depth3PaddingLeft: belt("item-depth3-paddingLeft"),
12434
12556
  depth1Icon: belt("item-depth1-icon"),
12435
12557
  // belt 전용 depth1 아이콘 토큰(16)
12558
+ depth1Typo: "typo-navigation-md-bold",
12559
+ // token: gnb.belt.item.depth1.typography
12560
+ itemTypo: "typo-navigation-sm-medium",
12561
+ // token: gnb.belt.item.typography.default
12562
+ itemTypoSelected: "typo-navigation-sm-bold",
12563
+ // token: gnb.belt.item.typography.selected
12436
12564
  depth1FontSize: 13,
12437
- // token: gnb.belt.item.depth1.typography.fontSize
12438
12565
  depth1LineHeight: 22,
12439
- // token: gnb.belt.item.depth1.typography.lineHeight
12440
12566
  depth1FontWeight: 700,
12441
- // token: gnb.belt.item.depth1.typography.fontWeight
12442
12567
  itemFontSize: 12,
12443
- // token: gnb.belt.item.typography.default.fontSize
12444
12568
  itemLineHeight: 20,
12445
- // token: gnb.belt.item.typography.default.lineHeight
12446
12569
  itemFontWeight: 500,
12447
- // token: gnb.belt.item.typography.default.fontWeight
12448
12570
  itemFontWeightSelected: 700
12449
- // token: gnb.belt.item.typography.selected.fontWeight
12450
12571
  }
12451
12572
  };
12452
12573
  var GNB_COLORS = {
@@ -12491,15 +12612,16 @@ var GNB_RAIL = {
12491
12612
  itemPaddingBottom: gnb2("rail-item-paddingBottom"),
12492
12613
  itemRadius: gnb2("rail-item-radius"),
12493
12614
  itemIcon: gnb2("rail-item-icon"),
12494
- // 타이포 (theme.css 에 gnb 타이포 변수 없음 → 토큰 값 직접 명시)
12615
+ // 타이포 — 토큰이 가리키는 typo-* 클래스
12616
+ itemTypo: "typo-navigation-xs-medium",
12617
+ // token: gnb.rail.item.typography.default
12618
+ itemTypoSelected: "typo-navigation-xs-bold",
12619
+ // token: gnb.rail.item.typography.selected
12620
+ // 아래 숫자는 공개 export 라 남겨 둔 같은 값이다 — 렌더에는 쓰지 않는다
12495
12621
  itemFontSize: 11,
12496
- // token: gnb.rail.item.typography.default.fontSize
12497
12622
  itemLineHeight: 18,
12498
- // token: gnb.rail.item.typography.default.lineHeight
12499
12623
  itemFontWeight: 500,
12500
- // token: gnb.rail.item.typography.default.fontWeight
12501
12624
  itemFontWeightSelected: 700
12502
- // token: gnb.rail.item.typography.selected.fontWeight
12503
12625
  };
12504
12626
  var GNB_RAIL_WIDTH = 68;
12505
12627
  var GNB_FOLD_MS = 200;
@@ -12733,7 +12855,10 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
12733
12855
  type: "button",
12734
12856
  disabled: item4.disabled,
12735
12857
  "aria-current": isActive ? "true" : void 0,
12736
- className: "box-border flex select-none flex-col items-center border-none bg-transparent transition-colors duration-150",
12858
+ className: cn(
12859
+ "box-border flex select-none flex-col items-center border-none bg-transparent transition-colors duration-150",
12860
+ isActive ? GNB_RAIL.itemTypoSelected : GNB_RAIL.itemTypo
12861
+ ),
12737
12862
  style: {
12738
12863
  width: GNB_RAIL.itemWidth,
12739
12864
  paddingTop: GNB_RAIL.itemPaddingTop,
@@ -12743,9 +12868,6 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
12743
12868
  color: isActive ? C.itemColorActive : C.railFgDefault,
12744
12869
  // <button> 의 UA 폰트를 끊고 앱 폰트를 잇는다 (메뉴 아이템과 같은 이유)
12745
12870
  fontFamily: "inherit",
12746
- fontSize: GNB_RAIL.itemFontSize,
12747
- lineHeight: `${GNB_RAIL.itemLineHeight}px`,
12748
- fontWeight: isActive ? GNB_RAIL.itemFontWeightSelected : GNB_RAIL.itemFontWeight,
12749
12871
  opacity: item4.disabled ? 0.4 : 1,
12750
12872
  cursor: item4.disabled ? "not-allowed" : "pointer"
12751
12873
  },
@@ -12784,9 +12906,6 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
12784
12906
  color: isSelected ? C.itemColorActive : isHovered ? C.itemColorHover : C.itemColorDefault,
12785
12907
  // <button> 의 UA 폰트(Arial 13.3px)를 끊고 앱 폰트를 잇는다
12786
12908
  fontFamily: "inherit",
12787
- fontSize: depth === 1 ? M.depth1FontSize : M.itemFontSize,
12788
- lineHeight: `${depth === 1 ? M.depth1LineHeight : M.itemLineHeight}px`,
12789
- fontWeight: depth === 1 ? M.depth1FontWeight : isSelected ? M.itemFontWeightSelected : M.itemFontWeight,
12790
12909
  opacity: item4.disabled ? 0.4 : 1,
12791
12910
  cursor: item4.disabled ? "not-allowed" : "pointer"
12792
12911
  };
@@ -12801,7 +12920,10 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
12801
12920
  disabled: item4.disabled,
12802
12921
  "aria-expanded": hasChildren ? isExpanded : void 0,
12803
12922
  "aria-current": isSelected ? "page" : void 0,
12804
- className: "box-border flex select-none items-center border-none bg-transparent text-left transition-colors duration-150",
12923
+ className: cn(
12924
+ "box-border flex select-none items-center border-none bg-transparent text-left transition-colors duration-150",
12925
+ depth === 1 ? M.depth1Typo : isSelected ? M.itemTypoSelected : M.itemTypo
12926
+ ),
12805
12927
  style: itemStyle,
12806
12928
  onClick: () => handleItemClick(item4),
12807
12929
  ...rowHoverProps(item4),
@@ -13987,8 +14109,10 @@ var SPageHeader = /* @__PURE__ */ withDisplayName(
13987
14109
  );
13988
14110
 
13989
14111
  // src/components/STabs/tabs.config.ts
13990
- var TAB_MAIN_SIZE = { height: 36, paddingX: 24 };
13991
- var TAB_TYPOGRAPHY = { fontSize: 12, lineHeight: 20 };
14112
+ var TAB_MAIN_SIZE = {
14113
+ height: "var(--cmp-tab-main-height)",
14114
+ paddingX: "var(--cmp-tab-main-paddingX)"
14115
+ };
13992
14116
  var TAB_MAIN_COLORS = {
13993
14117
  selected: {
13994
14118
  bg: "var(--cmp-tab-main-selected-bg)",
@@ -14033,7 +14157,7 @@ function STabs({
14033
14157
  // main(가로): baseline(하단 divider)이 100% 너비로 채워지도록 w-full
14034
14158
  sub ? "inline-flex w-fit" : "flex w-full",
14035
14159
  isVertical ? "flex-col items-stretch" : "flex-row",
14036
- sub ? isVertical ? "gap-[16px]" : "gap-[24px]" : "gap-[4px]",
14160
+ sub ? isVertical ? "gap-(--cmp-tab-sub-gap-vertical)" : "gap-(--cmp-tab-sub-gap-horizontal)" : "gap-(--cmp-tab-main-container-gap)",
14037
14161
  className
14038
14162
  ),
14039
14163
  style: containerStyle,
@@ -14043,30 +14167,26 @@ function STabs({
14043
14167
  let tabStyle;
14044
14168
  if (sub) {
14045
14169
  tabStyle = {
14046
- height: 20,
14047
- paddingBottom: 4,
14048
- fontSize: TAB_TYPOGRAPHY.fontSize,
14049
- lineHeight: `${TAB_TYPOGRAPHY.lineHeight}px`,
14170
+ height: "var(--cmp-tab-sub-item-height)",
14171
+ paddingBottom: "var(--cmp-tab-sub-content-gap)",
14050
14172
  color: selected ? TAB_SUB_COLORS.selected.text : TAB_SUB_COLORS.default.text,
14051
- borderBottom: `1px solid ${selected ? TAB_SUB_COLORS.selected.line : "transparent"}`
14173
+ borderBottom: `var(--cmp-tab-sub-border-width) solid ${selected ? TAB_SUB_COLORS.selected.line : "transparent"}`
14052
14174
  };
14053
14175
  } else {
14054
14176
  const border = selected ? TAB_MAIN_COLORS.selected.border : TAB_MAIN_COLORS.default.border;
14055
14177
  const selectedBg = TAB_MAIN_COLORS.selected.bg;
14056
14178
  tabStyle = {
14057
14179
  height: TAB_MAIN_SIZE.height,
14058
- padding: `0 ${TAB_MAIN_SIZE.paddingX}px`,
14059
- fontSize: TAB_TYPOGRAPHY.fontSize,
14060
- lineHeight: `${TAB_TYPOGRAPHY.lineHeight}px`,
14180
+ padding: `0 ${TAB_MAIN_SIZE.paddingX}`,
14061
14181
  background: selected ? TAB_MAIN_COLORS.selected.bg : TAB_MAIN_COLORS.default.bg,
14062
14182
  color: selected ? TAB_MAIN_COLORS.selected.text : TAB_MAIN_COLORS.default.text,
14063
- border: `1px solid ${border}`,
14183
+ border: `var(--cmp-tab-main-border-width) solid ${border}`,
14064
14184
  // 폴더형: 미선택 탭은 baseline 위에, 선택 탭은 baseline(파란선)을 1px 덮어 연결된 것처럼 보이게
14065
- borderTopLeftRadius: 6,
14066
- borderTopRightRadius: 6,
14185
+ borderTopLeftRadius: "var(--cmp-tab-main-radius)",
14186
+ borderTopRightRadius: "var(--cmp-tab-main-radius)",
14067
14187
  borderBottomLeftRadius: 0,
14068
14188
  borderBottomRightRadius: 0,
14069
- borderBottom: selected ? `1px solid ${selectedBg}` : "none",
14189
+ borderBottom: selected ? `var(--cmp-tab-main-border-width) solid ${selectedBg}` : "none",
14070
14190
  marginBottom: selected ? -1 : 0
14071
14191
  };
14072
14192
  }
@@ -14103,12 +14223,17 @@ function STabs({
14103
14223
  moveTo(tabs.length - 1);
14104
14224
  }
14105
14225
  },
14106
- className: "relative box-border inline-flex cursor-pointer select-none items-center justify-center gap-[8px] whitespace-nowrap outline-none transition-[color,background-color] duration-200",
14226
+ className: cn(
14227
+ "relative box-border inline-flex cursor-pointer select-none items-center justify-center whitespace-nowrap outline-none transition-[color,background-color] duration-200",
14228
+ sub ? "gap-[8px]" : "gap-(--cmp-tab-main-gap)",
14229
+ // 타이포 (token: tab.<main|sub>.<selected|default>.typography)
14230
+ selected ? "typo-navigation-sm-bold" : "typo-navigation-sm-default"
14231
+ ),
14107
14232
  style: tabStyle,
14108
14233
  children: [
14109
14234
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "grid", children: [
14110
14235
  /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "invisible font-bold", style: { gridArea: "1 / 1" }, children: tab.label }),
14111
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { gridArea: "1 / 1", fontWeight: selected ? 700 : 400 }, children: tab.label })
14236
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { gridArea: "1 / 1" }, children: tab.label })
14112
14237
  ] }),
14113
14238
  tab.badge !== void 0 && tab.badge !== null && tab.badge !== "" && /* @__PURE__ */ jsxRuntime.jsx(
14114
14239
  STag,
@@ -14159,7 +14284,7 @@ function SPagination({
14159
14284
  "aria-label": aria,
14160
14285
  onClick,
14161
14286
  className: "flex h-[var(--cmp-pagination-height)] w-[var(--cmp-pagination-height)] cursor-pointer items-center justify-center rounded-[var(--cmp-pagination-radius)] border-none bg-transparent hover:bg-[var(--cmp-pagination-item-bg-hover)]",
14162
- children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: 12, color: "var(--color-grey-65)" })
14287
+ children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: "var(--cmp-pagination-icon)", color: "var(--color-grey-65)" })
14163
14288
  }
14164
14289
  );
14165
14290
  const prevButtons = simple ? currentPage > 1 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -14183,8 +14308,8 @@ function SPagination({
14183
14308
  style,
14184
14309
  children: [
14185
14310
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-[calc(var(--cmp-pagination-height)*2+var(--cmp-pagination-move-gap))] items-center justify-end gap-[var(--cmp-pagination-move-gap)]", children: prevButtons }),
14186
- simple ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-[var(--cmp-pagination-height)] items-center gap-[var(--cmp-pagination-simple-gap)] px-[var(--cmp-pagination-paddingX)] text-[12px] font-medium leading-[20px] text-[color:var(--cmp-pagination-item-content-default)]", children: [
14187
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-[color:var(--cmp-pagination-item-content-selected)]", children: currentPage }),
14311
+ simple ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-[var(--cmp-pagination-height)] items-center gap-[var(--cmp-pagination-simple-gap)] px-[var(--cmp-pagination-paddingX)] typo-control-xs-medium text-[color:var(--cmp-pagination-item-content-default)]", children: [
14312
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-control-xs-bold text-[color:var(--cmp-pagination-item-content-selected)]", children: currentPage }),
14188
14313
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "/" }),
14189
14314
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: lastPage })
14190
14315
  ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-[var(--cmp-pagination-move-gap)]", children: pageNumbers.map((n) => {
@@ -14196,8 +14321,8 @@ function SPagination({
14196
14321
  "aria-current": selected ? "page" : void 0,
14197
14322
  onClick: () => go(n),
14198
14323
  className: cn(
14199
- "box-border flex h-[var(--cmp-pagination-height)] cursor-pointer items-center justify-center rounded-[var(--cmp-pagination-radius)] border-none px-[var(--cmp-pagination-paddingX)] text-[12px] leading-[20px]",
14200
- selected ? "bg-[var(--cmp-pagination-item-bg-selected)] font-bold text-[color:var(--cmp-pagination-item-content-selected)]" : "bg-transparent font-medium text-[color:var(--cmp-pagination-item-content-default)] hover:bg-[var(--cmp-pagination-item-bg-hover)] hover:text-[color:var(--cmp-pagination-item-content-hover)]"
14324
+ "box-border flex h-[var(--cmp-pagination-height)] cursor-pointer items-center justify-center rounded-[var(--cmp-pagination-radius)] border-none px-[var(--cmp-pagination-paddingX)]",
14325
+ selected ? "bg-[var(--cmp-pagination-item-bg-selected)] typo-control-xs-bold text-[color:var(--cmp-pagination-item-content-selected)]" : "bg-transparent typo-control-xs-medium text-[color:var(--cmp-pagination-item-content-default)] hover:bg-[var(--cmp-pagination-item-bg-hover)] hover:text-[color:var(--cmp-pagination-item-content-hover)]"
14201
14326
  ),
14202
14327
  style: { width: itemWidth },
14203
14328
  children: n
@@ -14220,15 +14345,18 @@ var STEPPER_SIZE_CONFIG = {
14220
14345
  sequenceSize: V2("sm-sequence-size"),
14221
14346
  fontSize: "12px",
14222
14347
  lineHeight: "20px",
14223
- fontWeightActive: 700,
14224
- fontWeightDefault: 500
14348
+ typoDefault: "typo-navigation-sm-medium",
14349
+ typoActive: "typo-navigation-sm-bold",
14350
+ fontWeightActive: 700
14225
14351
  },
14226
14352
  lg: {
14227
14353
  sequenceSize: V2("lg-sequence-size"),
14228
14354
  fontSize: "14px",
14229
14355
  lineHeight: "24px",
14230
- fontWeightActive: 700,
14231
- fontWeightDefault: 500
14356
+ typoDefault: "typo-navigation-lg-medium",
14357
+ // 토큰(navigation.lg.semibold)은 600 인데 지금 700 으로 그린다 — 값이 달라 토큰을 쓰지 않는다
14358
+ typoActive: null,
14359
+ fontWeightActive: 700
14232
14360
  }
14233
14361
  };
14234
14362
  var STEPPER_LAYOUT = {
@@ -14254,7 +14382,9 @@ var STEPPER_COLORS = {
14254
14382
  sequenceText: {
14255
14383
  active: V2("sequence-text-active"),
14256
14384
  default: V2("sequence-text-default"),
14257
- completed: VF("sequence-text-completed", "#0075FF")
14385
+ // 완료 시퀀스의 체크 아이콘 색은 전용 토큰이 없다(stepper.sequence.text 에 completed 가 없음).
14386
+ // 진행 중 시퀀스 숫자와 같은 accent 색을 시맨틱 토큰으로 직접 쓴다.
14387
+ completed: "var(--sys-color-fg-accent)"
14258
14388
  },
14259
14389
  text: {
14260
14390
  active: V2("text-active"),
@@ -14269,14 +14399,15 @@ var STEPPER_HORIZONTAL_COMPLETED_COLORS = {
14269
14399
  text: STEPPER_COLORS.text.completed
14270
14400
  };
14271
14401
  var STEPPER_VERTICAL_LAYOUT = {
14272
- width: VF("vertical-width", "240px"),
14402
+ /** 세로형 폭. 대응 토큰이 없어 디자인 값을 그대로 쓴다(stepper.vertical 에 width 가 없음). */
14403
+ width: "240px",
14273
14404
  itemGap: VF("vertical-item-gap", "12px"),
14274
14405
  itemPaddingX: VF("vertical-item-paddingX", "16px"),
14275
14406
  itemPaddingY: VF("vertical-item-paddingY", "8px"),
14276
14407
  titlePaddingTop: VF("vertical-title-paddingTop", "12px"),
14277
14408
  titlePaddingBottom: VF("vertical-title-paddingBottom", "4px"),
14278
- titleFontSize: VF("vertical-title-font-size", "11px"),
14279
- titleLineHeight: VF("vertical-title-line-height", "18px"),
14409
+ /** 구간 제목 타이포 — stepper.vertical.title.typography (= heading.xxs) */
14410
+ titleTypo: "typo-heading-xxs",
14280
14411
  accentStripeWidth: VF("vertical-item-accentStripe-width", "2px"),
14281
14412
  accentStripeColor: VF("vertical-item-accentStripe-color", "#64ABFF")
14282
14413
  };
@@ -14286,6 +14417,7 @@ var STEPPER_VERTICAL_COLORS = {
14286
14417
  hover: VF("vertical-item-bg-hover", "#F6F6F6"),
14287
14418
  selected: VF("vertical-item-bg-selected", "#EFF6FF")
14288
14419
  },
14420
+ titleBg: V2("vertical-title-bg"),
14289
14421
  titleText: VF("vertical-title-text", "#004290"),
14290
14422
  textDefault: STEPPER_COLORS.text.default,
14291
14423
  textCompleted: STEPPER_COLORS.text.completed,
@@ -14293,9 +14425,10 @@ var STEPPER_VERTICAL_COLORS = {
14293
14425
  sequenceBgActive: STEPPER_COLORS.sequenceBg.active,
14294
14426
  sequenceTextActive: STEPPER_COLORS.sequenceText.active,
14295
14427
  sequenceTextDefault: STEPPER_COLORS.sequenceText.default,
14296
- sequenceBorderCompleted: VF("vertical-sequence-border-completed", "#93C4FF"),
14297
- sequenceBgCompleted: VF("vertical-sequence-bg-completed", "#EFF6FF"),
14298
- sequenceIconCompleted: VF("vertical-sequence-icon-completed", "#0075FF"),
14428
+ // 세로형 전용 completed 토큰은 없다 — 가로형과 같은 sequence.*.completed 를 쓴다.
14429
+ sequenceBorderCompleted: STEPPER_COLORS.sequenceBorder.completed,
14430
+ sequenceBgCompleted: STEPPER_COLORS.sequenceBg.completed,
14431
+ sequenceIconCompleted: STEPPER_COLORS.sequenceText.completed,
14299
14432
  errorBadge: "#FB4444"
14300
14433
  };
14301
14434
  var ERROR_TOOLTIP_MESSAGE = "\uD655\uC778\uC774 \uD544\uC694\uD55C \uD56D\uBAA9\uC774 \uC788\uC2B5\uB2C8\uB2E4.";
@@ -14458,10 +14591,12 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
14458
14591
  if (isHorizontalCompleted) return STEPPER_HORIZONTAL_COMPLETED_COLORS.sequenceIcon;
14459
14592
  return STEPPER_COLORS.sequenceText[state2];
14460
14593
  })();
14594
+ const emphasized = state2 === "active" || isVertical && hovered;
14595
+ const itemTypo = emphasized ? config.typoActive : config.typoDefault;
14461
14596
  const itemStyle = {
14462
14597
  gap: STEPPER_LAYOUT.itemGap,
14463
14598
  color: itemColor,
14464
- fontWeight: state2 === "active" || isVertical && hovered ? config.fontWeightActive : config.fontWeightDefault
14599
+ fontWeight: itemTypo ? void 0 : config.fontWeightActive
14465
14600
  };
14466
14601
  const sequenceStyle = {
14467
14602
  width: config.sequenceSize,
@@ -14478,7 +14613,7 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
14478
14613
  {
14479
14614
  role: roleListItem ? "listitem" : void 0,
14480
14615
  "aria-current": roleListItem && state2 === "active" ? "step" : void 0,
14481
- className: "inline-flex items-center whitespace-nowrap",
14616
+ className: cn("inline-flex items-center whitespace-nowrap", itemTypo),
14482
14617
  style: itemStyle,
14483
14618
  children: [
14484
14619
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -14524,7 +14659,7 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
14524
14659
  className: cn("relative inline-flex flex-col items-start", className),
14525
14660
  style: {
14526
14661
  width: STEPPER_VERTICAL_LAYOUT.width,
14527
- // 폭은 토큰이 정하되 부모보다 넓어지지 않는다 — 부모가 세로 스크롤바만큼 좁아지면 따라 줄어
14662
+ // 폭은 디자인 값(전용 토큰 없음)이되 부모보다 넓어지지 않는다 — 부모가 세로 스크롤바만큼 좁아지면 따라 줄어
14528
14663
  // 가로 넘침(가로 스크롤바)이 생기지 않는다
14529
14664
  maxWidth: "100%",
14530
14665
  fontSize: config.fontSize,
@@ -14556,18 +14691,18 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
14556
14691
  group.group && /* @__PURE__ */ jsxRuntime.jsx(
14557
14692
  "div",
14558
14693
  {
14559
- className: "flex w-full items-center overflow-hidden",
14694
+ className: cn(
14695
+ "flex w-full items-center overflow-hidden",
14696
+ STEPPER_VERTICAL_LAYOUT.titleTypo
14697
+ ),
14560
14698
  style: {
14561
14699
  gap: STEPPER_VERTICAL_LAYOUT.itemGap,
14562
14700
  paddingLeft: STEPPER_VERTICAL_LAYOUT.itemPaddingX,
14563
14701
  paddingRight: STEPPER_VERTICAL_LAYOUT.itemPaddingX,
14564
14702
  paddingTop: STEPPER_VERTICAL_LAYOUT.titlePaddingTop,
14565
14703
  paddingBottom: STEPPER_VERTICAL_LAYOUT.titlePaddingBottom,
14566
- background: STEPPER_VERTICAL_COLORS.itemBg.default,
14567
- color: STEPPER_VERTICAL_COLORS.titleText,
14568
- fontSize: STEPPER_VERTICAL_LAYOUT.titleFontSize,
14569
- lineHeight: STEPPER_VERTICAL_LAYOUT.titleLineHeight,
14570
- fontWeight: 700
14704
+ background: STEPPER_VERTICAL_COLORS.titleBg,
14705
+ color: STEPPER_VERTICAL_COLORS.titleText
14571
14706
  },
14572
14707
  children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap", children: group.group })
14573
14708
  }
@@ -15146,8 +15281,8 @@ var CalendarDayCard = /* @__PURE__ */ react.forwardRef(function CalendarDayCard2
15146
15281
  {
15147
15282
  className: cn(
15148
15283
  "inline-flex size-(--cmp-calendarBoard-daySequence-size) items-center justify-center rounded-(--cmp-calendarBoard-daySequence-radius)",
15149
- isToday ? "typo-body-md-bold bg-(--cmp-calendarBoard-daySequence-bg-today) text-(--cmp-calendarBoard-daySequence-text-today)" : cn(
15150
- "typo-body-md-medium",
15284
+ isToday ? "typo-item-md-selected bg-(--cmp-calendarBoard-daySequence-bg-today) text-(--cmp-calendarBoard-daySequence-text-today)" : cn(
15285
+ "typo-item-md-default",
15151
15286
  inCurrentMonth ? "text-(--cmp-calendarBoard-daySequence-text-default)" : "text-(--cmp-calendarBoard-daySequence-text-otherMonth)"
15152
15287
  ),
15153
15288
  // 오늘이 아니면서 선택된 날은 테두리 원으로 표시한다 (오늘은 이미 채운 원이라 겹치지 않는다).
@@ -15705,14 +15840,12 @@ function clampToAvailableHeight(value, availableHeight) {
15705
15840
  }
15706
15841
  var FONT = {
15707
15842
  sm: {
15708
- fontSize: 12,
15709
- lineHeight: 20,
15843
+ typo: "typo-field-sm-default",
15710
15844
  paddingX: "var(--cmp-textinput-sm-paddingX)",
15711
15845
  gap: "var(--cmp-textinput-sm-gap)"
15712
15846
  },
15713
15847
  md: {
15714
- fontSize: 14,
15715
- lineHeight: 24,
15848
+ typo: "typo-field-md-default",
15716
15849
  paddingX: "var(--cmp-textinput-md-paddingX)",
15717
15850
  gap: "var(--cmp-textinput-md-gap)"
15718
15851
  }
@@ -15751,12 +15884,10 @@ var SSearchInput = /* @__PURE__ */ react.forwardRef(function SSearchInput2({
15751
15884
  children: /* @__PURE__ */ jsxRuntime.jsxs(
15752
15885
  "div",
15753
15886
  {
15754
- className: "flex h-full w-full items-center",
15887
+ className: cn("flex h-full w-full items-center", f.typo),
15755
15888
  style: {
15756
15889
  gap: f.gap,
15757
- padding: `0 ${f.paddingX}`,
15758
- fontSize: f.fontSize,
15759
- lineHeight: `${f.lineHeight}px`
15890
+ padding: `0 ${f.paddingX}`
15760
15891
  },
15761
15892
  children: [
15762
15893
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -15817,6 +15948,18 @@ var SSearchInput = /* @__PURE__ */ react.forwardRef(function SSearchInput2({
15817
15948
  );
15818
15949
  });
15819
15950
 
15951
+ // src/lib/list-box-item.ts
15952
+ var LIST_BOX_ITEM_PADDING_LEFT = {
15953
+ 1: "var(--cmp-listBoxItem-paddingLeft-depth1)",
15954
+ 2: "var(--cmp-listBoxItem-paddingLeft-depth2)",
15955
+ 3: "var(--cmp-listBoxItem-paddingLeft-depth3)"
15956
+ };
15957
+ var LIST_BOX_ITEM_PADDING_Y_RIGHT = {
15958
+ paddingTop: "var(--cmp-listBoxItem-paddingY)",
15959
+ paddingBottom: "var(--cmp-listBoxItem-paddingY)",
15960
+ paddingRight: "var(--cmp-listBoxItem-paddingRight)"
15961
+ };
15962
+
15820
15963
  // src/components/SSelect/select.config.ts
15821
15964
  function flattenOptions(options, depth = 1, inheritDisabled = true) {
15822
15965
  const out = [];
@@ -15991,6 +16134,21 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
15991
16134
  const [focusedIndex, setFocusedIndex] = react.useState(-1);
15992
16135
  const [expanded, setExpanded] = react.useState(() => /* @__PURE__ */ new Set());
15993
16136
  const [searchCollapsed, setSearchCollapsed] = react.useState(NO_SEARCH_COLLAPSED);
16137
+ const [treeMotion, setTreeMotion] = react.useState(null);
16138
+ const treeMotionTimerRef = react.useRef(null);
16139
+ const pendingCollapseRef = react.useRef(null);
16140
+ const cancelTreeMotion = () => {
16141
+ if (treeMotionTimerRef.current != null) clearTimeout(treeMotionTimerRef.current);
16142
+ treeMotionTimerRef.current = null;
16143
+ pendingCollapseRef.current = null;
16144
+ setTreeMotion(null);
16145
+ };
16146
+ react.useEffect(
16147
+ () => () => {
16148
+ if (treeMotionTimerRef.current != null) clearTimeout(treeMotionTimerRef.current);
16149
+ },
16150
+ []
16151
+ );
15994
16152
  const baseId = react.useId();
15995
16153
  const listboxId = `${baseId}-listbox`;
15996
16154
  const activeOptionId = `${baseId}-active-option`;
@@ -16058,6 +16216,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
16058
16216
  const commitOpen = (next, valueForRules) => {
16059
16217
  setOpen(next);
16060
16218
  onOpenChange?.(next);
16219
+ cancelTreeMotion();
16061
16220
  if (next) {
16062
16221
  dismissedByPointerRef.current = false;
16063
16222
  alignSelectedTopRef.current = true;
@@ -16090,6 +16249,14 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
16090
16249
  }, [insideModal, pendingOpen, portalContainer]);
16091
16250
  const requestOpenRef = react.useRef(requestOpen);
16092
16251
  requestOpenRef.current = requestOpen;
16252
+ react.useEffect(() => {
16253
+ if (!label || effectiveDisabled) return;
16254
+ const labelEl = document.getElementById(fieldLabelId(triggerId));
16255
+ if (!labelEl) return;
16256
+ const toggle = () => requestOpenRef.current(!open);
16257
+ labelEl.addEventListener("click", toggle);
16258
+ return () => labelEl.removeEventListener("click", toggle);
16259
+ }, [label, effectiveDisabled, triggerId, open]);
16093
16260
  react.useImperativeHandle(
16094
16261
  ref,
16095
16262
  () => ({
@@ -16120,6 +16287,10 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
16120
16287
  (groupValue) => treeSearching ? !searchCollapsed.has(groupValue) : expanded.has(groupValue),
16121
16288
  [expanded, searchCollapsed, treeSearching]
16122
16289
  );
16290
+ const isGroupShownExpanded = react.useCallback(
16291
+ (groupValue) => isGroupExpanded(groupValue) && !(treeMotion != null && !treeMotion.opening && treeMotion.group === groupValue),
16292
+ [isGroupExpanded, treeMotion]
16293
+ );
16123
16294
  const treeRows = react.useMemo(
16124
16295
  () => isTree ? visibleTreeRows(searched, (row) => isGroupExpanded(row.value)) : null,
16125
16296
  [isGroupExpanded, isTree, searched]
@@ -16371,6 +16542,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
16371
16542
  const handleClear = () => {
16372
16543
  emit3([]);
16373
16544
  if (rules && rules.length > 0) setRuleError(runRules(multi ? [] : "", rules));
16545
+ triggerRef.current?.focus();
16374
16546
  };
16375
16547
  const handleRemoveChip = (targets) => {
16376
16548
  const remove = new Set(targets);
@@ -16408,6 +16580,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
16408
16580
  const handleSearchChange = (next) => {
16409
16581
  setSearch(next);
16410
16582
  setSearchCollapsed(NO_SEARCH_COLLAPSED);
16583
+ cancelTreeMotion();
16411
16584
  };
16412
16585
  const handleToggleExpand = (groupValue) => {
16413
16586
  rangeAnchorRef.current = null;
@@ -16417,8 +16590,41 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
16417
16590
  else next.add(groupValue);
16418
16591
  return next;
16419
16592
  };
16420
- if (treeSearching) setSearchCollapsed(toggle);
16421
- else setExpanded(toggle);
16593
+ const applyToggle = treeSearching ? () => setSearchCollapsed(toggle) : () => setExpanded(toggle);
16594
+ if (treeMotionTimerRef.current != null) clearTimeout(treeMotionTimerRef.current);
16595
+ treeMotionTimerRef.current = null;
16596
+ const pendingCollapse = pendingCollapseRef.current;
16597
+ pendingCollapseRef.current = null;
16598
+ if (treeMotion?.group === groupValue && !treeMotion.opening) {
16599
+ setTreeMotion({ group: groupValue, opening: true });
16600
+ treeMotionTimerRef.current = setTimeout(
16601
+ () => setTreeMotion(null),
16602
+ TREE_BRANCH_MOTION.duration
16603
+ );
16604
+ return;
16605
+ }
16606
+ pendingCollapse?.();
16607
+ if (!canAnimateTreeBranch()) {
16608
+ setTreeMotion(null);
16609
+ applyToggle();
16610
+ return;
16611
+ }
16612
+ if (isGroupExpanded(groupValue)) {
16613
+ setTreeMotion({ group: groupValue, opening: false });
16614
+ pendingCollapseRef.current = applyToggle;
16615
+ treeMotionTimerRef.current = setTimeout(() => {
16616
+ pendingCollapseRef.current = null;
16617
+ setTreeMotion(null);
16618
+ applyToggle();
16619
+ }, TREE_BRANCH_MOTION.duration);
16620
+ } else {
16621
+ applyToggle();
16622
+ setTreeMotion({ group: groupValue, opening: true });
16623
+ treeMotionTimerRef.current = setTimeout(
16624
+ () => setTreeMotion(null),
16625
+ TREE_BRANCH_MOTION.duration
16626
+ );
16627
+ }
16422
16628
  };
16423
16629
  const handleToggleGroup = (leafValues) => {
16424
16630
  if (leafValues.length === 0) return;
@@ -16528,7 +16734,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
16528
16734
  const row = rowIndex != null ? filtered[rowIndex] : void 0;
16529
16735
  if (rowIndex == null || row == null) return;
16530
16736
  event.preventDefault();
16531
- const rowExpanded = row.isGroup && isGroupExpanded(row.value);
16737
+ const rowExpanded = row.isGroup && isGroupShownExpanded(row.value);
16532
16738
  if (event.key === "ArrowRight") {
16533
16739
  if (!row.isGroup) return;
16534
16740
  if (!rowExpanded) {
@@ -16566,6 +16772,15 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
16566
16772
  commitOpen(false);
16567
16773
  }
16568
16774
  };
16775
+ const handleTriggerKeyDown = (event) => {
16776
+ if (event.target !== event.currentTarget || effectiveDisabled) return;
16777
+ if (event.key === " " || !open && event.key === "Enter") {
16778
+ event.preventDefault();
16779
+ requestOpen(!open);
16780
+ return;
16781
+ }
16782
+ handleKeyDown(event);
16783
+ };
16569
16784
  return /* @__PURE__ */ jsxRuntime.jsxs(
16570
16785
  SField,
16571
16786
  {
@@ -16593,23 +16808,28 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
16593
16808
  children: [
16594
16809
  name && /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: selected.join(",") }),
16595
16810
  /* @__PURE__ */ jsxRuntime.jsxs(
16596
- "button",
16811
+ "div",
16597
16812
  {
16598
16813
  ref: triggerRef,
16599
16814
  id: triggerId,
16600
- type: "button",
16601
- disabled: effectiveDisabled,
16602
- "aria-labelledby": label ? `${fieldLabelId(triggerId)} ${triggerId}` : void 0,
16815
+ role: "combobox",
16816
+ tabIndex: effectiveDisabled ? -1 : 0,
16817
+ "aria-disabled": effectiveDisabled || void 0,
16818
+ "aria-labelledby": label ? `${fieldLabelId(triggerId)} ${triggerId}` : triggerId,
16603
16819
  "aria-haspopup": isTree ? "tree" : "listbox",
16604
16820
  "aria-expanded": open,
16605
16821
  "aria-controls": open ? listboxId : void 0,
16606
16822
  "aria-activedescendant": open && focusedIndex >= 0 ? activeOptionId : void 0,
16607
16823
  "aria-busy": showTriggerSpinner || void 0,
16608
- onClick: () => requestOpen(!open),
16609
- onKeyDown: handleKeyDown,
16824
+ onClick: () => {
16825
+ if (effectiveDisabled) return;
16826
+ requestOpen(!open);
16827
+ },
16828
+ onKeyDown: handleTriggerKeyDown,
16610
16829
  className: cn(
16611
- "flex h-full w-full cursor-pointer items-center justify-between bg-transparent text-left outline-none disabled:cursor-not-allowed",
16612
- 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)"
16830
+ "flex h-full w-full items-center justify-between bg-transparent text-left outline-none",
16831
+ effectiveDisabled ? "cursor-not-allowed" : "cursor-pointer",
16832
+ size === "md" ? "typo-field-md-default gap-(--cmp-select-md-gap) px-(--cmp-select-md-paddingX)" : "typo-field-sm-default gap-(--cmp-select-sm-gap) px-(--cmp-select-sm-paddingX)"
16613
16833
  ),
16614
16834
  style: {
16615
16835
  // 칩 한 줄이 기본 높이 안에서 세로 가운데에 오는 여백. 줄이 늘면 같은 여백을 유지한 채 트리거가 커진다.
@@ -16731,7 +16951,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
16731
16951
  "div",
16732
16952
  {
16733
16953
  ref: searchBarRef,
16734
- className: "sticky top-0 z-[1] bg-[var(--cmp-listBox-bg)] px-(--cmp-listBoxItem-search-paddingX) py-(--cmp-listBoxItem-search-paddingY)",
16954
+ className: "sticky top-0 z-[1] border-b-(length:--border-width-1) border-solid border-[color:var(--sys-color-divider-default)] bg-[var(--cmp-listBox-bg)] px-(--cmp-listBoxItem-search-paddingX) py-(--cmp-listBoxItem-search-paddingY)",
16735
16955
  children: /* @__PURE__ */ jsxRuntime.jsx(
16736
16956
  SSearchInput,
16737
16957
  {
@@ -16759,14 +16979,14 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
16759
16979
  setSize: isDepth || isTree ? void 0 : rowCount,
16760
16980
  multi,
16761
16981
  tree: isTree,
16762
- isExpanded: isGroupExpanded,
16982
+ isExpanded: isGroupShownExpanded,
16763
16983
  onToggleExpand: handleToggleExpand,
16984
+ treeMotion,
16764
16985
  treeLines,
16765
16986
  selected,
16766
16987
  groupLeafValues,
16767
16988
  focusedValue: navigableItems[focusedIndex]?.key,
16768
16989
  showSelectAll: selectAllVisible,
16769
- searchVisible,
16770
16990
  selectAllLabel: allSelectedLabel,
16771
16991
  selectAllSelected: allSelected,
16772
16992
  onSelectAll: handleSelectAll,
@@ -16818,12 +17038,12 @@ function ItemList({
16818
17038
  tree,
16819
17039
  isExpanded,
16820
17040
  onToggleExpand,
17041
+ treeMotion,
16821
17042
  treeLines,
16822
17043
  selected,
16823
17044
  groupLeafValues,
16824
17045
  focusedValue,
16825
17046
  showSelectAll,
16826
- searchVisible,
16827
17047
  selectAllLabel,
16828
17048
  selectAllSelected,
16829
17049
  onSelectAll,
@@ -16834,281 +17054,327 @@ function ItemList({
16834
17054
  const selectedSet = react.useMemo(() => new Set(selected), [selected]);
16835
17055
  const checkboxShiftRef = react.useRef(false);
16836
17056
  const itemBase = cn(
16837
- "group/select-item flex w-full cursor-pointer select-none items-center gap-[8px] border-none bg-transparent text-left text-[12px] leading-[20px] outline-none",
17057
+ "group/select-item flex w-full cursor-pointer select-none items-center gap-(--cmp-listBoxItem-gap) border-none bg-transparent text-left typo-field-sm-default outline-none",
16838
17058
  "text-[color:var(--cmp-listBoxItem-content-default)]",
16839
17059
  "disabled:cursor-not-allowed disabled:text-[color:var(--cmp-listBoxItem-content-disabled)]"
16840
17060
  );
16841
17061
  const activeClass = "hover:bg-[var(--cmp-listBoxItem-bg-hover)] hover:text-[color:var(--cmp-listBoxItem-content-hover)] focus-visible:bg-[var(--cmp-listBoxItem-bg-hover)] focus-visible:text-[color:var(--cmp-listBoxItem-content-hover)]";
16842
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { id: listboxId, role: tree ? "tree" : "listbox", "aria-multiselectable": multi || void 0, children: [
16843
- showSelectAll && (tree ? (
16844
- // 트리의 전체선택 줄은 STree 의 "전체" 줄 그대로다 (lib/tree-row).
16845
- /* @__PURE__ */ jsxRuntime.jsx(
16846
- TreeAllRow,
16847
- {
16848
- "data-select-all-row": true,
16849
- id: focusedValue === "__select_all__" ? activeOptionId : void 0,
16850
- "data-select-focused": focusedValue === "__select_all__" ? "true" : void 0,
16851
- "data-select-active": focusedValue === "__select_all__" ? "true" : void 0,
16852
- tabIndex: -1,
16853
- label: selectAllLabel,
16854
- selected: selectAllSelected,
16855
- active: focusedValue === "__select_all__",
16856
- className: "select-none",
16857
- onMouseEnter: () => onHoverValue("__select_all__"),
16858
- onMouseLeave: () => onHoverValue(null),
16859
- onToggle: onSelectAll
16860
- }
16861
- )
16862
- ) : /* @__PURE__ */ jsxRuntime.jsxs(
16863
- "button",
17062
+ const wrapTreeMotion = (nodes) => {
17063
+ if (!tree || treeMotion == null) return nodes;
17064
+ const start = items.findIndex((o) => o.isGroup && o.value === treeMotion.group);
17065
+ if (start < 0) return nodes;
17066
+ let end = start + 1;
17067
+ while (end < items.length && items[end].depth > items[start].depth) end++;
17068
+ if (end === start + 1) return nodes;
17069
+ return [
17070
+ ...nodes.slice(0, start + 1),
17071
+ /* @__PURE__ */ jsxRuntime.jsx(TreeRowsMotion, { opening: treeMotion.opening, children: nodes.slice(start + 1, end) }, `__motion_${treeMotion.group}__`),
17072
+ ...nodes.slice(end)
17073
+ ];
17074
+ };
17075
+ const selectAllRow = showSelectAll && (tree ? (
17076
+ // 트리의 전체선택 줄은 STree 의 "전체" 줄 그대로다 (lib/tree-row).
17077
+ /* @__PURE__ */ jsxRuntime.jsx(
17078
+ TreeAllRow,
16864
17079
  {
16865
- type: "button",
16866
17080
  "data-select-all-row": true,
16867
17081
  id: focusedValue === "__select_all__" ? activeOptionId : void 0,
16868
17082
  "data-select-focused": focusedValue === "__select_all__" ? "true" : void 0,
16869
17083
  "data-select-active": focusedValue === "__select_all__" ? "true" : void 0,
16870
- className: cn(
16871
- itemBase,
16872
- focusedValue === "__select_all__" && "bg-[var(--cmp-listBoxItem-bg-hover)] text-[color:var(--cmp-listBoxItem-content-hover)]"
16873
- ),
16874
- style: { paddingTop: 4, paddingBottom: 4, paddingRight: 12, paddingLeft: 12 },
17084
+ tabIndex: -1,
17085
+ label: selectAllLabel,
17086
+ selected: selectAllSelected,
17087
+ active: focusedValue === "__select_all__",
17088
+ className: "select-none",
16875
17089
  onMouseEnter: () => onHoverValue("__select_all__"),
16876
17090
  onMouseLeave: () => onHoverValue(null),
16877
- onClick: onSelectAll,
16878
- children: [
16879
- /* @__PURE__ */ jsxRuntime.jsx(CheckboxBox, { state: selectAllSelected, focused: focusedValue === "__select_all__" }),
16880
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: selectAllLabel })
16881
- ]
17091
+ onToggle: onSelectAll
16882
17092
  }
16883
- )),
16884
- topSpacer > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, style: { height: topSpacer } }),
16885
- items.map((o, windowIndex) => {
16886
- const idx = windowIndex + indexOffset;
16887
- const padLeft = o.depth === 1 ? 12 : o.depth === 2 ? 20 : 28;
16888
- const rowKey = `${o.value}-${idx}`;
16889
- if (tree) {
16890
- const togglesLeaves = multi && o.isGroup;
16891
- const leafValues = togglesLeaves ? groupLeafValues.get(idx) ?? [] : [];
16892
- const total = leafValues.length;
16893
- const selectedCount = leafValues.reduce((n, v) => selectedSet.has(v) ? n + 1 : n, 0);
16894
- const isSelected2 = selectedSet.has(o.value);
16895
- const checkState = togglesLeaves ? total === 0 || selectedCount === 0 ? false : selectedCount === total ? true : null : isSelected2;
16896
- const rowDisabled = o.disabled || togglesLeaves && total === 0;
16897
- const focusKey = togglesLeaves ? `__group_${idx}__` : o.value;
16898
- const focused = focusedValue === focusKey;
16899
- const expanded = o.isGroup && isExpanded(o.value);
16900
- const line = treeLines[idx];
16901
- const toggle = () => {
16902
- if (rowDisabled) return;
16903
- if (togglesLeaves) onToggleGroup(leafValues);
16904
- else onSelect(o.value, idx, checkboxShiftRef.current);
16905
- };
16906
- return (
16907
- // eslint-disable-next-line jsx-a11y/click-events-have-key-events -- 키보드는 트리거(또는 검색 입력)가 aria-activedescendant 로 맡는다. 줄로 포커스를 옮기지 않는다
16908
- /* @__PURE__ */ jsxRuntime.jsxs(
16909
- "div",
16910
- {
16911
- tabIndex: -1,
16912
- "data-select-row": true,
16913
- "data-index": idx,
16914
- id: focused ? activeOptionId : void 0,
16915
- role: "treeitem",
16916
- "aria-level": o.depth,
16917
- "aria-posinset": line?.posInSet,
16918
- "aria-setsize": line?.setSize,
16919
- "aria-expanded": o.isGroup ? expanded : void 0,
16920
- "aria-selected": checkState === true,
16921
- "aria-disabled": rowDisabled || void 0,
16922
- "data-select-focused": focused ? "true" : void 0,
16923
- "data-select-active": focused ? "true" : void 0,
16924
- className: cn(
16925
- TREE_ROW_CLASS,
16926
- TREE_LABEL_TYPOGRAPHY.sm.rowHeight,
16927
- TREE_ROW_BORDER_CLASS,
16928
- "select-none",
16929
- rowDisabled ? "cursor-not-allowed" : "cursor-pointer",
16930
- focused && TREE_ROW_ACTIVE_CLASS
16931
- ),
16932
- onMouseEnter: () => onHoverValue(focusKey),
16933
- onMouseLeave: () => onHoverValue(null),
16934
- onClick: (event) => {
16935
- if (isRowControlClick(event) || rowDisabled) return;
17093
+ )
17094
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
17095
+ "button",
17096
+ {
17097
+ type: "button",
17098
+ "data-select-all-row": true,
17099
+ id: focusedValue === "__select_all__" ? activeOptionId : void 0,
17100
+ "data-select-focused": focusedValue === "__select_all__" ? "true" : void 0,
17101
+ "data-select-active": focusedValue === "__select_all__" ? "true" : void 0,
17102
+ className: cn(
17103
+ itemBase,
17104
+ focusedValue === "__select_all__" && "bg-[var(--cmp-listBoxItem-bg-hover)] text-[color:var(--cmp-listBoxItem-content-hover)]"
17105
+ ),
17106
+ style: { ...LIST_BOX_ITEM_PADDING_Y_RIGHT, paddingLeft: LIST_BOX_ITEM_PADDING_LEFT[1] },
17107
+ onMouseEnter: () => onHoverValue("__select_all__"),
17108
+ onMouseLeave: () => onHoverValue(null),
17109
+ onClick: onSelectAll,
17110
+ children: [
17111
+ /* @__PURE__ */ jsxRuntime.jsx(CheckboxBox, { state: selectAllSelected, focused: focusedValue === "__select_all__" }),
17112
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: selectAllLabel })
17113
+ ]
17114
+ }
17115
+ ));
17116
+ const rowNodes = items.map((o, windowIndex) => {
17117
+ const idx = windowIndex + indexOffset;
17118
+ const padLeft = LIST_BOX_ITEM_PADDING_LEFT[o.depth === 1 ? 1 : o.depth === 2 ? 2 : 3];
17119
+ const rowKey = `${o.value}-${idx}`;
17120
+ if (tree) {
17121
+ const togglesLeaves = multi && o.isGroup;
17122
+ const leafValues = togglesLeaves ? groupLeafValues.get(idx) ?? [] : [];
17123
+ const total = leafValues.length;
17124
+ const selectedCount = leafValues.reduce((n, v) => selectedSet.has(v) ? n + 1 : n, 0);
17125
+ const isSelected2 = selectedSet.has(o.value);
17126
+ const checkState = togglesLeaves ? total === 0 || selectedCount === 0 ? false : selectedCount === total ? true : null : isSelected2;
17127
+ const rowDisabled = o.disabled || togglesLeaves && total === 0;
17128
+ const focusKey = togglesLeaves ? `__group_${idx}__` : o.value;
17129
+ const focused = focusedValue === focusKey;
17130
+ const expanded = o.isGroup && isExpanded(o.value);
17131
+ const line = treeLines[idx];
17132
+ const toggle = () => {
17133
+ if (rowDisabled) return;
17134
+ if (togglesLeaves) onToggleGroup(leafValues);
17135
+ else onSelect(o.value, idx, checkboxShiftRef.current);
17136
+ };
17137
+ return (
17138
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events -- 키보드는 트리거(또는 검색 입력)가 aria-activedescendant 로 맡는다. 줄로 포커스를 옮기지 않는다
17139
+ /* @__PURE__ */ jsxRuntime.jsxs(
17140
+ "div",
17141
+ {
17142
+ tabIndex: -1,
17143
+ "data-select-row": true,
17144
+ "data-index": idx,
17145
+ id: focused ? activeOptionId : void 0,
17146
+ role: "treeitem",
17147
+ "aria-level": o.depth,
17148
+ "aria-posinset": line?.posInSet,
17149
+ "aria-setsize": line?.setSize,
17150
+ "aria-expanded": o.isGroup ? expanded : void 0,
17151
+ "aria-selected": checkState === true,
17152
+ "aria-disabled": rowDisabled || void 0,
17153
+ "data-select-focused": focused ? "true" : void 0,
17154
+ "data-select-active": focused ? "true" : void 0,
17155
+ className: cn(
17156
+ TREE_ROW_CLASS,
17157
+ TREE_LABEL_TYPOGRAPHY.sm.rowHeight,
17158
+ TREE_ROW_BORDER_CLASS,
17159
+ "select-none",
17160
+ o.isGroup && "cursor-pointer",
17161
+ focused && TREE_ROW_ACTIVE_CLASS
17162
+ ),
17163
+ onMouseEnter: () => onHoverValue(focusKey),
17164
+ onMouseLeave: () => onHoverValue(null),
17165
+ onClick: (event) => {
17166
+ if (isRowControlClick(event)) return;
17167
+ if (isRowSelectClick(event)) {
17168
+ if (rowDisabled) return;
16936
17169
  if (togglesLeaves) onToggleGroup(leafValues);
16937
17170
  else onSelect(o.value, idx, event.shiftKey);
16938
- },
16939
- children: [
16940
- /* @__PURE__ */ jsxRuntime.jsx(
16941
- TreeConnector,
16942
- {
16943
- guideline: true,
16944
- size: "sm",
16945
- depth: o.depth,
16946
- hasChildren: o.isGroup,
16947
- isLast: line?.isLast ?? true,
16948
- ancestorLast: line?.ancestorLast ?? []
16949
- }
16950
- ),
16951
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: TREE_CONTENT_CLASS, children: [
16952
- o.isGroup ? (
16953
- // 비활성 그룹도 접고 편다 — 그룹이 비활성이어도 아래에 고를 수 있는 자식이 있을 수 있다.
16954
- /* @__PURE__ */ jsxRuntime.jsx(TreeCaret, { expanded, onToggle: () => onToggleExpand(o.value) })
16955
- ) : /* @__PURE__ */ jsxRuntime.jsx(TreeCaretSpacer, {}),
16956
- multi && /* @__PURE__ */ jsxRuntime.jsx(
16957
- "span",
16958
- {
16959
- "data-tree-control": true,
16960
- className: "flex shrink-0",
16961
- onPointerDownCapture: (event) => {
16962
- checkboxShiftRef.current = event.shiftKey;
16963
- },
16964
- children: /* @__PURE__ */ jsxRuntime.jsx(SCheckbox, { value: checkState, disabled: rowDisabled, onValueChange: toggle })
16965
- }
16966
- ),
16967
- /* @__PURE__ */ jsxRuntime.jsx(
16968
- OptionLabel,
16969
- {
16970
- label: o.label,
16971
- className: treeLabelClass("sm", {
16972
- // 고른 줄은 굵게 — multi_tree 는 일부만 고른 그룹도 굵다 (STree 와 같다)
16973
- emphasized: checkState !== false,
16974
- disabled: rowDisabled,
16975
- selectable: true
16976
- })
16977
- }
16978
- )
16979
- ] })
16980
- ]
17171
+ return;
17172
+ }
17173
+ if (o.isGroup) onToggleExpand(o.value);
16981
17174
  },
16982
- rowKey
16983
- )
16984
- );
16985
- }
16986
- if (o.isGroup) {
16987
- const isDepth1 = o.depth === 1;
16988
- const isFirstRow = idx === 0 && !showSelectAll && !searchVisible;
16989
- const groupTone = cn(
16990
- isDepth1 ? "bg-[var(--cmp-listBoxItem-depth1-bg-default)] font-bold" : "bg-[var(--cmp-listBoxItem-depth2-middle-bg)] font-medium",
16991
- isDepth1 && !isFirstRow && "border-t border-solid border-[color:var(--cmp-listBoxItem-depth1-border-color)]"
16992
- );
16993
- if (multi) {
16994
- const leafValues = groupLeafValues.get(idx) ?? [];
16995
- const total = leafValues.length;
16996
- const selectedCount = leafValues.reduce((n, v) => selectedSet.has(v) ? n + 1 : n, 0);
16997
- const groupState = total === 0 || selectedCount === 0 ? false : selectedCount === total ? true : null;
16998
- const groupDisabled = o.disabled || total === 0;
16999
- const groupFocused = focusedValue === `__group_${idx}__`;
17000
- return /* @__PURE__ */ jsxRuntime.jsxs(
17001
- "button",
17002
- {
17003
- type: "button",
17004
- "data-select-row": true,
17005
- "data-index": idx,
17006
- id: groupFocused ? activeOptionId : void 0,
17007
- role: "option",
17008
- "aria-selected": groupState === true,
17009
- disabled: groupDisabled,
17010
- "data-select-focused": groupFocused ? "true" : void 0,
17011
- "data-select-active": groupFocused ? "true" : void 0,
17012
- className: cn(
17013
- "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-listBoxItem-content-default)]",
17014
- groupTone,
17015
- groupDisabled ? "cursor-not-allowed text-[color:var(--cmp-listBoxItem-content-disabled)]" : "cursor-pointer",
17016
- groupDisabled && isDepth1 && "bg-[var(--cmp-listBoxItem-depth1-bg-disabled)]",
17017
- // 포커스 하이라이트는 depth 배경보다 뒤에 둬 tailwind-merge 로 이기게 한다.
17018
- groupFocused && !groupDisabled && "bg-[var(--cmp-listBoxItem-bg-hover)] text-[color:var(--cmp-listBoxItem-content-hover)]"
17175
+ children: [
17176
+ /* @__PURE__ */ jsxRuntime.jsx(
17177
+ TreeConnector,
17178
+ {
17179
+ guideline: true,
17180
+ size: "sm",
17181
+ depth: o.depth,
17182
+ hasChildren: o.isGroup,
17183
+ isLast: line?.isLast ?? true,
17184
+ ancestorLast: line?.ancestorLast ?? []
17185
+ }
17019
17186
  ),
17020
- style: { paddingLeft: padLeft },
17021
- onMouseEnter: () => onHoverValue(`__group_${idx}__`),
17022
- onMouseLeave: () => onHoverValue(null),
17023
- onClick: () => onToggleGroup(leafValues),
17024
- children: [
17025
- /* @__PURE__ */ jsxRuntime.jsx(CheckboxBox, { state: groupState, disabled: groupDisabled, focused: groupFocused }),
17026
- /* @__PURE__ */ jsxRuntime.jsx(OptionLabel, { label: o.label, className: "min-w-0 truncate" }),
17027
- total > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
17028
- "span",
17187
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: TREE_CONTENT_CLASS, children: [
17188
+ o.isGroup ? (
17189
+ // 비활성 그룹도 접고 편다 — 그룹이 비활성이어도 아래에 고를 수 있는 자식이 있을 수 있다.
17190
+ /* @__PURE__ */ jsxRuntime.jsx(TreeCaret, { expanded, onToggle: () => onToggleExpand(o.value) })
17191
+ ) : /* @__PURE__ */ jsxRuntime.jsx(TreeCaretSpacer, {}),
17192
+ /* @__PURE__ */ jsxRuntime.jsx(
17193
+ TreeSelectZone,
17029
17194
  {
17030
- className: cn(
17031
- "shrink-0 font-medium",
17032
- groupFocused ? "text-white" : "text-[color:var(--cmp-listBoxItem-content-disabled)]"
17195
+ selectable: true,
17196
+ disabled: rowDisabled,
17197
+ control: multi && /* @__PURE__ */ jsxRuntime.jsx(
17198
+ "span",
17199
+ {
17200
+ "data-tree-control": true,
17201
+ className: "flex shrink-0",
17202
+ onPointerDownCapture: (event) => {
17203
+ checkboxShiftRef.current = event.shiftKey;
17204
+ },
17205
+ children: /* @__PURE__ */ jsxRuntime.jsx(SCheckbox, { value: checkState, disabled: rowDisabled, onValueChange: toggle })
17206
+ }
17033
17207
  ),
17034
- children: [
17035
- "(",
17036
- selectedCount,
17037
- "/",
17038
- total,
17039
- ")"
17040
- ]
17208
+ children: /* @__PURE__ */ jsxRuntime.jsx(
17209
+ OptionLabel,
17210
+ {
17211
+ label: o.label,
17212
+ className: treeLabelClass("sm", {
17213
+ // 고른 줄은 굵게 — multi_tree 는 일부만 고른 그룹도 굵다 (STree 와 같다)
17214
+ emphasized: checkState !== false,
17215
+ disabled: rowDisabled,
17216
+ selectable: true
17217
+ })
17218
+ }
17219
+ )
17041
17220
  }
17042
17221
  )
17043
- ]
17044
- },
17045
- rowKey
17046
- );
17047
- }
17048
- return /* @__PURE__ */ jsxRuntime.jsx(
17049
- "div",
17222
+ ] })
17223
+ ]
17224
+ },
17225
+ rowKey
17226
+ )
17227
+ );
17228
+ }
17229
+ if (o.isGroup) {
17230
+ const isDepth1 = o.depth === 1;
17231
+ const isFirstRow = idx === 0 && !showSelectAll;
17232
+ const groupTone = cn(
17233
+ isDepth1 ? "bg-[var(--cmp-listBoxItem-depth1-bg-default)] font-bold" : "bg-[var(--cmp-listBoxItem-depth2-middle-bg)] font-medium",
17234
+ isDepth1 && !isFirstRow && "border-t border-solid border-[color:var(--cmp-listBoxItem-depth1-border-color)]"
17235
+ );
17236
+ if (multi) {
17237
+ const leafValues = groupLeafValues.get(idx) ?? [];
17238
+ const total = leafValues.length;
17239
+ const selectedCount = leafValues.reduce((n, v) => selectedSet.has(v) ? n + 1 : n, 0);
17240
+ const groupState = total === 0 || selectedCount === 0 ? false : selectedCount === total ? true : null;
17241
+ const groupDisabled = o.disabled || total === 0;
17242
+ const groupFocused = focusedValue === `__group_${idx}__`;
17243
+ return /* @__PURE__ */ jsxRuntime.jsxs(
17244
+ "button",
17050
17245
  {
17246
+ type: "button",
17051
17247
  "data-select-row": true,
17052
17248
  "data-index": idx,
17249
+ id: groupFocused ? activeOptionId : void 0,
17250
+ role: "option",
17251
+ "aria-selected": groupState === true,
17252
+ disabled: groupDisabled,
17253
+ "data-select-focused": groupFocused ? "true" : void 0,
17254
+ "data-select-active": groupFocused ? "true" : void 0,
17053
17255
  className: cn(
17054
- "select-none py-[4px] pr-[12px] text-[12px] leading-[20px] text-[color:var(--cmp-listBoxItem-content-default)]",
17256
+ "flex w-full select-none items-center gap-(--cmp-listBoxItem-gap) border-none py-(--cmp-listBoxItem-paddingY) pr-(--cmp-listBoxItem-paddingRight) text-left typo-field-sm-default text-[color:var(--cmp-listBoxItem-content-default)]",
17055
17257
  groupTone,
17056
- // 하위가 전부 비활성이면(select.config 에서 bubble-up) 어미 그룹도 비활성 처리:
17057
- // 텍스트는 회색(#888), depth1 그룹은 파란 배경 대신 회색(#EEE)으로 (depth2 는 #F6F6F6 유지)
17058
- o.disabled && "cursor-not-allowed text-[color:var(--cmp-listBoxItem-content-disabled)]",
17059
- o.disabled && isDepth1 && "bg-[var(--cmp-listBoxItem-depth1-bg-disabled)]"
17258
+ groupDisabled ? "cursor-not-allowed text-[color:var(--cmp-listBoxItem-content-disabled)]" : "cursor-pointer",
17259
+ groupDisabled && isDepth1 && "bg-[var(--cmp-listBoxItem-depth1-bg-disabled)]",
17260
+ // 포커스 하이라이트는 depth 배경보다 뒤에 둬 tailwind-merge 로 이기게 한다.
17261
+ groupFocused && !groupDisabled && "bg-[var(--cmp-listBoxItem-bg-hover)] text-[color:var(--cmp-listBoxItem-content-hover)]"
17060
17262
  ),
17061
17263
  style: { paddingLeft: padLeft },
17062
- children: o.label
17264
+ onMouseEnter: () => onHoverValue(`__group_${idx}__`),
17265
+ onMouseLeave: () => onHoverValue(null),
17266
+ onClick: () => onToggleGroup(leafValues),
17267
+ children: [
17268
+ /* @__PURE__ */ jsxRuntime.jsx(CheckboxBox, { state: groupState, disabled: groupDisabled, focused: groupFocused }),
17269
+ /* @__PURE__ */ jsxRuntime.jsx(OptionLabel, { label: o.label, className: "min-w-0 truncate" }),
17270
+ total > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
17271
+ "span",
17272
+ {
17273
+ className: cn(
17274
+ "shrink-0 font-medium",
17275
+ groupFocused ? "text-white" : "text-[color:var(--cmp-listBoxItem-content-disabled)]"
17276
+ ),
17277
+ children: [
17278
+ "(",
17279
+ selectedCount,
17280
+ "/",
17281
+ total,
17282
+ ")"
17283
+ ]
17284
+ }
17285
+ )
17286
+ ]
17063
17287
  },
17064
17288
  rowKey
17065
17289
  );
17066
17290
  }
17067
- const isSelected = selected.includes(o.value);
17068
- return /* @__PURE__ */ jsxRuntime.jsxs(
17069
- "button",
17291
+ return /* @__PURE__ */ jsxRuntime.jsx(
17292
+ "div",
17070
17293
  {
17071
- type: "button",
17072
17294
  "data-select-row": true,
17073
17295
  "data-index": idx,
17074
- id: focusedValue === o.value ? activeOptionId : void 0,
17075
- disabled: o.disabled,
17076
- role: "option",
17077
- "aria-selected": isSelected,
17078
- "aria-setsize": setSize,
17079
- "aria-posinset": setSize != null ? idx + 1 : void 0,
17080
- "data-select-focused": focusedValue === o.value ? "true" : void 0,
17081
- "data-select-active": focusedValue === o.value ? "true" : void 0,
17082
17296
  className: cn(
17083
- itemBase,
17084
- isSelected && !multi && "font-bold text-[color:var(--cmp-listBoxItem-content-selected)]",
17085
- focusedValue === o.value && "bg-[var(--cmp-listBoxItem-bg-hover)] text-[color:var(--cmp-listBoxItem-content-hover)]",
17086
- // 비활성 항목은 hover/focus 스타일 대상에서 제외한다.
17087
- // (:hover 는 disabled 버튼에도 매칭되므로 클래스 자체를 붙이지 않아야 한다)
17088
- !o.disabled && activeClass
17297
+ "select-none py-(--cmp-listBoxItem-paddingY) pr-(--cmp-listBoxItem-paddingRight) typo-field-sm-default text-[color:var(--cmp-listBoxItem-content-default)]",
17298
+ groupTone,
17299
+ // 하위가 전부 비활성이면(select.config 에서 bubble-up) 어미 그룹도 비활성 처리:
17300
+ // 텍스트는 회색(#888), depth1 그룹은 파란 배경 대신 회색(#EEE)으로 (depth2 는 #F6F6F6 유지)
17301
+ o.disabled && "cursor-not-allowed text-[color:var(--cmp-listBoxItem-content-disabled)]",
17302
+ o.disabled && isDepth1 && "bg-[var(--cmp-listBoxItem-depth1-bg-disabled)]"
17089
17303
  ),
17090
- style: { paddingTop: 4, paddingBottom: 4, paddingRight: 12, paddingLeft: padLeft },
17091
- onMouseEnter: () => onHoverValue(o.value),
17092
- onMouseLeave: () => onHoverValue(null),
17093
- onClick: (event) => onSelect(o.value, idx, event.shiftKey),
17094
- children: [
17095
- multi && /* @__PURE__ */ jsxRuntime.jsx(
17096
- CheckboxBox,
17097
- {
17098
- state: isSelected,
17099
- disabled: o.disabled,
17100
- focused: focusedValue === o.value
17101
- }
17102
- ),
17103
- /* @__PURE__ */ jsxRuntime.jsx(OptionLabel, { label: o.label, className: "flex-1 truncate" })
17104
- ]
17304
+ style: { paddingLeft: padLeft },
17305
+ children: o.label
17105
17306
  },
17106
17307
  rowKey
17107
17308
  );
17108
- }),
17309
+ }
17310
+ const isSelected = selected.includes(o.value);
17311
+ return /* @__PURE__ */ jsxRuntime.jsxs(
17312
+ "button",
17313
+ {
17314
+ type: "button",
17315
+ "data-select-row": true,
17316
+ "data-index": idx,
17317
+ id: focusedValue === o.value ? activeOptionId : void 0,
17318
+ disabled: o.disabled,
17319
+ role: "option",
17320
+ "aria-selected": isSelected,
17321
+ "aria-setsize": setSize,
17322
+ "aria-posinset": setSize != null ? idx + 1 : void 0,
17323
+ "data-select-focused": focusedValue === o.value ? "true" : void 0,
17324
+ "data-select-active": focusedValue === o.value ? "true" : void 0,
17325
+ className: cn(
17326
+ itemBase,
17327
+ isSelected && !multi && "font-bold text-[color:var(--cmp-listBoxItem-content-selected)]",
17328
+ focusedValue === o.value && "bg-[var(--cmp-listBoxItem-bg-hover)] text-[color:var(--cmp-listBoxItem-content-hover)]",
17329
+ // 비활성 항목은 hover/focus 스타일 대상에서 제외한다.
17330
+ // (:hover 는 disabled 버튼에도 매칭되므로 클래스 자체를 붙이지 않아야 한다)
17331
+ !o.disabled && activeClass
17332
+ ),
17333
+ style: { ...LIST_BOX_ITEM_PADDING_Y_RIGHT, paddingLeft: padLeft },
17334
+ onMouseEnter: () => onHoverValue(o.value),
17335
+ onMouseLeave: () => onHoverValue(null),
17336
+ onClick: (event) => onSelect(o.value, idx, event.shiftKey),
17337
+ children: [
17338
+ multi && /* @__PURE__ */ jsxRuntime.jsx(
17339
+ CheckboxBox,
17340
+ {
17341
+ state: isSelected,
17342
+ disabled: o.disabled,
17343
+ focused: focusedValue === o.value
17344
+ }
17345
+ ),
17346
+ /* @__PURE__ */ jsxRuntime.jsx(OptionLabel, { label: o.label, className: "flex-1 truncate" })
17347
+ ]
17348
+ },
17349
+ rowKey
17350
+ );
17351
+ });
17352
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { id: listboxId, role: tree ? "tree" : "listbox", "aria-multiselectable": multi || void 0, children: [
17353
+ selectAllRow,
17354
+ topSpacer > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, style: { height: topSpacer } }),
17355
+ wrapTreeMotion(rowNodes),
17109
17356
  bottomSpacer > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, style: { height: bottomSpacer } })
17110
17357
  ] });
17111
17358
  }
17359
+ function TreeRowsMotion({ opening, children }) {
17360
+ const ref = react.useRef(null);
17361
+ const animationRef = react.useRef(null);
17362
+ const mountedRef = react.useRef(false);
17363
+ react.useLayoutEffect(() => {
17364
+ const el = ref.current;
17365
+ if (el == null || typeof el.animate !== "function") return;
17366
+ const from = !mountedRef.current && opening ? 0 : el.getBoundingClientRect().height;
17367
+ mountedRef.current = true;
17368
+ animationRef.current?.cancel();
17369
+ animationRef.current = el.animate(
17370
+ [{ height: `${from}px` }, { height: opening ? `${el.scrollHeight}px` : "0px" }],
17371
+ // 접힌 뒤 줄이 목록에서 빠질 때까지 0 으로 붙잡아 둔다. 편 뒤에는 제 높이(auto)로 돌아간다
17372
+ { ...TREE_BRANCH_MOTION, fill: opening ? "none" : "forwards" }
17373
+ );
17374
+ }, [opening]);
17375
+ react.useEffect(() => () => animationRef.current?.cancel(), []);
17376
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: "overflow-hidden", "aria-hidden": opening ? void 0 : true, children });
17377
+ }
17112
17378
  function OptionLabel({ label, className }) {
17113
17379
  return isHtmlLabel(label) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className, dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(label) } }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className, children: label });
17114
17380
  }
@@ -17116,40 +17382,17 @@ function TriggerLabel({ label }) {
17116
17382
  return /* @__PURE__ */ jsxRuntime.jsx(OptionLabel, { label, className: "truncate" });
17117
17383
  }
17118
17384
  function TriggerRemoveButton({ ariaLabel, onRemove }) {
17119
- return /* @__PURE__ */ jsxRuntime.jsxs(
17120
- "span",
17385
+ return /* @__PURE__ */ jsxRuntime.jsx(
17386
+ SGhostButton,
17121
17387
  {
17122
- role: "button",
17123
- tabIndex: 0,
17124
- "aria-label": ariaLabel,
17125
- className: "group/select-remove relative inline-flex shrink-0 cursor-pointer items-center justify-center",
17126
- style: {
17127
- width: "var(--cmp-ghostButton-xxs-size)",
17128
- height: "var(--cmp-ghostButton-xxs-size)",
17129
- borderRadius: "var(--cmp-ghostButton-radius-sm)"
17130
- },
17388
+ icon: "close",
17389
+ size: "xxs",
17390
+ ariaLabel,
17391
+ className: "shrink-0",
17131
17392
  onClick: (event) => {
17132
- event.preventDefault();
17133
17393
  event.stopPropagation();
17134
17394
  onRemove();
17135
- },
17136
- onKeyDown: (event) => {
17137
- if (event.key !== "Enter" && event.key !== " ") return;
17138
- event.preventDefault();
17139
- event.stopPropagation();
17140
- onRemove();
17141
- },
17142
- children: [
17143
- /* @__PURE__ */ jsxRuntime.jsx(
17144
- "span",
17145
- {
17146
- "aria-hidden": true,
17147
- className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover/select-remove:opacity-5",
17148
- style: { background: "var(--cmp-ghostButton-default-hover-bg)" }
17149
- }
17150
- ),
17151
- /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
17152
- ]
17395
+ }
17153
17396
  }
17154
17397
  );
17155
17398
  }
@@ -17163,7 +17406,7 @@ function CheckboxBox({
17163
17406
  "span",
17164
17407
  {
17165
17408
  className: cn(
17166
- "flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid",
17409
+ "flex size-(--cmp-checkbox-size) flex-shrink-0 items-center justify-center rounded-(--cmp-checkbox-radius) border-(length:--cmp-checkbox-borderWidth) border-solid",
17167
17410
  disabled ? (
17168
17411
  // 비활성: 회색 채움(#E1E1E1) + 회색 테두리(#CCCCCC)
17169
17412
  "cursor-not-allowed border-[color:var(--cmp-checkbox-border-disabled)] bg-[var(--cmp-checkbox-bg-disabled)]"
@@ -17173,7 +17416,7 @@ function CheckboxBox({
17173
17416
  SIcon,
17174
17417
  {
17175
17418
  name: state2 === null ? "checkboxIndeterminate" : "checkboxCheck",
17176
- size: 12,
17419
+ size: "var(--cmp-checkbox-icon)",
17177
17420
  color: disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : "var(--cmp-checkbox-checked-icon-default)"
17178
17421
  }
17179
17422
  )
@@ -17806,7 +18049,7 @@ var STableImpl = /* @__PURE__ */ react.forwardRef(function STable({
17806
18049
  "span",
17807
18050
  {
17808
18051
  onMouseDown: (e) => startResize(i, e),
17809
- className: "absolute right-0 top-1/2 z-[5] flex h-[16px] w-[9px] -translate-y-1/2 cursor-col-resize items-center justify-end",
18052
+ className: "absolute right-0 top-1/2 z-[5] flex h-[var(--cmp-table-header-resizingBar-height)] w-[9px] -translate-y-1/2 cursor-col-resize items-center justify-end",
17810
18053
  "aria-hidden": true,
17811
18054
  children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-full w-[4px] border-x border-solid border-[color:var(--cmp-table-header-resizingBar-color)]" })
17812
18055
  },
@@ -17869,7 +18112,7 @@ var STableImpl = /* @__PURE__ */ react.forwardRef(function STable({
17869
18112
  colSpan: group.colSpan,
17870
18113
  rowSpan: group.rowSpan,
17871
18114
  className: cn(
17872
- "relative border-b border-r border-solid border-[color:var(--cmp-table-border-color)] bg-[var(--cmp-table-header-bg)] px-[16px] text-[12px] font-medium leading-[20px] text-[color:var(--sys-color-fg-primary)]",
18115
+ "relative border-b border-r border-solid border-[color:var(--cmp-table-border-color)] bg-[var(--cmp-table-header-bg)] px-[var(--cmp-table-header-paddingX)] typo-table-header text-[color:var(--sys-color-fg-primary)]",
17873
18116
  group.firstIndex + group.colSpan === visibleCols.length && "border-r-0",
17874
18117
  group.rowSpan === 2 && "border-b-0",
17875
18118
  group.className
@@ -17911,7 +18154,7 @@ var STableImpl = /* @__PURE__ */ react.forwardRef(function STable({
17911
18154
  "span",
17912
18155
  {
17913
18156
  "aria-hidden": true,
17914
- className: "pointer-events-none absolute right-0 top-1/2 h-[16px] w-px -translate-y-1/2 bg-[var(--cmp-table-header-resizingBar-color)]"
18157
+ className: "pointer-events-none absolute right-0 top-1/2 h-[var(--cmp-table-header-resizingBar-height)] w-px -translate-y-1/2 bg-[var(--cmp-table-header-resizingBar-color)]"
17915
18158
  }
17916
18159
  )
17917
18160
  ]
@@ -17932,7 +18175,7 @@ var STableImpl = /* @__PURE__ */ react.forwardRef(function STable({
17932
18175
  // 세로 가운데도 어긋난다. 글자 줄높이는 아래 th__content 가 다시 준다.
17933
18176
  headerGroupInfo && "border-r border-solid border-[color:var(--cmp-table-border-color)]",
17934
18177
  headerGroupInfo && i === visibleCols.length - 1 && "border-r-0",
17935
- "relative bg-[var(--cmp-table-header-bg)] px-[16px] text-[12px] font-medium leading-[0] text-[color:var(--sys-color-fg-primary)]",
18178
+ "relative bg-[var(--cmp-table-header-bg)] px-[var(--cmp-table-header-paddingX)] typo-table-header leading-[0] text-[color:var(--sys-color-fg-primary)]",
17936
18179
  stickyInfo(i).isSticky && "z-[6]",
17937
18180
  col.thClass
17938
18181
  ),
@@ -17951,7 +18194,7 @@ var STableImpl = /* @__PURE__ */ react.forwardRef(function STable({
17951
18194
  // 원본 th__content: align에 따라 justify-content 적용 (th도 정렬 반영)
17952
18195
  // th 가 leading-[0] 이므로 글자 줄높이는 여기서 준다 (truncate 가
17953
18196
  // overflow-hidden 이라 줄높이가 0이면 라벨이 잘려 사라진다).
17954
- "inline-flex w-full min-w-0 items-center gap-[4px] leading-[20px]",
18197
+ "inline-flex w-full min-w-0 items-center gap-[var(--cmp-table-header-gap)] leading-[20px]",
17955
18198
  col.align === "center" && "justify-center",
17956
18199
  col.align === "right" && "justify-end"
17957
18200
  ),
@@ -18849,8 +19092,8 @@ function useTruncatedValueTooltip({
18849
19092
  };
18850
19093
  }
18851
19094
  var FONT2 = {
18852
- sm: { fontSize: 12, lineHeight: 20, paddingX: "var(--cmp-textinput-sm-paddingX)" },
18853
- md: { fontSize: 14, lineHeight: 24, paddingX: "var(--cmp-textinput-md-paddingX)" }
19095
+ sm: { typo: "typo-field-sm-default", paddingX: "var(--cmp-textinput-sm-paddingX)" },
19096
+ md: { typo: "typo-field-md-default", paddingX: "var(--cmp-textinput-md-paddingX)" }
18854
19097
  };
18855
19098
  var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
18856
19099
  value,
@@ -18943,12 +19186,11 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
18943
19186
  {
18944
19187
  className: cn(
18945
19188
  "flex h-full w-full items-center",
19189
+ f.typo,
18946
19190
  size === "md" ? "gap-[var(--cmp-textinput-md-gap)]" : "gap-[var(--cmp-textinput-sm-gap)]"
18947
19191
  ),
18948
19192
  style: {
18949
- padding: `0 ${f.paddingX}`,
18950
- fontSize: f.fontSize,
18951
- lineHeight: `${f.lineHeight}px`
19193
+ padding: `0 ${f.paddingX}`
18952
19194
  },
18953
19195
  children: [
18954
19196
  prefix != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-shrink-0 items-center", children: prefix }),
@@ -19022,8 +19264,8 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
19022
19264
  );
19023
19265
  });
19024
19266
  var PAD2 = {
19025
- sm: { fontSize: 12, lineHeight: 20, stepper: 20, icon: 12 },
19026
- md: { fontSize: 14, lineHeight: 24, stepper: 24, icon: 14 }
19267
+ sm: { typo: "typo-field-sm-default", icon: 12 },
19268
+ md: { typo: "typo-field-md-default", icon: 14 }
19027
19269
  };
19028
19270
  var toNumber = (val) => {
19029
19271
  if (val === null || val === void 0 || val === "") return null;
@@ -19258,7 +19500,7 @@ var SNumberInput = /* @__PURE__ */ react.forwardRef(function SNumberInput2({
19258
19500
  onClick: dir === "inc" ? increment : decrement,
19259
19501
  className: cn(
19260
19502
  "flex flex-shrink-0 items-center justify-center border border-solid border-transparent transition-colors",
19261
- off ? "cursor-not-allowed" : "cursor-pointer hover:border-[var(--color-border-accentLight)]"
19503
+ off ? "cursor-not-allowed" : "cursor-pointer hover:border-[var(--cmp-numberInput-stepper-border-default)]"
19262
19504
  ),
19263
19505
  style: {
19264
19506
  width: `var(--cmp-numberInput-stepper-${size}-size)`,
@@ -19307,13 +19549,11 @@ var SNumberInput = /* @__PURE__ */ react.forwardRef(function SNumberInput2({
19307
19549
  children: /* @__PURE__ */ jsxRuntime.jsxs(
19308
19550
  "div",
19309
19551
  {
19310
- className: "flex h-full w-full items-center",
19552
+ className: cn("flex h-full w-full items-center", p.typo),
19311
19553
  style: {
19312
19554
  // 원본 sd-number-input: content gap = padding-x 토큰 (gap 토큰 아님)
19313
19555
  gap: `var(--cmp-numberInput-${size}-paddingX)`,
19314
- padding: `0 ${showButton ? padX : `calc(${padX} * 2)`}`,
19315
- fontSize: p.fontSize,
19316
- lineHeight: `${p.lineHeight}px`
19556
+ padding: `0 ${showButton ? padX : `calc(${padX} * 2)`}`
19317
19557
  },
19318
19558
  children: [
19319
19559
  showButton && stepper("dec"),
@@ -19599,7 +19839,7 @@ function SCalendar({
19599
19839
  onClick: () => view(y - 1, m)
19600
19840
  }
19601
19841
  ),
19602
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex min-w-[40px] items-center justify-center text-center text-[14px] font-medium leading-[24px]", children: y }),
19842
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex min-w-[40px] items-center justify-center text-center typo-field-md-medium", children: y }),
19603
19843
  /* @__PURE__ */ jsxRuntime.jsx(
19604
19844
  SGhostButton,
19605
19845
  {
@@ -19624,7 +19864,7 @@ function SCalendar({
19624
19864
  }
19625
19865
  }
19626
19866
  ),
19627
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex w-full min-w-[40px] items-center justify-center text-center text-[14px] font-medium leading-[24px]", children: [
19867
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex w-full min-w-[40px] items-center justify-center text-center typo-field-md-medium", children: [
19628
19868
  m,
19629
19869
  "\uC6D4"
19630
19870
  ] }),
@@ -19701,7 +19941,7 @@ function SCalendar({
19701
19941
  }) }),
19702
19942
  legend.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
19703
19943
  /* @__PURE__ */ jsxRuntime.jsx(SDivider, {}),
19704
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center justify-center gap-x-[var(--cmp-datepicker-calendar-legend-group-gap)] gap-y-[4px] text-[11px] leading-[18px]", children: legend.map((item4) => /* @__PURE__ */ jsxRuntime.jsxs(
19944
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center justify-center gap-x-[var(--cmp-datepicker-calendar-legend-group-gap)] gap-y-[4px] typo-field-xs-default", children: legend.map((item4) => /* @__PURE__ */ jsxRuntime.jsxs(
19705
19945
  "span",
19706
19946
  {
19707
19947
  className: "inline-flex items-center gap-[var(--cmp-datepicker-calendar-legend-gap)]",
@@ -19729,10 +19969,10 @@ function SCalendar({
19729
19969
  var MODE_LIST_HEIGHT = 240;
19730
19970
  var MODE_ITEM_HEIGHT = 28;
19731
19971
  var modeListItemClass = (selected, disabled) => cn(
19732
- "flex w-full items-center justify-center gap-[var(--cmp-datepicker-mode-item-gap)] border-0 px-[var(--cmp-datepicker-mode-item-paddingX)] py-[var(--cmp-datepicker-mode-item-paddingY)] text-center font-base text-12 leading-[20px]",
19733
- disabled && "cursor-not-allowed bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-disabled)]",
19734
- !disabled && !selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-default)] hover:bg-[var(--cmp-datepicker-mode-item-bg-hover)] hover:text-[color:var(--cmp-datepicker-mode-item-content-hover)]",
19735
- !disabled && selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-bold text-[color:var(--cmp-datepicker-mode-item-content-selected)]"
19972
+ "flex w-full items-center justify-center gap-[var(--cmp-datepicker-mode-item-gap)] border-0 px-[var(--cmp-datepicker-mode-item-paddingX)] py-[var(--cmp-datepicker-mode-item-paddingY)] text-center",
19973
+ disabled && "typo-field-sm-medium cursor-not-allowed bg-[var(--cmp-datepicker-mode-item-bg-default)] text-[color:var(--cmp-datepicker-mode-item-content-disabled)]",
19974
+ !disabled && !selected && "typo-field-sm-medium cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] text-[color:var(--cmp-datepicker-mode-item-content-default)] hover:bg-[var(--cmp-datepicker-mode-item-bg-hover)] hover:text-[color:var(--cmp-datepicker-mode-item-content-hover)]",
19975
+ !disabled && selected && "typo-field-sm-bold cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] text-[color:var(--cmp-datepicker-mode-item-content-selected)]"
19736
19976
  );
19737
19977
  var MODE_NOUN = {
19738
19978
  date: "\uB0A0\uC9DC",
@@ -20042,9 +20282,9 @@ function SDatePicker({
20042
20282
  const resolvedError = error || ruleError !== "";
20043
20283
  const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
20044
20284
  const baseDims = size === "md" ? {
20045
- padX: 16,
20046
- gap: 12,
20047
- icon: 20,
20285
+ padX: "var(--cmp-datepicker-md-paddingX)",
20286
+ gap: "var(--cmp-datepicker-md-gap)",
20287
+ icon: "var(--cmp-datepicker-md-icon)",
20048
20288
  minW: 104,
20049
20289
  fieldMinW: 168,
20050
20290
  // 값 길이가 YYYY-MM-DD 로 정해져 있어, width="100%" 를 받아도 행 전체로
@@ -20052,19 +20292,20 @@ function SDatePicker({
20052
20292
  // px 가 아니라 등급이라 --cmp-field-width-* 가 바뀌면 함께 따라간다.
20053
20293
  // 이 기본 상한이 걸리적거리는 자리(폭이 이미 좁게 정해진 팝오버 등)는 maxWidth prop 으로 덮는다
20054
20294
  fieldMaxW: "lg",
20295
+ // 요일 폭 계산에 숫자가 필요해 남긴다. 렌더 타이포는 typo 가 맡는다
20055
20296
  fontSize: 14,
20056
- lineHeight: 24,
20057
- radius: 6
20297
+ typo: "typo-field-md-default",
20298
+ radius: "var(--cmp-datepicker-md-radius)"
20058
20299
  } : {
20059
- padX: 12,
20060
- gap: 8,
20061
- icon: 16,
20300
+ padX: "var(--cmp-datepicker-sm-paddingX)",
20301
+ gap: "var(--cmp-datepicker-sm-gap)",
20302
+ icon: "var(--cmp-datepicker-sm-icon)",
20062
20303
  minW: 80,
20063
20304
  fieldMinW: 128,
20064
20305
  fieldMaxW: "md",
20065
20306
  fontSize: 12,
20066
- lineHeight: 20,
20067
- radius: 4
20307
+ typo: "typo-field-sm-default",
20308
+ radius: "var(--cmp-datepicker-sm-radius)"
20068
20309
  };
20069
20310
  const weekdayW = weekday ? weekdaySuffixWidth(baseDims.fontSize) : 0;
20070
20311
  const dims = {
@@ -20135,7 +20376,7 @@ function SDatePicker({
20135
20376
  "flex h-full w-full items-center overflow-hidden bg-transparent outline-none",
20136
20377
  disabled ? "cursor-not-allowed" : "cursor-pointer"
20137
20378
  ),
20138
- style: { padding: `0 ${dims.padX}px`, gap: dims.gap, borderRadius: dims.radius },
20379
+ style: { padding: `0 ${dims.padX}`, gap: dims.gap, borderRadius: dims.radius },
20139
20380
  children: [
20140
20381
  /* @__PURE__ */ jsxRuntime.jsx(
20141
20382
  SIcon,
@@ -20150,11 +20391,9 @@ function SDatePicker({
20150
20391
  "span",
20151
20392
  {
20152
20393
  id: triggerTextId,
20153
- className: "flex-1 truncate text-center",
20394
+ className: cn("flex-1 truncate text-center", dims.typo),
20154
20395
  style: {
20155
20396
  minWidth: dims.minW,
20156
- fontSize: dims.fontSize,
20157
- lineHeight: `${dims.lineHeight}px`,
20158
20397
  color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasValue ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
20159
20398
  },
20160
20399
  children: hasValue ? weekday ? withWeekday(value) : value : resolvedPlaceholder
@@ -20365,7 +20604,7 @@ function RangeCalendar({
20365
20604
  className: cn(!isLeft && "invisible pointer-events-none")
20366
20605
  }
20367
20606
  ),
20368
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex min-w-[40px] flex-1 items-center justify-center text-center text-[14px] font-medium leading-[24px]", children: [
20607
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex min-w-[40px] flex-1 items-center justify-center text-center typo-field-md-medium", children: [
20369
20608
  gy,
20370
20609
  ".",
20371
20610
  String(gm).padStart(2, "0")
@@ -20433,14 +20672,14 @@ function RangeCalendar({
20433
20672
  const hour = which === "start" ? sH : eH;
20434
20673
  const minute = which === "start" ? sM : eM;
20435
20674
  const num = (n, strip) => active && n !== "" ? strip ? String(Number(n)) : n : "-";
20436
- const INPUT_CLS = "h-[var(--cmp-datepicker-sm-height)] w-[40px] rounded-[var(--cmp-datepicker-sm-radius)] border border-solid border-[color:var(--cmp-datepicker-border-default)] bg-[var(--cmp-datepicker-bg-default)] text-center text-[12px] font-medium leading-[20px] text-[color:var(--cmp-datepicker-text-default)] outline-none placeholder:text-[color:var(--cmp-datepicker-text-disabled)] focus:border-[color:var(--cmp-datepicker-border-focus)] disabled:cursor-not-allowed";
20675
+ const INPUT_CLS = "h-[var(--cmp-datepicker-sm-height)] w-[40px] rounded-[var(--cmp-datepicker-sm-radius)] border-[length:var(--cmp-datepicker-border-width)] border-solid border-[color:var(--cmp-datepicker-border-default)] bg-[var(--cmp-datepicker-bg-default)] text-center typo-field-sm-medium text-[color:var(--cmp-datepicker-text-default)] outline-none placeholder:text-[color:var(--cmp-datepicker-text-disabled)] focus:border-[color:var(--cmp-datepicker-border-focus)] disabled:cursor-not-allowed";
20437
20676
  const LABEL = "text-[color:var(--cmp-datepicker-calendar-time-date-label)]";
20438
20677
  const UNIT = "text-[color:var(--cmp-datepicker-calendar-time-date-unit)]";
20439
20678
  return /* @__PURE__ */ jsxRuntime.jsxs(
20440
20679
  "div",
20441
20680
  {
20442
20681
  className: cn(
20443
- "flex flex-1 items-center justify-center gap-[var(--cmp-datepicker-calendar-time-section-gap)] rounded-[var(--cmp-datepicker-calendar-time-radius)] px-[var(--cmp-datepicker-calendar-time-paddingX)] py-[var(--cmp-datepicker-calendar-time-paddingY)] text-[12px] font-medium leading-[20px]",
20682
+ "flex flex-1 items-center justify-center gap-[var(--cmp-datepicker-calendar-time-section-gap)] rounded-[var(--cmp-datepicker-calendar-time-radius)] px-[var(--cmp-datepicker-calendar-time-paddingX)] py-[var(--cmp-datepicker-calendar-time-paddingY)] typo-field-sm-medium",
20444
20683
  active ? "bg-[var(--cmp-datepicker-calendar-time-bg-selected)]" : "bg-[var(--cmp-datepicker-calendar-time-bg-default)]"
20445
20684
  ),
20446
20685
  children: [
@@ -20502,7 +20741,7 @@ function RangeCalendar({
20502
20741
  ),
20503
20742
  children: [
20504
20743
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
20505
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-[var(--cmp-datepicker-calendar-gap)] text-[14px] font-medium leading-[24px]", children: [
20744
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-[var(--cmp-datepicker-calendar-gap)] typo-field-md-medium", children: [
20506
20745
  /* @__PURE__ */ jsxRuntime.jsx(SGhostButton, { icon: "chevronLeft", size: "xxs", ariaLabel: "prevYear", onClick: goPrevYear }),
20507
20746
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex min-w-[40px] items-center justify-center text-center", children: y }),
20508
20747
  /* @__PURE__ */ jsxRuntime.jsx(SGhostButton, { icon: "chevronRight", size: "xxs", ariaLabel: "nextYear", onClick: goNextYear })
@@ -20599,28 +20838,29 @@ function SDateRangePicker({
20599
20838
  const resolvedError = error || ruleError !== "";
20600
20839
  const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
20601
20840
  const baseDims = size === "md" ? {
20602
- padX: 16,
20603
- gap: 12,
20604
- icon: 20,
20841
+ padX: "var(--cmp-datepicker-md-paddingX)",
20842
+ gap: "var(--cmp-datepicker-md-gap)",
20843
+ icon: "var(--cmp-datepicker-md-icon)",
20605
20844
  minW: 104,
20606
20845
  fieldMinW: 260,
20607
20846
  // xl — 값이 `YYYY-MM-DD ~ YYYY-MM-DD` 라 단일 날짜의 두 배가 넘는다.
20608
20847
  // 최소너비(260)가 이미 lg 를 넘으므로 상한도 한 등급 위여야 한다
20609
20848
  fieldMaxW: "xl",
20849
+ // 요일 폭 계산에 숫자가 필요해 남긴다. 렌더 타이포는 typo 가 맡는다
20610
20850
  fontSize: 14,
20611
- lineHeight: 24,
20612
- radius: 6
20851
+ typo: "typo-field-md-default",
20852
+ radius: "var(--cmp-datepicker-md-radius)"
20613
20853
  } : {
20614
- padX: 12,
20615
- gap: 8,
20616
- icon: 16,
20854
+ padX: "var(--cmp-datepicker-sm-paddingX)",
20855
+ gap: "var(--cmp-datepicker-sm-gap)",
20856
+ icon: "var(--cmp-datepicker-sm-icon)",
20617
20857
  minW: 80,
20618
20858
  fieldMinW: 216,
20619
20859
  // lg — 최소너비 216 이 md 를 넘어 md 로는 담기지 않는다
20620
20860
  fieldMaxW: "lg",
20621
20861
  fontSize: 12,
20622
- lineHeight: 20,
20623
- radius: 4
20862
+ typo: "typo-field-sm-default",
20863
+ radius: "var(--cmp-datepicker-sm-radius)"
20624
20864
  };
20625
20865
  const weekdayW = showWeekday ? weekdaySuffixWidth(baseDims.fontSize) * 2 : 0;
20626
20866
  const dims = {
@@ -20697,7 +20937,7 @@ function SDateRangePicker({
20697
20937
  "flex h-full w-full items-center overflow-hidden bg-transparent outline-none",
20698
20938
  disabled ? "cursor-not-allowed" : "cursor-pointer"
20699
20939
  ),
20700
- style: { padding: `0 ${dims.padX}px`, gap: dims.gap, borderRadius: dims.radius },
20940
+ style: { padding: `0 ${dims.padX}`, gap: dims.gap, borderRadius: dims.radius },
20701
20941
  children: [
20702
20942
  /* @__PURE__ */ jsxRuntime.jsx(
20703
20943
  SIcon,
@@ -20714,12 +20954,11 @@ function SDateRangePicker({
20714
20954
  id: triggerTextId,
20715
20955
  className: cn(
20716
20956
  "flex-1 items-center",
20957
+ dims.typo,
20717
20958
  hasDisplay ? "flex" : "block truncate text-center"
20718
20959
  ),
20719
20960
  style: {
20720
20961
  minWidth: dims.minW,
20721
- fontSize: dims.fontSize,
20722
- lineHeight: `${dims.lineHeight}px`,
20723
20962
  color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasDisplay ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
20724
20963
  },
20725
20964
  children: hasDisplay ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -20874,8 +21113,9 @@ var SChipImpl = /* @__PURE__ */ react.forwardRef(function SChip({
20874
21113
  {
20875
21114
  "aria-disabled": disabled ? "true" : void 0,
20876
21115
  className: cn(
20877
- "box-border inline-flex h-[var(--cmp-chip-height)] max-w-full items-center justify-center gap-[var(--cmp-chip-gap)] overflow-hidden whitespace-nowrap border-[length:var(--cmp-chip-border-width)] border-solid px-[var(--cmp-chip-paddingX)] text-[12px] leading-[20px] select-none",
20878
- editing ? "font-normal" : "font-medium",
21116
+ "box-border inline-flex h-[var(--cmp-chip-height)] max-w-full items-center justify-center gap-[var(--cmp-chip-gap)] overflow-hidden whitespace-nowrap border-[length:var(--cmp-chip-border-width)] border-solid px-[var(--cmp-chip-paddingX)] select-none",
21117
+ // chip.typography.focus / .default
21118
+ editing ? "typo-control-xs-default" : "typo-control-xs-medium",
20879
21119
  disabled ? "cursor-not-allowed" : "",
20880
21120
  className
20881
21121
  ),
@@ -21047,7 +21287,7 @@ function SFilePicker({
21047
21287
  const resolvedError = error || ruleError !== "";
21048
21288
  const resolvedStatus = status ?? (rules?.length ? ruleError !== "" ? "error" : void 0 : void 0);
21049
21289
  const padX = size === "md" ? "var(--cmp-filepicker-md-paddingX)" : "var(--cmp-filepicker-sm-paddingX)";
21050
- const iconSize = size === "md" ? 20 : 16;
21290
+ const iconSize = size === "md" ? "var(--cmp-filepicker-md-icon)" : "var(--cmp-filepicker-sm-icon)";
21051
21291
  const gapCls = size === "md" ? "gap-[var(--cmp-filepicker-md-gap)]" : "gap-[var(--cmp-filepicker-sm-gap)]";
21052
21292
  const inlinePlaceholder = inline && !disabled && !hasFiles;
21053
21293
  const showListbox = multiple && showMultipleListBox;
@@ -21101,7 +21341,8 @@ function SFilePicker({
21101
21341
  {
21102
21342
  id: displayTextId,
21103
21343
  className: cn(
21104
- "min-w-0 flex-1 truncate text-[12px]",
21344
+ "min-w-0 flex-1 truncate",
21345
+ size === "md" ? "typo-field-md-default" : "typo-field-sm-default",
21105
21346
  inlinePlaceholder && "text-[color:var(--cmp-filepicker-text-placeholder)] transition-colors group-hover/filepicker:text-[color:var(--cmp-filepicker-text-default)]"
21106
21347
  ),
21107
21348
  style: inlinePlaceholder ? void 0 : {
@@ -21275,10 +21516,10 @@ function SKeyValueTable({
21275
21516
  skipOccupied();
21276
21517
  maxCols = Math.max(maxCols, col, occupied.length);
21277
21518
  });
21278
- const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[8px] rounded-t-none" : "rounded-[8px]";
21519
+ const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[var(--cmp-table-radius)] rounded-t-none" : "rounded-[var(--cmp-table-radius)]";
21279
21520
  const frameClass = cn(
21280
21521
  "overflow-hidden",
21281
- bordered && "border border-solid border-[color:var(--cmp-table-border-color)]",
21522
+ bordered && "border-[length:var(--cmp-table-border-width)] border-solid border-[color:var(--cmp-table-border-color)]",
21282
21523
  radiusClass
21283
21524
  );
21284
21525
  const table = /* @__PURE__ */ jsxRuntime.jsxs(
@@ -21314,7 +21555,7 @@ function SKeyValueTable({
21314
21555
  paddingBottom: cellPadY
21315
21556
  },
21316
21557
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full w-full items-center justify-between gap-[var(--cmp-table-header-gap)]", children: [
21317
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-[8px]", children: [
21558
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-[var(--cmp-table-content-gap)]", children: [
21318
21559
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[12px] font-bold leading-[20px] text-[color:var(--sys-color-fg-primary)]", children: f.label }),
21319
21560
  f.required && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "asterisk", size: 12, color: "var(--sys-color-fg-accent)" })
21320
21561
  ] }),
@@ -23422,22 +23663,15 @@ function SToast({
23422
23663
  ...style
23423
23664
  },
23424
23665
  children: [
23425
- icon && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: 16, color: iconColor }),
23426
- /* @__PURE__ */ jsxRuntime.jsx(
23427
- "span",
23428
- {
23429
- className: "text-[14px] font-medium leading-[24px] text-nowrap",
23430
- style: { color: content },
23431
- children: message
23432
- }
23433
- ),
23666
+ icon && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: "var(--cmp-toast-icon)", color: iconColor }),
23667
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-feedback-md-medium text-nowrap", style: { color: content }, children: message }),
23434
23668
  link && /* @__PURE__ */ jsxRuntime.jsx(
23435
23669
  "a",
23436
23670
  {
23437
23671
  href: link,
23438
23672
  target: "_blank",
23439
23673
  rel: "noopener noreferrer",
23440
- className: "text-[14px] font-bold leading-[24px] underline text-nowrap",
23674
+ className: "typo-feedback-md-underline text-nowrap",
23441
23675
  style: { color: linkColor },
23442
23676
  children: linkLabel || link
23443
23677
  }
@@ -23980,9 +24214,9 @@ var SForm = /* @__PURE__ */ react.forwardRef(function SForm2({ formClassName, on
23980
24214
  ) });
23981
24215
  });
23982
24216
  var SIZE_CONFIG2 = {
23983
- xs: { fontSize: 12, lineHeight: 20, radius: "var(--cmp-radioButton-radius-sm)" },
23984
- sm: { fontSize: 12, lineHeight: 20, radius: "var(--cmp-radioButton-radius-sm)" },
23985
- md: { fontSize: 14, lineHeight: 24, radius: "var(--cmp-radioButton-radius-md)" }
24217
+ xs: { typo: "typo-control-xs-medium", radius: "var(--cmp-radioButton-radius-sm)" },
24218
+ sm: { typo: "typo-control-xs-medium", radius: "var(--cmp-radioButton-radius-sm)" },
24219
+ md: { typo: "typo-control-sm-default", radius: "var(--cmp-radioButton-radius-md)" }
23986
24220
  };
23987
24221
  function SRadioButton({
23988
24222
  options = [],
@@ -24031,8 +24265,9 @@ function SRadioButton({
24031
24265
  onFocus: tooltip ? () => setHoveredValue(o.value) : void 0,
24032
24266
  onBlur: tooltip ? () => setHoveredValue(null) : void 0,
24033
24267
  className: cn(
24034
- "relative box-border grow inline-flex items-center justify-center whitespace-nowrap border border-solid font-medium transition-colors",
24035
- first ? "" : "-ml-px",
24268
+ "relative box-border grow inline-flex items-center justify-center whitespace-nowrap border-(length:--cmp-radioButton-border-width) border-solid transition-colors",
24269
+ s.typo,
24270
+ first ? "" : "ml-(--cmp-radioButton-group-gap)",
24036
24271
  selected ? "z-10" : "",
24037
24272
  !od && !ro && !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",
24038
24273
  od ? "cursor-not-allowed" : ro ? "cursor-default" : "cursor-pointer"
@@ -24040,8 +24275,6 @@ function SRadioButton({
24040
24275
  style: {
24041
24276
  height: `var(--cmp-radioButton-${size}-height)`,
24042
24277
  padding: `0 var(--cmp-radioButton-${size}-paddingX)`,
24043
- fontSize: `${s.fontSize}px`,
24044
- lineHeight: `${s.lineHeight}px`,
24045
24278
  borderRadius: [
24046
24279
  first ? s.radius : "0",
24047
24280
  last ? s.radius : "0",
@@ -24078,6 +24311,7 @@ function SRadioCard({
24078
24311
  value,
24079
24312
  label,
24080
24313
  subtitle,
24314
+ children,
24081
24315
  tag,
24082
24316
  disabled = false,
24083
24317
  name,
@@ -24105,72 +24339,85 @@ function SRadioCard({
24105
24339
  };
24106
24340
  const textColor = disabled ? "text-(--sys-color-disabled-text)" : null;
24107
24341
  return /* @__PURE__ */ jsxRuntime.jsxs(
24108
- "label",
24342
+ "div",
24109
24343
  {
24110
- ...cardInteractiveProps,
24111
- "aria-disabled": disabled || void 0,
24112
24344
  className: cn(
24113
- "box-border flex w-full flex-col rounded-(--cmp-radioCard-radius) border-(length:--cmp-radioCard-border-width) border-solid px-(--cmp-radioCard-paddingX) py-(--cmp-radioCard-paddingY) transition-colors",
24114
- disabled ? "cursor-not-allowed border-(--cmp-radioCard-border-default) bg-(--cmp-radioCard-bg-disabled)" : checked ? "cursor-pointer border-(--cmp-radioCard-border-selected) bg-(--cmp-radioCard-bg-selected)" : "cursor-pointer border-(--cmp-radioCard-border-default) bg-(--cmp-radioCard-bg-default) hover:border-(--cmp-radioCard-border-hover) hover:bg-(--cmp-radioCard-bg-hover)",
24345
+ "box-border flex w-full flex-col rounded-(--cmp-radioCard-radius) border-(length:--cmp-radioCard-border-width) border-solid transition-colors",
24346
+ disabled ? "border-(--cmp-radioCard-border-default) bg-(--cmp-radioCard-bg-disabled)" : checked ? "border-(--cmp-radioCard-border-selected) bg-(--cmp-radioCard-bg-selected)" : "border-(--cmp-radioCard-border-default) bg-(--cmp-radioCard-bg-default) hover:border-(--cmp-radioCard-border-hover) hover:bg-(--cmp-radioCard-bg-hover)",
24115
24347
  className
24116
24348
  ),
24117
24349
  style,
24118
24350
  children: [
24119
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-(--cmp-radioCard-gap)", children: [
24120
- native && /* @__PURE__ */ jsxRuntime.jsx(
24121
- "input",
24122
- {
24123
- type: "radio",
24124
- name,
24125
- value: valStr,
24126
- checked,
24127
- disabled,
24128
- onChange: () => onValueChange?.(val),
24129
- className: "sr-only"
24130
- }
24131
- ),
24132
- /* @__PURE__ */ jsxRuntime.jsx(
24133
- "span",
24134
- {
24135
- className: "flex h-(--cmp-radio-size) w-(--cmp-radio-size) shrink-0 items-center justify-center rounded-(--cmp-radio-radius) border-(length:--cmp-radio-borderWidth) border-solid border-(--rc-dot-border) bg-(--rc-dot-bg)",
24136
- style: {
24137
- "--rc-dot-bg": disabled ? "var(--cmp-radio-bg-disabled)" : "var(--cmp-radio-bg-default)",
24138
- "--rc-dot-border": disabled ? "var(--cmp-radio-border-disabled)" : checked ? "var(--cmp-radio-border-active)" : "var(--cmp-radio-border-default)"
24139
- },
24140
- children: checked && /* @__PURE__ */ jsxRuntime.jsx(
24351
+ /* @__PURE__ */ jsxRuntime.jsxs(
24352
+ "label",
24353
+ {
24354
+ ...cardInteractiveProps,
24355
+ "aria-disabled": disabled || void 0,
24356
+ className: cn(
24357
+ "box-border flex w-full flex-col px-(--cmp-radioCard-paddingX) py-(--cmp-radioCard-paddingY)",
24358
+ disabled ? "cursor-not-allowed" : "cursor-pointer"
24359
+ ),
24360
+ children: [
24361
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-(--cmp-radioCard-gap)", children: [
24362
+ native && /* @__PURE__ */ jsxRuntime.jsx(
24363
+ "input",
24364
+ {
24365
+ type: "radio",
24366
+ name,
24367
+ value: valStr,
24368
+ checked,
24369
+ disabled,
24370
+ onChange: () => onValueChange?.(val),
24371
+ className: "sr-only"
24372
+ }
24373
+ ),
24374
+ /* @__PURE__ */ jsxRuntime.jsx(
24375
+ "span",
24376
+ {
24377
+ className: "flex h-(--cmp-radio-size) w-(--cmp-radio-size) shrink-0 items-center justify-center rounded-(--cmp-radio-radius) border-(length:--cmp-radio-borderWidth) border-solid border-(--rc-dot-border) bg-(--rc-dot-bg)",
24378
+ style: {
24379
+ "--rc-dot-bg": disabled ? "var(--cmp-radio-bg-disabled)" : "var(--cmp-radio-bg-default)",
24380
+ "--rc-dot-border": disabled ? "var(--cmp-radio-border-disabled)" : checked ? "var(--cmp-radio-border-active)" : "var(--cmp-radio-border-default)"
24381
+ },
24382
+ children: checked && /* @__PURE__ */ jsxRuntime.jsx(
24383
+ "span",
24384
+ {
24385
+ className: "h-(--cmp-radio-dot-size) w-(--cmp-radio-dot-size) rounded-(--cmp-radio-radius) bg-(--rc-dot-fill)",
24386
+ style: {
24387
+ "--rc-dot-fill": disabled ? "var(--cmp-radio-dot-disabled)" : "var(--cmp-radio-dot-default)"
24388
+ }
24389
+ }
24390
+ )
24391
+ }
24392
+ ),
24393
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("grid min-w-0", textColor ?? "text-(--cmp-radioCard-label-color)"), children: [
24394
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "typo-body-md-bold invisible", style: { gridArea: "1 / 1" }, children: label }),
24395
+ /* @__PURE__ */ jsxRuntime.jsx(
24396
+ "span",
24397
+ {
24398
+ className: checked ? "typo-body-md-bold" : "typo-body-md-semibold",
24399
+ style: { gridArea: "1 / 1" },
24400
+ children: label
24401
+ }
24402
+ )
24403
+ ] }),
24404
+ tag && /* @__PURE__ */ jsxRuntime.jsx(STag, { ...tag, size: "xs", className: "ml-auto" })
24405
+ ] }),
24406
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(
24141
24407
  "span",
24142
24408
  {
24143
- className: "h-(--cmp-radio-dot-size) w-(--cmp-radio-dot-size) rounded-(--cmp-radio-radius) bg-(--rc-dot-fill)",
24144
- style: {
24145
- "--rc-dot-fill": disabled ? "var(--cmp-radio-dot-disabled)" : "var(--cmp-radio-dot-default)"
24146
- }
24409
+ className: cn(
24410
+ "typo-body-sm-default pl-(--cmp-radioCard-subtitle-paddingLeft)",
24411
+ textColor ?? "text-(--cmp-radioCard-subtitle-color)"
24412
+ ),
24413
+ children: subtitle
24147
24414
  }
24148
24415
  )
24149
- }
24150
- ),
24151
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("grid min-w-0", textColor ?? "text-(--cmp-radioCard-label-color)"), children: [
24152
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "typo-body-md-bold invisible", style: { gridArea: "1 / 1" }, children: label }),
24153
- /* @__PURE__ */ jsxRuntime.jsx(
24154
- "span",
24155
- {
24156
- className: checked ? "typo-body-md-bold" : "typo-body-md-semibold",
24157
- style: { gridArea: "1 / 1" },
24158
- children: label
24159
- }
24160
- )
24161
- ] }),
24162
- tag && /* @__PURE__ */ jsxRuntime.jsx(STag, { ...tag, size: "xs", className: "ml-auto" })
24163
- ] }),
24164
- subtitle && /* @__PURE__ */ jsxRuntime.jsx(
24165
- "span",
24166
- {
24167
- className: cn(
24168
- "typo-body-sm-default pl-(--cmp-radioCard-subtitle-paddingLeft)",
24169
- textColor ?? "text-(--cmp-radioCard-subtitle-color)"
24170
- ),
24171
- children: subtitle
24416
+ ]
24172
24417
  }
24173
- )
24418
+ ),
24419
+ children != null && children !== false && // 라벨 왼쪽 끝(카드 여백 + 서브타이틀 들여쓰기)에 맞춘다. 서브타이틀과의 간격은 label 의 아래 여백이다
24420
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "box-border w-full pr-(--cmp-radioCard-paddingX) pb-(--cmp-radioCard-paddingY) pl-[calc(var(--cmp-radioCard-paddingX)+var(--cmp-radioCard-subtitle-paddingLeft))]", children })
24174
24421
  ]
24175
24422
  }
24176
24423
  );
@@ -24205,7 +24452,8 @@ function SRadioCardGroup({
24205
24452
  tag: o.tag,
24206
24453
  name: groupName,
24207
24454
  disabled: disabled || o.disabled,
24208
- onValueChange
24455
+ onValueChange,
24456
+ children: o.content
24209
24457
  },
24210
24458
  String(o.value)
24211
24459
  ))
@@ -26544,6 +26792,7 @@ var CHIPFILTER = {
26544
26792
  dividerHeight: "var(--cmp-chipFilter-divider-height)",
26545
26793
  chipHeight: "var(--cmp-chipFilter-chip-height)",
26546
26794
  chipRadius: "var(--cmp-chipFilter-chip-radius)",
26795
+ chipPaddingX: "var(--cmp-chipFilter-chip-paddingX)",
26547
26796
  chipGap: "var(--cmp-chipFilter-chip-gap)",
26548
26797
  chipDefaultBg: "var(--cmp-chipFilter-chip-default-bg)",
26549
26798
  chipDefaultBorder: "var(--cmp-chipFilter-chip-default-border)",
@@ -26554,7 +26803,7 @@ var CHIPFILTER = {
26554
26803
  chipAppliedBg: "var(--cmp-chipFilter-chip-applied-bg)",
26555
26804
  chipAppliedBorder: "var(--cmp-chipFilter-chip-applied-border)",
26556
26805
  chipAppliedLabel: "var(--cmp-chipFilter-chip-applied-text-label)",
26557
- chipAppliedValue: "var(--color-brilliantblue-80)",
26806
+ chipAppliedValue: "var(--cmp-chipFilter-chip-applied-text-data)",
26558
26807
  chipDisabledBg: "var(--cmp-chipFilter-chip-disabled-bg)",
26559
26808
  chipDisabledBorder: "var(--cmp-chipFilter-chip-disabled-border)",
26560
26809
  chipDisabledText: "var(--cmp-chipFilter-chip-disabled-text)",
@@ -27189,20 +27438,13 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
27189
27438
  onValueChange: (next) => emitValueAndSearch(field.key, next)
27190
27439
  }),
27191
27440
  addable && !disabled && !field.disabled && showClear && /* @__PURE__ */ jsxRuntime.jsx(
27192
- "button",
27441
+ SGhostButton,
27193
27442
  {
27194
- type: "button",
27195
- "aria-label": `${field.label} \uD544\uD130 \uC81C\uAC70`,
27196
- className: "inline-flex size-[16px] shrink-0 items-center justify-center rounded-[var(--cmp-ghostButton-radius-sm)] border-none bg-transparent p-0",
27197
- onClick: handleClear,
27198
- children: /* @__PURE__ */ jsxRuntime.jsx(
27199
- SIcon,
27200
- {
27201
- name: "close",
27202
- size: 12,
27203
- color: "var(--cmp-ghostButton-default-content)"
27204
- }
27205
- )
27443
+ icon: "close",
27444
+ size: "xxs",
27445
+ ariaLabel: `${field.label} \uD544\uD130 \uC81C\uAC70`,
27446
+ className: "shrink-0",
27447
+ onClick: handleClear
27206
27448
  }
27207
27449
  )
27208
27450
  ] }, field.key) : /* @__PURE__ */ jsxRuntime.jsx(
@@ -27245,7 +27487,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
27245
27487
  {
27246
27488
  type: "button",
27247
27489
  disabled: disabled || inactiveFields.length === 0,
27248
- className: "inline-flex shrink-0 cursor-pointer items-center justify-center gap-[var(--cmp-chipFilter-addButton-gap)] whitespace-nowrap border border-solid bg-[var(--cmp-chipFilter-addButton-bg)] px-[var(--cmp-chipFilter-addButton-paddingX)] text-[12px] font-medium leading-[20px] outline-none disabled:cursor-not-allowed",
27490
+ className: "inline-flex shrink-0 cursor-pointer items-center justify-center gap-[var(--cmp-chipFilter-addButton-gap)] whitespace-nowrap border border-solid bg-[var(--cmp-chipFilter-addButton-bg)] px-[var(--cmp-chipFilter-addButton-paddingX)] typo-control-xs-medium outline-none disabled:cursor-not-allowed",
27249
27491
  style: {
27250
27492
  minHeight: "var(--cmp-chipFilter-addButton-height)" ,
27251
27493
  borderRadius: "var(--cmp-chipFilter-addButton-radius)" ,
@@ -27257,7 +27499,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
27257
27499
  SIcon,
27258
27500
  {
27259
27501
  name: "add",
27260
- size: 12,
27502
+ size: "var(--cmp-chipFilter-addButton-icon)",
27261
27503
  color: disabled || inactiveFields.length === 0 ? CHIPFILTER.addTextDisabled : CHIPFILTER.addText
27262
27504
  }
27263
27505
  ),
@@ -27293,9 +27535,9 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
27293
27535
  onClick: reset,
27294
27536
  className: cn(
27295
27537
  "shrink-0",
27296
- // 부모 flex gap(6px)은 칩 사이 간격 기준이라, 필터 추가 버튼과의 12px 간격을 맞추려면
27297
- // 부족한 만큼(12px - gap)을 추가로 띄운다. 필터 추가가 없을 땐 divider와 이미 12px이라 불필요.
27298
- hasAddButton && "ml-[calc(12px-var(--cmp-chipFilter-chip-group))]"
27538
+ // 부모 flex gap(chip-group)은 칩 사이 간격 기준이라, 필터 추가 버튼과의 bar-gap 간격을 맞추려면
27539
+ // 부족한 만큼(bar-gap - chip-group)을 추가로 띄운다. 필터 추가가 없을 땐 divider와 이미 bar-gap이라 불필요.
27540
+ hasAddButton && "ml-[calc(var(--cmp-chipFilter-bar-gap)_-_var(--cmp-chipFilter-chip-group))]"
27299
27541
  )
27300
27542
  }
27301
27543
  )
@@ -27349,7 +27591,7 @@ function Divider({ inset, top } = {}) {
27349
27591
  className: cn(
27350
27592
  "inline-flex w-px shrink-0 bg-[var(--chipfilter-bar-border)]",
27351
27593
  top ? "mt-[2px] self-start" : "my-auto",
27352
- inset && "mx-[calc(12px-var(--cmp-chipFilter-chip-group))]"
27594
+ inset && "mx-[calc(var(--cmp-chipFilter-bar-gap)_-_var(--cmp-chipFilter-chip-group))]"
27353
27595
  ),
27354
27596
  style: { height: "var(--chipfilter-divider-height)" }
27355
27597
  }
@@ -27389,87 +27631,97 @@ function FilterChip({
27389
27631
  const border = disabled ? CHIPFILTER.chipDisabledBorder : warning ? CHIPFILTER.chipWarningBorder : applied ? active ? "var(--color-blue-strong)" : CHIPFILTER.chipAppliedBorder : active ? CHIPFILTER.chipActiveBorder : CHIPFILTER.chipDefaultBorder;
27390
27632
  const background = disabled ? CHIPFILTER.chipDisabledBg : applied ? CHIPFILTER.chipAppliedBg : CHIPFILTER.chipDefaultBg;
27391
27633
  const textColor = disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipDefaultText;
27634
+ const hasClear = !disabled && showClear && (applied || showClearWhenEmpty);
27392
27635
  return /* @__PURE__ */ jsxRuntime.jsxs(
27393
- "button",
27636
+ "div",
27394
27637
  {
27395
- ref: refCallback,
27396
- type: "button",
27397
- disabled,
27398
- "aria-expanded": active,
27399
27638
  onPointerDown: (event) => event.stopPropagation(),
27400
- onClick: onOpen,
27401
- className: "group/chip-filter inline-flex max-w-full shrink-0 cursor-pointer items-center justify-center whitespace-nowrap border border-solid px-[var(--cmp-chipFilter-chip-paddingX)] text-[12px] leading-[20px] outline-none disabled:cursor-not-allowed",
27639
+ className: "inline-flex max-w-full shrink-0 items-stretch whitespace-nowrap border border-solid",
27402
27640
  style: {
27403
27641
  minHeight: CHIPFILTER.chipHeight,
27404
27642
  gap: CHIPFILTER.chipGap,
27405
27643
  borderRadius: CHIPFILTER.chipRadius,
27406
27644
  borderColor: border,
27407
27645
  background,
27408
- color: textColor
27646
+ paddingRight: hasClear ? CHIPFILTER.chipPaddingX : void 0
27409
27647
  },
27410
27648
  children: [
27411
- field.required && /* @__PURE__ */ jsxRuntime.jsx(
27412
- SIcon,
27649
+ /* @__PURE__ */ jsxRuntime.jsxs(
27650
+ "button",
27413
27651
  {
27414
- name: "asterisk",
27415
- size: 12,
27416
- color: disabled ? CHIPFILTER.chipDisabledText : "var(--cmp-tag-darkblue-content)"
27652
+ ref: refCallback,
27653
+ type: "button",
27654
+ disabled,
27655
+ "aria-expanded": active,
27656
+ onClick: onOpen,
27657
+ className: "inline-flex min-w-0 cursor-pointer items-center justify-center border-none bg-transparent p-0 typo-body-sm-default outline-none disabled:cursor-not-allowed",
27658
+ style: {
27659
+ gap: CHIPFILTER.chipGap,
27660
+ paddingLeft: CHIPFILTER.chipPaddingX,
27661
+ paddingRight: hasClear ? void 0 : CHIPFILTER.chipPaddingX,
27662
+ color: textColor
27663
+ },
27664
+ children: [
27665
+ field.required && /* @__PURE__ */ jsxRuntime.jsx(
27666
+ SIcon,
27667
+ {
27668
+ name: "asterisk",
27669
+ size: "var(--cmp-chipFilter-chip-icon-essential)",
27670
+ color: disabled ? CHIPFILTER.chipDisabledText : "var(--cmp-tag-darkblue-content)"
27671
+ }
27672
+ ),
27673
+ applied ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex min-w-0 items-center gap-[4px] truncate", children: [
27674
+ /* @__PURE__ */ jsxRuntime.jsx(
27675
+ "span",
27676
+ {
27677
+ className: "typo-body-sm-bold",
27678
+ style: {
27679
+ color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedLabel
27680
+ },
27681
+ children: field.label
27682
+ }
27683
+ ),
27684
+ /* @__PURE__ */ jsxRuntime.jsx(
27685
+ "span",
27686
+ {
27687
+ style: {
27688
+ color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedLabel
27689
+ },
27690
+ children: ":"
27691
+ }
27692
+ ),
27693
+ /* @__PURE__ */ jsxRuntime.jsx(
27694
+ "span",
27695
+ {
27696
+ className: "min-w-0 truncate typo-body-sm-bold",
27697
+ style: {
27698
+ color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedValue
27699
+ },
27700
+ children: valueText
27701
+ }
27702
+ )
27703
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
27704
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("min-w-0 truncate", active && "typo-body-sm-bold"), children: field.label }),
27705
+ /* @__PURE__ */ jsxRuntime.jsx(
27706
+ SIcon,
27707
+ {
27708
+ name: "caretDown",
27709
+ size: "var(--cmp-chipFilter-chip-icon-caret)",
27710
+ color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipCaret
27711
+ }
27712
+ )
27713
+ ] })
27714
+ ]
27417
27715
  }
27418
27716
  ),
27419
- applied ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex min-w-0 items-center gap-[4px] truncate", children: [
27420
- /* @__PURE__ */ jsxRuntime.jsx(
27421
- "span",
27422
- {
27423
- className: "font-bold",
27424
- style: { color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedLabel },
27425
- children: field.label
27426
- }
27427
- ),
27428
- /* @__PURE__ */ jsxRuntime.jsx(
27429
- "span",
27430
- {
27431
- style: { color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedLabel },
27432
- children: ":"
27433
- }
27434
- ),
27435
- /* @__PURE__ */ jsxRuntime.jsx(
27436
- "span",
27437
- {
27438
- className: "min-w-0 truncate font-bold",
27439
- style: { color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedValue },
27440
- children: valueText
27441
- }
27442
- )
27443
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
27444
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("min-w-0 truncate", active && "font-bold"), children: field.label }),
27445
- /* @__PURE__ */ jsxRuntime.jsx(
27446
- SIcon,
27447
- {
27448
- name: "caretDown",
27449
- size: 12,
27450
- color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipCaret
27451
- }
27452
- )
27453
- ] }),
27454
- !disabled && showClear && (applied || showClearWhenEmpty) && /* @__PURE__ */ jsxRuntime.jsx(
27455
- "span",
27717
+ hasClear && /* @__PURE__ */ jsxRuntime.jsx(
27718
+ SGhostButton,
27456
27719
  {
27457
- role: "button",
27458
- tabIndex: 0,
27459
- "aria-label": `${field.label} \uD544\uD130 \uC9C0\uC6B0\uAE30`,
27460
- className: "inline-flex size-[16px] items-center justify-center rounded-[var(--cmp-ghostButton-radius-sm)]",
27461
- onClick: (event) => {
27462
- event.preventDefault();
27463
- event.stopPropagation();
27464
- onClear();
27465
- },
27466
- onKeyDown: (event) => {
27467
- if (event.key !== "Enter" && event.key !== " ") return;
27468
- event.preventDefault();
27469
- event.stopPropagation();
27470
- onClear();
27471
- },
27472
- children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
27720
+ icon: "close",
27721
+ size: "xxs",
27722
+ ariaLabel: `${field.label} \uD544\uD130 \uC9C0\uC6B0\uAE30`,
27723
+ className: "shrink-0 self-center",
27724
+ onClick: onClear
27473
27725
  }
27474
27726
  )
27475
27727
  ]
@@ -27849,47 +28101,18 @@ function InlineDatePresetFilter({
27849
28101
  const badgeBackground = disabled ? CHIPFILTER.chipDisabledBg : CHIPFILTER.chipAppliedBg;
27850
28102
  const badgeLabelColor = disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedLabel;
27851
28103
  const badgeValueColor = disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedValue;
27852
- const badge = applied && /* @__PURE__ */ jsxRuntime.jsxs(
27853
- "span",
27854
- {
27855
- className: "inline-flex shrink-0 items-center gap-[4px] whitespace-nowrap border border-solid px-[var(--cmp-chipFilter-chip-paddingX)] text-[12px] leading-[20px]",
27856
- style: {
27857
- minHeight: CHIPFILTER.chipHeight,
27858
- borderRadius: CHIPFILTER.chipRadius,
27859
- borderColor: badgeBorder,
27860
- background: badgeBackground,
27861
- color: badgeLabelColor,
27862
- cursor: rangeValue && !disabled ? "pointer" : void 0
27863
- },
27864
- children: [
27865
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-bold", children: [
27866
- field.label,
27867
- ":"
27868
- ] }),
27869
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold", style: { color: badgeValueColor }, children: displayValue(field, value) }),
27870
- !disabled && showClear && /* @__PURE__ */ jsxRuntime.jsx(
27871
- "span",
27872
- {
27873
- role: "button",
27874
- tabIndex: 0,
27875
- "aria-label": `${field.label} \uD544\uD130 \uC9C0\uC6B0\uAE30`,
27876
- className: "inline-flex size-[16px] items-center justify-center rounded-[var(--cmp-ghostButton-radius-sm)]",
27877
- onClick: (event) => {
27878
- event.stopPropagation();
27879
- onClear();
27880
- },
27881
- onKeyDown: (event) => {
27882
- if (event.key !== "Enter" && event.key !== " ") return;
27883
- event.preventDefault();
27884
- event.stopPropagation();
27885
- onClear();
27886
- },
27887
- children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
27888
- }
27889
- )
27890
- ]
27891
- }
27892
- );
28104
+ const hasClear = !disabled && showClear;
28105
+ const badgeTextStyle = {
28106
+ paddingLeft: CHIPFILTER.chipPaddingX,
28107
+ paddingRight: hasClear ? void 0 : CHIPFILTER.chipPaddingX
28108
+ };
28109
+ const badgeText = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
28110
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "typo-body-sm-bold", children: [
28111
+ field.label,
28112
+ ":"
28113
+ ] }),
28114
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-body-sm-bold", style: { color: badgeValueColor }, children: displayValue(field, value) })
28115
+ ] });
27893
28116
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-[8px]", children: [
27894
28117
  /* @__PURE__ */ jsxRuntime.jsx(
27895
28118
  SRadioButton,
@@ -27901,43 +28124,71 @@ function InlineDatePresetFilter({
27901
28124
  onValueChange: (next) => selectPreset(String(next))
27902
28125
  }
27903
28126
  ),
27904
- applied && (rangeValue ? (
27905
- // 뱃지 모양은 그대로 두고, 눌렀을 때 캘린더가 열려 기간을 직접 다시 고를 수 있게 한다.
27906
- // 직접 고르면 프리셋 선택은 해제된다.
27907
- /* @__PURE__ */ jsxRuntime.jsxs(RPopover13__namespace.Root, { open: pickerOpen, onOpenChange: setPickerOpen, children: [
27908
- /* @__PURE__ */ jsxRuntime.jsx(RPopover13__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
27909
- "button",
27910
- {
27911
- type: "button",
27912
- disabled,
27913
- className: "border-none bg-transparent p-0 outline-none disabled:cursor-not-allowed",
27914
- children: badge
27915
- }
27916
- ) }),
27917
- /* @__PURE__ */ jsxRuntime.jsx(RPopover13__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
27918
- RPopover13__namespace.Content,
27919
- {
27920
- side: "bottom",
27921
- align: "start",
27922
- sideOffset: 4,
27923
- className: cn("z-50", FLOATING_SLIDE_ANIM),
27924
- children: /* @__PURE__ */ jsxRuntime.jsx(
27925
- RangeCalendar,
27926
- {
27927
- value: rangeValue,
27928
- selectable: field.selectable,
27929
- maxRange: field.maxRange,
27930
- onSelect: (range) => {
27931
- setSelectedId(null);
27932
- onValueChange(range);
27933
- setPickerOpen(false);
28127
+ applied && // 뱃지 모양(테두리·배경)은 바깥이 맡고, 라벨·값 칸과 지우기 × 를 형제로 둔다 — FilterChip 과
28128
+ // 같은 이유로, 캘린더를 여는 버튼 안에 × 를 넣지 않는다.
28129
+ /* @__PURE__ */ jsxRuntime.jsxs(
28130
+ "span",
28131
+ {
28132
+ className: "inline-flex shrink-0 items-stretch gap-[4px] whitespace-nowrap border border-solid typo-body-sm-default",
28133
+ style: {
28134
+ minHeight: CHIPFILTER.chipHeight,
28135
+ borderRadius: CHIPFILTER.chipRadius,
28136
+ borderColor: badgeBorder,
28137
+ background: badgeBackground,
28138
+ color: badgeLabelColor,
28139
+ paddingRight: hasClear ? CHIPFILTER.chipPaddingX : void 0
28140
+ },
28141
+ children: [
28142
+ rangeValue ? (
28143
+ // 눌렀을 때 캘린더가 열려 기간을 직접 다시 고를 수 있게 한다. 직접 고르면 프리셋 선택은 해제된다.
28144
+ /* @__PURE__ */ jsxRuntime.jsxs(RPopover13__namespace.Root, { open: pickerOpen, onOpenChange: setPickerOpen, children: [
28145
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover13__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
28146
+ "button",
28147
+ {
28148
+ type: "button",
28149
+ disabled,
28150
+ className: "inline-flex cursor-pointer items-center gap-[4px] border-none bg-transparent p-0 outline-none disabled:cursor-not-allowed",
28151
+ style: badgeTextStyle,
28152
+ children: badgeText
27934
28153
  }
27935
- }
27936
- )
27937
- }
27938
- ) })
27939
- ] })
27940
- ) : badge)
28154
+ ) }),
28155
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover13__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
28156
+ RPopover13__namespace.Content,
28157
+ {
28158
+ side: "bottom",
28159
+ align: "start",
28160
+ sideOffset: 4,
28161
+ className: cn("z-50", FLOATING_SLIDE_ANIM),
28162
+ children: /* @__PURE__ */ jsxRuntime.jsx(
28163
+ RangeCalendar,
28164
+ {
28165
+ value: rangeValue,
28166
+ selectable: field.selectable,
28167
+ maxRange: field.maxRange,
28168
+ onSelect: (range) => {
28169
+ setSelectedId(null);
28170
+ onValueChange(range);
28171
+ setPickerOpen(false);
28172
+ }
28173
+ }
28174
+ )
28175
+ }
28176
+ ) })
28177
+ ] })
28178
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center gap-[4px]", style: badgeTextStyle, children: badgeText }),
28179
+ hasClear && /* @__PURE__ */ jsxRuntime.jsx(
28180
+ SGhostButton,
28181
+ {
28182
+ icon: "close",
28183
+ size: "xxs",
28184
+ ariaLabel: `${field.label} \uD544\uD130 \uC9C0\uC6B0\uAE30`,
28185
+ className: "shrink-0 self-center",
28186
+ onClick: onClear
28187
+ }
28188
+ )
28189
+ ]
28190
+ }
28191
+ )
27941
28192
  ] });
27942
28193
  }
27943
28194
  var MATCH_MODE_OPTIONS = [
@@ -28026,7 +28277,7 @@ function KeywordEditor({
28026
28277
  /* @__PURE__ */ jsxRuntime.jsx(
28027
28278
  "span",
28028
28279
  {
28029
- className: "shrink-0 whitespace-nowrap text-[12px] font-medium leading-[20px]",
28280
+ className: "shrink-0 whitespace-nowrap typo-body-sm-medium",
28030
28281
  style: { color: CHIPFILTER.listboxLabel },
28031
28282
  children: "\uAC80\uC0C9 \uC870\uAC74 :"
28032
28283
  }
@@ -28086,7 +28337,7 @@ function KeywordEntryRow({
28086
28337
  return /* @__PURE__ */ jsxRuntime.jsxs(
28087
28338
  "div",
28088
28339
  {
28089
- className: "group flex w-full items-center justify-between gap-[8px] text-[12px] leading-[20px]",
28340
+ className: "group flex w-full items-center justify-between gap-[8px] typo-body-sm-default",
28090
28341
  style: {
28091
28342
  paddingTop: CHIPFILTER.itemPaddingY,
28092
28343
  paddingBottom: CHIPFILTER.itemPaddingY,
@@ -28097,13 +28348,13 @@ function KeywordEntryRow({
28097
28348
  children: [
28098
28349
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("min-w-0 truncate", !disabled && "group-hover:font-bold"), children: label }),
28099
28350
  !disabled && /* @__PURE__ */ jsxRuntime.jsx(
28100
- "button",
28351
+ SGhostButton,
28101
28352
  {
28102
- type: "button",
28103
- "aria-label": `${label} \uC0AD\uC81C`,
28104
- className: "invisible inline-flex size-[16px] shrink-0 cursor-pointer items-center justify-center group-hover:visible",
28105
- onClick: onRemove,
28106
- children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
28353
+ icon: "close",
28354
+ size: "xxs",
28355
+ ariaLabel: `${label} \uC0AD\uC81C`,
28356
+ className: "invisible shrink-0 group-hover:visible",
28357
+ onClick: onRemove
28107
28358
  }
28108
28359
  )
28109
28360
  ]
@@ -28112,7 +28363,7 @@ function KeywordEntryRow({
28112
28363
  }
28113
28364
  var OPTION_SEARCH_THRESHOLD = 11;
28114
28365
  var filterFlatOptions = (flat, query) => filterDepthRows(flat, (option) => option.label.toLowerCase().includes(query));
28115
- var depthPaddingLeft = (depth) => depth === 1 ? 12 : depth === 2 ? 20 : 28;
28366
+ var depthPaddingLeft = (depth) => LIST_BOX_ITEM_PADDING_LEFT[depth === 1 ? 1 : depth === 2 ? 2 : 3];
28116
28367
  function OptionList({
28117
28368
  field,
28118
28369
  value,
@@ -28328,14 +28579,14 @@ function OptionCheckbox({ checked, disabled }) {
28328
28579
  "span",
28329
28580
  {
28330
28581
  className: cn(
28331
- "inline-flex size-[16px] shrink-0 items-center justify-center rounded-[2px] border border-solid",
28582
+ "inline-flex size-(--cmp-checkbox-size) shrink-0 items-center justify-center rounded-(--cmp-checkbox-radius) border-(length:--cmp-checkbox-borderWidth) border-solid",
28332
28583
  disabled ? "border-[color:var(--cmp-checkbox-border-disabled)] bg-[var(--cmp-checkbox-bg-disabled)]" : filled ? "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)]"
28333
28584
  ),
28334
28585
  children: filled && /* @__PURE__ */ jsxRuntime.jsx(
28335
28586
  SIcon,
28336
28587
  {
28337
28588
  name: checked === null ? "checkboxIndeterminate" : "checkboxCheck",
28338
- size: 12,
28589
+ size: "var(--cmp-checkbox-icon)",
28339
28590
  color: disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : "var(--cmp-checkbox-checked-icon-default)"
28340
28591
  }
28341
28592
  )
@@ -28380,8 +28631,8 @@ function MenuItem({
28380
28631
  onMouseEnter,
28381
28632
  onClick,
28382
28633
  className: cn(
28383
- "flex w-full min-w-0 cursor-pointer items-center gap-[8px] border-none bg-transparent text-left text-[12px] leading-[20px] outline-none disabled:cursor-not-allowed",
28384
- selected ? "font-bold" : "font-normal",
28634
+ "flex w-full min-w-0 cursor-pointer items-center gap-[8px] border-none bg-transparent text-left outline-none disabled:cursor-not-allowed",
28635
+ selected ? "typo-body-sm-bold" : "typo-body-sm-default",
28385
28636
  !disabled && "hover:font-bold"
28386
28637
  ),
28387
28638
  style: {
@@ -28618,7 +28869,7 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
28618
28869
  labelPosition,
28619
28870
  subLabel,
28620
28871
  labelWidth,
28621
- labelHeight: `calc(var(--cmp-chipInput-${size}-minHeight) + 2px)`,
28872
+ labelHeight: `calc(var(--cmp-chipInput-${size}-minHeight) + var(--cmp-chipInput-borderWidth) * 2)`,
28622
28873
  icon,
28623
28874
  iconColor,
28624
28875
  labelTooltip,
@@ -28703,8 +28954,8 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
28703
28954
  {
28704
28955
  "aria-hidden": true,
28705
28956
  className: cn(
28706
- "invisible col-start-1 row-start-1 whitespace-pre font-normal",
28707
- size === "md" ? "text-14 leading-sd-24" : "text-12 leading-sd-20"
28957
+ "invisible col-start-1 row-start-1 whitespace-pre",
28958
+ size === "md" ? "typo-field-md-default" : "typo-field-sm-default"
28708
28959
  ),
28709
28960
  children: inputValue !== "" ? inputValue : values.length === 0 ? placeholder : ""
28710
28961
  }
@@ -28723,9 +28974,9 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
28723
28974
  "aria-activedescendant": showDropdown && activeIndex >= 0 ? activeOptionId : void 0,
28724
28975
  "aria-autocomplete": "list",
28725
28976
  className: cn(
28726
- "s-chip-input__input col-start-1 row-start-1 w-full border-0 bg-transparent p-0 font-normal text-(--cmp-chip-content-focus) outline-none placeholder:text-(--cmp-chipInput-text-placeholder) disabled:cursor-not-allowed",
28977
+ "s-chip-input__input col-start-1 row-start-1 w-full border-0 bg-transparent p-0 text-(--cmp-chip-content-focus) outline-none placeholder:text-(--cmp-chipInput-text-placeholder) disabled:cursor-not-allowed",
28727
28978
  AUTOFILL_RESET_CLASS,
28728
- size === "md" ? "text-14 leading-sd-24" : "text-12 leading-sd-20"
28979
+ size === "md" ? "typo-field-md-default" : "typo-field-sm-default"
28729
28980
  ),
28730
28981
  style: {
28731
28982
  minWidth: "1ch",
@@ -28895,7 +29146,7 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
28895
29146
  "aria-selected": selected || active,
28896
29147
  tabIndex: -1,
28897
29148
  className: cn(
28898
- "s-chip-input__suggestion-item flex shrink-0 cursor-pointer items-center gap-sd-8 overflow-hidden text-ellipsis whitespace-nowrap px-sd-12 py-sd-4 text-12 leading-sd-20",
29149
+ "s-chip-input__suggestion-item flex shrink-0 cursor-pointer items-center gap-(--cmp-listBoxItem-gap) overflow-hidden text-ellipsis whitespace-nowrap py-(--cmp-listBoxItem-paddingY) pl-(--cmp-listBoxItem-paddingLeft-depth1) pr-(--cmp-listBoxItem-paddingRight) typo-field-sm-default",
28899
29150
  selected ? "cursor-default overflow-visible font-bold text-(--cmp-listBoxItem-content-selected)" : active ? "bg-(--cmp-listBoxItem-bg-hover) font-medium text-(--cmp-listBoxItem-content-hover)" : "text-(--cmp-listBoxItem-content-default)"
28900
29151
  ),
28901
29152
  onMouseDown: (e) => {
@@ -29104,7 +29355,7 @@ var TIMEPICKER_SIZE_CONFIG = {
29104
29355
  gap: V4("sm-gap"),
29105
29356
  icon: V4("sm-icon"),
29106
29357
  radius: V4("sm-radius"),
29107
- // TODO: component.timepicker 토큰에 typography가 추가되면 CSS 변수로 교체한다.
29358
+ typography: "typo-field-sm-default",
29108
29359
  fontSize: 12,
29109
29360
  lineHeight: 20,
29110
29361
  minWidth: 80,
@@ -29117,7 +29368,7 @@ var TIMEPICKER_SIZE_CONFIG = {
29117
29368
  gap: V4("md-gap"),
29118
29369
  icon: V4("md-icon"),
29119
29370
  radius: V4("md-radius"),
29120
- // TODO: component.timepicker 토큰에 typography가 추가되면 CSS 변수로 교체한다.
29371
+ typography: "typo-field-md-default",
29121
29372
  fontSize: 14,
29122
29373
  lineHeight: 24,
29123
29374
  minWidth: 96,
@@ -29448,11 +29699,9 @@ function STimePicker({
29448
29699
  "span",
29449
29700
  {
29450
29701
  id: triggerTextId,
29451
- className: "flex-1 truncate text-center",
29702
+ className: cn("flex-1 truncate text-center", dims.typography),
29452
29703
  style: {
29453
29704
  minWidth: dims.minWidth,
29454
- fontSize: dims.fontSize,
29455
- lineHeight: `${dims.lineHeight}px`,
29456
29705
  color: disabled ? "var(--cmp-timepicker-text-disabled)" : hasValue ? "var(--cmp-timepicker-text-default)" : "var(--cmp-field-hint-color)"
29457
29706
  },
29458
29707
  children: hasValue ? displayText : placeholder
@@ -29556,7 +29805,7 @@ function RangeTimeSelector({
29556
29805
  className: "flex flex-col items-center",
29557
29806
  style: { gap: "var(--cmp-timepicker-selector-range-heading-gap)" },
29558
29807
  children: [
29559
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-nowrap text-center text-[12px] font-bold leading-[20px] text-[var(--cmp-timepicker-selector-range-heading-color)]", children: title }),
29808
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-nowrap text-center typo-field-sm-bold text-[var(--cmp-timepicker-selector-range-heading-color)]", children: title }),
29560
29809
  /* @__PURE__ */ jsxRuntime.jsx(
29561
29810
  TimeListbox,
29562
29811
  {
@@ -29723,11 +29972,9 @@ function STimeRangePicker({
29723
29972
  "span",
29724
29973
  {
29725
29974
  id: triggerTextId,
29726
- className: "flex-1 truncate text-center",
29975
+ className: cn("flex-1 truncate text-center", dims.typography),
29727
29976
  style: {
29728
29977
  minWidth: dims.minWidth,
29729
- fontSize: dims.fontSize,
29730
- lineHeight: `${dims.lineHeight}px`,
29731
29978
  color: disabled ? "var(--cmp-timepicker-text-disabled)" : hasValue ? "var(--cmp-timepicker-text-default)" : "var(--cmp-field-hint-color)"
29732
29979
  },
29733
29980
  children: hasValue ? displayText : placeholder