sellmate-design-system-react 2.1.2 → 3.0.0

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 (47) hide show
  1. package/dist/components/SCallout/SCallout.cjs +76 -1
  2. package/dist/components/SCallout/SCallout.cjs.map +1 -1
  3. package/dist/components/SCallout/SCallout.d.ts +6 -2
  4. package/dist/components/SCallout/SCallout.js +76 -1
  5. package/dist/components/SCallout/SCallout.js.map +1 -1
  6. package/dist/components/SDraggableItem/SDraggableItem.cjs +3079 -0
  7. package/dist/components/SDraggableItem/SDraggableItem.cjs.map +1 -0
  8. package/dist/components/SDraggableItem/SDraggableItem.d.ts +33 -0
  9. package/dist/components/SDraggableItem/SDraggableItem.js +3077 -0
  10. package/dist/components/SDraggableItem/SDraggableItem.js.map +1 -0
  11. package/dist/components/SDraggableItem/index.d.ts +1 -0
  12. package/dist/components/SExpansionItem/SExpansionItem.cjs +6 -15
  13. package/dist/components/SExpansionItem/SExpansionItem.cjs.map +1 -1
  14. package/dist/components/SExpansionItem/SExpansionItem.js +6 -15
  15. package/dist/components/SExpansionItem/SExpansionItem.js.map +1 -1
  16. package/dist/components/SList/SList.cjs +38 -0
  17. package/dist/components/SList/SList.cjs.map +1 -0
  18. package/dist/components/SList/SList.d.ts +10 -0
  19. package/dist/components/SList/SList.js +36 -0
  20. package/dist/components/SList/SList.js.map +1 -0
  21. package/dist/components/SList/index.d.ts +1 -0
  22. package/dist/components/SListItem/SListItem.cjs +83 -0
  23. package/dist/components/SListItem/SListItem.cjs.map +1 -0
  24. package/dist/components/SListItem/SListItem.d.ts +26 -0
  25. package/dist/components/SListItem/SListItem.js +81 -0
  26. package/dist/components/SListItem/SListItem.js.map +1 -0
  27. package/dist/components/SListItem/index.d.ts +1 -0
  28. package/dist/components/SSectionHeaderCard/SSectionHeaderCard.cjs +3414 -0
  29. package/dist/components/SSectionHeaderCard/SSectionHeaderCard.cjs.map +1 -0
  30. package/dist/components/SSectionHeaderCard/SSectionHeaderCard.d.ts +32 -0
  31. package/dist/components/SSectionHeaderCard/SSectionHeaderCard.js +3392 -0
  32. package/dist/components/SSectionHeaderCard/SSectionHeaderCard.js.map +1 -0
  33. package/dist/components/SSectionHeaderCard/index.d.ts +1 -0
  34. package/dist/components/STable/STable.cjs +101 -80
  35. package/dist/components/STable/STable.cjs.map +1 -1
  36. package/dist/components/STable/STable.d.ts +36 -1
  37. package/dist/components/STable/STable.js +102 -81
  38. package/dist/components/STable/STable.js.map +1 -1
  39. package/dist/components/STable/index.d.ts +1 -1
  40. package/dist/index.cjs +1040 -623
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.ts +4 -0
  43. package/dist/index.js +1040 -627
  44. package/dist/index.js.map +1 -1
  45. package/dist/styles.css +339 -19
  46. package/dist/theme.css +14 -0
  47. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -6,10 +6,10 @@ var tailwindMerge = require('tailwind-merge');
6
6
  var react = require('react');
7
7
  var jsxRuntime = require('react/jsx-runtime');
8
8
  var reactDom = require('react-dom');
9
+ var RPopover2 = require('@radix-ui/react-popover');
9
10
  var client = require('react-dom/client');
10
11
  var RTooltip = require('@radix-ui/react-tooltip');
11
12
  var RDropdown = require('@radix-ui/react-dropdown-menu');
12
- var RPopover2 = require('@radix-ui/react-popover');
13
13
  var RSwitch = require('@radix-ui/react-switch');
14
14
  var RDialog = require('@radix-ui/react-dialog');
15
15
  var RCheckbox = require('@radix-ui/react-checkbox');
@@ -33,9 +33,9 @@ function _interopNamespace(e) {
33
33
  return Object.freeze(n);
34
34
  }
35
35
 
36
+ var RPopover2__namespace = /*#__PURE__*/_interopNamespace(RPopover2);
36
37
  var RTooltip__namespace = /*#__PURE__*/_interopNamespace(RTooltip);
37
38
  var RDropdown__namespace = /*#__PURE__*/_interopNamespace(RDropdown);
38
- var RPopover2__namespace = /*#__PURE__*/_interopNamespace(RPopover2);
39
39
  var RSwitch__namespace = /*#__PURE__*/_interopNamespace(RSwitch);
40
40
  var RDialog__namespace = /*#__PURE__*/_interopNamespace(RDialog);
41
41
  var RCheckbox__namespace = /*#__PURE__*/_interopNamespace(RCheckbox);
@@ -2920,6 +2920,227 @@ var SCard = react.forwardRef(function SCard2({ bordered = false, className, chil
2920
2920
  }
2921
2921
  );
2922
2922
  });
