sellmate-design-system-react 0.1.7 → 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 (146) hide show
  1. package/dist/components/SActionModal/SActionModal.cjs +11 -3
  2. package/dist/components/SActionModal/SActionModal.cjs.map +1 -1
  3. package/dist/components/SActionModal/SActionModal.js +11 -3
  4. package/dist/components/SActionModal/SActionModal.js.map +1 -1
  5. package/dist/components/SBarcodeInput/SBarcodeInput.cjs +226 -209
  6. package/dist/components/SBarcodeInput/SBarcodeInput.cjs.map +1 -1
  7. package/dist/components/SBarcodeInput/SBarcodeInput.js +226 -209
  8. package/dist/components/SBarcodeInput/SBarcodeInput.js.map +1 -1
  9. package/dist/components/SCalendar/SCalendar.cjs +9 -1
  10. package/dist/components/SCalendar/SCalendar.cjs.map +1 -1
  11. package/dist/components/SCalendar/SCalendar.js +9 -1
  12. package/dist/components/SCalendar/SCalendar.js.map +1 -1
  13. package/dist/components/SChip/SChip.cjs +9 -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 +9 -1
  17. package/dist/components/SChip/SChip.js.map +1 -1
  18. package/dist/components/SChipInput/SChipInput.cjs +260 -235
  19. package/dist/components/SChipInput/SChipInput.cjs.map +1 -1
  20. package/dist/components/SChipInput/SChipInput.js +259 -235
  21. package/dist/components/SChipInput/SChipInput.js.map +1 -1
  22. package/dist/components/SCircleProgress/SCircleProgress.cjs +56 -58
  23. package/dist/components/SCircleProgress/SCircleProgress.cjs.map +1 -1
  24. package/dist/components/SCircleProgress/SCircleProgress.js +56 -58
  25. package/dist/components/SCircleProgress/SCircleProgress.js.map +1 -1
  26. package/dist/components/SConfirmModal/SConfirmModal.cjs +9 -1
  27. package/dist/components/SConfirmModal/SConfirmModal.cjs.map +1 -1
  28. package/dist/components/SConfirmModal/SConfirmModal.js +9 -1
  29. package/dist/components/SConfirmModal/SConfirmModal.js.map +1 -1
  30. package/dist/components/SDatePicker/SDatePicker.cjs +247 -221
  31. package/dist/components/SDatePicker/SDatePicker.cjs.map +1 -1
  32. package/dist/components/SDatePicker/SDatePicker.js +247 -221
  33. package/dist/components/SDatePicker/SDatePicker.js.map +1 -1
  34. package/dist/components/SDateRangePicker/SDateRangePicker.cjs +308 -256
  35. package/dist/components/SDateRangePicker/SDateRangePicker.cjs.map +1 -1
  36. package/dist/components/SDateRangePicker/SDateRangePicker.js +308 -256
  37. package/dist/components/SDateRangePicker/SDateRangePicker.js.map +1 -1
  38. package/dist/components/SDropdownButton/SDropdownButton.cjs +51 -4
  39. package/dist/components/SDropdownButton/SDropdownButton.cjs.map +1 -1
  40. package/dist/components/SDropdownButton/SDropdownButton.js +52 -5
  41. package/dist/components/SDropdownButton/SDropdownButton.js.map +1 -1
  42. package/dist/components/SField/SField.cjs +226 -21
  43. package/dist/components/SField/SField.cjs.map +1 -1
  44. package/dist/components/SField/SField.d.ts +11 -0
  45. package/dist/components/SField/SField.js +226 -21
  46. package/dist/components/SField/SField.js.map +1 -1
  47. package/dist/components/SFilePicker/SFilePicker.cjs +306 -278
  48. package/dist/components/SFilePicker/SFilePicker.cjs.map +1 -1
  49. package/dist/components/SFilePicker/SFilePicker.d.ts +4 -2
  50. package/dist/components/SFilePicker/SFilePicker.js +306 -278
  51. package/dist/components/SFilePicker/SFilePicker.js.map +1 -1
  52. package/dist/components/SGhostButton/SGhostButton.cjs +8 -0
  53. package/dist/components/SGhostButton/SGhostButton.cjs.map +1 -1
  54. package/dist/components/SGhostButton/SGhostButton.js +8 -0
  55. package/dist/components/SGhostButton/SGhostButton.js.map +1 -1
  56. package/dist/components/SGuide/SGuide.cjs +12 -1
  57. package/dist/components/SGuide/SGuide.cjs.map +1 -1
  58. package/dist/components/SGuide/SGuide.js +12 -1
  59. package/dist/components/SGuide/SGuide.js.map +1 -1
  60. package/dist/components/SInput/SInput.cjs +226 -209
  61. package/dist/components/SInput/SInput.cjs.map +1 -1
  62. package/dist/components/SInput/SInput.js +226 -209
  63. package/dist/components/SInput/SInput.js.map +1 -1
  64. package/dist/components/SKeyValueTable/SKeyValueTable.cjs +640 -453
  65. package/dist/components/SKeyValueTable/SKeyValueTable.cjs.map +1 -1
  66. package/dist/components/SKeyValueTable/SKeyValueTable.d.ts +3 -1
  67. package/dist/components/SKeyValueTable/SKeyValueTable.js +640 -453
  68. package/dist/components/SKeyValueTable/SKeyValueTable.js.map +1 -1
  69. package/dist/components/SLoadingContainer/SLoadingContainer.cjs +64 -58
  70. package/dist/components/SLoadingContainer/SLoadingContainer.cjs.map +1 -1
  71. package/dist/components/SLoadingContainer/SLoadingContainer.js +64 -58
  72. package/dist/components/SLoadingContainer/SLoadingContainer.js.map +1 -1
  73. package/dist/components/SLoadingContainer/loading.cjs +64 -58
  74. package/dist/components/SLoadingContainer/loading.cjs.map +1 -1
  75. package/dist/components/SLoadingContainer/loading.js +64 -58
  76. package/dist/components/SLoadingContainer/loading.js.map +1 -1
  77. package/dist/components/SLoadingModal/SLoadingModal.cjs +68 -61
  78. package/dist/components/SLoadingModal/SLoadingModal.cjs.map +1 -1
  79. package/dist/components/SLoadingModal/SLoadingModal.js +68 -61
  80. package/dist/components/SLoadingModal/SLoadingModal.js.map +1 -1
  81. package/dist/components/SModalContainer/SModalContainer.cjs +9 -1
  82. package/dist/components/SModalContainer/SModalContainer.cjs.map +1 -1
  83. package/dist/components/SModalContainer/SModalContainer.js +9 -1
  84. package/dist/components/SModalContainer/SModalContainer.js.map +1 -1
  85. package/dist/components/SNumberInput/SNumberInput.cjs +334 -50
  86. package/dist/components/SNumberInput/SNumberInput.cjs.map +1 -1
  87. package/dist/components/SNumberInput/SNumberInput.d.ts +2 -0
  88. package/dist/components/SNumberInput/SNumberInput.js +334 -50
  89. package/dist/components/SNumberInput/SNumberInput.js.map +1 -1
  90. package/dist/components/SPagination/SPagination.cjs +1 -1
  91. package/dist/components/SPagination/SPagination.cjs.map +1 -1
  92. package/dist/components/SPagination/SPagination.js +1 -1
  93. package/dist/components/SPagination/SPagination.js.map +1 -1
  94. package/dist/components/SPopover/SPopover.cjs +20 -3
  95. package/dist/components/SPopover/SPopover.cjs.map +1 -1
  96. package/dist/components/SPopover/SPopover.js +20 -4
  97. package/dist/components/SPopover/SPopover.js.map +1 -1
  98. package/dist/components/SPopup/SPopup.cjs +2 -2
  99. package/dist/components/SPopup/SPopup.cjs.map +1 -1
  100. package/dist/components/SPopup/SPopup.js +2 -2
  101. package/dist/components/SPopup/SPopup.js.map +1 -1
  102. package/dist/components/SPortal/SPortal.cjs +8 -0
  103. package/dist/components/SPortal/SPortal.cjs.map +1 -1
  104. package/dist/components/SPortal/SPortal.js +8 -0
  105. package/dist/components/SPortal/SPortal.js.map +1 -1
  106. package/dist/components/SSelect/SSelect.cjs +76 -32
  107. package/dist/components/SSelect/SSelect.cjs.map +1 -1
  108. package/dist/components/SSelect/SSelect.js +76 -32
  109. package/dist/components/SSelect/SSelect.js.map +1 -1
  110. package/dist/components/STable/STable.cjs +133 -91
  111. package/dist/components/STable/STable.cjs.map +1 -1
  112. package/dist/components/STable/STable.js +133 -91
  113. package/dist/components/STable/STable.js.map +1 -1
  114. package/dist/components/STextLink/STextLink.cjs +137 -3
  115. package/dist/components/STextLink/STextLink.cjs.map +1 -1
  116. package/dist/components/STextLink/STextLink.d.ts +1 -1
  117. package/dist/components/STextLink/STextLink.js +118 -4
  118. package/dist/components/STextLink/STextLink.js.map +1 -1
  119. package/dist/components/STextarea/STextarea.cjs +226 -21
  120. package/dist/components/STextarea/STextarea.cjs.map +1 -1
  121. package/dist/components/STextarea/STextarea.js +226 -21
  122. package/dist/components/STextarea/STextarea.js.map +1 -1
  123. package/dist/components/SToast/SToast.cjs +8 -0
  124. package/dist/components/SToast/SToast.cjs.map +1 -1
  125. package/dist/components/SToast/SToast.js +8 -0
  126. package/dist/components/SToast/SToast.js.map +1 -1
  127. package/dist/components/SToast/SToastContainer.cjs +11 -3
  128. package/dist/components/SToast/SToastContainer.cjs.map +1 -1
  129. package/dist/components/SToast/SToastContainer.js +11 -3
  130. package/dist/components/SToast/SToastContainer.js.map +1 -1
  131. package/dist/components/STooltip/STooltip.cjs +217 -14
  132. package/dist/components/STooltip/STooltip.cjs.map +1 -1
  133. package/dist/components/STooltip/STooltip.js +217 -14
  134. package/dist/components/STooltip/STooltip.js.map +1 -1
  135. package/dist/index.cjs +532 -300
  136. package/dist/index.cjs.map +1 -1
  137. package/dist/index.js +531 -300
  138. package/dist/index.js.map +1 -1
  139. package/dist/lib/floating-anim.cjs +8 -0
  140. package/dist/lib/floating-anim.cjs.map +1 -1
  141. package/dist/lib/floating-anim.d.ts +5 -1
  142. package/dist/lib/floating-anim.js +8 -0
  143. package/dist/lib/floating-anim.js.map +1 -1
  144. package/dist/styles.css +175 -66
  145. package/dist/theme.css +49 -22
  146. package/package.json +1 -1
