sellmate-design-system-react 0.1.10 → 0.2.0
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 +10 -4
- package/dist/components/SActionModal/SActionModal.cjs.map +1 -1
- package/dist/components/SActionModal/SActionModal.js +10 -4
- package/dist/components/SActionModal/SActionModal.js.map +1 -1
- package/dist/components/SBarcodeInput/SBarcodeInput.cjs +22 -5
- package/dist/components/SBarcodeInput/SBarcodeInput.cjs.map +1 -1
- package/dist/components/SBarcodeInput/SBarcodeInput.d.ts +3 -1
- package/dist/components/SBarcodeInput/SBarcodeInput.js +22 -5
- package/dist/components/SBarcodeInput/SBarcodeInput.js.map +1 -1
- package/dist/components/SCalendar/SCalendar.cjs +9 -3
- package/dist/components/SCalendar/SCalendar.cjs.map +1 -1
- package/dist/components/SCalendar/SCalendar.js +9 -3
- package/dist/components/SCalendar/SCalendar.js.map +1 -1
- package/dist/components/SChip/SChip.cjs +9 -3
- package/dist/components/SChip/SChip.cjs.map +1 -1
- package/dist/components/SChip/SChip.js +9 -3
- package/dist/components/SChip/SChip.js.map +1 -1
- package/dist/components/SChipInput/SChipInput.cjs +44 -13
- package/dist/components/SChipInput/SChipInput.cjs.map +1 -1
- package/dist/components/SChipInput/SChipInput.d.ts +5 -0
- package/dist/components/SChipInput/SChipInput.js +44 -13
- package/dist/components/SChipInput/SChipInput.js.map +1 -1
- package/dist/components/SChipInput/index.d.ts +1 -1
- package/dist/components/SCircleProgress/SCircleProgress.cjs +6 -2
- package/dist/components/SCircleProgress/SCircleProgress.cjs.map +1 -1
- package/dist/components/SCircleProgress/SCircleProgress.js +6 -2
- package/dist/components/SCircleProgress/SCircleProgress.js.map +1 -1
- package/dist/components/SConfirmModal/SConfirmModal.cjs +20 -13
- package/dist/components/SConfirmModal/SConfirmModal.cjs.map +1 -1
- package/dist/components/SConfirmModal/SConfirmModal.d.ts +7 -4
- package/dist/components/SConfirmModal/SConfirmModal.js +20 -13
- package/dist/components/SConfirmModal/SConfirmModal.js.map +1 -1
- package/dist/components/SDatePicker/SDatePicker.cjs +22 -5
- package/dist/components/SDatePicker/SDatePicker.cjs.map +1 -1
- package/dist/components/SDatePicker/SDatePicker.d.ts +3 -1
- package/dist/components/SDatePicker/SDatePicker.js +22 -5
- package/dist/components/SDatePicker/SDatePicker.js.map +1 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.cjs +22 -5
- package/dist/components/SDateRangePicker/SDateRangePicker.cjs.map +1 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.d.ts +3 -1
- package/dist/components/SDateRangePicker/SDateRangePicker.js +22 -5
- package/dist/components/SDateRangePicker/SDateRangePicker.js.map +1 -1
- package/dist/components/SDropdownButton/SDropdownButton.cjs +3 -1
- package/dist/components/SDropdownButton/SDropdownButton.cjs.map +1 -1
- package/dist/components/SDropdownButton/SDropdownButton.js +3 -1
- package/dist/components/SDropdownButton/SDropdownButton.js.map +1 -1
- package/dist/components/SField/SField.cjs +20 -5
- package/dist/components/SField/SField.cjs.map +1 -1
- package/dist/components/SField/SField.d.ts +4 -1
- package/dist/components/SField/SField.js +20 -5
- package/dist/components/SField/SField.js.map +1 -1
- package/dist/components/SFilePicker/SFilePicker.cjs +23 -6
- package/dist/components/SFilePicker/SFilePicker.cjs.map +1 -1
- package/dist/components/SFilePicker/SFilePicker.d.ts +3 -1
- package/dist/components/SFilePicker/SFilePicker.js +23 -6
- package/dist/components/SFilePicker/SFilePicker.js.map +1 -1
- package/dist/components/SGhostButton/SGhostButton.cjs +9 -3
- package/dist/components/SGhostButton/SGhostButton.cjs.map +1 -1
- package/dist/components/SGhostButton/SGhostButton.d.ts +5 -1
- package/dist/components/SGhostButton/SGhostButton.js +9 -3
- package/dist/components/SGhostButton/SGhostButton.js.map +1 -1
- package/dist/components/SGnb/SGnb.cjs +3297 -0
- package/dist/components/SGnb/SGnb.cjs.map +1 -0
- package/dist/components/SGnb/SGnb.d.ts +35 -0
- package/dist/components/SGnb/SGnb.js +3295 -0
- package/dist/components/SGnb/SGnb.js.map +1 -0
- package/dist/components/SGnb/gnb.config.d.ts +63 -0
- package/dist/components/SGnb/index.d.ts +2 -0
- package/dist/components/SGuide/SGuide.cjs +9 -3
- package/dist/components/SGuide/SGuide.cjs.map +1 -1
- package/dist/components/SGuide/SGuide.js +9 -3
- package/dist/components/SGuide/SGuide.js.map +1 -1
- package/dist/components/SInput/SInput.cjs +22 -5
- package/dist/components/SInput/SInput.cjs.map +1 -1
- package/dist/components/SInput/SInput.d.ts +4 -1
- package/dist/components/SInput/SInput.js +22 -5
- package/dist/components/SInput/SInput.js.map +1 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.cjs +511 -209
- package/dist/components/SKeyValueTable/SKeyValueTable.cjs.map +1 -1
- package/dist/components/SKeyValueTable/SKeyValueTable.d.ts +27 -6
- package/dist/components/SKeyValueTable/SKeyValueTable.js +510 -208
- package/dist/components/SKeyValueTable/SKeyValueTable.js.map +1 -1
- package/dist/components/SLayout/SLayout.cjs +79 -0
- package/dist/components/SLayout/SLayout.cjs.map +1 -0
- package/dist/components/SLayout/SLayout.d.ts +41 -0
- package/dist/components/SLayout/SLayout.js +75 -0
- package/dist/components/SLayout/SLayout.js.map +1 -0
- package/dist/components/SLayout/index.d.ts +1 -0
- package/dist/components/SLoadingContainer/SLoadingContainer.cjs +6 -2
- package/dist/components/SLoadingContainer/SLoadingContainer.cjs.map +1 -1
- package/dist/components/SLoadingContainer/SLoadingContainer.js +6 -2
- package/dist/components/SLoadingContainer/SLoadingContainer.js.map +1 -1
- package/dist/components/SLoadingContainer/loading.cjs +6 -2
- package/dist/components/SLoadingContainer/loading.cjs.map +1 -1
- package/dist/components/SLoadingContainer/loading.js +6 -2
- package/dist/components/SLoadingContainer/loading.js.map +1 -1
- package/dist/components/SLoadingModal/SLoadingModal.cjs +16 -6
- package/dist/components/SLoadingModal/SLoadingModal.cjs.map +1 -1
- package/dist/components/SLoadingModal/SLoadingModal.js +16 -6
- package/dist/components/SLoadingModal/SLoadingModal.js.map +1 -1
- package/dist/components/SModalContainer/SModalContainer.cjs +10 -4
- package/dist/components/SModalContainer/SModalContainer.cjs.map +1 -1
- package/dist/components/SModalContainer/SModalContainer.d.ts +10 -0
- package/dist/components/SModalContainer/SModalContainer.js +10 -4
- package/dist/components/SModalContainer/SModalContainer.js.map +1 -1
- package/dist/components/SNumberInput/SNumberInput.cjs +22 -5
- package/dist/components/SNumberInput/SNumberInput.cjs.map +1 -1
- package/dist/components/SNumberInput/SNumberInput.d.ts +2 -0
- package/dist/components/SNumberInput/SNumberInput.js +22 -5
- package/dist/components/SNumberInput/SNumberInput.js.map +1 -1
- package/dist/components/SPage/SPage.cjs +86 -0
- package/dist/components/SPage/SPage.cjs.map +1 -0
- package/dist/components/SPage/SPage.d.ts +13 -0
- package/dist/components/SPage/SPage.js +84 -0
- package/dist/components/SPage/SPage.js.map +1 -0
- package/dist/components/SPage/index.d.ts +1 -0
- package/dist/components/SPopover/SPopover.cjs +9 -3
- package/dist/components/SPopover/SPopover.cjs.map +1 -1
- package/dist/components/SPopover/SPopover.js +9 -3
- package/dist/components/SPopover/SPopover.js.map +1 -1
- package/dist/components/SPortal/SPortal.cjs +3 -1
- package/dist/components/SPortal/SPortal.cjs.map +1 -1
- package/dist/components/SPortal/SPortal.js +3 -1
- package/dist/components/SPortal/SPortal.js.map +1 -1
- package/dist/components/SSelect/SSelect.cjs +545 -265
- package/dist/components/SSelect/SSelect.cjs.map +1 -1
- package/dist/components/SSelect/SSelect.d.ts +4 -2
- package/dist/components/SSelect/SSelect.js +546 -265
- package/dist/components/SSelect/SSelect.js.map +1 -1
- package/dist/components/STable/STable.cjs +552 -268
- package/dist/components/STable/STable.cjs.map +1 -1
- package/dist/components/STable/STable.js +553 -268
- 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 +22 -5
- package/dist/components/STextarea/STextarea.cjs.map +1 -1
- package/dist/components/STextarea/STextarea.d.ts +2 -0
- package/dist/components/STextarea/STextarea.js +22 -5
- package/dist/components/STextarea/STextarea.js.map +1 -1
- package/dist/components/SToast/SToast.cjs +9 -3
- package/dist/components/SToast/SToast.cjs.map +1 -1
- package/dist/components/SToast/SToast.js +9 -3
- package/dist/components/SToast/SToast.js.map +1 -1
- package/dist/components/SToast/SToastContainer.cjs +9 -3
- package/dist/components/SToast/SToastContainer.cjs.map +1 -1
- package/dist/components/SToast/SToastContainer.js +9 -3
- package/dist/components/SToast/SToastContainer.js.map +1 -1
- package/dist/components/STooltip/STooltip.cjs +9 -3
- package/dist/components/STooltip/STooltip.cjs.map +1 -1
- package/dist/components/STooltip/STooltip.js +9 -3
- package/dist/components/STooltip/STooltip.js.map +1 -1
- package/dist/index.cjs +840 -199
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +832 -200
- package/dist/index.js.map +1 -1
- package/dist/lib/portal-container.d.ts +7 -0
- package/dist/styles.css +253 -63
- package/dist/theme.css +66 -13
- package/package.json +1 -1
|
@@ -4,8 +4,8 @@ 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 RPopover2 from '@radix-ui/react-popover';
|
|
7
|
-
import * as Ariakit from '@ariakit/react';
|
|
8
7
|
import * as RCheckbox from '@radix-ui/react-checkbox';
|
|
8
|
+
import * as Ariakit from '@ariakit/react';
|
|
9
9
|
|
|
10
10
|
var twMerge = extendTailwindMerge({
|
|
11
11
|
extend: {
|
|
@@ -2873,10 +2873,15 @@ var FLOATING_SLIDE_ANIM = [
|
|
|
2873
2873
|
"data-[state=closed]:data-[side=right]:animate-floating-out-right"
|
|
2874
2874
|
].join(" ");
|
|
2875
2875
|
var PortalContainerContext = createContext(null);
|
|
2876
|
+
var InsideModalContext = createContext(false);
|
|
2876
2877
|
PortalContainerContext.Provider;
|
|
2878
|
+
InsideModalContext.Provider;
|
|
2877
2879
|
function usePortalContainer() {
|
|
2878
2880
|
return useContext(PortalContainerContext) ?? void 0;
|
|
2879
2881
|
}
|
|
2882
|
+
function useInsideModal() {
|
|
2883
|
+
return useContext(InsideModalContext);
|
|
2884
|
+
}
|
|
2880
2885
|
|
|
2881
2886
|
// src/components/STag/tag.config.ts
|
|
2882
2887
|
var TAG_SIZE_CONFIG = {
|
|
@@ -2974,6 +2979,8 @@ function SGhostButton({
|
|
|
2974
2979
|
tooltipText,
|
|
2975
2980
|
disabled = false,
|
|
2976
2981
|
onClick,
|
|
2982
|
+
anchorClassName,
|
|
2983
|
+
anchorStyle,
|
|
2977
2984
|
className,
|
|
2978
2985
|
style
|
|
2979
2986
|
}) {
|
|
@@ -2996,6 +3003,8 @@ function SGhostButton({
|
|
|
2996
3003
|
};
|
|
2997
3004
|
const s = SIZE[size];
|
|
2998
3005
|
const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
|
|
3006
|
+
const text = (tooltipText ?? "").trim();
|
|
3007
|
+
const hasTooltip = text !== "";
|
|
2999
3008
|
const btn = /* @__PURE__ */ jsxs(
|
|
3000
3009
|
"button",
|
|
3001
3010
|
{
|
|
@@ -3036,13 +3045,13 @@ function SGhostButton({
|
|
|
3036
3045
|
]
|
|
3037
3046
|
}
|
|
3038
3047
|
);
|
|
3039
|
-
|
|
3040
|
-
if (text === "") return btn;
|
|
3048
|
+
if (!hasTooltip) return btn;
|
|
3041
3049
|
return /* @__PURE__ */ jsxs(RPopover2.Root, { open, onOpenChange: setOpen, children: [
|
|
3042
3050
|
/* @__PURE__ */ jsx(RPopover2.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3043
3051
|
"span",
|
|
3044
3052
|
{
|
|
3045
|
-
className: "inline-flex",
|
|
3053
|
+
className: cn("inline-flex", anchorClassName),
|
|
3054
|
+
style: anchorStyle,
|
|
3046
3055
|
onMouseEnter: openNow,
|
|
3047
3056
|
onMouseLeave: startHide,
|
|
3048
3057
|
onFocus: openNow,
|
|
@@ -3400,6 +3409,7 @@ var SField = forwardRef(function SField2({
|
|
|
3400
3409
|
name,
|
|
3401
3410
|
label = "",
|
|
3402
3411
|
icon,
|
|
3412
|
+
iconColor,
|
|
3403
3413
|
labelTooltip = "",
|
|
3404
3414
|
labelTooltipProps,
|
|
3405
3415
|
labelWidth,
|
|
@@ -3477,7 +3487,15 @@ var SField = forwardRef(function SField2({
|
|
|
3477
3487
|
lineHeight: `${s.lineHeight}px`
|
|
3478
3488
|
},
|
|
3479
3489
|
children: [
|
|
3480
|
-
icon && /* @__PURE__ */ jsx(
|
|
3490
|
+
icon && /* @__PURE__ */ jsx(
|
|
3491
|
+
SIcon,
|
|
3492
|
+
{
|
|
3493
|
+
name: icon,
|
|
3494
|
+
size: s.icon,
|
|
3495
|
+
color: iconColor,
|
|
3496
|
+
style: { marginRight: s.labelGap }
|
|
3497
|
+
}
|
|
3498
|
+
),
|
|
3481
3499
|
/* @__PURE__ */ jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis whitespace-nowrap", children: label }),
|
|
3482
3500
|
(labelTooltip !== "" || labelTooltipProps) && /* @__PURE__ */ jsx("span", { className: "shrink-0", style: { marginLeft: s.labelGap }, children: /* @__PURE__ */ jsx(
|
|
3483
3501
|
STooltip,
|
|
@@ -3527,7 +3545,7 @@ var SField = forwardRef(function SField2({
|
|
|
3527
3545
|
borderBottomLeftRadius: s.radius - 1
|
|
3528
3546
|
},
|
|
3529
3547
|
children: [
|
|
3530
|
-
icon && !label && /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon }),
|
|
3548
|
+
icon && !label && /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon, color: iconColor }),
|
|
3531
3549
|
effectiveAddonLabel
|
|
3532
3550
|
]
|
|
3533
3551
|
}
|
|
@@ -3553,6 +3571,7 @@ var SInput = forwardRef(function SInput2({
|
|
|
3553
3571
|
type = "text",
|
|
3554
3572
|
size = "sm",
|
|
3555
3573
|
icon,
|
|
3574
|
+
iconColor,
|
|
3556
3575
|
prefix,
|
|
3557
3576
|
suffix,
|
|
3558
3577
|
clearable = false,
|
|
@@ -3606,6 +3625,7 @@ var SInput = forwardRef(function SInput2({
|
|
|
3606
3625
|
labelTooltip,
|
|
3607
3626
|
labelTooltipProps,
|
|
3608
3627
|
icon,
|
|
3628
|
+
iconColor,
|
|
3609
3629
|
size,
|
|
3610
3630
|
hint,
|
|
3611
3631
|
error: resolvedError,
|
|
@@ -3707,6 +3727,7 @@ var STextarea = forwardRef(function STextarea2({
|
|
|
3707
3727
|
label,
|
|
3708
3728
|
labelWidth,
|
|
3709
3729
|
icon,
|
|
3730
|
+
iconColor,
|
|
3710
3731
|
labelTooltip,
|
|
3711
3732
|
labelTooltipProps,
|
|
3712
3733
|
addonLabel,
|
|
@@ -3743,6 +3764,7 @@ var STextarea = forwardRef(function STextarea2({
|
|
|
3743
3764
|
label,
|
|
3744
3765
|
labelWidth,
|
|
3745
3766
|
icon,
|
|
3767
|
+
iconColor,
|
|
3746
3768
|
labelTooltip,
|
|
3747
3769
|
labelTooltipProps,
|
|
3748
3770
|
addonLabel,
|
|
@@ -3875,6 +3897,7 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
3875
3897
|
label,
|
|
3876
3898
|
labelWidth,
|
|
3877
3899
|
icon,
|
|
3900
|
+
iconColor,
|
|
3878
3901
|
labelTooltip,
|
|
3879
3902
|
labelTooltipProps,
|
|
3880
3903
|
addonLabel,
|
|
@@ -4033,6 +4056,7 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
4033
4056
|
label,
|
|
4034
4057
|
labelWidth,
|
|
4035
4058
|
icon,
|
|
4059
|
+
iconColor,
|
|
4036
4060
|
labelTooltip,
|
|
4037
4061
|
labelTooltipProps,
|
|
4038
4062
|
addonLabel,
|
|
@@ -4118,40 +4142,6 @@ var SNumberInput = forwardRef(function SNumberInput2({
|
|
|
4118
4142
|
);
|
|
4119
4143
|
});
|
|
4120
4144
|
|
|
4121
|
-
// src/components/SSelect/select.config.ts
|
|
4122
|
-
function flattenOptions(options, depth = 1) {
|
|
4123
|
-
const out = [];
|
|
4124
|
-
for (const o of options) {
|
|
4125
|
-
const hasChildren = Array.isArray(o.children) && o.children.length > 0;
|
|
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
|
-
}
|
|
4148
|
-
}
|
|
4149
|
-
return out;
|
|
4150
|
-
}
|
|
4151
|
-
var selectableOptions = (flat) => flat.filter((o) => !o.isGroup && !o.disabled);
|
|
4152
|
-
var isHtmlLabel = (label) => /<[a-z][\s\S]*>/i.test(label);
|
|
4153
|
-
var extractText = (html) => html.replace(/<[^>]*>/g, "");
|
|
4154
|
-
|
|
4155
4145
|
// src/lib/sanitize-inline-html.ts
|
|
4156
4146
|
var ALLOWED_INLINE_TAGS = /* @__PURE__ */ new Set(["A", "B", "STRONG", "I", "EM", "BR", "SPAN"]);
|
|
4157
4147
|
var ALLOWED_ATTRS_BY_TAG = {
|
|
@@ -4220,6 +4210,111 @@ var sanitizeInlineHtml = (value) => {
|
|
|
4220
4210
|
Array.from(template.content.childNodes).forEach((child) => sanitizeNode(child));
|
|
4221
4211
|
return template.innerHTML;
|
|
4222
4212
|
};
|
|
4213
|
+
function SPortal({
|
|
4214
|
+
open,
|
|
4215
|
+
onClose,
|
|
4216
|
+
onOpenChange,
|
|
4217
|
+
anchorRef,
|
|
4218
|
+
placement = "bottom",
|
|
4219
|
+
align = "start",
|
|
4220
|
+
offset = 4,
|
|
4221
|
+
alignOffset = 0,
|
|
4222
|
+
fit = false,
|
|
4223
|
+
maxHeight,
|
|
4224
|
+
autoClose = false,
|
|
4225
|
+
persistent = false,
|
|
4226
|
+
viewportPadding = 0,
|
|
4227
|
+
onOpenAutoFocus,
|
|
4228
|
+
onCloseAutoFocus,
|
|
4229
|
+
children,
|
|
4230
|
+
className,
|
|
4231
|
+
style,
|
|
4232
|
+
ariaLabel
|
|
4233
|
+
}) {
|
|
4234
|
+
const portalContainer = usePortalContainer();
|
|
4235
|
+
return /* @__PURE__ */ jsxs(
|
|
4236
|
+
RPopover2.Root,
|
|
4237
|
+
{
|
|
4238
|
+
open,
|
|
4239
|
+
onOpenChange: (next) => {
|
|
4240
|
+
onOpenChange?.(next);
|
|
4241
|
+
if (!next) onClose?.();
|
|
4242
|
+
},
|
|
4243
|
+
children: [
|
|
4244
|
+
/* @__PURE__ */ jsx(RPopover2.Anchor, { virtualRef: anchorRef }),
|
|
4245
|
+
/* @__PURE__ */ jsx(RPopover2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
4246
|
+
RPopover2.Content,
|
|
4247
|
+
{
|
|
4248
|
+
side: placement,
|
|
4249
|
+
align,
|
|
4250
|
+
sideOffset: offset,
|
|
4251
|
+
alignOffset,
|
|
4252
|
+
collisionPadding: viewportPadding,
|
|
4253
|
+
"aria-label": ariaLabel,
|
|
4254
|
+
onPointerDownOutside: (e) => {
|
|
4255
|
+
if (persistent || anchorRef.current?.contains(e.target)) {
|
|
4256
|
+
e.preventDefault();
|
|
4257
|
+
}
|
|
4258
|
+
},
|
|
4259
|
+
onFocusOutside: (e) => {
|
|
4260
|
+
if (persistent || anchorRef.current?.contains(e.target)) {
|
|
4261
|
+
e.preventDefault();
|
|
4262
|
+
}
|
|
4263
|
+
},
|
|
4264
|
+
onEscapeKeyDown: persistent ? (e) => e.preventDefault() : void 0,
|
|
4265
|
+
onOpenAutoFocus,
|
|
4266
|
+
onCloseAutoFocus,
|
|
4267
|
+
onClick: autoClose ? () => onClose?.() : void 0,
|
|
4268
|
+
className: cn(
|
|
4269
|
+
"z-50 overflow-hidden rounded-(--cmp-listBox-radius) bg-(--cmp-listBox-bg) shadow-normal-sm",
|
|
4270
|
+
maxHeight != null && "overflow-y-auto",
|
|
4271
|
+
fit && "min-w-(--radix-popover-trigger-width)",
|
|
4272
|
+
FLOATING_SLIDE_ANIM,
|
|
4273
|
+
className
|
|
4274
|
+
),
|
|
4275
|
+
style: { maxHeight, ...style },
|
|
4276
|
+
children
|
|
4277
|
+
}
|
|
4278
|
+
) })
|
|
4279
|
+
]
|
|
4280
|
+
}
|
|
4281
|
+
);
|
|
4282
|
+
}
|
|
4283
|
+
SPortal.displayName = "SPortal";
|
|
4284
|
+
|
|
4285
|
+
// src/components/SSelect/select.config.ts
|
|
4286
|
+
function flattenOptions(options, depth = 1) {
|
|
4287
|
+
const out = [];
|
|
4288
|
+
for (const o of options) {
|
|
4289
|
+
const hasChildren = Array.isArray(o.children) && o.children.length > 0;
|
|
4290
|
+
if (hasChildren) {
|
|
4291
|
+
const childFlat = flattenOptions(o.children, depth + 1);
|
|
4292
|
+
const allChildrenDisabled = childFlat.every((c) => c.disabled);
|
|
4293
|
+
out.push({
|
|
4294
|
+
value: String(o.value),
|
|
4295
|
+
label: o.label,
|
|
4296
|
+
disabled: !!o.disabled || allChildrenDisabled,
|
|
4297
|
+
depth,
|
|
4298
|
+
isGroup: true,
|
|
4299
|
+
raw: o.value
|
|
4300
|
+
});
|
|
4301
|
+
out.push(...childFlat);
|
|
4302
|
+
} else {
|
|
4303
|
+
out.push({
|
|
4304
|
+
value: String(o.value),
|
|
4305
|
+
label: o.label,
|
|
4306
|
+
disabled: !!o.disabled,
|
|
4307
|
+
depth,
|
|
4308
|
+
isGroup: false,
|
|
4309
|
+
raw: o.value
|
|
4310
|
+
});
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
4313
|
+
return out;
|
|
4314
|
+
}
|
|
4315
|
+
var selectableOptions = (flat) => flat.filter((o) => !o.isGroup && !o.disabled);
|
|
4316
|
+
var isHtmlLabel = (label) => /<[a-z][\s\S]*>/i.test(label);
|
|
4317
|
+
var extractText = (html) => html.replace(/<[^>]*>/g, "");
|
|
4223
4318
|
var SEARCH_THRESHOLD = 11;
|
|
4224
4319
|
var SSelect = forwardRef(function SSelect2({
|
|
4225
4320
|
value,
|
|
@@ -4243,6 +4338,7 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
4243
4338
|
label,
|
|
4244
4339
|
labelWidth,
|
|
4245
4340
|
icon,
|
|
4341
|
+
iconColor,
|
|
4246
4342
|
labelTooltip,
|
|
4247
4343
|
addonLabel,
|
|
4248
4344
|
addonAlign,
|
|
@@ -4254,18 +4350,15 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
4254
4350
|
}, ref) {
|
|
4255
4351
|
const multi = type === "multi" || type === "multi_depth";
|
|
4256
4352
|
const portalContainer = usePortalContainer();
|
|
4353
|
+
const insideModal = useInsideModal();
|
|
4257
4354
|
const [search, setSearch] = useState("");
|
|
4258
4355
|
const [ruleError, setRuleError] = useState("");
|
|
4259
4356
|
const [open, setOpen] = useState(false);
|
|
4357
|
+
const [pendingOpen, setPendingOpen] = useState(false);
|
|
4358
|
+
const [focusedIndex, setFocusedIndex] = useState(-1);
|
|
4260
4359
|
const triggerRef = useRef(null);
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
() => ({
|
|
4264
|
-
focus: () => triggerRef.current?.focus(),
|
|
4265
|
-
open: () => setOpen(true)
|
|
4266
|
-
}),
|
|
4267
|
-
[]
|
|
4268
|
-
);
|
|
4360
|
+
const searchInputRef = useRef(null);
|
|
4361
|
+
const listRef = useRef(null);
|
|
4269
4362
|
const flat = useMemo(() => flattenOptions(options), [options]);
|
|
4270
4363
|
const selectable = useMemo(() => selectableOptions(flat), [flat]);
|
|
4271
4364
|
const hasLeaf = useMemo(() => flat.some((o) => !o.isGroup), [flat]);
|
|
@@ -4283,6 +4376,46 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
4283
4376
|
const arr = Array.isArray(value) ? value : [value];
|
|
4284
4377
|
return arr.map((v) => v != null && typeof v === "object" ? v.value : v).filter((v) => v != null && v !== "").map(String);
|
|
4285
4378
|
}, [value]);
|
|
4379
|
+
const selectedRef = useRef(selected);
|
|
4380
|
+
selectedRef.current = selected;
|
|
4381
|
+
const emit = (next) => {
|
|
4382
|
+
if (!onValueChange) return;
|
|
4383
|
+
const mapped = next.map(
|
|
4384
|
+
(v) => emitValue ? rawByValue.get(v) ?? v : optionByValue.get(v) ?? { value: v, label: v }
|
|
4385
|
+
);
|
|
4386
|
+
onValueChange(multi ? mapped : mapped[0] ?? (emitValue ? "" : null));
|
|
4387
|
+
};
|
|
4388
|
+
const commitOpen = (next) => {
|
|
4389
|
+
setOpen(next);
|
|
4390
|
+
onOpenChange?.(next);
|
|
4391
|
+
if (!next) {
|
|
4392
|
+
setPendingOpen(false);
|
|
4393
|
+
setSearch("");
|
|
4394
|
+
if (rules && rules.length > 0) {
|
|
4395
|
+
setRuleError(runRules(multi ? selectedRef.current : selectedRef.current[0] ?? "", rules));
|
|
4396
|
+
}
|
|
4397
|
+
}
|
|
4398
|
+
};
|
|
4399
|
+
const requestOpen = (next) => {
|
|
4400
|
+
if (next && insideModal && portalContainer == null) {
|
|
4401
|
+
setPendingOpen(true);
|
|
4402
|
+
return;
|
|
4403
|
+
}
|
|
4404
|
+
commitOpen(next);
|
|
4405
|
+
};
|
|
4406
|
+
useEffect(() => {
|
|
4407
|
+
if (!insideModal || portalContainer == null || !pendingOpen) return;
|
|
4408
|
+
setPendingOpen(false);
|
|
4409
|
+
commitOpen(true);
|
|
4410
|
+
}, [insideModal, pendingOpen, portalContainer]);
|
|
4411
|
+
useImperativeHandle(
|
|
4412
|
+
ref,
|
|
4413
|
+
() => ({
|
|
4414
|
+
focus: () => triggerRef.current?.focus(),
|
|
4415
|
+
open: () => requestOpen(true)
|
|
4416
|
+
}),
|
|
4417
|
+
[insideModal, portalContainer]
|
|
4418
|
+
);
|
|
4286
4419
|
useFormField({
|
|
4287
4420
|
name,
|
|
4288
4421
|
validate: () => {
|
|
@@ -4292,13 +4425,6 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
4292
4425
|
},
|
|
4293
4426
|
resetValidation: () => setRuleError("")
|
|
4294
4427
|
});
|
|
4295
|
-
const emit = (next) => {
|
|
4296
|
-
if (!onValueChange) return;
|
|
4297
|
-
const mapped = next.map(
|
|
4298
|
-
(v) => emitValue ? rawByValue.get(v) ?? v : optionByValue.get(v) ?? { value: v, label: v }
|
|
4299
|
-
);
|
|
4300
|
-
onValueChange(multi ? mapped : mapped[0] ?? (emitValue ? "" : null));
|
|
4301
|
-
};
|
|
4302
4428
|
const filtered = useMemo(() => {
|
|
4303
4429
|
if (!showSearch || search.trim() === "") return flat;
|
|
4304
4430
|
const q = search.trim().toLowerCase();
|
|
@@ -4309,6 +4435,16 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
4309
4435
|
const allValues = selectable.map((o) => o.value);
|
|
4310
4436
|
const allSelected = allValues.length > 0 && allValues.every((v) => selected.includes(v));
|
|
4311
4437
|
const hasItems = filtered.some((o) => !o.isGroup);
|
|
4438
|
+
const navigableItems = useMemo(() => {
|
|
4439
|
+
const items = [];
|
|
4440
|
+
if (multi && useSelectAll && allValues.length > 0) {
|
|
4441
|
+
items.push({ value: "__select_all__", isSelectAll: true });
|
|
4442
|
+
}
|
|
4443
|
+
filtered.forEach((o) => {
|
|
4444
|
+
if (!o.isGroup && !o.disabled) items.push({ value: o.value });
|
|
4445
|
+
});
|
|
4446
|
+
return items;
|
|
4447
|
+
}, [allValues.length, filtered, multi, useSelectAll]);
|
|
4312
4448
|
const triggerText = (() => {
|
|
4313
4449
|
if (selected.length === 0) return placeholder;
|
|
4314
4450
|
if (multi) {
|
|
@@ -4318,26 +4454,119 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
4318
4454
|
return labelByValue.get(selected[0]) ?? selected[0];
|
|
4319
4455
|
})();
|
|
4320
4456
|
const isPlaceholder = selected.length === 0;
|
|
4321
|
-
const
|
|
4322
|
-
|
|
4457
|
+
const handleSelect = (nextValue) => {
|
|
4458
|
+
if (multi) {
|
|
4459
|
+
const next = selected.includes(nextValue) ? selected.filter((v) => v !== nextValue) : [...selected, nextValue];
|
|
4460
|
+
emit(next);
|
|
4461
|
+
return;
|
|
4462
|
+
}
|
|
4463
|
+
emit([nextValue]);
|
|
4464
|
+
commitOpen(false);
|
|
4465
|
+
};
|
|
4466
|
+
const handleSelectAll = () => {
|
|
4467
|
+
emit(allSelected ? [] : allValues);
|
|
4468
|
+
};
|
|
4469
|
+
useEffect(() => {
|
|
4470
|
+
if (!open) {
|
|
4471
|
+
setFocusedIndex(-1);
|
|
4472
|
+
return;
|
|
4473
|
+
}
|
|
4474
|
+
setFocusedIndex(navigableItems.length > 0 ? 0 : -1);
|
|
4475
|
+
}, [open, navigableItems.length]);
|
|
4476
|
+
useEffect(() => {
|
|
4477
|
+
if (!open) return;
|
|
4478
|
+
setFocusedIndex(navigableItems.length > 0 ? 0 : -1);
|
|
4479
|
+
}, [search, open, navigableItems.length]);
|
|
4480
|
+
useEffect(() => {
|
|
4481
|
+
if (!open || focusedIndex < 0) return;
|
|
4482
|
+
const list = listRef.current;
|
|
4483
|
+
const focusedEl = list?.querySelector('[data-select-focused="true"]');
|
|
4484
|
+
if (!list || !focusedEl) return;
|
|
4485
|
+
const listRect = list.getBoundingClientRect();
|
|
4486
|
+
const itemRect = focusedEl.getBoundingClientRect();
|
|
4487
|
+
if (itemRect.top < listRect.top) {
|
|
4488
|
+
list.scrollTop += itemRect.top - listRect.top;
|
|
4489
|
+
} else if (itemRect.bottom > listRect.bottom) {
|
|
4490
|
+
list.scrollTop += itemRect.bottom - listRect.bottom;
|
|
4491
|
+
}
|
|
4492
|
+
}, [focusedIndex, open]);
|
|
4493
|
+
const moveFocusedIndex = (direction) => {
|
|
4494
|
+
if (!open || navigableItems.length === 0) return;
|
|
4495
|
+
setFocusedIndex((current) => {
|
|
4496
|
+
if (direction === "next") {
|
|
4497
|
+
return current < 0 ? 0 : (current + 1) % navigableItems.length;
|
|
4498
|
+
}
|
|
4499
|
+
return current <= 0 ? navigableItems.length - 1 : current - 1;
|
|
4500
|
+
});
|
|
4501
|
+
};
|
|
4502
|
+
const selectFocusedItem = () => {
|
|
4503
|
+
if (focusedIndex < 0 || focusedIndex >= navigableItems.length) return;
|
|
4504
|
+
const focused = navigableItems[focusedIndex];
|
|
4505
|
+
if (focused.isSelectAll) {
|
|
4506
|
+
handleSelectAll();
|
|
4507
|
+
return;
|
|
4508
|
+
}
|
|
4509
|
+
handleSelect(focused.value);
|
|
4510
|
+
};
|
|
4511
|
+
const handleKeyDown = (event) => {
|
|
4512
|
+
if (!open) {
|
|
4513
|
+
if ((event.key === "ArrowDown" || event.key === "ArrowUp") && !effectiveDisabled) {
|
|
4514
|
+
event.preventDefault();
|
|
4515
|
+
requestOpen(true);
|
|
4516
|
+
}
|
|
4517
|
+
return;
|
|
4518
|
+
}
|
|
4519
|
+
if (event.key === "ArrowDown") {
|
|
4520
|
+
event.preventDefault();
|
|
4521
|
+
moveFocusedIndex("next");
|
|
4522
|
+
return;
|
|
4523
|
+
}
|
|
4524
|
+
if (event.key === "ArrowUp") {
|
|
4525
|
+
event.preventDefault();
|
|
4526
|
+
moveFocusedIndex("prev");
|
|
4527
|
+
return;
|
|
4528
|
+
}
|
|
4529
|
+
if (event.key === "Enter") {
|
|
4530
|
+
event.preventDefault();
|
|
4531
|
+
selectFocusedItem();
|
|
4532
|
+
return;
|
|
4533
|
+
}
|
|
4534
|
+
if (event.key === "Escape") {
|
|
4535
|
+
event.preventDefault();
|
|
4536
|
+
commitOpen(false);
|
|
4537
|
+
}
|
|
4538
|
+
};
|
|
4539
|
+
return /* @__PURE__ */ jsxs(
|
|
4540
|
+
SField,
|
|
4323
4541
|
{
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4542
|
+
label,
|
|
4543
|
+
labelWidth,
|
|
4544
|
+
icon,
|
|
4545
|
+
iconColor,
|
|
4546
|
+
labelTooltip,
|
|
4547
|
+
labelTooltipProps,
|
|
4548
|
+
addonLabel,
|
|
4549
|
+
addonAlign,
|
|
4550
|
+
hint,
|
|
4551
|
+
error: error || ruleError !== "",
|
|
4552
|
+
status: rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0,
|
|
4553
|
+
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
4554
|
+
disabled: effectiveDisabled,
|
|
4555
|
+
width,
|
|
4556
|
+
className,
|
|
4557
|
+
style,
|
|
4335
4558
|
children: [
|
|
4559
|
+
name && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: selected.join(",") }),
|
|
4336
4560
|
/* @__PURE__ */ jsxs(
|
|
4337
|
-
|
|
4561
|
+
"button",
|
|
4338
4562
|
{
|
|
4339
4563
|
ref: triggerRef,
|
|
4564
|
+
type: "button",
|
|
4340
4565
|
disabled: effectiveDisabled,
|
|
4566
|
+
"aria-haspopup": "listbox",
|
|
4567
|
+
"aria-expanded": open,
|
|
4568
|
+
onClick: () => requestOpen(!open),
|
|
4569
|
+
onKeyDown: handleKeyDown,
|
|
4341
4570
|
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",
|
|
4342
4571
|
style: {
|
|
4343
4572
|
color: effectiveDisabled ? "var(--cmp-select-text-disabled)" : isPlaceholder ? "var(--cmp-select-icon-default)" : "var(--cmp-select-text-default)"
|
|
@@ -4362,178 +4591,237 @@ var SSelect = forwardRef(function SSelect2({
|
|
|
4362
4591
|
]
|
|
4363
4592
|
}
|
|
4364
4593
|
),
|
|
4365
|
-
/* @__PURE__ */
|
|
4366
|
-
|
|
4594
|
+
/* @__PURE__ */ jsx(
|
|
4595
|
+
SPortal,
|
|
4367
4596
|
{
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4597
|
+
open,
|
|
4598
|
+
onClose: () => commitOpen(false),
|
|
4599
|
+
onOpenChange: (next) => {
|
|
4600
|
+
if (next) requestOpen(true);
|
|
4601
|
+
},
|
|
4602
|
+
anchorRef: triggerRef,
|
|
4603
|
+
placement: "bottom",
|
|
4604
|
+
align: "start",
|
|
4605
|
+
offset: 4,
|
|
4606
|
+
fit: !dropdownWidth,
|
|
4607
|
+
onOpenAutoFocus: (event) => {
|
|
4608
|
+
if (!showSearch) {
|
|
4609
|
+
event.preventDefault();
|
|
4610
|
+
return;
|
|
4611
|
+
}
|
|
4612
|
+
event.preventDefault();
|
|
4613
|
+
requestAnimationFrame(() => searchInputRef.current?.focus());
|
|
4614
|
+
},
|
|
4615
|
+
onCloseAutoFocus: (event) => {
|
|
4616
|
+
event.preventDefault();
|
|
4617
|
+
triggerRef.current?.focus();
|
|
4618
|
+
},
|
|
4619
|
+
className: "rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.1)]",
|
|
4373
4620
|
style: {
|
|
4374
|
-
maxHeight: dropdownHeight,
|
|
4375
4621
|
...dropdownWidth ? { width: dropdownWidth } : {},
|
|
4376
4622
|
maxWidth: maxDropdownWidth
|
|
4377
4623
|
},
|
|
4378
|
-
children:
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4624
|
+
children: /* @__PURE__ */ jsxs(
|
|
4625
|
+
"div",
|
|
4626
|
+
{
|
|
4627
|
+
ref: listRef,
|
|
4628
|
+
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)]",
|
|
4629
|
+
style: { maxHeight: dropdownHeight },
|
|
4630
|
+
onMouseLeave: () => setFocusedIndex(-1),
|
|
4631
|
+
children: [
|
|
4632
|
+
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: [
|
|
4633
|
+
/* @__PURE__ */ jsx(SIcon, { name: "search", size: 16, color: "var(--color-grey-70)", className: "shrink-0" }),
|
|
4634
|
+
/* @__PURE__ */ jsx(
|
|
4635
|
+
"input",
|
|
4636
|
+
{
|
|
4637
|
+
ref: searchInputRef,
|
|
4638
|
+
value: search,
|
|
4639
|
+
onChange: (e) => setSearch(e.target.value),
|
|
4640
|
+
onKeyDown: handleKeyDown,
|
|
4641
|
+
placeholder: "\uAC80\uC0C9",
|
|
4642
|
+
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)]"
|
|
4643
|
+
}
|
|
4644
|
+
),
|
|
4645
|
+
search !== "" && /* @__PURE__ */ jsx(
|
|
4646
|
+
SGhostButton,
|
|
4647
|
+
{
|
|
4648
|
+
icon: "close",
|
|
4649
|
+
size: "xxs",
|
|
4650
|
+
intent: "default",
|
|
4651
|
+
ariaLabel: "\uAC80\uC0C9\uC5B4 \uC9C0\uC6B0\uAE30",
|
|
4652
|
+
onClick: () => setSearch(""),
|
|
4653
|
+
className: "shrink-0"
|
|
4654
|
+
}
|
|
4655
|
+
)
|
|
4656
|
+
] }) }),
|
|
4657
|
+
hasItems ? /* @__PURE__ */ jsx(
|
|
4658
|
+
ItemList,
|
|
4659
|
+
{
|
|
4660
|
+
items: filtered,
|
|
4661
|
+
multi,
|
|
4662
|
+
selected,
|
|
4663
|
+
focusedValue: navigableItems[focusedIndex]?.isSelectAll ? "__select_all__" : navigableItems[focusedIndex]?.value,
|
|
4664
|
+
showSelectAll: multi && useSelectAll && allValues.length > 0,
|
|
4665
|
+
selectAllLabel: allSelectedLabel,
|
|
4666
|
+
selectAllSelected: allSelected,
|
|
4667
|
+
onSelectAll: handleSelectAll,
|
|
4668
|
+
onSelect: handleSelect,
|
|
4669
|
+
onHoverValue: (value2) => {
|
|
4670
|
+
if (value2 == null) {
|
|
4671
|
+
setFocusedIndex(-1);
|
|
4672
|
+
return;
|
|
4673
|
+
}
|
|
4674
|
+
const index = navigableItems.findIndex(
|
|
4675
|
+
(item) => item.isSelectAll ? value2 === "__select_all__" : item.value === value2
|
|
4676
|
+
);
|
|
4677
|
+
if (index >= 0) setFocusedIndex(index);
|
|
4678
|
+
}
|
|
4679
|
+
}
|
|
4680
|
+
) : /* @__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." })
|
|
4681
|
+
]
|
|
4682
|
+
}
|
|
4683
|
+
)
|
|
4416
4684
|
}
|
|
4417
4685
|
)
|
|
4418
4686
|
]
|
|
4419
4687
|
}
|
|
4420
4688
|
);
|
|
4421
|
-
const control = showSearch ? /* @__PURE__ */ jsx(Ariakit.ComboboxProvider, { value: search, setValue: setSearch, resetValueOnHide: true, children: selectStore }) : selectStore;
|
|
4422
|
-
return /* @__PURE__ */ jsxs(
|
|
4423
|
-
SField,
|
|
4424
|
-
{
|
|
4425
|
-
label,
|
|
4426
|
-
labelWidth,
|
|
4427
|
-
icon,
|
|
4428
|
-
labelTooltip,
|
|
4429
|
-
labelTooltipProps,
|
|
4430
|
-
addonLabel,
|
|
4431
|
-
addonAlign,
|
|
4432
|
-
hint,
|
|
4433
|
-
error: error || ruleError !== "",
|
|
4434
|
-
status: rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0,
|
|
4435
|
-
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
4436
|
-
disabled: effectiveDisabled,
|
|
4437
|
-
width,
|
|
4438
|
-
className,
|
|
4439
|
-
style,
|
|
4440
|
-
children: [
|
|
4441
|
-
name && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: selected.join(",") }),
|
|
4442
|
-
control
|
|
4443
|
-
]
|
|
4444
|
-
}
|
|
4445
|
-
);
|
|
4446
4689
|
});
|
|
4447
4690
|
SSelect.displayName = "SSelect";
|
|
4448
4691
|
function ItemList({
|
|
4449
4692
|
items,
|
|
4450
4693
|
multi,
|
|
4451
4694
|
selected,
|
|
4452
|
-
|
|
4695
|
+
focusedValue,
|
|
4696
|
+
showSelectAll,
|
|
4697
|
+
selectAllLabel,
|
|
4698
|
+
selectAllSelected,
|
|
4699
|
+
onSelectAll,
|
|
4700
|
+
onSelect,
|
|
4701
|
+
onHoverValue
|
|
4453
4702
|
}) {
|
|
4454
4703
|
const itemBase = cn(
|
|
4455
|
-
|
|
4456
|
-
"group flex cursor-pointer select-none items-center gap-[8px] text-[12px] leading-[20px] outline-none",
|
|
4704
|
+
"group flex w-full cursor-pointer select-none items-center gap-[8px] border-none bg-transparent text-left text-[12px] leading-[20px] outline-none",
|
|
4457
4705
|
"text-[color:var(--cmp-listItem-content-default)]",
|
|
4458
|
-
|
|
4459
|
-
"aria-disabled:cursor-not-allowed aria-disabled:text-[color:var(--cmp-listItem-content-disabled)]"
|
|
4706
|
+
"disabled:cursor-not-allowed disabled:text-[color:var(--cmp-listItem-content-disabled)]"
|
|
4460
4707
|
);
|
|
4461
|
-
const activeClass = "
|
|
4462
|
-
return /* @__PURE__ */
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
const isDepth1 = o.depth === 1;
|
|
4466
|
-
return /* @__PURE__ */ jsx(
|
|
4467
|
-
"div",
|
|
4468
|
-
{
|
|
4469
|
-
className: cn(
|
|
4470
|
-
"select-none py-[4px] pr-[12px] text-[12px] leading-[20px] text-[color:var(--cmp-listItem-content-default)]",
|
|
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)]"
|
|
4476
|
-
),
|
|
4477
|
-
style: { paddingLeft: padLeft },
|
|
4478
|
-
children: o.label
|
|
4479
|
-
},
|
|
4480
|
-
o.value
|
|
4481
|
-
);
|
|
4482
|
-
}
|
|
4483
|
-
const isSelected = selected.includes(o.value);
|
|
4484
|
-
return /* @__PURE__ */ jsxs(
|
|
4485
|
-
Ariakit.SelectItem,
|
|
4708
|
+
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)]";
|
|
4709
|
+
return /* @__PURE__ */ jsxs("div", { role: "listbox", "aria-multiselectable": multi || void 0, children: [
|
|
4710
|
+
showSelectAll && /* @__PURE__ */ jsxs(
|
|
4711
|
+
"button",
|
|
4486
4712
|
{
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4713
|
+
type: "button",
|
|
4714
|
+
"data-select-focused": focusedValue === "__select_all__" ? "true" : void 0,
|
|
4715
|
+
"data-select-active": focusedValue === "__select_all__" ? "true" : void 0,
|
|
4490
4716
|
className: cn(
|
|
4491
4717
|
itemBase,
|
|
4492
|
-
|
|
4493
|
-
// Ariakit은 disabled 항목도 hover 시 active(data-active-item) 처리하므로,
|
|
4494
|
-
// 비활성 항목에는 hover 하이라이트를 적용하지 않아 회색 비활성 스타일을 유지한다.
|
|
4495
|
-
// (원본 Stencil의 `--focused...:not(--disabled)` 규칙과 동일한 의도)
|
|
4496
|
-
!o.disabled && activeClass
|
|
4718
|
+
focusedValue === "__select_all__" && "bg-[var(--cmp-listItem-bg-hover)] text-[color:var(--cmp-listItem-content-hover)]"
|
|
4497
4719
|
),
|
|
4498
|
-
style: { paddingTop: 4, paddingBottom: 4, paddingRight: 12, paddingLeft:
|
|
4499
|
-
|
|
4720
|
+
style: { paddingTop: 4, paddingBottom: 4, paddingRight: 12, paddingLeft: 12 },
|
|
4721
|
+
onMouseEnter: () => onHoverValue("__select_all__"),
|
|
4722
|
+
onMouseLeave: () => onHoverValue(null),
|
|
4723
|
+
onClick: onSelectAll,
|
|
4500
4724
|
children: [
|
|
4501
|
-
multi && // hover(active) 시 checkbox inverse — 파란 hover 배경 위에서 checked/unchecked 모두 흰 테두리 + 투명 배경
|
|
4502
4725
|
/* @__PURE__ */ jsx(
|
|
4503
4726
|
"span",
|
|
4504
4727
|
{
|
|
4505
4728
|
className: cn(
|
|
4506
4729
|
"flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid",
|
|
4507
|
-
|
|
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
|
-
)
|
|
4730
|
+
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)]"
|
|
4514
4731
|
),
|
|
4515
|
-
children:
|
|
4732
|
+
children: selectAllSelected && /* @__PURE__ */ jsx(
|
|
4516
4733
|
SIcon,
|
|
4517
4734
|
{
|
|
4518
4735
|
name: "checkboxCheck",
|
|
4519
4736
|
size: 12,
|
|
4520
|
-
color:
|
|
4737
|
+
color: "var(--cmp-checkbox-checked-icon-default)"
|
|
4521
4738
|
}
|
|
4522
4739
|
)
|
|
4523
4740
|
}
|
|
4524
4741
|
),
|
|
4525
|
-
|
|
4526
|
-
"span",
|
|
4527
|
-
{
|
|
4528
|
-
className: "flex-1 truncate",
|
|
4529
|
-
dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(o.label) }
|
|
4530
|
-
}
|
|
4531
|
-
) : /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: o.label })
|
|
4742
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: selectAllLabel })
|
|
4532
4743
|
]
|
|
4533
|
-
}
|
|
4534
|
-
|
|
4535
|
-
)
|
|
4536
|
-
|
|
4744
|
+
}
|
|
4745
|
+
),
|
|
4746
|
+
items.map((o) => {
|
|
4747
|
+
const padLeft = o.depth === 1 ? 12 : o.depth === 2 ? 20 : 28;
|
|
4748
|
+
if (o.isGroup) {
|
|
4749
|
+
const isDepth1 = o.depth === 1;
|
|
4750
|
+
return /* @__PURE__ */ jsx(
|
|
4751
|
+
"div",
|
|
4752
|
+
{
|
|
4753
|
+
className: cn(
|
|
4754
|
+
"select-none py-[4px] pr-[12px] text-[12px] leading-[20px] text-[color:var(--cmp-listItem-content-default)]",
|
|
4755
|
+
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",
|
|
4756
|
+
// 하위가 전부 비활성이면(select.config 에서 bubble-up) 어미 그룹도 비활성 처리:
|
|
4757
|
+
// 텍스트는 회색(#888), depth1 그룹은 파란 배경 대신 회색(#EEE)으로 (depth2 는 #F6F6F6 유지)
|
|
4758
|
+
o.disabled && "cursor-not-allowed text-[color:var(--cmp-listItem-content-disabled)]",
|
|
4759
|
+
o.disabled && isDepth1 && "bg-[var(--cmp-listItem-depth1-bg-disabled)]"
|
|
4760
|
+
),
|
|
4761
|
+
style: { paddingLeft: padLeft },
|
|
4762
|
+
children: o.label
|
|
4763
|
+
},
|
|
4764
|
+
o.value
|
|
4765
|
+
);
|
|
4766
|
+
}
|
|
4767
|
+
const isSelected = selected.includes(o.value);
|
|
4768
|
+
return /* @__PURE__ */ jsxs(
|
|
4769
|
+
"button",
|
|
4770
|
+
{
|
|
4771
|
+
type: "button",
|
|
4772
|
+
disabled: o.disabled,
|
|
4773
|
+
role: "option",
|
|
4774
|
+
"aria-selected": isSelected,
|
|
4775
|
+
"data-select-focused": focusedValue === o.value ? "true" : void 0,
|
|
4776
|
+
"data-select-active": focusedValue === o.value ? "true" : void 0,
|
|
4777
|
+
className: cn(
|
|
4778
|
+
itemBase,
|
|
4779
|
+
isSelected && !multi && "font-bold text-[color:var(--cmp-listItem-content-selected)]",
|
|
4780
|
+
focusedValue === o.value && "bg-[var(--cmp-listItem-bg-hover)] text-[color:var(--cmp-listItem-content-hover)]",
|
|
4781
|
+
// 비활성 항목은 hover/focus 스타일 대상에서 제외한다.
|
|
4782
|
+
// (:hover 는 disabled 버튼에도 매칭되므로 클래스 자체를 붙이지 않아야 한다)
|
|
4783
|
+
!o.disabled && activeClass
|
|
4784
|
+
),
|
|
4785
|
+
style: { paddingTop: 4, paddingBottom: 4, paddingRight: 12, paddingLeft: padLeft },
|
|
4786
|
+
onMouseEnter: () => onHoverValue(o.value),
|
|
4787
|
+
onMouseLeave: () => onHoverValue(null),
|
|
4788
|
+
onClick: () => onSelect(o.value),
|
|
4789
|
+
children: [
|
|
4790
|
+
multi && /* @__PURE__ */ jsx(
|
|
4791
|
+
"span",
|
|
4792
|
+
{
|
|
4793
|
+
className: cn(
|
|
4794
|
+
"flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-[2px] border border-solid",
|
|
4795
|
+
o.disabled ? (
|
|
4796
|
+
// 비활성: 회색 채움(#E1E1E1) + 회색 테두리(#CCCCCC)
|
|
4797
|
+
"cursor-not-allowed border-[color:var(--cmp-checkbox-border-disabled)] bg-[var(--cmp-checkbox-bg-disabled)]"
|
|
4798
|
+
) : cn(
|
|
4799
|
+
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)]"
|
|
4800
|
+
)
|
|
4801
|
+
),
|
|
4802
|
+
children: isSelected && /* @__PURE__ */ jsx(
|
|
4803
|
+
SIcon,
|
|
4804
|
+
{
|
|
4805
|
+
name: "checkboxCheck",
|
|
4806
|
+
size: 12,
|
|
4807
|
+
color: o.disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : "var(--cmp-checkbox-checked-icon-default)"
|
|
4808
|
+
}
|
|
4809
|
+
)
|
|
4810
|
+
}
|
|
4811
|
+
),
|
|
4812
|
+
isHtmlLabel(o.label) ? /* @__PURE__ */ jsx(
|
|
4813
|
+
"span",
|
|
4814
|
+
{
|
|
4815
|
+
className: "flex-1 truncate",
|
|
4816
|
+
dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(o.label) }
|
|
4817
|
+
}
|
|
4818
|
+
) : /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: o.label })
|
|
4819
|
+
]
|
|
4820
|
+
},
|
|
4821
|
+
o.value
|
|
4822
|
+
);
|
|
4823
|
+
})
|
|
4824
|
+
] });
|
|
4537
4825
|
}
|
|
4538
4826
|
function SRadio({
|
|
4539
4827
|
val,
|
|
@@ -4996,6 +5284,7 @@ function SDatePicker({
|
|
|
4996
5284
|
label,
|
|
4997
5285
|
labelWidth,
|
|
4998
5286
|
icon,
|
|
5287
|
+
iconColor,
|
|
4999
5288
|
labelTooltip,
|
|
5000
5289
|
labelTooltipProps,
|
|
5001
5290
|
addonLabel,
|
|
@@ -5034,6 +5323,7 @@ function SDatePicker({
|
|
|
5034
5323
|
label,
|
|
5035
5324
|
labelWidth,
|
|
5036
5325
|
icon,
|
|
5326
|
+
iconColor,
|
|
5037
5327
|
labelTooltip,
|
|
5038
5328
|
labelTooltipProps,
|
|
5039
5329
|
addonLabel,
|
|
@@ -5302,6 +5592,7 @@ function SDateRangePicker({
|
|
|
5302
5592
|
label,
|
|
5303
5593
|
labelWidth,
|
|
5304
5594
|
icon,
|
|
5595
|
+
iconColor,
|
|
5305
5596
|
labelTooltip,
|
|
5306
5597
|
labelTooltipProps,
|
|
5307
5598
|
addonLabel,
|
|
@@ -5344,6 +5635,7 @@ function SDateRangePicker({
|
|
|
5344
5635
|
label,
|
|
5345
5636
|
labelWidth,
|
|
5346
5637
|
icon,
|
|
5638
|
+
iconColor,
|
|
5347
5639
|
labelTooltip,
|
|
5348
5640
|
labelTooltipProps,
|
|
5349
5641
|
addonLabel,
|
|
@@ -5605,6 +5897,7 @@ function SFilePicker({
|
|
|
5605
5897
|
label,
|
|
5606
5898
|
labelWidth,
|
|
5607
5899
|
icon,
|
|
5900
|
+
iconColor,
|
|
5608
5901
|
labelTooltip,
|
|
5609
5902
|
labelTooltipProps,
|
|
5610
5903
|
addonLabel,
|
|
@@ -5774,7 +6067,7 @@ function SFilePicker({
|
|
|
5774
6067
|
unmountOnHide: true,
|
|
5775
6068
|
getAnchorRect: () => contentBoxRef.current?.getBoundingClientRect() ?? null,
|
|
5776
6069
|
style: { minWidth: contentBoxRef.current?.offsetWidth },
|
|
5777
|
-
className: "z-50 box-border flex flex-col items-
|
|
6070
|
+
className: "z-50 box-border flex flex-col items-start 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
6071
|
children: filesArr.map((f, i) => /* @__PURE__ */ jsx(SChip, { value: f.name, editable: false, onRemove: () => removeChip(i) }, i))
|
|
5779
6072
|
}
|
|
5780
6073
|
)
|
|
@@ -5788,6 +6081,7 @@ function SFilePicker({
|
|
|
5788
6081
|
label,
|
|
5789
6082
|
labelWidth,
|
|
5790
6083
|
icon,
|
|
6084
|
+
iconColor,
|
|
5791
6085
|
labelTooltip,
|
|
5792
6086
|
labelTooltipProps,
|
|
5793
6087
|
addonLabel,
|
|
@@ -5810,21 +6104,26 @@ function SFilePicker({
|
|
|
5810
6104
|
var cssLen2 = (v) => v == null ? void 0 : typeof v === "number" ? `${v}px` : v;
|
|
5811
6105
|
function SKeyValueTable({
|
|
5812
6106
|
fields = [],
|
|
6107
|
+
values = {},
|
|
5813
6108
|
search = false,
|
|
5814
6109
|
radius = "default",
|
|
5815
|
-
dense = false,
|
|
5816
6110
|
onChange,
|
|
5817
6111
|
onSearch,
|
|
5818
6112
|
className,
|
|
5819
6113
|
style
|
|
5820
6114
|
}) {
|
|
5821
6115
|
if (fields.length === 0) return null;
|
|
5822
|
-
const emit = (name, value) => onChange?.({
|
|
5823
|
-
|
|
5824
|
-
|
|
6116
|
+
const emit = (name, value) => onChange?.({
|
|
6117
|
+
name,
|
|
6118
|
+
value,
|
|
6119
|
+
values: { ...values, [name]: value }
|
|
6120
|
+
});
|
|
6121
|
+
const cellHeight = "var(--cmp-table-keyValue-height)";
|
|
6122
|
+
const cellPadY = "var(--cmp-table-keyValue-body-paddingY)";
|
|
5825
6123
|
const renderField = (f) => {
|
|
5826
6124
|
if (f.render) return f.render;
|
|
5827
|
-
const opt = f.options ?? {};
|
|
6125
|
+
const opt = { ...f.options ?? {} };
|
|
6126
|
+
if (Object.prototype.hasOwnProperty.call(values, f.name)) opt.value = values[f.name];
|
|
5828
6127
|
const up = (v) => emit(f.name, v);
|
|
5829
6128
|
switch (f.type) {
|
|
5830
6129
|
case "input":
|
|
@@ -5936,7 +6235,10 @@ function SKeyValueTable({
|
|
|
5936
6235
|
rowSpan: f.tdRowSpan && f.tdRowSpan > 1 ? f.tdRowSpan : void 0,
|
|
5937
6236
|
colSpan: f.tdColSpan && f.tdColSpan > 1 ? f.tdColSpan : void 0,
|
|
5938
6237
|
className: cn(
|
|
5939
|
-
"box-border bg-[var(--sys-color-bg-frame)]
|
|
6238
|
+
"box-border bg-[var(--sys-color-bg-frame)] align-middle",
|
|
6239
|
+
// text 타입(및 미지정 기본값)은 읽기 전용 콘텐츠라 넓은 paddingX(wide),
|
|
6240
|
+
// 폼 필드 셀은 default paddingX 유지
|
|
6241
|
+
f.type == null || f.type === "text" ? "px-[var(--cmp-table-keyValue-body-paddingX-wide)]" : "px-[var(--cmp-table-keyValue-body-paddingX-default)]",
|
|
5940
6242
|
cellBorder,
|
|
5941
6243
|
f.tdClass
|
|
5942
6244
|
),
|