2923
+ var setRefs = (refs, value) => {
2924
+ refs.forEach((ref) => {
2925
+ if (typeof ref === "function") {
2926
+ ref(value);
2927
+ return;
2928
+ }
2929
+ if (ref) {
2930
+ ref.current = value;
2931
+ }
2932
+ });
2933
+ };
2934
+ function renderSlot(slot, state2) {
2935
+ return typeof slot === "function" ? slot(state2) : slot;
2936
+ }
2937
+ var SDraggableItemView = react.forwardRef(
2938
+ function SDraggableItemView2({
2939
+ title,
2940
+ trailing,
2941
+ accentStripe,
2942
+ bordered,
2943
+ selected,
2944
+ dense,
2945
+ dragging,
2946
+ disabled,
2947
+ hovered,
2948
+ dragHandleProps,
2949
+ onDragHandleMouseDown,
2950
+ className,
2951
+ ...rest
2952
+ }, ref) {
2953
+ const renderState = { hovered, dragging, disabled };
2954
+ const titleNode = renderSlot(title, renderState);
2955
+ const trailingNode = renderSlot(trailing, renderState);
2956
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2957
+ "div",
2958
+ {
2959
+ ref,
2960
+ "aria-disabled": disabled || void 0,
2961
+ "data-dragging": dragging || void 0,
2962
+ className: cn(
2963
+ "relative flex w-full items-center gap-(--cmp-listDraggableItem-gap) overflow-hidden px-(--cmp-listDraggableItem-paddingX) text-[12px] leading-[20px]",
2964
+ disabled ? "bg-(--cmp-listDraggableItem-bg-default) font-medium text-(--sys-color-disabled-text)" : selected ? "bg-(--cmp-listDraggableItem-bg-selected) font-bold text-(--cmp-listDraggableItem-text-selected)" : "bg-(--cmp-listDraggableItem-bg-default) font-medium text-(--cmp-listDraggableItem-text-default)",
2965
+ !disabled && !selected && !dragging && "hover:bg-(--cmp-listDraggableItem-bg-hover)",
2966
+ dense ? "h-[32px] py-(--cmp-listDraggableItem-paddingY-dense)" : "h-[40px] py-(--cmp-listDraggableItem-paddingY-normal)",
2967
+ bordered ? cn(
2968
+ "rounded-(--cmp-listDraggableItem-radius-bordered) border border-(--cmp-listDraggableItem-border-default)",
2969
+ !disabled && !selected && !dragging && "hover:border-(--cmp-listDraggableItem-bordered-border-hover)",
2970
+ !disabled && selected && !dragging && "border-(--cmp-listDraggableItem-bordered-border-selected)",
2971
+ !disabled && selected && dragging && "border-[length:var(--cmp-listDraggableItem-bordered-dragging-border-width)] border-(--cmp-listDraggableItem-bordered-dragging-border-color) bg-(--cmp-listDraggableItem-bordered-dragging-bg)"
2972
+ ) : "border-b border-(--cmp-listDraggableItem-border-default)",
2973
+ disabled && "cursor-not-allowed",
2974
+ className
2975
+ ),
2976
+ ...rest,
2977
+ children: [
2978
+ accentStripe && !bordered && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
2979
+ "span",
2980
+ {
2981
+ "aria-hidden": "true",
2982
+ className: "pointer-events-none absolute bottom-[-1px] left-0 top-0 w-(--cmp-listDraggableItem-accentStripe-width) bg-(--cmp-listDraggableItem-accentStripe-color)"
2983
+ }
2984
+ ),
2985
+ /* @__PURE__ */ jsxRuntime.jsx(
2986
+ "div",
2987
+ {
2988
+ ...dragHandleProps,
2989
+ role: dragHandleProps?.role ?? "button",
2990
+ tabIndex: dragHandleProps?.tabIndex ?? (disabled ? -1 : 0),
2991
+ "aria-label": dragHandleProps?.["aria-label"] ?? "\uB4DC\uB798\uADF8 \uD578\uB4E4",
2992
+ "aria-disabled": disabled || void 0,
2993
+ onMouseDown: onDragHandleMouseDown,
2994
+ className: cn(
2995
+ "flex size-[24px] shrink-0 select-none items-center justify-center rounded-[4px]",
2996
+ disabled ? "cursor-not-allowed opacity-0" : "cursor-grab hover:bg-black/5 active:cursor-grabbing",
2997
+ dragging && "bg-black/5",
2998
+ dragHandleProps?.className
2999
+ ),
3000
+ children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "drag", size: 16, color: "grey_65" })
3001
+ }
3002
+ ),
3003
+ /* @__PURE__ */ jsxRuntime.jsxs(
3004
+ "div",
3005
+ {
3006
+ className: cn(
3007
+ "flex min-w-0 flex-1 items-center gap-[8px]",
3008
+ dragging && "opacity-(--cmp-listDraggableItem-dragging-content-opacity)"
3009
+ ),
3010
+ children: [
3011
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: titleNode }),
3012
+ trailingNode
3013
+ ]
3014
+ }
3015
+ )
3016
+ ]
3017
+ }
3018
+ );
3019
+ }
3020
+ );
3021
+ var SDraggableItem = react.forwardRef(
3022
+ function SDraggableItem2({
3023
+ title,
3024
+ trailing,
3025
+ accentStripe = false,
3026
+ bordered = false,
3027
+ selected = false,
3028
+ dense = false,
3029
+ disabled = false,
3030
+ dragOverlay = true,
3031
+ dragOverlayOpacity = 0.75,
3032
+ dragHandleProps,
3033
+ onDragHandleMouseDown,
3034
+ className,
3035
+ onMouseEnter,
3036
+ onMouseLeave,
3037
+ ...rest
3038
+ }, ref) {
3039
+ const [hovered, setHovered] = react.useState(false);
3040
+ const [overlay, setOverlay] = react.useState(null);
3041
+ const rootRef = react.useRef(null);
3042
+ const overlayVisible = overlay != null;
3043
+ const handleMouseEnter = (event) => {
3044
+ if (!disabled) setHovered(true);
3045
+ onMouseEnter?.(event);
3046
+ };
3047
+ const handleMouseLeave = (event) => {
3048
+ setHovered(false);
3049
+ onMouseLeave?.(event);
3050
+ };
3051
+ const handleDragMouseDown = (event) => {
3052
+ if (disabled) return;
3053
+ const rect = rootRef.current?.getBoundingClientRect();
3054
+ if (dragOverlay && rect) {
3055
+ setOverlay({
3056
+ offsetX: event.clientX - rect.left,
3057
+ offsetY: event.clientY - rect.top,
3058
+ rect,
3059
+ x: event.clientX,
3060
+ y: event.clientY
3061
+ });
3062
+ }
3063
+ dragHandleProps?.onMouseDown?.(event);
3064
+ onDragHandleMouseDown?.(event);
3065
+ };
3066
+ react.useEffect(() => {
3067
+ if (!overlayVisible) return void 0;
3068
+ const handleMouseMove = (event) => {
3069
+ setOverlay(
3070
+ (current) => current ? {
3071
+ ...current,
3072
+ x: event.clientX,
3073
+ y: event.clientY
3074
+ } : current
3075
+ );
3076
+ };
3077
+ const handleMouseUp = () => {
3078
+ setOverlay(null);
3079
+ };
3080
+ window.addEventListener("mousemove", handleMouseMove);
3081
+ window.addEventListener("mouseup", handleMouseUp);
3082
+ return () => {
3083
+ window.removeEventListener("mousemove", handleMouseMove);
3084
+ window.removeEventListener("mouseup", handleMouseUp);
3085
+ };
3086
+ }, [overlayVisible]);
3087
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3088
+ /* @__PURE__ */ jsxRuntime.jsx(
3089
+ SDraggableItemView,
3090
+ {
3091
+ ref: (node) => setRefs([rootRef, ref], node),
3092
+ title,
3093
+ trailing,
3094
+ accentStripe,
3095
+ bordered,
3096
+ selected,
3097
+ dense,
3098
+ dragging: overlayVisible,
3099
+ disabled,
3100
+ hovered,
3101
+ dragHandleProps,
3102
+ onDragHandleMouseDown: handleDragMouseDown,
3103
+ onMouseEnter: handleMouseEnter,
3104
+ onMouseLeave: handleMouseLeave,
3105
+ className,
3106
+ ...rest
3107
+ }
3108
+ ),
3109
+ overlay && typeof document !== "undefined" && reactDom.createPortal(
3110
+ /* @__PURE__ */ jsxRuntime.jsx(
3111
+ "div",
3112
+ {
3113
+ className: "pointer-events-none fixed z-[999999]",
3114
+ style: {
3115
+ left: overlay.x - overlay.offsetX,
3116
+ opacity: dragOverlayOpacity,
3117
+ top: overlay.y - overlay.offsetY,
3118
+ width: overlay.rect.width
3119
+ },
3120
+ children: /* @__PURE__ */ jsxRuntime.jsx(
3121
+ SDraggableItemView,
3122
+ {
3123
+ title,
3124
+ trailing,
3125
+ accentStripe,
3126
+ bordered,
3127
+ selected,
3128
+ dense,
3129
+ dragging: true,
3130
+ disabled,
3131
+ hovered: true,
3132
+ dragHandleProps,
3133
+ className
3134
+ }
3135
+ )
3136
+ }
3137
+ ),
3138
+ document.body
3139
+ )
3140
+ ] });
3141
+ }
3142
+ );
3143
+ SDraggableItem.displayName = "SDraggableItem";
2923
3144
  var SExpansionItem = react.forwardRef(
2924
3145
  function SExpansionItem2({
2925
3146
  title,
@@ -2946,7 +3167,7 @@ var SExpansionItem = react.forwardRef(
2946
3167
  {
2947
3168
  ref,
2948
3169
  className: cn(
2949
- "group/expansion-item overflow-hidden bg-[var(--cmp-listExpansionItem-title-bg-default)]",
3170
+ "group/expansion-item overflow-hidden bg-(--cmp-listExpansionItem-title-bg-default)",
2950
3171
  // TODO: expansionItem/bordered/radius 및 border intent 토큰 생성 후 고정값을 토큰으로 교체한다.
2951
3172
  bordered && "rounded-[8px] border border-[#E1E1E1] hover:border-[#AAAAAA] [&:has(>button:hover)]:border-[#AAAAAA]",
2952
3173
  bordered && isExpanded && "!border-[#93C4FF]",
@@ -2968,10 +3189,10 @@ var SExpansionItem = react.forwardRef(
2968
3189
  onToggle?.(next, event);
2969
3190
  },
2970
3191
  className: cn(
2971
- "flex w-full items-center justify-between border-0 text-left text-[14px] font-bold leading-[24px] text-[var(--cmp-listExpansionItem-title-text-default)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--sys-color-border-accent)] disabled:cursor-not-allowed disabled:text-[var(--sys-color-disabled-text)] cursor-pointer",
3192
+ "flex w-full cursor-pointer items-center justify-between border-0 text-left text-[14px] font-bold leading-[24px] text-(--cmp-listExpansionItem-title-text-default) focus-visible:outline focus-visible:outline-2 focus-visible:outline-(--sys-color-border-accent) disabled:cursor-not-allowed disabled:text-(--sys-color-disabled-text)",
2972
3193
  isExpanded && "border-b border-(--cmp-listExpansionItem-title-border)",
2973
3194
  !isExpanded && "hover:bg-(--cmp-listExpansionItem-title-bg-hover)",
2974
- dense ? "min-h-8 py-(--cmp-listExpansionItem-title-paddingY-dense)" : "min-h-10 py-(--cmp-listExpansionItem-title-paddingY-normal)",
3195
+ dense ? "h-[32px] py-(--cmp-listExpansionItem-title-paddingY-dense)" : "h-[40px] py-(--cmp-listExpansionItem-title-paddingY-normal)",
2975
3196
  "gap-(--cmp-listExpansionItem-title-gap)",
2976
3197
  "pr-(--cmp-listExpansionItem-title-paddingX)",
2977
3198
  depth === 2 ? "pl-[calc(var(--cmp-listExpansionItem-title-paddingX)+32px)]" : depth === 3 ? "pl-[calc(var(--cmp-listExpansionItem-title-paddingX)+64px)]" : "pl-(--cmp-listExpansionItem-title-paddingX)",
@@ -2985,7 +3206,7 @@ var SExpansionItem = react.forwardRef(
2985
3206
  "flex transition-transform duration-200 ease-out motion-reduce:transition-none",
2986
3207
  isExpanded && "rotate-180"
2987
3208
  ),
2988
- children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "caretDown", size: 12 })
3209
+ children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "caretDown", size: 12, color: "var(--sys-color-fg-quaternary)" })
2989
3210
  }
2990
3211
  ),
2991
3212
  leadingNode,
@@ -3000,19 +3221,10 @@ var SExpansionItem = react.forwardRef(
3000
3221
  id,
3001
3222
  "aria-hidden": !isExpanded,
3002
3223
  className: cn(
3003
- "grid overflow-hidden bg-[var(--cmp-listExpansionItem-body-bg)] transition-[grid-template-rows] duration-200 ease-out motion-reduce:transition-none",
3224
+ "grid overflow-hidden bg-(--cmp-listExpansionItem-body-bg) transition-[grid-template-rows] duration-200 ease-out motion-reduce:transition-none",
3004
3225
  isExpanded ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
3005
3226
  ),
3006
- children: /* @__PURE__ */ jsxRuntime.jsx(
3007
- "div",
3008
- {
3009
- className: cn(
3010
- "min-h-0 overflow-hidden",
3011
- bodyPadding && isExpanded && "p-(--cmp-listExpansionItem-body-padding)"
3012
- ),
3013
- children
3014
- }
3015
- )
3227
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(bodyPadding && "p-(--cmp-listExpansionItem-body-padding)"), children }) })
3016
3228
  }
3017
3229
  )
3018
3230
  ]
@@ -3020,69 +3232,182 @@ var SExpansionItem = react.forwardRef(
3020
3232
  );
3021
3233
  }
3022
3234
  );
