sellmate-design-system-react 0.1.9 → 0.1.11
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 +3 -1
- package/dist/components/SActionModal/SActionModal.cjs.map +1 -1
- package/dist/components/SActionModal/SActionModal.js +3 -1
- package/dist/components/SActionModal/SActionModal.js.map +1 -1
- package/dist/components/SBarcodeInput/SBarcodeInput.cjs +16 -3
- package/dist/components/SBarcodeInput/SBarcodeInput.cjs.map +1 -1
- package/dist/components/SBarcodeInput/SBarcodeInput.d.ts +3 -1
- package/dist/components/SBarcodeInput/SBarcodeInput.js +16 -3
- package/dist/components/SBarcodeInput/SBarcodeInput.js.map +1 -1
- package/dist/components/SCalendar/SCalendar.cjs +2 -0
- package/dist/components/SCalendar/SCalendar.cjs.map +1 -1
- package/dist/components/SCalendar/SCalendar.js +2 -0
- package/dist/components/SCalendar/SCalendar.js.map +1 -1
- package/dist/components/SChip/SChip.cjs +2 -0
- package/dist/components/SChip/SChip.cjs.map +1 -1
- package/dist/components/SChip/SChip.js +2 -0
- package/dist/components/SChip/SChip.js.map +1 -1
- package/dist/components/SChipInput/SChipInput.cjs +22 -4
- package/dist/components/SChipInput/SChipInput.cjs.map +1 -1
- package/dist/components/SChipInput/SChipInput.d.ts +5 -0
- package/dist/components/SChipInput/SChipInput.js +22 -4
- package/dist/components/SChipInput/SChipInput.js.map +1 -1
- package/dist/components/SChipInput/index.d.ts +1 -1
- package/dist/components/SCircleProgress/SCircleProgress.cjs +69 -50
- package/dist/components/SCircleProgress/SCircleProgress.cjs.map +1 -1
- package/dist/components/SCircleProgress/SCircleProgress.d.ts +2 -0
- package/dist/components/SCircleProgress/SCircleProgress.js +69 -50
- package/dist/components/SCircleProgress/SCircleProgress.js.map +1 -1
- package/dist/components/SConfirmModal/SConfirmModal.cjs +13 -10
- package/dist/components/SConfirmModal/SConfirmModal.cjs.map +1 -1
- package/dist/components/SConfirmModal/SConfirmModal.d.ts +7 -4
- package/dist/components/SConfirmModal/SConfirmModal.js +13 -10
- package/dist/components/SConfirmModal/SConfirmModal.js.map +1 -1
- package/dist/components/SDatePicker/SDatePicker.cjs +16 -3
- package/dist/components/SDatePicker/SDatePicker.cjs.map +1 -1
- package/dist/components/SDatePicker/SDatePicker.d.ts +3 -1
- package/dist/components/SDatePicker/SDatePicker.js +16 -3
- package/dist/components/SDatePicker/SDatePicker.js.map +1 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.cjs +16 -3
- package/dist/components/SDateRangePicker/SDateRangePicker.cjs.map +1 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.d.ts +3 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.js +16 -3
- package/dist/components/SDateRangePicker/SDateRangePicker.js.map +1 -1
- package/dist/components/SDropdownButton/SDropdownButton.cjs +2 -0
- package/dist/components/SDropdownButton/SDropdownButton.cjs.map +1 -1
- package/dist/components/SDropdownButton/SDropdownButton.js +2 -0
- package/dist/components/SDropdownButton/SDropdownButton.js.map +1 -1
- package/dist/components/SField/SField.cjs +14 -3
- package/dist/components/SField/SField.cjs.map +1 -1
- package/dist/components/SField/SField.d.ts +4 -1
- package/dist/components/SField/SField.js +14 -3
- package/dist/components/SField/SField.js.map +1 -1
- package/dist/components/SFilePicker/SFilePicker.cjs +51 -19
- package/dist/components/SFilePicker/SFilePicker.cjs.map +1 -1
- package/dist/components/SFilePicker/SFilePicker.d.ts +4 -2
- package/dist/components/SFilePicker/SFilePicker.js +50 -19
- package/dist/components/SFilePicker/SFilePicker.js.map +1 -1
- package/dist/components/SGhostButton/SGhostButton.cjs +2 -0
- package/dist/components/SGhostButton/SGhostButton.cjs.map +1 -1
- package/dist/components/SGhostButton/SGhostButton.js +2 -0
- package/dist/components/SGhostButton/SGhostButton.js.map +1 -1
- package/dist/components/SGuide/SGuide.cjs +2 -0
- package/dist/components/SGuide/SGuide.cjs.map +1 -1
- package/dist/components/SGuide/SGuide.js +2 -0
- package/dist/components/SGuide/SGuide.js.map +1 -1
- package/dist/components/SInput/SInput.cjs +16 -3
- package/dist/components/SInput/SInput.cjs.map +1 -1
- package/dist/components/SInput/SInput.d.ts +4 -1
- package/dist/components/SInput/SInput.js +16 -3
- package/dist/components/SInput/SInput.js.map +1 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.cjs +530 -219
- package/dist/components/SKeyValueTable/SKeyValueTable.cjs.map +1 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.d.ts +27 -6
- package/dist/components/SKeyValueTable/SKeyValueTable.js +529 -218
- package/dist/components/SKeyValueTable/SKeyValueTable.js.map +1 -1
- package/dist/components/SLoadingContainer/SLoadingContainer.cjs +69 -50
- package/dist/components/SLoadingContainer/SLoadingContainer.cjs.map +1 -1
- package/dist/components/SLoadingContainer/SLoadingContainer.js +69 -50
- package/dist/components/SLoadingContainer/SLoadingContainer.js.map +1 -1
- package/dist/components/SLoadingContainer/loading.cjs +69 -50
- package/dist/components/SLoadingContainer/loading.cjs.map +1 -1
- package/dist/components/SLoadingContainer/loading.js +69 -50
- package/dist/components/SLoadingContainer/loading.js.map +1 -1
- package/dist/components/SLoadingModal/SLoadingModal.cjs +75 -51
- package/dist/components/SLoadingModal/SLoadingModal.cjs.map +1 -1
- package/dist/components/SLoadingModal/SLoadingModal.d.ts +3 -1
- package/dist/components/SLoadingModal/SLoadingModal.js +75 -51
- package/dist/components/SLoadingModal/SLoadingModal.js.map +1 -1
- package/dist/components/SModalContainer/SModalContainer.cjs +3 -1
- package/dist/components/SModalContainer/SModalContainer.cjs.map +1 -1
- package/dist/components/SModalContainer/SModalContainer.js +3 -1
- package/dist/components/SModalContainer/SModalContainer.js.map +1 -1
- package/dist/components/SNumberInput/SNumberInput.cjs +16 -3
- package/dist/components/SNumberInput/SNumberInput.cjs.map +1 -1
- package/dist/components/SNumberInput/SNumberInput.d.ts +2 -0
- package/dist/components/SNumberInput/SNumberInput.js +16 -3
- package/dist/components/SNumberInput/SNumberInput.js.map +1 -1
- package/dist/components/SPopover/SPopover.cjs +2 -0
- package/dist/components/SPopover/SPopover.cjs.map +1 -1
- package/dist/components/SPopover/SPopover.js +2 -0
- package/dist/components/SPopover/SPopover.js.map +1 -1
- package/dist/components/SPortal/SPortal.cjs +2 -0
- package/dist/components/SPortal/SPortal.cjs.map +1 -1
- package/dist/components/SPortal/SPortal.js +2 -0
- package/dist/components/SPortal/SPortal.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 +530 -258
- package/dist/components/SSelect/SSelect.cjs.map +1 -1
- package/dist/components/SSelect/SSelect.d.ts +4 -2
- package/dist/components/SSelect/SSelect.js +531 -258
- package/dist/components/SSelect/SSelect.js.map +1 -1
- package/dist/components/STable/STable.cjs +603 -309
- package/dist/components/STable/STable.cjs.map +1 -1
- package/dist/components/STable/STable.js +604 -309
- package/dist/components/STable/STable.js.map +1 -1
- package/dist/components/STextLink/STextLink.cjs +2 -0
- package/dist/components/STextLink/STextLink.cjs.map +1 -1
- package/dist/components/STextLink/STextLink.js +2 -0
- package/dist/components/STextLink/STextLink.js.map +1 -1
- package/dist/components/STextarea/STextarea.cjs +16 -3
- package/dist/components/STextarea/STextarea.cjs.map +1 -1
- package/dist/components/STextarea/STextarea.d.ts +2 -0
- package/dist/components/STextarea/STextarea.js +16 -3
- package/dist/components/STextarea/STextarea.js.map +1 -1
- package/dist/components/SToast/SToast.cjs +2 -0
- package/dist/components/SToast/SToast.cjs.map +1 -1
- package/dist/components/SToast/SToast.js +2 -0
- package/dist/components/SToast/SToast.js.map +1 -1
- package/dist/components/SToast/SToastContainer.cjs +2 -0
- package/dist/components/SToast/SToastContainer.cjs.map +1 -1
- package/dist/components/SToast/SToastContainer.js +2 -0
- package/dist/components/SToast/SToastContainer.js.map +1 -1
- package/dist/components/STooltip/STooltip.cjs +3 -1
- package/dist/components/STooltip/STooltip.cjs.map +1 -1
- package/dist/components/STooltip/STooltip.js +3 -1
- package/dist/components/STooltip/STooltip.js.map +1 -1
- package/dist/index.cjs +522 -248
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +523 -248
- package/dist/index.js.map +1 -1
- package/dist/lib/portal-container.d.ts +7 -0
- package/dist/styles.css +123 -58
- package/dist/theme.css +45 -21
- package/package.json +1 -1
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { forwardRef, createContext, useState, useRef, useImperativeHandle, useMemo,
|
|
2
|
+
import { forwardRef, createContext, useState, useRef, useImperativeHandle, useMemo, useEffect, useId, useCallback, useContext } from 'react';
|
|
3
3
|
import { clsx } from 'clsx';
|
|
4
4
|
import { extendTailwindMerge } from 'tailwind-merge';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
import * as RCheckbox from '@radix-ui/react-checkbox';
|
|
7
|
-
import * as Ariakit from '@ariakit/react';
|
|
8
7
|
import * as RPopover2 from '@radix-ui/react-popover';
|
|
9
8
|
|
|
10
9
|
var twMerge = extendTailwindMerge({
|
|
@@ -2935,12 +2934,35 @@ var COLOR_MAP = {
|
|
|
2935
2934
|
};
|
|
2936
2935
|
var clamp = (v) => Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;
|
|
2937
2936
|
var SCircleProgress = forwardRef(
|
|
2938
|
-
function SCircleProgress2({
|
|
2937
|
+
function SCircleProgress2({
|
|
2938
|
+
value = 0,
|
|
2939
|
+
type = "primary",
|
|
2940
|
+
indeterminate = false,
|
|
2941
|
+
label,
|
|
2942
|
+
innerValue = false,
|
|
2943
|
+
className,
|
|
2944
|
+
style
|
|
2945
|
+
}, ref) {
|
|
2939
2946
|
const v = clamp(value);
|
|
2940
2947
|
const colors = COLOR_MAP[type];
|
|
2941
2948
|
const c = VIEWBOX / 2;
|
|
2942
2949
|
const percentColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : colors.arc;
|
|
2943
2950
|
const filled = v / 100 * CIRCUMFERENCE;
|
|
2951
|
+
const showPercent = !indeterminate;
|
|
2952
|
+
const percentNode = /* @__PURE__ */ jsxs(
|
|
2953
|
+
"span",
|
|
2954
|
+
{
|
|
2955
|
+
className: cn(
|
|
2956
|
+
"text-center text-[16px] font-bold leading-[26px]",
|
|
2957
|
+
innerValue && "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2"
|
|
2958
|
+
),
|
|
2959
|
+
style: { color: percentColor },
|
|
2960
|
+
children: [
|
|
2961
|
+
Math.round(v),
|
|
2962
|
+
"%"
|
|
2963
|
+
]
|
|
2964
|
+
}
|
|
2965
|
+
);
|
|
2944
2966
|
return /* @__PURE__ */ jsxs(
|
|
2945
2967
|
"div",
|
|
2946
2968
|
{
|
|
@@ -2951,57 +2973,53 @@ var SCircleProgress = forwardRef(
|
|
|
2951
2973
|
),
|
|
2952
2974
|
style,
|
|
2953
2975
|
children: [
|
|
2954
|
-
/* @__PURE__ */ jsxs(
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
"circle"
|
|
2963
|
-
{
|
|
2964
|
-
cx: c,
|
|
2965
|
-
cy: c,
|
|
2966
|
-
r: RADIUS,
|
|
2967
|
-
fill: "none",
|
|
2968
|
-
strokeWidth: STROKE,
|
|
2969
|
-
style: { stroke: colors.track }
|
|
2970
|
-
}
|
|
2976
|
+
/* @__PURE__ */ jsxs("div", { className: cn(innerValue && "relative"), children: [
|
|
2977
|
+
/* @__PURE__ */ jsxs(
|
|
2978
|
+
"svg",
|
|
2979
|
+
{
|
|
2980
|
+
viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
|
|
2981
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2982
|
+
className: cn(
|
|
2983
|
+
"h-[80px] w-[80px]",
|
|
2984
|
+
indeterminate && "origin-center animate-circle-spin"
|
|
2971
2985
|
),
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
"origin-center",
|
|
2983
|
-
indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
|
|
2984
|
-
),
|
|
2985
|
-
style: {
|
|
2986
|
-
stroke: colors.arc,
|
|
2987
|
-
...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
|
|
2986
|
+
children: [
|
|
2987
|
+
/* @__PURE__ */ jsx(
|
|
2988
|
+
"circle",
|
|
2989
|
+
{
|
|
2990
|
+
cx: c,
|
|
2991
|
+
cy: c,
|
|
2992
|
+
r: RADIUS,
|
|
2993
|
+
fill: "none",
|
|
2994
|
+
strokeWidth: STROKE,
|
|
2995
|
+
style: { stroke: colors.track }
|
|
2988
2996
|
}
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
2997
|
+
),
|
|
2998
|
+
/* @__PURE__ */ jsx(
|
|
2999
|
+
"circle",
|
|
3000
|
+
{
|
|
3001
|
+
cx: c,
|
|
3002
|
+
cy: c,
|
|
3003
|
+
r: RADIUS,
|
|
3004
|
+
fill: "none",
|
|
3005
|
+
strokeWidth: STROKE,
|
|
3006
|
+
strokeLinecap: "round",
|
|
3007
|
+
className: cn(
|
|
3008
|
+
"origin-center",
|
|
3009
|
+
indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
|
|
3010
|
+
),
|
|
3011
|
+
style: {
|
|
3012
|
+
stroke: colors.arc,
|
|
3013
|
+
...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
3016
|
+
)
|
|
3017
|
+
]
|
|
3018
|
+
}
|
|
3019
|
+
),
|
|
3020
|
+
showPercent && innerValue && percentNode
|
|
3021
|
+
] }),
|
|
3022
|
+
showPercent && !innerValue && percentNode,
|
|
3005
3023
|
label && /* @__PURE__ */ jsx("span", { className: "text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]", children: label })
|
|
3006
3024
|
]
|
|
3007
3025
|
}
|
|
@@ -3092,10 +3110,110 @@ function SPagination({
|
|
|
3092
3110
|
);
|
|
3093
3111
|
}
|
|
3094
3112
|
var PortalContainerContext = createContext(null);
|
|
3113
|
+
var InsideModalContext = createContext(false);
|
|
3095
3114
|
PortalContainerContext.Provider;
|
|
3115
|
+
InsideModalContext.Provider;
|
|
3096
3116
|
function usePortalContainer() {
|
|
3097
3117
|
return useContext(PortalContainerContext) ?? void 0;
|
|
3098
3118
|
}
|
|
3119
|
+
function useInsideModal() {
|
|
3120
|
+
return useContext(InsideModalContext);
|
|
3121
|
+
}
|
|
3122
|
+
function runRules(value, rules) {
|
|
3123
|
+
if (!rules || rules.length === 0) return "";
|
|
3124
|
+
for (const rule of rules) {
|
|
3125
|
+
const result = rule(value ?? "");
|
|
3126
|
+
if (result !== true) return typeof result === "string" ? result : "\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uAC12\uC785\uB2C8\uB2E4.";
|
|
3127
|
+
}
|
|
3128
|
+
return "";
|
|
3129
|
+
}
|
|
3130
|
+
var FormContext = createContext(null);
|
|
3131
|
+
function useFormContext() {
|
|
3132
|
+
return useContext(FormContext);
|
|
3133
|
+
}
|
|
3134
|
+
function useFormField(field) {
|
|
3135
|
+
const ctx = useFormContext();
|
|
3136
|
+
const cbRef = useRef(field);
|
|
3137
|
+
cbRef.current = field;
|
|
3138
|
+
const name = field.name ?? "";
|
|
3139
|
+
useEffect(() => {
|
|
3140
|
+
if (!ctx) return;
|
|
3141
|
+
return ctx.register({
|
|
3142
|
+
name,
|
|
3143
|
+
validate: () => cbRef.current.validate(),
|
|
3144
|
+
resetValidation: () => cbRef.current.resetValidation()
|
|
3145
|
+
});
|
|
3146
|
+
}, [ctx, name]);
|
|
3147
|
+
}
|
|
3148
|
+
|
|
3149
|
+
// src/lib/sanitize-inline-html.ts
|
|
3150
|
+
var ALLOWED_INLINE_TAGS = /* @__PURE__ */ new Set(["A", "B", "STRONG", "I", "EM", "BR", "SPAN"]);
|
|
3151
|
+
var ALLOWED_ATTRS_BY_TAG = {
|
|
3152
|
+
A: /* @__PURE__ */ new Set(["href", "target", "rel", "class"])
|
|
3153
|
+
};
|
|
3154
|
+
var COMMON_ALLOWED_ATTRS = /* @__PURE__ */ new Set(["class"]);
|
|
3155
|
+
var SAFE_HREF_RE = /^(https?:|mailto:|tel:|\/|#|\.)/i;
|
|
3156
|
+
var DROP_CONTENT_TAGS = /* @__PURE__ */ new Set([
|
|
3157
|
+
"SCRIPT",
|
|
3158
|
+
"STYLE",
|
|
3159
|
+
"IFRAME",
|
|
3160
|
+
"OBJECT",
|
|
3161
|
+
"EMBED",
|
|
3162
|
+
"META",
|
|
3163
|
+
"LINK",
|
|
3164
|
+
"BASE",
|
|
3165
|
+
"NOSCRIPT",
|
|
3166
|
+
// SVG/MATH 는 foreign-content 파싱 모드로 전환되어 재직렬화 시 다른 트리로
|
|
3167
|
+
// 재파싱될 수 있다(mXSS 벡터). 인라인 라벨에 필요 없으므로 통째로 제거한다.
|
|
3168
|
+
"SVG",
|
|
3169
|
+
"MATH",
|
|
3170
|
+
"TEMPLATE"
|
|
3171
|
+
]);
|
|
3172
|
+
var escapeHtml = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
3173
|
+
var sanitizeNode = (node) => {
|
|
3174
|
+
if (node.nodeType === Node.COMMENT_NODE) {
|
|
3175
|
+
node.remove();
|
|
3176
|
+
return;
|
|
3177
|
+
}
|
|
3178
|
+
if (node.nodeType !== Node.ELEMENT_NODE) return;
|
|
3179
|
+
const element = node;
|
|
3180
|
+
const tagName = element.tagName;
|
|
3181
|
+
if (DROP_CONTENT_TAGS.has(tagName)) {
|
|
3182
|
+
element.remove();
|
|
3183
|
+
return;
|
|
3184
|
+
}
|
|
3185
|
+
Array.from(element.childNodes).forEach((child) => sanitizeNode(child));
|
|
3186
|
+
if (ALLOWED_INLINE_TAGS.has(tagName)) {
|
|
3187
|
+
if (element.hasAttribute("className")) {
|
|
3188
|
+
const val = element.getAttribute("className");
|
|
3189
|
+
element.removeAttribute("className");
|
|
3190
|
+
if (!element.hasAttribute("class")) element.setAttribute("class", val);
|
|
3191
|
+
}
|
|
3192
|
+
const allowedAttrs = ALLOWED_ATTRS_BY_TAG[tagName] ?? COMMON_ALLOWED_ATTRS;
|
|
3193
|
+
Array.from(element.attributes).forEach((attr) => {
|
|
3194
|
+
if (!allowedAttrs.has(attr.name)) element.removeAttribute(attr.name);
|
|
3195
|
+
});
|
|
3196
|
+
if (tagName === "A") {
|
|
3197
|
+
const href = element.getAttribute("href");
|
|
3198
|
+
if (href !== null && href !== "" && !SAFE_HREF_RE.test(href)) element.removeAttribute("href");
|
|
3199
|
+
if (element.hasAttribute("target")) {
|
|
3200
|
+
element.setAttribute("rel", "noopener noreferrer");
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
return;
|
|
3204
|
+
}
|
|
3205
|
+
const parent = element.parentNode;
|
|
3206
|
+
if (parent == null) return;
|
|
3207
|
+
while (element.firstChild) parent.insertBefore(element.firstChild, element);
|
|
3208
|
+
parent.removeChild(element);
|
|
3209
|
+
};
|
|
3210
|
+
var sanitizeInlineHtml = (value) => {
|
|
3211
|
+
if (typeof document === "undefined") return escapeHtml(value);
|
|
3212
|
+
const template = document.createElement("template");
|
|
3213
|
+
template.innerHTML = value;
|
|
3214
|
+
Array.from(template.content.childNodes).forEach((child) => sanitizeNode(child));
|
|
3215
|
+
return template.innerHTML;
|
|
3216
|
+
};
|
|
3099
3217
|
|
|
3100
3218
|
// src/lib/floating-anim.ts
|
|
3101
3219
|
var FLOATING_SLIDE_ANIM = [
|
|
@@ -3367,7 +3485,7 @@ var STooltip = forwardRef(function STooltip2({
|
|
|
3367
3485
|
if (disabled || body == null) return /* @__PURE__ */ jsx(Fragment, { children: triggerNode });
|
|
3368
3486
|
const isHover = trigger === "hover";
|
|
3369
3487
|
const contentClass = cn(
|
|
3370
|
-
"z-50 max-w-xs rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px]
|
|
3488
|
+
"z-50 max-w-xs rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px]",
|
|
3371
3489
|
FLOATING_SLIDE_ANIM,
|
|
3372
3490
|
className
|
|
3373
3491
|
);
|
|
@@ -3433,32 +3551,6 @@ var STooltip = forwardRef(function STooltip2({
|
|
|
3433
3551
|
] });
|
|
3434
3552
|
});
|
|
3435
3553
|
STooltip.displayName = "STooltip";
|
|
3436
|
-
function runRules(value, rules) {
|
|
3437
|
-
if (!rules || rules.length === 0) return "";
|
|
3438
|
-
for (const rule of rules) {
|
|
3439
|
-
const result = rule(value ?? "");
|
|
3440
|
-
if (result !== true) return typeof result === "string" ? result : "\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uAC12\uC785\uB2C8\uB2E4.";
|
|
3441
|
-
}
|
|
3442
|
-
return "";
|
|
3443
|
-
}
|
|
3444
|
-
var FormContext = createContext(null);
|
|
3445
|
-
function useFormContext() {
|
|
3446
|
-
return useContext(FormContext);
|
|
3447
|
-
}
|
|
3448
|
-
function useFormField(field) {
|
|
3449
|
-
const ctx = useFormContext();
|
|
3450
|
-
const cbRef = useRef(field);
|
|
3451
|
-
cbRef.current = field;
|
|
3452
|
-
const name = field.name ?? "";
|
|
3453
|
-
useEffect(() => {
|
|
3454
|
-
if (!ctx) return;
|
|
3455
|
-
return ctx.register({
|
|
3456
|
-
name,
|
|
3457
|
-
validate: () => cbRef.current.validate(),
|
|
3458
|
-
resetValidation: () => cbRef.current.resetValidation()
|
|
3459
|
-
});
|
|
3460
|
-
}, [ctx, name]);
|
|
3461
|
-
}
|
|
3462
3554
|
var FIELD_SIZE = {
|
|
3463
3555
|
sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon: 16 },
|
|
3464
3556
|
md: { height: 36, radius: 6, fieldGap: 16, labelGap: 8, fontSize: 14, lineHeight: 24, icon: 16 }
|
|
@@ -3473,6 +3565,7 @@ var SField = forwardRef(function SField2({
|
|
|
3473
3565
|
name,
|
|
3474
3566
|
label = "",
|
|
3475
3567
|
icon,
|
|
3568
|
+
iconColor,
|
|
3476
3569
|
labelTooltip = "",
|
|
3477
3570
|
labelTooltipProps,
|
|
3478
3571
|
labelWidth,
|
|
@@ -3550,7 +3643,15 @@ var SField = forwardRef(function SField2({
|
|
|
3550
3643
|
lineHeight: `${s.lineHeight}px`
|
|
3551
3644
|
},
|
|
3552
3645
|
children: [
|
|
3553
|
-
icon && /* @__PURE__ */ jsx(
|
|
3646
|
+
icon && /* @__PURE__ */ jsx(
|
|
3647
|
+
SIcon,
|
|
3648
|
+
{
|
|
3649
|
+
name: icon,
|
|
3650
|
+
size: s.icon,
|
|
3651
|
+
color: iconColor,
|
|
3652
|
+
style: { marginRight: s.labelGap }
|
|
3653
|
+
}
|
|
3654
|
+
),
|
|
3554
3655
|
/* @__PURE__ */ jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis whitespace-nowrap", children: label }),
|
|
3555
3656
|
(labelTooltip !== "" || labelTooltipProps) && /* @__PURE__ */ jsx("span", { className: "shrink-0", style: { marginLeft: s.labelGap }, children: /* @__PURE__ */ jsx(
|
|
3556
3657
|
STooltip,
|
|
@@ -3600,7 +3701,7 @@ var SField = forwardRef(function SField2({
|
|
|
3600
3701
|
borderBottomLeftRadius: s.radius - 1
|
|
3601
3702
|
},
|
|
3602
3703
|
children: [
|
|
3603
|
-
icon && !label && /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon }),
|
|
3704
|
+
icon && !label && /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon, color: iconColor }),
|
|
3604
3705
|
effectiveAddonLabel
|
|
3605
3706
|
]
|
|
3606
3707
|
}
|
|
@@ -3615,6 +3716,77 @@ var SField = forwardRef(function SField2({
|
|
|
3615
3716
|
}
|
|
3616
3717
|
);
|
|
3617
3718
|
});
|
|
3719
|
+
function SPortal({
|
|
3720
|
+
open,
|
|
3721
|
+
onClose,
|
|
3722
|
+
onOpenChange,
|
|
3723
|
+
anchorRef,
|
|
3724
|
+
placement = "bottom",
|
|
3725
|
+
align = "start",
|
|
3726
|
+
offset = 4,
|
|
3727
|
+
alignOffset = 0,
|
|
3728
|
+
fit = false,
|
|
3729
|
+
maxHeight,
|
|
3730
|
+
autoClose = false,
|
|
3731
|
+
persistent = false,
|
|
3732
|
+
viewportPadding = 0,
|
|
3733
|
+
onOpenAutoFocus,
|
|
3734
|
+
onCloseAutoFocus,
|
|
3735
|
+
children,
|
|
3736
|
+
className,
|
|
3737
|
+
style,
|
|
3738
|
+
ariaLabel
|
|
3739
|
+
}) {
|
|
3740
|
+
const portalContainer = usePortalContainer();
|
|
3741
|
+
return /* @__PURE__ */ jsxs(
|
|
3742
|
+
RPopover2.Root,
|
|
3743
|
+
{
|
|
3744
|
+
open,
|
|
3745
|
+
onOpenChange: (next) => {
|
|
3746
|
+
onOpenChange?.(next);
|
|
3747
|
+
if (!next) onClose?.();
|
|
3748
|
+
},
|
|
3749
|
+
children: [
|
|
3750
|
+
/* @__PURE__ */ jsx(RPopover2.Anchor, { virtualRef: anchorRef }),
|
|
3751
|
+
/* @__PURE__ */ jsx(RPopover2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
3752
|
+
RPopover2.Content,
|
|
3753
|
+
{
|
|
3754
|
+
side: placement,
|
|
3755
|
+
align,
|
|
3756
|
+
sideOffset: offset,
|
|
3757
|
+
alignOffset,
|
|
3758
|
+
collisionPadding: viewportPadding,
|
|
3759
|
+
"aria-label": ariaLabel,
|
|
3760
|
+
onPointerDownOutside: (e) => {
|
|
3761
|
+
if (persistent || anchorRef.current?.contains(e.target)) {
|
|
3762
|
+
e.preventDefault();
|
|
3763
|
+
}
|
|
3764
|
+
},
|
|
3765
|
+
onFocusOutside: (e) => {
|
|
3766
|
+
if (persistent || anchorRef.current?.contains(e.target)) {
|
|
3767
|
+
e.preventDefault();
|
|
3768
|
+
}
|
|
3769
|
+
},
|
|
3770
|
+
onEscapeKeyDown: persistent ? (e) => e.preventDefault() : void 0,
|
|
3771
|
+
onOpenAutoFocus,
|
|
3772
|
+
onCloseAutoFocus,
|
|
3773
|
+
onClick: autoClose ? () => onClose?.() : void 0,
|
|
3774
|
+
className: cn(
|
|
3775
|
+
"z-50 overflow-hidden rounded-(--cmp-listBox-radius) bg-(--cmp-listBox-bg) py-4 shadow-normal-sm",
|
|
3776
|
+
maxHeight != null && "overflow-y-auto",
|
|
3777
|
+
fit && "min-w-(--radix-popover-trigger-width)",
|
|
3778
|
+
FLOATING_SLIDE_ANIM,
|
|
3779
|
+
className
|
|
3780
|
+
),
|
|
3781
|
+
style: { maxHeight, ...style },
|
|
3782
|
+
children
|
|
3783
|
+
}
|
|
3784
|
+
) })
|
|
3785
|
+
]
|
|
3786
|
+
}
|
|
3787
|
+
);
|
|
3788
|
+
}
|
|
3789
|
+
SPortal.displayName = "SPortal";
|
|
3618
3790
|
|
|
3619
3791
|
// src/components/SSelect/select.config.ts
|
|
3620
3792
|
function flattenOptions(options, depth = 1) {
|
|
@@ -3649,75 +3821,6 @@ function flattenOptions(options, depth = 1) {
|
|
|
3649
3821
|
var selectableOptions = (flat) => flat.filter((o) => !o.isGroup && !o.disabled);
|
|
3650
3822
|
var isHtmlLabel = (label) => /<[a-z][\s\S]*>/i.test(label);
|
|
3651
3823
|
var extractText = (html) => html.replace(/<[^>]*>/g, "");
|
|
3652
|
-
|
|
3653
|
-
// src/lib/sanitize-inline-html.ts
|
|
3654
|
-
var ALLOWED_INLINE_TAGS = /* @__PURE__ */ new Set(["A", "B", "STRONG", "I", "EM", "BR", "SPAN"]);
|
|
3655
|
-
var ALLOWED_ATTRS_BY_TAG = {
|
|
3656
|
-
A: /* @__PURE__ */ new Set(["href", "target", "rel", "class"])
|
|
3657
|
-
};
|
|
3658
|
-
var COMMON_ALLOWED_ATTRS = /* @__PURE__ */ new Set(["class"]);
|
|
3659
|
-
var SAFE_HREF_RE = /^(https?:|mailto:|tel:|\/|#|\.)/i;
|
|
3660
|
-
var DROP_CONTENT_TAGS = /* @__PURE__ */ new Set([
|
|
3661
|
-
"SCRIPT",
|
|
3662
|
-
"STYLE",
|
|
3663
|
-
"IFRAME",
|
|
3664
|
-
"OBJECT",
|
|
3665
|
-
"EMBED",
|
|
3666
|
-
"META",
|
|
3667
|
-
"LINK",
|
|
3668
|
-
"BASE",
|
|
3669
|
-
"NOSCRIPT",
|
|
3670
|
-
// SVG/MATH 는 foreign-content 파싱 모드로 전환되어 재직렬화 시 다른 트리로
|
|
3671
|
-
// 재파싱될 수 있다(mXSS 벡터). 인라인 라벨에 필요 없으므로 통째로 제거한다.
|
|
3672
|
-
"SVG",
|
|
3673
|
-
"MATH",
|
|
3674
|
-
"TEMPLATE"
|
|
3675
|
-
]);
|
|
3676
|
-
var escapeHtml = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
3677
|
-
var sanitizeNode = (node) => {
|
|
3678
|
-
if (node.nodeType === Node.COMMENT_NODE) {
|
|
3679
|
-
node.remove();
|
|
3680
|
-
return;
|
|
3681
|
-
}
|
|
3682
|
-
if (node.nodeType !== Node.ELEMENT_NODE) return;
|
|
3683
|
-
const element = node;
|
|
3684
|
-
const tagName = element.tagName;
|
|
3685
|
-
if (DROP_CONTENT_TAGS.has(tagName)) {
|
|
3686
|
-
element.remove();
|
|
3687
|
-
return;
|
|
3688
|
-
}
|
|
3689
|
-
Array.from(element.childNodes).forEach((child) => sanitizeNode(child));
|
|
3690
|
-
if (ALLOWED_INLINE_TAGS.has(tagName)) {
|
|
3691
|
-
if (element.hasAttribute("className")) {
|
|
3692
|
-
const val = element.getAttribute("className");
|
|
3693
|
-
element.removeAttribute("className");
|
|
3694
|
-
if (!element.hasAttribute("class")) element.setAttribute("class", val);
|
|
3695
|
-
}
|
|
3696
|
-
const allowedAttrs = ALLOWED_ATTRS_BY_TAG[tagName] ?? COMMON_ALLOWED_ATTRS;
|
|
3697
|
-
Array.from(element.attributes).forEach((attr) => {
|
|
3698
|
-
if (!allowedAttrs.has(attr.name)) element.removeAttribute(attr.name);
|
|
3699
|
-
});
|
|
3700
|
-
if (tagName === "A") {
|
|
3701
|
-
const href = element.getAttribute("href");
|
|
3702
|
-
if (href !== null && href !== "" && !SAFE_HREF_RE.test(href)) element.removeAttribute("href");
|
|
3703
|
-
if (element.hasAttribute("target")) {
|
|
3704
|
-
element.setAttribute("rel", "noopener noreferrer");
|
|
3705
|
-
}
|
|
3706
|
-
}
|
|
3707
|
-
return;
|
|
3708
|
-
}
|
|
3709
|
-
const parent = element.parentNode;
|
|
3710
|
-
if (parent == null) return;
|
|
3711
|
-
while (element.firstChild) parent.insertBefore(element.firstChild, element);
|
|
3712
|
-
parent.removeChild(element);
|
|
3713
|
-
};
|
|
3714
|
-
var sanitizeInlineHtml = (value) => {
|
|
3715
|
-
if (typeof document === "undefined") return escapeHtml(value);
|
|
3716
|
-
const template = document.createElement("template");
|
|
3717
|
-
template.innerHTML = value;
|
|
3718
|
-
Array.from(template.content.childNodes).forEach((child) => sanitizeNode(child));
|
|
3719
|
-
return template.innerHTML;
|
|
3720
|
-
};
|
|
3721
3824
|
var SEARCH_THRESHOLD = 11;
|
|
3722
3825
|
var SSelect = forwardRef(function SSelect2({
|
|
3723
3826
|
value,
|
|
@@ -3741,6 +3844,7 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
3741
3844
|
label,
|
|
3742
3845
|
labelWidth,
|
|
3743
3846
|
icon,
|
|
3847
|
+
iconColor,
|
|
3744
3848
|
labelTooltip,
|
|
3745
3849
|
addonLabel,
|
|
3746
3850
|
addonAlign,
|
|
@@ -3752,18 +3856,15 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
3752
3856
|
}, ref) {
|
|
3753
3857
|
const multi = type === "multi" || type === "multi_depth";
|
|
3754
3858
|
const portalContainer = usePortalContainer();
|
|
3859
|
+
const insideModal = useInsideModal();
|
|
3755
3860
|
const [search, setSearch] = useState("");
|
|
3756
3861
|
const [ruleError, setRuleError] = useState("");
|
|
3757
3862
|
const [open, setOpen] = useState(false);
|
|
3863
|
+
const [pendingOpen, setPendingOpen] = useState(false);
|
|
3864
|
+
const [focusedIndex, setFocusedIndex] = useState(-1);
|
|
3758
3865
|
const triggerRef = useRef(null);
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
() => ({
|
|
3762
|
-
focus: () => triggerRef.current?.focus(),
|
|
3763
|
-
open: () => setOpen(true)
|
|
3764
|
-
}),
|
|
3765
|
-
[]
|
|
3766
|
-
);
|
|
3866
|
+
const searchInputRef = useRef(null);
|
|
3867
|
+
const listRef = useRef(null);
|
|
3767
3868
|
const flat = useMemo(() => flattenOptions(options), [options]);
|
|
3768
3869
|
const selectable = useMemo(() => selectableOptions(flat), [flat]);
|
|
3769
3870
|
const hasLeaf = useMemo(() => flat.some((o) => !o.isGroup), [flat]);
|
|
@@ -3781,6 +3882,46 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
3781
3882
|
const arr = Array.isArray(value) ? value : [value];
|
|
3782
3883
|
return arr.map((v) => v != null && typeof v === "object" ? v.value : v).filter((v) => v != null && v !== "").map(String);
|
|
3783
3884
|
}, [value]);
|
|
3885
|
+
const selectedRef = useRef(selected);
|
|
3886
|
+
selectedRef.current = selected;
|
|
3887
|
+
const emit = (next) => {
|
|
3888
|
+
if (!onValueChange) return;
|
|
3889
|
+
const mapped = next.map(
|
|
3890
|
+
(v) => emitValue ? rawByValue.get(v) ?? v : optionByValue.get(v) ?? { value: v, label: v }
|
|
3891
|
+
);
|
|
3892
|
+
onValueChange(multi ? mapped : mapped[0] ?? (emitValue ? "" : null));
|
|
3893
|
+
};
|
|
3894
|
+
const commitOpen = (next) => {
|
|
3895
|
+
setOpen(next);
|
|
3896
|
+
onOpenChange?.(next);
|
|
3897
|
+
if (!next) {
|
|
3898
|
+
setPendingOpen(false);
|
|
3899
|
+
setSearch("");
|
|
3900
|
+
if (rules && rules.length > 0) {
|
|
3901
|
+
setRuleError(runRules(multi ? selectedRef.current : selectedRef.current[0] ?? "", rules));
|
|
3902
|
+
}
|
|
3903
|
+
}
|
|
3904
|
+
};
|
|
3905
|
+
const requestOpen = (next) => {
|
|
3906
|
+
if (next && insideModal && portalContainer == null) {
|
|
3907
|
+
setPendingOpen(true);
|
|
3908
|
+
return;
|
|
3909
|
+
}
|
|
3910
|
+
commitOpen(next);
|
|
3911
|
+
};
|
|
3912
|
+
useEffect(() => {
|
|
3913
|
+
if (!insideModal || portalContainer == null || !pendingOpen) return;
|
|
3914
|
+
setPendingOpen(false);
|
|
3915
|
+
commitOpen(true);
|
|
3916
|
+
}, [insideModal, pendingOpen, portalContainer]);
|
|
3917
|
+
useImperativeHandle(
|
|
3918
|
+
ref,
|
|
3919
|
+
() => ({
|
|
3920
|
+
focus: () => triggerRef.current?.focus(),
|
|
3921
|
+
open: () => requestOpen(true)
|
|
3922
|
+
}),
|
|
3923
|
+
[insideModal, portalContainer]
|
|
3924
|
+
);
|
|
3784
3925
|
useFormField({
|
|
3785
3926
|
name,
|
|
3786
3927
|
validate: () => {
|
|
@@ -3790,13 +3931,6 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
3790
3931
|
},
|
|
3791
3932
|
resetValidation: () => setRuleError("")
|
|
3792
3933
|
});
|
|
3793
|
-
const emit = (next) => {
|
|
3794
|
-
if (!onValueChange) return;
|
|
3795
|
-
const mapped = next.map(
|
|
3796
|
-
(v) => emitValue ? rawByValue.get(v) ?? v : optionByValue.get(v) ?? { value: v, label: v }
|
|
3797
|
-
);
|
|
3798
|
-
onValueChange(multi ? mapped : mapped[0] ?? (emitValue ? "" : null));
|
|
3799
|
-
};
|
|
3800
3934
|
const filtered = useMemo(() => {
|
|
3801
3935
|
if (!showSearch || search.trim() === "") return flat;
|
|
3802
3936
|
const q = search.trim().toLowerCase();
|
|
@@ -3807,6 +3941,16 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
3807
3941
|
const allValues = selectable.map((o) => o.value);
|
|
3808
3942
|
const allSelected = allValues.length > 0 && allValues.every((v) => selected.includes(v));
|
|
3809
3943
|
const hasItems = filtered.some((o) => !o.isGroup);
|
|
3944
|
+
const navigableItems = useMemo(() => {
|
|
3945
|
+
const items = [];
|
|
3946
|
+
if (multi && useSelectAll && allValues.length > 0) {
|
|
3947
|
+
items.push({ value: "__select_all__", isSelectAll: true });
|
|
3948
|
+
}
|
|
3949
|
+
filtered.forEach((o) => {
|
|
3950
|
+
if (!o.isGroup && !o.disabled) items.push({ value: o.value });
|
|
3951
|
+
});
|
|
3952
|
+
return items;
|
|
3953
|
+
}, [allValues.length, filtered, multi, useSelectAll]);
|
|
3810
3954
|
const triggerText = (() => {
|
|
3811
3955
|
if (selected.length === 0) return placeholder;
|
|
3812
3956
|
if (multi) {
|
|
@@ -3816,26 +3960,119 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
3816
3960
|
return labelByValue.get(selected[0]) ?? selected[0];
|
|
3817
3961
|
})();
|
|
3818
3962
|
const isPlaceholder = selected.length === 0;
|
|
3819
|
-
const
|
|
3820
|
-
|
|
3963
|
+
const handleSelect = (nextValue) => {
|
|
3964
|
+
if (multi) {
|
|
3965
|
+
const next = selected.includes(nextValue) ? selected.filter((v) => v !== nextValue) : [...selected, nextValue];
|
|
3966
|
+
emit(next);
|
|
3967
|
+
return;
|
|
3968
|
+
}
|
|
3969
|
+
emit([nextValue]);
|
|
3970
|
+
commitOpen(false);
|
|
3971
|
+
};
|
|
3972
|
+
const handleSelectAll = () => {
|
|
3973
|
+
emit(allSelected ? [] : allValues);
|
|
3974
|
+
};
|
|
3975
|
+
useEffect(() => {
|
|
3976
|
+
if (!open) {
|
|
3977
|
+
setFocusedIndex(-1);
|
|
3978
|
+
return;
|
|
3979
|
+
}
|
|
3980
|
+
setFocusedIndex(navigableItems.length > 0 ? 0 : -1);
|
|
3981
|
+
}, [open, navigableItems.length]);
|
|
3982
|
+
useEffect(() => {
|
|
3983
|
+
if (!open) return;
|
|
3984
|
+
setFocusedIndex(navigableItems.length > 0 ? 0 : -1);
|
|
3985
|
+
}, [search, open, navigableItems.length]);
|
|
3986
|
+
useEffect(() => {
|
|
3987
|
+
if (!open || focusedIndex < 0) return;
|
|
3988
|
+
const list = listRef.current;
|
|
3989
|
+
const focusedEl = list?.querySelector('[data-select-focused="true"]');
|
|
3990
|
+
if (!list || !focusedEl) return;
|
|
3991
|
+
const listRect = list.getBoundingClientRect();
|
|
3992
|
+
const itemRect = focusedEl.getBoundingClientRect();
|
|
3993
|
+
if (itemRect.top < listRect.top) {
|
|
3994
|
+
list.scrollTop += itemRect.top - listRect.top;
|
|
3995
|
+
} else if (itemRect.bottom > listRect.bottom) {
|
|
3996
|
+
list.scrollTop += itemRect.bottom - listRect.bottom;
|
|
3997
|
+
}
|
|
3998
|
+
}, [focusedIndex, open]);
|
|
3999
|
+
const moveFocusedIndex = (direction) => {
|
|
4000
|
+
if (!open || navigableItems.length === 0) return;
|
|
4001
|
+
setFocusedIndex((current) => {
|
|
4002
|
+
if (direction === "next") {
|
|
4003
|
+
return current < 0 ? 0 : (current + 1) % navigableItems.length;
|
|
4004
|
+
}
|
|
4005
|
+
return current <= 0 ? navigableItems.length - 1 : current - 1;
|
|
4006
|
+
});
|
|
4007
|
+
};
|
|
4008
|
+
const selectFocusedItem = () => {
|
|
4009
|
+
if (focusedIndex < 0 || focusedIndex >= navigableItems.length) return;
|
|
4010
|
+
const focused = navigableItems[focusedIndex];
|
|
4011
|
+
if (focused.isSelectAll) {
|
|
4012
|
+
handleSelectAll();
|
|
4013
|
+
return;
|
|
4014
|
+
}
|
|
4015
|
+
handleSelect(focused.value);
|
|
4016
|
+
};
|
|
4017
|
+
const handleKeyDown = (event) => {
|
|
4018
|
+
if (!open) {
|
|
4019
|
+
if ((event.key === "ArrowDown" || event.key === "ArrowUp") && !effectiveDisabled) {
|
|
4020
|
+
event.preventDefault();
|
|
4021
|
+
requestOpen(true);
|
|
4022
|
+
}
|
|
4023
|
+
return;
|
|
4024
|
+
}
|
|
4025
|
+
if (event.key === "ArrowDown") {
|
|
4026
|
+
event.preventDefault();
|
|
4027
|
+
moveFocusedIndex("next");
|
|
4028
|
+
return;
|
|
4029
|
+
}
|
|
4030
|
+
if (event.key === "ArrowUp") {
|
|
4031
|
+
event.preventDefault();
|
|
4032
|
+
moveFocusedIndex("prev");
|
|
4033
|
+
return;
|
|
4034
|
+
}
|
|
4035
|
+
if (event.key === "Enter") {
|
|
4036
|
+
event.preventDefault();
|
|
4037
|
+
selectFocusedItem();
|
|
4038
|
+
return;
|
|
4039
|
+
}
|
|
4040
|
+
if (event.key === "Escape") {
|
|
4041
|
+
event.preventDefault();
|
|
4042
|
+
commitOpen(false);
|
|
4043
|
+
}
|
|
4044
|
+
};
|
|
4045
|
+
return /* @__PURE__ */ jsxs(
|
|
4046
|
+
SField,
|
|
3821
4047
|
{
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
4048
|
+
label,
|
|
4049
|
+
labelWidth,
|
|
4050
|
+
icon,
|
|
4051
|
+
iconColor,
|
|
4052
|
+
labelTooltip,
|
|
4053
|
+
labelTooltipProps,
|
|
4054
|
+
addonLabel,
|
|
4055
|
+
addonAlign,
|
|
4056
|
+
hint,
|
|
4057
|
+
error: error || ruleError !== "",
|
|
4058
|
+
status: rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0,
|
|
4059
|
+
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
4060
|
+
disabled: effectiveDisabled,
|
|
4061
|
+
width,
|
|
4062
|
+
className,
|
|
4063
|
+
style,
|
|
3833
4064
|
children: [
|
|
4065
|
+
name && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: selected.join(",") }),
|
|
3834
4066
|
/* @__PURE__ */ jsxs(
|
|
3835
|
-
|
|
4067
|
+
"button",
|
|
3836
4068
|
{
|
|
3837
4069
|
ref: triggerRef,
|
|
4070
|
+
type: "button",
|
|
3838
4071
|
disabled: effectiveDisabled,
|
|
4072
|
+
"aria-haspopup": "listbox",
|
|
4073
|
+
"aria-expanded": open,
|
|
4074
|
+
onClick: () => requestOpen(!open),
|
|
4075
|
+
onKeyDown: handleKeyDown,
|
|
3839
4076
|
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",
|
|
3840
4077
|
style: {
|
|
3841
4078
|
color: effectiveDisabled ? "var(--cmp-select-text-disabled)" : isPlaceholder ? "var(--cmp-select-icon-default)" : "var(--cmp-select-text-default)"
|
|
@@ -3860,174 +4097,229 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
3860
4097
|
]
|
|
3861
4098
|
}
|
|
3862
4099
|
),
|
|
3863
|
-
/* @__PURE__ */
|
|
3864
|
-
|
|
4100
|
+
/* @__PURE__ */ jsx(
|
|
4101
|
+
SPortal,
|
|
3865
4102
|
{
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
4103
|
+
open,
|
|
4104
|
+
onClose: () => commitOpen(false),
|
|
4105
|
+
onOpenChange: (next) => {
|
|
4106
|
+
if (next) requestOpen(true);
|
|
4107
|
+
},
|
|
4108
|
+
anchorRef: triggerRef,
|
|
4109
|
+
placement: "bottom",
|
|
4110
|
+
align: "start",
|
|
4111
|
+
offset: 4,
|
|
4112
|
+
fit: !dropdownWidth,
|
|
4113
|
+
onOpenAutoFocus: (event) => {
|
|
4114
|
+
if (!showSearch) {
|
|
4115
|
+
event.preventDefault();
|
|
4116
|
+
return;
|
|
4117
|
+
}
|
|
4118
|
+
event.preventDefault();
|
|
4119
|
+
requestAnimationFrame(() => searchInputRef.current?.focus());
|
|
4120
|
+
},
|
|
4121
|
+
onCloseAutoFocus: (event) => {
|
|
4122
|
+
event.preventDefault();
|
|
4123
|
+
triggerRef.current?.focus();
|
|
4124
|
+
},
|
|
4125
|
+
className: "rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] py-[4px] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.1)]",
|
|
3871
4126
|
style: {
|
|
3872
|
-
maxHeight: dropdownHeight,
|
|
3873
4127
|
...dropdownWidth ? { width: dropdownWidth } : {},
|
|
3874
4128
|
maxWidth: maxDropdownWidth
|
|
3875
4129
|
},
|
|
3876
|
-
children:
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
4130
|
+
children: /* @__PURE__ */ jsxs(
|
|
4131
|
+
"div",
|
|
4132
|
+
{
|
|
4133
|
+
ref: listRef,
|
|
4134
|
+
className: "overflow-auto [scrollbar-width:auto] [&::-webkit-scrollbar]:w-[8px] [&::-webkit-scrollbar]:bg-[var(--color-grey-25)] [&::-webkit-scrollbar:horizontal]:h-[8px] [&::-webkit-scrollbar-thumb]:rounded-[4px] [&::-webkit-scrollbar-thumb]:bg-[var(--color-grey-45)] [&::-webkit-scrollbar-track]:bg-[var(--color-grey-25)]",
|
|
4135
|
+
style: { maxHeight: dropdownHeight },
|
|
4136
|
+
onMouseLeave: () => setFocusedIndex(-1),
|
|
4137
|
+
children: [
|
|
4138
|
+
showSearch && /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-[1] bg-[var(--cmp-listBox-bg)] px-[8px] py-[4px]", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-[6px] rounded-[4px] border border-solid border-[color:var(--color-grey-45)] bg-white px-[8px] py-[4px] focus-within:border-[color:var(--sys-color-field-border-focus)]", children: [
|
|
4139
|
+
/* @__PURE__ */ jsx(SIcon, { name: "search", size: 16, color: "var(--color-grey-70)", className: "shrink-0" }),
|
|
4140
|
+
/* @__PURE__ */ jsx(
|
|
4141
|
+
"input",
|
|
4142
|
+
{
|
|
4143
|
+
ref: searchInputRef,
|
|
4144
|
+
value: search,
|
|
4145
|
+
onChange: (e) => setSearch(e.target.value),
|
|
4146
|
+
onKeyDown: handleKeyDown,
|
|
4147
|
+
placeholder: "\uAC80\uC0C9",
|
|
4148
|
+
className: "min-w-0 flex-1 border-none bg-transparent text-[12px] leading-[20px] text-[color:var(--cmp-select-text-default)] outline-none placeholder:text-[color:var(--color-grey-55)]"
|
|
4149
|
+
}
|
|
4150
|
+
),
|
|
4151
|
+
search !== "" && /* @__PURE__ */ jsx(
|
|
4152
|
+
SGhostButton,
|
|
4153
|
+
{
|
|
4154
|
+
icon: "close",
|
|
4155
|
+
size: "xxs",
|
|
4156
|
+
intent: "default",
|
|
4157
|
+
ariaLabel: "\uAC80\uC0C9\uC5B4 \uC9C0\uC6B0\uAE30",
|
|
4158
|
+
onClick: () => setSearch(""),
|
|
4159
|
+
className: "shrink-0"
|
|
4160
|
+
}
|
|
4161
|
+
)
|
|
4162
|
+
] }) }),
|
|
4163
|
+
hasItems ? /* @__PURE__ */ jsx(
|
|
4164
|
+
ItemList,
|
|
4165
|
+
{
|
|
4166
|
+
items: filtered,
|
|
4167
|
+
multi,
|
|
4168
|
+
selected,
|
|
4169
|
+
focusedValue: navigableItems[focusedIndex]?.isSelectAll ? "__select_all__" : navigableItems[focusedIndex]?.value,
|
|
4170
|
+
showSelectAll: multi && useSelectAll && allValues.length > 0,
|
|
4171
|
+
selectAllLabel: allSelectedLabel,
|
|
4172
|
+
selectAllSelected: allSelected,
|
|
4173
|
+
onSelectAll: handleSelectAll,
|
|
4174
|
+
onSelect: handleSelect,
|
|
4175
|
+
onHoverValue: (value2) => {
|
|
4176
|
+
const index = navigableItems.findIndex(
|
|
4177
|
+
(item) => item.isSelectAll ? value2 === "__select_all__" : item.value === value2
|
|
4178
|
+
);
|
|
4179
|
+
if (index >= 0) setFocusedIndex(index);
|
|
4180
|
+
}
|
|
4181
|
+
}
|
|
4182
|
+
) : /* @__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." })
|
|
4183
|
+
]
|
|
4184
|
+
}
|
|
4185
|
+
)
|
|
3914
4186
|
}
|
|
3915
4187
|
)
|
|
3916
4188
|
]
|
|
3917
4189
|
}
|
|
3918
4190
|
);
|
|
3919
|
-
const control = showSearch ? /* @__PURE__ */ jsx(Ariakit.ComboboxProvider, { value: search, setValue: setSearch, resetValueOnHide: true, children: selectStore }) : selectStore;
|
|
3920
|
-
return /* @__PURE__ */ jsxs(
|
|
3921
|
-
SField,
|
|
3922
|
-
{
|
|
3923
|
-
label,
|
|
3924
|
-
labelWidth,
|
|
3925
|
-
icon,
|
|
3926
|
-
labelTooltip,
|
|
3927
|
-
labelTooltipProps,
|
|
3928
|
-
addonLabel,
|
|
3929
|
-
addonAlign,
|
|
3930
|
-
hint,
|
|
3931
|
-
error: error || ruleError !== "",
|
|
3932
|
-
status: rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0,
|
|
3933
|
-
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
3934
|
-
disabled: effectiveDisabled,
|
|
3935
|
-
width,
|
|
3936
|
-
className,
|
|
3937
|
-
style,
|
|
3938
|
-
children: [
|
|
3939
|
-
name && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: selected.join(",") }),
|
|
3940
|
-
control
|
|
3941
|
-
]
|
|
3942
|
-
}
|
|
3943
|
-
);
|
|
3944
4191
|
});
|
|
3945
4192
|
SSelect.displayName = "SSelect";
|
|
3946
4193
|
function ItemList({
|
|
3947
4194
|
items,
|
|
3948
4195
|
multi,
|
|
3949
4196
|
selected,
|
|
3950
|
-
|
|
4197
|
+
focusedValue,
|
|
4198
|
+
showSelectAll,
|
|
4199
|
+
selectAllLabel,
|
|
4200
|
+
selectAllSelected,
|
|
4201
|
+
onSelectAll,
|
|
4202
|
+
onSelect,
|
|
4203
|
+
onHoverValue
|
|
3951
4204
|
}) {
|
|
3952
4205
|
const itemBase = cn(
|
|
3953
|
-
|
|
3954
|
-
"group flex cursor-pointer select-none items-center gap-[8px] text-[12px] leading-[20px] outline-none",
|
|
4206
|
+
"group flex w-full cursor-pointer select-none items-center gap-[8px] border-none bg-transparent text-left text-[12px] leading-[20px] outline-none",
|
|
3955
4207
|
"text-[color:var(--cmp-listItem-content-default)]",
|
|
3956
|
-
|
|
3957
|
-
"aria-disabled:cursor-not-allowed aria-disabled:text-[color:var(--cmp-listItem-content-disabled)]"
|
|
4208
|
+
"disabled:cursor-not-allowed disabled:text-[color:var(--cmp-listItem-content-disabled)]"
|
|
3958
4209
|
);
|
|
3959
|
-
const activeClass = "
|
|
3960
|
-
return /* @__PURE__ */
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
const isDepth1 = o.depth === 1;
|
|
3964
|
-
return /* @__PURE__ */ jsx(
|
|
3965
|
-
"div",
|
|
3966
|
-
{
|
|
3967
|
-
className: cn(
|
|
3968
|
-
"select-none py-[4px] pr-[12px] text-[12px] leading-[20px] text-[color:var(--cmp-listItem-content-default)]",
|
|
3969
|
-
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",
|
|
3970
|
-
// 하위가 전부 비활성이면(select.config 에서 bubble-up) 어미 그룹도 비활성 처리:
|
|
3971
|
-
// 텍스트는 회색(#888), depth1 그룹은 파란 배경 대신 회색(#EEE)으로 (depth2 는 #F6F6F6 유지)
|
|
3972
|
-
o.disabled && "text-[color:var(--cmp-listItem-content-disabled)]",
|
|
3973
|
-
o.disabled && isDepth1 && "bg-[var(--cmp-listItem-depth1-bg-disabled)]"
|
|
3974
|
-
),
|
|
3975
|
-
style: { paddingLeft: padLeft },
|
|
3976
|
-
children: o.label
|
|
3977
|
-
},
|
|
3978
|
-
o.value
|
|
3979
|
-
);
|
|
3980
|
-
}
|
|
3981
|
-
const isSelected = selected.includes(o.value);
|
|
3982
|
-
return /* @__PURE__ */ jsxs(
|
|
3983
|
-
Ariakit.SelectItem,
|
|
4210
|
+
const activeClass = "hover:bg-[var(--cmp-listItem-bg-hover)] hover:text-[color:var(--cmp-listItem-content-hover)] focus:bg-[var(--cmp-listItem-bg-hover)] focus:text-[color:var(--cmp-listItem-content-hover)]";
|
|
4211
|
+
return /* @__PURE__ */ jsxs("div", { role: "listbox", "aria-multiselectable": multi || void 0, children: [
|
|
4212
|
+
showSelectAll && /* @__PURE__ */ jsxs(
|
|
4213
|
+
"button",
|
|
3984
4214
|
{
|
|
3985
|
-
|
|
3986
|
-
|
|
4215
|
+
type: "button",
|
|
4216
|
+
"data-select-focused": focusedValue === "__select_all__" ? "true" : void 0,
|
|
4217
|
+
"data-select-active": focusedValue === "__select_all__" ? "true" : void 0,
|
|
3987
4218
|
className: cn(
|
|
3988
4219
|
itemBase,
|
|
3989
|
-
|
|
3990
|
-
activeClass
|
|
4220
|
+
focusedValue === "__select_all__" && "bg-[var(--cmp-listItem-bg-hover)] text-[color:var(--cmp-listItem-content-hover)]"
|
|
3991
4221
|
),
|
|
3992
|
-
style: { paddingTop: 4, paddingBottom: 4, paddingRight: 12, paddingLeft:
|
|
3993
|
-
|
|
4222
|
+
style: { paddingTop: 4, paddingBottom: 4, paddingRight: 12, paddingLeft: 12 },
|
|
4223
|
+
onMouseEnter: () => onHoverValue("__select_all__"),
|
|
4224
|
+
onClick: onSelectAll,
|
|
3994
4225
|
children: [
|
|
3995
|
-
multi && // hover(active) 시 checkbox inverse — 파란 hover 배경 위에서 checked/unchecked 모두 흰 테두리 + 투명 배경
|
|
3996
4226
|
/* @__PURE__ */ jsx(
|
|
3997
4227
|
"span",
|
|
3998
4228
|
{
|
|
3999
4229
|
className: cn(
|
|
4000
4230
|
"flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid",
|
|
4001
|
-
|
|
4002
|
-
// 비활성: 회색 채움(#E1E1E1) + 회색 테두리(#CCCCCC)
|
|
4003
|
-
"border-[color:var(--cmp-checkbox-border-disabled)] bg-[var(--cmp-checkbox-bg-disabled)]"
|
|
4004
|
-
) : cn(
|
|
4005
|
-
"group-data-[active-item]:border-[color:var(--cmp-checkbox-checked-border-inverse)]",
|
|
4006
|
-
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"
|
|
4007
|
-
)
|
|
4231
|
+
selectAllSelected ? focusedValue === "__select_all__" ? "border-[color:var(--cmp-checkbox-checked-border-inverse)] bg-[var(--cmp-checkbox-checked-bg-default)]" : "border-[color:var(--cmp-checkbox-checked-bg-default)] bg-[var(--cmp-checkbox-checked-bg-default)]" : "border-[color:var(--cmp-checkbox-unchecked-border-default)] bg-[var(--cmp-checkbox-unchecked-bg-default)]"
|
|
4008
4232
|
),
|
|
4009
|
-
children:
|
|
4233
|
+
children: selectAllSelected && /* @__PURE__ */ jsx(
|
|
4010
4234
|
SIcon,
|
|
4011
4235
|
{
|
|
4012
4236
|
name: "checkboxCheck",
|
|
4013
4237
|
size: 12,
|
|
4014
|
-
color:
|
|
4238
|
+
color: "var(--cmp-checkbox-checked-icon-default)"
|
|
4015
4239
|
}
|
|
4016
4240
|
)
|
|
4017
4241
|
}
|
|
4018
4242
|
),
|
|
4019
|
-
|
|
4020
|
-
"span",
|
|
4021
|
-
{
|
|
4022
|
-
className: "flex-1 truncate",
|
|
4023
|
-
dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(o.label) }
|
|
4024
|
-
}
|
|
4025
|
-
) : /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: o.label })
|
|
4243
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: selectAllLabel })
|
|
4026
4244
|
]
|
|
4027
|
-
}
|
|
4028
|
-
|
|
4029
|
-
)
|
|
4030
|
-
|
|
4245
|
+
}
|
|
4246
|
+
),
|
|
4247
|
+
items.map((o) => {
|
|
4248
|
+
const padLeft = o.depth === 1 ? 12 : o.depth === 2 ? 20 : 28;
|
|
4249
|
+
if (o.isGroup) {
|
|
4250
|
+
const isDepth1 = o.depth === 1;
|
|
4251
|
+
return /* @__PURE__ */ jsx(
|
|
4252
|
+
"div",
|
|
4253
|
+
{
|
|
4254
|
+
className: cn(
|
|
4255
|
+
"select-none py-[4px] pr-[12px] text-[12px] leading-[20px] text-[color:var(--cmp-listItem-content-default)]",
|
|
4256
|
+
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",
|
|
4257
|
+
// 하위가 전부 비활성이면(select.config 에서 bubble-up) 어미 그룹도 비활성 처리:
|
|
4258
|
+
// 텍스트는 회색(#888), depth1 그룹은 파란 배경 대신 회색(#EEE)으로 (depth2 는 #F6F6F6 유지)
|
|
4259
|
+
o.disabled && "cursor-not-allowed text-[color:var(--cmp-listItem-content-disabled)]",
|
|
4260
|
+
o.disabled && isDepth1 && "bg-[var(--cmp-listItem-depth1-bg-disabled)]"
|
|
4261
|
+
),
|
|
4262
|
+
style: { paddingLeft: padLeft },
|
|
4263
|
+
children: o.label
|
|
4264
|
+
},
|
|
4265
|
+
o.value
|
|
4266
|
+
);
|
|
4267
|
+
}
|
|
4268
|
+
const isSelected = selected.includes(o.value);
|
|
4269
|
+
return /* @__PURE__ */ jsxs(
|
|
4270
|
+
"button",
|
|
4271
|
+
{
|
|
4272
|
+
type: "button",
|
|
4273
|
+
disabled: o.disabled,
|
|
4274
|
+
role: "option",
|
|
4275
|
+
"aria-selected": isSelected,
|
|
4276
|
+
"data-select-focused": focusedValue === o.value ? "true" : void 0,
|
|
4277
|
+
"data-select-active": focusedValue === o.value ? "true" : void 0,
|
|
4278
|
+
className: cn(
|
|
4279
|
+
itemBase,
|
|
4280
|
+
isSelected && !multi && "font-bold text-[color:var(--cmp-listItem-content-selected)]",
|
|
4281
|
+
focusedValue === o.value && "bg-[var(--cmp-listItem-bg-hover)] text-[color:var(--cmp-listItem-content-hover)]",
|
|
4282
|
+
activeClass
|
|
4283
|
+
),
|
|
4284
|
+
style: { paddingTop: 4, paddingBottom: 4, paddingRight: 12, paddingLeft: padLeft },
|
|
4285
|
+
onMouseEnter: () => onHoverValue(o.value),
|
|
4286
|
+
onClick: () => onSelect(o.value),
|
|
4287
|
+
children: [
|
|
4288
|
+
multi && /* @__PURE__ */ jsx(
|
|
4289
|
+
"span",
|
|
4290
|
+
{
|
|
4291
|
+
className: cn(
|
|
4292
|
+
"flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid",
|
|
4293
|
+
o.disabled ? (
|
|
4294
|
+
// 비활성: 회색 채움(#E1E1E1) + 회색 테두리(#CCCCCC)
|
|
4295
|
+
"cursor-not-allowed border-[color:var(--cmp-checkbox-border-disabled)] bg-[var(--cmp-checkbox-bg-disabled)]"
|
|
4296
|
+
) : cn(
|
|
4297
|
+
isSelected ? focusedValue === o.value ? "border-[color:var(--cmp-checkbox-checked-border-inverse)] bg-[var(--cmp-checkbox-checked-bg-default)]" : "border-[color:var(--cmp-checkbox-checked-bg-default)] bg-[var(--cmp-checkbox-checked-bg-default)]" : "border-[color:var(--cmp-checkbox-unchecked-border-default)] bg-[var(--cmp-checkbox-unchecked-bg-default)]"
|
|
4298
|
+
)
|
|
4299
|
+
),
|
|
4300
|
+
children: isSelected && /* @__PURE__ */ jsx(
|
|
4301
|
+
SIcon,
|
|
4302
|
+
{
|
|
4303
|
+
name: "checkboxCheck",
|
|
4304
|
+
size: 12,
|
|
4305
|
+
color: o.disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : "var(--cmp-checkbox-checked-icon-default)"
|
|
4306
|
+
}
|
|
4307
|
+
)
|
|
4308
|
+
}
|
|
4309
|
+
),
|
|
4310
|
+
isHtmlLabel(o.label) ? /* @__PURE__ */ jsx(
|
|
4311
|
+
"span",
|
|
4312
|
+
{
|
|
4313
|
+
className: "flex-1 truncate",
|
|
4314
|
+
dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(o.label) }
|
|
4315
|
+
}
|
|
4316
|
+
) : /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: o.label })
|
|
4317
|
+
]
|
|
4318
|
+
},
|
|
4319
|
+
o.value
|
|
4320
|
+
);
|
|
4321
|
+
})
|
|
4322
|
+
] });
|
|
4031
4323
|
}
|
|
4032
4324
|
var DEFAULT_ROW_HEIGHT = 44;
|
|
4033
4325
|
var DENSE_ROW_HEIGHT = 32;
|
|
@@ -4302,7 +4594,8 @@ var STable = forwardRef(function STable2({
|
|
|
4302
4594
|
else onSelectedChange?.([...selected, row]);
|
|
4303
4595
|
};
|
|
4304
4596
|
const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[var(--cmp-table-radius)] rounded-t-none" : "rounded-[var(--cmp-table-radius)]";
|
|
4305
|
-
const cellPadY = dense ? "var(--cmp-table-body-dense
|
|
4597
|
+
const cellPadY = dense ? "var(--cmp-table-body-paddingY-dense)" : "var(--cmp-table-body-paddingY-default)";
|
|
4598
|
+
const cellPadX = "var(--cmp-table-body-paddingX-wide)";
|
|
4306
4599
|
const rowH = dense ? "var(--cmp-table-body-dense-height)" : "var(--cmp-table-body-default-height)";
|
|
4307
4600
|
const totalColSpan = visibleCols.length + (selectable ? 1 : 0);
|
|
4308
4601
|
const stickyInfo = (i) => {
|
|
@@ -4477,13 +4770,15 @@ var STable = forwardRef(function STable2({
|
|
|
4477
4770
|
className: cn(
|
|
4478
4771
|
// 원본 .td: 컬럼 폭에 맞춰 내용 말줄임(overflow hidden + ellipsis) + 행 구분선(border-b)
|
|
4479
4772
|
// 셀 배경은 흰색으로 채워 뒤 배경이 비치지 않게 하고, hover 시 행 배경(grey_05)을 따른다.
|
|
4480
|
-
"overflow-hidden text-ellipsis whitespace-nowrap border-b border-solid border-[color:var(--cmp-table-border-color)]
|
|
4773
|
+
"overflow-hidden text-ellipsis whitespace-nowrap border-b border-solid border-[color:var(--cmp-table-border-color)] text-[12px] leading-[20px] text-[color:var(--sys-color-fg-primary)]",
|
|
4481
4774
|
rowBg,
|
|
4482
4775
|
"group-hover:bg-[var(--color-grey-05)]",
|
|
4483
4776
|
stickyShadowClass(i),
|
|
4484
4777
|
col.tdClass
|
|
4485
4778
|
),
|
|
4486
4779
|
style: {
|
|
4780
|
+
paddingLeft: cellPadX,
|
|
4781
|
+
paddingRight: cellPadX,
|
|
4487
4782
|
paddingTop: cellPadY,
|
|
4488
4783
|
paddingBottom: cellPadY,
|
|
4489
4784
|
textAlign: col.align ?? "left",
|