sellmate-design-system-react 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/SActionModal/SActionModal.cjs +1 -1
- package/dist/components/SActionModal/SActionModal.cjs.map +1 -1
- package/dist/components/SActionModal/SActionModal.js +1 -1
- package/dist/components/SActionModal/SActionModal.js.map +1 -1
- package/dist/components/SBarcodeInput/SBarcodeInput.cjs +217 -208
- package/dist/components/SBarcodeInput/SBarcodeInput.cjs.map +1 -1
- package/dist/components/SBarcodeInput/SBarcodeInput.js +217 -208
- package/dist/components/SBarcodeInput/SBarcodeInput.js.map +1 -1
- package/dist/components/SCalendar/SCalendar.cjs +1 -1
- package/dist/components/SCalendar/SCalendar.cjs.map +1 -1
- package/dist/components/SCalendar/SCalendar.js +1 -1
- package/dist/components/SCalendar/SCalendar.js.map +1 -1
- package/dist/components/SChip/SChip.cjs +1 -1
- package/dist/components/SChip/SChip.cjs.map +1 -1
- package/dist/components/SChip/SChip.d.ts +1 -1
- package/dist/components/SChip/SChip.js +1 -1
- package/dist/components/SChip/SChip.js.map +1 -1
- package/dist/components/SChipInput/SChipInput.cjs +234 -220
- package/dist/components/SChipInput/SChipInput.cjs.map +1 -1
- package/dist/components/SChipInput/SChipInput.js +234 -220
- package/dist/components/SChipInput/SChipInput.js.map +1 -1
- package/dist/components/SCircleProgress/SCircleProgress.cjs +31 -14
- package/dist/components/SCircleProgress/SCircleProgress.cjs.map +1 -1
- package/dist/components/SCircleProgress/SCircleProgress.d.ts +2 -0
- package/dist/components/SCircleProgress/SCircleProgress.js +31 -14
- package/dist/components/SCircleProgress/SCircleProgress.js.map +1 -1
- package/dist/components/SDatePicker/SDatePicker.cjs +222 -213
- package/dist/components/SDatePicker/SDatePicker.cjs.map +1 -1
- package/dist/components/SDatePicker/SDatePicker.js +222 -213
- package/dist/components/SDatePicker/SDatePicker.js.map +1 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.cjs +297 -262
- package/dist/components/SDateRangePicker/SDateRangePicker.cjs.map +1 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.js +297 -262
- package/dist/components/SDateRangePicker/SDateRangePicker.js.map +1 -1
- package/dist/components/SDropdownButton/SDropdownButton.cjs +4 -4
- package/dist/components/SDropdownButton/SDropdownButton.cjs.map +1 -1
- package/dist/components/SDropdownButton/SDropdownButton.js +4 -4
- package/dist/components/SDropdownButton/SDropdownButton.js.map +1 -1
- package/dist/components/SField/SField.cjs +217 -20
- package/dist/components/SField/SField.cjs.map +1 -1
- package/dist/components/SField/SField.d.ts +11 -0
- package/dist/components/SField/SField.js +217 -20
- package/dist/components/SField/SField.js.map +1 -1
- package/dist/components/SFilePicker/SFilePicker.cjs +315 -276
- package/dist/components/SFilePicker/SFilePicker.cjs.map +1 -1
- package/dist/components/SFilePicker/SFilePicker.d.ts +4 -2
- package/dist/components/SFilePicker/SFilePicker.js +314 -276
- package/dist/components/SFilePicker/SFilePicker.js.map +1 -1
- package/dist/components/SInput/SInput.cjs +217 -208
- package/dist/components/SInput/SInput.cjs.map +1 -1
- package/dist/components/SInput/SInput.js +217 -208
- package/dist/components/SInput/SInput.js.map +1 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.cjs +631 -450
- package/dist/components/SKeyValueTable/SKeyValueTable.cjs.map +1 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.d.ts +3 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.js +631 -450
- package/dist/components/SKeyValueTable/SKeyValueTable.js.map +1 -1
- package/dist/components/SLoadingContainer/SLoadingContainer.cjs +39 -14
- package/dist/components/SLoadingContainer/SLoadingContainer.cjs.map +1 -1
- package/dist/components/SLoadingContainer/SLoadingContainer.js +39 -14
- package/dist/components/SLoadingContainer/SLoadingContainer.js.map +1 -1
- package/dist/components/SLoadingContainer/loading.cjs +39 -14
- package/dist/components/SLoadingContainer/loading.cjs.map +1 -1
- package/dist/components/SLoadingContainer/loading.js +39 -14
- package/dist/components/SLoadingContainer/loading.js.map +1 -1
- package/dist/components/SLoadingModal/SLoadingModal.cjs +37 -16
- package/dist/components/SLoadingModal/SLoadingModal.cjs.map +1 -1
- package/dist/components/SLoadingModal/SLoadingModal.d.ts +3 -1
- package/dist/components/SLoadingModal/SLoadingModal.js +37 -16
- package/dist/components/SLoadingModal/SLoadingModal.js.map +1 -1
- package/dist/components/SNumberInput/SNumberInput.cjs +325 -49
- package/dist/components/SNumberInput/SNumberInput.cjs.map +1 -1
- package/dist/components/SNumberInput/SNumberInput.d.ts +2 -0
- package/dist/components/SNumberInput/SNumberInput.js +325 -49
- 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/SRadio/SRadioGroup.cjs +1 -1
- package/dist/components/SRadio/SRadioGroup.cjs.map +1 -1
- package/dist/components/SRadio/SRadioGroup.js +1 -1
- package/dist/components/SRadio/SRadioGroup.js.map +1 -1
- package/dist/components/SSelect/SSelect.cjs +71 -32
- package/dist/components/SSelect/SSelect.cjs.map +1 -1
- package/dist/components/SSelect/SSelect.js +71 -32
- package/dist/components/SSelect/SSelect.js.map +1 -1
- package/dist/components/STable/STable.cjs +108 -49
- package/dist/components/STable/STable.cjs.map +1 -1
- package/dist/components/STable/STable.js +108 -49
- package/dist/components/STable/STable.js.map +1 -1
- package/dist/components/STextarea/STextarea.cjs +217 -20
- package/dist/components/STextarea/STextarea.cjs.map +1 -1
- package/dist/components/STextarea/STextarea.js +217 -20
- package/dist/components/STextarea/STextarea.js.map +1 -1
- package/dist/components/SToast/SToastContainer.cjs +3 -3
- package/dist/components/SToast/SToastContainer.cjs.map +1 -1
- package/dist/components/SToast/SToastContainer.js +3 -3
- package/dist/components/SToast/SToastContainer.js.map +1 -1
- package/dist/components/STooltip/STooltip.cjs +208 -13
- package/dist/components/STooltip/STooltip.cjs.map +1 -1
- package/dist/components/STooltip/STooltip.js +208 -13
- package/dist/components/STooltip/STooltip.js.map +1 -1
- package/dist/index.cjs +439 -221
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +439 -221
- package/dist/index.js.map +1 -1
- package/dist/styles.css +113 -48
- package/dist/theme.css +49 -23
- package/package.json +1 -1
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { forwardRef, createContext, useState, useRef, useImperativeHandle, useEffect, useMemo, useContext, Fragment as Fragment$1, useId } 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
|
import * as Ariakit from '@ariakit/react';
|
|
8
8
|
import * as RCheckbox from '@radix-ui/react-checkbox';
|
|
9
9
|
|
|
@@ -2877,11 +2877,200 @@ PortalContainerContext.Provider;
|
|
|
2877
2877
|
function usePortalContainer() {
|
|
2878
2878
|
return useContext(PortalContainerContext) ?? void 0;
|
|
2879
2879
|
}
|
|
2880
|
+
|
|
2881
|
+
// src/components/STag/tag.config.ts
|
|
2882
|
+
var TAG_SIZE_CONFIG = {
|
|
2883
|
+
xs: {
|
|
2884
|
+
height: 20,
|
|
2885
|
+
paddingX: 8,
|
|
2886
|
+
gap: 4,
|
|
2887
|
+
radius: 6,
|
|
2888
|
+
iconSize: 12,
|
|
2889
|
+
fontSize: 11,
|
|
2890
|
+
fontWeight: 500,
|
|
2891
|
+
lineHeight: 18
|
|
2892
|
+
},
|
|
2893
|
+
sm: {
|
|
2894
|
+
height: 24,
|
|
2895
|
+
paddingX: 8,
|
|
2896
|
+
gap: 4,
|
|
2897
|
+
radius: 6,
|
|
2898
|
+
iconSize: 16,
|
|
2899
|
+
fontSize: 12,
|
|
2900
|
+
fontWeight: 700,
|
|
2901
|
+
lineHeight: 20
|
|
2902
|
+
},
|
|
2903
|
+
md: {
|
|
2904
|
+
height: 28,
|
|
2905
|
+
paddingX: 12,
|
|
2906
|
+
gap: 6,
|
|
2907
|
+
radius: 8,
|
|
2908
|
+
iconSize: 16,
|
|
2909
|
+
fontSize: 14,
|
|
2910
|
+
fontWeight: 700,
|
|
2911
|
+
lineHeight: 24
|
|
2912
|
+
}
|
|
2913
|
+
};
|
|
2914
|
+
var STag = forwardRef(function STag2({
|
|
2915
|
+
shape = "square",
|
|
2916
|
+
size = "sm",
|
|
2917
|
+
color = "grey",
|
|
2918
|
+
label = "",
|
|
2919
|
+
icon,
|
|
2920
|
+
iconLeft = true,
|
|
2921
|
+
width,
|
|
2922
|
+
className,
|
|
2923
|
+
style,
|
|
2924
|
+
...rest
|
|
2925
|
+
}, ref) {
|
|
2926
|
+
const s = TAG_SIZE_CONFIG[size];
|
|
2927
|
+
const contentColor = `var(--cmp-tag-${color}-content)`;
|
|
2928
|
+
const iconNode = icon ? /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.iconSize, color: contentColor }) : null;
|
|
2929
|
+
const resolvedWidth = typeof width === "number" ? `${width}px` : width;
|
|
2930
|
+
return /* @__PURE__ */ jsxs(
|
|
2931
|
+
"span",
|
|
2932
|
+
{
|
|
2933
|
+
ref,
|
|
2934
|
+
"aria-label": label || "tag",
|
|
2935
|
+
className: cn(
|
|
2936
|
+
"box-border inline-flex w-fit select-none items-center justify-center whitespace-nowrap",
|
|
2937
|
+
className
|
|
2938
|
+
),
|
|
2939
|
+
style: {
|
|
2940
|
+
minHeight: s.height,
|
|
2941
|
+
padding: `0 ${s.paddingX}px`,
|
|
2942
|
+
gap: s.gap,
|
|
2943
|
+
borderRadius: shape === "pill" ? 999 : s.radius,
|
|
2944
|
+
fontSize: s.fontSize,
|
|
2945
|
+
fontWeight: s.fontWeight,
|
|
2946
|
+
lineHeight: `${s.lineHeight}px`,
|
|
2947
|
+
background: `var(--cmp-tag-${color}-bg)`,
|
|
2948
|
+
color: contentColor,
|
|
2949
|
+
...resolvedWidth != null ? { width: resolvedWidth } : {},
|
|
2950
|
+
...style
|
|
2951
|
+
},
|
|
2952
|
+
...rest,
|
|
2953
|
+
children: [
|
|
2954
|
+
icon && iconLeft && iconNode,
|
|
2955
|
+
label && /* @__PURE__ */ jsx("span", { className: "inline-flex min-w-0 items-center justify-center", children: label }),
|
|
2956
|
+
icon && !iconLeft && iconNode
|
|
2957
|
+
]
|
|
2958
|
+
}
|
|
2959
|
+
);
|
|
2960
|
+
});
|
|
2961
|
+
var SIZE = {
|
|
2962
|
+
xxs: { icon: 12, radius: "sm" },
|
|
2963
|
+
xs: { icon: 16, radius: "sm" },
|
|
2964
|
+
sm: { icon: 20, radius: "sm" },
|
|
2965
|
+
md: { icon: 24, radius: "md" },
|
|
2966
|
+
lg: { icon: 32, radius: "md" }
|
|
2967
|
+
};
|
|
2968
|
+
var TOOLTIP_HIDE_DELAY_MS = 100;
|
|
2969
|
+
function SGhostButton({
|
|
2970
|
+
icon,
|
|
2971
|
+
size = "sm",
|
|
2972
|
+
intent = "default",
|
|
2973
|
+
ariaLabel = "",
|
|
2974
|
+
tooltipText,
|
|
2975
|
+
disabled = false,
|
|
2976
|
+
onClick,
|
|
2977
|
+
className,
|
|
2978
|
+
style
|
|
2979
|
+
}) {
|
|
2980
|
+
const portalContainer = usePortalContainer();
|
|
2981
|
+
const [open, setOpen] = useState(false);
|
|
2982
|
+
const hideTimer = useRef(void 0);
|
|
2983
|
+
const cancelHide = () => {
|
|
2984
|
+
if (hideTimer.current) {
|
|
2985
|
+
clearTimeout(hideTimer.current);
|
|
2986
|
+
hideTimer.current = void 0;
|
|
2987
|
+
}
|
|
2988
|
+
};
|
|
2989
|
+
const openNow = () => {
|
|
2990
|
+
cancelHide();
|
|
2991
|
+
setOpen(true);
|
|
2992
|
+
};
|
|
2993
|
+
const startHide = () => {
|
|
2994
|
+
cancelHide();
|
|
2995
|
+
hideTimer.current = setTimeout(() => setOpen(false), TOOLTIP_HIDE_DELAY_MS);
|
|
2996
|
+
};
|
|
2997
|
+
const s = SIZE[size];
|
|
2998
|
+
const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
|
|
2999
|
+
const btn = /* @__PURE__ */ jsxs(
|
|
3000
|
+
"button",
|
|
3001
|
+
{
|
|
3002
|
+
type: "button",
|
|
3003
|
+
disabled,
|
|
3004
|
+
"aria-disabled": disabled ? "true" : void 0,
|
|
3005
|
+
"aria-label": ariaLabel.trim() || void 0,
|
|
3006
|
+
tabIndex: disabled ? -1 : void 0,
|
|
3007
|
+
onClick: (e) => {
|
|
3008
|
+
if (disabled) {
|
|
3009
|
+
e.preventDefault();
|
|
3010
|
+
return;
|
|
3011
|
+
}
|
|
3012
|
+
onClick?.(e);
|
|
3013
|
+
},
|
|
3014
|
+
className: cn(
|
|
3015
|
+
"group relative box-border inline-flex items-center justify-center border-none bg-transparent p-0 transition-shadow",
|
|
3016
|
+
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
3017
|
+
"focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
|
|
3018
|
+
className
|
|
3019
|
+
),
|
|
3020
|
+
style: {
|
|
3021
|
+
width: `var(--cmp-ghostButton-${size}-size)`,
|
|
3022
|
+
height: `var(--cmp-ghostButton-${size}-size)`,
|
|
3023
|
+
borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
|
|
3024
|
+
...style
|
|
3025
|
+
},
|
|
3026
|
+
children: [
|
|
3027
|
+
!disabled && /* @__PURE__ */ jsx(
|
|
3028
|
+
"span",
|
|
3029
|
+
{
|
|
3030
|
+
"aria-hidden": true,
|
|
3031
|
+
className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover:opacity-5",
|
|
3032
|
+
style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
|
|
3033
|
+
}
|
|
3034
|
+
),
|
|
3035
|
+
/* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon, color: contentColor })
|
|
3036
|
+
]
|
|
3037
|
+
}
|
|
3038
|
+
);
|
|
3039
|
+
const text = (tooltipText ?? "").trim();
|
|
3040
|
+
if (text === "") return btn;
|
|
3041
|
+
return /* @__PURE__ */ jsxs(RPopover2.Root, { open, onOpenChange: setOpen, children: [
|
|
3042
|
+
/* @__PURE__ */ jsx(RPopover2.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3043
|
+
"span",
|
|
3044
|
+
{
|
|
3045
|
+
className: "inline-flex",
|
|
3046
|
+
onMouseEnter: openNow,
|
|
3047
|
+
onMouseLeave: startHide,
|
|
3048
|
+
onFocus: openNow,
|
|
3049
|
+
onBlur: startHide,
|
|
3050
|
+
children: btn
|
|
3051
|
+
}
|
|
3052
|
+
) }),
|
|
3053
|
+
/* @__PURE__ */ jsx(RPopover2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
3054
|
+
RPopover2.Content,
|
|
3055
|
+
{
|
|
3056
|
+
side: "top",
|
|
3057
|
+
sideOffset: 4,
|
|
3058
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
3059
|
+
"aria-hidden": true,
|
|
3060
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
3061
|
+
onMouseEnter: cancelHide,
|
|
3062
|
+
onMouseLeave: startHide,
|
|
3063
|
+
children: /* @__PURE__ */ jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
|
|
3064
|
+
}
|
|
3065
|
+
) })
|
|
3066
|
+
] });
|
|
3067
|
+
}
|
|
2880
3068
|
var HIDE_DELAY_MS = 100;
|
|
2881
3069
|
function useBody(content, message = []) {
|
|
2882
3070
|
if (content != null) return content;
|
|
2883
3071
|
if (message.length === 0) return null;
|
|
2884
|
-
|
|
3072
|
+
const singleLine = message.length === 1;
|
|
3073
|
+
return /* @__PURE__ */ jsx(Fragment, { children: message.map((line, i) => /* @__PURE__ */ jsx("div", { className: singleLine ? "leading-[24px]" : void 0, children: line }, i)) });
|
|
2885
3074
|
}
|
|
2886
3075
|
var STooltip = forwardRef(function STooltip2({
|
|
2887
3076
|
content,
|
|
@@ -2949,10 +3138,10 @@ var STooltip = forwardRef(function STooltip2({
|
|
|
2949
3138
|
fontWeight: tooltipType === "default" ? 500 : 700,
|
|
2950
3139
|
...style
|
|
2951
3140
|
};
|
|
2952
|
-
return /* @__PURE__ */ jsxs(
|
|
3141
|
+
return /* @__PURE__ */ jsxs(RPopover2.Root, { open, onOpenChange: setOpen, children: [
|
|
2953
3142
|
isHover ? (
|
|
2954
3143
|
// hover: Anchor(위치 기준) + 직접 mouse 핸들러 — 클릭으로 토글되지 않도록 Trigger 미사용
|
|
2955
|
-
/* @__PURE__ */ jsx(
|
|
3144
|
+
/* @__PURE__ */ jsx(RPopover2.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
2956
3145
|
"span",
|
|
2957
3146
|
{
|
|
2958
3147
|
className: "inline-flex",
|
|
@@ -2963,9 +3152,9 @@ var STooltip = forwardRef(function STooltip2({
|
|
|
2963
3152
|
children: triggerNode
|
|
2964
3153
|
}
|
|
2965
3154
|
) })
|
|
2966
|
-
) : /* @__PURE__ */ jsx(
|
|
2967
|
-
/* @__PURE__ */ jsx(
|
|
2968
|
-
|
|
3155
|
+
) : /* @__PURE__ */ jsx(RPopover2.Trigger, { asChild: true, children: triggerNode }),
|
|
3156
|
+
/* @__PURE__ */ jsx(RPopover2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(
|
|
3157
|
+
RPopover2.Content,
|
|
2969
3158
|
{
|
|
2970
3159
|
side: placement,
|
|
2971
3160
|
sideOffset: 8,
|
|
@@ -2984,15 +3173,21 @@ var STooltip = forwardRef(function STooltip2({
|
|
|
2984
3173
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-[12px]", children: [
|
|
2985
3174
|
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: body }),
|
|
2986
3175
|
useClose && /* @__PURE__ */ jsx(
|
|
2987
|
-
|
|
3176
|
+
SGhostButton,
|
|
2988
3177
|
{
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
3178
|
+
icon: "close",
|
|
3179
|
+
size: "xs",
|
|
3180
|
+
intent: tooltipType === "default" ? "inverse" : "default",
|
|
3181
|
+
ariaLabel: "\uB2EB\uAE30",
|
|
3182
|
+
className: "shrink-0",
|
|
3183
|
+
onClick: () => {
|
|
3184
|
+
cancelHide();
|
|
3185
|
+
setOpen(false);
|
|
3186
|
+
}
|
|
2992
3187
|
}
|
|
2993
3188
|
)
|
|
2994
3189
|
] }),
|
|
2995
|
-
/* @__PURE__ */ jsx(
|
|
3190
|
+
/* @__PURE__ */ jsx(RPopover2.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
2996
3191
|
]
|
|
2997
3192
|
}
|
|
2998
3193
|
) })
|
|
@@ -3192,8 +3387,8 @@ function useFormField(field) {
|
|
|
3192
3387
|
}, [ctx, name]);
|
|
3193
3388
|
}
|
|
3194
3389
|
var FIELD_SIZE = {
|
|
3195
|
-
sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon:
|
|
3196
|
-
md: { height: 36, radius: 6, fieldGap: 16, labelGap: 8, fontSize: 14, lineHeight: 24, icon:
|
|
3390
|
+
sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon: 16 },
|
|
3391
|
+
md: { height: 36, radius: 6, fieldGap: 16, labelGap: 8, fontSize: 14, lineHeight: 24, icon: 16 }
|
|
3197
3392
|
};
|
|
3198
3393
|
var ALIGN = {
|
|
3199
3394
|
start: "flex-start",
|
|
@@ -3208,6 +3403,7 @@ var SField = forwardRef(function SField2({
|
|
|
3208
3403
|
labelTooltip = "",
|
|
3209
3404
|
labelTooltipProps,
|
|
3210
3405
|
labelWidth,
|
|
3406
|
+
labelHeight,
|
|
3211
3407
|
size = "sm",
|
|
3212
3408
|
addonLabel = "",
|
|
3213
3409
|
addonAlign = "start",
|
|
@@ -3222,6 +3418,7 @@ var SField = forwardRef(function SField2({
|
|
|
3222
3418
|
readOnly = false,
|
|
3223
3419
|
width,
|
|
3224
3420
|
multiline = false,
|
|
3421
|
+
borderless = false,
|
|
3225
3422
|
children,
|
|
3226
3423
|
className,
|
|
3227
3424
|
style,
|
|
@@ -3255,8 +3452,8 @@ var SField = forwardRef(function SField2({
|
|
|
3255
3452
|
const resolvedSuccess = status === "pass";
|
|
3256
3453
|
const showError = resolvedError && errorMessage !== "";
|
|
3257
3454
|
const interactive = !disabled && !readOnly;
|
|
3258
|
-
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)";
|
|
3259
|
-
const bgColor = disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
|
|
3455
|
+
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)";
|
|
3456
|
+
const bgColor = borderless ? "transparent" : disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
|
|
3260
3457
|
const textColor = disabled ? "var(--color-grey-65)" : readOnly ? "var(--sys-color-field-text-readOnly)" : "var(--sys-color-field-text-default)";
|
|
3261
3458
|
return /* @__PURE__ */ jsx(
|
|
3262
3459
|
"div",
|
|
@@ -3273,266 +3470,78 @@ var SField = forwardRef(function SField2({
|
|
|
3273
3470
|
{
|
|
3274
3471
|
className: "flex shrink-0 items-center font-bold text-(--sys-color-field-text-default)",
|
|
3275
3472
|
style: {
|
|
3276
|
-
height: s.height,
|
|
3473
|
+
height: cssLen(labelHeight) ?? s.height,
|
|
3277
3474
|
marginRight: s.fieldGap,
|
|
3278
3475
|
width: cssLen(labelWidth),
|
|
3279
|
-
fontSize: s.fontSize,
|
|
3280
|
-
lineHeight: `${s.lineHeight}px`
|
|
3281
|
-
},
|
|
3282
|
-
children: [
|
|
3283
|
-
icon && /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon, style: { marginRight: s.labelGap } }),
|
|
3284
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis whitespace-nowrap", children: label }),
|
|
3285
|
-
(labelTooltip !== "" || labelTooltipProps) && /* @__PURE__ */ jsx("span", { className: "shrink-0", style: { marginLeft: s.labelGap }, children: /* @__PURE__ */ jsx(
|
|
3286
|
-
STooltip,
|
|
3287
|
-
{
|
|
3288
|
-
message: labelTooltip !== "" ? [labelTooltip] : void 0,
|
|
3289
|
-
iconSize: s.icon,
|
|
3290
|
-
...labelTooltipProps
|
|
3291
|
-
}
|
|
3292
|
-
) })
|
|
3293
|
-
]
|
|
3294
|
-
}
|
|
3295
|
-
),
|
|
3296
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
3297
|
-
/* @__PURE__ */ jsxs(
|
|
3298
|
-
"div",
|
|
3299
|
-
{
|
|
3300
|
-
className: cn(
|
|
3301
|
-
"relative box-border flex min-w-0 items-stretch overflow-hidden border border-solid border-(--field-bc)",
|
|
3302
|
-
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]",
|
|
3303
|
-
disabled && "cursor-not-allowed"
|
|
3304
|
-
),
|
|
3305
|
-
style: {
|
|
3306
|
-
// @ts-expect-error CSS 변수
|
|
3307
|
-
"--field-bc": borderColor,
|
|
3308
|
-
// focused/hovered prop이 명시된 경우 강조를 즉시 반영
|
|
3309
|
-
...interactive && focused ? { boxShadow: "0px 0px 4px 0px #0071ff66" } : {},
|
|
3310
|
-
...multiline ? { minHeight: s.height } : { height: s.height },
|
|
3311
|
-
"width": cssLen(width),
|
|
3312
|
-
"borderRadius": s.radius,
|
|
3313
|
-
"background": bgColor,
|
|
3314
|
-
"color": textColor
|
|
3315
|
-
},
|
|
3316
|
-
"data-focused": focused || void 0,
|
|
3317
|
-
"data-hovered": hovered || void 0,
|
|
3318
|
-
children: [
|
|
3319
|
-
effectiveAddonLabel !== "" && /* @__PURE__ */ jsxs(
|
|
3320
|
-
"div",
|
|
3321
|
-
{
|
|
3322
|
-
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",
|
|
3323
|
-
style: {
|
|
3324
|
-
// 원본 sd-field: labelWidth가 addon 폭(--sd-field-addon-width)에도 적용됨
|
|
3325
|
-
width: cssLen(labelWidth),
|
|
3326
|
-
justifyContent: ALIGN[addonAlign],
|
|
3327
|
-
background: "var(--cmp-field-addonLabel-bg)",
|
|
3328
|
-
borderRightColor: disabled ? "var(--cmp-field-addonLabel-border-disabled)" : "var(--cmp-field-addonLabel-border-default)",
|
|
3329
|
-
borderTopLeftRadius: s.radius - 1,
|
|
3330
|
-
borderBottomLeftRadius: s.radius - 1
|
|
3331
|
-
},
|
|
3332
|
-
children: [
|
|
3333
|
-
icon && !label && /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon }),
|
|
3334
|
-
effectiveAddonLabel
|
|
3335
|
-
]
|
|
3336
|
-
}
|
|
3337
|
-
),
|
|
3338
|
-
/* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1", children })
|
|
3339
|
-
]
|
|
3340
|
-
}
|
|
3341
|
-
),
|
|
3342
|
-
showError ? /* @__PURE__ */ jsx("div", { className: "mt-(--cmp-field-contents-gap) text-12 font-normal leading-20 text-(--cmp-field-errorMessage-color)", children: errorMessage }) : hint !== "" ? /* @__PURE__ */ jsx("div", { className: "mt-(--cmp-field-contents-gap) text-12 font-normal leading-20 text-(--cmp-field-hint-color)", children: hint }) : null
|
|
3343
|
-
] })
|
|
3344
|
-
] })
|
|
3345
|
-
}
|
|
3346
|
-
);
|
|
3347
|
-
});
|
|
3348
|
-
|
|
3349
|
-
// src/components/STag/tag.config.ts
|
|
3350
|
-
var TAG_SIZE_CONFIG = {
|
|
3351
|
-
xs: {
|
|
3352
|
-
height: 20,
|
|
3353
|
-
paddingX: 8,
|
|
3354
|
-
gap: 4,
|
|
3355
|
-
radius: 6,
|
|
3356
|
-
iconSize: 12,
|
|
3357
|
-
fontSize: 11,
|
|
3358
|
-
fontWeight: 500,
|
|
3359
|
-
lineHeight: 18
|
|
3360
|
-
},
|
|
3361
|
-
sm: {
|
|
3362
|
-
height: 24,
|
|
3363
|
-
paddingX: 8,
|
|
3364
|
-
gap: 4,
|
|
3365
|
-
radius: 6,
|
|
3366
|
-
iconSize: 16,
|
|
3367
|
-
fontSize: 12,
|
|
3368
|
-
fontWeight: 700,
|
|
3369
|
-
lineHeight: 20
|
|
3370
|
-
},
|
|
3371
|
-
md: {
|
|
3372
|
-
height: 28,
|
|
3373
|
-
paddingX: 12,
|
|
3374
|
-
gap: 6,
|
|
3375
|
-
radius: 8,
|
|
3376
|
-
iconSize: 16,
|
|
3377
|
-
fontSize: 14,
|
|
3378
|
-
fontWeight: 700,
|
|
3379
|
-
lineHeight: 24
|
|
3380
|
-
}
|
|
3381
|
-
};
|
|
3382
|
-
var STag = forwardRef(function STag2({
|
|
3383
|
-
shape = "square",
|
|
3384
|
-
size = "sm",
|
|
3385
|
-
color = "grey",
|
|
3386
|
-
label = "",
|
|
3387
|
-
icon,
|
|
3388
|
-
iconLeft = true,
|
|
3389
|
-
width,
|
|
3390
|
-
className,
|
|
3391
|
-
style,
|
|
3392
|
-
...rest
|
|
3393
|
-
}, ref) {
|
|
3394
|
-
const s = TAG_SIZE_CONFIG[size];
|
|
3395
|
-
const contentColor = `var(--cmp-tag-${color}-content)`;
|
|
3396
|
-
const iconNode = icon ? /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.iconSize, color: contentColor }) : null;
|
|
3397
|
-
const resolvedWidth = typeof width === "number" ? `${width}px` : width;
|
|
3398
|
-
return /* @__PURE__ */ jsxs(
|
|
3399
|
-
"span",
|
|
3400
|
-
{
|
|
3401
|
-
ref,
|
|
3402
|
-
"aria-label": label || "tag",
|
|
3403
|
-
className: cn(
|
|
3404
|
-
"box-border inline-flex w-fit select-none items-center justify-center whitespace-nowrap",
|
|
3405
|
-
className
|
|
3406
|
-
),
|
|
3407
|
-
style: {
|
|
3408
|
-
minHeight: s.height,
|
|
3409
|
-
padding: `0 ${s.paddingX}px`,
|
|
3410
|
-
gap: s.gap,
|
|
3411
|
-
borderRadius: shape === "pill" ? 999 : s.radius,
|
|
3412
|
-
fontSize: s.fontSize,
|
|
3413
|
-
fontWeight: s.fontWeight,
|
|
3414
|
-
lineHeight: `${s.lineHeight}px`,
|
|
3415
|
-
background: `var(--cmp-tag-${color}-bg)`,
|
|
3416
|
-
color: contentColor,
|
|
3417
|
-
...resolvedWidth != null ? { width: resolvedWidth } : {},
|
|
3418
|
-
...style
|
|
3419
|
-
},
|
|
3420
|
-
...rest,
|
|
3421
|
-
children: [
|
|
3422
|
-
icon && iconLeft && iconNode,
|
|
3423
|
-
label && /* @__PURE__ */ jsx("span", { className: "inline-flex min-w-0 items-center justify-center", children: label }),
|
|
3424
|
-
icon && !iconLeft && iconNode
|
|
3425
|
-
]
|
|
3426
|
-
}
|
|
3427
|
-
);
|
|
3428
|
-
});
|
|
3429
|
-
var SIZE = {
|
|
3430
|
-
xxs: { icon: 12, radius: "sm" },
|
|
3431
|
-
xs: { icon: 16, radius: "sm" },
|
|
3432
|
-
sm: { icon: 20, radius: "sm" },
|
|
3433
|
-
md: { icon: 24, radius: "md" },
|
|
3434
|
-
lg: { icon: 32, radius: "md" }
|
|
3435
|
-
};
|
|
3436
|
-
var TOOLTIP_HIDE_DELAY_MS = 100;
|
|
3437
|
-
function SGhostButton({
|
|
3438
|
-
icon,
|
|
3439
|
-
size = "sm",
|
|
3440
|
-
intent = "default",
|
|
3441
|
-
ariaLabel = "",
|
|
3442
|
-
tooltipText,
|
|
3443
|
-
disabled = false,
|
|
3444
|
-
onClick,
|
|
3445
|
-
className,
|
|
3446
|
-
style
|
|
3447
|
-
}) {
|
|
3448
|
-
const portalContainer = usePortalContainer();
|
|
3449
|
-
const [open, setOpen] = useState(false);
|
|
3450
|
-
const hideTimer = useRef(void 0);
|
|
3451
|
-
const cancelHide = () => {
|
|
3452
|
-
if (hideTimer.current) {
|
|
3453
|
-
clearTimeout(hideTimer.current);
|
|
3454
|
-
hideTimer.current = void 0;
|
|
3455
|
-
}
|
|
3456
|
-
};
|
|
3457
|
-
const openNow = () => {
|
|
3458
|
-
cancelHide();
|
|
3459
|
-
setOpen(true);
|
|
3460
|
-
};
|
|
3461
|
-
const startHide = () => {
|
|
3462
|
-
cancelHide();
|
|
3463
|
-
hideTimer.current = setTimeout(() => setOpen(false), TOOLTIP_HIDE_DELAY_MS);
|
|
3464
|
-
};
|
|
3465
|
-
const s = SIZE[size];
|
|
3466
|
-
const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
|
|
3467
|
-
const btn = /* @__PURE__ */ jsxs(
|
|
3468
|
-
"button",
|
|
3469
|
-
{
|
|
3470
|
-
type: "button",
|
|
3471
|
-
disabled,
|
|
3472
|
-
"aria-disabled": disabled ? "true" : void 0,
|
|
3473
|
-
"aria-label": ariaLabel.trim() || void 0,
|
|
3474
|
-
tabIndex: disabled ? -1 : void 0,
|
|
3475
|
-
onClick: (e) => {
|
|
3476
|
-
if (disabled) {
|
|
3477
|
-
e.preventDefault();
|
|
3478
|
-
return;
|
|
3479
|
-
}
|
|
3480
|
-
onClick?.(e);
|
|
3481
|
-
},
|
|
3482
|
-
className: cn(
|
|
3483
|
-
"group relative box-border inline-flex items-center justify-center border-none bg-transparent p-0 transition-shadow",
|
|
3484
|
-
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
3485
|
-
"focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
|
|
3486
|
-
className
|
|
3487
|
-
),
|
|
3488
|
-
style: {
|
|
3489
|
-
width: `var(--cmp-ghostButton-${size}-size)`,
|
|
3490
|
-
height: `var(--cmp-ghostButton-${size}-size)`,
|
|
3491
|
-
borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
|
|
3492
|
-
...style
|
|
3493
|
-
},
|
|
3494
|
-
children: [
|
|
3495
|
-
!disabled && /* @__PURE__ */ jsx(
|
|
3496
|
-
"span",
|
|
3497
|
-
{
|
|
3498
|
-
"aria-hidden": true,
|
|
3499
|
-
className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover:opacity-5",
|
|
3500
|
-
style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
|
|
3476
|
+
fontSize: s.fontSize,
|
|
3477
|
+
lineHeight: `${s.lineHeight}px`
|
|
3478
|
+
},
|
|
3479
|
+
children: [
|
|
3480
|
+
icon && /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon, style: { marginRight: s.labelGap } }),
|
|
3481
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis whitespace-nowrap", children: label }),
|
|
3482
|
+
(labelTooltip !== "" || labelTooltipProps) && /* @__PURE__ */ jsx("span", { className: "shrink-0", style: { marginLeft: s.labelGap }, children: /* @__PURE__ */ jsx(
|
|
3483
|
+
STooltip,
|
|
3484
|
+
{
|
|
3485
|
+
message: labelTooltip !== "" ? [labelTooltip] : void 0,
|
|
3486
|
+
iconSize: s.icon,
|
|
3487
|
+
...labelTooltipProps
|
|
3488
|
+
}
|
|
3489
|
+
) })
|
|
3490
|
+
]
|
|
3501
3491
|
}
|
|
3502
3492
|
),
|
|
3503
|
-
/* @__PURE__ */
|
|
3504
|
-
|
|
3493
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
3494
|
+
/* @__PURE__ */ jsxs(
|
|
3495
|
+
"div",
|
|
3496
|
+
{
|
|
3497
|
+
className: cn(
|
|
3498
|
+
"relative box-border flex min-w-0 items-stretch overflow-hidden border border-solid border-(--field-bc)",
|
|
3499
|
+
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]",
|
|
3500
|
+
disabled && "cursor-not-allowed"
|
|
3501
|
+
),
|
|
3502
|
+
style: {
|
|
3503
|
+
// @ts-expect-error CSS 변수
|
|
3504
|
+
"--field-bc": borderColor,
|
|
3505
|
+
// focused/hovered prop이 명시된 경우 강조를 즉시 반영
|
|
3506
|
+
...interactive && !borderless && focused ? { boxShadow: "0px 0px 4px 0px #0071ff66" } : {},
|
|
3507
|
+
...multiline ? { minHeight: s.height } : { height: s.height },
|
|
3508
|
+
"width": cssLen(width),
|
|
3509
|
+
"borderRadius": s.radius,
|
|
3510
|
+
"background": bgColor,
|
|
3511
|
+
"color": textColor
|
|
3512
|
+
},
|
|
3513
|
+
"data-focused": focused || void 0,
|
|
3514
|
+
"data-hovered": hovered || void 0,
|
|
3515
|
+
children: [
|
|
3516
|
+
effectiveAddonLabel !== "" && /* @__PURE__ */ jsxs(
|
|
3517
|
+
"div",
|
|
3518
|
+
{
|
|
3519
|
+
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",
|
|
3520
|
+
style: {
|
|
3521
|
+
// 원본 sd-field: labelWidth가 addon 폭(--sd-field-addon-width)에도 적용됨
|
|
3522
|
+
width: cssLen(labelWidth),
|
|
3523
|
+
justifyContent: ALIGN[addonAlign],
|
|
3524
|
+
background: "var(--cmp-field-addonLabel-bg)",
|
|
3525
|
+
borderRightColor: disabled ? "var(--cmp-field-addonLabel-border-disabled)" : "var(--cmp-field-addonLabel-border-default)",
|
|
3526
|
+
borderTopLeftRadius: s.radius - 1,
|
|
3527
|
+
borderBottomLeftRadius: s.radius - 1
|
|
3528
|
+
},
|
|
3529
|
+
children: [
|
|
3530
|
+
icon && !label && /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon }),
|
|
3531
|
+
effectiveAddonLabel
|
|
3532
|
+
]
|
|
3533
|
+
}
|
|
3534
|
+
),
|
|
3535
|
+
/* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1", children })
|
|
3536
|
+
]
|
|
3537
|
+
}
|
|
3538
|
+
),
|
|
3539
|
+
showError ? /* @__PURE__ */ jsx("div", { className: "mt-(--cmp-field-contents-gap) text-12 font-normal leading-20 text-(--cmp-field-errorMessage-color)", children: errorMessage }) : hint !== "" ? /* @__PURE__ */ jsx("div", { className: "mt-(--cmp-field-contents-gap) text-12 font-normal leading-20 text-(--cmp-field-hint-color)", children: hint }) : null
|
|
3540
|
+
] })
|
|
3541
|
+
] })
|
|
3505
3542
|
}
|
|
3506
3543
|
);
|
|
3507
|
-
|
|
3508
|
-
if (text === "") return btn;
|
|
3509
|
-
return /* @__PURE__ */ jsxs(RPopover.Root, { open, onOpenChange: setOpen, children: [
|
|
3510
|
-
/* @__PURE__ */ jsx(RPopover.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3511
|
-
"span",
|
|
3512
|
-
{
|
|
3513
|
-
className: "inline-flex",
|
|
3514
|
-
onMouseEnter: openNow,
|
|
3515
|
-
onMouseLeave: startHide,
|
|
3516
|
-
onFocus: openNow,
|
|
3517
|
-
onBlur: startHide,
|
|
3518
|
-
children: btn
|
|
3519
|
-
}
|
|
3520
|
-
) }),
|
|
3521
|
-
/* @__PURE__ */ jsx(RPopover.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
3522
|
-
RPopover.Content,
|
|
3523
|
-
{
|
|
3524
|
-
side: "top",
|
|
3525
|
-
sideOffset: 4,
|
|
3526
|
-
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
3527
|
-
"aria-hidden": true,
|
|
3528
|
-
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
3529
|
-
onMouseEnter: cancelHide,
|
|
3530
|
-
onMouseLeave: startHide,
|
|
3531
|
-
children: /* @__PURE__ */ jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
|
|
3532
|
-
}
|
|
3533
|
-
) })
|
|
3534
|
-
] });
|
|
3535
|
-
}
|
|
3544
|
+
});
|
|
3536
3545
|
var FONT = {
|
|
3537
3546
|
sm: { fontSize: 12, lineHeight: 20, paddingX: "var(--cmp-textinput-sm-paddingX)" },
|
|
3538
3547
|
md: { fontSize: 14, lineHeight: 24, paddingX: "var(--cmp-textinput-md-paddingX)" }
|
|
@@ -3787,8 +3796,8 @@ var STextarea = forwardRef(function STextarea2({
|
|
|
3787
3796
|
);
|
|
3788
3797
|
});
|
|
3789
3798
|
var PAD2 = {
|
|
3790
|
-
sm: { fontSize: 12, stepper: 20, icon: 12 },
|
|
3791
|
-
md: { fontSize: 14, stepper: 24, icon: 14 }
|
|
3799
|
+
sm: { fontSize: 12, lineHeight: 20, stepper: 20, icon: 12 },
|
|
3800
|
+
md: { fontSize: 14, lineHeight: 24, stepper: 24, icon: 14 }
|
|
3792
3801
|
};
|
|
3793
3802
|
var toNumber = (val) => {
|
|
3794
3803
|
if (val === null || val === void 0 || val === "") return null;
|
|
@@ -3806,6 +3815,38 @@ var formatWithCommas = (value) => {
|
|
|
3806
3815
|
const result = isNeg ? "-" + formatted : formatted;
|
|
3807
3816
|
return decPart !== void 0 && decPart !== "" ? result + "." + decPart : result;
|
|
3808
3817
|
};
|
|
3818
|
+
var addCommas = (value) => value.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
3819
|
+
var formatInputWithCommas = (value) => {
|
|
3820
|
+
const isNeg = value.startsWith("-");
|
|
3821
|
+
const unsigned = isNeg ? value.slice(1) : value;
|
|
3822
|
+
const hasDecimal = unsigned.includes(".");
|
|
3823
|
+
const [intPart = "", decPart = ""] = unsigned.split(".");
|
|
3824
|
+
const formattedInt = addCommas(intPart === "" ? "0" : intPart);
|
|
3825
|
+
return `${isNeg ? "-" : ""}${formattedInt}${hasDecimal ? `.${decPart}` : ""}`;
|
|
3826
|
+
};
|
|
3827
|
+
var getDecimalLimit = (useDecimal, maxDecimalLength) => {
|
|
3828
|
+
if (!useDecimal || maxDecimalLength === void 0 || !Number.isFinite(maxDecimalLength)) {
|
|
3829
|
+
return void 0;
|
|
3830
|
+
}
|
|
3831
|
+
return Math.max(0, Math.floor(maxDecimalLength));
|
|
3832
|
+
};
|
|
3833
|
+
var applyDecimalLimit = (value, decimalLimit) => {
|
|
3834
|
+
if (value === null || decimalLimit === void 0) return value;
|
|
3835
|
+
return Number(value.toFixed(decimalLimit));
|
|
3836
|
+
};
|
|
3837
|
+
var getLogicalCaret = (value, caret) => {
|
|
3838
|
+
return value.slice(0, caret ?? value.length).replace(/,/g, "").length;
|
|
3839
|
+
};
|
|
3840
|
+
var getDisplayCaret = (value, logicalCaret) => {
|
|
3841
|
+
if (logicalCaret <= 0) return 0;
|
|
3842
|
+
let seen = 0;
|
|
3843
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
3844
|
+
if (value[i] === ",") continue;
|
|
3845
|
+
seen += 1;
|
|
3846
|
+
if (seen >= logicalCaret) return i + 1;
|
|
3847
|
+
}
|
|
3848
|
+
return value.length;
|
|
3849
|
+
};
|
|
3809
3850
|
var SNumberInput = forwardRef(function SNumberInput2({
|
|
3810
3851
|
value,
|
|
3811
3852
|
onValueChange,
|
|
@@ -3815,6 +3856,7 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3815
3856
|
step = 1,
|
|
3816
3857
|
useButton = false,
|
|
3817
3858
|
useDecimal = false,
|
|
3859
|
+
maxDecimalLength,
|
|
3818
3860
|
inputPrefix = "",
|
|
3819
3861
|
inputSuffix = "",
|
|
3820
3862
|
inputClass,
|
|
@@ -3846,7 +3888,8 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3846
3888
|
}, ref) {
|
|
3847
3889
|
const p = PAD2[size];
|
|
3848
3890
|
const padX = `var(--cmp-numberInput-${size}-paddingX)`;
|
|
3849
|
-
const
|
|
3891
|
+
const decimalLimit = getDecimalLimit(useDecimal, maxDecimalLength);
|
|
3892
|
+
const numValue = applyDecimalLimit(toNumber(value), decimalLimit);
|
|
3850
3893
|
const [display, setDisplay] = useState(() => formatWithCommas(numValue));
|
|
3851
3894
|
const [ruleError, setRuleError] = useState("");
|
|
3852
3895
|
const innerRef = useRef(null);
|
|
@@ -3856,8 +3899,9 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3856
3899
|
else if (ref) ref.current = el;
|
|
3857
3900
|
};
|
|
3858
3901
|
useEffect(() => {
|
|
3859
|
-
|
|
3860
|
-
|
|
3902
|
+
if (document.activeElement === innerRef.current) return;
|
|
3903
|
+
setDisplay(formatWithCommas(applyDecimalLimit(toNumber(value), decimalLimit)));
|
|
3904
|
+
}, [decimalLimit, value]);
|
|
3861
3905
|
useFormField({
|
|
3862
3906
|
name,
|
|
3863
3907
|
validate: () => {
|
|
@@ -3869,48 +3913,87 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3869
3913
|
});
|
|
3870
3914
|
const resolvedError = error || ruleError !== "";
|
|
3871
3915
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
3872
|
-
const
|
|
3873
|
-
|
|
3874
|
-
|
|
3916
|
+
const restoreCaret = (nextDisplay, logicalCaret) => {
|
|
3917
|
+
const input = innerRef.current;
|
|
3918
|
+
if (logicalCaret === void 0 || !input || document.activeElement !== input) return;
|
|
3919
|
+
const nextCaret = getDisplayCaret(nextDisplay, logicalCaret);
|
|
3920
|
+
requestAnimationFrame(() => {
|
|
3921
|
+
if (document.activeElement !== input) return;
|
|
3922
|
+
input.setSelectionRange(nextCaret, nextCaret);
|
|
3923
|
+
});
|
|
3924
|
+
};
|
|
3925
|
+
const setDisplayWithCaret = (nextDisplay, logicalCaret) => {
|
|
3926
|
+
setDisplay(nextDisplay);
|
|
3927
|
+
restoreCaret(nextDisplay, logicalCaret);
|
|
3928
|
+
};
|
|
3929
|
+
const resetRejectedInput = (target, logicalCaret) => {
|
|
3930
|
+
target.value = display;
|
|
3931
|
+
restoreCaret(display, Math.min(logicalCaret, display.replace(/,/g, "").length));
|
|
3932
|
+
};
|
|
3933
|
+
const emit = (n, logicalCaret) => {
|
|
3934
|
+
const next = applyDecimalLimit(n, decimalLimit);
|
|
3935
|
+
const nextDisplay = formatWithCommas(next);
|
|
3936
|
+
setDisplayWithCaret(nextDisplay, logicalCaret);
|
|
3937
|
+
onValueChange?.(next);
|
|
3875
3938
|
};
|
|
3876
3939
|
const incDisabled = disabled || readOnly || numValue !== null && numValue >= max;
|
|
3877
3940
|
const decDisabled = disabled || readOnly || numValue !== null && numValue <= min;
|
|
3878
3941
|
const increment = () => {
|
|
3879
3942
|
if (incDisabled) return;
|
|
3880
3943
|
const cur = numValue ?? (min === Number.NEGATIVE_INFINITY ? 0 : min);
|
|
3881
|
-
const next = Math.min(cur + step, max);
|
|
3944
|
+
const next = applyDecimalLimit(Math.min(cur + step, max), decimalLimit);
|
|
3882
3945
|
if (next !== cur) emit(next);
|
|
3883
3946
|
};
|
|
3884
3947
|
const decrement = () => {
|
|
3885
3948
|
if (decDisabled) return;
|
|
3886
3949
|
const cur = numValue ?? (min === Number.NEGATIVE_INFINITY ? 0 : min);
|
|
3887
|
-
const next = Math.max(cur - step, min);
|
|
3950
|
+
const next = applyDecimalLimit(Math.max(cur - step, min), decimalLimit);
|
|
3888
3951
|
if (next !== cur) emit(next);
|
|
3889
3952
|
};
|
|
3890
|
-
const handleInput = (
|
|
3953
|
+
const handleInput = (event) => {
|
|
3954
|
+
const target = event.currentTarget;
|
|
3955
|
+
const raw = target.value;
|
|
3956
|
+
const logicalCaret = getLogicalCaret(raw, target.selectionStart);
|
|
3891
3957
|
if (raw === "") {
|
|
3892
|
-
|
|
3958
|
+
setDisplayWithCaret("", 0);
|
|
3893
3959
|
onValueChange?.(null);
|
|
3894
3960
|
return;
|
|
3895
3961
|
}
|
|
3896
3962
|
const cleaned = raw.replace(/,/g, "");
|
|
3897
3963
|
const decimals = (cleaned.match(/\./g) || []).length;
|
|
3898
|
-
if (decimals > 1)
|
|
3964
|
+
if (decimals > 1) {
|
|
3965
|
+
resetRejectedInput(target, logicalCaret);
|
|
3966
|
+
return;
|
|
3967
|
+
}
|
|
3899
3968
|
if (cleaned === "-" || cleaned === "." || cleaned === "-.") {
|
|
3900
|
-
|
|
3969
|
+
setDisplayWithCaret(cleaned, logicalCaret);
|
|
3970
|
+
return;
|
|
3971
|
+
}
|
|
3972
|
+
if (!useDecimal && cleaned.includes(".")) {
|
|
3973
|
+
resetRejectedInput(target, logicalCaret);
|
|
3901
3974
|
return;
|
|
3902
3975
|
}
|
|
3903
|
-
if (
|
|
3976
|
+
if (decimalLimit !== void 0 && cleaned.includes(".")) {
|
|
3977
|
+
const fraction = cleaned.split(".")[1] ?? "";
|
|
3978
|
+
if (fraction.length > decimalLimit) {
|
|
3979
|
+
resetRejectedInput(target, logicalCaret);
|
|
3980
|
+
return;
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3904
3983
|
if (cleaned.endsWith(".") && decimals === 1) {
|
|
3905
3984
|
const parsed2 = toNumber(cleaned.slice(0, -1));
|
|
3906
3985
|
if (parsed2 !== null) {
|
|
3907
|
-
|
|
3986
|
+
setDisplayWithCaret(formatInputWithCommas(cleaned), logicalCaret);
|
|
3908
3987
|
return;
|
|
3909
3988
|
}
|
|
3910
3989
|
}
|
|
3911
3990
|
const parsed = toNumber(cleaned);
|
|
3912
|
-
if (parsed === null)
|
|
3913
|
-
|
|
3991
|
+
if (parsed === null) {
|
|
3992
|
+
resetRejectedInput(target, logicalCaret);
|
|
3993
|
+
return;
|
|
3994
|
+
}
|
|
3995
|
+
setDisplayWithCaret(formatInputWithCommas(cleaned), logicalCaret);
|
|
3996
|
+
onValueChange?.(applyDecimalLimit(parsed, decimalLimit));
|
|
3914
3997
|
};
|
|
3915
3998
|
const stepper = (dir) => {
|
|
3916
3999
|
const off = dir === "inc" ? incDisabled : decDisabled;
|
|
@@ -3923,8 +4006,8 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3923
4006
|
"aria-label": dir === "inc" ? "\uC99D\uAC00" : "\uAC10\uC18C",
|
|
3924
4007
|
onClick: dir === "inc" ? increment : decrement,
|
|
3925
4008
|
className: cn(
|
|
3926
|
-
"flex flex-shrink-0 items-center justify-center",
|
|
3927
|
-
off ? "cursor-not-allowed" : "cursor-pointer"
|
|
4009
|
+
"flex flex-shrink-0 items-center justify-center border border-solid border-transparent transition-colors",
|
|
4010
|
+
off ? "cursor-not-allowed" : "cursor-pointer hover:border-[var(--color-border-accentLight)]"
|
|
3928
4011
|
),
|
|
3929
4012
|
style: {
|
|
3930
4013
|
width: `var(--cmp-numberInput-stepper-${size}-size)`,
|
|
@@ -3973,24 +4056,26 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3973
4056
|
style: {
|
|
3974
4057
|
// 원본 sd-number-input: content gap = padding-x 토큰 (gap 토큰 아님)
|
|
3975
4058
|
gap: `var(--cmp-numberInput-${size}-paddingX)`,
|
|
3976
|
-
padding: `0 ${useButton ? padX : `calc(${padX} * 2)`}
|
|
4059
|
+
padding: `0 ${useButton ? padX : `calc(${padX} * 2)`}`,
|
|
4060
|
+
fontSize: p.fontSize,
|
|
4061
|
+
lineHeight: `${p.lineHeight}px`
|
|
3977
4062
|
},
|
|
3978
4063
|
children: [
|
|
3979
4064
|
useButton && stepper("dec"),
|
|
3980
|
-
inputPrefix !== "" && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", style: {
|
|
4065
|
+
inputPrefix !== "" && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", style: { color: affixColor }, children: inputPrefix }),
|
|
3981
4066
|
/* @__PURE__ */ jsx(
|
|
3982
4067
|
"input",
|
|
3983
4068
|
{
|
|
3984
4069
|
ref: setRefs,
|
|
3985
4070
|
name,
|
|
3986
4071
|
type: "text",
|
|
3987
|
-
inputMode: "numeric",
|
|
4072
|
+
inputMode: useDecimal ? "decimal" : "numeric",
|
|
3988
4073
|
value: display,
|
|
3989
4074
|
placeholder,
|
|
3990
4075
|
disabled,
|
|
3991
4076
|
readOnly,
|
|
3992
4077
|
autoFocus,
|
|
3993
|
-
onChange:
|
|
4078
|
+
onChange: handleInput,
|
|
3994
4079
|
onKeyDown: (e) => {
|
|
3995
4080
|
if (e.key === "ArrowUp") {
|
|
3996
4081
|
e.preventDefault();
|
|
@@ -4002,26 +4087,29 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
4002
4087
|
},
|
|
4003
4088
|
onFocus: (e) => onFocus?.(e),
|
|
4004
4089
|
onBlur: (e) => {
|
|
4005
|
-
const
|
|
4090
|
+
const cleaned = display.replace(/,/g, "");
|
|
4091
|
+
const n = toNumber(cleaned);
|
|
4006
4092
|
const clamped = n === null ? null : Math.min(Math.max(n, min), max);
|
|
4007
4093
|
if (clamped !== n) emit(clamped);
|
|
4008
|
-
else setDisplay(
|
|
4094
|
+
else setDisplay(n === null ? "" : formatInputWithCommas(cleaned));
|
|
4009
4095
|
if (rules && rules.length > 0) setRuleError(runRules(clamped, rules));
|
|
4010
4096
|
onBlur?.(e);
|
|
4011
4097
|
},
|
|
4012
4098
|
className: cn(
|
|
4013
|
-
|
|
4099
|
+
// h-full 대신 라인박스 높이 그대로 두어 prefix/suffix 와 동일하게 flex 로 수직 센터링
|
|
4100
|
+
// (h-full 이면 input 내부 텍스트 센터링을 브라우저가 수행해 1px 어긋날 수 있음)
|
|
4101
|
+
"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",
|
|
4014
4102
|
inputClass
|
|
4015
4103
|
),
|
|
4016
4104
|
style: {
|
|
4017
|
-
fontSize
|
|
4105
|
+
// fontSize/lineHeight 는 컨테이너에서 상속
|
|
4018
4106
|
textAlign: useButton ? "center" : "right",
|
|
4019
4107
|
color: disabled ? "var(--cmp-numberInput-text-disabled)" : "var(--cmp-numberInput-text-default)",
|
|
4020
4108
|
...inputStyle
|
|
4021
4109
|
}
|
|
4022
4110
|
}
|
|
4023
4111
|
),
|
|
4024
|
-
inputSuffix !== "" && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", style: {
|
|
4112
|
+
inputSuffix !== "" && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", style: { color: affixColor }, children: inputSuffix }),
|
|
4025
4113
|
useButton && stepper("inc")
|
|
4026
4114
|
]
|
|
4027
4115
|
}
|
|
@@ -4035,15 +4123,28 @@ function flattenOptions(options, depth = 1) {
|
|
|
4035
4123
|
const out = [];
|
|
4036
4124
|
for (const o of options) {
|
|
4037
4125
|
const hasChildren = Array.isArray(o.children) && o.children.length > 0;
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4126
|
+
if (hasChildren) {
|
|
4127
|
+
const childFlat = flattenOptions(o.children, depth + 1);
|
|
4128
|
+
const allChildrenDisabled = childFlat.every((c) => c.disabled);
|
|
4129
|
+
out.push({
|
|
4130
|
+
value: String(o.value),
|
|
4131
|
+
label: o.label,
|
|
4132
|
+
disabled: !!o.disabled || allChildrenDisabled,
|
|
4133
|
+
depth,
|
|
4134
|
+
isGroup: true,
|
|
4135
|
+
raw: o.value
|
|
4136
|
+
});
|
|
4137
|
+
out.push(...childFlat);
|
|
4138
|
+
} else {
|
|
4139
|
+
out.push({
|
|
4140
|
+
value: String(o.value),
|
|
4141
|
+
label: o.label,
|
|
4142
|
+
disabled: !!o.disabled,
|
|
4143
|
+
depth,
|
|
4144
|
+
isGroup: false,
|
|
4145
|
+
raw: o.value
|
|
4146
|
+
});
|
|
4147
|
+
}
|
|
4047
4148
|
}
|
|
4048
4149
|
return out;
|
|
4049
4150
|
}
|
|
@@ -4167,6 +4268,9 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
4167
4268
|
);
|
|
4168
4269
|
const flat = useMemo(() => flattenOptions(options), [options]);
|
|
4169
4270
|
const selectable = useMemo(() => selectableOptions(flat), [flat]);
|
|
4271
|
+
const hasLeaf = useMemo(() => flat.some((o) => !o.isGroup), [flat]);
|
|
4272
|
+
const allOptionsDisabled = hasLeaf && selectable.length === 0;
|
|
4273
|
+
const effectiveDisabled = disabled || allOptionsDisabled;
|
|
4170
4274
|
const showSearch = useSearch && selectable.length >= SEARCH_THRESHOLD;
|
|
4171
4275
|
const labelByValue = useMemo(() => new Map(flat.map((o) => [o.value, o.label])), [flat]);
|
|
4172
4276
|
const rawByValue = useMemo(() => new Map(flat.map((o) => [o.value, o.raw])), [flat]);
|
|
@@ -4233,10 +4337,10 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
4233
4337
|
Ariakit.Select,
|
|
4234
4338
|
{
|
|
4235
4339
|
ref: triggerRef,
|
|
4236
|
-
disabled,
|
|
4340
|
+
disabled: effectiveDisabled,
|
|
4237
4341
|
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",
|
|
4238
4342
|
style: {
|
|
4239
|
-
color:
|
|
4343
|
+
color: effectiveDisabled ? "var(--cmp-select-text-disabled)" : isPlaceholder ? "var(--cmp-select-icon-default)" : "var(--cmp-select-text-default)"
|
|
4240
4344
|
},
|
|
4241
4345
|
children: [
|
|
4242
4346
|
isHtmlLabel(triggerText) ? /* @__PURE__ */ jsx(
|
|
@@ -4251,7 +4355,7 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
4251
4355
|
{
|
|
4252
4356
|
name: "chevronDown",
|
|
4253
4357
|
size: 12,
|
|
4254
|
-
color:
|
|
4358
|
+
color: effectiveDisabled ? "var(--cmp-select-icon-disabled)" : "var(--cmp-select-icon-default)",
|
|
4255
4359
|
className: cn("shrink-0 transition-transform duration-200", open && "rotate-180")
|
|
4256
4360
|
}
|
|
4257
4361
|
)
|
|
@@ -4265,7 +4369,7 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
4265
4369
|
portalElement: portalContainer,
|
|
4266
4370
|
gutter: 4,
|
|
4267
4371
|
sameWidth: !dropdownWidth,
|
|
4268
|
-
className: "z-50 overflow-auto rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)]
|
|
4372
|
+
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",
|
|
4269
4373
|
style: {
|
|
4270
4374
|
maxHeight: dropdownHeight,
|
|
4271
4375
|
...dropdownWidth ? { width: dropdownWidth } : {},
|
|
@@ -4306,7 +4410,7 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
4306
4410
|
),
|
|
4307
4411
|
hasItems ? /* @__PURE__ */ jsx(ItemList, { items: filtered, multi, selected, useSearch: showSearch }) : (
|
|
4308
4412
|
// 원본 sd-select-listbox__empty (표시할 항목이 없을 때)
|
|
4309
|
-
/* @__PURE__ */ jsx("div", { className: "px-[12px] py-[12px] text-
|
|
4413
|
+
/* @__PURE__ */ 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." })
|
|
4310
4414
|
)
|
|
4311
4415
|
]
|
|
4312
4416
|
}
|
|
@@ -4329,7 +4433,7 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
4329
4433
|
error: error || ruleError !== "",
|
|
4330
4434
|
status: rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0,
|
|
4331
4435
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
4332
|
-
disabled,
|
|
4436
|
+
disabled: effectiveDisabled,
|
|
4333
4437
|
width,
|
|
4334
4438
|
className,
|
|
4335
4439
|
style,
|
|
@@ -4364,7 +4468,11 @@ function ItemList({
|
|
|
4364
4468
|
{
|
|
4365
4469
|
className: cn(
|
|
4366
4470
|
"select-none py-[4px] pr-[12px] text-[12px] leading-[20px] text-[color:var(--cmp-listItem-content-default)]",
|
|
4367
|
-
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"
|
|
4471
|
+
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",
|
|
4472
|
+
// 하위가 전부 비활성이면(select.config 에서 bubble-up) 어미 그룹도 비활성 처리:
|
|
4473
|
+
// 텍스트는 회색(#888), depth1 그룹은 파란 배경 대신 회색(#EEE)으로 (depth2 는 #F6F6F6 유지)
|
|
4474
|
+
o.disabled && "cursor-not-allowed text-[color:var(--cmp-listItem-content-disabled)]",
|
|
4475
|
+
o.disabled && isDepth1 && "bg-[var(--cmp-listItem-depth1-bg-disabled)]"
|
|
4368
4476
|
),
|
|
4369
4477
|
style: { paddingLeft: padLeft },
|
|
4370
4478
|
children: o.label
|
|
@@ -4378,10 +4486,14 @@ function ItemList({
|
|
|
4378
4486
|
{
|
|
4379
4487
|
value: o.value,
|
|
4380
4488
|
disabled: o.disabled,
|
|
4489
|
+
accessibleWhenDisabled: true,
|
|
4381
4490
|
className: cn(
|
|
4382
4491
|
itemBase,
|
|
4383
4492
|
isSelected && !multi && "font-bold text-[color:var(--cmp-listItem-content-selected)]",
|
|
4384
|
-
|
|
4493
|
+
// Ariakit은 disabled 항목도 hover 시 active(data-active-item) 처리하므로,
|
|
4494
|
+
// 비활성 항목에는 hover 하이라이트를 적용하지 않아 회색 비활성 스타일을 유지한다.
|
|
4495
|
+
// (원본 Stencil의 `--focused...:not(--disabled)` 규칙과 동일한 의도)
|
|
4496
|
+
!o.disabled && activeClass
|
|
4385
4497
|
),
|
|
4386
4498
|
style: { paddingTop: 4, paddingBottom: 4, paddingRight: 12, paddingLeft: padLeft },
|
|
4387
4499
|
render: useSearch ? /* @__PURE__ */ jsx(Ariakit.ComboboxItem, {}) : void 0,
|
|
@@ -4391,15 +4503,21 @@ function ItemList({
|
|
|
4391
4503
|
"span",
|
|
4392
4504
|
{
|
|
4393
4505
|
className: cn(
|
|
4394
|
-
"flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid
|
|
4395
|
-
|
|
4506
|
+
"flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid",
|
|
4507
|
+
o.disabled ? (
|
|
4508
|
+
// 비활성: 회색 채움(#E1E1E1) + 회색 테두리(#CCCCCC)
|
|
4509
|
+
"cursor-not-allowed border-[color:var(--cmp-checkbox-border-disabled)] bg-[var(--cmp-checkbox-bg-disabled)]"
|
|
4510
|
+
) : cn(
|
|
4511
|
+
"group-data-[active-item]:border-[color:var(--cmp-checkbox-checked-border-inverse)]",
|
|
4512
|
+
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"
|
|
4513
|
+
)
|
|
4396
4514
|
),
|
|
4397
4515
|
children: isSelected && /* @__PURE__ */ jsx(
|
|
4398
4516
|
SIcon,
|
|
4399
4517
|
{
|
|
4400
4518
|
name: "checkboxCheck",
|
|
4401
4519
|
size: 12,
|
|
4402
|
-
color: "var(--cmp-checkbox-checked-icon-default)"
|
|
4520
|
+
color: o.disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : "var(--cmp-checkbox-checked-icon-default)"
|
|
4403
4521
|
}
|
|
4404
4522
|
)
|
|
4405
4523
|
}
|
|
@@ -4523,7 +4641,7 @@ function SRadioGroup({
|
|
|
4523
4641
|
role: "radiogroup",
|
|
4524
4642
|
className: cn(
|
|
4525
4643
|
"inline-flex",
|
|
4526
|
-
direction === "vertical" ? "flex-col gap-[
|
|
4644
|
+
direction === "vertical" ? "flex-col gap-[var(--cmp-radio-group-gap-vertical)]" : "flex-row gap-[var(--cmp-radio-group-gap-horizontal)]",
|
|
4527
4645
|
className
|
|
4528
4646
|
),
|
|
4529
4647
|
style,
|
|
@@ -4805,7 +4923,7 @@ function SCalendar({
|
|
|
4805
4923
|
"span",
|
|
4806
4924
|
{
|
|
4807
4925
|
className: cn(
|
|
4808
|
-
"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]",
|
|
4926
|
+
"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)]",
|
|
4809
4927
|
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)]",
|
|
4810
4928
|
isToday && !disabled && "font-bold"
|
|
4811
4929
|
),
|
|
@@ -4930,8 +5048,8 @@ function SDatePicker({
|
|
|
4930
5048
|
disabled,
|
|
4931
5049
|
className,
|
|
4932
5050
|
style,
|
|
4933
|
-
children: /* @__PURE__ */ jsxs(
|
|
4934
|
-
/* @__PURE__ */ jsx(
|
|
5051
|
+
children: /* @__PURE__ */ jsxs(RPopover2.Root, { open, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
5052
|
+
/* @__PURE__ */ jsx(RPopover2.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
4935
5053
|
"button",
|
|
4936
5054
|
{
|
|
4937
5055
|
type: "button",
|
|
@@ -4967,8 +5085,8 @@ function SDatePicker({
|
|
|
4967
5085
|
]
|
|
4968
5086
|
}
|
|
4969
5087
|
) }),
|
|
4970
|
-
/* @__PURE__ */ jsx(
|
|
4971
|
-
|
|
5088
|
+
/* @__PURE__ */ jsx(RPopover2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
5089
|
+
RPopover2.Content,
|
|
4972
5090
|
{
|
|
4973
5091
|
side: "bottom",
|
|
4974
5092
|
align: "start",
|
|
@@ -4995,6 +5113,7 @@ function RangeCalendar({
|
|
|
4995
5113
|
selectable,
|
|
4996
5114
|
maxRange,
|
|
4997
5115
|
onSelect,
|
|
5116
|
+
onPendingStartChange,
|
|
4998
5117
|
onViewChange
|
|
4999
5118
|
}) {
|
|
5000
5119
|
const today = todayStr();
|
|
@@ -5057,9 +5176,11 @@ function RangeCalendar({
|
|
|
5057
5176
|
setStart(d);
|
|
5058
5177
|
setEnd(null);
|
|
5059
5178
|
setHover(null);
|
|
5179
|
+
onPendingStartChange?.(d);
|
|
5060
5180
|
return;
|
|
5061
5181
|
}
|
|
5062
5182
|
setEnd(d);
|
|
5183
|
+
onPendingStartChange?.(null);
|
|
5063
5184
|
onSelect([start, d]);
|
|
5064
5185
|
};
|
|
5065
5186
|
const GRID_COLS = "grid grid-cols-[repeat(7,var(--cmp-datepicker-calendar-day-width))]";
|
|
@@ -5194,8 +5315,11 @@ function SDateRangePicker({
|
|
|
5194
5315
|
const portalContainer = usePortalContainer();
|
|
5195
5316
|
const [open, setOpen] = useState(false);
|
|
5196
5317
|
const [ruleError, setRuleError] = useState("");
|
|
5318
|
+
const [pendingStart, setPendingStart] = useState(null);
|
|
5197
5319
|
const hasValue = value != null && value[0] !== "" && value[1] !== "";
|
|
5198
|
-
const
|
|
5320
|
+
const hasDisplay = pendingStart != null || hasValue;
|
|
5321
|
+
const startText = pendingStart ?? (hasValue ? value[0] : "");
|
|
5322
|
+
const endText = pendingStart ? "" : hasValue ? value[1] : "";
|
|
5199
5323
|
useFormField({
|
|
5200
5324
|
name,
|
|
5201
5325
|
validate: () => {
|
|
@@ -5209,6 +5333,7 @@ function SDateRangePicker({
|
|
|
5209
5333
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
5210
5334
|
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 };
|
|
5211
5335
|
const select = (r) => {
|
|
5336
|
+
setPendingStart(null);
|
|
5212
5337
|
onValueChange?.(r);
|
|
5213
5338
|
if (rules && rules.length > 0) setRuleError(runRules(r, rules));
|
|
5214
5339
|
setOpen(false);
|
|
@@ -5233,61 +5358,80 @@ function SDateRangePicker({
|
|
|
5233
5358
|
disabled,
|
|
5234
5359
|
className,
|
|
5235
5360
|
style,
|
|
5236
|
-
children: /* @__PURE__ */ jsxs(
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
{
|
|
5249
|
-
name: "date",
|
|
5250
|
-
size: dims.icon,
|
|
5251
|
-
color: disabled ? "var(--cmp-datepicker-icon-disabled)" : "var(--cmp-datepicker-icon-default)",
|
|
5252
|
-
className: "flex-shrink-0"
|
|
5253
|
-
}
|
|
5254
|
-
),
|
|
5255
|
-
/* @__PURE__ */ jsx(
|
|
5256
|
-
"span",
|
|
5257
|
-
{
|
|
5258
|
-
className: "flex-1 truncate text-center",
|
|
5259
|
-
style: {
|
|
5260
|
-
minWidth: dims.minW,
|
|
5261
|
-
fontSize: dims.fontSize,
|
|
5262
|
-
lineHeight: `${dims.lineHeight}px`,
|
|
5263
|
-
color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasValue ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
|
|
5264
|
-
},
|
|
5265
|
-
children: display
|
|
5266
|
-
}
|
|
5267
|
-
)
|
|
5268
|
-
]
|
|
5269
|
-
}
|
|
5270
|
-
) }),
|
|
5271
|
-
/* @__PURE__ */ jsx(RPopover.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
5272
|
-
RPopover.Content,
|
|
5273
|
-
{
|
|
5274
|
-
side: "bottom",
|
|
5275
|
-
align: "start",
|
|
5276
|
-
sideOffset: 4,
|
|
5277
|
-
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
5278
|
-
children: /* @__PURE__ */ jsx(
|
|
5279
|
-
RangeCalendar,
|
|
5361
|
+
children: /* @__PURE__ */ jsxs(
|
|
5362
|
+
RPopover2.Root,
|
|
5363
|
+
{
|
|
5364
|
+
open,
|
|
5365
|
+
onOpenChange: (o) => {
|
|
5366
|
+
if (disabled) return;
|
|
5367
|
+
setOpen(o);
|
|
5368
|
+
if (!o) setPendingStart(null);
|
|
5369
|
+
},
|
|
5370
|
+
children: [
|
|
5371
|
+
/* @__PURE__ */ jsx(RPopover2.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
5372
|
+
"button",
|
|
5280
5373
|
{
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5374
|
+
type: "button",
|
|
5375
|
+
name,
|
|
5376
|
+
disabled,
|
|
5377
|
+
className: "flex h-full w-full items-center overflow-hidden bg-transparent outline-none disabled:cursor-not-allowed",
|
|
5378
|
+
style: { padding: `0 ${dims.padX}px`, gap: dims.gap, borderRadius: dims.radius },
|
|
5379
|
+
children: [
|
|
5380
|
+
/* @__PURE__ */ jsx(
|
|
5381
|
+
SIcon,
|
|
5382
|
+
{
|
|
5383
|
+
name: "date",
|
|
5384
|
+
size: dims.icon,
|
|
5385
|
+
color: disabled ? "var(--cmp-datepicker-icon-disabled)" : "var(--cmp-datepicker-icon-default)",
|
|
5386
|
+
className: "flex-shrink-0"
|
|
5387
|
+
}
|
|
5388
|
+
),
|
|
5389
|
+
/* @__PURE__ */ jsx(
|
|
5390
|
+
"span",
|
|
5391
|
+
{
|
|
5392
|
+
className: cn(
|
|
5393
|
+
"flex-1 items-center",
|
|
5394
|
+
hasDisplay ? "flex" : "block truncate text-center"
|
|
5395
|
+
),
|
|
5396
|
+
style: {
|
|
5397
|
+
minWidth: dims.minW,
|
|
5398
|
+
fontSize: dims.fontSize,
|
|
5399
|
+
lineHeight: `${dims.lineHeight}px`,
|
|
5400
|
+
color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasDisplay ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
|
|
5401
|
+
},
|
|
5402
|
+
children: hasDisplay ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5403
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-right", children: startText }),
|
|
5404
|
+
/* @__PURE__ */ jsx("span", { className: "px-[4px]", children: "~" }),
|
|
5405
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-left", children: endText })
|
|
5406
|
+
] }) : placeholder
|
|
5407
|
+
}
|
|
5408
|
+
)
|
|
5409
|
+
]
|
|
5286
5410
|
}
|
|
5287
|
-
)
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5411
|
+
) }),
|
|
5412
|
+
/* @__PURE__ */ jsx(RPopover2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
5413
|
+
RPopover2.Content,
|
|
5414
|
+
{
|
|
5415
|
+
side: "bottom",
|
|
5416
|
+
align: "start",
|
|
5417
|
+
sideOffset: 4,
|
|
5418
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
5419
|
+
children: /* @__PURE__ */ jsx(
|
|
5420
|
+
RangeCalendar,
|
|
5421
|
+
{
|
|
5422
|
+
value: value ?? null,
|
|
5423
|
+
selectable,
|
|
5424
|
+
maxRange,
|
|
5425
|
+
onSelect: select,
|
|
5426
|
+
onPendingStartChange: setPendingStart,
|
|
5427
|
+
onViewChange
|
|
5428
|
+
}
|
|
5429
|
+
)
|
|
5430
|
+
}
|
|
5431
|
+
) })
|
|
5432
|
+
]
|
|
5433
|
+
}
|
|
5434
|
+
)
|
|
5291
5435
|
}
|
|
5292
5436
|
);
|
|
5293
5437
|
}
|
|
@@ -5296,7 +5440,7 @@ var SChip = forwardRef(function SChip2({
|
|
|
5296
5440
|
value = "",
|
|
5297
5441
|
error: errorProp = false,
|
|
5298
5442
|
disabled = false,
|
|
5299
|
-
editable =
|
|
5443
|
+
editable = false,
|
|
5300
5444
|
showRemove = true,
|
|
5301
5445
|
placeholder = "",
|
|
5302
5446
|
rules,
|
|
@@ -5449,6 +5593,7 @@ function SFilePicker({
|
|
|
5449
5593
|
hovered = false,
|
|
5450
5594
|
inline = false,
|
|
5451
5595
|
multiple = false,
|
|
5596
|
+
useMultipleListBox = false,
|
|
5452
5597
|
accept,
|
|
5453
5598
|
maxFileSize,
|
|
5454
5599
|
maxTotalSize,
|
|
@@ -5474,10 +5619,13 @@ function SFilePicker({
|
|
|
5474
5619
|
const autoId = useId();
|
|
5475
5620
|
const resolvedName = name ?? autoId;
|
|
5476
5621
|
const inputRef = useRef(null);
|
|
5622
|
+
const contentBoxRef = useRef(null);
|
|
5477
5623
|
const [ruleError, setRuleError] = useState("");
|
|
5624
|
+
const [listOpen, setListOpen] = useState(false);
|
|
5625
|
+
const portalContainer = usePortalContainer();
|
|
5478
5626
|
const files = multiple ? Array.isArray(value) ? value : [] : value && !Array.isArray(value) ? value : null;
|
|
5479
|
-
const
|
|
5480
|
-
const displayText =
|
|
5627
|
+
const hasFiles = multiple ? files.length > 0 : !!files;
|
|
5628
|
+
const displayText = !hasFiles ? placeholder : multiple ? files.map((f) => f.name).join(", ") : files.name;
|
|
5481
5629
|
useFormField({
|
|
5482
5630
|
name,
|
|
5483
5631
|
validate: () => {
|
|
@@ -5528,10 +5676,12 @@ function SFilePicker({
|
|
|
5528
5676
|
e.stopPropagation();
|
|
5529
5677
|
if (disabled) return;
|
|
5530
5678
|
onValueChange?.(multiple ? [] : null);
|
|
5679
|
+
setListOpen(false);
|
|
5531
5680
|
};
|
|
5532
5681
|
const removeChip = (i) => {
|
|
5533
5682
|
const next = files.filter((_, idx) => idx !== i);
|
|
5534
5683
|
onValueChange?.(next);
|
|
5684
|
+
if (next.length === 0) setListOpen(false);
|
|
5535
5685
|
};
|
|
5536
5686
|
const open = () => {
|
|
5537
5687
|
if (!disabled) inputRef.current?.click();
|
|
@@ -5541,78 +5691,100 @@ function SFilePicker({
|
|
|
5541
5691
|
const padX = size === "md" ? "var(--cmp-filepicker-md-paddingX)" : "var(--cmp-filepicker-sm-paddingX)";
|
|
5542
5692
|
const iconSize = size === "md" ? 20 : 16;
|
|
5543
5693
|
const gapCls = size === "md" ? "gap-[var(--cmp-filepicker-md-gap)]" : "gap-[var(--cmp-filepicker-sm-gap)]";
|
|
5544
|
-
const
|
|
5694
|
+
const inlinePlaceholder = inline && !disabled && !hasFiles;
|
|
5695
|
+
const showListbox = multiple && useMultipleListBox;
|
|
5696
|
+
const filesArr = multiple ? files : [];
|
|
5697
|
+
const contentInner = /* @__PURE__ */ jsxs(
|
|
5698
|
+
"div",
|
|
5699
|
+
{
|
|
5700
|
+
ref: contentBoxRef,
|
|
5701
|
+
className: cn("group/filepicker flex h-full w-full items-center", gapCls),
|
|
5702
|
+
style: { padding: inline ? 0 : `0 ${padX}` },
|
|
5703
|
+
children: [
|
|
5704
|
+
/* @__PURE__ */ jsx(
|
|
5705
|
+
"input",
|
|
5706
|
+
{
|
|
5707
|
+
ref: inputRef,
|
|
5708
|
+
type: "file",
|
|
5709
|
+
className: "hidden",
|
|
5710
|
+
disabled,
|
|
5711
|
+
multiple,
|
|
5712
|
+
accept,
|
|
5713
|
+
name: resolvedName,
|
|
5714
|
+
onChange,
|
|
5715
|
+
"aria-label": placeholder
|
|
5716
|
+
}
|
|
5717
|
+
),
|
|
5718
|
+
/* @__PURE__ */ jsxs(
|
|
5719
|
+
"button",
|
|
5720
|
+
{
|
|
5721
|
+
type: "button",
|
|
5722
|
+
disabled,
|
|
5723
|
+
onClick: open,
|
|
5724
|
+
"aria-label": placeholder,
|
|
5725
|
+
className: cn(
|
|
5726
|
+
"flex min-w-0 flex-1 items-center bg-transparent text-left",
|
|
5727
|
+
gapCls,
|
|
5728
|
+
disabled ? "cursor-not-allowed" : "cursor-pointer"
|
|
5729
|
+
),
|
|
5730
|
+
children: [
|
|
5731
|
+
/* @__PURE__ */ jsx(
|
|
5732
|
+
SIcon,
|
|
5733
|
+
{
|
|
5734
|
+
name: "attachFile",
|
|
5735
|
+
size: iconSize,
|
|
5736
|
+
color: disabled ? "var(--cmp-filepicker-icon-disabled)" : "var(--color-grey-65)"
|
|
5737
|
+
}
|
|
5738
|
+
),
|
|
5739
|
+
/* @__PURE__ */ jsx(
|
|
5740
|
+
"span",
|
|
5741
|
+
{
|
|
5742
|
+
className: cn(
|
|
5743
|
+
"min-w-0 flex-1 truncate text-[12px]",
|
|
5744
|
+
inlinePlaceholder && "text-[color:var(--cmp-filepicker-text-placeholder)] transition-colors group-hover/filepicker:text-[color:var(--cmp-filepicker-text-default)]"
|
|
5745
|
+
),
|
|
5746
|
+
style: inlinePlaceholder ? void 0 : {
|
|
5747
|
+
color: disabled ? "var(--cmp-filepicker-text-disabled)" : hasFiles ? "var(--cmp-filepicker-text-default)" : "var(--cmp-filepicker-text-placeholder)"
|
|
5748
|
+
},
|
|
5749
|
+
children: displayText
|
|
5750
|
+
}
|
|
5751
|
+
)
|
|
5752
|
+
]
|
|
5753
|
+
}
|
|
5754
|
+
),
|
|
5755
|
+
showListbox && hasFiles && !disabled && /* @__PURE__ */ jsx(
|
|
5756
|
+
Ariakit.PopoverDisclosure,
|
|
5757
|
+
{
|
|
5758
|
+
render: /* @__PURE__ */ jsx(SGhostButton, { icon: "caretDown", size: "xxs", ariaLabel: "toggle file list" }),
|
|
5759
|
+
className: cn("shrink-0 transition-transform duration-150", listOpen && "rotate-180")
|
|
5760
|
+
}
|
|
5761
|
+
),
|
|
5762
|
+
!disabled && hasFiles && /* @__PURE__ */ jsx(SGhostButton, { icon: "close", size: "xxs", ariaLabel: "clear", onClick: clear })
|
|
5763
|
+
]
|
|
5764
|
+
}
|
|
5765
|
+
);
|
|
5766
|
+
const content = showListbox ? /* @__PURE__ */ jsxs(Ariakit.PopoverProvider, { open: listOpen, setOpen: setListOpen, placement: "bottom-start", children: [
|
|
5767
|
+
contentInner,
|
|
5545
5768
|
/* @__PURE__ */ jsx(
|
|
5546
|
-
|
|
5547
|
-
{
|
|
5548
|
-
ref: inputRef,
|
|
5549
|
-
type: "file",
|
|
5550
|
-
className: "hidden",
|
|
5551
|
-
disabled,
|
|
5552
|
-
multiple,
|
|
5553
|
-
accept,
|
|
5554
|
-
name: resolvedName,
|
|
5555
|
-
onChange,
|
|
5556
|
-
"aria-label": placeholder
|
|
5557
|
-
}
|
|
5558
|
-
),
|
|
5559
|
-
/* @__PURE__ */ jsxs(
|
|
5560
|
-
"button",
|
|
5769
|
+
Ariakit.Popover,
|
|
5561
5770
|
{
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
),
|
|
5571
|
-
children: [
|
|
5572
|
-
/* @__PURE__ */ jsx(
|
|
5573
|
-
SIcon,
|
|
5574
|
-
{
|
|
5575
|
-
name: "attachFile",
|
|
5576
|
-
size: iconSize,
|
|
5577
|
-
color: disabled ? "var(--cmp-filepicker-icon-disabled)" : "var(--color-grey-65)"
|
|
5578
|
-
}
|
|
5579
|
-
),
|
|
5580
|
-
/* @__PURE__ */ jsx(
|
|
5581
|
-
"span",
|
|
5582
|
-
{
|
|
5583
|
-
className: "min-w-0 flex-1 truncate text-[12px]",
|
|
5584
|
-
style: {
|
|
5585
|
-
color: disabled ? "var(--cmp-filepicker-text-disabled)" : hasSingle ? "var(--cmp-filepicker-text-default)" : "var(--cmp-filepicker-text-placeholder)"
|
|
5586
|
-
},
|
|
5587
|
-
children: displayText
|
|
5588
|
-
}
|
|
5589
|
-
)
|
|
5590
|
-
]
|
|
5771
|
+
portal: true,
|
|
5772
|
+
portalElement: portalContainer,
|
|
5773
|
+
gutter: 4,
|
|
5774
|
+
unmountOnHide: true,
|
|
5775
|
+
getAnchorRect: () => contentBoxRef.current?.getBoundingClientRect() ?? null,
|
|
5776
|
+
style: { minWidth: contentBoxRef.current?.offsetWidth },
|
|
5777
|
+
className: "z-50 box-border flex flex-col items-stretch gap-[8px] rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] p-[8px] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.1)]",
|
|
5778
|
+
children: filesArr.map((f, i) => /* @__PURE__ */ jsx(SChip, { value: f.name, editable: false, onRemove: () => removeChip(i) }, i))
|
|
5591
5779
|
}
|
|
5592
|
-
)
|
|
5593
|
-
|
|
5594
|
-
] });
|
|
5595
|
-
const chips = multiple && files.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-[8px] flex flex-wrap gap-[8px]", children: files.map((f, i) => /* @__PURE__ */ jsx(SChip, { value: f.name, editable: false, onRemove: () => removeChip(i) }, i)) });
|
|
5596
|
-
if (inline) {
|
|
5597
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("inline-flex flex-col", className), style, children: [
|
|
5598
|
-
/* @__PURE__ */ jsx(
|
|
5599
|
-
"div",
|
|
5600
|
-
{
|
|
5601
|
-
className: "box-border flex items-center rounded-[var(--cmp-filepicker-sm-radius)] border border-solid border-[color:var(--cmp-filepicker-border-default)] bg-[var(--cmp-filepicker-bg-default)]",
|
|
5602
|
-
style: {
|
|
5603
|
-
height: "var(--cmp-filepicker-sm-height)",
|
|
5604
|
-
width: typeof width === "number" ? `${width}px` : width
|
|
5605
|
-
},
|
|
5606
|
-
children: content
|
|
5607
|
-
}
|
|
5608
|
-
),
|
|
5609
|
-
chips
|
|
5610
|
-
] });
|
|
5611
|
-
}
|
|
5780
|
+
)
|
|
5781
|
+
] }) : contentInner;
|
|
5782
|
+
const chips = multiple && !useMultipleListBox && filesArr.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-[8px] flex flex-wrap gap-[8px]", children: filesArr.map((f, i) => /* @__PURE__ */ jsx(SChip, { value: f.name, editable: false, onRemove: () => removeChip(i) }, i)) });
|
|
5612
5783
|
return /* @__PURE__ */ jsxs("div", { className, style, children: [
|
|
5613
5784
|
/* @__PURE__ */ jsx(
|
|
5614
5785
|
SField,
|
|
5615
5786
|
{
|
|
5787
|
+
borderless: inline,
|
|
5616
5788
|
label,
|
|
5617
5789
|
labelWidth,
|
|
5618
5790
|
icon,
|
|
@@ -5640,6 +5812,7 @@ function SKeyValueTable({
|
|
|
5640
5812
|
fields = [],
|
|
5641
5813
|
search = false,
|
|
5642
5814
|
radius = "default",
|
|
5815
|
+
dense = false,
|
|
5643
5816
|
onChange,
|
|
5644
5817
|
onSearch,
|
|
5645
5818
|
className,
|
|
@@ -5647,6 +5820,8 @@ function SKeyValueTable({
|
|
|
5647
5820
|
}) {
|
|
5648
5821
|
if (fields.length === 0) return null;
|
|
5649
5822
|
const emit = (name, value) => onChange?.({ name, value });
|
|
5823
|
+
const cellHeight = dense ? "var(--cmp-table-body-dense-height)" : "var(--cmp-table-keyValue-height)";
|
|
5824
|
+
const cellPadY = dense ? "var(--cmp-table-body-paddingY-dense)" : "var(--cmp-table-keyValue-body-paddingY)";
|
|
5650
5825
|
const renderField = (f) => {
|
|
5651
5826
|
if (f.render) return f.render;
|
|
5652
5827
|
const opt = f.options ?? {};
|
|
@@ -5727,10 +5902,15 @@ function SKeyValueTable({
|
|
|
5727
5902
|
rowSpan: f.thRowSpan && f.thRowSpan > 1 ? f.thRowSpan : void 0,
|
|
5728
5903
|
colSpan: f.thColSpan && f.thColSpan > 1 ? f.thColSpan : void 0,
|
|
5729
5904
|
className: cn(
|
|
5730
|
-
"
|
|
5905
|
+
"box-border bg-[var(--cmp-table-header-bg)] px-[var(--cmp-table-header-paddingX)] text-left align-middle",
|
|
5731
5906
|
cellBorder,
|
|
5732
5907
|
f.thClass
|
|
5733
5908
|
),
|
|
5909
|
+
style: {
|
|
5910
|
+
height: cellHeight,
|
|
5911
|
+
paddingTop: cellPadY,
|
|
5912
|
+
paddingBottom: cellPadY
|
|
5913
|
+
},
|
|
5734
5914
|
children: /* @__PURE__ */ jsxs("div", { className: "flex h-full w-full items-center justify-between gap-[var(--cmp-table-header-gap)]", children: [
|
|
5735
5915
|
/* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-[8px]", children: [
|
|
5736
5916
|
/* @__PURE__ */ jsx("span", { className: "text-[12px] font-bold leading-[20px] text-[color:var(--sys-color-fg-primary)]", children: f.label }),
|
|
@@ -5756,10 +5936,11 @@ function SKeyValueTable({
|
|
|
5756
5936
|
rowSpan: f.tdRowSpan && f.tdRowSpan > 1 ? f.tdRowSpan : void 0,
|
|
5757
5937
|
colSpan: f.tdColSpan && f.tdColSpan > 1 ? f.tdColSpan : void 0,
|
|
5758
5938
|
className: cn(
|
|
5759
|
-
"
|
|
5939
|
+
"box-border bg-[var(--sys-color-bg-frame)] px-[var(--cmp-table-keyValue-body-paddingX-default)] align-middle",
|
|
5760
5940
|
cellBorder,
|
|
5761
5941
|
f.tdClass
|
|
5762
5942
|
),
|
|
5943
|
+
style: { height: cellHeight, paddingTop: cellPadY, paddingBottom: cellPadY },
|
|
5763
5944
|
children: renderField(f)
|
|
5764
5945
|
},
|
|
5765
5946
|
`td-${r}-${c}`
|