3023
- var SDivider = react.forwardRef(function SDivider2({ vertical = false, className, style, ...rest }, ref) {
3235
+ var SList = react.forwardRef(function SList2({ className, children, useGap = false, usePadding = false, ...rest }, ref) {
3024
3236
  return /* @__PURE__ */ jsxRuntime.jsx(
3025
- "hr",
3237
+ "div",
3026
3238
  {
3027
3239
  ref,
3028
- "aria-orientation": vertical ? "vertical" : "horizontal",
3029
3240
  className: cn(
3030
- "shrink-0 border-0",
3031
- vertical ? "inline-block h-auto w-px self-stretch" : "block h-px w-full",
3241
+ useGap && "flex flex-col gap-(--cmp-list-group-gap)",
3242
+ usePadding && "p-(--cmp-list-group-padding)",
3032
3243
  className
3033
3244
  ),
3034
- style: { backgroundColor: "var(--sys-color-divider-default, #E1E1E1)", ...style },
3035
- ...rest
3245
+ ...rest,
3246
+ children
3036
3247
  }
3037
3248
  );
3038
3249
  });
3039
-
3040
- // src/lib/scrollbar.ts
3041
- var FIREFOX_SCROLLBAR_CLASS = "supports-[not_selector(::-webkit-scrollbar)]:[scrollbar-width:thin] supports-[not_selector(::-webkit-scrollbar)]:[scrollbar-color:var(--color-grey-45)_transparent]";
3042
- var SCROLLBAR_CLASS = `${FIREFOX_SCROLLBAR_CLASS} [&::-webkit-scrollbar]:h-[12px] [&::-webkit-scrollbar]:w-[12px] [&::-webkit-scrollbar]:bg-transparent [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:border-2 [&::-webkit-scrollbar-thumb]:border-solid [&::-webkit-scrollbar-thumb]:border-transparent [&::-webkit-scrollbar-thumb]:bg-[var(--color-grey-45)] [&::-webkit-scrollbar-thumb]:bg-clip-padding`;
3043
- var SCROLLBAR_HIDDEN_CLASS = "[scrollbar-width:none] [&::-webkit-scrollbar]:hidden";
3044
- var SCROLLBAR_TRACK_BG_CLASS = "supports-[not_selector(::-webkit-scrollbar)]:[scrollbar-color:var(--color-grey-45)_var(--color-grey-10)] [&::-webkit-scrollbar]:bg-[var(--color-grey-10)] [&::-webkit-scrollbar-track]:bg-[var(--color-grey-10)] [&::-webkit-scrollbar-corner]:bg-[var(--color-grey-10)]";
3045
- var SCROLLBAR_TRACK_BG_WHITE_CLASS = "supports-[not_selector(::-webkit-scrollbar)]:[scrollbar-color:var(--color-grey-45)_var(--color-white)] [&::-webkit-scrollbar]:bg-[var(--color-white)] [&::-webkit-scrollbar-track]:bg-[var(--color-white)] [&::-webkit-scrollbar-corner]:bg-[var(--color-white)]";
3046
- var SCROLLBAR_TRACK_BORDER_CLASS = "[&::-webkit-scrollbar-track:vertical]:[border-left:1px_solid_var(--sys-color-border-default)] [&::-webkit-scrollbar-track:horizontal]:[border-top:1px_solid_var(--sys-color-border-default)] [&::-webkit-scrollbar-corner]:[border-top:1px_solid_var(--sys-color-border-default)] [&::-webkit-scrollbar-corner]:[border-left:1px_solid_var(--sys-color-border-default)] [&::-webkit-scrollbar-thumb:vertical]:[border-left-width:3px] [&::-webkit-scrollbar-thumb:horizontal]:[border-top-width:3px]";
3047
- var AXIS_CLASS = {
3048
- vertical: "overflow-x-hidden overflow-y-auto",
3049
- horizontal: "overflow-x-auto overflow-y-hidden",
3050
- both: "overflow-auto"
3051
- };
3052
- var SScrollArea = react.forwardRef(function SScrollArea2({
3053
- axis = "both",
3054
- background = false,
3250
+ SList.displayName = "SList";
3251
+ var SListItem = react.forwardRef(function SListItem2({
3252
+ title,
3253
+ depth = 1,
3254
+ leading,
3255
+ trailing,
3055
3256
  bordered = false,
3056
- maxHeight,
3057
- maxWidth,
3257
+ accentStripe = false,
3258
+ dense = false,
3259
+ disabled = false,
3058
3260
  className,
3059
- style,
3060
- children,
3261
+ onMouseEnter,
3262
+ onMouseLeave,
3061
3263
  ...rest
3062
3264
  }, ref) {
3063
- const mergedStyle = { ...style };
3064
- if (maxHeight) mergedStyle.maxHeight = maxHeight;
3065
- if (maxWidth) mergedStyle.maxWidth = maxWidth;
3066
- return /* @__PURE__ */ jsxRuntime.jsx(
3265
+ const [hovered, setHovered] = react.useState(false);
3266
+ const renderState = { hovered, disabled };
3267
+ const titleNode = typeof title === "function" ? title(renderState) : title;
3268
+ const leadingNode = typeof leading === "function" ? leading(renderState) : leading;
3269
+ const trailingNode = typeof trailing === "function" ? trailing(renderState) : trailing;
3270
+ const handleMouseEnter = (event) => {
3271
+ if (!disabled) setHovered(true);
3272
+ onMouseEnter?.(event);
3273
+ };
3274
+ const handleMouseLeave = (event) => {
3275
+ setHovered(false);
3276
+ onMouseLeave?.(event);
3277
+ };
3278
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3067
3279
  "div",
3068
3280
  {
3069
3281
  ref,
3282
+ "aria-disabled": disabled || void 0,
3283
+ onMouseEnter: handleMouseEnter,
3284
+ onMouseLeave: handleMouseLeave,
3070
3285
  className: cn(
3071
- AXIS_CLASS[axis],
3072
- SCROLLBAR_CLASS,
3073
- background && SCROLLBAR_TRACK_BG_CLASS,
3074
- bordered && SCROLLBAR_TRACK_BORDER_CLASS,
3286
+ "group/list-item relative flex w-full items-center justify-between bg-(--cmp-listItem-bg-default) text-left text-[14px] font-bold leading-[24px] text-(--cmp-listItem-text-default)",
3287
+ disabled ? "pointer-events-none cursor-not-allowed text-(--sys-color-disabled-text)" : "hover:bg-(--cmp-listItem-bg-hover)",
3288
+ dense ? "h-[32px] py-(--cmp-listItem-paddingY-dense)" : "h-[40px] py-(--cmp-listItem-paddingY-normal)",
3289
+ "gap-(--cmp-listItem-gap)",
3290
+ "pr-(--cmp-listItem-paddingX)",
3291
+ depth === 2 ? "pl-[calc(var(--cmp-listItem-paddingX)+32px)]" : depth === 3 ? "pl-[calc(var(--cmp-listItem-paddingX)+64px)]" : "pl-(--cmp-listItem-paddingX)",
3292
+ bordered ? "overflow-hidden rounded-(--cmp-listItem-radius-bordered) border border-(--cmp-listItem-border-default) hover:border-(--cmp-listItem-bordered-border-hover)" : "border-b border-(--cmp-listItem-border-default)",
3075
3293
  className
3076
3294
  ),
3077
- style: mergedStyle,
3078
3295
  ...rest,
3079
- children
3296
+ children: [
3297
+ accentStripe && !bordered && /* @__PURE__ */ jsxRuntime.jsx(
3298
+ "span",
3299
+ {
3300
+ "aria-hidden": "true",
3301
+ className: "pointer-events-none absolute bottom-[-1px] left-0 top-0 w-(--cmp-listItem-accentStripe-width) bg-(--cmp-listItem-accentStripe-color)"
3302
+ }
3303
+ ),
3304
+ leadingNode,
3305
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex min-w-0 flex-1 flex-col", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: titleNode }) }),
3306
+ trailingNode
3307
+ ]
3080
3308
  }
3081
3309
  );
3082
3310
  });
3311
+ SListItem.displayName = "SListItem";
3083
3312
 
3084
- // src/components/SScrollArea/scrollArea.config.ts
3085
- var SCROLL_AREA_AXES = ["vertical", "horizontal", "both"];
3313
+ // src/lib/floating-anim.ts
3314
+ var FLOATING_SLIDE_ANIM = [
3315
+ "data-[state=open]:data-[side=top]:animate-floating-in-top",
3316
+ "data-[state=delayed-open]:data-[side=top]:animate-floating-in-top",
3317
+ "data-[state=instant-open]:data-[side=top]:animate-floating-in-top",
3318
+ "data-[state=closed]:data-[side=top]:animate-floating-out-top",
3319
+ "data-[state=open]:data-[side=bottom]:animate-floating-in-bottom",
3320
+ "data-[state=delayed-open]:data-[side=bottom]:animate-floating-in-bottom",
3321
+ "data-[state=instant-open]:data-[side=bottom]:animate-floating-in-bottom",
3322
+ "data-[state=closed]:data-[side=bottom]:animate-floating-out-bottom",
3323
+ "data-[state=open]:data-[side=left]:animate-floating-in-left",
3324
+ "data-[state=delayed-open]:data-[side=left]:animate-floating-in-left",
3325
+ "data-[state=instant-open]:data-[side=left]:animate-floating-in-left",
3326
+ "data-[state=closed]:data-[side=left]:animate-floating-out-left",
3327
+ "data-[state=open]:data-[side=right]:animate-floating-in-right",
3328
+ "data-[state=delayed-open]:data-[side=right]:animate-floating-in-right",
3329
+ "data-[state=instant-open]:data-[side=right]:animate-floating-in-right",
3330
+ "data-[state=closed]:data-[side=right]:animate-floating-out-right"
3331
+ ].join(" ");
3332
+ var PortalContainerContext = react.createContext(null);
3333
+ var InsideModalContext = react.createContext(false);
3334
+ var PortalContainerProvider = PortalContainerContext.Provider;
3335
+ var InsideModalProvider = InsideModalContext.Provider;
3336
+ function usePortalContainer() {
3337
+ return react.useContext(PortalContainerContext) ?? void 0;
3338
+ }
3339
+ function useInsideModal() {
3340
+ return react.useContext(InsideModalContext);
3341
+ }
3342
+
3343
+ // src/lib/sanitize-inline-html.ts
3344
+ var ALLOWED_INLINE_TAGS = /* @__PURE__ */ new Set(["A", "B", "STRONG", "I", "EM", "BR", "SPAN"]);
3345
+ var ALLOWED_ATTRS_BY_TAG = {
3346
+ A: /* @__PURE__ */ new Set(["href", "target", "rel", "class"])
3347
+ };
3348
+ var COMMON_ALLOWED_ATTRS = /* @__PURE__ */ new Set(["class"]);
3349
+ var SAFE_HREF_RE = /^(https?:|mailto:|tel:|\/|#|\.)/i;
3350
+ var DROP_CONTENT_TAGS = /* @__PURE__ */ new Set([
3351
+ "SCRIPT",
3352
+ "STYLE",
3353
+ "IFRAME",
3354
+ "OBJECT",
3355
+ "EMBED",
3356
+ "META",
3357
+ "LINK",
3358
+ "BASE",
3359
+ "NOSCRIPT",
3360
+ // SVG/MATH 는 foreign-content 파싱 모드로 전환되어 재직렬화 시 다른 트리로
3361
+ // 재파싱될 수 있다(mXSS 벡터). 인라인 라벨에 필요 없으므로 통째로 제거한다.
3362
+ "SVG",
3363
+ "MATH",
3364
+ "TEMPLATE"
3365
+ ]);
3366
+ var escapeHtml = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
3367
+ var sanitizeNode = (node) => {
3368
+ if (node.nodeType === Node.COMMENT_NODE) {
3369
+ node.remove();
3370
+ return;
3371
+ }
3372
+ if (node.nodeType !== Node.ELEMENT_NODE) return;
3373
+ const element = node;
3374
+ const tagName = element.tagName;
3375
+ if (DROP_CONTENT_TAGS.has(tagName)) {
3376
+ element.remove();
3377
+ return;
3378
+ }
3379
+ Array.from(element.childNodes).forEach((child) => sanitizeNode(child));
3380
+ if (ALLOWED_INLINE_TAGS.has(tagName)) {
3381
+ if (element.hasAttribute("className")) {
3382
+ const val = element.getAttribute("className");
3383
+ element.removeAttribute("className");
3384
+ if (!element.hasAttribute("class")) element.setAttribute("class", val);
3385
+ }
3386
+ const allowedAttrs = ALLOWED_ATTRS_BY_TAG[tagName] ?? COMMON_ALLOWED_ATTRS;
3387
+ Array.from(element.attributes).forEach((attr) => {
3388
+ if (!allowedAttrs.has(attr.name)) element.removeAttribute(attr.name);
3389
+ });
3390
+ if (tagName === "A") {
3391
+ const href = element.getAttribute("href");
3392
+ if (href !== null && href !== "" && !SAFE_HREF_RE.test(href)) element.removeAttribute("href");
3393
+ if (element.hasAttribute("target")) {
3394
+ element.setAttribute("rel", "noopener noreferrer");
3395
+ }
3396
+ }
3397
+ return;
3398
+ }
3399
+ const parent = element.parentNode;
3400
+ if (parent == null) return;
3401
+ while (element.firstChild) parent.insertBefore(element.firstChild, element);
3402
+ parent.removeChild(element);
3403
+ };
3404
+ var sanitizeInlineHtml = (value) => {
3405
+ if (typeof document === "undefined") return escapeHtml(value);
3406
+ const template = document.createElement("template");
3407
+ template.innerHTML = value;
3408
+ Array.from(template.content.childNodes).forEach((child) => sanitizeNode(child));
3409
+ return template.innerHTML;
3410
+ };
3086
3411
 
3087
3412
  // src/components/STag/tag.config.ts
3088
3413
  var TAG_SHAPES = ["square", "pill"];
@@ -3176,9 +3501,418 @@ var STag = react.forwardRef(function STag2({
3176
3501
  }
3177
3502
  );
3178
3503
  });
3179
-
3180
- // src/components/SButton/button.config.ts
3181
- var BUTTON_COLORS = ["primary", "secondary", "neutral", "danger"];
3504
+ var SIZE = {
3505
+ xxs: { icon: 12, radius: "sm" },
3506
+ xs: { icon: 16, radius: "sm" },
3507
+ sm: { icon: 20, radius: "sm" },
3508
+ md: { icon: 24, radius: "md" },
3509
+ lg: { icon: 32, radius: "md" }
3510
+ };
3511
+ var TOOLTIP_HIDE_DELAY_MS = 100;
3512
+ function SGhostButton({
3513
+ icon,
3514
+ size = "sm",
3515
+ intent = "default",
3516
+ ariaLabel = "",
3517
+ ariaPressed,
3518
+ tooltipText,
3519
+ disabled = false,
3520
+ onClick,
3521
+ anchorClassName,
3522
+ anchorStyle,
3523
+ className,
3524
+ style
3525
+ }) {
3526
+ const portalContainer = usePortalContainer();
3527
+ const [open, setOpen] = react.useState(false);
3528
+ const hideTimer = react.useRef(void 0);
3529
+ const cancelHide = () => {
3530
+ if (hideTimer.current) {
3531
+ clearTimeout(hideTimer.current);
3532
+ hideTimer.current = void 0;
3533
+ }
3534
+ };
3535
+ const openNow = () => {
3536
+ cancelHide();
3537
+ setOpen(true);
3538
+ };
3539
+ const startHide = () => {
3540
+ cancelHide();
3541
+ hideTimer.current = setTimeout(() => setOpen(false), TOOLTIP_HIDE_DELAY_MS);
3542
+ };
3543
+ const s = SIZE[size];
3544
+ const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
3545
+ const text = (tooltipText ?? "").trim();
3546
+ const hasTooltip = text !== "";
3547
+ const btn = /* @__PURE__ */ jsxRuntime.jsxs(
3548
+ "button",
3549
+ {
3550
+ type: "button",
3551
+ disabled,
3552
+ "aria-disabled": disabled ? "true" : void 0,
3553
+ "aria-label": ariaLabel.trim() || void 0,
3554
+ "aria-pressed": ariaPressed,
3555
+ tabIndex: disabled ? -1 : void 0,
3556
+ onClick: (e) => {
3557
+ if (disabled) {
3558
+ e.preventDefault();
3559
+ return;
3560
+ }
3561
+ onClick?.(e);
3562
+ },
3563
+ className: cn(
3564
+ "group/ghost-button relative box-border inline-flex items-center justify-center border-none bg-transparent p-0 transition-shadow",
3565
+ disabled ? "cursor-not-allowed" : "cursor-pointer",
3566
+ "focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
3567
+ className
3568
+ ),
3569
+ style: {
3570
+ width: `var(--cmp-ghostButton-${size}-size)`,
3571
+ height: `var(--cmp-ghostButton-${size}-size)`,
3572
+ borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
3573
+ ...style
3574
+ },
3575
+ children: [
3576
+ !disabled && /* @__PURE__ */ jsxRuntime.jsx(
3577
+ "span",
3578
+ {
3579
+ "aria-hidden": true,
3580
+ className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover/ghost-button:opacity-5",
3581
+ style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
3582
+ }
3583
+ ),
3584
+ /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.icon, color: contentColor })
3585
+ ]
3586
+ }
3587
+ );
3588
+ if (!hasTooltip) return btn;
3589
+ return /* @__PURE__ */ jsxRuntime.jsxs(RPopover2__namespace.Root, { open, onOpenChange: setOpen, children: [
3590
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
3591
+ "span",
3592
+ {
3593
+ className: cn("inline-flex", anchorClassName),
3594
+ style: anchorStyle,
3595
+ onMouseEnter: openNow,
3596
+ onMouseLeave: startHide,
3597
+ onFocus: openNow,
3598
+ onBlur: startHide,
3599
+ children: btn
3600
+ }
3601
+ ) }),
3602
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
3603
+ RPopover2__namespace.Content,
3604
+ {
3605
+ side: "top",
3606
+ sideOffset: 4,
3607
+ className: cn("z-50", FLOATING_SLIDE_ANIM),
3608
+ "aria-hidden": true,
3609
+ onOpenAutoFocus: (e) => e.preventDefault(),
3610
+ onMouseEnter: cancelHide,
3611
+ onMouseLeave: startHide,
3612
+ children: /* @__PURE__ */ jsxRuntime.jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
3613
+ }
3614
+ ) })
3615
+ ] });
3616
+ }
3617
+ var HIDE_DELAY_MS = 100;
3618
+ function useBody(content, message = []) {
3619
+ if (content != null) return content;
3620
+ if (message.length === 0) return null;
3621
+ const singleLine = message.length === 1;
3622
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: message.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx(
3623
+ "div",
3624
+ {
3625
+ className: singleLine ? "leading-[24px]" : void 0,
3626
+ dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(line) }
3627
+ },
3628
+ i
3629
+ )) });
3630
+ }
3631
+ var STooltip = react.forwardRef(function STooltip2({
3632
+ content,
3633
+ message = [],
3634
+ trigger = "hover",
3635
+ placement = "top",
3636
+ tooltipType = "default",
3637
+ useClose = false,
3638
+ disabled = false,
3639
+ children,
3640
+ icon = "helpOutline",
3641
+ iconSize = 12,
3642
+ color = "#01BB4B",
3643
+ ariaLabel,
3644
+ className,
3645
+ triggerClassName,
3646
+ style
3647
+ }, ref) {
3648
+ const portalContainer = usePortalContainer();
3649
+ const [open, setOpen] = react.useState(false);
3650
+ const hideTimer = react.useRef(void 0);
3651
+ const cancelHide = () => {
3652
+ if (hideTimer.current) {
3653
+ clearTimeout(hideTimer.current);
3654
+ hideTimer.current = void 0;
3655
+ }
3656
+ };
3657
+ const openNow = () => {
3658
+ cancelHide();
3659
+ setOpen(true);
3660
+ };
3661
+ const startHide = () => {
3662
+ if (useClose) return;
3663
+ cancelHide();
3664
+ hideTimer.current = setTimeout(() => setOpen(false), HIDE_DELAY_MS);
3665
+ };
3666
+ react.useImperativeHandle(
3667
+ ref,
3668
+ () => ({
3669
+ show: () => {
3670
+ cancelHide();
3671
+ setOpen(true);
3672
+ },
3673
+ hide: () => {
3674
+ cancelHide();
3675
+ setOpen(false);
3676
+ }
3677
+ }),
3678
+ []
3679
+ );
3680
+ const body = useBody(content, message);
3681
+ const bg = `var(--cmp-tooltip-${tooltipType}-bg)`;
3682
+ const fg = `var(--cmp-tooltip-${tooltipType}-content)`;
3683
+ const triggerNode = children ?? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("inline-flex cursor-pointer", triggerClassName), "aria-label": ariaLabel, children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: iconSize, color }) });
3684
+ if (disabled || body == null) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: triggerNode });
3685
+ const isHover = trigger === "hover";
3686
+ const contentClass = cn(
3687
+ "z-50 w-fit whitespace-nowrap rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px] shadow-normal-sm",
3688
+ FLOATING_SLIDE_ANIM,
3689
+ className
3690
+ );
3691
+ const contentStyle = {
3692
+ background: bg,
3693
+ color: fg,
3694
+ fontWeight: tooltipType === "default" ? 500 : 700,
3695
+ ...style
3696
+ };
3697
+ return /* @__PURE__ */ jsxRuntime.jsxs(RPopover2__namespace.Root, { open, onOpenChange: setOpen, children: [
3698
+ isHover ? (
3699
+ // hover: Anchor(위치 기준) + 직접 mouse 핸들러 — 클릭으로 토글되지 않도록 Trigger 미사용
3700
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
3701
+ "span",
3702
+ {
3703
+ className: "inline-flex",
3704
+ onMouseEnter: openNow,
3705
+ onMouseLeave: startHide,
3706
+ onFocus: openNow,
3707
+ onBlur: startHide,
3708
+ children: triggerNode
3709
+ }
3710
+ ) })
3711
+ ) : /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Trigger, { asChild: true, children: triggerNode }),
3712
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
3713
+ RPopover2__namespace.Content,
3714
+ {
3715
+ side: placement,
3716
+ sideOffset: 8,
3717
+ className: contentClass,
3718
+ style: contentStyle,
3719
+ onOpenAutoFocus: (e) => e.preventDefault(),
3720
+ onInteractOutside: (e) => {
3721
+ if (useClose) e.preventDefault();
3722
+ },
3723
+ onEscapeKeyDown: (e) => {
3724
+ if (useClose) e.preventDefault();
3725
+ },
3726
+ onMouseEnter: isHover ? cancelHide : void 0,
3727
+ onMouseLeave: isHover ? startHide : void 0,
3728
+ children: [
3729
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-[12px]", children: [
3730
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: body }),
3731
+ useClose && /* @__PURE__ */ jsxRuntime.jsx(
3732
+ SGhostButton,
3733
+ {
3734
+ icon: "close",
3735
+ size: "xs",
3736
+ intent: tooltipType === "default" ? "inverse" : "default",
3737
+ ariaLabel: "\uB2EB\uAE30",
3738
+ className: "shrink-0",
3739
+ onClick: () => {
3740
+ cancelHide();
3741
+ setOpen(false);
3742
+ }
3743
+ }
3744
+ )
3745
+ ] }),
3746
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
3747
+ ]
3748
+ }
3749
+ ) })
3750
+ ] });
3751
+ });
3752
+ STooltip.displayName = "STooltip";
3753
+ var topBorderColorClass = {
3754
+ default: "bg-(--cmp-sectionHeaderCard-topBorder-color-default)",
3755
+ accent: "bg-(--cmp-sectionHeaderCard-topBorder-color-accent)"
3756
+ };
3757
+ var SSectionHeaderCardBody = react.forwardRef(
3758
+ function SSectionHeaderCardBody2({ className, children, ...rest }, ref) {
3759
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className, ...rest, children });
3760
+ }
3761
+ );
3762
+ var SSectionHeaderCardHeader = react.forwardRef(
3763
+ function SSectionHeaderCardHeader2({
3764
+ title,
3765
+ marker = false,
3766
+ required = false,
3767
+ helpText,
3768
+ subtitle,
3769
+ slot,
3770
+ thickness = false,
3771
+ className,
3772
+ ...rest
3773
+ }, ref) {
3774
+ const hasHelp = helpText != null && helpText.length > 0;
3775
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3776
+ thickness && /* @__PURE__ */ jsxRuntime.jsx(
3777
+ "div",
3778
+ {
3779
+ className: cn(
3780
+ "h-(--cmp-sectionHeaderCard-topBorder-thickness) w-full shrink-0",
3781
+ topBorderColorClass[thickness]
3782
+ )
3783
+ }
3784
+ ),
3785
+ /* @__PURE__ */ jsxRuntime.jsxs(
3786
+ "div",
3787
+ {
3788
+ ref,
3789
+ className: cn(
3790
+ "box-border flex h-[40px] w-full shrink-0 items-center gap-[8px] overflow-hidden border-b border-(--sys-color-border-default) bg-(--sys-color-bg-frame) px-[16px] py-[4px]",
3791
+ className
3792
+ ),
3793
+ ...rest,
3794
+ children: [
3795
+ marker && /* @__PURE__ */ jsxRuntime.jsx(SBadge, { color: "darkblue", className: "shrink-0" }),
3796
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 shrink-0 items-center gap-[8px]", children: [
3797
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate text-[12px] font-bold leading-[20px] text-(--sys-color-fg-brand)", children: title }),
3798
+ required && /* @__PURE__ */ jsxRuntime.jsx(
3799
+ SIcon,
3800
+ {
3801
+ name: "star",
3802
+ size: 16,
3803
+ color: "var(--sys-color-fg-accent)",
3804
+ className: "shrink-0"
3805
+ }
3806
+ ),
3807
+ hasHelp && /* @__PURE__ */ jsxRuntime.jsx(
3808
+ STooltip,
3809
+ {
3810
+ trigger: "hover",
3811
+ icon: "helpOutline",
3812
+ iconSize: 16,
3813
+ color: "var(--sys-color-fg-success)",
3814
+ message: helpText,
3815
+ triggerClassName: "shrink-0 rounded-[4px]"
3816
+ }
3817
+ )
3818
+ ] }),
3819
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate text-[12px] font-normal leading-[20px] text-(--sys-color-fg-secondary)", children: subtitle }),
3820
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto flex min-h-6 min-w-0 flex-1 items-center justify-end", children: slot })
3821
+ ]
3822
+ }
3823
+ )
3824
+ ] });
3825
+ }
3826
+ );
3827
+ var SSectionHeaderCardRoot = react.forwardRef(
3828
+ function SSectionHeaderCard({ className, children, ...rest }, ref) {
3829
+ return /* @__PURE__ */ jsxRuntime.jsx(
3830
+ "div",
3831
+ {
3832
+ ref,
3833
+ className: cn(
3834
+ "box-border flex w-full flex-col items-stretch overflow-hidden rounded-[8px] border border-(--sys-color-border-default) bg-(--sys-color-bg-frame)",
3835
+ className
3836
+ ),
3837
+ ...rest,
3838
+ children
3839
+ }
3840
+ );
3841
+ }
3842
+ );
3843
+ var SSectionHeaderCard2 = Object.assign(SSectionHeaderCardRoot, {
3844
+ Header: SSectionHeaderCardHeader,
3845
+ Body: SSectionHeaderCardBody
3846
+ });
3847
+ SSectionHeaderCardRoot.displayName = "SSectionHeaderCard";
3848
+ SSectionHeaderCardHeader.displayName = "SSectionHeaderCard.Header";
3849
+ SSectionHeaderCardBody.displayName = "SSectionHeaderCard.Body";
3850
+ var SDivider = react.forwardRef(function SDivider2({ vertical = false, className, style, ...rest }, ref) {
3851
+ return /* @__PURE__ */ jsxRuntime.jsx(
3852
+ "hr",
3853
+ {
3854
+ ref,
3855
+ "aria-orientation": vertical ? "vertical" : "horizontal",
3856
+ className: cn(
3857
+ "shrink-0 border-0",
3858
+ vertical ? "inline-block h-auto w-px self-stretch" : "block h-px w-full",
3859
+ className
3860
+ ),
3861
+ style: { backgroundColor: "var(--sys-color-divider-default, #E1E1E1)", ...style },
3862
+ ...rest
3863
+ }
3864
+ );
3865
+ });
3866
+
3867
+ // src/lib/scrollbar.ts
3868
+ var FIREFOX_SCROLLBAR_CLASS = "supports-[not_selector(::-webkit-scrollbar)]:[scrollbar-width:thin] supports-[not_selector(::-webkit-scrollbar)]:[scrollbar-color:var(--color-grey-45)_transparent]";
3869
+ var SCROLLBAR_CLASS = `${FIREFOX_SCROLLBAR_CLASS} [&::-webkit-scrollbar]:h-[12px] [&::-webkit-scrollbar]:w-[12px] [&::-webkit-scrollbar]:bg-transparent [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:border-2 [&::-webkit-scrollbar-thumb]:border-solid [&::-webkit-scrollbar-thumb]:border-transparent [&::-webkit-scrollbar-thumb]:bg-[var(--color-grey-45)] [&::-webkit-scrollbar-thumb]:bg-clip-padding`;
3870
+ var SCROLLBAR_HIDDEN_CLASS = "[scrollbar-width:none] [&::-webkit-scrollbar]:hidden";
3871
+ var SCROLLBAR_TRACK_BG_CLASS = "supports-[not_selector(::-webkit-scrollbar)]:[scrollbar-color:var(--color-grey-45)_var(--color-grey-10)] [&::-webkit-scrollbar]:bg-[var(--color-grey-10)] [&::-webkit-scrollbar-track]:bg-[var(--color-grey-10)] [&::-webkit-scrollbar-corner]:bg-[var(--color-grey-10)]";
3872
+ var SCROLLBAR_TRACK_BG_WHITE_CLASS = "supports-[not_selector(::-webkit-scrollbar)]:[scrollbar-color:var(--color-grey-45)_var(--color-white)] [&::-webkit-scrollbar]:bg-[var(--color-white)] [&::-webkit-scrollbar-track]:bg-[var(--color-white)] [&::-webkit-scrollbar-corner]:bg-[var(--color-white)]";
3873
+ var SCROLLBAR_TRACK_BORDER_CLASS = "[&::-webkit-scrollbar-track:vertical]:[border-left:1px_solid_var(--sys-color-border-default)] [&::-webkit-scrollbar-track:horizontal]:[border-top:1px_solid_var(--sys-color-border-default)] [&::-webkit-scrollbar-corner]:[border-top:1px_solid_var(--sys-color-border-default)] [&::-webkit-scrollbar-corner]:[border-left:1px_solid_var(--sys-color-border-default)] [&::-webkit-scrollbar-thumb:vertical]:[border-left-width:3px] [&::-webkit-scrollbar-thumb:horizontal]:[border-top-width:3px]";
3874
+ var AXIS_CLASS = {
3875
+ vertical: "overflow-x-hidden overflow-y-auto",
3876
+ horizontal: "overflow-x-auto overflow-y-hidden",
3877
+ both: "overflow-auto"
3878
+ };
3879
+ var SScrollArea = react.forwardRef(function SScrollArea2({
3880
+ axis = "both",
3881
+ background = false,
3882
+ bordered = false,
3883
+ maxHeight,
3884
+ maxWidth,
3885
+ className,
3886
+ style,
3887
+ children,
3888
+ ...rest
3889
+ }, ref) {
3890
+ const mergedStyle = { ...style };
3891
+ if (maxHeight) mergedStyle.maxHeight = maxHeight;
3892
+ if (maxWidth) mergedStyle.maxWidth = maxWidth;
3893
+ return /* @__PURE__ */ jsxRuntime.jsx(
3894
+ "div",
3895
+ {
3896
+ ref,
3897
+ className: cn(
3898
+ AXIS_CLASS[axis],
3899
+ SCROLLBAR_CLASS,
3900
+ background && SCROLLBAR_TRACK_BG_CLASS,
3901
+ bordered && SCROLLBAR_TRACK_BORDER_CLASS,
3902
+ className
3903
+ ),
3904
+ style: mergedStyle,
3905
+ ...rest,
3906
+ children
3907
+ }
3908
+ );
3909
+ });
3910
+
3911
+ // src/components/SScrollArea/scrollArea.config.ts
3912
+ var SCROLL_AREA_AXES = ["vertical", "horizontal", "both"];
3913
+
3914
+ // src/components/SButton/button.config.ts
3915
+ var BUTTON_COLORS = ["primary", "secondary", "neutral", "danger"];
3182
3916
  var BUTTON_SIZES = ["xs", "sm", "md", "lg"];
