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
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { forwardRef, createContext, useState, useRef, useImperativeHandle, useEffect, useContext } from 'react';
|
|
3
3
|
import { clsx } from 'clsx';
|
|
4
4
|
import { extendTailwindMerge } from 'tailwind-merge';
|
|
5
|
-
import { jsx,
|
|
6
|
-
import * as
|
|
5
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
|
+
import * as RPopover2 from '@radix-ui/react-popover';
|
|
7
7
|
|
|
8
8
|
var twMerge = extendTailwindMerge({
|
|
9
9
|
extend: {
|
|
@@ -2854,12 +2854,20 @@ var SIcon = forwardRef(function SIcon2({ name, size = 24, color, rotate, label,
|
|
|
2854
2854
|
// src/lib/floating-anim.ts
|
|
2855
2855
|
var FLOATING_SLIDE_ANIM = [
|
|
2856
2856
|
"data-[state=open]:data-[side=top]:animate-floating-in-top",
|
|
2857
|
+
"data-[state=delayed-open]:data-[side=top]:animate-floating-in-top",
|
|
2858
|
+
"data-[state=instant-open]:data-[side=top]:animate-floating-in-top",
|
|
2857
2859
|
"data-[state=closed]:data-[side=top]:animate-floating-out-top",
|
|
2858
2860
|
"data-[state=open]:data-[side=bottom]:animate-floating-in-bottom",
|
|
2861
|
+
"data-[state=delayed-open]:data-[side=bottom]:animate-floating-in-bottom",
|
|
2862
|
+
"data-[state=instant-open]:data-[side=bottom]:animate-floating-in-bottom",
|
|
2859
2863
|
"data-[state=closed]:data-[side=bottom]:animate-floating-out-bottom",
|
|
2860
2864
|
"data-[state=open]:data-[side=left]:animate-floating-in-left",
|
|
2865
|
+
"data-[state=delayed-open]:data-[side=left]:animate-floating-in-left",
|
|
2866
|
+
"data-[state=instant-open]:data-[side=left]:animate-floating-in-left",
|
|
2861
2867
|
"data-[state=closed]:data-[side=left]:animate-floating-out-left",
|
|
2862
2868
|
"data-[state=open]:data-[side=right]:animate-floating-in-right",
|
|
2869
|
+
"data-[state=delayed-open]:data-[side=right]:animate-floating-in-right",
|
|
2870
|
+
"data-[state=instant-open]:data-[side=right]:animate-floating-in-right",
|
|
2863
2871
|
"data-[state=closed]:data-[side=right]:animate-floating-out-right"
|
|
2864
2872
|
].join(" ");
|
|
2865
2873
|
var PortalContainerContext = createContext(null);
|
|
@@ -2867,11 +2875,200 @@ PortalContainerContext.Provider;
|
|
|
2867
2875
|
function usePortalContainer() {
|
|
2868
2876
|
return useContext(PortalContainerContext) ?? void 0;
|
|
2869
2877
|
}
|
|
2878
|
+
|
|
2879
|
+
// src/components/STag/tag.config.ts
|
|
2880
|
+
var TAG_SIZE_CONFIG = {
|
|
2881
|
+
xs: {
|
|
2882
|
+
height: 20,
|
|
2883
|
+
paddingX: 8,
|
|
2884
|
+
gap: 4,
|
|
2885
|
+
radius: 6,
|
|
2886
|
+
iconSize: 12,
|
|
2887
|
+
fontSize: 11,
|
|
2888
|
+
fontWeight: 500,
|
|
2889
|
+
lineHeight: 18
|
|
2890
|
+
},
|
|
2891
|
+
sm: {
|
|
2892
|
+
height: 24,
|
|
2893
|
+
paddingX: 8,
|
|
2894
|
+
gap: 4,
|
|
2895
|
+
radius: 6,
|
|
2896
|
+
iconSize: 16,
|
|
2897
|
+
fontSize: 12,
|
|
2898
|
+
fontWeight: 700,
|
|
2899
|
+
lineHeight: 20
|
|
2900
|
+
},
|
|
2901
|
+
md: {
|
|
2902
|
+
height: 28,
|
|
2903
|
+
paddingX: 12,
|
|
2904
|
+
gap: 6,
|
|
2905
|
+
radius: 8,
|
|
2906
|
+
iconSize: 16,
|
|
2907
|
+
fontSize: 14,
|
|
2908
|
+
fontWeight: 700,
|
|
2909
|
+
lineHeight: 24
|
|
2910
|
+
}
|
|
2911
|
+
};
|
|
2912
|
+
var STag = forwardRef(function STag2({
|
|
2913
|
+
shape = "square",
|
|
2914
|
+
size = "sm",
|
|
2915
|
+
color = "grey",
|
|
2916
|
+
label = "",
|
|
2917
|
+
icon,
|
|
2918
|
+
iconLeft = true,
|
|
2919
|
+
width,
|
|
2920
|
+
className,
|
|
2921
|
+
style,
|
|
2922
|
+
...rest
|
|
2923
|
+
}, ref) {
|
|
2924
|
+
const s = TAG_SIZE_CONFIG[size];
|
|
2925
|
+
const contentColor = `var(--cmp-tag-${color}-content)`;
|
|
2926
|
+
const iconNode = icon ? /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.iconSize, color: contentColor }) : null;
|
|
2927
|
+
const resolvedWidth = typeof width === "number" ? `${width}px` : width;
|
|
2928
|
+
return /* @__PURE__ */ jsxs(
|
|
2929
|
+
"span",
|
|
2930
|
+
{
|
|
2931
|
+
ref,
|
|
2932
|
+
"aria-label": label || "tag",
|
|
2933
|
+
className: cn(
|
|
2934
|
+
"box-border inline-flex w-fit select-none items-center justify-center whitespace-nowrap",
|
|
2935
|
+
className
|
|
2936
|
+
),
|
|
2937
|
+
style: {
|
|
2938
|
+
minHeight: s.height,
|
|
2939
|
+
padding: `0 ${s.paddingX}px`,
|
|
2940
|
+
gap: s.gap,
|
|
2941
|
+
borderRadius: shape === "pill" ? 999 : s.radius,
|
|
2942
|
+
fontSize: s.fontSize,
|
|
2943
|
+
fontWeight: s.fontWeight,
|
|
2944
|
+
lineHeight: `${s.lineHeight}px`,
|
|
2945
|
+
background: `var(--cmp-tag-${color}-bg)`,
|
|
2946
|
+
color: contentColor,
|
|
2947
|
+
...resolvedWidth != null ? { width: resolvedWidth } : {},
|
|
2948
|
+
...style
|
|
2949
|
+
},
|
|
2950
|
+
...rest,
|
|
2951
|
+
children: [
|
|
2952
|
+
icon && iconLeft && iconNode,
|
|
2953
|
+
label && /* @__PURE__ */ jsx("span", { className: "inline-flex min-w-0 items-center justify-center", children: label }),
|
|
2954
|
+
icon && !iconLeft && iconNode
|
|
2955
|
+
]
|
|
2956
|
+
}
|
|
2957
|
+
);
|
|
2958
|
+
});
|
|
2959
|
+
var SIZE = {
|
|
2960
|
+
xxs: { icon: 12, radius: "sm" },
|
|
2961
|
+
xs: { icon: 16, radius: "sm" },
|
|
2962
|
+
sm: { icon: 20, radius: "sm" },
|
|
2963
|
+
md: { icon: 24, radius: "md" },
|
|
2964
|
+
lg: { icon: 32, radius: "md" }
|
|
2965
|
+
};
|
|
2966
|
+
var TOOLTIP_HIDE_DELAY_MS = 100;
|
|
2967
|
+
function SGhostButton({
|
|
2968
|
+
icon,
|
|
2969
|
+
size = "sm",
|
|
2970
|
+
intent = "default",
|
|
2971
|
+
ariaLabel = "",
|
|
2972
|
+
tooltipText,
|
|
2973
|
+
disabled = false,
|
|
2974
|
+
onClick,
|
|
2975
|
+
className,
|
|
2976
|
+
style
|
|
2977
|
+
}) {
|
|
2978
|
+
const portalContainer = usePortalContainer();
|
|
2979
|
+
const [open, setOpen] = useState(false);
|
|
2980
|
+
const hideTimer = useRef(void 0);
|
|
2981
|
+
const cancelHide = () => {
|
|
2982
|
+
if (hideTimer.current) {
|
|
2983
|
+
clearTimeout(hideTimer.current);
|
|
2984
|
+
hideTimer.current = void 0;
|
|
2985
|
+
}
|
|
2986
|
+
};
|
|
2987
|
+
const openNow = () => {
|
|
2988
|
+
cancelHide();
|
|
2989
|
+
setOpen(true);
|
|
2990
|
+
};
|
|
2991
|
+
const startHide = () => {
|
|
2992
|
+
cancelHide();
|
|
2993
|
+
hideTimer.current = setTimeout(() => setOpen(false), TOOLTIP_HIDE_DELAY_MS);
|
|
2994
|
+
};
|
|
2995
|
+
const s = SIZE[size];
|
|
2996
|
+
const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
|
|
2997
|
+
const btn = /* @__PURE__ */ jsxs(
|
|
2998
|
+
"button",
|
|
2999
|
+
{
|
|
3000
|
+
type: "button",
|
|
3001
|
+
disabled,
|
|
3002
|
+
"aria-disabled": disabled ? "true" : void 0,
|
|
3003
|
+
"aria-label": ariaLabel.trim() || void 0,
|
|
3004
|
+
tabIndex: disabled ? -1 : void 0,
|
|
3005
|
+
onClick: (e) => {
|
|
3006
|
+
if (disabled) {
|
|
3007
|
+
e.preventDefault();
|
|
3008
|
+
return;
|
|
3009
|
+
}
|
|
3010
|
+
onClick?.(e);
|
|
3011
|
+
},
|
|
3012
|
+
className: cn(
|
|
3013
|
+
"group relative box-border inline-flex items-center justify-center border-none bg-transparent p-0 transition-shadow",
|
|
3014
|
+
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
3015
|
+
"focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
|
|
3016
|
+
className
|
|
3017
|
+
),
|
|
3018
|
+
style: {
|
|
3019
|
+
width: `var(--cmp-ghostButton-${size}-size)`,
|
|
3020
|
+
height: `var(--cmp-ghostButton-${size}-size)`,
|
|
3021
|
+
borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
|
|
3022
|
+
...style
|
|
3023
|
+
},
|
|
3024
|
+
children: [
|
|
3025
|
+
!disabled && /* @__PURE__ */ jsx(
|
|
3026
|
+
"span",
|
|
3027
|
+
{
|
|
3028
|
+
"aria-hidden": true,
|
|
3029
|
+
className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover:opacity-5",
|
|
3030
|
+
style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
|
|
3031
|
+
}
|
|
3032
|
+
),
|
|
3033
|
+
/* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon, color: contentColor })
|
|
3034
|
+
]
|
|
3035
|
+
}
|
|
3036
|
+
);
|
|
3037
|
+
const text = (tooltipText ?? "").trim();
|
|
3038
|
+
if (text === "") return btn;
|
|
3039
|
+
return /* @__PURE__ */ jsxs(RPopover2.Root, { open, onOpenChange: setOpen, children: [
|
|
3040
|
+
/* @__PURE__ */ jsx(RPopover2.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3041
|
+
"span",
|
|
3042
|
+
{
|
|
3043
|
+
className: "inline-flex",
|
|
3044
|
+
onMouseEnter: openNow,
|
|
3045
|
+
onMouseLeave: startHide,
|
|
3046
|
+
onFocus: openNow,
|
|
3047
|
+
onBlur: startHide,
|
|
3048
|
+
children: btn
|
|
3049
|
+
}
|
|
3050
|
+
) }),
|
|
3051
|
+
/* @__PURE__ */ jsx(RPopover2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
3052
|
+
RPopover2.Content,
|
|
3053
|
+
{
|
|
3054
|
+
side: "top",
|
|
3055
|
+
sideOffset: 4,
|
|
3056
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
3057
|
+
"aria-hidden": true,
|
|
3058
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
3059
|
+
onMouseEnter: cancelHide,
|
|
3060
|
+
onMouseLeave: startHide,
|
|
3061
|
+
children: /* @__PURE__ */ jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
|
|
3062
|
+
}
|
|
3063
|
+
) })
|
|
3064
|
+
] });
|
|
3065
|
+
}
|
|
2870
3066
|
var HIDE_DELAY_MS = 100;
|
|
2871
3067
|
function useBody(content, message = []) {
|
|
2872
3068
|
if (content != null) return content;
|
|
2873
3069
|
if (message.length === 0) return null;
|
|
2874
|
-
|
|
3070
|
+
const singleLine = message.length === 1;
|
|
3071
|
+
return /* @__PURE__ */ jsx(Fragment, { children: message.map((line, i) => /* @__PURE__ */ jsx("div", { className: singleLine ? "leading-[24px]" : void 0, children: line }, i)) });
|
|
2875
3072
|
}
|
|
2876
3073
|
var STooltip = forwardRef(function STooltip2({
|
|
2877
3074
|
content,
|
|
@@ -2929,7 +3126,7 @@ var STooltip = forwardRef(function STooltip2({
|
|
|
2929
3126
|
if (disabled || body == null) return /* @__PURE__ */ jsx(Fragment, { children: triggerNode });
|
|
2930
3127
|
const isHover = trigger === "hover";
|
|
2931
3128
|
const contentClass = cn(
|
|
2932
|
-
"z-50 max-w-xs rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px]",
|
|
3129
|
+
"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)]",
|
|
2933
3130
|
FLOATING_SLIDE_ANIM,
|
|
2934
3131
|
className
|
|
2935
3132
|
);
|
|
@@ -2939,10 +3136,10 @@ var STooltip = forwardRef(function STooltip2({
|
|
|
2939
3136
|
fontWeight: tooltipType === "default" ? 500 : 700,
|
|
2940
3137
|
...style
|
|
2941
3138
|
};
|
|
2942
|
-
return /* @__PURE__ */ jsxs(
|
|
3139
|
+
return /* @__PURE__ */ jsxs(RPopover2.Root, { open, onOpenChange: setOpen, children: [
|
|
2943
3140
|
isHover ? (
|
|
2944
3141
|
// hover: Anchor(위치 기준) + 직접 mouse 핸들러 — 클릭으로 토글되지 않도록 Trigger 미사용
|
|
2945
|
-
/* @__PURE__ */ jsx(
|
|
3142
|
+
/* @__PURE__ */ jsx(RPopover2.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
2946
3143
|
"span",
|
|
2947
3144
|
{
|
|
2948
3145
|
className: "inline-flex",
|
|
@@ -2953,9 +3150,9 @@ var STooltip = forwardRef(function STooltip2({
|
|
|
2953
3150
|
children: triggerNode
|
|
2954
3151
|
}
|
|
2955
3152
|
) })
|
|
2956
|
-
) : /* @__PURE__ */ jsx(
|
|
2957
|
-
/* @__PURE__ */ jsx(
|
|
2958
|
-
|
|
3153
|
+
) : /* @__PURE__ */ jsx(RPopover2.Trigger, { asChild: true, children: triggerNode }),
|
|
3154
|
+
/* @__PURE__ */ jsx(RPopover2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(
|
|
3155
|
+
RPopover2.Content,
|
|
2959
3156
|
{
|
|
2960
3157
|
side: placement,
|
|
2961
3158
|
sideOffset: 8,
|
|
@@ -2974,15 +3171,21 @@ var STooltip = forwardRef(function STooltip2({
|
|
|
2974
3171
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-[12px]", children: [
|
|
2975
3172
|
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: body }),
|
|
2976
3173
|
useClose && /* @__PURE__ */ jsx(
|
|
2977
|
-
|
|
3174
|
+
SGhostButton,
|
|
2978
3175
|
{
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
3176
|
+
icon: "close",
|
|
3177
|
+
size: "xs",
|
|
3178
|
+
intent: tooltipType === "default" ? "inverse" : "default",
|
|
3179
|
+
ariaLabel: "\uB2EB\uAE30",
|
|
3180
|
+
className: "shrink-0",
|
|
3181
|
+
onClick: () => {
|
|
3182
|
+
cancelHide();
|
|
3183
|
+
setOpen(false);
|
|
3184
|
+
}
|
|
2982
3185
|
}
|
|
2983
3186
|
)
|
|
2984
3187
|
] }),
|
|
2985
|
-
/* @__PURE__ */ jsx(
|
|
3188
|
+
/* @__PURE__ */ jsx(RPopover2.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
2986
3189
|
]
|
|
2987
3190
|
}
|
|
2988
3191
|
) })
|
|
@@ -3016,8 +3219,8 @@ function useFormField(field) {
|
|
|
3016
3219
|
}, [ctx, name]);
|
|
3017
3220
|
}
|
|
3018
3221
|
var FIELD_SIZE = {
|
|
3019
|
-
sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon:
|
|
3020
|
-
md: { height: 36, radius: 6, fieldGap: 16, labelGap: 8, fontSize: 14, lineHeight: 24, icon:
|
|
3222
|
+
sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon: 16 },
|
|
3223
|
+
md: { height: 36, radius: 6, fieldGap: 16, labelGap: 8, fontSize: 14, lineHeight: 24, icon: 16 }
|
|
3021
3224
|
};
|
|
3022
3225
|
var ALIGN = {
|
|
3023
3226
|
start: "flex-start",
|
|
@@ -3032,6 +3235,7 @@ var SField = forwardRef(function SField2({
|
|
|
3032
3235
|
labelTooltip = "",
|
|
3033
3236
|
labelTooltipProps,
|
|
3034
3237
|
labelWidth,
|
|
3238
|
+
labelHeight,
|
|
3035
3239
|
size = "sm",
|
|
3036
3240
|
addonLabel = "",
|
|
3037
3241
|
addonAlign = "start",
|
|
@@ -3046,6 +3250,7 @@ var SField = forwardRef(function SField2({
|
|
|
3046
3250
|
readOnly = false,
|
|
3047
3251
|
width,
|
|
3048
3252
|
multiline = false,
|
|
3253
|
+
borderless = false,
|
|
3049
3254
|
children,
|
|
3050
3255
|
className,
|
|
3051
3256
|
style,
|
|
@@ -3079,8 +3284,8 @@ var SField = forwardRef(function SField2({
|
|
|
3079
3284
|
const resolvedSuccess = status === "pass";
|
|
3080
3285
|
const showError = resolvedError && errorMessage !== "";
|
|
3081
3286
|
const interactive = !disabled && !readOnly;
|
|
3082
|
-
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)";
|
|
3083
|
-
const bgColor = disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
|
|
3287
|
+
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)";
|
|
3288
|
+
const bgColor = borderless ? "transparent" : disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
|
|
3084
3289
|
const textColor = disabled ? "var(--color-grey-65)" : readOnly ? "var(--sys-color-field-text-readOnly)" : "var(--sys-color-field-text-default)";
|
|
3085
3290
|
return /* @__PURE__ */ jsx(
|
|
3086
3291
|
"div",
|
|
@@ -3097,7 +3302,7 @@ var SField = forwardRef(function SField2({
|
|
|
3097
3302
|
{
|
|
3098
3303
|
className: "flex shrink-0 items-center font-bold text-(--sys-color-field-text-default)",
|
|
3099
3304
|
style: {
|
|
3100
|
-
height: s.height,
|
|
3305
|
+
height: cssLen(labelHeight) ?? s.height,
|
|
3101
3306
|
marginRight: s.fieldGap,
|
|
3102
3307
|
width: cssLen(labelWidth),
|
|
3103
3308
|
fontSize: s.fontSize,
|
|
@@ -3123,14 +3328,14 @@ var SField = forwardRef(function SField2({
|
|
|
3123
3328
|
{
|
|
3124
3329
|
className: cn(
|
|
3125
3330
|
"relative box-border flex min-w-0 items-stretch overflow-hidden border border-solid border-(--field-bc)",
|
|
3126
|
-
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]",
|
|
3331
|
+
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]",
|
|
3127
3332
|
disabled && "cursor-not-allowed"
|
|
3128
3333
|
),
|
|
3129
3334
|
style: {
|
|
3130
3335
|
// @ts-expect-error CSS 변수
|
|
3131
3336
|
"--field-bc": borderColor,
|
|
3132
3337
|
// focused/hovered prop이 명시된 경우 강조를 즉시 반영
|
|
3133
|
-
...interactive && focused ? { boxShadow: "0px 0px 4px 0px #0071ff66" } : {},
|
|
3338
|
+
...interactive && !borderless && focused ? { boxShadow: "0px 0px 4px 0px #0071ff66" } : {},
|
|
3134
3339
|
...multiline ? { minHeight: s.height } : { height: s.height },
|
|
3135
3340
|
"width": cssLen(width),
|
|
3136
3341
|
"borderRadius": s.radius,
|
|
@@ -3170,8 +3375,8 @@ var SField = forwardRef(function SField2({
|
|
|
3170
3375
|
);
|
|
3171
3376
|
});
|
|
3172
3377
|
var PAD = {
|
|
3173
|
-
sm: { fontSize: 12, stepper: 20, icon: 12 },
|
|
3174
|
-
md: { fontSize: 14, stepper: 24, icon: 14 }
|
|
3378
|
+
sm: { fontSize: 12, lineHeight: 20, stepper: 20, icon: 12 },
|
|
3379
|
+
md: { fontSize: 14, lineHeight: 24, stepper: 24, icon: 14 }
|
|
3175
3380
|
};
|
|
3176
3381
|
var toNumber = (val) => {
|
|
3177
3382
|
if (val === null || val === void 0 || val === "") return null;
|
|
@@ -3189,6 +3394,38 @@ var formatWithCommas = (value) => {
|
|
|
3189
3394
|
const result = isNeg ? "-" + formatted : formatted;
|
|
3190
3395
|
return decPart !== void 0 && decPart !== "" ? result + "." + decPart : result;
|
|
3191
3396
|
};
|
|
3397
|
+
var addCommas = (value) => value.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
3398
|
+
var formatInputWithCommas = (value) => {
|
|
3399
|
+
const isNeg = value.startsWith("-");
|
|
3400
|
+
const unsigned = isNeg ? value.slice(1) : value;
|
|
3401
|
+
const hasDecimal = unsigned.includes(".");
|
|
3402
|
+
const [intPart = "", decPart = ""] = unsigned.split(".");
|
|
3403
|
+
const formattedInt = addCommas(intPart === "" ? "0" : intPart);
|
|
3404
|
+
return `${isNeg ? "-" : ""}${formattedInt}${hasDecimal ? `.${decPart}` : ""}`;
|
|
3405
|
+
};
|
|
3406
|
+
var getDecimalLimit = (useDecimal, maxDecimalLength) => {
|
|
3407
|
+
if (!useDecimal || maxDecimalLength === void 0 || !Number.isFinite(maxDecimalLength)) {
|
|
3408
|
+
return void 0;
|
|
3409
|
+
}
|
|
3410
|
+
return Math.max(0, Math.floor(maxDecimalLength));
|
|
3411
|
+
};
|
|
3412
|
+
var applyDecimalLimit = (value, decimalLimit) => {
|
|
3413
|
+
if (value === null || decimalLimit === void 0) return value;
|
|
3414
|
+
return Number(value.toFixed(decimalLimit));
|
|
3415
|
+
};
|
|
3416
|
+
var getLogicalCaret = (value, caret) => {
|
|
3417
|
+
return value.slice(0, caret ?? value.length).replace(/,/g, "").length;
|
|
3418
|
+
};
|
|
3419
|
+
var getDisplayCaret = (value, logicalCaret) => {
|
|
3420
|
+
if (logicalCaret <= 0) return 0;
|
|
3421
|
+
let seen = 0;
|
|
3422
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
3423
|
+
if (value[i] === ",") continue;
|
|
3424
|
+
seen += 1;
|
|
3425
|
+
if (seen >= logicalCaret) return i + 1;
|
|
3426
|
+
}
|
|
3427
|
+
return value.length;
|
|
3428
|
+
};
|
|
3192
3429
|
var SNumberInput = forwardRef(function SNumberInput2({
|
|
3193
3430
|
value,
|
|
3194
3431
|
onValueChange,
|
|
@@ -3198,6 +3435,7 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3198
3435
|
step = 1,
|
|
3199
3436
|
useButton = false,
|
|
3200
3437
|
useDecimal = false,
|
|
3438
|
+
maxDecimalLength,
|
|
3201
3439
|
inputPrefix = "",
|
|
3202
3440
|
inputSuffix = "",
|
|
3203
3441
|
inputClass,
|
|
@@ -3229,7 +3467,8 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3229
3467
|
}, ref) {
|
|
3230
3468
|
const p = PAD[size];
|
|
3231
3469
|
const padX = `var(--cmp-numberInput-${size}-paddingX)`;
|
|
3232
|
-
const
|
|
3470
|
+
const decimalLimit = getDecimalLimit(useDecimal, maxDecimalLength);
|
|
3471
|
+
const numValue = applyDecimalLimit(toNumber(value), decimalLimit);
|
|
3233
3472
|
const [display, setDisplay] = useState(() => formatWithCommas(numValue));
|
|
3234
3473
|
const [ruleError, setRuleError] = useState("");
|
|
3235
3474
|
const innerRef = useRef(null);
|
|
@@ -3239,8 +3478,9 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3239
3478
|
else if (ref) ref.current = el;
|
|
3240
3479
|
};
|
|
3241
3480
|
useEffect(() => {
|
|
3242
|
-
|
|
3243
|
-
|
|
3481
|
+
if (document.activeElement === innerRef.current) return;
|
|
3482
|
+
setDisplay(formatWithCommas(applyDecimalLimit(toNumber(value), decimalLimit)));
|
|
3483
|
+
}, [decimalLimit, value]);
|
|
3244
3484
|
useFormField({
|
|
3245
3485
|
name,
|
|
3246
3486
|
validate: () => {
|
|
@@ -3252,48 +3492,87 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3252
3492
|
});
|
|
3253
3493
|
const resolvedError = error || ruleError !== "";
|
|
3254
3494
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
3255
|
-
const
|
|
3256
|
-
|
|
3257
|
-
|
|
3495
|
+
const restoreCaret = (nextDisplay, logicalCaret) => {
|
|
3496
|
+
const input = innerRef.current;
|
|
3497
|
+
if (logicalCaret === void 0 || !input || document.activeElement !== input) return;
|
|
3498
|
+
const nextCaret = getDisplayCaret(nextDisplay, logicalCaret);
|
|
3499
|
+
requestAnimationFrame(() => {
|
|
3500
|
+
if (document.activeElement !== input) return;
|
|
3501
|
+
input.setSelectionRange(nextCaret, nextCaret);
|
|
3502
|
+
});
|
|
3503
|
+
};
|
|
3504
|
+
const setDisplayWithCaret = (nextDisplay, logicalCaret) => {
|
|
3505
|
+
setDisplay(nextDisplay);
|
|
3506
|
+
restoreCaret(nextDisplay, logicalCaret);
|
|
3507
|
+
};
|
|
3508
|
+
const resetRejectedInput = (target, logicalCaret) => {
|
|
3509
|
+
target.value = display;
|
|
3510
|
+
restoreCaret(display, Math.min(logicalCaret, display.replace(/,/g, "").length));
|
|
3511
|
+
};
|
|
3512
|
+
const emit = (n, logicalCaret) => {
|
|
3513
|
+
const next = applyDecimalLimit(n, decimalLimit);
|
|
3514
|
+
const nextDisplay = formatWithCommas(next);
|
|
3515
|
+
setDisplayWithCaret(nextDisplay, logicalCaret);
|
|
3516
|
+
onValueChange?.(next);
|
|
3258
3517
|
};
|
|
3259
3518
|
const incDisabled = disabled || readOnly || numValue !== null && numValue >= max;
|
|
3260
3519
|
const decDisabled = disabled || readOnly || numValue !== null && numValue <= min;
|
|
3261
3520
|
const increment = () => {
|
|
3262
3521
|
if (incDisabled) return;
|
|
3263
3522
|
const cur = numValue ?? (min === Number.NEGATIVE_INFINITY ? 0 : min);
|
|
3264
|
-
const next = Math.min(cur + step, max);
|
|
3523
|
+
const next = applyDecimalLimit(Math.min(cur + step, max), decimalLimit);
|
|
3265
3524
|
if (next !== cur) emit(next);
|
|
3266
3525
|
};
|
|
3267
3526
|
const decrement = () => {
|
|
3268
3527
|
if (decDisabled) return;
|
|
3269
3528
|
const cur = numValue ?? (min === Number.NEGATIVE_INFINITY ? 0 : min);
|
|
3270
|
-
const next = Math.max(cur - step, min);
|
|
3529
|
+
const next = applyDecimalLimit(Math.max(cur - step, min), decimalLimit);
|
|
3271
3530
|
if (next !== cur) emit(next);
|
|
3272
3531
|
};
|
|
3273
|
-
const handleInput = (
|
|
3532
|
+
const handleInput = (event) => {
|
|
3533
|
+
const target = event.currentTarget;
|
|
3534
|
+
const raw = target.value;
|
|
3535
|
+
const logicalCaret = getLogicalCaret(raw, target.selectionStart);
|
|
3274
3536
|
if (raw === "") {
|
|
3275
|
-
|
|
3537
|
+
setDisplayWithCaret("", 0);
|
|
3276
3538
|
onValueChange?.(null);
|
|
3277
3539
|
return;
|
|
3278
3540
|
}
|
|
3279
3541
|
const cleaned = raw.replace(/,/g, "");
|
|
3280
3542
|
const decimals = (cleaned.match(/\./g) || []).length;
|
|
3281
|
-
if (decimals > 1)
|
|
3543
|
+
if (decimals > 1) {
|
|
3544
|
+
resetRejectedInput(target, logicalCaret);
|
|
3545
|
+
return;
|
|
3546
|
+
}
|
|
3282
3547
|
if (cleaned === "-" || cleaned === "." || cleaned === "-.") {
|
|
3283
|
-
|
|
3548
|
+
setDisplayWithCaret(cleaned, logicalCaret);
|
|
3284
3549
|
return;
|
|
3285
3550
|
}
|
|
3286
|
-
if (!useDecimal && cleaned.includes("."))
|
|
3551
|
+
if (!useDecimal && cleaned.includes(".")) {
|
|
3552
|
+
resetRejectedInput(target, logicalCaret);
|
|
3553
|
+
return;
|
|
3554
|
+
}
|
|
3555
|
+
if (decimalLimit !== void 0 && cleaned.includes(".")) {
|
|
3556
|
+
const fraction = cleaned.split(".")[1] ?? "";
|
|
3557
|
+
if (fraction.length > decimalLimit) {
|
|
3558
|
+
resetRejectedInput(target, logicalCaret);
|
|
3559
|
+
return;
|
|
3560
|
+
}
|
|
3561
|
+
}
|
|
3287
3562
|
if (cleaned.endsWith(".") && decimals === 1) {
|
|
3288
3563
|
const parsed2 = toNumber(cleaned.slice(0, -1));
|
|
3289
3564
|
if (parsed2 !== null) {
|
|
3290
|
-
|
|
3565
|
+
setDisplayWithCaret(formatInputWithCommas(cleaned), logicalCaret);
|
|
3291
3566
|
return;
|
|
3292
3567
|
}
|
|
3293
3568
|
}
|
|
3294
3569
|
const parsed = toNumber(cleaned);
|
|
3295
|
-
if (parsed === null)
|
|
3296
|
-
|
|
3570
|
+
if (parsed === null) {
|
|
3571
|
+
resetRejectedInput(target, logicalCaret);
|
|
3572
|
+
return;
|
|
3573
|
+
}
|
|
3574
|
+
setDisplayWithCaret(formatInputWithCommas(cleaned), logicalCaret);
|
|
3575
|
+
onValueChange?.(applyDecimalLimit(parsed, decimalLimit));
|
|
3297
3576
|
};
|
|
3298
3577
|
const stepper = (dir) => {
|
|
3299
3578
|
const off = dir === "inc" ? incDisabled : decDisabled;
|
|
@@ -3306,8 +3585,8 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3306
3585
|
"aria-label": dir === "inc" ? "\uC99D\uAC00" : "\uAC10\uC18C",
|
|
3307
3586
|
onClick: dir === "inc" ? increment : decrement,
|
|
3308
3587
|
className: cn(
|
|
3309
|
-
"flex flex-shrink-0 items-center justify-center",
|
|
3310
|
-
off ? "cursor-not-allowed" : "cursor-pointer"
|
|
3588
|
+
"flex flex-shrink-0 items-center justify-center border border-solid border-transparent transition-colors",
|
|
3589
|
+
off ? "cursor-not-allowed" : "cursor-pointer hover:border-[var(--color-border-accentLight)]"
|
|
3311
3590
|
),
|
|
3312
3591
|
style: {
|
|
3313
3592
|
width: `var(--cmp-numberInput-stepper-${size}-size)`,
|
|
@@ -3356,24 +3635,26 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3356
3635
|
style: {
|
|
3357
3636
|
// 원본 sd-number-input: content gap = padding-x 토큰 (gap 토큰 아님)
|
|
3358
3637
|
gap: `var(--cmp-numberInput-${size}-paddingX)`,
|
|
3359
|
-
padding: `0 ${useButton ? padX : `calc(${padX} * 2)`}
|
|
3638
|
+
padding: `0 ${useButton ? padX : `calc(${padX} * 2)`}`,
|
|
3639
|
+
fontSize: p.fontSize,
|
|
3640
|
+
lineHeight: `${p.lineHeight}px`
|
|
3360
3641
|
},
|
|
3361
3642
|
children: [
|
|
3362
3643
|
useButton && stepper("dec"),
|
|
3363
|
-
inputPrefix !== "" && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", style: {
|
|
3644
|
+
inputPrefix !== "" && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", style: { color: affixColor }, children: inputPrefix }),
|
|
3364
3645
|
/* @__PURE__ */ jsx(
|
|
3365
3646
|
"input",
|
|
3366
3647
|
{
|
|
3367
3648
|
ref: setRefs,
|
|
3368
3649
|
name,
|
|
3369
3650
|
type: "text",
|
|
3370
|
-
inputMode: "numeric",
|
|
3651
|
+
inputMode: useDecimal ? "decimal" : "numeric",
|
|
3371
3652
|
value: display,
|
|
3372
3653
|
placeholder,
|
|
3373
3654
|
disabled,
|
|
3374
3655
|
readOnly,
|
|
3375
3656
|
autoFocus,
|
|
3376
|
-
onChange:
|
|
3657
|
+
onChange: handleInput,
|
|
3377
3658
|
onKeyDown: (e) => {
|
|
3378
3659
|
if (e.key === "ArrowUp") {
|
|
3379
3660
|
e.preventDefault();
|
|
@@ -3385,26 +3666,29 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3385
3666
|
},
|
|
3386
3667
|
onFocus: (e) => onFocus?.(e),
|
|
3387
3668
|
onBlur: (e) => {
|
|
3388
|
-
const
|
|
3669
|
+
const cleaned = display.replace(/,/g, "");
|
|
3670
|
+
const n = toNumber(cleaned);
|
|
3389
3671
|
const clamped = n === null ? null : Math.min(Math.max(n, min), max);
|
|
3390
3672
|
if (clamped !== n) emit(clamped);
|
|
3391
|
-
else setDisplay(
|
|
3673
|
+
else setDisplay(n === null ? "" : formatInputWithCommas(cleaned));
|
|
3392
3674
|
if (rules && rules.length > 0) setRuleError(runRules(clamped, rules));
|
|
3393
3675
|
onBlur?.(e);
|
|
3394
3676
|
},
|
|
3395
3677
|
className: cn(
|
|
3396
|
-
|
|
3678
|
+
// h-full 대신 라인박스 높이 그대로 두어 prefix/suffix 와 동일하게 flex 로 수직 센터링
|
|
3679
|
+
// (h-full 이면 input 내부 텍스트 센터링을 브라우저가 수행해 1px 어긋날 수 있음)
|
|
3680
|
+
"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",
|
|
3397
3681
|
inputClass
|
|
3398
3682
|
),
|
|
3399
3683
|
style: {
|
|
3400
|
-
fontSize
|
|
3684
|
+
// fontSize/lineHeight 는 컨테이너에서 상속
|
|
3401
3685
|
textAlign: useButton ? "center" : "right",
|
|
3402
3686
|
color: disabled ? "var(--cmp-numberInput-text-disabled)" : "var(--cmp-numberInput-text-default)",
|
|
3403
3687
|
...inputStyle
|
|
3404
3688
|
}
|
|
3405
3689
|
}
|
|
3406
3690
|
),
|
|
3407
|
-
inputSuffix !== "" && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", style: {
|
|
3691
|
+
inputSuffix !== "" && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", style: { color: affixColor }, children: inputSuffix }),
|
|
3408
3692
|
useButton && stepper("inc")
|
|
3409
3693
|
]
|
|
3410
3694
|
}
|