@@ -5,7 +5,7 @@ var react = require('react');
5
5
  var clsx = require('clsx');
6
6
  var tailwindMerge = require('tailwind-merge');
7
7
  var jsxRuntime = require('react/jsx-runtime');
8
- var RPopover = require('@radix-ui/react-popover');
8
+ var RPopover2 = require('@radix-ui/react-popover');
9
9
 
10
10
  function _interopNamespace(e) {
11
11
  if (e && e.__esModule) return e;
@@ -25,7 +25,7 @@ function _interopNamespace(e) {
25
25
  return Object.freeze(n);
26
26
  }
27
27
 
28
- var RPopover__namespace = /*#__PURE__*/_interopNamespace(RPopover);
28
+ var RPopover2__namespace = /*#__PURE__*/_interopNamespace(RPopover2);
29
29
 
30
30
  var twMerge = tailwindMerge.extendTailwindMerge({
31
31
  extend: {
@@ -2876,12 +2876,20 @@ var SIcon = react.forwardRef(function SIcon2({ name, size = 24, color, rotate, l
2876
2876
  // src/lib/floating-anim.ts
2877
2877
  var FLOATING_SLIDE_ANIM = [
2878
2878
  "data-[state=open]:data-[side=top]:animate-floating-in-top",
2879
+ "data-[state=delayed-open]:data-[side=top]:animate-floating-in-top",
2880
+ "data-[state=instant-open]:data-[side=top]:animate-floating-in-top",
2879
2881
  "data-[state=closed]:data-[side=top]:animate-floating-out-top",
2880
2882
  "data-[state=open]:data-[side=bottom]:animate-floating-in-bottom",
2883
+ "data-[state=delayed-open]:data-[side=bottom]:animate-floating-in-bottom",
2884
+ "data-[state=instant-open]:data-[side=bottom]:animate-floating-in-bottom",
2881
2885
  "data-[state=closed]:data-[side=bottom]:animate-floating-out-bottom",
2882
2886
  "data-[state=open]:data-[side=left]:animate-floating-in-left",
2887
+ "data-[state=delayed-open]:data-[side=left]:animate-floating-in-left",
2888
+ "data-[state=instant-open]:data-[side=left]:animate-floating-in-left",
2883
2889
  "data-[state=closed]:data-[side=left]:animate-floating-out-left",
2884
2890
  "data-[state=open]:data-[side=right]:animate-floating-in-right",
2891
+ "data-[state=delayed-open]:data-[side=right]:animate-floating-in-right",
2892
+ "data-[state=instant-open]:data-[side=right]:animate-floating-in-right",
2885
2893
  "data-[state=closed]:data-[side=right]:animate-floating-out-right"
2886
2894
  ].join(" ");
2887
2895
  var PortalContainerContext = react.createContext(null);
@@ -2889,11 +2897,200 @@ PortalContainerContext.Provider;
2889
2897
  function usePortalContainer() {
2890
2898
  return react.useContext(PortalContainerContext) ?? void 0;
2891
2899
  }
2900
+
2901
+ // src/components/STag/tag.config.ts
2902
+ var TAG_SIZE_CONFIG = {
2903
+ xs: {
2904
+ height: 20,
2905
+ paddingX: 8,
2906
+ gap: 4,
2907
+ radius: 6,
2908
+ iconSize: 12,
2909
+ fontSize: 11,
2910
+ fontWeight: 500,
2911
+ lineHeight: 18
2912
+ },
2913
+ sm: {
2914
+ height: 24,
2915
+ paddingX: 8,
2916
+ gap: 4,
2917
+ radius: 6,
2918
+ iconSize: 16,
2919
+ fontSize: 12,
2920
+ fontWeight: 700,
2921
+ lineHeight: 20
2922
+ },
2923
+ md: {
2924
+ height: 28,
2925
+ paddingX: 12,
2926
+ gap: 6,
2927
+ radius: 8,
2928
+ iconSize: 16,
2929
+ fontSize: 14,
2930
+ fontWeight: 700,
2931
+ lineHeight: 24
2932
+ }
2933
+ };
2934
+ var STag = react.forwardRef(function STag2({
2935
+ shape = "square",
2936
+ size = "sm",
2937
+ color = "grey",
2938
+ label = "",
2939
+ icon,
2940
+ iconLeft = true,
2941
+ width,
2942
+ className,
2943
+ style,
2944
+ ...rest
2945
+ }, ref) {
2946
+ const s = TAG_SIZE_CONFIG[size];
2947
+ const contentColor = `var(--cmp-tag-${color}-content)`;
2948
+ const iconNode = icon ? /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.iconSize, color: contentColor }) : null;
2949
+ const resolvedWidth = typeof width === "number" ? `${width}px` : width;
2950
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2951
+ "span",
2952
+ {
2953
+ ref,
2954
+ "aria-label": label || "tag",
2955
+ className: cn(
2956
+ "box-border inline-flex w-fit select-none items-center justify-center whitespace-nowrap",
2957
+ className
2958
+ ),
2959
+ style: {
2960
+ minHeight: s.height,
2961
+ padding: `0 ${s.paddingX}px`,
2962
+ gap: s.gap,
2963
+ borderRadius: shape === "pill" ? 999 : s.radius,
2964
+ fontSize: s.fontSize,
2965
+ fontWeight: s.fontWeight,
2966
+ lineHeight: `${s.lineHeight}px`,
2967
+ background: `var(--cmp-tag-${color}-bg)`,
2968
+ color: contentColor,
2969
+ ...resolvedWidth != null ? { width: resolvedWidth } : {},
2970
+ ...style
2971
+ },
2972
+ ...rest,
2973
+ children: [
2974
+ icon && iconLeft && iconNode,
2975
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex min-w-0 items-center justify-center", children: label }),
2976
+ icon && !iconLeft && iconNode
2977
+ ]
2978
+ }
2979
+ );
2980
+ });
2981
+ var SIZE = {
2982
+ xxs: { icon: 12, radius: "sm" },
2983
+ xs: { icon: 16, radius: "sm" },
2984
+ sm: { icon: 20, radius: "sm" },
2985
+ md: { icon: 24, radius: "md" },
2986
+ lg: { icon: 32, radius: "md" }
2987
+ };
2988
+ var TOOLTIP_HIDE_DELAY_MS = 100;
2989
+ function SGhostButton({
2990
+ icon,
2991
+ size = "sm",
2992
+ intent = "default",
2993
+ ariaLabel = "",
2994
+ tooltipText,
2995
+ disabled = false,
2996
+ onClick,
2997
+ className,
2998
+ style
2999
+ }) {
3000
+ const portalContainer = usePortalContainer();
3001
+ const [open, setOpen] = react.useState(false);
3002
+ const hideTimer = react.useRef(void 0);
3003
+ const cancelHide = () => {
3004
+ if (hideTimer.current) {
3005
+ clearTimeout(hideTimer.current);
3006
+ hideTimer.current = void 0;
3007
+ }
3008
+ };
3009
+ const openNow = () => {
3010
+ cancelHide();
3011
+ setOpen(true);
3012
+ };
3013
+ const startHide = () => {
3014
+ cancelHide();
3015
+ hideTimer.current = setTimeout(() => setOpen(false), TOOLTIP_HIDE_DELAY_MS);
3016
+ };
3017
+ const s = SIZE[size];
3018
+ const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
3019
+ const btn = /* @__PURE__ */ jsxRuntime.jsxs(
3020
+ "button",
3021
+ {
3022
+ type: "button",
3023
+ disabled,
3024
+ "aria-disabled": disabled ? "true" : void 0,
3025
+ "aria-label": ariaLabel.trim() || void 0,
3026
+ tabIndex: disabled ? -1 : void 0,
3027
+ onClick: (e) => {
3028
+ if (disabled) {
3029
+ e.preventDefault();
3030
+ return;
3031
+ }
3032
+ onClick?.(e);
3033
+ },
3034
+ className: cn(
3035
+ "group relative box-border inline-flex items-center justify-center border-none bg-transparent p-0 transition-shadow",
3036
+ disabled ? "cursor-not-allowed" : "cursor-pointer",
3037
+ "focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
3038
+ className
3039
+ ),
3040
+ style: {
3041
+ width: `var(--cmp-ghostButton-${size}-size)`,
3042
+ height: `var(--cmp-ghostButton-${size}-size)`,
3043
+ borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
3044
+ ...style
3045
+ },
3046
+ children: [
3047
+ !disabled && /* @__PURE__ */ jsxRuntime.jsx(
3048
+ "span",
3049
+ {
3050
+ "aria-hidden": true,
3051
+ className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover:opacity-5",
3052
+ style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
3053
+ }
3054
+ ),
3055
+ /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.icon, color: contentColor })
3056
+ ]
3057
+ }
3058
+ );
3059
+ const text = (tooltipText ?? "").trim();
3060
+ if (text === "") return btn;
3061
+ return /* @__PURE__ */ jsxRuntime.jsxs(RPopover2__namespace.Root, { open, onOpenChange: setOpen, children: [
3062
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
3063
+ "span",
3064
+ {
3065
+ className: "inline-flex",
3066
+ onMouseEnter: openNow,
3067
+ onMouseLeave: startHide,
3068
+ onFocus: openNow,
3069
+ onBlur: startHide,
3070
+ children: btn
3071
+ }
3072
+ ) }),
3073
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
3074
+ RPopover2__namespace.Content,
3075
+ {
3076
+ side: "top",
3077
+ sideOffset: 4,
3078
+ className: cn("z-50", FLOATING_SLIDE_ANIM),
3079
+ "aria-hidden": true,
3080
+ onOpenAutoFocus: (e) => e.preventDefault(),
3081
+ onMouseEnter: cancelHide,
3082
+ onMouseLeave: startHide,
3083
+ children: /* @__PURE__ */ jsxRuntime.jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
3084
+ }
3085
+ ) })
3086
+ ] });
3087
+ }
2892
3088
  var HIDE_DELAY_MS = 100;