3183
3917
  var V = (path) => `var(--cmp-button-${path})`;
3184
3918
  function buttonPreset(color, outline) {
@@ -3360,7 +4094,13 @@ function renderItems(message, depth = 1) {
3360
4094
  className: cn("flex items-start", isDepth2 && "pl-[32px]"),
3361
4095
  children: [
3362
4096
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-[24px] shrink-0 text-center", "aria-hidden": true, children: isDepth2 ? "\u2022" : "-" }),
3363
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "m-0 min-w-0 flex-1 break-words", children: m })
4097
+ /* @__PURE__ */ jsxRuntime.jsx(
4098
+ "p",
4099
+ {
4100
+ className: "m-0 min-w-0 flex-1 break-words",
4101
+ dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(m) }
4102
+ }
4103
+ )
3364
4104
  ]
3365
4105
  },
3366
4106
  `${depth}-${i}-${out.length}`
@@ -3663,36 +4403,6 @@ var loading = {
3663
4403
  setState({ open: false });
3664
4404
  }
3665
4405
  };
3666
-
3667
- // src/lib/floating-anim.ts
3668
- var FLOATING_SLIDE_ANIM = [
3669
- "data-[state=open]:data-[side=top]:animate-floating-in-top",
3670
- "data-[state=delayed-open]:data-[side=top]:animate-floating-in-top",
3671
- "data-[state=instant-open]:data-[side=top]:animate-floating-in-top",
3672
- "data-[state=closed]:data-[side=top]:animate-floating-out-top",
3673
- "data-[state=open]:data-[side=bottom]:animate-floating-in-bottom",
3674
- "data-[state=delayed-open]:data-[side=bottom]:animate-floating-in-bottom",
3675
- "data-[state=instant-open]:data-[side=bottom]:animate-floating-in-bottom",
3676
- "data-[state=closed]:data-[side=bottom]:animate-floating-out-bottom",
3677
- "data-[state=open]:data-[side=left]:animate-floating-in-left",
3678
- "data-[state=delayed-open]:data-[side=left]:animate-floating-in-left",
3679
- "data-[state=instant-open]:data-[side=left]:animate-floating-in-left",
3680
- "data-[state=closed]:data-[side=left]:animate-floating-out-left",
3681
- "data-[state=open]:data-[side=right]:animate-floating-in-right",
3682
- "data-[state=delayed-open]:data-[side=right]:animate-floating-in-right",
3683
- "data-[state=instant-open]:data-[side=right]:animate-floating-in-right",
3684
- "data-[state=closed]:data-[side=right]:animate-floating-out-right"
3685
- ].join(" ");
3686
- var PortalContainerContext = react.createContext(null);
3687
- var InsideModalContext = react.createContext(false);
3688
- var PortalContainerProvider = PortalContainerContext.Provider;
3689
- var InsideModalProvider = InsideModalContext.Provider;
3690
- function usePortalContainer() {
3691
- return react.useContext(PortalContainerContext) ?? void 0;
3692
- }
3693
- function useInsideModal() {
3694
- return react.useContext(InsideModalContext);
3695
- }
3696
4406
  var SIZE_CONFIG = {
3697
4407
  sm: {
3698
4408
  gap: 4,
@@ -3735,127 +4445,58 @@ var STextLink = react.forwardRef(function STextLink2({
3735
4445
  const handle = () => {
3736
4446
  if (!disabled) onClick?.();
3737
4447
  };
3738
- const portalContainer = usePortalContainer();
3739
- const link = /* @__PURE__ */ jsxRuntime.jsxs(
3740
- "span",
3741
- {
3742
- ref,
3743
- role: "button",
3744
- tabIndex: disabled ? -1 : 0,
3745
- onClick: handle,
3746
- onKeyDown: (e) => {
3747
- if (e.key === "Enter" || e.key === " ") {
3748
- e.preventDefault();
3749
- handle();
3750
- }
3751
- },
3752
- className: cn(
3753
- "inline-flex cursor-pointer items-center",
3754
- underline ? s.underlineTypo : s.typo,
3755
- !disabled && "hover:underline",
3756
- disabled && "cursor-not-allowed",
3757
- className
3758
- ),
3759
- style: { gap: s.gap, color: contentColor, ...style },
3760
- ...rest,
3761
- children: [
3762
- icon && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.iconSize, color: resolvedIconColor }),
3763
- /* @__PURE__ */ jsxRuntime.jsx(
3764
- "span",
3765
- {
3766
- className: cn(labelClass),
3767
- style: disabled ? { color: "var(--cmp-textLink-content-disabled)" } : void 0,
3768
- children: label || children
3769
- }
3770
- ),
3771
- rightArrow !== "none" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex h-[16px] w-[16px] items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
3772
- SIcon,
3773
- {
3774
- name: rightArrow === "chevron" ? "chevronRight" : "caretRight",
3775
- size: 12,
3776
- color: disabled ? "var(--cmp-textLink-icon-disabled)" : "var(--color-grey-65)"
3777
- }
3778
- ) })
3779
- ]
3780
- }
3781
- );
3782
- const text = (tooltipText ?? "").trim();
3783
- if (text === "") return link;
3784
- return /* @__PURE__ */ jsxRuntime.jsx(RTooltip__namespace.Provider, { delayDuration: 200, children: /* @__PURE__ */ jsxRuntime.jsxs(RTooltip__namespace.Root, { children: [
3785
- /* @__PURE__ */ jsxRuntime.jsx(RTooltip__namespace.Trigger, { asChild: true, children: link }),
3786
- /* @__PURE__ */ jsxRuntime.jsx(RTooltip__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(RTooltip__namespace.Content, { side: "top", sideOffset: 4, className: cn("z-50", FLOATING_SLIDE_ANIM), children: /* @__PURE__ */ jsxRuntime.jsx(STag, { shape: "square", size: "xs", color: "grey", label: text }) }) })
3787
- ] }) });
3788
- });
3789
-
3790
- // src/lib/sanitize-inline-html.ts
3791
- var ALLOWED_INLINE_TAGS = /* @__PURE__ */ new Set(["A", "B", "STRONG", "I", "EM", "BR", "SPAN"]);
3792
- var ALLOWED_ATTRS_BY_TAG = {
3793
- A: /* @__PURE__ */ new Set(["href", "target", "rel", "class"])
3794
- };
3795
- var COMMON_ALLOWED_ATTRS = /* @__PURE__ */ new Set(["class"]);
3796
- var SAFE_HREF_RE = /^(https?:|mailto:|tel:|\/|#|\.)/i;
3797
- var DROP_CONTENT_TAGS = /* @__PURE__ */ new Set([
3798
- "SCRIPT",
3799
- "STYLE",
3800
- "IFRAME",
3801
- "OBJECT",
3802
- "EMBED",
3803
- "META",
3804
- "LINK",
3805
- "BASE",
3806
- "NOSCRIPT",
3807
- // SVG/MATH 는 foreign-content 파싱 모드로 전환되어 재직렬화 시 다른 트리로
3808
- // 재파싱될 수 있다(mXSS 벡터). 인라인 라벨에 필요 없으므로 통째로 제거한다.
3809
- "SVG",
3810
- "MATH",
3811
- "TEMPLATE"
3812
- ]);
3813
- var escapeHtml = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
3814
- var sanitizeNode = (node) => {
3815
- if (node.nodeType === Node.COMMENT_NODE) {
3816
- node.remove();
3817
- return;
3818
- }
3819
- if (node.nodeType !== Node.ELEMENT_NODE) return;
3820
- const element = node;
3821
- const tagName = element.tagName;
3822
- if (DROP_CONTENT_TAGS.has(tagName)) {
3823
- element.remove();
3824
- return;
3825
- }
3826
- Array.from(element.childNodes).forEach((child) => sanitizeNode(child));
3827
- if (ALLOWED_INLINE_TAGS.has(tagName)) {
3828
- if (element.hasAttribute("className")) {
3829
- const val = element.getAttribute("className");
3830
- element.removeAttribute("className");
3831
- if (!element.hasAttribute("class")) element.setAttribute("class", val);
3832
- }
3833
- const allowedAttrs = ALLOWED_ATTRS_BY_TAG[tagName] ?? COMMON_ALLOWED_ATTRS;
3834
- Array.from(element.attributes).forEach((attr) => {
3835
- if (!allowedAttrs.has(attr.name)) element.removeAttribute(attr.name);
3836
- });
3837
- if (tagName === "A") {
3838
- const href = element.getAttribute("href");
3839
- if (href !== null && href !== "" && !SAFE_HREF_RE.test(href)) element.removeAttribute("href");
3840
- if (element.hasAttribute("target")) {
3841
- element.setAttribute("rel", "noopener noreferrer");
3842
- }
4448
+ const portalContainer = usePortalContainer();
4449
+ const link = /* @__PURE__ */ jsxRuntime.jsxs(
4450
+ "span",
4451
+ {
4452
+ ref,
4453
+ role: "button",
4454
+ tabIndex: disabled ? -1 : 0,
4455
+ onClick: handle,
4456
+ onKeyDown: (e) => {
4457
+ if (e.key === "Enter" || e.key === " ") {
4458
+ e.preventDefault();
4459
+ handle();
4460
+ }
4461
+ },
4462
+ className: cn(
4463
+ "inline-flex cursor-pointer items-center",
4464
+ underline ? s.underlineTypo : s.typo,
4465
+ !disabled && "hover:underline",
4466
+ disabled && "cursor-not-allowed",
4467
+ className
4468
+ ),
4469
+ style: { gap: s.gap, color: contentColor, ...style },
4470
+ ...rest,
4471
+ children: [
4472
+ icon && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.iconSize, color: resolvedIconColor }),
4473
+ /* @__PURE__ */ jsxRuntime.jsx(
4474
+ "span",
4475
+ {
4476
+ className: cn(labelClass),
4477
+ style: disabled ? { color: "var(--cmp-textLink-content-disabled)" } : void 0,
4478
+ children: label || children
4479
+ }
4480
+ ),
4481
+ rightArrow !== "none" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex h-[16px] w-[16px] items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
4482
+ SIcon,
4483
+ {
4484
+ name: rightArrow === "chevron" ? "chevronRight" : "caretRight",
4485
+ size: 12,
4486
+ color: disabled ? "var(--cmp-textLink-icon-disabled)" : "var(--color-grey-65)"
4487
+ }
4488
+ ) })
4489
+ ]
3843
4490
  }
