sellmate-design-system-react 0.1.8 → 0.1.9

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 (104) hide show
  1. package/dist/components/SActionModal/SActionModal.cjs +1 -1
  2. package/dist/components/SActionModal/SActionModal.cjs.map +1 -1
  3. package/dist/components/SActionModal/SActionModal.js +1 -1
  4. package/dist/components/SActionModal/SActionModal.js.map +1 -1
  5. package/dist/components/SBarcodeInput/SBarcodeInput.cjs +218 -209
  6. package/dist/components/SBarcodeInput/SBarcodeInput.cjs.map +1 -1
  7. package/dist/components/SBarcodeInput/SBarcodeInput.js +218 -209
  8. package/dist/components/SBarcodeInput/SBarcodeInput.js.map +1 -1
  9. package/dist/components/SCalendar/SCalendar.cjs +1 -1
  10. package/dist/components/SCalendar/SCalendar.cjs.map +1 -1
  11. package/dist/components/SCalendar/SCalendar.js +1 -1
  12. package/dist/components/SCalendar/SCalendar.js.map +1 -1
  13. package/dist/components/SChip/SChip.cjs +1 -1
  14. package/dist/components/SChip/SChip.cjs.map +1 -1
  15. package/dist/components/SChip/SChip.d.ts +1 -1
  16. package/dist/components/SChip/SChip.js +1 -1
  17. package/dist/components/SChip/SChip.js.map +1 -1
  18. package/dist/components/SChipInput/SChipInput.cjs +235 -221
  19. package/dist/components/SChipInput/SChipInput.cjs.map +1 -1
  20. package/dist/components/SChipInput/SChipInput.js +235 -221
  21. package/dist/components/SChipInput/SChipInput.js.map +1 -1
  22. package/dist/components/SCircleProgress/SCircleProgress.cjs +53 -55
  23. package/dist/components/SCircleProgress/SCircleProgress.cjs.map +1 -1
  24. package/dist/components/SCircleProgress/SCircleProgress.js +53 -55
  25. package/dist/components/SCircleProgress/SCircleProgress.js.map +1 -1
  26. package/dist/components/SDatePicker/SDatePicker.cjs +223 -214
  27. package/dist/components/SDatePicker/SDatePicker.cjs.map +1 -1
  28. package/dist/components/SDatePicker/SDatePicker.js +223 -214
  29. package/dist/components/SDatePicker/SDatePicker.js.map +1 -1
  30. package/dist/components/SDateRangePicker/SDateRangePicker.cjs +298 -263
  31. package/dist/components/SDateRangePicker/SDateRangePicker.cjs.map +1 -1
  32. package/dist/components/SDateRangePicker/SDateRangePicker.js +298 -263
  33. package/dist/components/SDateRangePicker/SDateRangePicker.js.map +1 -1
  34. package/dist/components/SDropdownButton/SDropdownButton.cjs +4 -4
  35. package/dist/components/SDropdownButton/SDropdownButton.cjs.map +1 -1
  36. package/dist/components/SDropdownButton/SDropdownButton.js +4 -4
  37. package/dist/components/SDropdownButton/SDropdownButton.js.map +1 -1
  38. package/dist/components/SField/SField.cjs +218 -21
  39. package/dist/components/SField/SField.cjs.map +1 -1
  40. package/dist/components/SField/SField.d.ts +11 -0
  41. package/dist/components/SField/SField.js +218 -21
  42. package/dist/components/SField/SField.js.map +1 -1
  43. package/dist/components/SFilePicker/SFilePicker.cjs +298 -278
  44. package/dist/components/SFilePicker/SFilePicker.cjs.map +1 -1
  45. package/dist/components/SFilePicker/SFilePicker.d.ts +4 -2
  46. package/dist/components/SFilePicker/SFilePicker.js +298 -278
  47. package/dist/components/SFilePicker/SFilePicker.js.map +1 -1
  48. package/dist/components/SInput/SInput.cjs +218 -209
  49. package/dist/components/SInput/SInput.cjs.map +1 -1
  50. package/dist/components/SInput/SInput.js +218 -209
  51. package/dist/components/SInput/SInput.js.map +1 -1
  52. package/dist/components/SKeyValueTable/SKeyValueTable.cjs +610 -450
  53. package/dist/components/SKeyValueTable/SKeyValueTable.cjs.map +1 -1
  54. package/dist/components/SKeyValueTable/SKeyValueTable.d.ts +3 -1
  55. package/dist/components/SKeyValueTable/SKeyValueTable.js +610 -450
  56. package/dist/components/SKeyValueTable/SKeyValueTable.js.map +1 -1
  57. package/dist/components/SLoadingContainer/SLoadingContainer.cjs +61 -55
  58. package/dist/components/SLoadingContainer/SLoadingContainer.cjs.map +1 -1
  59. package/dist/components/SLoadingContainer/SLoadingContainer.js +61 -55
  60. package/dist/components/SLoadingContainer/SLoadingContainer.js.map +1 -1
  61. package/dist/components/SLoadingContainer/loading.cjs +61 -55
  62. package/dist/components/SLoadingContainer/loading.cjs.map +1 -1
  63. package/dist/components/SLoadingContainer/loading.js +61 -55
  64. package/dist/components/SLoadingContainer/loading.js.map +1 -1
  65. package/dist/components/SLoadingModal/SLoadingModal.cjs +56 -57
  66. package/dist/components/SLoadingModal/SLoadingModal.cjs.map +1 -1
  67. package/dist/components/SLoadingModal/SLoadingModal.js +56 -57
  68. package/dist/components/SLoadingModal/SLoadingModal.js.map +1 -1
  69. package/dist/components/SNumberInput/SNumberInput.cjs +326 -50
  70. package/dist/components/SNumberInput/SNumberInput.cjs.map +1 -1
  71. package/dist/components/SNumberInput/SNumberInput.d.ts +2 -0
  72. package/dist/components/SNumberInput/SNumberInput.js +326 -50
  73. package/dist/components/SNumberInput/SNumberInput.js.map +1 -1
  74. package/dist/components/SPagination/SPagination.cjs +1 -1
  75. package/dist/components/SPagination/SPagination.cjs.map +1 -1
  76. package/dist/components/SPagination/SPagination.js +1 -1
  77. package/dist/components/SPagination/SPagination.js.map +1 -1
  78. package/dist/components/SSelect/SSelect.cjs +67 -32
  79. package/dist/components/SSelect/SSelect.cjs.map +1 -1
  80. package/dist/components/SSelect/SSelect.js +67 -32
  81. package/dist/components/SSelect/SSelect.js.map +1 -1
  82. package/dist/components/STable/STable.cjs +121 -88
  83. package/dist/components/STable/STable.cjs.map +1 -1
  84. package/dist/components/STable/STable.js +121 -88
  85. package/dist/components/STable/STable.js.map +1 -1
  86. package/dist/components/STextarea/STextarea.cjs +218 -21
  87. package/dist/components/STextarea/STextarea.cjs.map +1 -1
  88. package/dist/components/STextarea/STextarea.js +218 -21
  89. package/dist/components/STextarea/STextarea.js.map +1 -1
  90. package/dist/components/SToast/SToastContainer.cjs +3 -3
  91. package/dist/components/SToast/SToastContainer.cjs.map +1 -1
  92. package/dist/components/SToast/SToastContainer.js +3 -3
  93. package/dist/components/SToast/SToastContainer.js.map +1 -1
  94. package/dist/components/STooltip/STooltip.cjs +209 -14
  95. package/dist/components/STooltip/STooltip.cjs.map +1 -1
  96. package/dist/components/STooltip/STooltip.js +209 -14
  97. package/dist/components/STooltip/STooltip.js.map +1 -1
  98. package/dist/index.cjs +432 -260
  99. package/dist/index.cjs.map +1 -1
  100. package/dist/index.js +432 -260
  101. package/dist/index.js.map +1 -1
  102. package/dist/styles.css +51 -27
  103. package/dist/theme.css +4 -2
  104. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -3338,65 +3338,63 @@ var SCircleProgress = react.forwardRef(
3338
3338
  "div",
3339
3339
  {
3340
3340
  ref,
3341
- className: cn("inline-flex flex-col items-center gap-[8px]", className),
3341
+ className: cn(
3342
+ "inline-flex flex-col items-center gap-[var(--cmp-progress-circular-gap)]",
3343
+ className
3344
+ ),
3342
3345
  style,
3343
3346
  children: [
3344
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-[80px] w-[80px]", children: [
3345
- /* @__PURE__ */ jsxRuntime.jsxs(
3346
- "svg",
3347
- {
3348
- viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
3349
- xmlns: "http://www.w3.org/2000/svg",
3350
- className: cn(
3351
- "h-[80px] w-[80px]",
3352
- indeterminate && "origin-center animate-circle-spin"
3347
+ /* @__PURE__ */ jsxRuntime.jsxs(
3348
+ "svg",
3349
+ {
3350
+ viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
3351
+ xmlns: "http://www.w3.org/2000/svg",
3352
+ className: cn("h-[80px] w-[80px]", indeterminate && "origin-center animate-circle-spin"),
3353
+ children: [
3354
+ /* @__PURE__ */ jsxRuntime.jsx(
3355
+ "circle",
3356
+ {
3357
+ cx: c,
3358
+ cy: c,
3359
+ r: RADIUS,
3360
+ fill: "none",
3361
+ strokeWidth: STROKE,
3362
+ style: { stroke: colors.track }
3363
+ }
3353
3364
  ),
3354
- children: [
3355
- /* @__PURE__ */ jsxRuntime.jsx(
3356
- "circle",
3357
- {
3358
- cx: c,
3359
- cy: c,
3360
- r: RADIUS,
3361
- fill: "none",
3362
- strokeWidth: STROKE,
3363
- style: { stroke: colors.track }
3364
- }
3365
- ),
3366
- /* @__PURE__ */ jsxRuntime.jsx(
3367
- "circle",
3368
- {
3369
- cx: c,
3370
- cy: c,
3371
- r: RADIUS,
3372
- fill: "none",
3373
- strokeWidth: STROKE,
3374
- strokeLinecap: "round",
3375
- className: cn(
3376
- "origin-center",
3377
- indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
3378
- ),
3379
- style: {
3380
- stroke: colors.arc,
3381
- ...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
3382
- }
3365
+ /* @__PURE__ */ jsxRuntime.jsx(
3366
+ "circle",
3367
+ {
3368
+ cx: c,
3369
+ cy: c,
3370
+ r: RADIUS,
3371
+ fill: "none",
3372
+ strokeWidth: STROKE,
3373
+ strokeLinecap: "round",
3374
+ className: cn(
3375
+ "origin-center",
3376
+ indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
3377
+ ),
3378
+ style: {
3379
+ stroke: colors.arc,
3380
+ ...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
3383
3381
  }
3384
- )
3385
- ]
3386
- }
3387
- ),
3388
- !indeterminate && /* @__PURE__ */ jsxRuntime.jsxs(
3389
- "span",
3390
- {
3391
- className: "absolute inset-0 flex items-center justify-center text-[16px] font-bold leading-[26px]",
3392
- style: { color: percentColor },
3393
- children: [
3394
- Math.round(v),
3395
- "%"
3396
- ]
3397
- }
3398
- )
3399
- ] }),
3382
+ }
3383
+ )
3384
+ ]
3385
+ }
3386
+ ),
3387
+ !indeterminate && /* @__PURE__ */ jsxRuntime.jsxs(
3388
+ "span",
3389
+ {
3390
+ className: "text-center text-[16px] font-bold leading-[26px]",
3391
+ style: { color: percentColor },
3392
+ children: [
3393
+ Math.round(v),
3394
+ "%"
3395
+ ]
3396
+ }
3397
+ ),
3400
3398
  label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]", children: label })
3401
3399
  ]