2893
3089
  function useBody(content, message = []) {
2894
3090
  if (content != null) return content;
2895
3091
  if (message.length === 0) return null;
2896
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: message.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: line }, i)) });
3092
+ const singleLine = message.length === 1;
3093
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: message.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: singleLine ? "leading-[24px]" : void 0, children: line }, i)) });
2897
3094
  }
2898
3095
  var STooltip = react.forwardRef(function STooltip2({
2899
3096
  content,
@@ -2951,7 +3148,7 @@ var STooltip = react.forwardRef(function STooltip2({
2951
3148
  if (disabled || body == null) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: triggerNode });
2952
3149
  const isHover = trigger === "hover";
2953
3150
  const contentClass = cn(
2954
- "z-50 max-w-xs rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px]",
3151
+ "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)]",
2955
3152
  FLOATING_SLIDE_ANIM,
2956
3153
  className
2957
3154
  );
@@ -2961,10 +3158,10 @@ var STooltip = react.forwardRef(function STooltip2({
2961
3158
  fontWeight: tooltipType === "default" ? 500 : 700,
2962
3159
  ...style
2963
3160
  };
2964
- return /* @__PURE__ */ jsxRuntime.jsxs(RPopover__namespace.Root, { open, onOpenChange: setOpen, children: [
3161
+ return /* @__PURE__ */ jsxRuntime.jsxs(RPopover2__namespace.Root, { open, onOpenChange: setOpen, children: [
2965
3162
  isHover ? (
2966
3163
  // hover: Anchor(위치 기준) + 직접 mouse 핸들러 — 클릭으로 토글되지 않도록 Trigger 미사용
2967
- /* @__PURE__ */ jsxRuntime.jsx(RPopover__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
3164
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
2968
3165
  "span",
2969
3166
  {
2970
3167
  className: "inline-flex",
@@ -2975,9 +3172,9 @@ var STooltip = react.forwardRef(function STooltip2({
2975
3172
  children: triggerNode
2976
3173
  }
2977
3174
  ) })
2978
- ) : /* @__PURE__ */ jsxRuntime.jsx(RPopover__namespace.Trigger, { asChild: true, children: triggerNode }),
2979
- /* @__PURE__ */ jsxRuntime.jsx(RPopover__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
2980
- RPopover__namespace.Content,
3175
+ ) : /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Trigger, { asChild: true, children: triggerNode }),
3176
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
3177
+ RPopover2__namespace.Content,
2981
3178
  {
2982
3179
  side: placement,
2983
3180
  sideOffset: 8,
@@ -2996,15 +3193,21 @@ var STooltip = react.forwardRef(function STooltip2({
2996
3193
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-[12px]", children: [
2997
3194
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: body }),
2998
3195
  useClose && /* @__PURE__ */ jsxRuntime.jsx(
2999
- RPopover__namespace.Close,
3196
+ SGhostButton,
3000
3197
  {
3001
- "aria-label": "\uB2EB\uAE30",
3002
- className: "shrink-0 cursor-pointer opacity-70 hover:opacity-100",
3003
- children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 16, color: fg })
3198
+ icon: "close",
3199
+ size: "xs",
3200
+ intent: tooltipType === "default" ? "inverse" : "default",
3201
+ ariaLabel: "\uB2EB\uAE30",
3202
+ className: "shrink-0",
3203
+ onClick: () => {
3204
+ cancelHide();
3205
+ setOpen(false);
3206
+ }
3004
3207
  }
3005
3208
  )
3006
3209
  ] }),
3007
- /* @__PURE__ */ jsxRuntime.jsx(RPopover__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
3210
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
3008
3211
  ]
3009
3212
  }
3010
3213
  ) })
@@ -3038,8 +3241,8 @@ function useFormField(field) {
3038
3241
  }, [ctx, name]);
3039
3242
  }
3040
3243
  var FIELD_SIZE = {
3041
- sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon: 12 },
3042
- md: { height: 36, radius: 6, fieldGap: 16, labelGap: 8, fontSize: 14, lineHeight: 24, icon: 12 }
3244
+ sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon: 16 },
3245
+ md: { height: 36, radius: 6, fieldGap: 16, labelGap: 8, fontSize: 14, lineHeight: 24, icon: 16 }
3043
3246
  };
3044
3247
  var ALIGN = {
3045
3248
  start: "flex-start",
@@ -3054,6 +3257,7 @@ var SField = react.forwardRef(function SField2({
3054
3257
  labelTooltip = "",
3055
3258
  labelTooltipProps,
3056
3259
  labelWidth,
3260
+ labelHeight,
3057
3261
  size = "sm",
3058
3262
  addonLabel = "",
3059
3263
  addonAlign = "start",
@@ -3068,6 +3272,7 @@ var SField = react.forwardRef(function SField2({
3068
3272
  readOnly = false,
3069
3273
  width,
3070
3274
  multiline = false,
3275
+ borderless = false,
3071
3276
  children,
3072
3277
  className,
3073
3278
  style,
@@ -3101,8 +3306,8 @@ var SField = react.forwardRef(function SField2({
3101
3306
  const resolvedSuccess = status === "pass";
3102
3307
  const showError = resolvedError && errorMessage !== "";
3103
3308
  const interactive = !disabled && !readOnly;
3104
- 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)";
3105
- const bgColor = disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
3309
+ 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)";
3310
+ const bgColor = borderless ? "transparent" : disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
3106
3311
  const textColor = disabled ? "var(--color-grey-65)" : readOnly ? "var(--sys-color-field-text-readOnly)" : "var(--sys-color-field-text-default)";
3107
3312
  return /* @__PURE__ */ jsxRuntime.jsx(
3108
3313
  "div",
@@ -3119,7 +3324,7 @@ var SField = react.forwardRef(function SField2({
3119
3324
  {
3120
3325
  className: "flex shrink-0 items-center font-bold text-(--sys-color-field-text-default)",
3121
3326
  style: {
3122
- height: s.height,
3327
+ height: cssLen(labelHeight) ?? s.height,
3123
3328
  marginRight: s.fieldGap,
3124
3329
  width: cssLen(labelWidth),
3125
3330
  fontSize: s.fontSize,
@@ -3145,14 +3350,14 @@ var SField = react.forwardRef(function SField2({
3145
3350
  {
3146
3351
  className: cn(
3147
3352
  "relative box-border flex min-w-0 items-stretch overflow-hidden border border-solid border-(--field-bc)",
3148
- 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]",
3353
+ 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]",
3149
3354
  disabled && "cursor-not-allowed"
3150
3355
  ),
3151
3356
  style: {
3152
3357
  // @ts-expect-error CSS 변수
3153
3358
  "--field-bc": borderColor,
3154
3359
  // focused/hovered prop이 명시된 경우 강조를 즉시 반영
3155
- ...interactive && focused ? { boxShadow: "0px 0px 4px 0px #0071ff66" } : {},
3360
+ ...interactive && !borderless && focused ? { boxShadow: "0px 0px 4px 0px #0071ff66" } : {},
3156
3361
  ...multiline ? { minHeight: s.height } : { height: s.height },
3157
3362
  "width": cssLen(width),
3158
3363
  "borderRadius": s.radius,
@@ -3191,200 +3396,12 @@ var SField = react.forwardRef(function SField2({
3191
3396
  }
3192
3397
  );
3193
3398
  });
3194
-
3195
- // src/components/STag/tag.config.ts
3196
- var TAG_SIZE_CONFIG = {
3197
- xs: {
3198
- height: 20,
3199
- paddingX: 8,
3200
- gap: 4,
3201
- radius: 6,
3202
- iconSize: 12,
3203
- fontSize: 11,
3204
- fontWeight: 500,
3205
- lineHeight: 18
3206
- },
3207
- sm: {
3208
- height: 24,
3209
- paddingX: 8,
3210
- gap: 4,
3211
- radius: 6,
3212
- iconSize: 16,
3213
- fontSize: 12,
3214
- fontWeight: 700,
3215
- lineHeight: 20
3216
- },
3217
- md: {
3218
- height: 28,
3219
- paddingX: 12,
3220
- gap: 6,
3221
- radius: 8,
3222
- iconSize: 16,
3223
- fontSize: 14,
3224
- fontWeight: 700,
3225
- lineHeight: 24
3226
- }
3227
- };
3228
- var STag = react.forwardRef(function STag2({
3229
- shape = "square",
3230
- size = "sm",
3231
- color = "grey",
3232
- label = "",
3233
- icon,
3234
- iconLeft = true,
3235
- width,
3236
- className,
3237
- style,
3238
- ...rest
3239
- }, ref) {
3240
- const s = TAG_SIZE_CONFIG[size];
3241
- const contentColor = `var(--cmp-tag-${color}-content)`;
3242
- const iconNode = icon ? /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.iconSize, color: contentColor }) : null;
3243
- const resolvedWidth = typeof width === "number" ? `${width}px` : width;
3244
- return /* @__PURE__ */ jsxRuntime.jsxs(
3245
- "span",
3246
- {
3247
- ref,
3248
- "aria-label": label || "tag",
3249
- className: cn(
3250
- "box-border inline-flex w-fit select-none items-center justify-center whitespace-nowrap",
3251
- className
3252
- ),
3253
- style: {
3254
- minHeight: s.height,
3255
- padding: `0 ${s.paddingX}px`,
3256
- gap: s.gap,
3257
- borderRadius: shape === "pill" ? 999 : s.radius,
3258
- fontSize: s.fontSize,
3259
- fontWeight: s.fontWeight,
3260
- lineHeight: `${s.lineHeight}px`,
3261
- background: `var(--cmp-tag-${color}-bg)`,
3262
- color: contentColor,
3263
- ...resolvedWidth != null ? { width: resolvedWidth } : {},
3264
- ...style
3265
- },
3266
- ...rest,
3267
- children: [
3268
- icon && iconLeft && iconNode,
3269
- label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex min-w-0 items-center justify-center", children: label }),
3270
- icon && !iconLeft && iconNode
3271
- ]
3272
- }
3273
- );
3274
- });
3275
- var SIZE = {
3276
- xxs: { icon: 12, radius: "sm" },
3277
- xs: { icon: 16, radius: "sm" },
3278
- sm: { icon: 20, radius: "sm" },
3279
- md: { icon: 24, radius: "md" },
3280
- lg: { icon: 32, radius: "md" }
3281
- };
3282
- var TOOLTIP_HIDE_DELAY_MS = 100;
3283
- function SGhostButton({
3284
- icon,
3285
- size = "sm",
3286
- intent = "default",
3287
- ariaLabel = "",
3288
- tooltipText,
3289
- disabled = false,
3290
- onClick,
3291
- className,
3292
- style
3293
- }) {
3294
- const portalContainer = usePortalContainer();
3295
- const [open, setOpen] = react.useState(false);
3296
- const hideTimer = react.useRef(void 0);
3297
- const cancelHide = () => {
3298
- if (hideTimer.current) {
3299
- clearTimeout(hideTimer.current);
3300
- hideTimer.current = void 0;
3301
- }
3302
- };
3303
- const openNow = () => {
3304
- cancelHide();
3305
- setOpen(true);
3306
- };
3307
- const startHide = () => {
3308
- cancelHide();
3309
- hideTimer.current = setTimeout(() => setOpen(false), TOOLTIP_HIDE_DELAY_MS);
3310
- };
3311
- const s = SIZE[size];
3312
- const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
3313
- const btn = /* @__PURE__ */ jsxRuntime.jsxs(
3314
- "button",
3315
- {
3316
- type: "button",
3317
- disabled,
3318
- "aria-disabled": disabled ? "true" : void 0,
3319
- "aria-label": ariaLabel.trim() || void 0,
3320
- tabIndex: disabled ? -1 : void 0,
3321
- onClick: (e) => {
3322
- if (disabled) {
3323
- e.preventDefault();
3324
- return;
3325
- }
3326
- onClick?.(e);
3327
- },
3328
- className: cn(
3329
- "group relative box-border inline-flex items-center justify-center border-none bg-transparent p-0 transition-shadow",
3330
- disabled ? "cursor-not-allowed" : "cursor-pointer",
3331
- "focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
3332
- className
3333
- ),
3334
- style: {
3335
- width: `var(--cmp-ghostButton-${size}-size)`,
3336
- height: `var(--cmp-ghostButton-${size}-size)`,
3337
- borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
3338
- ...style
3339
- },
3340
- children: [
3341
- !disabled && /* @__PURE__ */ jsxRuntime.jsx(
3342
- "span",
3343
- {
3344
- "aria-hidden": true,
3345
- className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover:opacity-5",
3346
- style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
3347
- }
3348
- ),
3349
- /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.icon, color: contentColor })
3350
- ]
3351
- }
3352
- );
3353
- const text = (tooltipText ?? "").trim();
3354
- if (text === "") return btn;
3355
- return /* @__PURE__ */ jsxRuntime.jsxs(RPopover__namespace.Root, { open, onOpenChange: setOpen, children: [
3356
- /* @__PURE__ */ jsxRuntime.jsx(RPopover__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
3357
- "span",
3358
- {
3359
- className: "inline-flex",
3360
- onMouseEnter: openNow,
3361
- onMouseLeave: startHide,
3362
- onFocus: openNow,
3363
- onBlur: startHide,
3364
- children: btn
3365
- }
3366
- ) }),
3367
- /* @__PURE__ */ jsxRuntime.jsx(RPopover__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
3368
- RPopover__namespace.Content,
3369
- {
3370
- side: "top",
3371
- sideOffset: 4,
3372
- className: cn("z-50", FLOATING_SLIDE_ANIM),
3373
- "aria-hidden": true,
3374
- onOpenAutoFocus: (e) => e.preventDefault(),
3375
- onMouseEnter: cancelHide,
3376
- onMouseLeave: startHide,
3377
- children: /* @__PURE__ */ jsxRuntime.jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
3378
- }
3379
- ) })
3380
- ] });
3381
- }
3382
3399
  var SChip = react.forwardRef(function SChip2({
3383
3400
  name,
3384
3401
  value = "",
3385
3402
  error: errorProp = false,
3386
3403
  disabled = false,
3387
- editable = true,
3404
+ editable = false,
3388
3405
  showRemove = true,
3389
3406
  placeholder = "",
3390
3407
  rules,
@@ -3537,6 +3554,7 @@ function SFilePicker({
3537
3554
  hovered = false,
3538
3555
  inline = false,
3539
3556
  multiple = false,
3557
+ useMultipleListBox = false,
3540
3558
  accept,
3541
3559
  maxFileSize,
3542
3560
  maxTotalSize,
@@ -3564,8 +3582,8 @@ function SFilePicker({
3564
3582
  const inputRef = react.useRef(null);
3565
3583
  const [ruleError, setRuleError] = react.useState("");
3566
3584
  const files = multiple ? Array.isArray(value) ? value : [] : value && !Array.isArray(value) ? value : null;
3567
- const hasSingle = !multiple && !!files;
3568
- const displayText = hasSingle ? files.name : placeholder;
3585
+ const hasFiles = multiple ? files.length > 0 : !!files;
3586
+ const displayText = !hasFiles ? placeholder : multiple ? files.map((f) => f.name).join(", ") : files.name;
3569
3587
  useFormField({
3570
3588
  name,
3571
3589
  validate: () => {
@@ -3629,78 +3647,88 @@ function SFilePicker({
3629
3647
  const padX = size === "md" ? "var(--cmp-filepicker-md-paddingX)" : "var(--cmp-filepicker-sm-paddingX)";
3630
3648
  const iconSize = size === "md" ? 20 : 16;
3631
3649
  const gapCls = size === "md" ? "gap-[var(--cmp-filepicker-md-gap)]" : "gap-[var(--cmp-filepicker-sm-gap)]";
3632
- const content = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex h-full w-full items-center", gapCls), style: { padding: `0 ${padX}` }, children: [
3633
- /* @__PURE__ */ jsxRuntime.jsx(
3634
- "input",
3635
- {
3636
- ref: inputRef,
3637
- type: "file",
3638
- className: "hidden",
3639
- disabled,
3640
- multiple,
3641
- accept,
3642
- name: resolvedName,
3643
- onChange,
3644
- "aria-label": placeholder
3645
- }
3646
- ),
3647
- /* @__PURE__ */ jsxRuntime.jsxs(
3648
- "button",
3649
- {
3650
- type: "button",
3651
- disabled,
3652
- onClick: open,
3653
- "aria-label": placeholder,
3654
- className: cn(
3655
- "flex min-w-0 flex-1 items-center bg-transparent text-left",
3656
- gapCls,
3657
- disabled ? "cursor-not-allowed" : "cursor-pointer"
3650
+ const inlinePlaceholder = inline && !disabled && !hasFiles;
3651
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(
3652
+ "div",
3653
+ {
3654
+ className: cn("group/filepicker flex h-full w-full items-center", gapCls),
3655
+ style: { padding: inline ? 0 : `0 ${padX}` },
3656
+ children: [
3657
+ /* @__PURE__ */ jsxRuntime.jsx(
3658
+ "input",
3659
+ {
3660
+ ref: inputRef,
3661
+ type: "file",
3662
+ className: "hidden",
3663
+ disabled,
3664
+ multiple,
3665
+ accept,
3666
+ name: resolvedName,
3667
+ onChange,
3668
+ "aria-label": placeholder
3669
+ }
3670
+ ),
3671
+ /* @__PURE__ */ jsxRuntime.jsxs(
3672
+ "button",
3673
+ {
3674
+ type: "button",
3675
+ disabled,
3676
+ onClick: open,
3677
+ "aria-label": placeholder,
3678
+ className: cn(
3679
+ "flex min-w-0 flex-1 items-center bg-transparent text-left",
3680
+ gapCls,
3681
+ disabled ? "cursor-not-allowed" : "cursor-pointer"
3682
+ ),
3683
+ children: [
3684
+ /* @__PURE__ */ jsxRuntime.jsx(
3685
+ SIcon,
3686
+ {
3687
+ name: "attachFile",
3688
+ size: iconSize,
3689
+ color: disabled ? "var(--cmp-filepicker-icon-disabled)" : "var(--color-grey-65)"
3690
+ }
3691
+ ),
3692
+ /* @__PURE__ */ jsxRuntime.jsx(
3693
+ "span",
3694
+ {
3695
+ className: cn(
3696
+ "min-w-0 flex-1 truncate text-[12px]",
3697
+ inlinePlaceholder && "text-[color:var(--cmp-filepicker-text-placeholder)] transition-colors group-hover/filepicker:text-[color:var(--cmp-filepicker-text-default)]"
3698
+ ),
3699
+ style: inlinePlaceholder ? void 0 : {
3700
+ color: disabled ? "var(--cmp-filepicker-text-disabled)" : hasFiles ? "var(--cmp-filepicker-text-default)" : "var(--cmp-filepicker-text-placeholder)"
3701
+ },
3702
+ children: displayText
3703
+ }
3704
+ )
3705
+ ]
3706
+ }
3658
3707
  ),
3659
- children: [
3660
- /* @__PURE__ */ jsxRuntime.jsx(
3661
- SIcon,
3662
- {
3663
- name: "attachFile",
3664
- size: iconSize,
3665
- color: disabled ? "var(--cmp-filepicker-icon-disabled)" : "var(--color-grey-65)"
3666
- }
3667
- ),
3668
- /* @__PURE__ */ jsxRuntime.jsx(
3669
- "span",
3670
- {
3671
- className: "min-w-0 flex-1 truncate text-[12px]",
3672
- style: {
3673
- color: disabled ? "var(--cmp-filepicker-text-disabled)" : hasSingle ? "var(--cmp-filepicker-text-default)" : "var(--cmp-filepicker-text-placeholder)"
3674
- },
3675
- children: displayText
3676
- }
3677
- )
3678
- ]
3679
- }
3680
- ),
3681
- !disabled && hasSingle && /* @__PURE__ */ jsxRuntime.jsx(SGhostButton, { icon: "close", size: "xxs", ariaLabel: "clear", onClick: clear })
3682
- ] });
3683
- 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)) });
3684
- if (inline) {
3685
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("inline-flex flex-col", className), style, children: [
3686
- /* @__PURE__ */ jsxRuntime.jsx(
3687
- "div",
3688
- {
3689
- 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)]",
3690
- style: {
3691
- height: "var(--cmp-filepicker-sm-height)",
3692
- width: typeof width === "number" ? `${width}px` : width
3693
- },
3694
- children: content
3695
- }
3708
+ !disabled && hasFiles && /* @__PURE__ */ jsxRuntime.jsx(SGhostButton, { icon: "close", size: "xxs", ariaLabel: "clear", onClick: clear })
3709
+ ]
3710
+ }
3711
+ );
3712
+ const chips = multiple && files.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
3713
+ "div",
3714
+ {
3715
+ className: cn(
3716
+ "mt-[8px] flex gap-[8px]",
3717
+ 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"
3696
3718
  ),
3697
- chips
3698
- ] });
3699
- }
3719
+ style: useMultipleListBox ? {
3720
+ width: typeof width === "number" ? `${width}px` : width,
3721
+ // label 이 있으면 SField 입력 박스 시작 위치(labelWidth + fieldGap)에 맞춰 정렬
3722
+ marginLeft: label && labelWidth != null ? `calc(${typeof labelWidth === "number" ? `${labelWidth}px` : labelWidth} + var(--sys-space-field-${size}-gap))` : void 0
3723
+ } : void 0,
3724
+ children: files.map((f, i) => /* @__PURE__ */ jsxRuntime.jsx(SChip, { value: f.name, editable: false, onRemove: () => removeChip(i) }, i))
3725
+ }
3726
+ );
3700
3727
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style, children: [
3701
3728
  /* @__PURE__ */ jsxRuntime.jsx(
3702
3729
  SField,
3703
3730
  {
3731
+ borderless: inline,
3704
3732
  label,
3705
3733
  labelWidth,
3706
3734
  icon,