3844
- return;
3845
- }
3846
- const parent = element.parentNode;
3847
- if (parent == null) return;
3848
- while (element.firstChild) parent.insertBefore(element.firstChild, element);
3849
- parent.removeChild(element);
3850
- };
3851
- var sanitizeInlineHtml = (value) => {
3852
- if (typeof document === "undefined") return escapeHtml(value);
3853
- const template = document.createElement("template");
3854
- template.innerHTML = value;
3855
- Array.from(template.content.childNodes).forEach((child) => sanitizeNode(child));
3856
- return template.innerHTML;
3857
- };
3858
- var SIZE = {
4491
+ );
4492
+ const text = (tooltipText ?? "").trim();
4493
+ if (text === "") return link;
4494
+ return /* @__PURE__ */ jsxRuntime.jsx(RTooltip__namespace.Provider, { delayDuration: 200, children: /* @__PURE__ */ jsxRuntime.jsxs(RTooltip__namespace.Root, { children: [
4495
+ /* @__PURE__ */ jsxRuntime.jsx(RTooltip__namespace.Trigger, { asChild: true, children: link }),
4496
+ /* @__PURE__ */ jsxRuntime.jsx(RTooltip__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(RTooltip__namespace.Content, { side: "top", sideOffset: 4, className: cn("z-50", FLOATING_SLIDE_ANIM), children: /* @__PURE__ */ jsxRuntime.jsx(STag, { shape: "square", size: "xs", color: "grey", label: text }) }) })
4497
+ ] }) });
4498
+ });
4499
+ var SIZE2 = {
3859
4500
  xs: { height: 24, paddingX: 8, gap: 6, arrow: 12, fontSize: 12, minWidth: 64, splitMinWidth: 72 },
3860
4501
  sm: {
3861
4502
  height: 28,
@@ -3941,7 +4582,7 @@ var SDropdownButton = react.forwardRef(
3941
4582
  }),
3942
4583
  []
3943
4584
  );