3402
3400
  }
@@ -3407,6 +3405,14 @@ var SLoadingContainer = react.forwardRef(
3407
3405
  function SLoadingContainer2({ open = false, message, zIndex = 1200, className, style }, ref) {
3408
3406
  const [mounted2, setMounted] = react.useState(false);
3409
3407
  react.useEffect(() => setMounted(true), []);
3408
+ react.useEffect(() => {
3409
+ if (!open) return;
3410
+ const prev = document.body.style.overflow;
3411
+ document.body.style.overflow = "hidden";
3412
+ return () => {
3413
+ document.body.style.overflow = prev;
3414
+ };
3415
+ }, [open]);
3410
3416
  const innerRef = react.useRef(null);
3411
3417
  const setRef = react.useCallback(
3412
3418
  (node) => {
@@ -3675,15 +3681,15 @@ var sanitizeInlineHtml = (value) => {
3675
3681
  return template.innerHTML;
3676
3682
  };
3677
3683
  var SIZE = {
3678
- xs: { height: 24, paddingX: 8, gap: 6, arrow: 12, fontSize: 12, minWidth: 44, splitMinWidth: 60 },
3684
+ xs: { height: 24, paddingX: 8, gap: 6, arrow: 12, fontSize: 12, minWidth: 64, splitMinWidth: 72 },
3679
3685
  sm: {
3680
3686
  height: 28,
3681
3687
  paddingX: 12,
3682
3688
  gap: 8,
3683
3689
  arrow: 12,
3684
3690
  fontSize: 12,
3685
- minWidth: 70,
3686
- splitMinWidth: 76
3691
+ minWidth: 72,
3692
+ splitMinWidth: 88
3687
3693
  },
3688
3694
  md: {
3689
3695
  height: 36,
@@ -3791,7 +3797,7 @@ var SDropdownButton = react.forwardRef(
3791
3797
  align: "start",
3792
3798
  alignOffset: split ? splitAlignOffset : 0,
3793
3799
  className: cn(
3794
- "z-50 overflow-hidden rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] py-[4px] shadow-normal-sm",
3800
+ "z-50 overflow-hidden rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] shadow-normal-sm",
3795
3801
  !split && "min-w-[var(--radix-dropdown-menu-trigger-width)]",
3796
3802
  FLOATING_SLIDE_ANIM
3797
3803
  ),
@@ -4088,7 +4094,8 @@ var HIDE_DELAY_MS = 100;
4088
4094
  function useBody(content, message = []) {
4089
4095
  if (content != null) return content;
4090
4096
  if (message.length === 0) return null;
4091
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: message.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: line }, i)) });
4097
+ const singleLine = message.length === 1;
4098
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: message.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: singleLine ? "leading-[24px]" : void 0, children: line }, i)) });
4092
4099
  }
4093
4100
  var STooltip = react.forwardRef(function STooltip2({
4094
4101
  content,
@@ -4146,7 +4153,7 @@ var STooltip = react.forwardRef(function STooltip2({
4146
4153
  if (disabled || body == null) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: triggerNode });
4147
4154
  const isHover = trigger === "hover";
4148
4155
  const contentClass = cn(
4149
- "z-50 max-w-xs rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px]",
4156
+ "z-50 max-w-xs rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.1)]",
4150
4157
  FLOATING_SLIDE_ANIM,
4151
4158
  className
4152
4159
  );
@@ -4191,11 +4198,17 @@ var STooltip = react.forwardRef(function STooltip2({
4191
4198
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-[12px]", children: [
4192
4199
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: body }),
4193
4200
  useClose && /* @__PURE__ */ jsxRuntime.jsx(
4194
- RPopover2__namespace.Close,
4201
+ SGhostButton,
4195
4202
  {
4196
- "aria-label": "\uB2EB\uAE30",
4197
- className: "shrink-0 cursor-pointer opacity-70 hover:opacity-100",
4198
- children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 16, color: fg })
4203
+ icon: "close",
4204
+ size: "xs",
4205
+ intent: tooltipType === "default" ? "inverse" : "default",
4206
+ ariaLabel: "\uB2EB\uAE30",
4207
+ className: "shrink-0",
4208
+ onClick: () => {
4209
+ cancelHide();
4210
+ setOpen(false);
4211
+ }
4199
4212
  }
4200
4213
  )
4201
4214
  ] }),
