sellmate-design-system-react 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/SActionModal/SActionModal.cjs +11 -3
- package/dist/components/SActionModal/SActionModal.cjs.map +1 -1
- package/dist/components/SActionModal/SActionModal.js +11 -3
- package/dist/components/SActionModal/SActionModal.js.map +1 -1
- package/dist/components/SBarcodeInput/SBarcodeInput.cjs +226 -209
- package/dist/components/SBarcodeInput/SBarcodeInput.cjs.map +1 -1
- package/dist/components/SBarcodeInput/SBarcodeInput.js +226 -209
- package/dist/components/SBarcodeInput/SBarcodeInput.js.map +1 -1
- package/dist/components/SCalendar/SCalendar.cjs +9 -1
- package/dist/components/SCalendar/SCalendar.cjs.map +1 -1
- package/dist/components/SCalendar/SCalendar.js +9 -1
- package/dist/components/SCalendar/SCalendar.js.map +1 -1
- package/dist/components/SChip/SChip.cjs +9 -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 +9 -1
- package/dist/components/SChip/SChip.js.map +1 -1
- package/dist/components/SChipInput/SChipInput.cjs +260 -235
- package/dist/components/SChipInput/SChipInput.cjs.map +1 -1
- package/dist/components/SChipInput/SChipInput.js +259 -235
- package/dist/components/SChipInput/SChipInput.js.map +1 -1
- package/dist/components/SCircleProgress/SCircleProgress.cjs +56 -58
- package/dist/components/SCircleProgress/SCircleProgress.cjs.map +1 -1
- package/dist/components/SCircleProgress/SCircleProgress.js +56 -58
- package/dist/components/SCircleProgress/SCircleProgress.js.map +1 -1
- package/dist/components/SConfirmModal/SConfirmModal.cjs +9 -1
- package/dist/components/SConfirmModal/SConfirmModal.cjs.map +1 -1
- package/dist/components/SConfirmModal/SConfirmModal.js +9 -1
- package/dist/components/SConfirmModal/SConfirmModal.js.map +1 -1
- package/dist/components/SDatePicker/SDatePicker.cjs +247 -221
- package/dist/components/SDatePicker/SDatePicker.cjs.map +1 -1
- package/dist/components/SDatePicker/SDatePicker.js +247 -221
- package/dist/components/SDatePicker/SDatePicker.js.map +1 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.cjs +308 -256
- package/dist/components/SDateRangePicker/SDateRangePicker.cjs.map +1 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.js +308 -256
- package/dist/components/SDateRangePicker/SDateRangePicker.js.map +1 -1
- package/dist/components/SDropdownButton/SDropdownButton.cjs +51 -4
- package/dist/components/SDropdownButton/SDropdownButton.cjs.map +1 -1
- package/dist/components/SDropdownButton/SDropdownButton.js +52 -5
- package/dist/components/SDropdownButton/SDropdownButton.js.map +1 -1
- package/dist/components/SField/SField.cjs +226 -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 +226 -21
- package/dist/components/SField/SField.js.map +1 -1
- package/dist/components/SFilePicker/SFilePicker.cjs +306 -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 +306 -278
- package/dist/components/SFilePicker/SFilePicker.js.map +1 -1
- package/dist/components/SGhostButton/SGhostButton.cjs +8 -0
- package/dist/components/SGhostButton/SGhostButton.cjs.map +1 -1
- package/dist/components/SGhostButton/SGhostButton.js +8 -0
- package/dist/components/SGhostButton/SGhostButton.js.map +1 -1
- package/dist/components/SGuide/SGuide.cjs +12 -1
- package/dist/components/SGuide/SGuide.cjs.map +1 -1
- package/dist/components/SGuide/SGuide.js +12 -1
- package/dist/components/SGuide/SGuide.js.map +1 -1
- package/dist/components/SInput/SInput.cjs +226 -209
- package/dist/components/SInput/SInput.cjs.map +1 -1
- package/dist/components/SInput/SInput.js +226 -209
- package/dist/components/SInput/SInput.js.map +1 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.cjs +640 -453
- package/dist/components/SKeyValueTable/SKeyValueTable.cjs.map +1 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.d.ts +3 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.js +640 -453
- package/dist/components/SKeyValueTable/SKeyValueTable.js.map +1 -1
- package/dist/components/SLoadingContainer/SLoadingContainer.cjs +64 -58
- package/dist/components/SLoadingContainer/SLoadingContainer.cjs.map +1 -1
- package/dist/components/SLoadingContainer/SLoadingContainer.js +64 -58
- package/dist/components/SLoadingContainer/SLoadingContainer.js.map +1 -1
- package/dist/components/SLoadingContainer/loading.cjs +64 -58
- package/dist/components/SLoadingContainer/loading.cjs.map +1 -1
- package/dist/components/SLoadingContainer/loading.js +64 -58
- package/dist/components/SLoadingContainer/loading.js.map +1 -1
- package/dist/components/SLoadingModal/SLoadingModal.cjs +68 -61
- package/dist/components/SLoadingModal/SLoadingModal.cjs.map +1 -1
- package/dist/components/SLoadingModal/SLoadingModal.js +68 -61
- package/dist/components/SLoadingModal/SLoadingModal.js.map +1 -1
- package/dist/components/SModalContainer/SModalContainer.cjs +9 -1
- package/dist/components/SModalContainer/SModalContainer.cjs.map +1 -1
- package/dist/components/SModalContainer/SModalContainer.js +9 -1
- package/dist/components/SModalContainer/SModalContainer.js.map +1 -1
- package/dist/components/SNumberInput/SNumberInput.cjs +334 -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 +334 -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/SPopover/SPopover.cjs +20 -3
- package/dist/components/SPopover/SPopover.cjs.map +1 -1
- package/dist/components/SPopover/SPopover.js +20 -4
- package/dist/components/SPopover/SPopover.js.map +1 -1
- package/dist/components/SPopup/SPopup.cjs +2 -2
- package/dist/components/SPopup/SPopup.cjs.map +1 -1
- package/dist/components/SPopup/SPopup.js +2 -2
- package/dist/components/SPopup/SPopup.js.map +1 -1
- package/dist/components/SPortal/SPortal.cjs +8 -0
- package/dist/components/SPortal/SPortal.cjs.map +1 -1
- package/dist/components/SPortal/SPortal.js +8 -0
- package/dist/components/SPortal/SPortal.js.map +1 -1
- package/dist/components/SSelect/SSelect.cjs +76 -32
- package/dist/components/SSelect/SSelect.cjs.map +1 -1
- package/dist/components/SSelect/SSelect.js +76 -32
- package/dist/components/SSelect/SSelect.js.map +1 -1
- package/dist/components/STable/STable.cjs +133 -91
- package/dist/components/STable/STable.cjs.map +1 -1
- package/dist/components/STable/STable.js +133 -91
- package/dist/components/STable/STable.js.map +1 -1
- package/dist/components/STextLink/STextLink.cjs +137 -3
- package/dist/components/STextLink/STextLink.cjs.map +1 -1
- package/dist/components/STextLink/STextLink.d.ts +1 -1
- package/dist/components/STextLink/STextLink.js +118 -4
- package/dist/components/STextLink/STextLink.js.map +1 -1
- package/dist/components/STextarea/STextarea.cjs +226 -21
- package/dist/components/STextarea/STextarea.cjs.map +1 -1
- package/dist/components/STextarea/STextarea.js +226 -21
- package/dist/components/STextarea/STextarea.js.map +1 -1
- package/dist/components/SToast/SToast.cjs +8 -0
- package/dist/components/SToast/SToast.cjs.map +1 -1
- package/dist/components/SToast/SToast.js +8 -0
- package/dist/components/SToast/SToast.js.map +1 -1
- package/dist/components/SToast/SToastContainer.cjs +11 -3
- package/dist/components/SToast/SToastContainer.cjs.map +1 -1
- package/dist/components/SToast/SToastContainer.js +11 -3
- package/dist/components/SToast/SToastContainer.js.map +1 -1
- package/dist/components/STooltip/STooltip.cjs +217 -14
- package/dist/components/STooltip/STooltip.cjs.map +1 -1
- package/dist/components/STooltip/STooltip.js +217 -14
- package/dist/components/STooltip/STooltip.js.map +1 -1
- package/dist/index.cjs +532 -300
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +531 -300
- package/dist/index.js.map +1 -1
- package/dist/lib/floating-anim.cjs +8 -0
- package/dist/lib/floating-anim.cjs.map +1 -1
- package/dist/lib/floating-anim.d.ts +5 -1
- package/dist/lib/floating-anim.js +8 -0
- package/dist/lib/floating-anim.js.map +1 -1
- package/dist/styles.css +175 -66
- package/dist/theme.css +49 -22
- 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
|
|
|
@@ -2880,12 +2880,20 @@ var SIcon = react.forwardRef(function SIcon2({ name, size = 24, color, rotate, l
|
|
|
2880
2880
|
// src/lib/floating-anim.ts
|
|
2881
2881
|
var FLOATING_SLIDE_ANIM = [
|
|
2882
2882
|
"data-[state=open]:data-[side=top]:animate-floating-in-top",
|
|
2883
|
+
"data-[state=delayed-open]:data-[side=top]:animate-floating-in-top",
|
|
2884
|
+
"data-[state=instant-open]:data-[side=top]:animate-floating-in-top",
|
|
2883
2885
|
"data-[state=closed]:data-[side=top]:animate-floating-out-top",
|
|
2884
2886
|
"data-[state=open]:data-[side=bottom]:animate-floating-in-bottom",
|
|
2887
|
+
"data-[state=delayed-open]:data-[side=bottom]:animate-floating-in-bottom",
|
|
2888
|
+
"data-[state=instant-open]:data-[side=bottom]:animate-floating-in-bottom",
|
|
2885
2889
|
"data-[state=closed]:data-[side=bottom]:animate-floating-out-bottom",
|
|
2886
2890
|
"data-[state=open]:data-[side=left]:animate-floating-in-left",
|
|
2891
|
+
"data-[state=delayed-open]:data-[side=left]:animate-floating-in-left",
|
|
2892
|
+
"data-[state=instant-open]:data-[side=left]:animate-floating-in-left",
|
|
2887
2893
|
"data-[state=closed]:data-[side=left]:animate-floating-out-left",
|
|
2888
2894
|
"data-[state=open]:data-[side=right]:animate-floating-in-right",
|
|
2895
|
+
"data-[state=delayed-open]:data-[side=right]:animate-floating-in-right",
|
|
2896
|
+
"data-[state=instant-open]:data-[side=right]:animate-floating-in-right",
|
|
2889
2897
|
"data-[state=closed]:data-[side=right]:animate-floating-out-right"
|
|
2890
2898
|
].join(" ");
|
|
2891
2899
|
var PortalContainerContext = react.createContext(null);
|
|
@@ -2893,11 +2901,200 @@ PortalContainerContext.Provider;
|
|
|
2893
2901
|
function usePortalContainer() {
|
|
2894
2902
|
return react.useContext(PortalContainerContext) ?? void 0;
|
|
2895
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
|
+
}
|
|
2896
3092
|
var HIDE_DELAY_MS = 100;
|
|
2897
3093
|
function useBody(content, message = []) {
|
|
2898
3094
|
if (content != null) return content;
|
|
2899
3095
|
if (message.length === 0) return null;
|
|
2900
|
-
|
|
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)) });
|
|
2901
3098
|
}
|
|
2902
3099
|
var STooltip = react.forwardRef(function STooltip2({
|
|
2903
3100
|
content,
|
|
@@ -2955,7 +3152,7 @@ var STooltip = react.forwardRef(function STooltip2({
|
|
|
2955
3152
|
if (disabled || body == null) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: triggerNode });
|
|
2956
3153
|
const isHover = trigger === "hover";
|
|
2957
3154
|
const contentClass = cn(
|
|
2958
|
-
"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)]",
|
|
2959
3156
|
FLOATING_SLIDE_ANIM,
|
|
2960
3157
|
className
|
|
2961
3158
|
);
|
|
@@ -2965,10 +3162,10 @@ var STooltip = react.forwardRef(function STooltip2({
|
|
|
2965
3162
|
fontWeight: tooltipType === "default" ? 500 : 700,
|
|
2966
3163
|
...style
|
|
2967
3164
|
};
|
|
2968
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3165
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(RPopover2__namespace.Root, { open, onOpenChange: setOpen, children: [
|
|
2969
3166
|
isHover ? (
|
|
2970
3167
|
// hover: Anchor(위치 기준) + 직접 mouse 핸들러 — 클릭으로 토글되지 않도록 Trigger 미사용
|
|
2971
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3168
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2972
3169
|
"span",
|
|
2973
3170
|
{
|
|
2974
3171
|
className: "inline-flex",
|
|
@@ -2979,9 +3176,9 @@ var STooltip = react.forwardRef(function STooltip2({
|
|
|
2979
3176
|
children: triggerNode
|
|
2980
3177
|
}
|
|
2981
3178
|
) })
|
|
2982
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2983
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2984
|
-
|
|
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,
|
|
2985
3182
|
{
|
|
2986
3183
|
side: placement,
|
|
2987
3184
|
sideOffset: 8,
|
|
@@ -3000,15 +3197,21 @@ var STooltip = react.forwardRef(function STooltip2({
|
|
|
3000
3197
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-[12px]", children: [
|
|
3001
3198
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: body }),
|
|
3002
3199
|
useClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3003
|
-
|
|
3200
|
+
SGhostButton,
|
|
3004
3201
|
{
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
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
|
+
}
|
|
3008
3211
|
}
|
|
3009
3212
|
)
|
|
3010
3213
|
] }),
|
|
3011
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3214
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
3012
3215
|
]
|
|
3013
3216
|
}
|
|
3014
3217
|
) })
|
|
@@ -3208,8 +3411,8 @@ function useFormField(field) {
|
|
|
3208
3411
|
}, [ctx, name]);
|
|
3209
3412
|
}
|
|
3210
3413
|
var FIELD_SIZE = {
|
|
3211
|
-
sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon:
|
|
3212
|
-
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 }
|
|
3213
3416
|
};
|
|
3214
3417
|
var ALIGN = {
|
|
3215
3418
|
start: "flex-start",
|
|
@@ -3224,6 +3427,7 @@ var SField = react.forwardRef(function SField2({
|
|
|
3224
3427
|
labelTooltip = "",
|
|
3225
3428
|
labelTooltipProps,
|
|
3226
3429
|
labelWidth,
|
|
3430
|
+
labelHeight,
|
|
3227
3431
|
size = "sm",
|
|
3228
3432
|
addonLabel = "",
|
|
3229
3433
|
addonAlign = "start",
|
|
@@ -3238,6 +3442,7 @@ var SField = react.forwardRef(function SField2({
|
|
|
3238
3442
|
readOnly = false,
|
|
3239
3443
|
width,
|
|
3240
3444
|
multiline = false,
|
|
3445
|
+
borderless = false,
|
|
3241
3446
|
children,
|
|
3242
3447
|
className,
|
|
3243
3448
|
style,
|
|
@@ -3271,8 +3476,8 @@ var SField = react.forwardRef(function SField2({
|
|
|
3271
3476
|
const resolvedSuccess = status === "pass";
|
|
3272
3477
|
const showError = resolvedError && errorMessage !== "";
|
|
3273
3478
|
const interactive = !disabled && !readOnly;
|
|
3274
|
-
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)";
|
|
3275
|
-
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)";
|
|
3276
3481
|
const textColor = disabled ? "var(--color-grey-65)" : readOnly ? "var(--sys-color-field-text-readOnly)" : "var(--sys-color-field-text-default)";
|
|
3277
3482
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3278
3483
|
"div",
|
|
@@ -3288,267 +3493,79 @@ var SField = react.forwardRef(function SField2({
|
|
|
3288
3493
|
"div",
|
|
3289
3494
|
{
|
|
3290
3495
|
className: "flex shrink-0 items-center font-bold text-(--sys-color-field-text-default)",
|
|
3291
|
-
style: {
|
|
3292
|
-
height: s.height,
|
|
3293
|
-
marginRight: s.fieldGap,
|
|
3294
|
-
width: cssLen(labelWidth),
|
|
3295
|
-
fontSize: s.fontSize,
|
|
3296
|
-
lineHeight: `${s.lineHeight}px`
|
|
3297
|
-
},
|
|
3298
|
-
children: [
|
|
3299
|
-
icon && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.icon, style: { marginRight: s.labelGap } }),
|
|
3300
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis whitespace-nowrap", children: label }),
|
|
3301
|
-
(labelTooltip !== "" || labelTooltipProps) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", style: { marginLeft: s.labelGap }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3302
|
-
STooltip,
|
|
3303
|
-
{
|
|
3304
|
-
message: labelTooltip !== "" ? [labelTooltip] : void 0,
|
|
3305
|
-
iconSize: s.icon,
|
|
3306
|
-
...labelTooltipProps
|
|
3307
|
-
}
|
|
3308
|
-
) })
|
|
3309
|
-
]
|
|
3310
|
-
}
|
|
3311
|
-
),
|
|
3312
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
3313
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3314
|
-
"div",
|
|
3315
|
-
{
|
|
3316
|
-
className: cn(
|
|
3317
|
-
"relative box-border flex min-w-0 items-stretch overflow-hidden border border-solid border-(--field-bc)",
|
|
3318
|
-
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]",
|
|
3319
|
-
disabled && "cursor-not-allowed"
|
|
3320
|
-
),
|
|
3321
|
-
style: {
|
|
3322
|
-
// @ts-expect-error CSS 변수
|
|
3323
|
-
"--field-bc": borderColor,
|
|
3324
|
-
// focused/hovered prop이 명시된 경우 강조를 즉시 반영
|
|
3325
|
-
...interactive && focused ? { boxShadow: "0px 0px 4px 0px #0071ff66" } : {},
|
|
3326
|
-
...multiline ? { minHeight: s.height } : { height: s.height },
|
|
3327
|
-
"width": cssLen(width),
|
|
3328
|
-
"borderRadius": s.radius,
|
|
3329
|
-
"background": bgColor,
|
|
3330
|
-
"color": textColor
|
|
3331
|
-
},
|
|
3332
|
-
"data-focused": focused || void 0,
|
|
3333
|
-
"data-hovered": hovered || void 0,
|
|
3334
|
-
children: [
|
|
3335
|
-
effectiveAddonLabel !== "" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3336
|
-
"div",
|
|
3337
|
-
{
|
|
3338
|
-
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",
|
|
3339
|
-
style: {
|
|
3340
|
-
// 원본 sd-field: labelWidth가 addon 폭(--sd-field-addon-width)에도 적용됨
|
|
3341
|
-
width: cssLen(labelWidth),
|
|
3342
|
-
justifyContent: ALIGN[addonAlign],
|
|
3343
|
-
background: "var(--cmp-field-addonLabel-bg)",
|
|
3344
|
-
borderRightColor: disabled ? "var(--cmp-field-addonLabel-border-disabled)" : "var(--cmp-field-addonLabel-border-default)",
|
|
3345
|
-
borderTopLeftRadius: s.radius - 1,
|
|
3346
|
-
borderBottomLeftRadius: s.radius - 1
|
|
3347
|
-
},
|
|
3348
|
-
children: [
|
|
3349
|
-
icon && !label && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.icon }),
|
|
3350
|
-
effectiveAddonLabel
|
|
3351
|
-
]
|
|
3352
|
-
}
|
|
3353
|
-
),
|
|
3354
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 flex-1", children })
|
|
3355
|
-
]
|
|
3356
|
-
}
|
|
3357
|
-
),
|
|
3358
|
-
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
|
|
3359
|
-
] })
|
|
3360
|
-
] })
|
|
3361
|
-
}
|
|
3362
|
-
);
|
|
3363
|
-
});
|
|
3364
|
-
|
|
3365
|
-
// src/components/STag/tag.config.ts
|
|
3366
|
-
var TAG_SIZE_CONFIG = {
|
|
3367
|
-
xs: {
|
|
3368
|
-
height: 20,
|
|
3369
|
-
paddingX: 8,
|
|
3370
|
-
gap: 4,
|
|
3371
|
-
radius: 6,
|
|
3372
|
-
iconSize: 12,
|
|
3373
|
-
fontSize: 11,
|
|
3374
|
-
fontWeight: 500,
|
|
3375
|
-
lineHeight: 18
|
|
3376
|
-
},
|
|
3377
|
-
sm: {
|
|
3378
|
-
height: 24,
|
|
3379
|
-
paddingX: 8,
|
|
3380
|
-
gap: 4,
|
|
3381
|
-
radius: 6,
|
|
3382
|
-
iconSize: 16,
|
|
3383
|
-
fontSize: 12,
|
|
3384
|
-
fontWeight: 700,
|
|
3385
|
-
lineHeight: 20
|
|
3386
|
-
},
|
|
3387
|
-
md: {
|
|
3388
|
-
height: 28,
|
|
3389
|
-
paddingX: 12,
|
|
3390
|
-
gap: 6,
|
|
3391
|
-
radius: 8,
|
|
3392
|
-
iconSize: 16,
|
|
3393
|
-
fontSize: 14,
|
|
3394
|
-
fontWeight: 700,
|
|
3395
|
-
lineHeight: 24
|
|
3396
|
-
}
|
|
3397
|
-
};
|
|
3398
|
-
var STag = react.forwardRef(function STag2({
|
|
3399
|
-
shape = "square",
|
|
3400
|
-
size = "sm",
|
|
3401
|
-
color = "grey",
|
|
3402
|
-
label = "",
|
|
3403
|
-
icon,
|
|
3404
|
-
iconLeft = true,
|
|
3405
|
-
width,
|
|
3406
|
-
className,
|
|
3407
|
-
style,
|
|
3408
|
-
...rest
|
|
3409
|
-
}, ref) {
|
|
3410
|
-
const s = TAG_SIZE_CONFIG[size];
|
|
3411
|
-
const contentColor = `var(--cmp-tag-${color}-content)`;
|
|
3412
|
-
const iconNode = icon ? /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.iconSize, color: contentColor }) : null;
|
|
3413
|
-
const resolvedWidth = typeof width === "number" ? `${width}px` : width;
|
|
3414
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3415
|
-
"span",
|
|
3416
|
-
{
|
|
3417
|
-
ref,
|
|
3418
|
-
"aria-label": label || "tag",
|
|
3419
|
-
className: cn(
|
|
3420
|
-
"box-border inline-flex w-fit select-none items-center justify-center whitespace-nowrap",
|
|
3421
|
-
className
|
|
3422
|
-
),
|
|
3423
|
-
style: {
|
|
3424
|
-
minHeight: s.height,
|
|
3425
|
-
padding: `0 ${s.paddingX}px`,
|
|
3426
|
-
gap: s.gap,
|
|
3427
|
-
borderRadius: shape === "pill" ? 999 : s.radius,
|
|
3428
|
-
fontSize: s.fontSize,
|
|
3429
|
-
fontWeight: s.fontWeight,
|
|
3430
|
-
lineHeight: `${s.lineHeight}px`,
|
|
3431
|
-
background: `var(--cmp-tag-${color}-bg)`,
|
|
3432
|
-
color: contentColor,
|
|
3433
|
-
...resolvedWidth != null ? { width: resolvedWidth } : {},
|
|
3434
|
-
...style
|
|
3435
|
-
},
|
|
3436
|
-
...rest,
|
|
3437
|
-
children: [
|
|
3438
|
-
icon && iconLeft && iconNode,
|
|
3439
|
-
label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex min-w-0 items-center justify-center", children: label }),
|
|
3440
|
-
icon && !iconLeft && iconNode
|
|
3441
|
-
]
|
|
3442
|
-
}
|
|
3443
|
-
);
|
|
3444
|
-
});
|
|
3445
|
-
var SIZE = {
|
|
3446
|
-
xxs: { icon: 12, radius: "sm" },
|
|
3447
|
-
xs: { icon: 16, radius: "sm" },
|
|
3448
|
-
sm: { icon: 20, radius: "sm" },
|
|
3449
|
-
md: { icon: 24, radius: "md" },
|
|
3450
|
-
lg: { icon: 32, radius: "md" }
|
|
3451
|
-
};
|
|
3452
|
-
var TOOLTIP_HIDE_DELAY_MS = 100;
|
|
3453
|
-
function SGhostButton({
|
|
3454
|
-
icon,
|
|
3455
|
-
size = "sm",
|
|
3456
|
-
intent = "default",
|
|
3457
|
-
ariaLabel = "",
|
|
3458
|
-
tooltipText,
|
|
3459
|
-
disabled = false,
|
|
3460
|
-
onClick,
|
|
3461
|
-
className,
|
|
3462
|
-
style
|
|
3463
|
-
}) {
|
|
3464
|
-
const portalContainer = usePortalContainer();
|
|
3465
|
-
const [open, setOpen] = react.useState(false);
|
|
3466
|
-
const hideTimer = react.useRef(void 0);
|
|
3467
|
-
const cancelHide = () => {
|
|
3468
|
-
if (hideTimer.current) {
|
|
3469
|
-
clearTimeout(hideTimer.current);
|
|
3470
|
-
hideTimer.current = void 0;
|
|
3471
|
-
}
|
|
3472
|
-
};
|
|
3473
|
-
const openNow = () => {
|
|
3474
|
-
cancelHide();
|
|
3475
|
-
setOpen(true);
|
|
3476
|
-
};
|
|
3477
|
-
const startHide = () => {
|
|
3478
|
-
cancelHide();
|
|
3479
|
-
hideTimer.current = setTimeout(() => setOpen(false), TOOLTIP_HIDE_DELAY_MS);
|
|
3480
|
-
};
|
|
3481
|
-
const s = SIZE[size];
|
|
3482
|
-
const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
|
|
3483
|
-
const btn = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3484
|
-
"button",
|
|
3485
|
-
{
|
|
3486
|
-
type: "button",
|
|
3487
|
-
disabled,
|
|
3488
|
-
"aria-disabled": disabled ? "true" : void 0,
|
|
3489
|
-
"aria-label": ariaLabel.trim() || void 0,
|
|
3490
|
-
tabIndex: disabled ? -1 : void 0,
|
|
3491
|
-
onClick: (e) => {
|
|
3492
|
-
if (disabled) {
|
|
3493
|
-
e.preventDefault();
|
|
3494
|
-
return;
|
|
3495
|
-
}
|
|
3496
|
-
onClick?.(e);
|
|
3497
|
-
},
|
|
3498
|
-
className: cn(
|
|
3499
|
-
"group relative box-border inline-flex items-center justify-center border-none bg-transparent p-0 transition-shadow",
|
|
3500
|
-
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
3501
|
-
"focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
|
|
3502
|
-
className
|
|
3503
|
-
),
|
|
3504
|
-
style: {
|
|
3505
|
-
width: `var(--cmp-ghostButton-${size}-size)`,
|
|
3506
|
-
height: `var(--cmp-ghostButton-${size}-size)`,
|
|
3507
|
-
borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
|
|
3508
|
-
...style
|
|
3509
|
-
},
|
|
3510
|
-
children: [
|
|
3511
|
-
!disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3512
|
-
"span",
|
|
3513
|
-
{
|
|
3514
|
-
"aria-hidden": true,
|
|
3515
|
-
className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover:opacity-5",
|
|
3516
|
-
style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
|
|
3496
|
+
style: {
|
|
3497
|
+
height: cssLen(labelHeight) ?? s.height,
|
|
3498
|
+
marginRight: s.fieldGap,
|
|
3499
|
+
width: cssLen(labelWidth),
|
|
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
|
+
]
|
|
3517
3515
|
}
|
|
3518
3516
|
),
|
|
3519
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3520
|
-
|
|
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
|
+
] })
|
|
3521
3566
|
}
|
|
3522
3567
|
);
|
|
3523
|
-
|
|
3524
|
-
if (text === "") return btn;
|
|
3525
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(RPopover__namespace.Root, { open, onOpenChange: setOpen, children: [
|
|
3526
|
-
/* @__PURE__ */ jsxRuntime.jsx(RPopover__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3527
|
-
"span",
|
|
3528
|
-
{
|
|
3529
|
-
className: "inline-flex",
|
|
3530
|
-
onMouseEnter: openNow,
|
|
3531
|
-
onMouseLeave: startHide,
|
|
3532
|
-
onFocus: openNow,
|
|
3533
|
-
onBlur: startHide,
|
|
3534
|
-
children: btn
|
|
3535
|
-
}
|
|
3536
|
-
) }),
|
|
3537
|
-
/* @__PURE__ */ jsxRuntime.jsx(RPopover__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3538
|
-
RPopover__namespace.Content,
|
|
3539
|
-
{
|
|
3540
|
-
side: "top",
|
|
3541
|
-
sideOffset: 4,
|
|
3542
|
-
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
3543
|
-
"aria-hidden": true,
|
|
3544
|
-
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
3545
|
-
onMouseEnter: cancelHide,
|
|
3546
|
-
onMouseLeave: startHide,
|
|
3547
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
|
|
3548
|
-
}
|
|
3549
|
-
) })
|
|
3550
|
-
] });
|
|
3551
|
-
}
|
|
3568
|
+
});
|
|
3552
3569
|
var FONT = {
|
|
3553
3570
|
sm: { fontSize: 12, lineHeight: 20, paddingX: "var(--cmp-textinput-sm-paddingX)" },
|
|
3554
3571
|
md: { fontSize: 14, lineHeight: 24, paddingX: "var(--cmp-textinput-md-paddingX)" }
|
|
@@ -3803,8 +3820,8 @@ var STextarea = react.forwardRef(function STextarea2({
|
|
|
3803
3820
|
);
|
|
3804
3821
|
});
|
|
3805
3822
|
var PAD2 = {
|
|
3806
|
-
sm: { fontSize: 12, stepper: 20, icon: 12 },
|
|
3807
|
-
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 }
|
|
3808
3825
|
};
|
|
3809
3826
|
var toNumber = (val) => {
|
|
3810
3827
|
if (val === null || val === void 0 || val === "") return null;
|
|
@@ -3822,6 +3839,38 @@ var formatWithCommas = (value) => {
|
|
|
3822
3839
|
const result = isNeg ? "-" + formatted : formatted;
|
|
3823
3840
|
return decPart !== void 0 && decPart !== "" ? result + "." + decPart : result;
|
|
3824
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
|
+
};
|
|
3825
3874
|
var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
3826
3875
|
value,
|
|
3827
3876
|
onValueChange,
|
|
@@ -3831,6 +3880,7 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
3831
3880
|
step = 1,
|
|
3832
3881
|
useButton = false,
|
|
3833
3882
|
useDecimal = false,
|
|
3883
|
+
maxDecimalLength,
|
|
3834
3884
|
inputPrefix = "",
|
|
3835
3885
|
inputSuffix = "",
|
|
3836
3886
|
inputClass,
|
|
@@ -3862,7 +3912,8 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
3862
3912
|
}, ref) {
|
|
3863
3913
|
const p = PAD2[size];
|
|
3864
3914
|
const padX = `var(--cmp-numberInput-${size}-paddingX)`;
|
|
3865
|
-
const
|
|
3915
|
+
const decimalLimit = getDecimalLimit(useDecimal, maxDecimalLength);
|
|
3916
|
+
const numValue = applyDecimalLimit(toNumber(value), decimalLimit);
|
|
3866
3917
|
const [display, setDisplay] = react.useState(() => formatWithCommas(numValue));
|
|
3867
3918
|
const [ruleError, setRuleError] = react.useState("");
|
|
3868
3919
|
const innerRef = react.useRef(null);
|
|
@@ -3872,8 +3923,9 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
3872
3923
|
else if (ref) ref.current = el;
|
|
3873
3924
|
};
|
|
3874
3925
|
react.useEffect(() => {
|
|
3875
|
-
|
|
3876
|
-
|
|
3926
|
+
if (document.activeElement === innerRef.current) return;
|
|
3927
|
+
setDisplay(formatWithCommas(applyDecimalLimit(toNumber(value), decimalLimit)));
|
|
3928
|
+
}, [decimalLimit, value]);
|
|
3877
3929
|
useFormField({
|
|
3878
3930
|
name,
|
|
3879
3931
|
validate: () => {
|
|
@@ -3885,48 +3937,87 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
3885
3937
|
});
|
|
3886
3938
|
const resolvedError = error || ruleError !== "";
|
|
3887
3939
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
3888
|
-
const
|
|
3889
|
-
|
|
3890
|
-
|
|
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);
|
|
3891
3962
|
};
|
|
3892
3963
|
const incDisabled = disabled || readOnly || numValue !== null && numValue >= max;
|
|
3893
3964
|
const decDisabled = disabled || readOnly || numValue !== null && numValue <= min;
|
|
3894
3965
|
const increment = () => {
|
|
3895
3966
|
if (incDisabled) return;
|
|
3896
3967
|
const cur = numValue ?? (min === Number.NEGATIVE_INFINITY ? 0 : min);
|
|
3897
|
-
const next = Math.min(cur + step, max);
|
|
3968
|
+
const next = applyDecimalLimit(Math.min(cur + step, max), decimalLimit);
|
|
3898
3969
|
if (next !== cur) emit(next);
|
|
3899
3970
|
};
|
|
3900
3971
|
const decrement = () => {
|
|
3901
3972
|
if (decDisabled) return;
|
|
3902
3973
|
const cur = numValue ?? (min === Number.NEGATIVE_INFINITY ? 0 : min);
|
|
3903
|
-
const next = Math.max(cur - step, min);
|
|
3974
|
+
const next = applyDecimalLimit(Math.max(cur - step, min), decimalLimit);
|
|
3904
3975
|
if (next !== cur) emit(next);
|
|
3905
3976
|
};
|
|
3906
|
-
const handleInput = (
|
|
3977
|
+
const handleInput = (event) => {
|
|
3978
|
+
const target = event.currentTarget;
|
|
3979
|
+
const raw = target.value;
|
|
3980
|
+
const logicalCaret = getLogicalCaret(raw, target.selectionStart);
|
|
3907
3981
|
if (raw === "") {
|
|
3908
|
-
|
|
3982
|
+
setDisplayWithCaret("", 0);
|
|
3909
3983
|
onValueChange?.(null);
|
|
3910
3984
|
return;
|
|
3911
3985
|
}
|
|
3912
3986
|
const cleaned = raw.replace(/,/g, "");
|
|
3913
3987
|
const decimals = (cleaned.match(/\./g) || []).length;
|
|
3914
|
-
if (decimals > 1)
|
|
3988
|
+
if (decimals > 1) {
|
|
3989
|
+
resetRejectedInput(target, logicalCaret);
|
|
3990
|
+
return;
|
|
3991
|
+
}
|
|
3915
3992
|
if (cleaned === "-" || cleaned === "." || cleaned === "-.") {
|
|
3916
|
-
|
|
3993
|
+
setDisplayWithCaret(cleaned, logicalCaret);
|
|
3917
3994
|
return;
|
|
3918
3995
|
}
|
|
3919
|
-
if (!useDecimal && cleaned.includes("."))
|
|
3996
|
+
if (!useDecimal && cleaned.includes(".")) {
|
|
3997
|
+
resetRejectedInput(target, logicalCaret);
|
|
3998
|
+
return;
|
|
3999
|
+
}
|
|
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
|
+
}
|
|
3920
4007
|
if (cleaned.endsWith(".") && decimals === 1) {
|
|
3921
4008
|
const parsed2 = toNumber(cleaned.slice(0, -1));
|
|
3922
4009
|
if (parsed2 !== null) {
|
|
3923
|
-
|
|
4010
|
+
setDisplayWithCaret(formatInputWithCommas(cleaned), logicalCaret);
|
|
3924
4011
|
return;
|
|
3925
4012
|
}
|
|
3926
4013
|
}
|
|
3927
4014
|
const parsed = toNumber(cleaned);
|
|
3928
|
-
if (parsed === null)
|
|
3929
|
-
|
|
4015
|
+
if (parsed === null) {
|
|
4016
|
+
resetRejectedInput(target, logicalCaret);
|
|
4017
|
+
return;
|
|
4018
|
+
}
|
|
4019
|
+
setDisplayWithCaret(formatInputWithCommas(cleaned), logicalCaret);
|
|
4020
|
+
onValueChange?.(applyDecimalLimit(parsed, decimalLimit));
|
|
3930
4021
|
};
|
|
3931
4022
|
const stepper = (dir) => {
|
|
3932
4023
|
const off = dir === "inc" ? incDisabled : decDisabled;
|
|
@@ -3939,8 +4030,8 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
3939
4030
|
"aria-label": dir === "inc" ? "\uC99D\uAC00" : "\uAC10\uC18C",
|
|
3940
4031
|
onClick: dir === "inc" ? increment : decrement,
|
|
3941
4032
|
className: cn(
|
|
3942
|
-
"flex flex-shrink-0 items-center justify-center",
|
|
3943
|
-
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)]"
|
|
3944
4035
|
),
|
|
3945
4036
|
style: {
|
|
3946
4037
|
width: `var(--cmp-numberInput-stepper-${size}-size)`,
|
|
@@ -3989,24 +4080,26 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
3989
4080
|
style: {
|
|
3990
4081
|
// 원본 sd-number-input: content gap = padding-x 토큰 (gap 토큰 아님)
|
|
3991
4082
|
gap: `var(--cmp-numberInput-${size}-paddingX)`,
|
|
3992
|
-
padding: `0 ${useButton ? padX : `calc(${padX} * 2)`}
|
|
4083
|
+
padding: `0 ${useButton ? padX : `calc(${padX} * 2)`}`,
|
|
4084
|
+
fontSize: p.fontSize,
|
|
4085
|
+
lineHeight: `${p.lineHeight}px`
|
|
3993
4086
|
},
|
|
3994
4087
|
children: [
|
|
3995
4088
|
useButton && stepper("dec"),
|
|
3996
|
-
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 }),
|
|
3997
4090
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3998
4091
|
"input",
|
|
3999
4092
|
{
|
|
4000
4093
|
ref: setRefs,
|
|
4001
4094
|
name,
|
|
4002
4095
|
type: "text",
|
|
4003
|
-
inputMode: "numeric",
|
|
4096
|
+
inputMode: useDecimal ? "decimal" : "numeric",
|
|
4004
4097
|
value: display,
|
|
4005
4098
|
placeholder,
|
|
4006
4099
|
disabled,
|
|
4007
4100
|
readOnly,
|
|
4008
4101
|
autoFocus,
|
|
4009
|
-
onChange:
|
|
4102
|
+
onChange: handleInput,
|
|
4010
4103
|
onKeyDown: (e) => {
|
|
4011
4104
|
if (e.key === "ArrowUp") {
|
|
4012
4105
|
e.preventDefault();
|
|
@@ -4018,26 +4111,29 @@ var SNumberInput = react.forwardRef(function SNumberInput2({
|
|
|
4018
4111
|
},
|
|
4019
4112
|
onFocus: (e) => onFocus?.(e),
|
|
4020
4113
|
onBlur: (e) => {
|
|
4021
|
-
const
|
|
4114
|
+
const cleaned = display.replace(/,/g, "");
|
|
4115
|
+
const n = toNumber(cleaned);
|
|
4022
4116
|
const clamped = n === null ? null : Math.min(Math.max(n, min), max);
|
|
4023
4117
|
if (clamped !== n) emit(clamped);
|
|
4024
|
-
else setDisplay(
|
|
4118
|
+
else setDisplay(n === null ? "" : formatInputWithCommas(cleaned));
|
|
4025
4119
|
if (rules && rules.length > 0) setRuleError(runRules(clamped, rules));
|
|
4026
4120
|
onBlur?.(e);
|
|
4027
4121
|
},
|
|
4028
4122
|
className: cn(
|
|
4029
|
-
|
|
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",
|
|
4030
4126
|
inputClass
|
|
4031
4127
|
),
|
|
4032
4128
|
style: {
|
|
4033
|
-
fontSize
|
|
4129
|
+
// fontSize/lineHeight 는 컨테이너에서 상속
|
|
4034
4130
|
textAlign: useButton ? "center" : "right",
|
|
4035
4131
|
color: disabled ? "var(--cmp-numberInput-text-disabled)" : "var(--cmp-numberInput-text-default)",
|
|
4036
4132
|
...inputStyle
|
|
4037
4133
|
}
|
|
4038
4134
|
}
|
|
4039
4135
|
),
|
|
4040
|
-
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 }),
|
|
4041
4137
|
useButton && stepper("inc")
|
|
4042
4138
|
]
|
|
4043
4139
|
}
|
|
@@ -4051,15 +4147,28 @@ function flattenOptions(options, depth = 1) {
|
|
|
4051
4147
|
const out = [];
|
|
4052
4148
|
for (const o of options) {
|
|
4053
4149
|
const hasChildren = Array.isArray(o.children) && o.children.length > 0;
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
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
|
+
}
|
|
4063
4172
|
}
|
|
4064
4173
|
return out;
|
|
4065
4174
|
}
|
|
@@ -4183,6 +4292,9 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
4183
4292
|
);
|
|
4184
4293
|
const flat = react.useMemo(() => flattenOptions(options), [options]);
|
|
4185
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;
|
|
4186
4298
|
const showSearch = useSearch && selectable.length >= SEARCH_THRESHOLD;
|
|
4187
4299
|
const labelByValue = react.useMemo(() => new Map(flat.map((o) => [o.value, o.label])), [flat]);
|
|
4188
4300
|
const rawByValue = react.useMemo(() => new Map(flat.map((o) => [o.value, o.raw])), [flat]);
|
|
@@ -4233,6 +4345,7 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
4233
4345
|
const selectStore = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4234
4346
|
Ariakit__namespace.SelectProvider,
|
|
4235
4347
|
{
|
|
4348
|
+
animated: portalContainer == null ? 150 : false,
|
|
4236
4349
|
value: multi ? selected : selected[0] ?? "",
|
|
4237
4350
|
setValue: (v) => emit(Array.isArray(v) ? v : v === "" ? [] : [v]),
|
|
4238
4351
|
open,
|
|
@@ -4248,10 +4361,10 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
4248
4361
|
Ariakit__namespace.Select,
|
|
4249
4362
|
{
|
|
4250
4363
|
ref: triggerRef,
|
|
4251
|
-
disabled,
|
|
4364
|
+
disabled: effectiveDisabled,
|
|
4252
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",
|
|
4253
4366
|
style: {
|
|
4254
|
-
color:
|
|
4367
|
+
color: effectiveDisabled ? "var(--cmp-select-text-disabled)" : isPlaceholder ? "var(--cmp-select-icon-default)" : "var(--cmp-select-text-default)"
|
|
4255
4368
|
},
|
|
4256
4369
|
children: [
|
|
4257
4370
|
isHtmlLabel(triggerText) ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4266,7 +4379,7 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
4266
4379
|
{
|
|
4267
4380
|
name: "chevronDown",
|
|
4268
4381
|
size: 12,
|
|
4269
|
-
color:
|
|
4382
|
+
color: effectiveDisabled ? "var(--cmp-select-icon-disabled)" : "var(--cmp-select-icon-default)",
|
|
4270
4383
|
className: cn("shrink-0 transition-transform duration-200", open && "rotate-180")
|
|
4271
4384
|
}
|
|
4272
4385
|
)
|
|
@@ -4280,7 +4393,7 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
4280
4393
|
portalElement: portalContainer,
|
|
4281
4394
|
gutter: 4,
|
|
4282
4395
|
sameWidth: !dropdownWidth,
|
|
4283
|
-
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",
|
|
4284
4397
|
style: {
|
|
4285
4398
|
maxHeight: dropdownHeight,
|
|
4286
4399
|
...dropdownWidth ? { width: dropdownWidth } : {},
|
|
@@ -4321,7 +4434,7 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
4321
4434
|
),
|
|
4322
4435
|
hasItems ? /* @__PURE__ */ jsxRuntime.jsx(ItemList, { items: filtered, multi, selected, useSearch: showSearch }) : (
|
|
4323
4436
|
// 원본 sd-select-listbox__empty (표시할 항목이 없을 때)
|
|
4324
|
-
/* @__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." })
|
|
4325
4438
|
)
|
|
4326
4439
|
]
|
|
4327
4440
|
}
|
|
@@ -4344,7 +4457,7 @@ var SSelect = react.forwardRef(function SSelect2({
|
|
|
4344
4457
|
error: error || ruleError !== "",
|
|
4345
4458
|
status: rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0,
|
|
4346
4459
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
4347
|
-
disabled,
|
|
4460
|
+
disabled: effectiveDisabled,
|
|
4348
4461
|
width,
|
|
4349
4462
|
className,
|
|
4350
4463
|
style,
|
|
@@ -4379,7 +4492,11 @@ function ItemList({
|
|
|
4379
4492
|
{
|
|
4380
4493
|
className: cn(
|
|
4381
4494
|
"select-none py-[4px] pr-[12px] text-[12px] leading-[20px] text-[color:var(--cmp-listItem-content-default)]",
|
|
4382
|
-
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)]"
|
|
4383
4500
|
),
|
|
4384
4501
|
style: { paddingLeft: padLeft },
|
|
4385
4502
|
children: o.label
|
|
@@ -4406,15 +4523,21 @@ function ItemList({
|
|
|
4406
4523
|
"span",
|
|
4407
4524
|
{
|
|
4408
4525
|
className: cn(
|
|
4409
|
-
"flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid
|
|
4410
|
-
|
|
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
|
+
)
|
|
4411
4534
|
),
|
|
4412
4535
|
children: isSelected && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4413
4536
|
SIcon,
|
|
4414
4537
|
{
|
|
4415
4538
|
name: "checkboxCheck",
|
|
4416
4539
|
size: 12,
|
|
4417
|
-
color: "var(--cmp-checkbox-checked-icon-default)"
|
|
4540
|
+
color: o.disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : "var(--cmp-checkbox-checked-icon-default)"
|
|
4418
4541
|
}
|
|
4419
4542
|
)
|
|
4420
4543
|
}
|
|
@@ -4820,7 +4943,7 @@ function SCalendar({
|
|
|
4820
4943
|
"span",
|
|
4821
4944
|
{
|
|
4822
4945
|
className: cn(
|
|
4823
|
-
"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)]",
|
|
4824
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)]",
|
|
4825
4948
|
isToday && !disabled && "font-bold"
|
|
4826
4949
|
),
|
|
@@ -4945,8 +5068,8 @@ function SDatePicker({
|
|
|
4945
5068
|
disabled,
|
|
4946
5069
|
className,
|
|
4947
5070
|
style,
|
|
4948
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4949
|
-
/* @__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(
|
|
4950
5073
|
"button",
|
|
4951
5074
|
{
|
|
4952
5075
|
type: "button",
|
|
@@ -4982,16 +5105,25 @@ function SDatePicker({
|
|
|
4982
5105
|
]
|
|
4983
5106
|
}
|
|
4984
5107
|
) }),
|
|
4985
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4986
|
-
|
|
4987
|
-
{
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
5108
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5109
|
+
RPopover2__namespace.Content,
|
|
5110
|
+
{
|
|
5111
|
+
side: "bottom",
|
|
5112
|
+
align: "start",
|
|
5113
|
+
sideOffset: 4,
|
|
5114
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
5115
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5116
|
+
SCalendar,
|
|
5117
|
+
{
|
|
5118
|
+
value: value ?? void 0,
|
|
5119
|
+
selectable,
|
|
5120
|
+
elevated: true,
|
|
5121
|
+
onValueChange: select,
|
|
5122
|
+
onViewChange
|
|
5123
|
+
}
|
|
5124
|
+
)
|
|
4993
5125
|
}
|
|
4994
|
-
) })
|
|
5126
|
+
) })
|
|
4995
5127
|
] })
|
|
4996
5128
|
}
|
|
4997
5129
|
);
|
|
@@ -5001,6 +5133,7 @@ function RangeCalendar({
|
|
|
5001
5133
|
selectable,
|
|
5002
5134
|
maxRange,
|
|
5003
5135
|
onSelect,
|
|
5136
|
+
onPendingStartChange,
|
|
5004
5137
|
onViewChange
|
|
5005
5138
|
}) {
|
|
5006
5139
|
const today = todayStr();
|
|
@@ -5063,9 +5196,11 @@ function RangeCalendar({
|
|
|
5063
5196
|
setStart(d);
|
|
5064
5197
|
setEnd(null);
|
|
5065
5198
|
setHover(null);
|
|
5199
|
+
onPendingStartChange?.(d);
|
|
5066
5200
|
return;
|
|
5067
5201
|
}
|
|
5068
5202
|
setEnd(d);
|
|
5203
|
+
onPendingStartChange?.(null);
|
|
5069
5204
|
onSelect([start, d]);
|
|
5070
5205
|
};
|
|
5071
5206
|
const GRID_COLS = "grid grid-cols-[repeat(7,var(--cmp-datepicker-calendar-day-width))]";
|
|
@@ -5200,8 +5335,11 @@ function SDateRangePicker({
|
|
|
5200
5335
|
const portalContainer = usePortalContainer();
|
|
5201
5336
|
const [open, setOpen] = react.useState(false);
|
|
5202
5337
|
const [ruleError, setRuleError] = react.useState("");
|
|
5338
|
+
const [pendingStart, setPendingStart] = react.useState(null);
|
|
5203
5339
|
const hasValue = value != null && value[0] !== "" && value[1] !== "";
|
|
5204
|
-
const
|
|
5340
|
+
const hasDisplay = pendingStart != null || hasValue;
|
|
5341
|
+
const startText = pendingStart ?? (hasValue ? value[0] : "");
|
|
5342
|
+
const endText = pendingStart ? "" : hasValue ? value[1] : "";
|
|
5205
5343
|
useFormField({
|
|
5206
5344
|
name,
|
|
5207
5345
|
validate: () => {
|
|
@@ -5215,6 +5353,7 @@ function SDateRangePicker({
|
|
|
5215
5353
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
5216
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 };
|
|
5217
5355
|
const select = (r) => {
|
|
5356
|
+
setPendingStart(null);
|
|
5218
5357
|
onValueChange?.(r);
|
|
5219
5358
|
if (rules && rules.length > 0) setRuleError(runRules(r, rules));
|
|
5220
5359
|
setOpen(false);
|
|
@@ -5239,52 +5378,80 @@ function SDateRangePicker({
|
|
|
5239
5378
|
disabled,
|
|
5240
5379
|
className,
|
|
5241
5380
|
style,
|
|
5242
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
}
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
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",
|
|
5393
|
+
{
|
|
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
|
+
]
|
|
5430
|
+
}
|
|
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
|
+
)
|
|
5288
5455
|
}
|
|
5289
5456
|
);
|
|
5290
5457
|
}
|
|
@@ -5293,7 +5460,7 @@ var SChip = react.forwardRef(function SChip2({
|
|
|
5293
5460
|
value = "",
|
|
5294
5461
|
error: errorProp = false,
|
|
5295
5462
|
disabled = false,
|
|
5296
|
-
editable =
|
|
5463
|
+
editable = false,
|
|
5297
5464
|
showRemove = true,
|
|
5298
5465
|
placeholder = "",
|
|
5299
5466
|
rules,
|
|
@@ -5446,6 +5613,7 @@ function SFilePicker({
|
|
|
5446
5613
|
hovered = false,
|
|
5447
5614
|
inline = false,
|
|
5448
5615
|
multiple = false,
|
|
5616
|
+
useMultipleListBox = false,
|
|
5449
5617
|
accept,
|
|
5450
5618
|
maxFileSize,
|
|
5451
5619
|
maxTotalSize,
|
|
@@ -5473,8 +5641,8 @@ function SFilePicker({
|
|
|
5473
5641
|
const inputRef = react.useRef(null);
|
|
5474
5642
|
const [ruleError, setRuleError] = react.useState("");
|
|
5475
5643
|
const files = multiple ? Array.isArray(value) ? value : [] : value && !Array.isArray(value) ? value : null;
|
|
5476
|
-
const
|
|
5477
|
-
const displayText =
|
|
5644
|
+
const hasFiles = multiple ? files.length > 0 : !!files;
|
|
5645
|
+
const displayText = !hasFiles ? placeholder : multiple ? files.map((f) => f.name).join(", ") : files.name;
|
|
5478
5646
|
useFormField({
|
|
5479
5647
|
name,
|
|
5480
5648
|
validate: () => {
|
|
@@ -5538,78 +5706,88 @@ function SFilePicker({
|
|
|
5538
5706
|
const padX = size === "md" ? "var(--cmp-filepicker-md-paddingX)" : "var(--cmp-filepicker-sm-paddingX)";
|
|
5539
5707
|
const iconSize = size === "md" ? 20 : 16;
|
|
5540
5708
|
const gapCls = size === "md" ? "gap-[var(--cmp-filepicker-md-gap)]" : "gap-[var(--cmp-filepicker-sm-gap)]";
|
|
5541
|
-
const
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
onClick: open,
|
|
5562
|
-
"aria-label": placeholder,
|
|
5563
|
-
className: cn(
|
|
5564
|
-
"flex min-w-0 flex-1 items-center bg-transparent text-left",
|
|
5565
|
-
gapCls,
|
|
5566
|
-
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
|
+
}
|
|
5567
5729
|
),
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
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"
|
|
5605
5777
|
),
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
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
|
+
);
|
|
5609
5786
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style, children: [
|
|
5610
5787
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5611
5788
|
SField,
|
|
5612
5789
|
{
|
|
5790
|
+
borderless: inline,
|
|
5613
5791
|
label,
|
|
5614
5792
|
labelWidth,
|
|
5615
5793
|
icon,
|
|
@@ -5637,6 +5815,7 @@ function SKeyValueTable({
|
|
|
5637
5815
|
fields = [],
|
|
5638
5816
|
search = false,
|
|
5639
5817
|
radius = "default",
|
|
5818
|
+
dense = false,
|
|
5640
5819
|
onChange,
|
|
5641
5820
|
onSearch,
|
|
5642
5821
|
className,
|
|
@@ -5644,6 +5823,8 @@ function SKeyValueTable({
|
|
|
5644
5823
|
}) {
|
|
5645
5824
|
if (fields.length === 0) return null;
|
|
5646
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)";
|
|
5647
5828
|
const renderField = (f) => {
|
|
5648
5829
|
if (f.render) return f.render;
|
|
5649
5830
|
const opt = f.options ?? {};
|
|
@@ -5724,10 +5905,15 @@ function SKeyValueTable({
|
|
|
5724
5905
|
rowSpan: f.thRowSpan && f.thRowSpan > 1 ? f.thRowSpan : void 0,
|
|
5725
5906
|
colSpan: f.thColSpan && f.thColSpan > 1 ? f.thColSpan : void 0,
|
|
5726
5907
|
className: cn(
|
|
5727
|
-
"
|
|
5908
|
+
"box-border bg-[var(--cmp-table-header-bg)] px-[var(--cmp-table-header-paddingX)] text-left align-middle",
|
|
5728
5909
|
cellBorder,
|
|
5729
5910
|
f.thClass
|
|
5730
5911
|
),
|
|
5912
|
+
style: {
|
|
5913
|
+
height: cellHeight,
|
|
5914
|
+
paddingTop: cellPadY,
|
|
5915
|
+
paddingBottom: cellPadY
|
|
5916
|
+
},
|
|
5731
5917
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full w-full items-center justify-between gap-[var(--cmp-table-header-gap)]", children: [
|
|
5732
5918
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-[8px]", children: [
|
|
5733
5919
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[12px] font-bold leading-[20px] text-[color:var(--sys-color-fg-primary)]", children: f.label }),
|
|
@@ -5753,10 +5939,11 @@ function SKeyValueTable({
|
|
|
5753
5939
|
rowSpan: f.tdRowSpan && f.tdRowSpan > 1 ? f.tdRowSpan : void 0,
|
|
5754
5940
|
colSpan: f.tdColSpan && f.tdColSpan > 1 ? f.tdColSpan : void 0,
|
|
5755
5941
|
className: cn(
|
|
5756
|
-
"
|
|
5942
|
+
"box-border bg-[var(--sys-color-bg-frame)] px-[var(--cmp-table-keyValue-body-paddingX-default)] align-middle",
|
|
5757
5943
|
cellBorder,
|
|
5758
5944
|
f.tdClass
|
|
5759
5945
|
),
|
|
5946
|
+
style: { height: cellHeight, paddingTop: cellPadY, paddingBottom: cellPadY },
|
|
5760
5947
|
children: renderField(f)
|
|
5761
5948
|
},
|
|
5762
5949
|
`td-${r}-${c}`
|