3944
- const s = SIZE[size];
4585
+ const s = SIZE2[size];
3945
4586
  const p = buttonPreset(color, outline);
3946
4587
  const colorVars = {
3947
4588
  "--dd-bg": disabled ? "var(--cmp-button-bg-disabled)" : p.bg,
@@ -3995,201 +4636,88 @@ var SDropdownButton = react.forwardRef(
3995
4636
  ]
3996
4637
  },
3997
4638
  it.value
3998
- ))
3999
- }
4000
- ) });
4001
- return /* @__PURE__ */ jsxRuntime.jsxs(
4002
- RDropdown__namespace.Root,
4003
- {
4004
- open,
4005
- onOpenChange: (o) => {
4006
- setOpen(o);
4007
- onOpenChange?.(o);
4008
- },
4009
- children: [
4010
- split ? /* @__PURE__ */ jsxRuntime.jsxs(
4011
- "div",
4012
- {
4013
- ref: splitWrapRef,
4014
- className: cn("inline-flex items-stretch", className),
4015
- style: { minWidth: s.splitMinWidth, ...style },
4016
- children: [
4017
- /* @__PURE__ */ jsxRuntime.jsx(
4018
- "button",
4019
- {
4020
- type: "button",
4021
- disabled,
4022
- onClick: onLabelClick,
4023
- className: cn(triggerBase, "flex-1 justify-center rounded-l-[4px] border-r-0"),
4024
- style: {
4025
- minHeight: s.height,
4026
- padding: `0 ${s.paddingX}px`,
4027
- fontSize: s.fontSize,
4028
- ...colorVars
4029
- },
4030
- children: label
4031
- }
4032
- ),
4033
- /* @__PURE__ */ jsxRuntime.jsx(RDropdown__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4034
- "button",
4035
- {
4036
- ref: splitToggleRef,
4037
- type: "button",
4038
- disabled,
4039
- "aria-label": "\uBA54\uB274 \uC5F4\uAE30",
4040
- className: cn(triggerBase, "justify-center rounded-r-[4px] border-l"),
4041
- style: {
4042
- minHeight: s.height,
4043
- minWidth: s.height,
4044
- borderLeftColor: disabled ? "var(--cmp-button-border-disabled)" : splitDivider(color, outline),
4045
- ...colorVars
4046
- },
4047
- children: splitIcon
4048
- }
4049
- ) })
4050
- ]
4051
- }
4052
- ) : /* @__PURE__ */ jsxRuntime.jsx(RDropdown__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
4053
- "button",
4054
- {
4055
- type: "button",
4056
- disabled,
4057
- className: cn(triggerBase, "justify-between rounded-[4px]", className),
4058
- style: {
4059
- minWidth: s.minWidth,
4060
- minHeight: s.height,
4061
- padding: `0 ${s.paddingX}px`,
4062
- gap: s.gap,
4063
- fontSize: s.fontSize,
4064
- ...colorVars,
4065
- ...style
4066
- },
4067
- children: [
4068
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate text-center", children: label }),
4069
- caret
4070
- ]
4071
- }
4072
- ) }),
4073
- menu
4074
- ]
4075
- }
4076
- );
4077
- }
4078
- );
4079
- SDropdownButton.displayName = "SDropdownButton";
4080
- var SIZE2 = {
4081
- xxs: { icon: 12, radius: "sm" },
4082
- xs: { icon: 16, radius: "sm" },
4083
- sm: { icon: 20, radius: "sm" },
4084
- md: { icon: 24, radius: "md" },
4085
- lg: { icon: 32, radius: "md" }
4086
- };
4087
- var TOOLTIP_HIDE_DELAY_MS = 100;
4088
- function SGhostButton({
4089
- icon,
4090
- size = "sm",
4091
- intent = "default",
4092
- ariaLabel = "",
4093
- ariaPressed,
4094
- tooltipText,
4095
- disabled = false,
4096
- onClick,
4097
- anchorClassName,
4098
- anchorStyle,
4099
- className,
4100
- style
4101
- }) {
4102
- const portalContainer = usePortalContainer();
4103
- const [open, setOpen] = react.useState(false);
4104
- const hideTimer = react.useRef(void 0);
4105
- const cancelHide = () => {
4106
- if (hideTimer.current) {
4107
- clearTimeout(hideTimer.current);
4108
- hideTimer.current = void 0;
4109
- }
4110
- };
4111
- const openNow = () => {
4112
- cancelHide();
4113
- setOpen(true);
4114
- };
4115
- const startHide = () => {
4116
- cancelHide();
4117
- hideTimer.current = setTimeout(() => setOpen(false), TOOLTIP_HIDE_DELAY_MS);
4118
- };
4119
- const s = SIZE2[size];
4120
- const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
4121
- const text = (tooltipText ?? "").trim();
4122
- const hasTooltip = text !== "";
4123
- const btn = /* @__PURE__ */ jsxRuntime.jsxs(
4124
- "button",
4125
- {
4126
- type: "button",
4127
- disabled,
4128
- "aria-disabled": disabled ? "true" : void 0,
4129
- "aria-label": ariaLabel.trim() || void 0,
4130
- "aria-pressed": ariaPressed,
4131
- tabIndex: disabled ? -1 : void 0,
4132
- onClick: (e) => {
4133
- if (disabled) {
4134
- e.preventDefault();
4135
- return;
4136
- }
4137
- onClick?.(e);
4138
- },
4139
- className: cn(
4140
- "group/ghost-button relative box-border inline-flex items-center justify-center border-none bg-transparent p-0 transition-shadow",
4141
- disabled ? "cursor-not-allowed" : "cursor-pointer",
4142
- "focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
4143
- className
4144
- ),
4145
- style: {
4146
- width: `var(--cmp-ghostButton-${size}-size)`,
4147
- height: `var(--cmp-ghostButton-${size}-size)`,
4148
- borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
4149
- ...style
4150
- },
4151
- children: [
4152
- !disabled && /* @__PURE__ */ jsxRuntime.jsx(
4153
- "span",
4154
- {
4155
- "aria-hidden": true,
4156
- className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover/ghost-button:opacity-5",
4157
- style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
4158
- }
4159
- ),
4160
- /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.icon, color: contentColor })
4161
- ]
4162
- }
4163
- );
4164
- if (!hasTooltip) return btn;
4165
- return /* @__PURE__ */ jsxRuntime.jsxs(RPopover2__namespace.Root, { open, onOpenChange: setOpen, children: [
4166
- /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4167
- "span",
4168
- {
4169
- className: cn("inline-flex", anchorClassName),
4170
- style: anchorStyle,
4171
- onMouseEnter: openNow,
4172
- onMouseLeave: startHide,
4173
- onFocus: openNow,
4174
- onBlur: startHide,
4175
- children: btn
4176
- }
4177
- ) }),
4178
- /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
4179
- RPopover2__namespace.Content,
4180
- {
4181
- side: "top",
4182
- sideOffset: 4,
4183
- className: cn("z-50", FLOATING_SLIDE_ANIM),
4184
- "aria-hidden": true,
4185
- onOpenAutoFocus: (e) => e.preventDefault(),
4186
- onMouseEnter: cancelHide,
4187
- onMouseLeave: startHide,
4188
- children: /* @__PURE__ */ jsxRuntime.jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
4639
+ ))
4189
4640
  }