@@ -4760,7 +4773,7 @@ function SActionModal({
4760
4773
  showClose: true,
4761
4774
  width,
4762
4775
  height,
4763
- className: "w-fit min-w-[480px]",
4776
+ className: "w-fit min-w-[480px] min-h-[320px]",
4764
4777
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full min-h-[320px] flex-col", children: [
4765
4778
  /* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex flex-shrink-0 items-center gap-[var(--cmp-overlay-header-gap)] py-[var(--cmp-overlay-header-paddingY)] pl-[var(--cmp-overlay-header-paddingX)] pr-[calc(var(--cmp-overlay-header-paddingX)+20px)]", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-[16px] font-bold leading-[26px] text-[color:var(--cmp-overlay-header-title-color)]", children: modalTitle }) }),
4766
4779
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1 overflow-auto px-[var(--cmp-modal-action-body-paddingX)] pb-[var(--cmp-modal-action-body-paddingBottom)]", children }),
@@ -4792,7 +4805,7 @@ function SActionModal({
4792
4805
  );
4793
4806
  }
4794
4807
  var DEFAULT_MESSAGE = {
4795
- loading: "",
4808
+ loading: "\uC791\uC5C5 \uC9C4\uD589\uC911...",
4796
4809
  error: "\uC791\uC5C5\uC5D0 \uC2E4\uD328\uD558\uC600\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2DC\uB3C4\uD574 \uC8FC\uC138\uC694."
4797
4810
  };
4798
4811
  var DEFAULT_BUTTON_LABEL = {
@@ -4814,6 +4827,7 @@ function SLoadingModal({
4814
4827
  }) {
4815
4828
  const resolvedMessage = message ?? DEFAULT_MESSAGE[state2];
4816
4829
  const lines = Array.isArray(resolvedMessage) ? resolvedMessage : resolvedMessage ? [resolvedMessage] : [];
4830
+ const showButton = useButton || state2 === "error";
4817
4831
  return /* @__PURE__ */ jsxRuntime.jsx(
4818
4832
  SModalContainer,
4819
4833
  {
@@ -4833,7 +4847,7 @@ function SLoadingModal({
4833
4847
  },
4834
4848
  i
4835
4849
  )) }),
4836
- useButton && /* @__PURE__ */ jsxRuntime.jsx(
4850
+ showButton && /* @__PURE__ */ jsxRuntime.jsx(
4837
4851
  SButton,
4838
4852
  {
4839
4853
  color: "neutral",
@@ -5064,7 +5078,7 @@ function SPagination({
5064
5078
  style,
5065
5079
  children: [
5066
5080
  /* @__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 }),
5067
- simple ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-[var(--cmp-pagination-height)] items-center gap-[var(--cmp-pagination-move-gap)] px-[var(--cmp-pagination-paddingX)] text-[12px] font-medium leading-[20px] text-[color:var(--cmp-pagination-item-content-default)]", children: [
5081
+ 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: [
5068
5082
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-[color:var(--cmp-pagination-item-content-selected)]", children: currentPage }),
5069
5083
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "/" }),
5070
5084
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: lastPage })
@@ -5188,8 +5202,8 @@ function useFormField(field) {
5188
5202
  }, [ctx, name]);
5189
5203
  }
5190
5204
  var FIELD_SIZE = {
5191
- sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon: 12 },
5192
- md: { height: 36, radius: 6, fieldGap: 16, labelGap: 8, fontSize: 14, lineHeight: 24, icon: 12 }
5205
+ sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon: 16 },
5206
+ md: { height: 36, radius: 6, fieldGap: 16, labelGap: 8, fontSize: 14, lineHeight: 24, icon: 16 }
5193
5207
  };
5194
5208
  var ALIGN = {
5195
5209
  start: "flex-start",
@@ -5204,6 +5218,7 @@ var SField = react.forwardRef(function SField2({
5204
5218
  labelTooltip = "",
5205
5219
  labelTooltipProps,
5206
5220
  labelWidth,
5221
+ labelHeight,
5207
5222
  size = "sm",
5208
5223
  addonLabel = "",
5209
5224
  addonAlign = "start",
@@ -5218,6 +5233,7 @@ var SField = react.forwardRef(function SField2({
5218
5233
  readOnly = false,
5219
5234
  width,
5220
5235
  multiline = false,
5236
+ borderless = false,
5221
5237
  children,
5222
5238
  className,
5223
5239
  style,
@@ -5251,8 +5267,8 @@ var SField = react.forwardRef(function SField2({
5251
5267
  const resolvedSuccess = status === "pass";
5252
5268
  const showError = resolvedError && errorMessage !== "";
5253
5269
  const interactive = !disabled && !readOnly;
5254
- const borderColor = disabled ? "var(--color-grey-45)" : interactive && focused ? "var(--sys-color-field-border-focus)" : resolvedSuccess ? "var(--sys-color-field-border-success)" : resolvedError ? "var(--sys-color-field-border-danger)" : "var(--sys-color-field-border-default)";
5255
- const bgColor = disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
5270
+ const borderColor = borderless ? "transparent" : disabled ? "var(--color-grey-45)" : interactive && focused ? "var(--sys-color-field-border-focus)" : resolvedSuccess ? "var(--sys-color-field-border-success)" : resolvedError ? "var(--sys-color-field-border-danger)" : "var(--sys-color-field-border-default)";
5271
+ const bgColor = borderless ? "transparent" : disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
5256
5272
  const textColor = disabled ? "var(--color-grey-65)" : readOnly ? "var(--sys-color-field-text-readOnly)" : "var(--sys-color-field-text-default)";
5257
5273
  return /* @__PURE__ */ jsxRuntime.jsx(
5258
5274
  "div",
@@ -5269,7 +5285,7 @@ var SField = react.forwardRef(function SField2({
5269
5285
  {
5270
5286
  className: "flex shrink-0 items-center font-bold text-(--sys-color-field-text-default)",
5271
5287
  style: {
5272
- height: s.height,
5288
+ height: cssLen(labelHeight) ?? s.height,
5273
5289
  marginRight: s.fieldGap,
5274
5290
  width: cssLen(labelWidth),
5275
5291
  fontSize: s.fontSize,
@@ -5295,14 +5311,14 @@ var SField = react.forwardRef(function SField2({
5295
5311
  {
5296
5312
  className: cn(
5297
5313
  "relative box-border flex min-w-0 items-stretch overflow-hidden border border-solid border-(--field-bc)",
5298
- interactive && "hover:border-(--sys-color-field-border-focus) hover:shadow-[0px_0px_4px_0px_#0071ff66] focus-within:border-(--sys-color-field-border-focus) focus-within:shadow-[0px_0px_4px_0px_#0071ff66]",
5314
+ interactive && !borderless && "hover:border-(--sys-color-field-border-focus) hover:shadow-[0px_0px_4px_0px_#0071ff66] focus-within:border-(--sys-color-field-border-focus) focus-within:shadow-[0px_0px_4px_0px_#0071ff66]",
5299
5315
  disabled && "cursor-not-allowed"
5300
5316
  ),
5301
5317
  style: {
5302
5318
  // @ts-expect-error CSS 변수
5303
5319
  "--field-bc": borderColor,
5304
5320
  // focused/hovered prop이 명시된 경우 강조를 즉시 반영
5305
- ...interactive && focused ? { boxShadow: "0px 0px 4px 0px #0071ff66" } : {},
5321
+ ...interactive && !borderless && focused ? { boxShadow: "0px 0px 4px 0px #0071ff66" } : {},
5306
5322
  ...multiline ? { minHeight: s.height } : { height: s.height },
5307
5323
  "width": cssLen(width),
5308
5324
  "borderRadius": s.radius,
@@ -5347,15 +5363,28 @@ function flattenOptions(options, depth = 1) {
5347
5363
  const out = [];
5348
5364
  for (const o of options) {
5349
5365
  const hasChildren = Array.isArray(o.children) && o.children.length > 0;
5350
- out.push({
5351
- value: String(o.value),
5352
- label: o.label,
5353
- disabled: !!o.disabled,
5354
- depth,
5355
- isGroup: hasChildren,
5356
- raw: o.value
5357
- });
5358
- if (hasChildren) out.push(...flattenOptions(o.children, depth + 1));
5366
+ if (hasChildren) {
5367
+ const childFlat = flattenOptions(o.children, depth + 1);
5368
+ const allChildrenDisabled = childFlat.every((c) => c.disabled);
5369
+ out.push({
5370
+ value: String(o.value),
5371
+ label: o.label,
5372
+ disabled: !!o.disabled || allChildrenDisabled,
5373
+ depth,
5374
+ isGroup: true,
5375
+ raw: o.value
5376
+ });
5377
+ out.push(...childFlat);
5378
+ } else {
5379
+ out.push({
5380
+ value: String(o.value),
5381
+ label: o.label,
5382
+ disabled: !!o.disabled,
5383
+ depth,
5384
+ isGroup: false,
5385
+ raw: o.value
5386
+ });
5387
+ }
5359
5388
  }
5360
5389
  return out;
5361
5390
  }
@@ -5410,6 +5439,9 @@ var SSelect = react.forwardRef(function SSelect2({
5410
5439
  );
5411
5440
  const flat = react.useMemo(() => flattenOptions(options), [options]);
5412
5441
  const selectable = react.useMemo(() => selectableOptions(flat), [flat]);
5442
+ const hasLeaf = react.useMemo(() => flat.some((o) => !o.isGroup), [flat]);
5443
+ const allOptionsDisabled = hasLeaf && selectable.length === 0;
5444
+ const effectiveDisabled = disabled || allOptionsDisabled;
5413
5445
  const showSearch = useSearch && selectable.length >= SEARCH_THRESHOLD;
5414
5446
  const labelByValue = react.useMemo(() => new Map(flat.map((o) => [o.value, o.label])), [flat]);
5415
5447
  const rawByValue = react.useMemo(() => new Map(flat.map((o) => [o.value, o.raw])), [flat]);
@@ -5476,10 +5508,10 @@ var SSelect = react.forwardRef(function SSelect2({
5476
5508
  Ariakit__namespace.Select,
5477
5509
  {
5478
5510
  ref: triggerRef,
5479
- disabled,
5511
+ disabled: effectiveDisabled,
5480
5512
  className: "flex h-full w-full cursor-pointer items-center justify-between gap-[8px] bg-transparent px-[12px] text-left text-[12px] leading-[20px] outline-none disabled:cursor-not-allowed",
5481
5513
  style: {
5482
- color: disabled ? "var(--cmp-select-text-disabled)" : isPlaceholder ? "var(--cmp-select-icon-default)" : "var(--cmp-select-text-default)"
5514
+ color: effectiveDisabled ? "var(--cmp-select-text-disabled)" : isPlaceholder ? "var(--cmp-select-icon-default)" : "var(--cmp-select-text-default)"
5483
5515
  },
5484
5516
  children: [
5485
5517
  isHtmlLabel(triggerText) ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -5494,7 +5526,7 @@ var SSelect = react.forwardRef(function SSelect2({
5494
5526
  {
5495
5527
  name: "chevronDown",
5496
5528
  size: 12,
5497
- color: disabled ? "var(--cmp-select-icon-disabled)" : "var(--cmp-select-icon-default)",
5529
+ color: effectiveDisabled ? "var(--cmp-select-icon-disabled)" : "var(--cmp-select-icon-default)",
5498
5530
  className: cn("shrink-0 transition-transform duration-200", open && "rotate-180")
5499
5531
  }
5500
5532
  )
@@ -5508,7 +5540,7 @@ var SSelect = react.forwardRef(function SSelect2({
5508
5540
  portalElement: portalContainer,
5509
5541
  gutter: 4,
5510
5542
  sameWidth: !dropdownWidth,
5511
- className: "z-50 overflow-auto rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] py-[4px] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.1)] data-[enter]:animate-floating-in-bottom data-[leave]:animate-floating-out-bottom",
5543
+ className: "z-50 overflow-auto rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.1)] data-[enter]:animate-floating-in-bottom data-[leave]:animate-floating-out-bottom",
5512
5544
  style: {
5513
5545
  maxHeight: dropdownHeight,
5514
5546
  ...dropdownWidth ? { width: dropdownWidth } : {},
@@ -5549,7 +5581,7 @@ var SSelect = react.forwardRef(function SSelect2({
5549
5581
  ),
5550
5582
  hasItems ? /* @__PURE__ */ jsxRuntime.jsx(ItemList, { items: filtered, multi, selected, useSearch: showSearch }) : (
5551
5583
  // 원본 sd-select-listbox__empty (표시할 항목이 없을 때)
5552
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-[12px] py-[12px] text-center text-[12px] leading-[20px] text-[color:var(--cmp-listItem-content-disabled)]", children: "\uD45C\uC2DC\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." })
5584
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-[12px] py-[12px] text-left text-[12px] leading-[20px] text-[color:var(--cmp-listItem-content-disabled)]", children: "\uD45C\uC2DC\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." })
5553
5585
  )
5554
5586
  ]
5555
5587
  }
@@ -5572,7 +5604,7 @@ var SSelect = react.forwardRef(function SSelect2({
5572
5604
  error: error || ruleError !== "",
5573
5605
  status: rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0,
5574
5606
  errorMessage: ruleError !== "" ? ruleError : errorMessage,
5575
- disabled,
5607
+ disabled: effectiveDisabled,
5576
5608
  width,
5577
5609
  className,
5578
5610
  style,
@@ -5607,7 +5639,11 @@ function ItemList({
5607
5639
  {
5608
5640
  className: cn(
5609
5641
  "select-none py-[4px] pr-[12px] text-[12px] leading-[20px] text-[color:var(--cmp-listItem-content-default)]",
5610
- isDepth1 ? "border-t border-solid border-[color:var(--cmp-listItem-depth1-border-color)] bg-[var(--cmp-listItem-depth1-bg-default)] font-bold" : "bg-[var(--cmp-listItem-depth2-middle-bg)] font-medium"
5642
+ isDepth1 ? "border-t border-solid border-[color:var(--cmp-listItem-depth1-border-color)] bg-[var(--cmp-listItem-depth1-bg-default)] font-bold" : "bg-[var(--cmp-listItem-depth2-middle-bg)] font-medium",
5643
+ // 하위가 전부 비활성이면(select.config 에서 bubble-up) 어미 그룹도 비활성 처리:
5644
+ // 텍스트는 회색(#888), depth1 그룹은 파란 배경 대신 회색(#EEE)으로 (depth2 는 #F6F6F6 유지)
5645
+ o.disabled && "text-[color:var(--cmp-listItem-content-disabled)]",
5646
+ o.disabled && isDepth1 && "bg-[var(--cmp-listItem-depth1-bg-disabled)]"
5611
5647
  ),
5612
5648
  style: { paddingLeft: padLeft },
5613
5649
  children: o.label
@@ -5634,15 +5670,21 @@ function ItemList({
5634
5670
  "span",
5635
5671
  {
5636
5672
  className: cn(
5637
- "flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid group-data-[active-item]:border-[color:var(--cmp-checkbox-checked-border-inverse)]",
5638
- isSelected ? "border-[color:var(--cmp-checkbox-checked-bg-default)] bg-[var(--cmp-checkbox-checked-bg-default)] group-data-[active-item]:bg-transparent" : "border-[color:var(--cmp-checkbox-unchecked-border-default)] bg-transparent"
5673
+ "flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid",
5674
+ o.disabled ? (
5675
+ // 비활성: 회색 채움(#E1E1E1) + 회색 테두리(#CCCCCC)
5676
+ "border-[color:var(--cmp-checkbox-border-disabled)] bg-[var(--cmp-checkbox-bg-disabled)]"
5677
+ ) : cn(
5678
+ "group-data-[active-item]:border-[color:var(--cmp-checkbox-checked-border-inverse)]",
5679
+ isSelected ? "border-[color:var(--cmp-checkbox-checked-bg-default)] bg-[var(--cmp-checkbox-checked-bg-default)] group-data-[active-item]:bg-transparent" : "border-[color:var(--cmp-checkbox-unchecked-border-default)] bg-transparent"
5680
+ )
5639
5681
  ),
5640
5682
  children: isSelected && /* @__PURE__ */ jsxRuntime.jsx(
5641
5683
  SIcon,
5642
5684
  {
5643
5685
  name: "checkboxCheck",
5644
5686
  size: 12,
5645
- color: "var(--cmp-checkbox-checked-icon-default)"
5687
+ color: o.disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : "var(--cmp-checkbox-checked-icon-default)"
5646
5688
  }
5647
5689
  )
5648
5690
  }
@@ -6421,8 +6463,8 @@ var STextarea = react.forwardRef(function STextarea2({
6421
6463
  );
6422
6464
  });
6423
6465
  var PAD2 = {
6424
- sm: { fontSize: 12, stepper: 20, icon: 12 },
6425
- md: { fontSize: 14, stepper: 24, icon: 14 }
6466
+ sm: { fontSize: 12, lineHeight: 20, stepper: 20, icon: 12 },
6467
+ md: { fontSize: 14, lineHeight: 24, stepper: 24, icon: 14 }
6426
6468
  };
6427
6469
  var toNumber = (val) => {
6428
6470
  if (val === null || val === void 0 || val === "") return null;
@@ -6440,6 +6482,38 @@ var formatWithCommas = (value) => {
6440
6482
  const result = isNeg ? "-" + formatted : formatted;
6441
6483
  return decPart !== void 0 && decPart !== "" ? result + "." + decPart : result;
6442
6484
  };
6485
+ var addCommas = (value) => value.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
6486
+ var formatInputWithCommas = (value) => {
6487
+ const isNeg = value.startsWith("-");
6488
+ const unsigned = isNeg ? value.slice(1) : value;
6489
+ const hasDecimal = unsigned.includes(".");
6490
+ const [intPart = "", decPart = ""] = unsigned.split(".");
6491
+ const formattedInt = addCommas(intPart === "" ? "0" : intPart);
6492
+ return `${isNeg ? "-" : ""}${formattedInt}${hasDecimal ? `.${decPart}` : ""}`;
6493
+ };
6494
+ var getDecimalLimit = (useDecimal, maxDecimalLength) => {
6495
+ if (!useDecimal || maxDecimalLength === void 0 || !Number.isFinite(maxDecimalLength)) {
6496
+ return void 0;
6497
+ }
6498
+ return Math.max(0, Math.floor(maxDecimalLength));
6499
+ };
6500
+ var applyDecimalLimit = (value, decimalLimit) => {
6501
+ if (value === null || decimalLimit === void 0) return value;
6502
+ return Number(value.toFixed(decimalLimit));
6503
+ };
6504
+ var getLogicalCaret = (value, caret) => {
6505
+ return value.slice(0, caret ?? value.length).replace(/,/g, "").length;
6506
+ };
6507
+ var getDisplayCaret = (value, logicalCaret) => {
6508
+ if (logicalCaret <= 0) return 0;
6509
+ let seen = 0;
6510
+ for (let i = 0; i < value.length; i += 1) {
6511
+ if (value[i] === ",") continue;
6512
+ seen += 1;
6513
+ if (seen >= logicalCaret) return i + 1;
6514
+ }
6515
+ return value.length;
6516
+ };
6443
6517
  var SNumberInput = react.forwardRef(function SNumberInput2({
6444
6518
  value,
6445
6519
  onValueChange,
@@ -6449,6 +6523,7 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
6449
6523
  step = 1,
6450
6524
  useButton = false,
6451
6525
  useDecimal = false,
6526
+ maxDecimalLength,
6452
6527
  inputPrefix = "",
6453
6528
  inputSuffix = "",
6454
6529
  inputClass,
@@ -6480,7 +6555,8 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
6480
6555
  }, ref) {
6481
6556
  const p = PAD2[size];
6482
6557
  const padX = `var(--cmp-numberInput-${size}-paddingX)`;
6483
- const numValue = toNumber(value);
6558
+ const decimalLimit = getDecimalLimit(useDecimal, maxDecimalLength);
6559
+ const numValue = applyDecimalLimit(toNumber(value), decimalLimit);
6484
6560
  const [display, setDisplay] = react.useState(() => formatWithCommas(numValue));
6485
6561
  const [ruleError, setRuleError] = react.useState("");
6486
6562
  const innerRef = react.useRef(null);
@@ -6490,8 +6566,9 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
6490
6566
  else if (ref) ref.current = el;
6491
6567
  };
6492
6568
  react.useEffect(() => {
6493
- setDisplay(formatWithCommas(toNumber(value)));
6494
- }, [value]);
6569
+ if (document.activeElement === innerRef.current) return;
6570
+ setDisplay(formatWithCommas(applyDecimalLimit(toNumber(value), decimalLimit)));
6571
+ }, [decimalLimit, value]);
6495
6572
  useFormField({
6496
6573
  name,
6497
6574
  validate: () => {
@@ -6503,48 +6580,87 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
6503
6580
  });
6504
6581
  const resolvedError = error || ruleError !== "";
6505
6582
  const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
6506
- const emit2 = (n) => {
6507
- setDisplay(formatWithCommas(n));
6508
- onValueChange?.(n);
6583
+ const restoreCaret = (nextDisplay, logicalCaret) => {
6584
+ const input = innerRef.current;
6585
+ if (logicalCaret === void 0 || !input || document.activeElement !== input) return;
6586
+ const nextCaret = getDisplayCaret(nextDisplay, logicalCaret);
6587
+ requestAnimationFrame(() => {
6588
+ if (document.activeElement !== input) return;
6589
+ input.setSelectionRange(nextCaret, nextCaret);
6590
+ });
6591
+ };
6592
+ const setDisplayWithCaret = (nextDisplay, logicalCaret) => {
6593
+ setDisplay(nextDisplay);
6594
+ restoreCaret(nextDisplay, logicalCaret);
6595
+ };
6596
+ const resetRejectedInput = (target, logicalCaret) => {
6597
+ target.value = display;
6598
+ restoreCaret(display, Math.min(logicalCaret, display.replace(/,/g, "").length));
6599
+ };
6600
+ const emit2 = (n, logicalCaret) => {
6601
+ const next = applyDecimalLimit(n, decimalLimit);
6602
+ const nextDisplay = formatWithCommas(next);
6603
+ setDisplayWithCaret(nextDisplay, logicalCaret);
6604
+ onValueChange?.(next);
6509
6605
  };
6510
6606
  const incDisabled = disabled || readOnly || numValue !== null && numValue >= max;
6511
6607
  const decDisabled = disabled || readOnly || numValue !== null && numValue <= min;
6512
6608
  const increment = () => {
6513
6609
  if (incDisabled) return;
6514
6610
  const cur = numValue ?? (min === Number.NEGATIVE_INFINITY ? 0 : min);
6515
- const next = Math.min(cur + step, max);
6611
+ const next = applyDecimalLimit(Math.min(cur + step, max), decimalLimit);
6516
6612
  if (next !== cur) emit2(next);
6517
6613
  };
6518
6614
  const decrement = () => {
6519
6615
  if (decDisabled) return;
6520
6616
  const cur = numValue ?? (min === Number.NEGATIVE_INFINITY ? 0 : min);
6521
- const next = Math.max(cur - step, min);
6617
+ const next = applyDecimalLimit(Math.max(cur - step, min), decimalLimit);
6522
6618
  if (next !== cur) emit2(next);
6523
6619
  };
6524
- const handleInput = (raw) => {
6620
+ const handleInput = (event) => {
6621
+ const target = event.currentTarget;
6622
+ const raw = target.value;
6623
+ const logicalCaret = getLogicalCaret(raw, target.selectionStart);
6525
6624
  if (raw === "") {
6526
- setDisplay("");
6625
+ setDisplayWithCaret("", 0);
6527
6626
  onValueChange?.(null);
6528
6627
  return;
6529
6628
  }
6530
6629
  const cleaned = raw.replace(/,/g, "");
6531
6630
  const decimals = (cleaned.match(/\./g) || []).length;
6532
- if (decimals > 1) return;
6631
+ if (decimals > 1) {
6632
+ resetRejectedInput(target, logicalCaret);
6633
+ return;
6634
+ }
6533
6635
  if (cleaned === "-" || cleaned === "." || cleaned === "-.") {
6534
- setDisplay(cleaned);
6636
+ setDisplayWithCaret(cleaned, logicalCaret);
6637
+ return;
6638
+ }
6639
+ if (!useDecimal && cleaned.includes(".")) {
6640
+ resetRejectedInput(target, logicalCaret);
6535
6641
  return;
6536
6642
  }
6537
- if (!useDecimal && cleaned.includes(".")) return;
6643
+ if (decimalLimit !== void 0 && cleaned.includes(".")) {
6644
+ const fraction = cleaned.split(".")[1] ?? "";
6645
+ if (fraction.length > decimalLimit) {
6646
+ resetRejectedInput(target, logicalCaret);
6647
+ return;
6648
+ }
6649
+ }
6538
6650
  if (cleaned.endsWith(".") && decimals === 1) {
6539
6651
  const parsed2 = toNumber(cleaned.slice(0, -1));
6540
6652
  if (parsed2 !== null) {
6541
- setDisplay(formatWithCommas(parsed2) + ".");
6653
+ setDisplayWithCaret(formatInputWithCommas(cleaned), logicalCaret);
6542
6654
  return;
6543
6655
  }
6544
6656
  }
6545
6657
  const parsed = toNumber(cleaned);
6546
- if (parsed === null) return;
6547
- emit2(parsed);
6658
+ if (parsed === null) {
6659
+ resetRejectedInput(target, logicalCaret);
6660
+ return;
6661
+ }
6662
+ setDisplayWithCaret(formatInputWithCommas(cleaned), logicalCaret);
6663
+ onValueChange?.(applyDecimalLimit(parsed, decimalLimit));
6548
6664
  };
6549
6665
  const stepper = (dir) => {
6550
6666
  const off = dir === "inc" ? incDisabled : decDisabled;
@@ -6557,8 +6673,8 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
6557
6673
  "aria-label": dir === "inc" ? "\uC99D\uAC00" : "\uAC10\uC18C",
6558
6674
  onClick: dir === "inc" ? increment : decrement,
6559
6675
  className: cn(
6560
- "flex flex-shrink-0 items-center justify-center",
6561
- off ? "cursor-not-allowed" : "cursor-pointer"
6676
+ "flex flex-shrink-0 items-center justify-center border border-solid border-transparent transition-colors",
6677
+ off ? "cursor-not-allowed" : "cursor-pointer hover:border-[var(--color-border-accentLight)]"
6562
6678
  ),
6563
6679
  style: {
6564
6680
  width: `var(--cmp-numberInput-stepper-${size}-size)`,
@@ -6607,24 +6723,26 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
6607
6723
  style: {
6608
6724
  // 원본 sd-number-input: content gap = padding-x 토큰 (gap 토큰 아님)
6609
6725
  gap: `var(--cmp-numberInput-${size}-paddingX)`,
6610
- padding: `0 ${useButton ? padX : `calc(${padX} * 2)`}`
6726
+ padding: `0 ${useButton ? padX : `calc(${padX} * 2)`}`,
6727
+ fontSize: p.fontSize,
6728
+ lineHeight: `${p.lineHeight}px`
6611
6729
  },
6612
6730
  children: [
6613
6731
  useButton && stepper("dec"),
6614
- inputPrefix !== "" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", style: { fontSize: p.fontSize, color: affixColor }, children: inputPrefix }),
6732
+ inputPrefix !== "" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", style: { color: affixColor }, children: inputPrefix }),
6615
6733
  /* @__PURE__ */ jsxRuntime.jsx(
6616
6734
  "input",
6617
6735
  {
6618
6736
  ref: setRefs,
6619
6737
  name,
6620
6738
  type: "text",
6621
- inputMode: "numeric",
6739
+ inputMode: useDecimal ? "decimal" : "numeric",
6622
6740
  value: display,
6623
6741
  placeholder,
6624
6742
  disabled,
6625
6743
  readOnly,
6626
6744
  autoFocus,
6627
- onChange: (e) => handleInput(e.target.value),
6745
+ onChange: handleInput,
6628
6746
  onKeyDown: (e) => {
6629
6747
  if (e.key === "ArrowUp") {
6630
6748
  e.preventDefault();
@@ -6636,26 +6754,29 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
6636
6754
  },
6637
6755
  onFocus: (e) => onFocus?.(e),
6638
6756
  onBlur: (e) => {
6639
- const n = toNumber(display);
6757
+ const cleaned = display.replace(/,/g, "");
6758
+ const n = toNumber(cleaned);
6640
6759
  const clamped = n === null ? null : Math.min(Math.max(n, min), max);
6641
6760
  if (clamped !== n) emit2(clamped);
6642
- else setDisplay(formatWithCommas(n));
6761
+ else setDisplay(n === null ? "" : formatInputWithCommas(cleaned));
6643
6762
  if (rules && rules.length > 0) setRuleError(runRules(clamped, rules));
6644
6763
  onBlur?.(e);
6645
6764
  },
6646
6765
  className: cn(
6647
- "h-full min-w-0 flex-1 border-0 bg-transparent p-0 outline-none placeholder:text-[color:var(--cmp-numberInput-text-placeholder)] disabled:cursor-not-allowed",
6766
+ // h-full 대신 라인박스 높이 그대로 두어 prefix/suffix 동일하게 flex 로 수직 센터링
6767
+ // (h-full 이면 input 내부 텍스트 센터링을 브라우저가 수행해 1px 어긋날 수 있음)
6768
+ "min-w-0 flex-1 border-0 bg-transparent p-0 outline-none placeholder:text-[color:var(--cmp-numberInput-text-placeholder)] disabled:cursor-not-allowed",
6648
6769
  inputClass
6649
6770
  ),
6650
6771
  style: {
6651
- fontSize: p.fontSize,
6772
+ // fontSize/lineHeight 는 컨테이너에서 상속
6652
6773
  textAlign: useButton ? "center" : "right",
6653
6774
  color: disabled ? "var(--cmp-numberInput-text-disabled)" : "var(--cmp-numberInput-text-default)",
6654
6775
  ...inputStyle
6655
6776
  }
6656
6777
  }
6657
6778
  ),
6658
- inputSuffix !== "" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", style: { fontSize: p.fontSize, color: affixColor }, children: inputSuffix }),
6779
+ inputSuffix !== "" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", style: { color: affixColor }, children: inputSuffix }),
6659
6780
  useButton && stepper("inc")
6660
6781
  ]
6661
6782
  }
@@ -6981,7 +7102,7 @@ function SCalendar({
6981
7102
  "span",
6982
7103
  {
6983
7104
  className: cn(
6984
- "flex h-[var(--cmp-datepicker-calendar-day-circle-size)] w-[var(--cmp-datepicker-calendar-day-circle-size)] items-center justify-center rounded-[var(--cmp-datepicker-calendar-day-circle-radius)] border border-solid border-transparent text-[14px]",
7105
+ "flex h-[var(--cmp-datepicker-calendar-day-circle-size)] w-[var(--cmp-datepicker-calendar-day-circle-size)] items-center justify-center rounded-[var(--cmp-datepicker-calendar-day-circle-radius)] border border-solid border-transparent text-[14px] leading-[var(--cmp-datepicker-calendar-day-circle-size)]",
6985
7106
  selected ? "bg-[var(--cmp-datepicker-calendar-day-select-bg)] text-[color:var(--cmp-datepicker-calendar-day-select-text)]" : disabled ? "text-[color:var(--cmp-datepicker-calendar-day-disabled-text)]" : "text-[color:var(--cmp-datepicker-calendar-day-default-text)] hover:border-[color:var(--cmp-datepicker-calendar-day-hover-border)]",
6986
7107
  isToday && !disabled && "font-bold"
6987
7108
  ),
@@ -7171,6 +7292,7 @@ function RangeCalendar({
7171
7292
  selectable,
7172
7293
  maxRange,
7173
7294
  onSelect,
7295
+ onPendingStartChange,
7174
7296
  onViewChange
7175
7297
  }) {
7176
7298
  const today = todayStr();
@@ -7233,9 +7355,11 @@ function RangeCalendar({
7233
7355
  setStart(d);
7234
7356
  setEnd(null);
7235
7357
  setHover(null);
7358
+ onPendingStartChange?.(d);
7236
7359
  return;
7237
7360
  }
7238
7361
  setEnd(d);
7362
+ onPendingStartChange?.(null);
7239
7363
  onSelect([start, d]);
7240
7364
  };
7241
7365
  const GRID_COLS = "grid grid-cols-[repeat(7,var(--cmp-datepicker-calendar-day-width))]";
@@ -7370,8 +7494,11 @@ function SDateRangePicker({
7370
7494
  const portalContainer = usePortalContainer();
7371
7495
  const [open, setOpen] = react.useState(false);
7372
7496
  const [ruleError, setRuleError] = react.useState("");
7497
+ const [pendingStart, setPendingStart] = react.useState(null);
7373
7498
  const hasValue = value != null && value[0] !== "" && value[1] !== "";
7374
- const display = hasValue ? `${value[0]} ~ ${value[1]}` : placeholder;
7499
+ const hasDisplay = pendingStart != null || hasValue;
7500
+ const startText = pendingStart ?? (hasValue ? value[0] : "");
7501
+ const endText = pendingStart ? "" : hasValue ? value[1] : "";
7375
7502
  useFormField({
7376
7503
  name,
7377
7504
  validate: () => {
@@ -7385,6 +7512,7 @@ function SDateRangePicker({
7385
7512
  const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
7386
7513
  const dims = size === "md" ? { padX: 16, gap: 12, icon: 20, minW: 104, fontSize: 14, lineHeight: 24, radius: 6 } : { padX: 12, gap: 8, icon: 16, minW: 80, fontSize: 12, lineHeight: 20, radius: 4 };
7387
7514
  const select = (r) => {
7515
+ setPendingStart(null);
7388
7516
  onValueChange?.(r);
7389
7517
  if (rules && rules.length > 0) setRuleError(runRules(r, rules));
7390
7518
  setOpen(false);
@@ -7409,61 +7537,80 @@ function SDateRangePicker({
7409
7537
  disabled,
7410
7538
  className,
7411
7539
  style,
7412
- children: /* @__PURE__ */ jsxRuntime.jsxs(RPopover2__namespace.Root, { open, onOpenChange: (o) => !disabled && setOpen(o), children: [
7413
- /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
7414
- "button",
7415
- {
7416
- type: "button",
7417
- name,
7418
- disabled,
7419
- className: "flex h-full w-full items-center overflow-hidden bg-transparent outline-none disabled:cursor-not-allowed",
7420
- style: { padding: `0 ${dims.padX}px`, gap: dims.gap, borderRadius: dims.radius },
7421
- children: [
7422
- /* @__PURE__ */ jsxRuntime.jsx(
7423
- SIcon,
7424
- {
7425
- name: "date",
7426
- size: dims.icon,
7427
- color: disabled ? "var(--cmp-datepicker-icon-disabled)" : "var(--cmp-datepicker-icon-default)",
7428
- className: "flex-shrink-0"
7429
- }
7430
- ),
7431
- /* @__PURE__ */ jsxRuntime.jsx(
7432
- "span",
7433
- {
7434
- className: "flex-1 truncate text-center",
7435
- style: {
7436
- minWidth: dims.minW,
7437
- fontSize: dims.fontSize,
7438
- lineHeight: `${dims.lineHeight}px`,
7439
- color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasValue ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
7440
- },
7441
- children: display
7442
- }
7443
- )
7444
- ]
7445
- }
7446
- ) }),
7447
- /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
7448
- RPopover2__namespace.Content,
7449
- {
7450
- side: "bottom",
7451
- align: "start",
7452
- sideOffset: 4,
7453
- className: cn("z-50", FLOATING_SLIDE_ANIM),
7454
- children: /* @__PURE__ */ jsxRuntime.jsx(
7455
- RangeCalendar,
7540
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
7541
+ RPopover2__namespace.Root,
7542
+ {
7543
+ open,
7544
+ onOpenChange: (o) => {
7545
+ if (disabled) return;
7546
+ setOpen(o);
7547
+ if (!o) setPendingStart(null);
7548
+ },
7549
+ children: [
7550
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
7551
+ "button",
7456
7552
  {
7457
- value: value ?? null,
7458
- selectable,
7459
- maxRange,
7460
- onSelect: select,
7461
- onViewChange
7553
+ type: "button",
7554
+ name,
7555
+ disabled,
7556
+ className: "flex h-full w-full items-center overflow-hidden bg-transparent outline-none disabled:cursor-not-allowed",
7557
+ style: { padding: `0 ${dims.padX}px`, gap: dims.gap, borderRadius: dims.radius },
7558
+ children: [
7559
+ /* @__PURE__ */ jsxRuntime.jsx(
7560
+ SIcon,
7561
+ {
7562
+ name: "date",
7563
+ size: dims.icon,
7564
+ color: disabled ? "var(--cmp-datepicker-icon-disabled)" : "var(--cmp-datepicker-icon-default)",
7565
+ className: "flex-shrink-0"
7566
+ }
7567
+ ),
7568
+ /* @__PURE__ */ jsxRuntime.jsx(
7569
+ "span",
7570
+ {
7571
+ className: cn(
7572
+ "flex-1 items-center",
7573
+ hasDisplay ? "flex" : "block truncate text-center"
7574
+ ),
7575
+ style: {
7576
+ minWidth: dims.minW,
7577
+ fontSize: dims.fontSize,
7578
+ lineHeight: `${dims.lineHeight}px`,
7579
+ color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasDisplay ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
7580
+ },
7581
+ children: hasDisplay ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7582
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-right", children: startText }),
7583
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-[4px]", children: "~" }),
7584
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-left", children: endText })
7585
+ ] }) : placeholder
7586
+ }
7587
+ )
7588
+ ]
7462
7589
  }
7463
- )
7464
- }
7465
- ) })
7466
- ] })
7590
+ ) }),
7591
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
7592
+ RPopover2__namespace.Content,
7593
+ {
7594
+ side: "bottom",
7595
+ align: "start",
7596
+ sideOffset: 4,
7597
+ className: cn("z-50", FLOATING_SLIDE_ANIM),
7598
+ children: /* @__PURE__ */ jsxRuntime.jsx(
7599
+ RangeCalendar,
7600
+ {
7601
+ value: value ?? null,
7602
+ selectable,
7603
+ maxRange,
7604
+ onSelect: select,
7605
+ onPendingStartChange: setPendingStart,
7606
+ onViewChange
7607
+ }
7608
+ )
7609
+ }
7610
+ ) })
7611
+ ]
7612
+ }
7613
+ )
7467
7614
  }
7468
7615
  );
7469
7616
  }
@@ -7472,7 +7619,7 @@ var SChip = react.forwardRef(function SChip2({
7472
7619
  value = "",
7473
7620
  error: errorProp = false,
7474
7621
  disabled = false,
7475
- editable = true,
7622
+ editable = false,
7476
7623
  showRemove = true,
7477
7624
  placeholder = "",
7478
7625
  rules,
@@ -7625,6 +7772,7 @@ function SFilePicker({
7625
7772
  hovered = false,
7626
7773
  inline = false,
7627
7774
  multiple = false,
7775
+ useMultipleListBox = false,
7628
7776
  accept,
7629
7777
  maxFileSize,
7630
7778
  maxTotalSize,
@@ -7652,8 +7800,8 @@ function SFilePicker({
7652
7800
  const inputRef = react.useRef(null);
7653
7801
  const [ruleError, setRuleError] = react.useState("");
7654
7802
  const files = multiple ? Array.isArray(value) ? value : [] : value && !Array.isArray(value) ? value : null;
7655
- const hasSingle = !multiple && !!files;
7656
- const displayText = hasSingle ? files.name : placeholder;
7803
+ const hasFiles = multiple ? files.length > 0 : !!files;
7804
+ const displayText = !hasFiles ? placeholder : multiple ? files.map((f) => f.name).join(", ") : files.name;
7657
7805
  useFormField({
7658
7806
  name,
7659
7807
  validate: () => {
@@ -7717,78 +7865,88 @@ function SFilePicker({
7717
7865
  const padX = size === "md" ? "var(--cmp-filepicker-md-paddingX)" : "var(--cmp-filepicker-sm-paddingX)";
7718
7866
  const iconSize = size === "md" ? 20 : 16;
7719
7867
  const gapCls = size === "md" ? "gap-[var(--cmp-filepicker-md-gap)]" : "gap-[var(--cmp-filepicker-sm-gap)]";
7720
- const content = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex h-full w-full items-center", gapCls), style: { padding: `0 ${padX}` }, children: [
7721
- /* @__PURE__ */ jsxRuntime.jsx(
7722
- "input",
7723
- {
7724
- ref: inputRef,
7725
- type: "file",
7726
- className: "hidden",
7727
- disabled,
7728
- multiple,
7729
- accept,
7730
- name: resolvedName,
7731
- onChange,
7732
- "aria-label": placeholder
7733
- }
7734
- ),
7735
- /* @__PURE__ */ jsxRuntime.jsxs(
7736
- "button",
7737
- {
7738
- type: "button",
7739
- disabled,
7740
- onClick: open,
7741
- "aria-label": placeholder,
7742
- className: cn(
7743
- "flex min-w-0 flex-1 items-center bg-transparent text-left",
7744
- gapCls,
7745
- disabled ? "cursor-not-allowed" : "cursor-pointer"
7868
+ const inlinePlaceholder = inline && !disabled && !hasFiles;
7869
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(
7870
+ "div",
7871
+ {
7872
+ className: cn("group/filepicker flex h-full w-full items-center", gapCls),
7873
+ style: { padding: inline ? 0 : `0 ${padX}` },
7874
+ children: [
7875
+ /* @__PURE__ */ jsxRuntime.jsx(
7876
+ "input",
7877
+ {
7878
+ ref: inputRef,
7879
+ type: "file",
7880
+ className: "hidden",
7881
+ disabled,
7882
+ multiple,
7883
+ accept,
7884
+ name: resolvedName,
7885
+ onChange,
7886
+ "aria-label": placeholder
7887
+ }
7746
7888
  ),
7747
- children: [
7748
- /* @__PURE__ */ jsxRuntime.jsx(
7749
- SIcon,
7750
- {
7751
- name: "attachFile",
7752
- size: iconSize,
7753
- color: disabled ? "var(--cmp-filepicker-icon-disabled)" : "var(--color-grey-65)"
7754
- }
7755
- ),
7756
- /* @__PURE__ */ jsxRuntime.jsx(
7757
- "span",
7758
- {
7759
- className: "min-w-0 flex-1 truncate text-[12px]",
7760
- style: {
7761
- color: disabled ? "var(--cmp-filepicker-text-disabled)" : hasSingle ? "var(--cmp-filepicker-text-default)" : "var(--cmp-filepicker-text-placeholder)"
7762
- },
7763
- children: displayText
7764
- }
7765
- )
7766
- ]
7767
- }
7768
- ),
7769
- !disabled && hasSingle && /* @__PURE__ */ jsxRuntime.jsx(SGhostButton, { icon: "close", size: "xxs", ariaLabel: "clear", onClick: clear })
7770
- ] });
7771
- const chips = multiple && files.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-[8px] flex flex-wrap gap-[8px]", children: files.map((f, i) => /* @__PURE__ */ jsxRuntime.jsx(SChip, { value: f.name, editable: false, onRemove: () => removeChip(i) }, i)) });
7772
- if (inline) {
7773
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("inline-flex flex-col", className), style, children: [
7774
- /* @__PURE__ */ jsxRuntime.jsx(
7775
- "div",
7776
- {
7777
- className: "box-border flex items-center rounded-[var(--cmp-filepicker-sm-radius)] border border-solid border-[color:var(--cmp-filepicker-border-default)] bg-[var(--cmp-filepicker-bg-default)]",
7778
- style: {
7779
- height: "var(--cmp-filepicker-sm-height)",
7780
- width: typeof width === "number" ? `${width}px` : width
7781
- },
7782
- children: content
7783
- }
7889
+ /* @__PURE__ */ jsxRuntime.jsxs(
7890
+ "button",
7891
+ {
7892
+ type: "button",
7893
+ disabled,
7894
+ onClick: open,
7895
+ "aria-label": placeholder,
7896
+ className: cn(
7897
+ "flex min-w-0 flex-1 items-center bg-transparent text-left",
7898
+ gapCls,
7899
+ disabled ? "cursor-not-allowed" : "cursor-pointer"
7900
+ ),
7901
+ children: [
7902
+ /* @__PURE__ */ jsxRuntime.jsx(
7903
+ SIcon,
7904
+ {
7905
+ name: "attachFile",
7906
+ size: iconSize,
7907
+ color: disabled ? "var(--cmp-filepicker-icon-disabled)" : "var(--color-grey-65)"
7908
+ }
7909
+ ),
7910
+ /* @__PURE__ */ jsxRuntime.jsx(
7911
+ "span",
7912
+ {
7913
+ className: cn(
7914
+ "min-w-0 flex-1 truncate text-[12px]",
7915
+ inlinePlaceholder && "text-[color:var(--cmp-filepicker-text-placeholder)] transition-colors group-hover/filepicker:text-[color:var(--cmp-filepicker-text-default)]"
7916
+ ),
7917
+ style: inlinePlaceholder ? void 0 : {
7918
+ color: disabled ? "var(--cmp-filepicker-text-disabled)" : hasFiles ? "var(--cmp-filepicker-text-default)" : "var(--cmp-filepicker-text-placeholder)"
7919
+ },
7920
+ children: displayText
7921
+ }
7922
+ )
7923
+ ]
7924
+ }
7925
+ ),
7926
+ !disabled && hasFiles && /* @__PURE__ */ jsxRuntime.jsx(SGhostButton, { icon: "close", size: "xxs", ariaLabel: "clear", onClick: clear })
7927
+ ]
7928
+ }
7929
+ );
7930
+ const chips = multiple && files.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
7931
+ "div",
7932
+ {
7933
+ className: cn(
7934
+ "mt-[8px] flex gap-[8px]",
7935
+ useMultipleListBox ? "box-border flex-col items-start rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] p-[8px] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.1)]" : "flex-wrap"
7784
7936
  ),
7785
- chips
7786
- ] });
7787
- }
7937
+ style: useMultipleListBox ? {
7938
+ width: typeof width === "number" ? `${width}px` : width,
7939
+ // label 이 있으면 SField 입력 박스 시작 위치(labelWidth + fieldGap)에 맞춰 정렬
7940
+ marginLeft: label && labelWidth != null ? `calc(${typeof labelWidth === "number" ? `${labelWidth}px` : labelWidth} + var(--sys-space-field-${size}-gap))` : void 0
7941
+ } : void 0,
7942
+ children: files.map((f, i) => /* @__PURE__ */ jsxRuntime.jsx(SChip, { value: f.name, editable: false, onRemove: () => removeChip(i) }, i))
7943
+ }
7944
+ );
7788
7945
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style, children: [
7789
7946
  /* @__PURE__ */ jsxRuntime.jsx(
7790
7947
  SField,
7791
7948
  {
7949
+ borderless: inline,
7792
7950
  label,
7793
7951
  labelWidth,
7794
7952
  icon,
@@ -7816,6 +7974,7 @@ function SKeyValueTable({
7816
7974
  fields = [],
7817
7975
  search = false,
7818
7976
  radius = "default",
7977
+ dense = false,
7819
7978
  onChange,
7820
7979
  onSearch,
7821
7980
  className,
@@ -7823,6 +7982,8 @@ function SKeyValueTable({
7823
7982
  }) {
7824
7983
  if (fields.length === 0) return null;
7825
7984
  const emit2 = (name, value) => onChange?.({ name, value });
7985
+ const cellHeight = dense ? "var(--cmp-table-body-dense-height)" : "var(--cmp-table-keyValue-height)";
7986
+ const cellPadY = dense ? "var(--cmp-table-body-dense-paddingY)" : "var(--cmp-table-keyValue-body-paddingY)";
7826
7987
  const renderField = (f) => {
7827
7988
  if (f.render) return f.render;
7828
7989
  const opt = f.options ?? {};
@@ -7903,10 +8064,15 @@ function SKeyValueTable({
7903
8064
  rowSpan: f.thRowSpan && f.thRowSpan > 1 ? f.thRowSpan : void 0,
7904
8065
  colSpan: f.thColSpan && f.thColSpan > 1 ? f.thColSpan : void 0,
7905
8066
  className: cn(
7906
- "h-[var(--cmp-table-keyValue-height)] box-border bg-[var(--cmp-table-header-bg)] px-[var(--cmp-table-header-paddingX)] py-[var(--cmp-table-keyValue-body-paddingY)] text-left align-middle",
8067
+ "box-border bg-[var(--cmp-table-header-bg)] px-[var(--cmp-table-header-paddingX)] text-left align-middle",
7907
8068
  cellBorder,
7908
8069
  f.thClass
7909
8070
  ),
8071
+ style: {
8072
+ height: cellHeight,
8073
+ paddingTop: cellPadY,
8074
+ paddingBottom: cellPadY
8075
+ },
7910
8076
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full w-full items-center justify-between gap-[var(--cmp-table-header-gap)]", children: [
7911
8077
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-[8px]", children: [
7912
8078
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[12px] font-bold leading-[20px] text-[color:var(--sys-color-fg-primary)]", children: f.label }),
@@ -7932,10 +8098,11 @@ function SKeyValueTable({
7932
8098
  rowSpan: f.tdRowSpan && f.tdRowSpan > 1 ? f.tdRowSpan : void 0,
7933
8099
  colSpan: f.tdColSpan && f.tdColSpan > 1 ? f.tdColSpan : void 0,
7934
8100
  className: cn(
7935
- "h-[var(--cmp-table-keyValue-height)] box-border bg-[var(--sys-color-bg-frame)] px-[var(--cmp-table-keyValue-body-paddingX-default)] py-[var(--cmp-table-keyValue-body-paddingY)] align-middle",
8101
+ "box-border bg-[var(--sys-color-bg-frame)] px-[var(--cmp-table-keyValue-body-paddingX-default)] align-middle",
7936
8102
  cellBorder,
7937
8103
  f.tdClass
7938
8104
  ),
8105
+ style: { height: cellHeight, paddingTop: cellPadY, paddingBottom: cellPadY },
7939
8106
  children: renderField(f)
7940
8107
  },
7941
8108
  `td-${r}-${c}`
@@ -8056,9 +8223,9 @@ var POS_ANCHOR = {
8056
8223
  "top-left": { top: 20, left: 20 },
8057
8224
  "top-center": { top: 20, left: "50%" },
8058
8225
  "top-right": { top: 20, right: 20 },
8059
- "bottom-left": { bottom: 20, left: 20 },
8060
- "bottom-center": { bottom: 20, left: "50%" },
8061
- "bottom-right": { bottom: 20, right: 20 }
8226
+ "bottom-left": { bottom: 100, left: 20 },
8227
+ "bottom-center": { bottom: 100, left: "50%" },
8228
+ "bottom-right": { bottom: 100, right: 20 }
8062
8229
  };
8063
8230
  var counter = 0;
8064
8231
  var SToastContainer = react.forwardRef(
@@ -8418,7 +8585,7 @@ var SChipInput = react.forwardRef(function SChipInput2({
8418
8585
  disabledChips = [],
8419
8586
  size = "sm",
8420
8587
  disabled = false,
8421
- placeholder = "\uC785\uB825\uD574 \uC8FC\uC138\uC694.",
8588
+ placeholder = "\uD0DC\uADF8 \uC785\uB825 (Enter\uB85C \uB4F1\uB85D / \uCF64\uB9C8\uB85C \uAD6C\uBD84 / \uB744\uC5B4\uC4F0\uAE30 \uBD88\uAC00)",
8422
8589
  name,
8423
8590
  rules,
8424
8591
  error,
@@ -8569,6 +8736,7 @@ var SChipInput = react.forwardRef(function SChipInput2({
8569
8736
  {
8570
8737
  label,
8571
8738
  labelWidth,
8739
+ labelHeight: `calc(var(--cmp-chipInput-${size}-minHeight) + 2px)`,
8572
8740
  icon,
8573
8741
  labelTooltip,
8574
8742
  labelTooltipProps,
@@ -8639,9 +8807,11 @@ var SChipInput = react.forwardRef(function SChipInput2({
8639
8807
  paddingInline: isFieldFilled ? "var(--cmp-chip-paddingX)" : void 0,
8640
8808
  borderWidth: isFieldFilled ? "var(--cmp-chip-border-width)" : void 0,
8641
8809
  borderStyle: isFieldFilled ? "solid" : void 0,
8642
- borderColor: isFieldFilled ? "transparent" : void 0,
8810
+ // 작성중 필드는 SChip의 editable 수정중(editing) 스타일과 동일하게 —
8811
+ // bg/보더/글자색 모두 focus 토큰을 사용한다.
8812
+ borderColor: isFieldFilled ? "var(--cmp-chip-border-focus)" : void 0,
8643
8813
  borderRadius: isFieldFilled ? "var(--cmp-chip-radius)" : 0,
8644
- background: isFieldFilled ? "var(--cmp-chip-bg-default)" : "transparent",
8814
+ background: isFieldFilled ? "var(--cmp-chip-bg-focus)" : "transparent",
8645
8815
  overflow: "hidden"
8646
8816
  },
8647
8817
  children: [
@@ -8650,7 +8820,7 @@ var SChipInput = react.forwardRef(function SChipInput2({
8650
8820
  {
8651
8821
  "aria-hidden": true,
8652
8822
  className: cn(
8653
- "invisible col-start-1 row-start-1 whitespace-pre font-medium",
8823
+ "invisible col-start-1 row-start-1 whitespace-pre font-normal",
8654
8824
  size === "md" ? "text-14 leading-24" : "text-12 leading-20"
8655
8825
  ),
8656
8826
  children: inputValue !== "" ? inputValue : values.length === 0 ? placeholder : ""
@@ -8663,12 +8833,14 @@ var SChipInput = react.forwardRef(function SChipInput2({
8663
8833
  name: resolvedName,
8664
8834
  size: 1,
8665
8835
  className: cn(
8666
- "s-chip-input__input col-start-1 row-start-1 w-full border-0 bg-transparent p-0 font-medium text-(--cmp-chip-content-focus) outline-none placeholder:text-(--cmp-chipInput-text-placeholder) disabled:cursor-not-allowed",
8836
+ "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",
8667
8837
  size === "md" ? "text-14 leading-24" : "text-12 leading-20"
8668
8838
  ),
8669
8839
  style: {
8670
8840
  minWidth: "1ch",
8671
- height: "var(--cmp-chip-height)",
8841
+ // height 지정하지 않고 line-height(20/24px)에 맞춰 자동 크기로 둔다.
8842
+ // var(--cmp-chip-height)(24px)로 고정하면 네이티브 <input>이 남는 세로 여백에
8843
+ // 텍스트를 아래로 밀어 넣어, 확정된 chip 텍스트보다 2px 낮게 보인다.
8672
8844
  margin: 0,
8673
8845
  overflow: "hidden",
8674
8846
  textOverflow: "ellipsis"
@@ -8713,7 +8885,7 @@ var SChipInput = react.forwardRef(function SChipInput2({
8713
8885
  showMetaInfo && /* @__PURE__ */ jsxRuntime.jsxs(
8714
8886
  "div",
8715
8887
  {
8716
- className: "s-chip-input__meta flex items-center gap-8",
8888
+ className: "s-chip-input__meta ml-auto flex items-center gap-8",
8717
8889
  onMouseDown: (e) => e.preventDefault(),
8718
8890
  children: [
8719
8891
  /* @__PURE__ */ jsxRuntime.jsx(