sellmate-design-system-react 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/SActionModal/SActionModal.cjs +1 -1
- package/dist/components/SActionModal/SActionModal.cjs.map +1 -1
- package/dist/components/SActionModal/SActionModal.js +1 -1
- package/dist/components/SActionModal/SActionModal.js.map +1 -1
- package/dist/components/SBarcodeInput/SBarcodeInput.cjs +218 -209
- package/dist/components/SBarcodeInput/SBarcodeInput.cjs.map +1 -1
- package/dist/components/SBarcodeInput/SBarcodeInput.js +218 -209
- package/dist/components/SBarcodeInput/SBarcodeInput.js.map +1 -1
- package/dist/components/SCalendar/SCalendar.cjs +1 -1
- package/dist/components/SCalendar/SCalendar.cjs.map +1 -1
- package/dist/components/SCalendar/SCalendar.js +1 -1
- package/dist/components/SCalendar/SCalendar.js.map +1 -1
- package/dist/components/SChip/SChip.cjs +1 -1
- package/dist/components/SChip/SChip.cjs.map +1 -1
- package/dist/components/SChip/SChip.d.ts +1 -1
- package/dist/components/SChip/SChip.js +1 -1
- package/dist/components/SChip/SChip.js.map +1 -1
- package/dist/components/SChipInput/SChipInput.cjs +235 -221
- package/dist/components/SChipInput/SChipInput.cjs.map +1 -1
- package/dist/components/SChipInput/SChipInput.js +235 -221
- package/dist/components/SChipInput/SChipInput.js.map +1 -1
- package/dist/components/SCircleProgress/SCircleProgress.cjs +53 -55
- package/dist/components/SCircleProgress/SCircleProgress.cjs.map +1 -1
- package/dist/components/SCircleProgress/SCircleProgress.js +53 -55
- package/dist/components/SCircleProgress/SCircleProgress.js.map +1 -1
- package/dist/components/SDatePicker/SDatePicker.cjs +223 -214
- package/dist/components/SDatePicker/SDatePicker.cjs.map +1 -1
- package/dist/components/SDatePicker/SDatePicker.js +223 -214
- package/dist/components/SDatePicker/SDatePicker.js.map +1 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.cjs +298 -263
- package/dist/components/SDateRangePicker/SDateRangePicker.cjs.map +1 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.js +298 -263
- package/dist/components/SDateRangePicker/SDateRangePicker.js.map +1 -1
- package/dist/components/SDropdownButton/SDropdownButton.cjs +4 -4
- package/dist/components/SDropdownButton/SDropdownButton.cjs.map +1 -1
- package/dist/components/SDropdownButton/SDropdownButton.js +4 -4
- package/dist/components/SDropdownButton/SDropdownButton.js.map +1 -1
- package/dist/components/SField/SField.cjs +218 -21
- package/dist/components/SField/SField.cjs.map +1 -1
- package/dist/components/SField/SField.d.ts +11 -0
- package/dist/components/SField/SField.js +218 -21
- package/dist/components/SField/SField.js.map +1 -1
- package/dist/components/SFilePicker/SFilePicker.cjs +298 -278
- package/dist/components/SFilePicker/SFilePicker.cjs.map +1 -1
- package/dist/components/SFilePicker/SFilePicker.d.ts +4 -2
- package/dist/components/SFilePicker/SFilePicker.js +298 -278
- package/dist/components/SFilePicker/SFilePicker.js.map +1 -1
- package/dist/components/SInput/SInput.cjs +218 -209
- package/dist/components/SInput/SInput.cjs.map +1 -1
- package/dist/components/SInput/SInput.js +218 -209
- package/dist/components/SInput/SInput.js.map +1 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.cjs +610 -450
- package/dist/components/SKeyValueTable/SKeyValueTable.cjs.map +1 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.d.ts +3 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.js +610 -450
- package/dist/components/SKeyValueTable/SKeyValueTable.js.map +1 -1
- package/dist/components/SLoadingContainer/SLoadingContainer.cjs +61 -55
- package/dist/components/SLoadingContainer/SLoadingContainer.cjs.map +1 -1
- package/dist/components/SLoadingContainer/SLoadingContainer.js +61 -55
- package/dist/components/SLoadingContainer/SLoadingContainer.js.map +1 -1
- package/dist/components/SLoadingContainer/loading.cjs +61 -55
- package/dist/components/SLoadingContainer/loading.cjs.map +1 -1
- package/dist/components/SLoadingContainer/loading.js +61 -55
- package/dist/components/SLoadingContainer/loading.js.map +1 -1
- package/dist/components/SLoadingModal/SLoadingModal.cjs +56 -57
- package/dist/components/SLoadingModal/SLoadingModal.cjs.map +1 -1
- package/dist/components/SLoadingModal/SLoadingModal.js +56 -57
- package/dist/components/SLoadingModal/SLoadingModal.js.map +1 -1
- package/dist/components/SNumberInput/SNumberInput.cjs +326 -50
- package/dist/components/SNumberInput/SNumberInput.cjs.map +1 -1
- package/dist/components/SNumberInput/SNumberInput.d.ts +2 -0
- package/dist/components/SNumberInput/SNumberInput.js +326 -50
- package/dist/components/SNumberInput/SNumberInput.js.map +1 -1
- package/dist/components/SPagination/SPagination.cjs +1 -1
- package/dist/components/SPagination/SPagination.cjs.map +1 -1
- package/dist/components/SPagination/SPagination.js +1 -1
- package/dist/components/SPagination/SPagination.js.map +1 -1
- package/dist/components/SSelect/SSelect.cjs +67 -32
- package/dist/components/SSelect/SSelect.cjs.map +1 -1
- package/dist/components/SSelect/SSelect.js +67 -32
- package/dist/components/SSelect/SSelect.js.map +1 -1
- package/dist/components/STable/STable.cjs +121 -88
- package/dist/components/STable/STable.cjs.map +1 -1
- package/dist/components/STable/STable.js +121 -88
- package/dist/components/STable/STable.js.map +1 -1
- package/dist/components/STextarea/STextarea.cjs +218 -21
- package/dist/components/STextarea/STextarea.cjs.map +1 -1
- package/dist/components/STextarea/STextarea.js +218 -21
- package/dist/components/STextarea/STextarea.js.map +1 -1
- package/dist/components/SToast/SToastContainer.cjs +3 -3
- package/dist/components/SToast/SToastContainer.cjs.map +1 -1
- package/dist/components/SToast/SToastContainer.js +3 -3
- package/dist/components/SToast/SToastContainer.js.map +1 -1
- package/dist/components/STooltip/STooltip.cjs +209 -14
- package/dist/components/STooltip/STooltip.cjs.map +1 -1
- package/dist/components/STooltip/STooltip.js +209 -14
- package/dist/components/STooltip/STooltip.js.map +1 -1
- package/dist/index.cjs +432 -260
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +432 -260
- package/dist/index.js.map +1 -1
- package/dist/styles.css +51 -27
- package/dist/theme.css +4 -2
- 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
|
|
8
|
+
var RPopover2 = require('@radix-ui/react-popover');
|
|
9
9
|
var Ariakit = require('@ariakit/react');
|
|
10
10
|
var RCheckbox = require('@radix-ui/react-checkbox');
|
|
11
11
|
|
|
@@ -27,7 +27,7 @@ function _interopNamespace(e) {
|
|
|
27
27
|
return Object.freeze(n);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
var
|
|
30
|
+
var RPopover2__namespace = /*#__PURE__*/_interopNamespace(RPopover2);
|
|
31
31
|
var Ariakit__namespace = /*#__PURE__*/_interopNamespace(Ariakit);
|
|
32
32
|
var RCheckbox__namespace = /*#__PURE__*/_interopNamespace(RCheckbox);
|
|
33
33
|
|
|
@@ -2901,11 +2901,200 @@ PortalContainerContext.Provider;
|
|
|
2901
2901
|
function usePortalContainer() {
|
|
2902
2902
|
return react.useContext(PortalContainerContext) ?? void 0;
|
|
2903
2903
|
}
|
|
2904
|
+
|
|
2905
|
+
// src/components/STag/tag.config.ts
|
|
2906
|
+
var TAG_SIZE_CONFIG = {
|
|
2907
|
+
xs: {
|
|
2908
|
+
height: 20,
|
|
2909
|
+
paddingX: 8,
|
|
2910
|
+
gap: 4,
|
|
2911
|
+
radius: 6,
|
|
2912
|
+
iconSize: 12,
|
|
2913
|
+
fontSize: 11,
|
|
2914
|
+
fontWeight: 500,
|
|
2915
|
+
lineHeight: 18
|
|
2916
|
+
},
|
|
2917
|
+
sm: {
|
|
2918
|
+
height: 24,
|
|
2919
|
+
paddingX: 8,
|
|
2920
|
+
gap: 4,
|
|
2921
|
+
radius: 6,
|
|
2922
|
+
iconSize: 16,
|
|
2923
|
+
fontSize: 12,
|
|
2924
|
+
fontWeight: 700,
|
|
2925
|
+
lineHeight: 20
|
|
2926
|
+
},
|
|
2927
|
+
md: {
|
|
2928
|
+
height: 28,
|
|
2929
|
+
paddingX: 12,
|
|
2930
|
+
gap: 6,
|
|
2931
|
+
radius: 8,
|
|
2932
|
+
iconSize: 16,
|
|
2933
|
+
fontSize: 14,
|
|
2934
|
+
fontWeight: 700,
|
|
2935
|
+
lineHeight: 24
|
|
2936
|
+
}
|
|
2937
|
+
};
|
|
2938
|
+
var STag = react.forwardRef(function STag2({
|
|
2939
|
+
shape = "square",
|
|
2940
|
+
size = "sm",
|
|
2941
|
+
color = "grey",
|
|
2942
|
+
label = "",
|
|
2943
|
+
icon,
|
|
2944
|
+
iconLeft = true,
|
|
2945
|
+
width,
|
|
2946
|
+
className,
|
|
2947
|
+
style,
|
|
2948
|
+
...rest
|
|
2949
|
+
}, ref) {
|
|
2950
|
+
const s = TAG_SIZE_CONFIG[size];
|
|
2951
|
+
const contentColor = `var(--cmp-tag-${color}-content)`;
|
|
2952
|
+
const iconNode = icon ? /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.iconSize, color: contentColor }) : null;
|
|
2953
|
+
const resolvedWidth = typeof width === "number" ? `${width}px` : width;
|
|
2954
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2955
|
+
"span",
|
|
2956
|
+
{
|
|
2957
|
+
ref,
|
|
2958
|
+
"aria-label": label || "tag",
|
|
2959
|
+
className: cn(
|
|
2960
|
+
"box-border inline-flex w-fit select-none items-center justify-center whitespace-nowrap",
|
|
2961
|
+
className
|
|
2962
|
+
),
|
|
2963
|
+
style: {
|
|
2964
|
+
minHeight: s.height,
|
|
2965
|
+
padding: `0 ${s.paddingX}px`,
|
|
2966
|
+
gap: s.gap,
|
|
2967
|
+
borderRadius: shape === "pill" ? 999 : s.radius,
|
|
2968
|
+
fontSize: s.fontSize,
|
|
2969
|
+
fontWeight: s.fontWeight,
|
|
2970
|
+
lineHeight: `${s.lineHeight}px`,
|
|
2971
|
+
background: `var(--cmp-tag-${color}-bg)`,
|
|
2972
|
+
color: contentColor,
|
|
2973
|
+
...resolvedWidth != null ? { width: resolvedWidth } : {},
|
|
2974
|
+
...style
|
|
2975
|
+
},
|
|
2976
|
+
...rest,
|
|
2977
|
+
children: [
|
|
2978
|
+
icon && iconLeft && iconNode,
|
|
2979
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex min-w-0 items-center justify-center", children: label }),
|
|
2980
|
+
icon && !iconLeft && iconNode
|
|
2981
|
+
]
|
|
2982
|
+
}
|
|
2983
|
+
);
|
|
2984
|
+
});
|
|
2985
|
+
var SIZE = {
|
|
2986
|
+
xxs: { icon: 12, radius: "sm" },
|
|
2987
|
+
xs: { icon: 16, radius: "sm" },
|
|
2988
|
+
sm: { icon: 20, radius: "sm" },
|
|
2989
|
+
md: { icon: 24, radius: "md" },
|
|
2990
|
+
lg: { icon: 32, radius: "md" }
|
|
2991
|
+
};
|
|
2992
|
+
var TOOLTIP_HIDE_DELAY_MS = 100;
|
|
2993
|
+
function SGhostButton({
|
|
2994
|
+
icon,
|
|
2995
|
+
size = "sm",
|
|
2996
|
+
intent = "default",
|
|
2997
|
+
ariaLabel = "",
|
|
2998
|
+
tooltipText,
|
|
2999
|
+
disabled = false,
|
|
3000
|
+
onClick,
|
|
3001
|
+
className,
|
|
3002
|
+
style
|
|
3003
|
+
}) {
|
|
3004
|
+
const portalContainer = usePortalContainer();
|
|
3005
|
+
const [open, setOpen] = react.useState(false);
|
|
3006
|
+
const hideTimer = react.useRef(void 0);
|
|
3007
|
+
const cancelHide = () => {
|
|
3008
|
+
if (hideTimer.current) {
|
|
3009
|
+
clearTimeout(hideTimer.current);
|
|
3010
|
+
hideTimer.current = void 0;
|
|
3011
|
+
}
|
|
3012
|
+
};
|
|
3013
|
+
const openNow = () => {
|
|
3014
|
+
cancelHide();
|
|
3015
|
+
setOpen(true);
|
|
3016
|
+
};
|
|
3017
|
+
const startHide = () => {
|
|
3018
|
+
cancelHide();
|
|
3019
|
+
hideTimer.current = setTimeout(() => setOpen(false), TOOLTIP_HIDE_DELAY_MS);
|
|
3020
|
+
};
|
|
3021
|
+
const s = SIZE[size];
|
|
3022
|
+
const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
|
|
3023
|
+
const btn = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3024
|
+
"button",
|
|
3025
|
+
{
|
|
3026
|
+
type: "button",
|
|
3027
|
+
disabled,
|
|
3028
|
+
"aria-disabled": disabled ? "true" : void 0,
|
|
3029
|
+
"aria-label": ariaLabel.trim() || void 0,
|
|
3030
|
+
tabIndex: disabled ? -1 : void 0,
|
|
3031
|
+
onClick: (e) => {
|
|
3032
|
+
if (disabled) {
|
|
3033
|
+
e.preventDefault();
|
|
3034
|
+
return;
|
|
3035
|
+
}
|
|
3036
|
+
onClick?.(e);
|
|
3037
|
+
},
|
|
3038
|
+
className: cn(
|
|
3039
|
+
"group relative box-border inline-flex items-center justify-center border-none bg-transparent p-0 transition-shadow",
|
|
3040
|
+
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
3041
|
+
"focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
|
|
3042
|
+
className
|
|
3043
|
+
),
|
|
3044
|
+
style: {
|
|
3045
|
+
width: `var(--cmp-ghostButton-${size}-size)`,
|
|
3046
|
+
height: `var(--cmp-ghostButton-${size}-size)`,
|
|
3047
|
+
borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
|
|
3048
|
+
...style
|
|
3049
|
+
},
|
|
3050
|
+
children: [
|
|
3051
|
+
!disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3052
|
+
"span",
|
|
3053
|
+
{
|
|
3054
|
+
"aria-hidden": true,
|
|
3055
|
+
className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover:opacity-5",
|
|
3056
|
+
style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
|
|
3057
|
+
}
|
|
3058
|
+
),
|
|
3059
|
+
/* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.icon, color: contentColor })
|
|
3060
|
+
]
|
|
3061
|
+
}
|
|
3062
|
+
);
|
|
3063
|
+
const text = (tooltipText ?? "").trim();
|
|
3064
|
+
if (text === "") return btn;
|
|
3065
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(RPopover2__namespace.Root, { open, onOpenChange: setOpen, children: [
|
|
3066
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3067
|
+
"span",
|
|
3068
|
+
{
|
|
3069
|
+
className: "inline-flex",
|
|
3070
|
+
onMouseEnter: openNow,
|
|
3071
|
+
onMouseLeave: startHide,
|
|
3072
|
+
onFocus: openNow,
|
|
3073
|
+
onBlur: startHide,
|
|
3074
|
+
children: btn
|
|
3075
|
+
}
|
|
3076
|
+
) }),
|
|
3077
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3078
|
+
RPopover2__namespace.Content,
|
|
3079
|
+
{
|
|
3080
|
+
side: "top",
|
|
3081
|
+
sideOffset: 4,
|
|
3082
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
3083
|
+
"aria-hidden": true,
|
|
3084
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
3085
|
+
onMouseEnter: cancelHide,
|
|
3086
|
+
onMouseLeave: startHide,
|
|
3087
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
|
|
3088
|
+
}
|
|
3089
|
+
) })
|
|
3090
|
+
] });
|
|
3091
|
+
}
|
|
2904
3092
|
var HIDE_DELAY_MS = 100;
|
|
2905
3093
|
function useBody(content, message = []) {
|
|
2906
3094
|
if (content != null) return content;
|
|
2907
3095
|
if (message.length === 0) return null;
|
|
2908
|
-
|
|
3096
|
+
const singleLine = message.length === 1;
|
|
3097
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: message.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: singleLine ? "leading-[24px]" : void 0, children: line }, i)) });
|
|
2909
3098
|
}
|
|
2910
3099
|
var STooltip = react.forwardRef(function STooltip2({
|
|
2911
3100
|
content,
|
|
@@ -2963,7 +3152,7 @@ var STooltip = react.forwardRef(function STooltip2({
|
|
|
2963
3152
|
if (disabled || body == null) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: triggerNode });
|
|
2964
3153
|
const isHover = trigger === "hover";
|
|
2965
3154
|
const contentClass = cn(
|
|
2966
|
-
"z-50 max-w-xs rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px]",
|
|
3155
|
+
"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)]",
|
|
2967
3156
|
FLOATING_SLIDE_ANIM,
|
|
2968
3157
|
className
|
|
2969
3158
|
);
|
|
@@ -2973,10 +3162,10 @@ var STooltip = react.forwardRef(function STooltip2({
|
|
|
2973
3162
|
fontWeight: tooltipType === "default" ? 500 : 700,
|
|
2974
3163
|
...style
|
|
2975
3164
|
};
|
|
2976
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3165
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(RPopover2__namespace.Root, { open, onOpenChange: setOpen, children: [
|
|
2977
3166
|
isHover ? (
|
|
2978
3167
|
// hover: Anchor(위치 기준) + 직접 mouse 핸들러 — 클릭으로 토글되지 않도록 Trigger 미사용
|
|
2979
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3168
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2980
3169
|
"span",
|
|
2981
3170
|
{
|
|
2982
3171
|
className: "inline-flex",
|
|
@@ -2987,9 +3176,9 @@ var STooltip = react.forwardRef(function STooltip2({
|
|
|
2987
3176
|
children: triggerNode
|
|
2988
3177
|
}
|
|
2989
3178
|
) })
|
|
2990
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2991
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2992
|
-
|
|
3179
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Trigger, { asChild: true, children: triggerNode }),
|
|
3180
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3181
|
+
RPopover2__namespace.Content,
|
|
2993
3182
|
{
|
|
2994
3183
|
side: placement,
|
|
2995
3184
|
sideOffset: 8,
|
|
@@ -3008,15 +3197,21 @@ var STooltip = react.forwardRef(function STooltip2({
|
|
|
3008
3197
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-[12px]", children: [
|
|
3009
3198
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: body }),
|
|
3010
3199
|
useClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3011
|
-
|
|
3200
|
+
SGhostButton,
|
|
3012
3201
|
{
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3202
|
+
icon: "close",
|
|
3203
|
+
size: "xs",
|
|
3204
|
+
intent: tooltipType === "default" ? "inverse" : "default",
|
|
3205
|
+
ariaLabel: "\uB2EB\uAE30",
|
|
3206
|
+
className: "shrink-0",
|
|
3207
|
+
onClick: () => {
|
|
3208
|
+
cancelHide();
|
|
3209
|
+
setOpen(false);
|
|
3210
|
+
}
|
|
3016
3211
|
}
|
|
3017
3212
|
)
|
|
3018
3213
|
] }),
|
|
3019
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3214
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
3020
3215
|
]
|
|
3021
3216
|
}
|
|
3022
3217
|
) })
|
|
@@ -3216,8 +3411,8 @@ function useFormField(field) {
|
|
|
3216
3411
|
}, [ctx, name]);
|
|
3217
3412
|
}
|
|
3218
3413
|
var FIELD_SIZE = {
|
|
3219
|
-
sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon:
|
|
3220
|
-
md: { height: 36, radius: 6, fieldGap: 16, labelGap: 8, fontSize: 14, lineHeight: 24, icon:
|
|
3414
|
+
sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon: 16 },
|
|
3415
|
+
md: { height: 36, radius: 6, fieldGap: 16, labelGap: 8, fontSize: 14, lineHeight: 24, icon: 16 }
|
|
3221
3416
|
};
|
|
3222
3417
|
var ALIGN = {
|
|
3223
3418
|
start: "flex-start",
|
|
@@ -3232,6 +3427,7 @@ var SField = react.forwardRef(function SField2({
|
|
|
3232
3427
|
labelTooltip = "",
|
|
3233
3428
|
labelTooltipProps,
|
|
3234
3429
|
labelWidth,
|
|
3430
|
+
labelHeight,
|
|
3235
3431
|
size = "sm",
|
|
3236
3432
|
addonLabel = "",
|
|
3237
3433
|
addonAlign = "start",
|
|
@@ -3246,6 +3442,7 @@ var SField = react.forwardRef(function SField2({
|
|
|
3246
3442
|
readOnly = false,
|
|
3247
3443
|
width,
|
|
3248
3444
|
multiline = false,
|
|
3445
|
+
borderless = false,
|
|
3249
3446
|
children,
|
|
3250
3447
|
className,
|
|
3251
3448
|
style,
|
|
@@ -3279,8 +3476,8 @@ var SField = react.forwardRef(function SField2({
|
|
|
3279
3476
|
const resolvedSuccess = status === "pass";
|
|
3280
3477
|
const showError = resolvedError && errorMessage !== "";
|
|
3281
3478
|
const interactive = !disabled && !readOnly;
|
|
3282
|
-
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)";
|
|
3283
|
-
const bgColor = disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
|
|
3479
|
+
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)";
|
|
3480
|
+
const bgColor = borderless ? "transparent" : disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
|
|
3284
3481
|
const textColor = disabled ? "var(--color-grey-65)" : readOnly ? "var(--sys-color-field-text-readOnly)" : "var(--sys-color-field-text-default)";
|
|
3285
3482
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3286
3483
|
"div",
|
|
@@ -3297,266 +3494,78 @@ var SField = react.forwardRef(function SField2({
|
|
|
3297
3494
|
{
|
|
3298
3495
|
className: "flex shrink-0 items-center font-bold text-(--sys-color-field-text-default)",
|
|
3299
3496
|
style: {
|
|
3300
|
-
height: s.height,
|
|
3497
|
+
height: cssLen(labelHeight) ?? s.height,
|
|
3301
3498
|
marginRight: s.fieldGap,
|
|
3302
3499
|
width: cssLen(labelWidth),
|
|
3303
|
-
fontSize: s.fontSize,
|
|
3304
|
-
lineHeight: `${s.lineHeight}px`
|
|
3305
|
-
},
|
|
3306
|
-
children: [
|
|
3307
|
-
icon && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.icon, style: { marginRight: s.labelGap } }),
|
|
3308
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis whitespace-nowrap", children: label }),
|
|
3309
|
-
(labelTooltip !== "" || labelTooltipProps) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", style: { marginLeft: s.labelGap }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3310
|
-
STooltip,
|
|
3311
|
-
{
|
|
3312
|
-
message: labelTooltip !== "" ? [labelTooltip] : void 0,
|
|
3313
|
-
iconSize: s.icon,
|
|
3314
|
-
...labelTooltipProps
|
|
3315
|
-
}
|
|
3316
|
-
) })
|
|
3317
|
-
]
|
|
3318
|
-
}
|
|
3319
|
-
),
|
|
3320
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
3321
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3322
|
-
"div",
|
|
3323
|
-
{
|
|
3324
|
-
className: cn(
|
|
3325
|
-
"relative box-border flex min-w-0 items-stretch overflow-hidden border border-solid border-(--field-bc)",
|
|
3326
|
-
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]",
|
|
3327
|
-
disabled && "cursor-not-allowed"
|
|
3328
|
-
),
|
|
3329
|
-
style: {
|
|
3330
|
-
// @ts-expect-error CSS 변수
|
|
3331
|
-
"--field-bc": borderColor,
|
|
3332
|
-
// focused/hovered prop이 명시된 경우 강조를 즉시 반영
|
|
3333
|
-
...interactive && focused ? { boxShadow: "0px 0px 4px 0px #0071ff66" } : {},
|
|
3334
|
-
...multiline ? { minHeight: s.height } : { height: s.height },
|
|
3335
|
-
"width": cssLen(width),
|
|
3336
|
-
"borderRadius": s.radius,
|
|
3337
|
-
"background": bgColor,
|
|
3338
|
-
"color": textColor
|
|
3339
|
-
},
|
|
3340
|
-
"data-focused": focused || void 0,
|
|
3341
|
-
"data-hovered": hovered || void 0,
|
|
3342
|
-
children: [
|
|
3343
|
-
effectiveAddonLabel !== "" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3344
|
-
"div",
|
|
3345
|
-
{
|
|
3346
|
-
className: "flex shrink-0 items-center gap-(--cmp-field-addonLabel-gap) whitespace-nowrap border-r border-solid px-(--cmp-field-addonLabel-paddingX) text-12 font-medium leading-20",
|
|
3347
|
-
style: {
|
|
3348
|
-
// 원본 sd-field: labelWidth가 addon 폭(--sd-field-addon-width)에도 적용됨
|
|
3349
|
-
width: cssLen(labelWidth),
|
|
3350
|
-
justifyContent: ALIGN[addonAlign],
|
|
3351
|
-
background: "var(--cmp-field-addonLabel-bg)",
|
|
3352
|
-
borderRightColor: disabled ? "var(--cmp-field-addonLabel-border-disabled)" : "var(--cmp-field-addonLabel-border-default)",
|
|
3353
|
-
borderTopLeftRadius: s.radius - 1,
|
|
3354
|
-
borderBottomLeftRadius: s.radius - 1
|
|
3355
|
-
},
|
|
3356
|
-
children: [
|
|
3357
|
-
icon && !label && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.icon }),
|
|
3358
|
-
effectiveAddonLabel
|
|
3359
|
-
]
|
|
3360
|
-
}
|
|
3361
|
-
),
|
|
3362
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 flex-1", children })
|
|
3363
|
-
]
|
|
3364
|
-
}
|
|
3365
|
-
),
|
|
3366
|
-
showError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-(--cmp-field-contents-gap) text-12 font-normal leading-20 text-(--cmp-field-errorMessage-color)", children: errorMessage }) : hint !== "" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-(--cmp-field-contents-gap) text-12 font-normal leading-20 text-(--cmp-field-hint-color)", children: hint }) : null
|
|
3367
|
-
] })
|
|
3368
|
-
] })
|
|
3369
|
-
}
|
|
3370
|
-
);
|
|
3371
|
-
});
|
|
3372
|
-
|
|
3373
|
-
// src/components/STag/tag.config.ts
|
|
3374
|
-
var TAG_SIZE_CONFIG = {
|
|
3375
|
-
xs: {
|
|
3376
|
-
height: 20,
|
|
3377
|
-
paddingX: 8,
|
|
3378
|
-
gap: 4,
|
|
3379
|
-
radius: 6,
|
|
3380
|
-
iconSize: 12,
|
|
3381
|
-
fontSize: 11,
|
|
3382
|
-
fontWeight: 500,
|
|
3383
|
-
lineHeight: 18
|
|
3384
|
-
},
|
|
3385
|
-
sm: {
|
|
3386
|
-
height: 24,
|
|
3387
|
-
paddingX: 8,
|
|
3388
|
-
gap: 4,
|
|
3389
|
-
radius: 6,
|
|
3390
|
-
iconSize: 16,
|
|
3391
|
-
fontSize: 12,
|
|
3392
|
-
fontWeight: 700,
|
|
3393
|
-
lineHeight: 20
|
|
3394
|
-
},
|
|
3395
|
-
md: {
|
|
3396
|
-
height: 28,
|
|
3397
|
-
paddingX: 12,
|
|
3398
|
-
gap: 6,
|
|
3399
|
-
radius: 8,
|
|
3400
|
-
iconSize: 16,
|
|
3401
|
-
fontSize: 14,
|
|
3402
|
-
fontWeight: 700,
|
|
3403
|
-
lineHeight: 24
|
|
3404
|
-
}
|
|
3405
|
-
};
|
|
3406
|
-
var STag = react.forwardRef(function STag2({
|
|
3407
|
-
shape = "square",
|
|
3408
|
-
size = "sm",
|
|
3409
|
-
color = "grey",
|
|
3410
|
-
label = "",
|
|
3411
|
-
icon,
|
|
3412
|
-
iconLeft = true,
|
|
3413
|
-
width,
|
|
3414
|
-
className,
|
|
3415
|
-
style,
|
|
3416
|
-
...rest
|
|
3417
|
-
}, ref) {
|
|
3418
|
-
const s = TAG_SIZE_CONFIG[size];
|
|
3419
|
-
const contentColor = `var(--cmp-tag-${color}-content)`;
|
|
3420
|
-
const iconNode = icon ? /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.iconSize, color: contentColor }) : null;
|
|
3421
|
-
const resolvedWidth = typeof width === "number" ? `${width}px` : width;
|
|
3422
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3423
|
-
"span",
|
|
3424
|
-
{
|
|
3425
|
-
ref,
|
|
3426
|
-
"aria-label": label || "tag",
|
|
3427
|
-
className: cn(
|
|
3428
|
-
"box-border inline-flex w-fit select-none items-center justify-center whitespace-nowrap",
|
|
3429
|
-
className
|
|
3430
|
-
),
|
|
3431
|
-
style: {
|
|
3432
|
-
minHeight: s.height,
|
|
3433
|
-
padding: `0 ${s.paddingX}px`,
|
|
3434
|
-
gap: s.gap,
|
|
3435
|
-
borderRadius: shape === "pill" ? 999 : s.radius,
|
|
3436
|
-
fontSize: s.fontSize,
|
|
3437
|
-
fontWeight: s.fontWeight,
|
|
3438
|
-
lineHeight: `${s.lineHeight}px`,
|
|
3439
|
-
background: `var(--cmp-tag-${color}-bg)`,
|
|
3440
|
-
color: contentColor,
|
|
3441
|
-
...resolvedWidth != null ? { width: resolvedWidth } : {},
|
|
3442
|
-
...style
|
|
3443
|
-
},
|
|
3444
|
-
...rest,
|
|
3445
|
-
children: [
|
|
3446
|
-
icon && iconLeft && iconNode,
|
|
3447
|
-
label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex min-w-0 items-center justify-center", children: label }),
|
|
3448
|
-
icon && !iconLeft && iconNode
|
|
3449
|
-
]
|
|
3450
|
-
}
|
|
3451
|
-
);
|
|
3452
|
-
});
|
|
3453
|
-
var SIZE = {
|
|
3454
|
-
xxs: { icon: 12, radius: "sm" },
|
|
3455
|
-
xs: { icon: 16, radius: "sm" },
|
|
3456
|
-
sm: { icon: 20, radius: "sm" },
|
|
3457
|
-
md: { icon: 24, radius: "md" },
|
|
3458
|
-
lg: { icon: 32, radius: "md" }
|
|
3459
|
-
};
|
|
3460
|
-
var TOOLTIP_HIDE_DELAY_MS = 100;
|
|
3461
|
-
function SGhostButton({
|
|
3462
|
-
icon,
|
|
3463
|
-
size = "sm",
|
|
3464
|
-
intent = "default",
|
|
3465
|
-
ariaLabel = "",
|
|
3466
|
-
tooltipText,
|
|
3467
|
-
disabled = false,
|
|
3468
|
-
onClick,
|
|
3469
|
-
className,
|
|
3470
|
-
style
|
|
3471
|
-
}) {
|
|
3472
|
-
const portalContainer = usePortalContainer();
|
|
3473
|
-
const [open, setOpen] = react.useState(false);
|
|
3474
|
-
const hideTimer = react.useRef(void 0);
|
|
3475
|
-
const cancelHide = () => {
|
|
3476
|
-
if (hideTimer.current) {
|
|
3477
|
-
clearTimeout(hideTimer.current);
|
|
3478
|
-
hideTimer.current = void 0;
|
|
3479
|
-
}
|
|
3480
|
-
};
|
|
3481
|
-
const openNow = () => {
|
|
3482
|
-
cancelHide();
|
|
3483
|
-
setOpen(true);
|
|
3484
|
-
};
|
|
3485
|
-
const startHide = () => {
|
|
3486
|
-
cancelHide();
|
|
3487
|
-
hideTimer.current = setTimeout(() => setOpen(false), TOOLTIP_HIDE_DELAY_MS);
|
|
3488
|
-
};
|
|
3489
|
-
const s = SIZE[size];
|
|
3490
|
-
const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
|
|
3491
|
-
const btn = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3492
|
-
"button",
|
|
3493
|
-
{
|
|
3494
|
-
type: "button",
|
|
3495
|
-
disabled,
|
|
3496
|
-
"aria-disabled": disabled ? "true" : void 0,
|
|
3497
|
-
"aria-label": ariaLabel.trim() || void 0,
|
|
3498
|
-
tabIndex: disabled ? -1 : void 0,
|
|
3499
|
-
onClick: (e) => {
|
|
3500
|
-
if (disabled) {
|
|
3501
|
-
e.preventDefault();
|
|
3502
|
-
return;
|
|
3503
|
-
}
|
|
3504
|
-
onClick?.(e);
|
|
3505
|
-
},
|
|
3506
|
-
className: cn(
|
|
3507
|
-
"group relative box-border inline-flex items-center justify-center border-none bg-transparent p-0 transition-shadow",
|
|
3508
|
-
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
3509
|
-
"focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
|
|
3510
|
-
className
|
|
3511
|
-
),
|
|
3512
|
-
style: {
|
|
3513
|
-
width: `var(--cmp-ghostButton-${size}-size)`,
|
|
3514
|
-
height: `var(--cmp-ghostButton-${size}-size)`,
|
|
3515
|
-
borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
|
|
3516
|
-
...style
|
|
3517
|
-
},
|
|
3518
|
-
children: [
|
|
3519
|
-
!disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3520
|
-
"span",
|
|
3521
|
-
{
|
|
3522
|
-
"aria-hidden": true,
|
|
3523
|
-
className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover:opacity-5",
|
|
3524
|
-
style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
|
|
3500
|
+
fontSize: s.fontSize,
|
|
3501
|
+
lineHeight: `${s.lineHeight}px`
|
|
3502
|
+
},
|
|
3503
|
+
children: [
|
|
3504
|
+
icon && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.icon, style: { marginRight: s.labelGap } }),
|
|
3505
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis whitespace-nowrap", children: label }),
|
|
3506
|
+
(labelTooltip !== "" || labelTooltipProps) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", style: { marginLeft: s.labelGap }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3507
|
+
STooltip,
|
|
3508
|
+
{
|
|
3509
|
+
message: labelTooltip !== "" ? [labelTooltip] : void 0,
|
|
3510
|
+
iconSize: s.icon,
|
|
3511
|
+
...labelTooltipProps
|
|
3512
|
+
}
|
|
3513
|
+
) })
|
|
3514
|
+
]
|
|
3525
3515
|
}
|
|
3526
3516
|
),
|
|
3527
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3528
|
-
|
|
3517
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
3518
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3519
|
+
"div",
|
|
3520
|
+
{
|
|
3521
|
+
className: cn(
|
|
3522
|
+
"relative box-border flex min-w-0 items-stretch overflow-hidden border border-solid border-(--field-bc)",
|
|
3523
|
+
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]",
|
|
3524
|
+
disabled && "cursor-not-allowed"
|
|
3525
|
+
),
|
|
3526
|
+
style: {
|
|
3527
|
+
// @ts-expect-error CSS 변수
|
|
3528
|
+
"--field-bc": borderColor,
|
|
3529
|
+
// focused/hovered prop이 명시된 경우 강조를 즉시 반영
|
|
3530
|
+
...interactive && !borderless && focused ? { boxShadow: "0px 0px 4px 0px #0071ff66" } : {},
|
|
3531
|
+
...multiline ? { minHeight: s.height } : { height: s.height },
|
|
3532
|
+
"width": cssLen(width),
|
|
3533
|
+
"borderRadius": s.radius,
|
|
3534
|
+
"background": bgColor,
|
|
3535
|
+
"color": textColor
|
|
3536
|
+
},
|
|
3537
|
+
"data-focused": focused || void 0,
|
|
3538
|
+
"data-hovered": hovered || void 0,
|
|
3539
|
+
children: [
|
|
3540
|
+
effectiveAddonLabel !== "" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3541
|
+
"div",
|
|
3542
|
+
{
|
|
3543
|
+
className: "flex shrink-0 items-center gap-(--cmp-field-addonLabel-gap) whitespace-nowrap border-r border-solid px-(--cmp-field-addonLabel-paddingX) text-12 font-medium leading-20",
|
|
3544
|
+
style: {
|
|
3545
|
+
// 원본 sd-field: labelWidth가 addon 폭(--sd-field-addon-width)에도 적용됨
|
|
3546
|
+
width: cssLen(labelWidth),
|
|
3547
|
+
justifyContent: ALIGN[addonAlign],
|
|
3548
|
+
background: "var(--cmp-field-addonLabel-bg)",
|
|
3549
|
+
borderRightColor: disabled ? "var(--cmp-field-addonLabel-border-disabled)" : "var(--cmp-field-addonLabel-border-default)",
|
|
3550
|
+
borderTopLeftRadius: s.radius - 1,
|
|
3551
|
+
borderBottomLeftRadius: s.radius - 1
|
|
3552
|
+
},
|
|
3553
|
+
children: [
|
|
3554
|
+
icon && !label && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.icon }),
|
|
3555
|
+
effectiveAddonLabel
|
|
3556
|
+
]
|
|
3557
|
+
}
|
|
3558
|
+
),
|
|
3559
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 flex-1", children })
|
|
3560
|
+
]
|
|
3561
|
+
}
|
|
3562
|
+
),
|
|
3563
|
+
showError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-(--cmp-field-contents-gap) text-12 font-normal leading-20 text-(--cmp-field-errorMessage-color)", children: errorMessage }) : hint !== "" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-(--cmp-field-contents-gap) text-12 font-normal leading-20 text-(--cmp-field-hint-color)", children: hint }) : null
|
|
3564
|
+
] })
|
|
3565
|
+
] })
|
|
3529
3566
|
}
|
|
3530
3567
|
);
|
|
3531
|
-
|
|
3532
|
-
if (text === "") return btn;
|
|
3533
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(RPopover__namespace.Root, { open, onOpenChange: setOpen, children: [
|
|
3534
|
-
/* @__PURE__ */ jsxRuntime.jsx(RPopover__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3535
|
-
"span",
|
|
3536
|
-
{
|
|
3537
|
-
className: "inline-flex",
|
|
3538
|
-
onMouseEnter: openNow,
|
|
3539
|
-
onMouseLeave: startHide,
|
|
3540
|
-
onFocus: openNow,
|
|
3541
|
-
onBlur: startHide,
|
|
3542
|
-
children: btn
|
|
3543
|
-
}
|
|
3544
|
-
) }),
|
|
3545
|
-
/* @__PURE__ */ jsxRuntime.jsx(RPopover__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3546
|
-
RPopover__namespace.Content,
|
|
3547
|
-
{
|
|
3548
|
-
side: "top",
|
|
3549
|
-
sideOffset: 4,
|
|
3550
|
-
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
3551
|
-
"aria-hidden": true,
|
|
3552
|
-
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
3553
|
-
onMouseEnter: cancelHide,
|
|
3554
|
-
onMouseLeave: startHide,
|
|
3555
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
|
|
3556
|
-
}
|
|
3557
|
-
) })
|
|
3558
|
-
] });
|
|
3559
|
-
}
|
|
3568
|
+
});
|
|
3560
3569
|
var FONT = {
|
|
3561
3570
|
sm: { fontSize: 12, lineHeight: 20, paddingX: "var(--cmp-textinput-sm-paddingX)" },
|
|
3562
3571
|
md: { fontSize: 14, lineHeight: 24, paddingX: "var(--cmp-textinput-md-paddingX)" }
|
|
@@ -3811,8 +3820,8 @@ var STextarea = react.forwardRef(function STextarea2({
|
|
|
3811
3820
|
);
|
|
3812
3821
|
});
|
|
3813
3822
|
var PAD2 = {
|
|
3814
|
-
sm: { fontSize: 12, stepper: 20, icon: 12 },
|
|
3815
|
-
md: { fontSize: 14, stepper: 24, icon: 14 }
|
|
3823
|
+
sm: { fontSize: 12, lineHeight: 20, stepper: 20, icon: 12 },
|
|
3824
|
+
md: { fontSize: 14, lineHeight: 24, stepper: 24, icon: 14 }
|
|
3816
3825
|
};
|
|
3817
3826
|
var toNumber = (val) => {
|
|
3818
3827
|
if (val === null || val === void 0 || val === "") return null;
|
|
@@ -3830,6 +3839,38 @@ var formatWithCommas = (value) => {
|
|
|
3830
3839
|
const result = isNeg ? "-" + formatted : formatted;
|
|
3831
3840
|
return decPart !== void 0 && decPart !== "" ? result + "." + decPart : result;
|
|
3832
3841
|
};
|
|
3842
|
+
var addCommas = (value) => value.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
3843
|
+
var formatInputWithCommas = (value) => {
|
|
3844
|
+
const isNeg = value.startsWith("-");
|
|
3845
|
+
const unsigned = isNeg ? value.slice(1) : value;
|
|
3846
|
+
const hasDecimal = unsigned.includes(".");
|
|
3847
|
+
const [intPart = "", decPart = ""] = unsigned.split(".");
|
|
3848
|
+
const formattedInt = addCommas(intPart === "" ? "0" : intPart);
|
|
3849
|
+
return `${isNeg ? "-" : ""}${formattedInt}${hasDecimal ? `.${decPart}` : ""}`;
|
|
3850
|
+
};
|
|
3851
|
+
var getDecimalLimit = (useDecimal, maxDecimalLength) => {
|
|
3852
|
+
if (!useDecimal || maxDecimalLength === void 0 || !Number.isFinite(maxDecimalLength)) {
|
|
3853
|
+
return void 0;
|
|
3854
|
+
}
|
|
3855
|
+
return Math.max(0, Math.floor(maxDecimalLength));
|
|
3856
|
+
};
|
|
3857
|
+
var applyDecimalLimit = (value, decimalLimit) => {
|
|
3858
|
+
if (value === null || decimalLimit === void 0) return value;
|
|
3859
|
+
return Number(value.toFixed(decimalLimit));
|
|
3860
|
+
};
|
|
3861
|
+
var getLogicalCaret = (value, caret) => {
|
|
3862
|
+
return value.slice(0, caret ?? value.length).replace(/,/g, "").length;
|
|
3863
|
+
};
|
|
3864
|
+
var getDisplayCaret = (value, logicalCaret) => {
|
|
3865
|
+
if (logicalCaret <= 0) return 0;
|
|
3866
|
+
let seen = 0;
|
|
3867
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
3868
|
+
if (value[i] === ",") continue;
|
|
3869
|
+
seen += 1;
|
|
3870
|
+
if (seen >= logicalCaret) return i + 1;
|
|
3871
|
+
}
|
|
3872
|
+
return value.length;
|
|
3873
|
+
};
|
|
3833
3874
|
var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
3834
3875
|
value,
|
|
3835
3876
|
onValueChange,
|
|
@@ -3839,6 +3880,7 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
3839
3880
|
step = 1,
|
|
3840
3881
|
useButton = false,
|
|
3841
3882
|
useDecimal = false,
|
|
3883
|
+
maxDecimalLength,
|
|
3842
3884
|
inputPrefix = "",
|
|
3843
3885
|
inputSuffix = "",
|
|
3844
3886
|
inputClass,
|
|
@@ -3870,7 +3912,8 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
3870
3912
|
}, ref) {
|
|
3871
3913
|
const p = PAD2[size];
|
|
3872
3914
|
const padX = `var(--cmp-numberInput-${size}-paddingX)`;
|
|
3873
|
-
const
|
|
3915
|
+
const decimalLimit = getDecimalLimit(useDecimal, maxDecimalLength);
|
|
3916
|
+
const numValue = applyDecimalLimit(toNumber(value), decimalLimit);
|
|
3874
3917
|
const [display, setDisplay] = react.useState(() => formatWithCommas(numValue));
|
|
3875
3918
|
const [ruleError, setRuleError] = react.useState("");
|
|
3876
3919
|
const innerRef = react.useRef(null);
|
|
@@ -3880,8 +3923,9 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
3880
3923
|
else if (ref) ref.current = el;
|
|
3881
3924
|
};
|
|
3882
3925
|
react.useEffect(() => {
|
|
3883
|
-
|
|
3884
|
-
|
|
3926
|
+
if (document.activeElement === innerRef.current) return;
|
|
3927
|
+
setDisplay(formatWithCommas(applyDecimalLimit(toNumber(value), decimalLimit)));
|
|
3928
|
+
}, [decimalLimit, value]);
|
|
3885
3929
|
useFormField({
|
|
3886
3930
|
name,
|
|
3887
3931
|
validate: () => {
|
|
@@ -3893,48 +3937,87 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
3893
3937
|
});
|
|
3894
3938
|
const resolvedError = error || ruleError !== "";
|
|
3895
3939
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
3896
|
-
const
|
|
3897
|
-
|
|
3898
|
-
|
|
3940
|
+
const restoreCaret = (nextDisplay, logicalCaret) => {
|
|
3941
|
+
const input = innerRef.current;
|
|
3942
|
+
if (logicalCaret === void 0 || !input || document.activeElement !== input) return;
|
|
3943
|
+
const nextCaret = getDisplayCaret(nextDisplay, logicalCaret);
|
|
3944
|
+
requestAnimationFrame(() => {
|
|
3945
|
+
if (document.activeElement !== input) return;
|
|
3946
|
+
input.setSelectionRange(nextCaret, nextCaret);
|
|
3947
|
+
});
|
|
3948
|
+
};
|
|
3949
|
+
const setDisplayWithCaret = (nextDisplay, logicalCaret) => {
|
|
3950
|
+
setDisplay(nextDisplay);
|
|
3951
|
+
restoreCaret(nextDisplay, logicalCaret);
|
|
3952
|
+
};
|
|
3953
|
+
const resetRejectedInput = (target, logicalCaret) => {
|
|
3954
|
+
target.value = display;
|
|
3955
|
+
restoreCaret(display, Math.min(logicalCaret, display.replace(/,/g, "").length));
|
|
3956
|
+
};
|
|
3957
|
+
const emit = (n, logicalCaret) => {
|
|
3958
|
+
const next = applyDecimalLimit(n, decimalLimit);
|
|
3959
|
+
const nextDisplay = formatWithCommas(next);
|
|
3960
|
+
setDisplayWithCaret(nextDisplay, logicalCaret);
|
|
3961
|
+
onValueChange?.(next);
|
|
3899
3962
|
};
|
|
3900
3963
|
const incDisabled = disabled || readOnly || numValue !== null && numValue >= max;
|
|
3901
3964
|
const decDisabled = disabled || readOnly || numValue !== null && numValue <= min;
|
|
3902
3965
|
const increment = () => {
|
|
3903
3966
|
if (incDisabled) return;
|
|
3904
3967
|
const cur = numValue ?? (min === Number.NEGATIVE_INFINITY ? 0 : min);
|
|
3905
|
-
const next = Math.min(cur + step, max);
|
|
3968
|
+
const next = applyDecimalLimit(Math.min(cur + step, max), decimalLimit);
|
|
3906
3969
|
if (next !== cur) emit(next);
|
|
3907
3970
|
};
|
|
3908
3971
|
const decrement = () => {
|
|
3909
3972
|
if (decDisabled) return;
|
|
3910
3973
|
const cur = numValue ?? (min === Number.NEGATIVE_INFINITY ? 0 : min);
|
|
3911
|
-
const next = Math.max(cur - step, min);
|
|
3974
|
+
const next = applyDecimalLimit(Math.max(cur - step, min), decimalLimit);
|
|
3912
3975
|
if (next !== cur) emit(next);
|
|
3913
3976
|
};
|
|
3914
|
-
const handleInput = (
|
|
3977
|
+
const handleInput = (event) => {
|
|
3978
|
+
const target = event.currentTarget;
|
|
3979
|
+
const raw = target.value;
|
|
3980
|
+
const logicalCaret = getLogicalCaret(raw, target.selectionStart);
|
|
3915
3981
|
if (raw === "") {
|
|
3916
|
-
|
|
3982
|
+
setDisplayWithCaret("", 0);
|
|
3917
3983
|
onValueChange?.(null);
|
|
3918
3984
|
return;
|
|
3919
3985
|
}
|
|
3920
3986
|
const cleaned = raw.replace(/,/g, "");
|
|
3921
3987
|
const decimals = (cleaned.match(/\./g) || []).length;
|
|
3922
|
-
if (decimals > 1)
|
|
3988
|
+
if (decimals > 1) {
|
|
3989
|
+
resetRejectedInput(target, logicalCaret);
|
|
3990
|
+
return;
|
|
3991
|
+
}
|
|
3923
3992
|
if (cleaned === "-" || cleaned === "." || cleaned === "-.") {
|
|
3924
|
-
|
|
3993
|
+
setDisplayWithCaret(cleaned, logicalCaret);
|
|
3994
|
+
return;
|
|
3995
|
+
}
|
|
3996
|
+
if (!useDecimal && cleaned.includes(".")) {
|
|
3997
|
+
resetRejectedInput(target, logicalCaret);
|
|
3925
3998
|
return;
|
|
3926
3999
|
}
|
|
3927
|
-
if (
|
|
4000
|
+
if (decimalLimit !== void 0 && cleaned.includes(".")) {
|
|
4001
|
+
const fraction = cleaned.split(".")[1] ?? "";
|
|
4002
|
+
if (fraction.length > decimalLimit) {
|
|
4003
|
+
resetRejectedInput(target, logicalCaret);
|
|
4004
|
+
return;
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
3928
4007
|
if (cleaned.endsWith(".") && decimals === 1) {
|
|
3929
4008
|
const parsed2 = toNumber(cleaned.slice(0, -1));
|
|
3930
4009
|
if (parsed2 !== null) {
|
|
3931
|
-
|
|
4010
|
+
setDisplayWithCaret(formatInputWithCommas(cleaned), logicalCaret);
|
|
3932
4011
|
return;
|
|
3933
4012
|
}
|
|
3934
4013
|
}
|
|
3935
4014
|
const parsed = toNumber(cleaned);
|
|
3936
|
-
if (parsed === null)
|
|
3937
|
-
|
|
4015
|
+
if (parsed === null) {
|
|
4016
|
+
resetRejectedInput(target, logicalCaret);
|
|
4017
|
+
return;
|
|
4018
|
+
}
|
|
4019
|
+
setDisplayWithCaret(formatInputWithCommas(cleaned), logicalCaret);
|
|
4020
|
+
onValueChange?.(applyDecimalLimit(parsed, decimalLimit));
|
|
3938
4021
|
};
|
|
3939
4022
|
const stepper = (dir) => {
|
|
3940
4023
|
const off = dir === "inc" ? incDisabled : decDisabled;
|
|
@@ -3947,8 +4030,8 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
3947
4030
|
"aria-label": dir === "inc" ? "\uC99D\uAC00" : "\uAC10\uC18C",
|
|
3948
4031
|
onClick: dir === "inc" ? increment : decrement,
|
|
3949
4032
|
className: cn(
|
|
3950
|
-
"flex flex-shrink-0 items-center justify-center",
|
|
3951
|
-
off ? "cursor-not-allowed" : "cursor-pointer"
|
|
4033
|
+
"flex flex-shrink-0 items-center justify-center border border-solid border-transparent transition-colors",
|
|
4034
|
+
off ? "cursor-not-allowed" : "cursor-pointer hover:border-[var(--color-border-accentLight)]"
|
|
3952
4035
|
),
|
|
3953
4036
|
style: {
|
|
3954
4037
|
width: `var(--cmp-numberInput-stepper-${size}-size)`,
|
|
@@ -3997,24 +4080,26 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
3997
4080
|
style: {
|
|
3998
4081
|
// 원본 sd-number-input: content gap = padding-x 토큰 (gap 토큰 아님)
|
|
3999
4082
|
gap: `var(--cmp-numberInput-${size}-paddingX)`,
|
|
4000
|
-
padding: `0 ${useButton ? padX : `calc(${padX} * 2)`}
|
|
4083
|
+
padding: `0 ${useButton ? padX : `calc(${padX} * 2)`}`,
|
|
4084
|
+
fontSize: p.fontSize,
|
|
4085
|
+
lineHeight: `${p.lineHeight}px`
|
|
4001
4086
|
},
|
|
4002
4087
|
children: [
|
|
4003
4088
|
useButton && stepper("dec"),
|
|
4004
|
-
inputPrefix !== "" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", style: {
|
|
4089
|
+
inputPrefix !== "" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", style: { color: affixColor }, children: inputPrefix }),
|
|
4005
4090
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4006
4091
|
"input",
|
|
4007
4092
|
{
|
|
4008
4093
|
ref: setRefs,
|
|
4009
4094
|
name,
|
|
4010
4095
|
type: "text",
|
|
4011
|
-
inputMode: "numeric",
|
|
4096
|
+
inputMode: useDecimal ? "decimal" : "numeric",
|
|
4012
4097
|
value: display,
|
|
4013
4098
|
placeholder,
|
|
4014
4099
|
disabled,
|
|
4015
4100
|
readOnly,
|
|
4016
4101
|
autoFocus,
|
|
4017
|
-
onChange:
|
|
4102
|
+
onChange: handleInput,
|
|
4018
4103
|
onKeyDown: (e) => {
|
|
4019
4104
|
if (e.key === "ArrowUp") {
|
|
4020
4105
|
e.preventDefault();
|
|
@@ -4026,26 +4111,29 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
4026
4111
|
},
|
|
4027
4112
|
onFocus: (e) => onFocus?.(e),
|
|
4028
4113
|
onBlur: (e) => {
|
|
4029
|
-
const
|
|
4114
|
+
const cleaned = display.replace(/,/g, "");
|
|
4115
|
+
const n = toNumber(cleaned);
|
|
4030
4116
|
const clamped = n === null ? null : Math.min(Math.max(n, min), max);
|
|
4031
4117
|
if (clamped !== n) emit(clamped);
|
|
4032
|
-
else setDisplay(
|
|
4118
|
+
else setDisplay(n === null ? "" : formatInputWithCommas(cleaned));
|
|
4033
4119
|
if (rules && rules.length > 0) setRuleError(runRules(clamped, rules));
|
|
4034
4120
|
onBlur?.(e);
|
|
4035
4121
|
},
|
|
4036
4122
|
className: cn(
|
|
4037
|
-
|
|
4123
|
+
// h-full 대신 라인박스 높이 그대로 두어 prefix/suffix 와 동일하게 flex 로 수직 센터링
|
|
4124
|
+
// (h-full 이면 input 내부 텍스트 센터링을 브라우저가 수행해 1px 어긋날 수 있음)
|
|
4125
|
+
"min-w-0 flex-1 border-0 bg-transparent p-0 outline-none placeholder:text-[color:var(--cmp-numberInput-text-placeholder)] disabled:cursor-not-allowed",
|
|
4038
4126
|
inputClass
|
|
4039
4127
|
),
|
|
4040
4128
|
style: {
|
|
4041
|
-
fontSize
|
|
4129
|
+
// fontSize/lineHeight 는 컨테이너에서 상속
|
|
4042
4130
|
textAlign: useButton ? "center" : "right",
|
|
4043
4131
|
color: disabled ? "var(--cmp-numberInput-text-disabled)" : "var(--cmp-numberInput-text-default)",
|
|
4044
4132
|
...inputStyle
|
|
4045
4133
|
}
|
|
4046
4134
|
}
|
|
4047
4135
|
),
|
|
4048
|
-
inputSuffix !== "" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", style: {
|
|
4136
|
+
inputSuffix !== "" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", style: { color: affixColor }, children: inputSuffix }),
|
|
4049
4137
|
useButton && stepper("inc")
|
|
4050
4138
|
]
|
|
4051
4139
|
}
|
|
@@ -4059,15 +4147,28 @@ function flattenOptions(options, depth = 1) {
|
|
|
4059
4147
|
const out = [];
|
|
4060
4148
|
for (const o of options) {
|
|
4061
4149
|
const hasChildren = Array.isArray(o.children) && o.children.length > 0;
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4150
|
+
if (hasChildren) {
|
|
4151
|
+
const childFlat = flattenOptions(o.children, depth + 1);
|
|
4152
|
+
const allChildrenDisabled = childFlat.every((c) => c.disabled);
|
|
4153
|
+
out.push({
|
|
4154
|
+
value: String(o.value),
|
|
4155
|
+
label: o.label,
|
|
4156
|
+
disabled: !!o.disabled || allChildrenDisabled,
|
|
4157
|
+
depth,
|
|
4158
|
+
isGroup: true,
|
|
4159
|
+
raw: o.value
|
|
4160
|
+
});
|
|
4161
|
+
out.push(...childFlat);
|
|
4162
|
+
} else {
|
|
4163
|
+
out.push({
|
|
4164
|
+
value: String(o.value),
|
|
4165
|
+
label: o.label,
|
|
4166
|
+
disabled: !!o.disabled,
|
|
4167
|
+
depth,
|
|
4168
|
+
isGroup: false,
|
|
4169
|
+
raw: o.value
|
|
4170
|
+
});
|
|
4171
|
+
}
|
|
4071
4172
|
}
|
|
4072
4173
|
return out;
|
|
4073
4174
|
}
|
|
@@ -4191,6 +4292,9 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
4191
4292
|
);
|
|
4192
4293
|
const flat = react.useMemo(() => flattenOptions(options), [options]);
|
|
4193
4294
|
const selectable = react.useMemo(() => selectableOptions(flat), [flat]);
|
|
4295
|
+
const hasLeaf = react.useMemo(() => flat.some((o) => !o.isGroup), [flat]);
|
|
4296
|
+
const allOptionsDisabled = hasLeaf && selectable.length === 0;
|
|
4297
|
+
const effectiveDisabled = disabled || allOptionsDisabled;
|
|
4194
4298
|
const showSearch = useSearch && selectable.length >= SEARCH_THRESHOLD;
|
|
4195
4299
|
const labelByValue = react.useMemo(() => new Map(flat.map((o) => [o.value, o.label])), [flat]);
|
|
4196
4300
|
const rawByValue = react.useMemo(() => new Map(flat.map((o) => [o.value, o.raw])), [flat]);
|
|
@@ -4257,10 +4361,10 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
4257
4361
|
Ariakit__namespace.Select,
|
|
4258
4362
|
{
|
|
4259
4363
|
ref: triggerRef,
|
|
4260
|
-
disabled,
|
|
4364
|
+
disabled: effectiveDisabled,
|
|
4261
4365
|
className: "flex h-full w-full cursor-pointer items-center justify-between gap-[8px] bg-transparent px-[12px] text-left text-[12px] leading-[20px] outline-none disabled:cursor-not-allowed",
|
|
4262
4366
|
style: {
|
|
4263
|
-
color:
|
|
4367
|
+
color: effectiveDisabled ? "var(--cmp-select-text-disabled)" : isPlaceholder ? "var(--cmp-select-icon-default)" : "var(--cmp-select-text-default)"
|
|
4264
4368
|
},
|
|
4265
4369
|
children: [
|
|
4266
4370
|
isHtmlLabel(triggerText) ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4275,7 +4379,7 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
4275
4379
|
{
|
|
4276
4380
|
name: "chevronDown",
|
|
4277
4381
|
size: 12,
|
|
4278
|
-
color:
|
|
4382
|
+
color: effectiveDisabled ? "var(--cmp-select-icon-disabled)" : "var(--cmp-select-icon-default)",
|
|
4279
4383
|
className: cn("shrink-0 transition-transform duration-200", open && "rotate-180")
|
|
4280
4384
|
}
|
|
4281
4385
|
)
|
|
@@ -4289,7 +4393,7 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
4289
4393
|
portalElement: portalContainer,
|
|
4290
4394
|
gutter: 4,
|
|
4291
4395
|
sameWidth: !dropdownWidth,
|
|
4292
|
-
className: "z-50 overflow-auto rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)]
|
|
4396
|
+
className: "z-50 overflow-auto rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.1)] data-[enter]:animate-floating-in-bottom data-[leave]:animate-floating-out-bottom",
|
|
4293
4397
|
style: {
|
|
4294
4398
|
maxHeight: dropdownHeight,
|
|
4295
4399
|
...dropdownWidth ? { width: dropdownWidth } : {},
|
|
@@ -4330,7 +4434,7 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
4330
4434
|
),
|
|
4331
4435
|
hasItems ? /* @__PURE__ */ jsxRuntime.jsx(ItemList, { items: filtered, multi, selected, useSearch: showSearch }) : (
|
|
4332
4436
|
// 원본 sd-select-listbox__empty (표시할 항목이 없을 때)
|
|
4333
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-[12px] py-[12px] text-
|
|
4437
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-[12px] py-[12px] text-left text-[12px] leading-[20px] text-[color:var(--cmp-listItem-content-disabled)]", children: "\uD45C\uC2DC\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." })
|
|
4334
4438
|
)
|
|
4335
4439
|
]
|
|
4336
4440
|
}
|
|
@@ -4353,7 +4457,7 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
4353
4457
|
error: error || ruleError !== "",
|
|
4354
4458
|
status: rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0,
|
|
4355
4459
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
4356
|
-
disabled,
|
|
4460
|
+
disabled: effectiveDisabled,
|
|
4357
4461
|
width,
|
|
4358
4462
|
className,
|
|
4359
4463
|
style,
|
|
@@ -4388,7 +4492,11 @@ function ItemList({
|
|
|
4388
4492
|
{
|
|
4389
4493
|
className: cn(
|
|
4390
4494
|
"select-none py-[4px] pr-[12px] text-[12px] leading-[20px] text-[color:var(--cmp-listItem-content-default)]",
|
|
4391
|
-
isDepth1 ? "border-t border-solid border-[color:var(--cmp-listItem-depth1-border-color)] bg-[var(--cmp-listItem-depth1-bg-default)] font-bold" : "bg-[var(--cmp-listItem-depth2-middle-bg)] font-medium"
|
|
4495
|
+
isDepth1 ? "border-t border-solid border-[color:var(--cmp-listItem-depth1-border-color)] bg-[var(--cmp-listItem-depth1-bg-default)] font-bold" : "bg-[var(--cmp-listItem-depth2-middle-bg)] font-medium",
|
|
4496
|
+
// 하위가 전부 비활성이면(select.config 에서 bubble-up) 어미 그룹도 비활성 처리:
|
|
4497
|
+
// 텍스트는 회색(#888), depth1 그룹은 파란 배경 대신 회색(#EEE)으로 (depth2 는 #F6F6F6 유지)
|
|
4498
|
+
o.disabled && "text-[color:var(--cmp-listItem-content-disabled)]",
|
|
4499
|
+
o.disabled && isDepth1 && "bg-[var(--cmp-listItem-depth1-bg-disabled)]"
|
|
4392
4500
|
),
|
|
4393
4501
|
style: { paddingLeft: padLeft },
|
|
4394
4502
|
children: o.label
|
|
@@ -4415,15 +4523,21 @@ function ItemList({
|
|
|
4415
4523
|
"span",
|
|
4416
4524
|
{
|
|
4417
4525
|
className: cn(
|
|
4418
|
-
"flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid
|
|
4419
|
-
|
|
4526
|
+
"flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid",
|
|
4527
|
+
o.disabled ? (
|
|
4528
|
+
// 비활성: 회색 채움(#E1E1E1) + 회색 테두리(#CCCCCC)
|
|
4529
|
+
"border-[color:var(--cmp-checkbox-border-disabled)] bg-[var(--cmp-checkbox-bg-disabled)]"
|
|
4530
|
+
) : cn(
|
|
4531
|
+
"group-data-[active-item]:border-[color:var(--cmp-checkbox-checked-border-inverse)]",
|
|
4532
|
+
isSelected ? "border-[color:var(--cmp-checkbox-checked-bg-default)] bg-[var(--cmp-checkbox-checked-bg-default)] group-data-[active-item]:bg-transparent" : "border-[color:var(--cmp-checkbox-unchecked-border-default)] bg-transparent"
|
|
4533
|
+
)
|
|
4420
4534
|
),
|
|
4421
4535
|
children: isSelected && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4422
4536
|
SIcon,
|
|
4423
4537
|
{
|
|
4424
4538
|
name: "checkboxCheck",
|
|
4425
4539
|
size: 12,
|
|
4426
|
-
color: "var(--cmp-checkbox-checked-icon-default)"
|
|
4540
|
+
color: o.disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : "var(--cmp-checkbox-checked-icon-default)"
|
|
4427
4541
|
}
|
|
4428
4542
|
)
|
|
4429
4543
|
}
|
|
@@ -4829,7 +4943,7 @@ function SCalendar({
|
|
|
4829
4943
|
"span",
|
|
4830
4944
|
{
|
|
4831
4945
|
className: cn(
|
|
4832
|
-
"flex h-[var(--cmp-datepicker-calendar-day-circle-size)] w-[var(--cmp-datepicker-calendar-day-circle-size)] items-center justify-center rounded-[var(--cmp-datepicker-calendar-day-circle-radius)] border border-solid border-transparent text-[14px]",
|
|
4946
|
+
"flex h-[var(--cmp-datepicker-calendar-day-circle-size)] w-[var(--cmp-datepicker-calendar-day-circle-size)] items-center justify-center rounded-[var(--cmp-datepicker-calendar-day-circle-radius)] border border-solid border-transparent text-[14px] leading-[var(--cmp-datepicker-calendar-day-circle-size)]",
|
|
4833
4947
|
selected ? "bg-[var(--cmp-datepicker-calendar-day-select-bg)] text-[color:var(--cmp-datepicker-calendar-day-select-text)]" : disabled ? "text-[color:var(--cmp-datepicker-calendar-day-disabled-text)]" : "text-[color:var(--cmp-datepicker-calendar-day-default-text)] hover:border-[color:var(--cmp-datepicker-calendar-day-hover-border)]",
|
|
4834
4948
|
isToday && !disabled && "font-bold"
|
|
4835
4949
|
),
|
|
@@ -4954,8 +5068,8 @@ function SDatePicker({
|
|
|
4954
5068
|
disabled,
|
|
4955
5069
|
className,
|
|
4956
5070
|
style,
|
|
4957
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4958
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5071
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(RPopover2__namespace.Root, { open, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
5072
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4959
5073
|
"button",
|
|
4960
5074
|
{
|
|
4961
5075
|
type: "button",
|
|
@@ -4991,8 +5105,8 @@ function SDatePicker({
|
|
|
4991
5105
|
]
|
|
4992
5106
|
}
|
|
4993
5107
|
) }),
|
|
4994
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4995
|
-
|
|
5108
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5109
|
+
RPopover2__namespace.Content,
|
|
4996
5110
|
{
|
|
4997
5111
|
side: "bottom",
|
|
4998
5112
|
align: "start",
|
|
@@ -5019,6 +5133,7 @@ function RangeCalendar({
|
|
|
5019
5133
|
selectable,
|
|
5020
5134
|
maxRange,
|
|
5021
5135
|
onSelect,
|
|
5136
|
+
onPendingStartChange,
|
|
5022
5137
|
onViewChange
|
|
5023
5138
|
}) {
|
|
5024
5139
|
const today = todayStr();
|
|
@@ -5081,9 +5196,11 @@ function RangeCalendar({
|
|
|
5081
5196
|
setStart(d);
|
|
5082
5197
|
setEnd(null);
|
|
5083
5198
|
setHover(null);
|
|
5199
|
+
onPendingStartChange?.(d);
|
|
5084
5200
|
return;
|
|
5085
5201
|
}
|
|
5086
5202
|
setEnd(d);
|
|
5203
|
+
onPendingStartChange?.(null);
|
|
5087
5204
|
onSelect([start, d]);
|
|
5088
5205
|
};
|
|
5089
5206
|
const GRID_COLS = "grid grid-cols-[repeat(7,var(--cmp-datepicker-calendar-day-width))]";
|
|
@@ -5218,8 +5335,11 @@ function SDateRangePicker({
|
|
|
5218
5335
|
const portalContainer = usePortalContainer();
|
|
5219
5336
|
const [open, setOpen] = react.useState(false);
|
|
5220
5337
|
const [ruleError, setRuleError] = react.useState("");
|
|
5338
|
+
const [pendingStart, setPendingStart] = react.useState(null);
|
|
5221
5339
|
const hasValue = value != null && value[0] !== "" && value[1] !== "";
|
|
5222
|
-
const
|
|
5340
|
+
const hasDisplay = pendingStart != null || hasValue;
|
|
5341
|
+
const startText = pendingStart ?? (hasValue ? value[0] : "");
|
|
5342
|
+
const endText = pendingStart ? "" : hasValue ? value[1] : "";
|
|
5223
5343
|
useFormField({
|
|
5224
5344
|
name,
|
|
5225
5345
|
validate: () => {
|
|
@@ -5233,6 +5353,7 @@ function SDateRangePicker({
|
|
|
5233
5353
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
5234
5354
|
const dims = size === "md" ? { padX: 16, gap: 12, icon: 20, minW: 104, fontSize: 14, lineHeight: 24, radius: 6 } : { padX: 12, gap: 8, icon: 16, minW: 80, fontSize: 12, lineHeight: 20, radius: 4 };
|
|
5235
5355
|
const select = (r) => {
|
|
5356
|
+
setPendingStart(null);
|
|
5236
5357
|
onValueChange?.(r);
|
|
5237
5358
|
if (rules && rules.length > 0) setRuleError(runRules(r, rules));
|
|
5238
5359
|
setOpen(false);
|
|
@@ -5257,61 +5378,80 @@ function SDateRangePicker({
|
|
|
5257
5378
|
disabled,
|
|
5258
5379
|
className,
|
|
5259
5380
|
style,
|
|
5260
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
{
|
|
5273
|
-
name: "date",
|
|
5274
|
-
size: dims.icon,
|
|
5275
|
-
color: disabled ? "var(--cmp-datepicker-icon-disabled)" : "var(--cmp-datepicker-icon-default)",
|
|
5276
|
-
className: "flex-shrink-0"
|
|
5277
|
-
}
|
|
5278
|
-
),
|
|
5279
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5280
|
-
"span",
|
|
5281
|
-
{
|
|
5282
|
-
className: "flex-1 truncate text-center",
|
|
5283
|
-
style: {
|
|
5284
|
-
minWidth: dims.minW,
|
|
5285
|
-
fontSize: dims.fontSize,
|
|
5286
|
-
lineHeight: `${dims.lineHeight}px`,
|
|
5287
|
-
color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasValue ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
|
|
5288
|
-
},
|
|
5289
|
-
children: display
|
|
5290
|
-
}
|
|
5291
|
-
)
|
|
5292
|
-
]
|
|
5293
|
-
}
|
|
5294
|
-
) }),
|
|
5295
|
-
/* @__PURE__ */ jsxRuntime.jsx(RPopover__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5296
|
-
RPopover__namespace.Content,
|
|
5297
|
-
{
|
|
5298
|
-
side: "bottom",
|
|
5299
|
-
align: "start",
|
|
5300
|
-
sideOffset: 4,
|
|
5301
|
-
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
5302
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5303
|
-
RangeCalendar,
|
|
5381
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5382
|
+
RPopover2__namespace.Root,
|
|
5383
|
+
{
|
|
5384
|
+
open,
|
|
5385
|
+
onOpenChange: (o) => {
|
|
5386
|
+
if (disabled) return;
|
|
5387
|
+
setOpen(o);
|
|
5388
|
+
if (!o) setPendingStart(null);
|
|
5389
|
+
},
|
|
5390
|
+
children: [
|
|
5391
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5392
|
+
"button",
|
|
5304
5393
|
{
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5394
|
+
type: "button",
|
|
5395
|
+
name,
|
|
5396
|
+
disabled,
|
|
5397
|
+
className: "flex h-full w-full items-center overflow-hidden bg-transparent outline-none disabled:cursor-not-allowed",
|
|
5398
|
+
style: { padding: `0 ${dims.padX}px`, gap: dims.gap, borderRadius: dims.radius },
|
|
5399
|
+
children: [
|
|
5400
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5401
|
+
SIcon,
|
|
5402
|
+
{
|
|
5403
|
+
name: "date",
|
|
5404
|
+
size: dims.icon,
|
|
5405
|
+
color: disabled ? "var(--cmp-datepicker-icon-disabled)" : "var(--cmp-datepicker-icon-default)",
|
|
5406
|
+
className: "flex-shrink-0"
|
|
5407
|
+
}
|
|
5408
|
+
),
|
|
5409
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5410
|
+
"span",
|
|
5411
|
+
{
|
|
5412
|
+
className: cn(
|
|
5413
|
+
"flex-1 items-center",
|
|
5414
|
+
hasDisplay ? "flex" : "block truncate text-center"
|
|
5415
|
+
),
|
|
5416
|
+
style: {
|
|
5417
|
+
minWidth: dims.minW,
|
|
5418
|
+
fontSize: dims.fontSize,
|
|
5419
|
+
lineHeight: `${dims.lineHeight}px`,
|
|
5420
|
+
color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasDisplay ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
|
|
5421
|
+
},
|
|
5422
|
+
children: hasDisplay ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5423
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-right", children: startText }),
|
|
5424
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-[4px]", children: "~" }),
|
|
5425
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-left", children: endText })
|
|
5426
|
+
] }) : placeholder
|
|
5427
|
+
}
|
|
5428
|
+
)
|
|
5429
|
+
]
|
|
5310
5430
|
}
|
|
5311
|
-
)
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5431
|
+
) }),
|
|
5432
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5433
|
+
RPopover2__namespace.Content,
|
|
5434
|
+
{
|
|
5435
|
+
side: "bottom",
|
|
5436
|
+
align: "start",
|
|
5437
|
+
sideOffset: 4,
|
|
5438
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
5439
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5440
|
+
RangeCalendar,
|
|
5441
|
+
{
|
|
5442
|
+
value: value ?? null,
|
|
5443
|
+
selectable,
|
|
5444
|
+
maxRange,
|
|
5445
|
+
onSelect: select,
|
|
5446
|
+
onPendingStartChange: setPendingStart,
|
|
5447
|
+
onViewChange
|
|
5448
|
+
}
|
|
5449
|
+
)
|
|
5450
|
+
}
|
|
5451
|
+
) })
|
|
5452
|
+
]
|
|
5453
|
+
}
|
|
5454
|
+
)
|
|
5315
5455
|
}
|
|
5316
5456
|
);
|
|
5317
5457
|
}
|
|
@@ -5320,7 +5460,7 @@ var SChip = react.forwardRef(function SChip2({
|
|
|
5320
5460
|
value = "",
|
|
5321
5461
|
error: errorProp = false,
|
|
5322
5462
|
disabled = false,
|
|
5323
|
-
editable =
|
|
5463
|
+
editable = false,
|
|
5324
5464
|
showRemove = true,
|
|
5325
5465
|
placeholder = "",
|
|
5326
5466
|
rules,
|
|
@@ -5473,6 +5613,7 @@ function SFilePicker({
|
|
|
5473
5613
|
hovered = false,
|
|
5474
5614
|
inline = false,
|
|
5475
5615
|
multiple = false,
|
|
5616
|
+
useMultipleListBox = false,
|
|
5476
5617
|
accept,
|
|
5477
5618
|
maxFileSize,
|
|
5478
5619
|
maxTotalSize,
|
|
@@ -5500,8 +5641,8 @@ function SFilePicker({
|
|
|
5500
5641
|
const inputRef = react.useRef(null);
|
|
5501
5642
|
const [ruleError, setRuleError] = react.useState("");
|
|
5502
5643
|
const files = multiple ? Array.isArray(value) ? value : [] : value && !Array.isArray(value) ? value : null;
|
|
5503
|
-
const
|
|
5504
|
-
const displayText =
|
|
5644
|
+
const hasFiles = multiple ? files.length > 0 : !!files;
|
|
5645
|
+
const displayText = !hasFiles ? placeholder : multiple ? files.map((f) => f.name).join(", ") : files.name;
|
|
5505
5646
|
useFormField({
|
|
5506
5647
|
name,
|
|
5507
5648
|
validate: () => {
|
|
@@ -5565,78 +5706,88 @@ function SFilePicker({
|
|
|
5565
5706
|
const padX = size === "md" ? "var(--cmp-filepicker-md-paddingX)" : "var(--cmp-filepicker-sm-paddingX)";
|
|
5566
5707
|
const iconSize = size === "md" ? 20 : 16;
|
|
5567
5708
|
const gapCls = size === "md" ? "gap-[var(--cmp-filepicker-md-gap)]" : "gap-[var(--cmp-filepicker-sm-gap)]";
|
|
5568
|
-
const
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
onClick: open,
|
|
5589
|
-
"aria-label": placeholder,
|
|
5590
|
-
className: cn(
|
|
5591
|
-
"flex min-w-0 flex-1 items-center bg-transparent text-left",
|
|
5592
|
-
gapCls,
|
|
5593
|
-
disabled ? "cursor-not-allowed" : "cursor-pointer"
|
|
5709
|
+
const inlinePlaceholder = inline && !disabled && !hasFiles;
|
|
5710
|
+
const content = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5711
|
+
"div",
|
|
5712
|
+
{
|
|
5713
|
+
className: cn("group/filepicker flex h-full w-full items-center", gapCls),
|
|
5714
|
+
style: { padding: inline ? 0 : `0 ${padX}` },
|
|
5715
|
+
children: [
|
|
5716
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5717
|
+
"input",
|
|
5718
|
+
{
|
|
5719
|
+
ref: inputRef,
|
|
5720
|
+
type: "file",
|
|
5721
|
+
className: "hidden",
|
|
5722
|
+
disabled,
|
|
5723
|
+
multiple,
|
|
5724
|
+
accept,
|
|
5725
|
+
name: resolvedName,
|
|
5726
|
+
onChange,
|
|
5727
|
+
"aria-label": placeholder
|
|
5728
|
+
}
|
|
5594
5729
|
),
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5730
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5731
|
+
"button",
|
|
5732
|
+
{
|
|
5733
|
+
type: "button",
|
|
5734
|
+
disabled,
|
|
5735
|
+
onClick: open,
|
|
5736
|
+
"aria-label": placeholder,
|
|
5737
|
+
className: cn(
|
|
5738
|
+
"flex min-w-0 flex-1 items-center bg-transparent text-left",
|
|
5739
|
+
gapCls,
|
|
5740
|
+
disabled ? "cursor-not-allowed" : "cursor-pointer"
|
|
5741
|
+
),
|
|
5742
|
+
children: [
|
|
5743
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5744
|
+
SIcon,
|
|
5745
|
+
{
|
|
5746
|
+
name: "attachFile",
|
|
5747
|
+
size: iconSize,
|
|
5748
|
+
color: disabled ? "var(--cmp-filepicker-icon-disabled)" : "var(--color-grey-65)"
|
|
5749
|
+
}
|
|
5750
|
+
),
|
|
5751
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5752
|
+
"span",
|
|
5753
|
+
{
|
|
5754
|
+
className: cn(
|
|
5755
|
+
"min-w-0 flex-1 truncate text-[12px]",
|
|
5756
|
+
inlinePlaceholder && "text-[color:var(--cmp-filepicker-text-placeholder)] transition-colors group-hover/filepicker:text-[color:var(--cmp-filepicker-text-default)]"
|
|
5757
|
+
),
|
|
5758
|
+
style: inlinePlaceholder ? void 0 : {
|
|
5759
|
+
color: disabled ? "var(--cmp-filepicker-text-disabled)" : hasFiles ? "var(--cmp-filepicker-text-default)" : "var(--cmp-filepicker-text-placeholder)"
|
|
5760
|
+
},
|
|
5761
|
+
children: displayText
|
|
5762
|
+
}
|
|
5763
|
+
)
|
|
5764
|
+
]
|
|
5765
|
+
}
|
|
5766
|
+
),
|
|
5767
|
+
!disabled && hasFiles && /* @__PURE__ */ jsxRuntime.jsx(SGhostButton, { icon: "close", size: "xxs", ariaLabel: "clear", onClick: clear })
|
|
5768
|
+
]
|
|
5769
|
+
}
|
|
5770
|
+
);
|
|
5771
|
+
const chips = multiple && files.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5772
|
+
"div",
|
|
5773
|
+
{
|
|
5774
|
+
className: cn(
|
|
5775
|
+
"mt-[8px] flex gap-[8px]",
|
|
5776
|
+
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"
|
|
5632
5777
|
),
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5778
|
+
style: useMultipleListBox ? {
|
|
5779
|
+
width: typeof width === "number" ? `${width}px` : width,
|
|
5780
|
+
// label 이 있으면 SField 입력 박스 시작 위치(labelWidth + fieldGap)에 맞춰 정렬
|
|
5781
|
+
marginLeft: label && labelWidth != null ? `calc(${typeof labelWidth === "number" ? `${labelWidth}px` : labelWidth} + var(--sys-space-field-${size}-gap))` : void 0
|
|
5782
|
+
} : void 0,
|
|
5783
|
+
children: files.map((f, i) => /* @__PURE__ */ jsxRuntime.jsx(SChip, { value: f.name, editable: false, onRemove: () => removeChip(i) }, i))
|
|
5784
|
+
}
|
|
5785
|
+
);
|
|
5636
5786
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style, children: [
|
|
5637
5787
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5638
5788
|
SField,
|
|
5639
5789
|
{
|
|
5790
|
+
borderless: inline,
|
|
5640
5791
|
label,
|
|
5641
5792
|
labelWidth,
|
|
5642
5793
|
icon,
|
|
@@ -5664,6 +5815,7 @@ function SKeyValueTable({
|
|
|
5664
5815
|
fields = [],
|
|
5665
5816
|
search = false,
|
|
5666
5817
|
radius = "default",
|
|
5818
|
+
dense = false,
|
|
5667
5819
|
onChange,
|
|
5668
5820
|
onSearch,
|
|
5669
5821
|
className,
|
|
@@ -5671,6 +5823,8 @@ function SKeyValueTable({
|
|
|
5671
5823
|
}) {
|
|
5672
5824
|
if (fields.length === 0) return null;
|
|
5673
5825
|
const emit = (name, value) => onChange?.({ name, value });
|
|
5826
|
+
const cellHeight = dense ? "var(--cmp-table-body-dense-height)" : "var(--cmp-table-keyValue-height)";
|
|
5827
|
+
const cellPadY = dense ? "var(--cmp-table-body-dense-paddingY)" : "var(--cmp-table-keyValue-body-paddingY)";
|
|
5674
5828
|
const renderField = (f) => {
|
|
5675
5829
|
if (f.render) return f.render;
|
|
5676
5830
|
const opt = f.options ?? {};
|
|
@@ -5751,10 +5905,15 @@ function SKeyValueTable({
|
|
|
5751
5905
|
rowSpan: f.thRowSpan && f.thRowSpan > 1 ? f.thRowSpan : void 0,
|
|
5752
5906
|
colSpan: f.thColSpan && f.thColSpan > 1 ? f.thColSpan : void 0,
|
|
5753
5907
|
className: cn(
|
|
5754
|
-
"
|
|
5908
|
+
"box-border bg-[var(--cmp-table-header-bg)] px-[var(--cmp-table-header-paddingX)] text-left align-middle",
|
|
5755
5909
|
cellBorder,
|
|
5756
5910
|
f.thClass
|
|
5757
5911
|
),
|
|
5912
|
+
style: {
|
|
5913
|
+
height: cellHeight,
|
|
5914
|
+
paddingTop: cellPadY,
|
|
5915
|
+
paddingBottom: cellPadY
|
|
5916
|
+
},
|
|
5758
5917
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full w-full items-center justify-between gap-[var(--cmp-table-header-gap)]", children: [
|
|
5759
5918
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-[8px]", children: [
|
|
5760
5919
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[12px] font-bold leading-[20px] text-[color:var(--sys-color-fg-primary)]", children: f.label }),
|
|
@@ -5780,10 +5939,11 @@ function SKeyValueTable({
|
|
|
5780
5939
|
rowSpan: f.tdRowSpan && f.tdRowSpan > 1 ? f.tdRowSpan : void 0,
|
|
5781
5940
|
colSpan: f.tdColSpan && f.tdColSpan > 1 ? f.tdColSpan : void 0,
|
|
5782
5941
|
className: cn(
|
|
5783
|
-
"
|
|
5942
|
+
"box-border bg-[var(--sys-color-bg-frame)] px-[var(--cmp-table-keyValue-body-paddingX-default)] align-middle",
|
|
5784
5943
|
cellBorder,
|
|
5785
5944
|
f.tdClass
|
|
5786
5945
|
),
|
|
5946
|
+
style: { height: cellHeight, paddingTop: cellPadY, paddingBottom: cellPadY },
|
|
5787
5947
|
children: renderField(f)
|
|
5788
5948
|
},
|
|
5789
5949
|
`td-${r}-${c}`
|