4190
- ) })
4191
- ] });
4192
- }
4641
+ ) });
4642
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4643
+ RDropdown__namespace.Root,
4644
+ {
4645
+ open,
4646
+ onOpenChange: (o) => {
4647
+ setOpen(o);
4648
+ onOpenChange?.(o);
4649
+ },
4650
+ children: [
4651
+ split ? /* @__PURE__ */ jsxRuntime.jsxs(
4652
+ "div",
4653
+ {
4654
+ ref: splitWrapRef,
4655
+ className: cn("inline-flex items-stretch", className),
4656
+ style: { minWidth: s.splitMinWidth, ...style },
4657
+ children: [
4658
+ /* @__PURE__ */ jsxRuntime.jsx(
4659
+ "button",
4660
+ {
4661
+ type: "button",
4662
+ disabled,
4663
+ onClick: onLabelClick,
4664
+ className: cn(triggerBase, "flex-1 justify-center rounded-l-[4px] border-r-0"),
4665
+ style: {
4666
+ minHeight: s.height,
4667
+ padding: `0 ${s.paddingX}px`,
4668
+ fontSize: s.fontSize,
4669
+ ...colorVars
4670
+ },
4671
+ children: label
4672
+ }
4673
+ ),
4674
+ /* @__PURE__ */ jsxRuntime.jsx(RDropdown__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4675
+ "button",
4676
+ {
4677
+ ref: splitToggleRef,
4678
+ type: "button",
4679
+ disabled,
4680
+ "aria-label": "\uBA54\uB274 \uC5F4\uAE30",
4681
+ className: cn(triggerBase, "justify-center rounded-r-[4px] border-l"),
4682
+ style: {
4683
+ minHeight: s.height,
4684
+ minWidth: s.height,
4685
+ borderLeftColor: disabled ? "var(--cmp-button-border-disabled)" : splitDivider(color, outline),
4686
+ ...colorVars
4687
+ },
4688
+ children: splitIcon
4689
+ }
4690
+ ) })
4691
+ ]
4692
+ }
4693
+ ) : /* @__PURE__ */ jsxRuntime.jsx(RDropdown__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
4694
+ "button",
4695
+ {
4696
+ type: "button",
4697
+ disabled,
4698
+ className: cn(triggerBase, "justify-between rounded-[4px]", className),
4699
+ style: {
4700
+ minWidth: s.minWidth,
4701
+ minHeight: s.height,
4702
+ padding: `0 ${s.paddingX}px`,
4703
+ gap: s.gap,
4704
+ fontSize: s.fontSize,
4705
+ ...colorVars,
4706
+ ...style
4707
+ },
4708
+ children: [
4709
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate text-center", children: label }),
4710
+ caret
4711
+ ]
4712
+ }
4713
+ ) }),
4714
+ menu
4715
+ ]
4716
+ }
4717
+ );
4718
+ }
4719
+ );
4720
+ SDropdownButton.displayName = "SDropdownButton";
4193
4721
  function SSwitch({
4194
4722
  value = false,
4195
4723
  leftLabel,
@@ -4271,142 +4799,6 @@ function SToggle({
4271
4799
  }
4272
4800
  );
4273
4801
  }
4274
- var HIDE_DELAY_MS = 100;
4275
- function useBody(content, message = []) {
4276
- if (content != null) return content;
4277
- if (message.length === 0) return null;
4278
- const singleLine = message.length === 1;
4279
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: message.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx(
4280
- "div",
4281
- {
4282
- className: singleLine ? "leading-[24px]" : void 0,
4283
- dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(line) }
4284
- },
4285
- i
4286
- )) });
4287
- }
4288
- var STooltip = react.forwardRef(function STooltip2({
4289
- content,
4290
- message = [],
4291
- trigger = "hover",
4292
- placement = "top",
4293
- tooltipType = "default",
4294
- useClose = false,
4295
- disabled = false,
4296
- children,
4297
- icon = "helpOutline",
4298
- iconSize = 12,
4299
- color = "#01BB4B",
4300
- ariaLabel,
4301
- className,
4302
- triggerClassName,
4303
- style
4304
- }, ref) {
4305
- const portalContainer = usePortalContainer();
4306
- const [open, setOpen] = react.useState(false);
4307
- const hideTimer = react.useRef(void 0);
4308
- const cancelHide = () => {
4309
- if (hideTimer.current) {
4310
- clearTimeout(hideTimer.current);
4311
- hideTimer.current = void 0;
4312
- }
4313
- };
4314
- const openNow = () => {
4315
- cancelHide();
4316
- setOpen(true);
4317
- };
4318
- const startHide = () => {
4319
- if (useClose) return;
4320
- cancelHide();
4321
- hideTimer.current = setTimeout(() => setOpen(false), HIDE_DELAY_MS);
4322
- };
4323
- react.useImperativeHandle(
4324
- ref,
4325
- () => ({
4326
- show: () => {
4327
- cancelHide();
4328
- setOpen(true);
4329
- },
4330
- hide: () => {
4331
- cancelHide();
4332
- setOpen(false);
4333
- }
4334
- }),
4335
- []
4336
- );
4337
- const body = useBody(content, message);
4338
- const bg = `var(--cmp-tooltip-${tooltipType}-bg)`;
4339
- const fg = `var(--cmp-tooltip-${tooltipType}-content)`;
4340
- const triggerNode = children ?? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("inline-flex cursor-pointer", triggerClassName), "aria-label": ariaLabel, children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: iconSize, color }) });
4341
- if (disabled || body == null) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: triggerNode });
4342
- const isHover = trigger === "hover";
4343
- const contentClass = cn(
4344
- "z-50 w-fit whitespace-nowrap rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px] shadow-normal-sm",
4345
- FLOATING_SLIDE_ANIM,
4346
- className
4347
- );
4348
- const contentStyle = {
4349
- background: bg,
4350
- color: fg,
4351
- fontWeight: tooltipType === "default" ? 500 : 700,
4352
- ...style
4353
- };
4354
- return /* @__PURE__ */ jsxRuntime.jsxs(RPopover2__namespace.Root, { open, onOpenChange: setOpen, children: [
4355
- isHover ? (
4356
- // hover: Anchor(위치 기준) + 직접 mouse 핸들러 — 클릭으로 토글되지 않도록 Trigger 미사용
4357
- /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4358
- "span",
4359
- {
4360
- className: "inline-flex",
4361
- onMouseEnter: openNow,
4362
- onMouseLeave: startHide,
4363
- onFocus: openNow,
4364
- onBlur: startHide,
4365
- children: triggerNode
4366
- }
4367
- ) })
4368
- ) : /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Trigger, { asChild: true, children: triggerNode }),
4369
- /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
4370
- RPopover2__namespace.Content,
4371
- {
4372
- side: placement,
4373
- sideOffset: 8,
4374
- className: contentClass,
4375
- style: contentStyle,
4376
- onOpenAutoFocus: (e) => e.preventDefault(),
4377
- onInteractOutside: (e) => {
4378
- if (useClose) e.preventDefault();
4379
- },
4380
- onEscapeKeyDown: (e) => {
4381
- if (useClose) e.preventDefault();
4382
- },
4383
- onMouseEnter: isHover ? cancelHide : void 0,
4384
- onMouseLeave: isHover ? startHide : void 0,
4385
- children: [
4386
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-[12px]", children: [
4387
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: body }),
4388
- useClose && /* @__PURE__ */ jsxRuntime.jsx(
4389
- SGhostButton,
4390
- {
4391
- icon: "close",
4392
- size: "xs",
4393
- intent: tooltipType === "default" ? "inverse" : "default",
4394
- ariaLabel: "\uB2EB\uAE30",
4395
- className: "shrink-0",
4396
- onClick: () => {
4397
- cancelHide();
4398
- setOpen(false);
4399
- }
4400
- }
4401
- )
4402
- ] }),
4403
- /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
4404
- ]
4405
- }
4406
- ) })
4407
- ] });
4408
- });
4409
- STooltip.displayName = "STooltip";
4410
4802
  var BUTTON_PRESET = {
4411
4803
  default: { color: "primary", outline: false },
4412
4804
  accent: { color: "primary", outline: false },
@@ -7384,8 +7776,10 @@ var STable = react.forwardRef(function STable2({
7384
7776
  stickyColumn,
7385
7777
  radius = "default",
7386
7778
  noDataLabel = "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
7779
+ noDataSlot,
7387
7780
  isLoading = false,
7388
7781
  dense = false,
7782
+ noHover = false,
7389
7783
  pagination,
7390
7784
  onPageChange,
7391
7785
  useInternalPagination = false,
@@ -7471,7 +7865,10 @@ var STable = react.forwardRef(function STable2({
7471
7865
  );
7472
7866
  const handleScroll = react.useCallback(() => {
7473
7867
  const el = scrollRef.current;
7474
- if (!el) return;
7868
+ if (!el) {
7869
+ setHeaderGutter(0);
7870
+ return;
7871
+ }
7475
7872
  const header = headerScrollRef.current;
7476
7873
  if (header) header.scrollLeft = el.scrollLeft;
7477
7874
  setHeaderGutter(el.offsetWidth - el.clientWidth);
@@ -7603,6 +8000,7 @@ var STable = react.forwardRef(function STable2({
7603
8000
  bodyRows = rows.slice(pageInfo.startIndex, pageInfo.endIndex);
7604
8001
  }
7605
8002
  const isNoData = rowCount === 0 && !isLoading;
8003
+ const showNoDataSlot = isNoData && noDataSlot != null;
7606
8004
  const showPagination = !useVirtualScroll && (pagination != null || useInternalPagination);
7607
8005
  const lastPage = useInternalPagination ? Math.max(1, Math.ceil(rowCount / (innerRowsPerPage || 1))) : pagination?.lastPage ?? Math.max(1, Math.ceil(rowCount / (pagination?.rowsPerPage ?? 10)));
7608
8006
  const displayPage = useInternalPagination ? currentPage : pagination?.page ?? 1;
@@ -7664,6 +8062,12 @@ var STable = react.forwardRef(function STable2({
7664
8062
  isRightEdge && scrolledRight && "shadow-[-5px_0_8px_0_rgba(34,34,34,0.1)]"
7665
8063
  );
7666
8064
  };
8065
+ const bodyScrollClass = cn(
8066
+ "min-h-0 flex-1 overflow-auto border-t border-solid border-[color:var(--cmp-table-border-color)]",
8067
+ SCROLLBAR_CLASS,
8068
+ SCROLLBAR_TRACK_BG_CLASS,
8069
+ SCROLLBAR_TRACK_BORDER_CLASS
8070
+ );
7667
8071
  const colgroup = /* @__PURE__ */ jsxRuntime.jsxs("colgroup", { children: [
7668
8072
  selectable && /* @__PURE__ */ jsxRuntime.jsx("col", { style: { width: SELECTABLE_COLUMN_WIDTH } }),
7669
8073
  visibleCols.map((col, i) => /* @__PURE__ */ jsxRuntime.jsx("col", { style: col.autoWidth ? void 0 : { width: columnWidths[i] } }, col.name))
@@ -7785,97 +8189,106 @@ var STable = react.forwardRef(function STable2({
7785
8189
  )
7786
8190
  }
7787
8191
  ),
7788
- /* @__PURE__ */ jsxRuntime.jsx(
7789
- "div",
7790
- {
7791
- ref: scrollRef,
7792
- onScroll: handleScroll,
7793
- className: cn(
7794
- // 헤더 하단 구분선은 body 상단 border로 그린다. body 래퍼는 스크롤바를 포함한
7795
- // 전체 폭을 차지하므로(스크롤바는 border 안쪽) 헤더 거터의 border-right와 미터가
7796
- // 생기지 않아 색·길이가 균일한 한 줄이 된다.
7797
- "min-h-0 flex-1 overflow-auto border-t border-solid border-[color:var(--cmp-table-border-color)]",
7798
- SCROLLBAR_CLASS,
7799
- SCROLLBAR_TRACK_BG_CLASS,
7800
- SCROLLBAR_TRACK_BORDER_CLASS,
7801
- // 원본 sd-table__scroll-container--loading/--no-data: 로딩·데이터 없음 시 스크롤 차단
7802
- (isLoading || rowCount === 0) && "overflow-hidden"
7803
- ),
7804
- children: /* @__PURE__ */ jsxRuntime.jsxs(
7805
- "table",
7806
- {
7807
- className: "w-full table-fixed border-separate border-spacing-0 text-left",
7808
- style: { fontSize: 12 },
7809
- children: [
7810
- colgroup,
7811
- /* @__PURE__ */ jsxRuntime.jsxs("tbody", { children: [
7812
- useVirtualScroll && topSpacer > 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { "aria-hidden": true, style: { height: topSpacer }, children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: totalColSpan, className: "p-0" }) }),
7813
- rowCount === 0 ? null : bodyRows.map((row, ri) => {
7814
- const isSel = selectedKeys.has(row[rowKey]);
7815
- const rowBg = "bg-white";
7816
- return /* @__PURE__ */ jsxRuntime.jsxs(
7817
- "tr",
7818
- {
7819
- onClick: () => onRowClick?.(row),
7820
- className: cn(
7821
- "group/table-row hover:bg-[var(--color-grey-05)]",
7822
- onRowClick && "cursor-pointer"
7823
- ),
7824
- style: { height: useVirtualScroll ? effectiveRowHeight : rowH },
7825
- children: [
7826
- selectable && /* @__PURE__ */ jsxRuntime.jsx(
7827
- "td",
7828
- {
7829
- className: cn(
7830
- // 원본 .td--selected: 48px 고정폭, 항상 left sticky, 체크박스 중앙정렬
7831
- "sticky left-0 z-[2] border-b border-solid border-[color:var(--cmp-table-border-color)] align-middle group-hover/table-row:bg-[var(--color-grey-05)]",
7832
- rowBg,
7833
- stickyLeft === 0 && scrolledLeft && "shadow-[5px_0_8px_0_rgba(34,34,34,0.1)]"
7834
- ),
7835
- style: {
7836
- width: SELECTABLE_COLUMN_WIDTH,
7837
- minWidth: SELECTABLE_COLUMN_WIDTH,
7838
- maxWidth: SELECTABLE_COLUMN_WIDTH
7839
- },
7840
- onClick: (e) => e.stopPropagation(),
7841
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(SCheckbox, { value: isSel, onValueChange: () => toggleRow(row) }) })
7842
- }
8192
+ showNoDataSlot ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(bodyScrollClass, "pointer-events-auto bg-white"), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full min-h-[60px] w-full items-center justify-center", children: noDataSlot }) }) : (
8193
+ /* 바디: 세로 스크롤은 이 컨테이너에만 생긴다 (헤더 제외) */
8194
+ /* @__PURE__ */ jsxRuntime.jsx(
8195
+ "div",
8196
+ {
8197
+ ref: scrollRef,
8198
+ onScroll: handleScroll,
8199
+ className: cn(
8200
+ bodyScrollClass,
8201
+ // 원본 sd-table__scroll-container--loading/--no-data: 로딩·데이터 없음 스크롤 차단
8202
+ (isLoading || rowCount === 0) && "overflow-hidden"
8203
+ ),
8204
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
8205
+ "table",
8206
+ {
8207
+ className: "w-full table-fixed border-separate border-spacing-0 text-left",
8208
+ style: { fontSize: 12 },
8209
+ children: [
8210
+ colgroup,
8211
+ /* @__PURE__ */ jsxRuntime.jsxs("tbody", { children: [
8212
+ useVirtualScroll && topSpacer > 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { "aria-hidden": true, style: { height: topSpacer }, children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: totalColSpan, className: "p-0" }) }),
8213
+ rowCount === 0 ? null : bodyRows.map((row, ri) => {
8214
+ const isSel = selectedKeys.has(row[rowKey]);
8215
+ const rowBg = "bg-white";
8216
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8217
+ "tr",
8218
+ {
8219
+ onClick: () => onRowClick?.(row),
8220
+ className: cn(
8221
+ "group/table-row",
8222
+ !noHover && "hover:bg-[var(--color-grey-05)]",
8223
+ onRowClick && "cursor-pointer"
7843
8224
  ),
7844
- visibleCols.map((col, i) => /* @__PURE__ */ jsxRuntime.jsx(
7845
- "td",
7846
- {
7847
- className: cn(
8225
+ style: { height: useVirtualScroll ? effectiveRowHeight : rowH },
8226
+ children: [
8227
+ selectable && /* @__PURE__ */ jsxRuntime.jsx(
8228
+ "td",
8229
+ {
8230
+ className: cn(
8231
+ // 원본 .td--selected: 48px 고정폭, 항상 left sticky, 체크박스 중앙정렬
8232
+ "sticky left-0 z-[2] border-b border-solid border-[color:var(--cmp-table-border-color)] align-middle",
8233
+ rowBg,
8234
+ !noHover && "group-hover/table-row:bg-[var(--color-grey-05)]",
8235
+ stickyLeft === 0 && scrolledLeft && "shadow-[5px_0_8px_0_rgba(34,34,34,0.1)]"
8236
+ ),
8237
+ style: {
8238
+ width: SELECTABLE_COLUMN_WIDTH,
8239
+ minWidth: SELECTABLE_COLUMN_WIDTH,
8240
+ maxWidth: SELECTABLE_COLUMN_WIDTH
8241
+ },
8242
+ onClick: (e) => e.stopPropagation(),
8243
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(SCheckbox, { value: isSel, onValueChange: () => toggleRow(row) }) })
8244
+ }
8245
+ ),
8246
+ visibleCols.map((col, i) => {
8247
+ const tdClassName = cn(
7848
8248
  // 원본 .td: 컬럼 폭에 맞춰 내용 말줄임(overflow hidden + ellipsis) + 행 구분선(border-b)
7849
8249
  // 셀 배경은 흰색으로 채워 뒤 배경이 비치지 않게 하고, hover 시 행 배경(grey_05)을 따른다.
7850
8250
  "overflow-hidden text-ellipsis whitespace-nowrap border-b border-solid border-[color:var(--cmp-table-border-color)] text-[12px] leading-[20px] text-[color:var(--sys-color-fg-primary)]",
7851
8251
  rowBg,
7852
- "group-hover/table-row:bg-[var(--color-grey-05)]",
8252
+ !noHover && "group-hover/table-row:bg-[var(--color-grey-05)]",
7853
8253
  stickyShadowClass(i),
7854
8254
  typeof col.tdClass === "function" ? col.tdClass(row) : col.tdClass
7855
- ),
7856
- style: {
8255
+ );
8256
+ const tdStyle = {
7857
8257
  paddingLeft: cellPadX,
7858
8258
  paddingRight: cellPadX,
7859
8259
  paddingTop: cellPadY,
7860
8260
  paddingBottom: cellPadY,
7861
8261
  textAlign: col.align ?? "left",
7862
8262
  ...cellStyle(i)
7863
- },
7864
- children: col.render ? col.render(row, cellValue(col, row)) : cellValue(col, row)
7865
- },
7866
- col.name
7867
- ))
7868
- ]
7869
- },
7870
- row[rowKey] ?? ri
7871
- );
7872
- }),
7873
- useVirtualScroll && bottomSpacer > 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { "aria-hidden": true, style: { height: bottomSpacer }, children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: totalColSpan, className: "p-0" }) })
7874
- ] })
7875
- ]
7876
- }
7877
- )
7878
- }
8263
+ };
8264
+ if (col.renderCell) {
8265
+ const cell = col.renderCell({
8266
+ row,
8267
+ value: cellValue(col, row),
8268
+ column: col,
8269
+ colIndex: i,
8270
+ rowIndex: ri,
8271
+ isSelected: isSel,
8272
+ className: tdClassName,
8273
+ style: tdStyle
8274
+ });
8275
+ if (cell == null || cell === false) return null;
8276
+ return /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: cell }, col.name);
8277
+ }
8278
+ return /* @__PURE__ */ jsxRuntime.jsx("td", { className: tdClassName, style: tdStyle, children: col.render ? col.render(row, cellValue(col, row)) : cellValue(col, row) }, col.name);
8279
+ })
8280
+ ]
8281
+ },
8282
+ row[rowKey] ?? ri
8283
+ );
8284
+ }),
8285
+ useVirtualScroll && bottomSpacer > 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { "aria-hidden": true, style: { height: bottomSpacer }, children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: totalColSpan, className: "p-0" }) })
8286
+ ] })
8287
+ ]
8288
+ }
8289
+ )
8290
+ }
8291
+ )
7879
8292
  ),
7880
8293
  isNoData && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7881
8294
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -7885,7 +8298,7 @@ var STable = react.forwardRef(function STable2({
7885
8298
  className: "pointer-events-none absolute left-0 right-0 top-0 z-[31] h-[var(--cmp-table-header-height)] bg-white/60"
7886
8299
  }
7887
8300
  ),
7888
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute bottom-0 left-0 right-0 top-[var(--cmp-table-header-height)] z-[30] flex items-center justify-center bg-white/60 text-[12px] text-[color:var(--color-grey-65)]", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[60px] w-full items-center justify-center", children: noDataLabel }) })
8301
+ !showNoDataSlot && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute bottom-0 left-0 right-0 top-[var(--cmp-table-header-height)] z-[30] flex items-center justify-center bg-white/60 text-[12px] text-[color:var(--color-grey-65)]", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[60px] w-full items-center justify-center", children: noDataLabel }) })
7889
8302
  ] }),
7890
8303
  isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-white/60", children: /* @__PURE__ */ jsxRuntime.jsx(SCircleProgress, { indeterminate: true }) })
7891
8304
  ]
@@ -8323,7 +8736,7 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
8323
8736
  const [display, setDisplay] = react.useState(() => formatWithCommas(numValue));
8324
8737
  const [ruleError, setRuleError] = react.useState("");
8325
8738
  const innerRef = react.useRef(null);
8326
- const setRefs = (el) => {
8739
+ const setRefs2 = (el) => {
8327
8740
  innerRef.current = el;
8328
8741
  if (typeof ref === "function") ref(el);
8329
8742
  else if (ref) ref.current = el;
@@ -8497,7 +8910,7 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
8497
8910
  /* @__PURE__ */ jsxRuntime.jsx(
8498
8911
  "input",
8499
8912
  {
8500
- ref: setRefs,
8913
+ ref: setRefs2,
8501
8914
  name,
8502
8915
  type: "text",
8503
8916
  inputMode: useDecimal ? "decimal" : "numeric",
@@ -12025,6 +12438,7 @@ exports.SConfirmModal = SConfirmModal;
12025
12438
  exports.SDatePicker = SDatePicker;
12026
12439
  exports.SDateRangePicker = SDateRangePicker;
12027
12440
  exports.SDivider = SDivider;
12441
+ exports.SDraggableItem = SDraggableItem;
12028
12442
  exports.SDropdownButton = SDropdownButton;
12029
12443
  exports.SExpansionItem = SExpansionItem;
12030
12444
  exports.SField = SField;
@@ -12039,6 +12453,8 @@ exports.SKeyValueTable = SKeyValueTable;
12039
12453
  exports.SLayout = SLayout;
12040
12454
  exports.SLayoutContext = SLayoutContext;
12041
12455
  exports.SLinearProgress = SLinearProgress;
12456
+ exports.SList = SList;
12457
+ exports.SListItem = SListItem;
12042
12458
  exports.SLoadingContainer = SLoadingContainer;
12043
12459
  exports.SLoadingModal = SLoadingModal;
12044
12460
  exports.SLoadingViewport = SLoadingViewport;
@@ -12053,6 +12469,7 @@ exports.SRadio = SRadio;
12053
12469
  exports.SRadioButton = SRadioButton;
12054
12470
  exports.SRadioGroup = SRadioGroup;
12055
12471
  exports.SScrollArea = SScrollArea;
12472
+ exports.SSectionHeaderCard = SSectionHeaderCard2;
12056
12473
  exports.SSelect = SSelect;
12057
12474
  exports.SStepper = SStepper;
12058
12475
  exports.SSwitch = SSwitch;