sellmate-design-system-react 8.1.0 → 9.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +279 -124
- package/README.md +101 -8
- package/dist/components/SChipFilter/README.md +70 -0
- package/dist/components/SChipFilter/SChipFilter.d.ts +167 -0
- package/dist/components/SChipFilter/index.d.ts +1 -0
- package/dist/components/SCircleProgress/README.md +3 -0
- package/dist/components/SCircleProgress/SCircleProgress.d.ts +7 -1
- package/dist/components/SDatePicker/README.md +43 -3
- package/dist/components/SDatePicker/SDatePicker.d.ts +36 -3
- package/dist/components/SDatePicker/index.d.ts +1 -1
- package/dist/components/SDateRangePicker/README.md +21 -0
- package/dist/components/SDateRangePicker/SDateRangePicker.d.ts +16 -0
- package/dist/components/SDateRangePicker/index.d.ts +1 -1
- package/dist/components/SField/README.md +3 -0
- package/dist/components/SField/SField.d.ts +12 -0
- package/dist/components/SGhostButton/README.md +6 -0
- package/dist/components/SGnb/gnb.config.d.ts +2 -0
- package/dist/components/SGuide/README.md +1 -1
- package/dist/components/SGuide/SGuide.d.ts +1 -1
- package/dist/components/SIcon/README.md +6 -0
- package/dist/components/SIcon/icons.gen.d.ts +1 -0
- package/dist/components/SImage/README.md +44 -0
- package/dist/components/SImage/SImage.d.ts +41 -0
- package/dist/components/SImage/index.d.ts +1 -0
- package/dist/components/SKeyValueTable/README.md +1 -0
- package/dist/components/SKeyValueTable/SKeyValueTable.d.ts +8 -1
- package/dist/components/SListItem/README.md +2 -2
- package/dist/components/SListItem/SListItem.d.ts +2 -2
- package/dist/components/SPage/README.md +23 -0
- package/dist/components/SPage/SPage.d.ts +27 -1
- package/dist/components/SPage/SPageHeader.d.ts +32 -0
- package/dist/components/SPage/index.d.ts +2 -1
- package/dist/components/SPage/page.config.d.ts +8 -0
- package/dist/components/SPortal/README.md +1 -1
- package/dist/components/SPortal/SPortal.d.ts +7 -1
- package/dist/components/SRadio/README.md +2 -0
- package/dist/components/SRadioButton/README.md +13 -0
- package/dist/components/SSearchInput/README.md +48 -0
- package/dist/components/SSearchInput/SSearchInput.d.ts +46 -0
- package/dist/components/SSearchInput/index.d.ts +1 -0
- package/dist/components/SSectionHeaderCard/README.md +10 -23
- package/dist/components/SSectionHeaderCard/SSectionHeaderCard.d.ts +21 -14
- package/dist/components/SSectionHeaderCard/index.d.ts +1 -1
- package/dist/components/SSelect/README.md +4 -2
- package/dist/components/SSelect/SSelect.d.ts +2 -2
- package/dist/components/STable/README.md +1 -0
- package/dist/components/STable/STable.d.ts +20 -0
- package/dist/components/STabs/README.md +0 -1
- package/dist/components/STabs/STabs.d.ts +2 -4
- package/dist/components/STabs/index.d.ts +1 -1
- package/dist/components/STabs/tabs.config.d.ts +3 -4
- package/dist/components/STag/README.md +2 -0
- package/dist/components/STextLink/README.md +2 -0
- package/dist/components/STimePicker/timepicker.config.d.ts +5 -0
- package/dist/components/SToggle/README.md +1 -0
- package/dist/components/SToggle/SToggle.d.ts +4 -1
- package/dist/components/STooltip/README.md +2 -0
- package/dist/components/STree/README.md +3 -0
- package/dist/components/STree/STree.d.ts +8 -0
- package/dist/components/STree/index.d.ts +1 -1
- package/dist/index.cjs +2988 -393
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2981 -394
- package/dist/index.js.map +1 -1
- package/dist/lib/floating-width.d.ts +22 -0
- package/dist/lib/truncated-value-tooltip.d.ts +18 -0
- package/dist/llms-full.txt +545 -152
- package/dist/llms.txt +283 -127
- package/dist/styles.css +397 -36
- package/dist/theme.css +34 -11
- package/eslint/index.mjs +5 -0
- package/eslint/rules/field-width-grade.d.mts +41 -0
- package/eslint/rules/field-width-grade.mjs +294 -0
- package/eslint/scale.gen.mjs +1 -1
- package/package.json +7 -4
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { forwardRef, useState, useRef, useEffect, createContext, useContext, use
|
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
7
7
|
import * as RCheckbox from '@radix-ui/react-checkbox';
|
|
8
|
-
import * as
|
|
8
|
+
import * as RPopover10 from '@radix-ui/react-popover';
|
|
9
9
|
import { createRoot } from 'react-dom/client';
|
|
10
10
|
import * as RTooltip from '@radix-ui/react-tooltip';
|
|
11
11
|
import * as RDropdown from '@radix-ui/react-dropdown-menu';
|
|
@@ -2565,6 +2565,27 @@ var Icon_sidebar = (p) => {
|
|
|
2565
2565
|
}
|
|
2566
2566
|
);
|
|
2567
2567
|
};
|
|
2568
|
+
var Icon_star = (p) => {
|
|
2569
|
+
const { size = 24, ...rest } = p;
|
|
2570
|
+
return /* @__PURE__ */ jsx(
|
|
2571
|
+
"svg",
|
|
2572
|
+
{
|
|
2573
|
+
width: size,
|
|
2574
|
+
height: size,
|
|
2575
|
+
viewBox: "0 0 24 24",
|
|
2576
|
+
fill: "none",
|
|
2577
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2578
|
+
...rest,
|
|
2579
|
+
children: /* @__PURE__ */ jsx(
|
|
2580
|
+
"path",
|
|
2581
|
+
{
|
|
2582
|
+
d: "M12.3358 3.45335C12.0755 2.84888 11.2185 2.84888 10.9582 3.45335L8.78136 8.50811C8.67278 8.76024 8.43512 8.93291 8.16178 8.95826L2.68175 9.46652C2.02642 9.5273 1.76157 10.3424 2.25602 10.7768L6.39071 14.409C6.59695 14.5902 6.68773 14.8696 6.62737 15.1374L5.41733 20.5063C5.27263 21.1483 5.966 21.6521 6.5319 21.3161L11.2641 18.5062C11.5001 18.366 11.7939 18.366 12.0299 18.5062L16.7621 21.3161C17.328 21.6521 18.0214 21.1483 17.8767 20.5063L16.6666 15.1374C16.6063 14.8696 16.6971 14.5902 16.9033 14.409L21.038 10.7768C21.5324 10.3424 21.2676 9.5273 20.6123 9.46652L15.1322 8.95826C14.8589 8.93291 14.6212 8.76024 14.5126 8.50811L12.3358 3.45335Z",
|
|
2583
|
+
fill: "currentColor"
|
|
2584
|
+
}
|
|
2585
|
+
)
|
|
2586
|
+
}
|
|
2587
|
+
);
|
|
2588
|
+
};
|
|
2568
2589
|
var Icon_store = (p) => {
|
|
2569
2590
|
const { size = 24, ...rest } = p;
|
|
2570
2591
|
return /* @__PURE__ */ jsxs(
|
|
@@ -3059,6 +3080,7 @@ var ICONS = {
|
|
|
3059
3080
|
settingOutline: Icon_settingOutline,
|
|
3060
3081
|
shield: Icon_shield,
|
|
3061
3082
|
sidebar: Icon_sidebar,
|
|
3083
|
+
star: Icon_star,
|
|
3062
3084
|
store: Icon_store,
|
|
3063
3085
|
synchronize: Icon_synchronize,
|
|
3064
3086
|
thumbsDown: Icon_thumbsDown,
|
|
@@ -3091,6 +3113,209 @@ var SIcon = /* @__PURE__ */ forwardRef(function SIcon2({ name, size = 24, color,
|
|
|
3091
3113
|
}
|
|
3092
3114
|
);
|
|
3093
3115
|
});
|
|
3116
|
+
var VIEWBOX = 80;
|
|
3117
|
+
var RADIUS = 34;
|
|
3118
|
+
var STROKE = 12;
|
|
3119
|
+
var CIRCUMFERENCE = 2 * Math.PI * RADIUS;
|
|
3120
|
+
var COLOR_MAP = {
|
|
3121
|
+
primary: { arc: "var(--cmp-progress-color-active)", track: "var(--cmp-progress-color-track)" },
|
|
3122
|
+
// inverse: 어두운 배경용 — arc 흰색, track 은 흰색 40%(회색 링)
|
|
3123
|
+
inverse: { arc: "var(--color-white)", track: "rgba(255,255,255,0.4)" },
|
|
3124
|
+
error: { arc: "var(--color-red-75)", track: "var(--cmp-progress-color-track)" },
|
|
3125
|
+
complete: { arc: "#01BB4B", track: "var(--cmp-progress-color-track)" },
|
|
3126
|
+
// neutral: 콘텐츠가 아직 없는 자리를 채우는 용도 — arc 도 회색이라 진행률보다 "대기"로 읽힌다
|
|
3127
|
+
neutral: { arc: "var(--color-grey-35)", track: "var(--cmp-progress-color-track)" }
|
|
3128
|
+
};
|
|
3129
|
+
var DEFAULT_SIZE = 80;
|
|
3130
|
+
var clamp = (v) => Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;
|
|
3131
|
+
var SCircleProgress = /* @__PURE__ */ forwardRef(
|
|
3132
|
+
function SCircleProgress2({
|
|
3133
|
+
value = 0,
|
|
3134
|
+
type = "primary",
|
|
3135
|
+
indeterminate = false,
|
|
3136
|
+
size = DEFAULT_SIZE,
|
|
3137
|
+
label,
|
|
3138
|
+
innerValue = false,
|
|
3139
|
+
className,
|
|
3140
|
+
style
|
|
3141
|
+
}, ref) {
|
|
3142
|
+
const v = clamp(value);
|
|
3143
|
+
const dimension = typeof size === "number" ? `${size}px` : size;
|
|
3144
|
+
const colors = COLOR_MAP[type];
|
|
3145
|
+
const c = VIEWBOX / 2;
|
|
3146
|
+
const percentColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : colors.arc;
|
|
3147
|
+
const filled = v / 100 * CIRCUMFERENCE;
|
|
3148
|
+
const showPercent = !indeterminate;
|
|
3149
|
+
const percentNode = /* @__PURE__ */ jsxs(
|
|
3150
|
+
"span",
|
|
3151
|
+
{
|
|
3152
|
+
className: cn(
|
|
3153
|
+
"text-center text-[16px] font-bold",
|
|
3154
|
+
innerValue ? (
|
|
3155
|
+
// leading-[normal]: 26px leading 은 폰트 content(19px) 위아래로 홀수(7px)만큼 남아
|
|
3156
|
+
// 3px/4px 로 쪼개지고 글자가 링 중심보다 위로 뜬다. (leading-normal 은 1.5 라 동일 문제)
|
|
3157
|
+
"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 leading-[normal]"
|
|
3158
|
+
) : "leading-[26px]"
|
|
3159
|
+
),
|
|
3160
|
+
style: { color: percentColor },
|
|
3161
|
+
children: [
|
|
3162
|
+
Math.round(v),
|
|
3163
|
+
"%"
|
|
3164
|
+
]
|
|
3165
|
+
}
|
|
3166
|
+
);
|
|
3167
|
+
return /* @__PURE__ */ jsxs(
|
|
3168
|
+
"div",
|
|
3169
|
+
{
|
|
3170
|
+
ref,
|
|
3171
|
+
className: cn(
|
|
3172
|
+
"inline-flex flex-col items-center gap-[var(--cmp-progress-circular-gap)]",
|
|
3173
|
+
className
|
|
3174
|
+
),
|
|
3175
|
+
style,
|
|
3176
|
+
children: [
|
|
3177
|
+
/* @__PURE__ */ jsxs("div", { className: cn(innerValue && "relative"), children: [
|
|
3178
|
+
/* @__PURE__ */ jsxs(
|
|
3179
|
+
"svg",
|
|
3180
|
+
{
|
|
3181
|
+
viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
|
|
3182
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3183
|
+
className: cn(indeterminate && "origin-center animate-circle-spin"),
|
|
3184
|
+
style: { width: dimension, height: dimension },
|
|
3185
|
+
children: [
|
|
3186
|
+
/* @__PURE__ */ jsx(
|
|
3187
|
+
"circle",
|
|
3188
|
+
{
|
|
3189
|
+
cx: c,
|
|
3190
|
+
cy: c,
|
|
3191
|
+
r: RADIUS,
|
|
3192
|
+
fill: "none",
|
|
3193
|
+
strokeWidth: STROKE,
|
|
3194
|
+
style: { stroke: colors.track }
|
|
3195
|
+
}
|
|
3196
|
+
),
|
|
3197
|
+
/* @__PURE__ */ jsx(
|
|
3198
|
+
"circle",
|
|
3199
|
+
{
|
|
3200
|
+
cx: c,
|
|
3201
|
+
cy: c,
|
|
3202
|
+
r: RADIUS,
|
|
3203
|
+
fill: "none",
|
|
3204
|
+
strokeWidth: STROKE,
|
|
3205
|
+
strokeLinecap: "round",
|
|
3206
|
+
className: cn(
|
|
3207
|
+
"origin-center",
|
|
3208
|
+
indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
|
|
3209
|
+
),
|
|
3210
|
+
style: {
|
|
3211
|
+
stroke: colors.arc,
|
|
3212
|
+
...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
|
|
3213
|
+
}
|
|
3214
|
+
}
|
|
3215
|
+
)
|
|
3216
|
+
]
|
|
3217
|
+
}
|
|
3218
|
+
),
|
|
3219
|
+
showPercent && innerValue && percentNode
|
|
3220
|
+
] }),
|
|
3221
|
+
showPercent && !innerValue && percentNode,
|
|
3222
|
+
label && /* @__PURE__ */ jsx("span", { className: "text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]", children: label })
|
|
3223
|
+
]
|
|
3224
|
+
}
|
|
3225
|
+
);
|
|
3226
|
+
}
|
|
3227
|
+
);
|
|
3228
|
+
var IMAGE_FITS = ["cover", "contain", "fill", "none", "scale-down"];
|
|
3229
|
+
var EMPTY_ICON_SIZE = "60cqh";
|
|
3230
|
+
var SPINNER_SIZE = "45cqh";
|
|
3231
|
+
var SImage = /* @__PURE__ */ forwardRef(function SImage2({
|
|
3232
|
+
src,
|
|
3233
|
+
alt = "",
|
|
3234
|
+
ratio = 1,
|
|
3235
|
+
fit = "cover",
|
|
3236
|
+
position = "50% 50%",
|
|
3237
|
+
loading: loading2 = "lazy",
|
|
3238
|
+
loadingShowDelay = 0,
|
|
3239
|
+
noSpinner = false,
|
|
3240
|
+
loadingSlot,
|
|
3241
|
+
errorSlot,
|
|
3242
|
+
imgProps,
|
|
3243
|
+
onLoad,
|
|
3244
|
+
onError,
|
|
3245
|
+
className,
|
|
3246
|
+
style,
|
|
3247
|
+
...rest
|
|
3248
|
+
}, ref) {
|
|
3249
|
+
const [status, setStatus] = useState("loading");
|
|
3250
|
+
const [spinnerVisible, setSpinnerVisible] = useState(loadingShowDelay <= 0);
|
|
3251
|
+
const [trackedSrc, setTrackedSrc] = useState(src);
|
|
3252
|
+
const imgRef = useRef(null);
|
|
3253
|
+
if (src !== trackedSrc) {
|
|
3254
|
+
setTrackedSrc(src);
|
|
3255
|
+
setStatus("loading");
|
|
3256
|
+
}
|
|
3257
|
+
useEffect(() => {
|
|
3258
|
+
if (!src) return;
|
|
3259
|
+
const node = imgRef.current;
|
|
3260
|
+
if (node?.complete && node.naturalWidth > 0) {
|
|
3261
|
+
setStatus((current) => current === "loading" ? "loaded" : current);
|
|
3262
|
+
}
|
|
3263
|
+
}, [src]);
|
|
3264
|
+
useEffect(() => {
|
|
3265
|
+
if (status !== "loading" || loadingShowDelay <= 0) {
|
|
3266
|
+
setSpinnerVisible(status === "loading");
|
|
3267
|
+
return;
|
|
3268
|
+
}
|
|
3269
|
+
setSpinnerVisible(false);
|
|
3270
|
+
const timer = setTimeout(() => setSpinnerVisible(true), loadingShowDelay);
|
|
3271
|
+
return () => clearTimeout(timer);
|
|
3272
|
+
}, [status, loadingShowDelay, src]);
|
|
3273
|
+
const isEmpty = !src;
|
|
3274
|
+
const showFallback = isEmpty || status === "error";
|
|
3275
|
+
const showSpinner = !isEmpty && status === "loading" && !noSpinner && spinnerVisible;
|
|
3276
|
+
return /* @__PURE__ */ jsxs(
|
|
3277
|
+
"div",
|
|
3278
|
+
{
|
|
3279
|
+
ref,
|
|
3280
|
+
className: cn("relative overflow-hidden bg-(--cmp-image-bg)", className),
|
|
3281
|
+
style: { containerType: "size", aspectRatio: ratio, ...style },
|
|
3282
|
+
...rest,
|
|
3283
|
+
children: [
|
|
3284
|
+
!isEmpty && /* @__PURE__ */ jsx(
|
|
3285
|
+
"img",
|
|
3286
|
+
{
|
|
3287
|
+
...imgProps,
|
|
3288
|
+
ref: imgRef,
|
|
3289
|
+
src,
|
|
3290
|
+
alt,
|
|
3291
|
+
loading: loading2,
|
|
3292
|
+
onLoad: () => {
|
|
3293
|
+
setStatus("loaded");
|
|
3294
|
+
onLoad?.(src);
|
|
3295
|
+
},
|
|
3296
|
+
onError: (event) => {
|
|
3297
|
+
setStatus("error");
|
|
3298
|
+
onError?.(event);
|
|
3299
|
+
},
|
|
3300
|
+
className: cn(
|
|
3301
|
+
"h-full w-full",
|
|
3302
|
+
// 로딩 중에도 자리를 지켜야 브라우저가 계속 받아온다 — 숨기되 없애지 않는다
|
|
3303
|
+
status === "loaded" ? "visible" : "invisible",
|
|
3304
|
+
imgProps?.className
|
|
3305
|
+
),
|
|
3306
|
+
style: {
|
|
3307
|
+
objectFit: fit,
|
|
3308
|
+
objectPosition: position,
|
|
3309
|
+
...imgProps?.style
|
|
3310
|
+
}
|
|
3311
|
+
}
|
|
3312
|
+
),
|
|
3313
|
+
showFallback && /* @__PURE__ */ jsx("span", { className: "absolute inset-0 flex items-center justify-center", children: errorSlot ?? /* @__PURE__ */ jsx(SIcon, { name: "image", size: EMPTY_ICON_SIZE, color: "var(--cmp-image-icon)" }) }),
|
|
3314
|
+
showSpinner && /* @__PURE__ */ jsx("span", { className: "absolute inset-0 flex items-center justify-center", children: loadingSlot ?? /* @__PURE__ */ jsx(SCircleProgress, { indeterminate: true, type: "neutral", size: SPINNER_SIZE }) })
|
|
3315
|
+
]
|
|
3316
|
+
}
|
|
3317
|
+
);
|
|
3318
|
+
});
|
|
3094
3319
|
var BADGE_COLORS = [
|
|
3095
3320
|
"red",
|
|
3096
3321
|
"orange",
|
|
@@ -3192,12 +3417,13 @@ var SDraggableItemView = /* @__PURE__ */ forwardRef(
|
|
|
3192
3417
|
!disabled && !selected && !dragging && "hover:bg-(--cmp-listDraggableItem-bg-hover)",
|
|
3193
3418
|
hasSupportingText && supportingTextPosition === "bottom" ? dense ? "min-h-[52px]" : "min-h-[60px]" : dense ? "h-[32px]" : "h-[40px]",
|
|
3194
3419
|
paddingYClass,
|
|
3195
|
-
|
|
3420
|
+
// 항목 사이 구분선은 리스트가 그린다.
|
|
3421
|
+
bordered && cn(
|
|
3196
3422
|
"rounded-(--cmp-listDraggableItem-radius-bordered) border border-(--cmp-listDraggableItem-border-default)",
|
|
3197
3423
|
!disabled && !selected && !dragging && "hover:border-(--cmp-listDraggableItem-bordered-border-hover)",
|
|
3198
3424
|
!disabled && selected && !dragging && "border-(--cmp-listDraggableItem-bordered-border-selected) bg-(--cmp-listDraggableItem-bordered-bg-selected)",
|
|
3199
3425
|
!disabled && selected && dragging && "border-[length:var(--cmp-listDraggableItem-bordered-dragging-border-width)] border-(--cmp-listDraggableItem-bordered-dragging-border-color) bg-(--cmp-listDraggableItem-bordered-dragging-bg)"
|
|
3200
|
-
)
|
|
3426
|
+
),
|
|
3201
3427
|
disabled && "cursor-not-allowed",
|
|
3202
3428
|
className
|
|
3203
3429
|
),
|
|
@@ -3407,6 +3633,7 @@ var SListImpl = /* @__PURE__ */ forwardRef(function SList({ className, children,
|
|
|
3407
3633
|
className: cn(
|
|
3408
3634
|
useGap && "flex flex-col gap-(--cmp-list-group-gap)",
|
|
3409
3635
|
usePadding && "p-(--cmp-list-group-padding)",
|
|
3636
|
+
"[&>*]:border-b [&>*]:border-(--cmp-listItem-border-default)",
|
|
3410
3637
|
className
|
|
3411
3638
|
),
|
|
3412
3639
|
...rest,
|
|
@@ -3778,7 +4005,7 @@ var SExpansionItem = /* @__PURE__ */ forwardRef(
|
|
|
3778
4005
|
ref,
|
|
3779
4006
|
className: cn(
|
|
3780
4007
|
"group/expansion-item relative overflow-hidden bg-(--cmp-listExpansionItem-title-bg-default)",
|
|
3781
|
-
|
|
4008
|
+
// 항목 사이 구분선은 리스트가 그린다.
|
|
3782
4009
|
// 보더 색은 시맨틱 토큰(border-default → hover strong → 펼침 accentLight)을 쓴다.
|
|
3783
4010
|
// TODO: expansionItem/bordered/radius 토큰 생성 후 rounded 고정값도 토큰으로 교체한다.
|
|
3784
4011
|
bordered && "rounded-[8px] border border-border-default hover:border-border-strong [&:has(>button:hover)]:border-border-strong",
|
|
@@ -3888,7 +4115,7 @@ var SListItemImpl = /* @__PURE__ */ forwardRef(function SListItem({
|
|
|
3888
4115
|
trailing,
|
|
3889
4116
|
bordered = false,
|
|
3890
4117
|
selected = false,
|
|
3891
|
-
clickable =
|
|
4118
|
+
clickable = false,
|
|
3892
4119
|
interaction,
|
|
3893
4120
|
accentStripe = false,
|
|
3894
4121
|
dense = false,
|
|
@@ -3941,10 +4168,10 @@ var SListItemImpl = /* @__PURE__ */ forwardRef(function SListItem({
|
|
|
3941
4168
|
"gap-(--cmp-listItem-gap)",
|
|
3942
4169
|
"pr-(--cmp-listItem-paddingX)",
|
|
3943
4170
|
depth === 2 ? "pl-[36px]" : depth === 3 ? "pl-[56px]" : "pl-[16px]",
|
|
3944
|
-
bordered
|
|
4171
|
+
bordered && cn(
|
|
3945
4172
|
"overflow-hidden rounded-(--cmp-listItem-radius-bordered) border border-(--cmp-listItem-border-default)",
|
|
3946
4173
|
isSelected ? "border-(--cmp-listItem-bordered-border-selected)" : isInteractive && "hover:border-(--cmp-listItem-bordered-border-hover)"
|
|
3947
|
-
)
|
|
4174
|
+
),
|
|
3948
4175
|
className
|
|
3949
4176
|
),
|
|
3950
4177
|
...rest,
|
|
@@ -4023,6 +4250,8 @@ var SExpansionListImpl = /* @__PURE__ */ forwardRef(function SExpansionList({ ch
|
|
|
4023
4250
|
const depth2 = child.props.depth ?? 1;
|
|
4024
4251
|
const itemKey2 = String(child.key ?? index);
|
|
4025
4252
|
return cloneElement(child, {
|
|
4253
|
+
// 선택을 리스트가 관리하는 이상 아이템은 클릭 가능해야 한다 — SListItem 의 기본값(false)을 뒤집는다
|
|
4254
|
+
clickable: child.props.clickable ?? true,
|
|
4026
4255
|
selected: selectedKeys[depth2] === itemKey2,
|
|
4027
4256
|
onClick: (event) => {
|
|
4028
4257
|
setSelectedKeys((current) => ({ ...current, [depth2]: itemKey2 }));
|
|
@@ -4328,8 +4557,8 @@ function SGhostButton({
|
|
|
4328
4557
|
}
|
|
4329
4558
|
);
|
|
4330
4559
|
if (!hasTooltip) return btn;
|
|
4331
|
-
return /* @__PURE__ */ jsxs(
|
|
4332
|
-
/* @__PURE__ */ jsx(
|
|
4560
|
+
return /* @__PURE__ */ jsxs(RPopover10.Root, { open, onOpenChange: setOpen, children: [
|
|
4561
|
+
/* @__PURE__ */ jsx(RPopover10.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
4333
4562
|
"span",
|
|
4334
4563
|
{
|
|
4335
4564
|
className: cn("inline-flex", anchorClassName),
|
|
@@ -4341,8 +4570,8 @@ function SGhostButton({
|
|
|
4341
4570
|
children: btn
|
|
4342
4571
|
}
|
|
4343
4572
|
) }),
|
|
4344
|
-
/* @__PURE__ */ jsx(
|
|
4345
|
-
|
|
4573
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
4574
|
+
RPopover10.Content,
|
|
4346
4575
|
{
|
|
4347
4576
|
side: "top",
|
|
4348
4577
|
sideOffset: 4,
|
|
@@ -4356,6 +4585,18 @@ function SGhostButton({
|
|
|
4356
4585
|
) })
|
|
4357
4586
|
] });
|
|
4358
4587
|
}
|
|
4588
|
+
var TREE_LABEL_TYPOGRAPHY = {
|
|
4589
|
+
sm: {
|
|
4590
|
+
default: "typo-body-sm-medium",
|
|
4591
|
+
selected: "typo-body-sm-bold",
|
|
4592
|
+
rowHeight: "h-[28px]"
|
|
4593
|
+
},
|
|
4594
|
+
md: {
|
|
4595
|
+
default: "typo-body-md-medium",
|
|
4596
|
+
selected: "typo-body-md-bold",
|
|
4597
|
+
rowHeight: "h-[32px]"
|
|
4598
|
+
}
|
|
4599
|
+
};
|
|
4359
4600
|
function collectIds(nodes) {
|
|
4360
4601
|
return nodes.flatMap((node) => [node.id, ...collectIds(node.children ?? [])]);
|
|
4361
4602
|
}
|
|
@@ -4366,18 +4607,19 @@ function collectSelectableIds(node) {
|
|
|
4366
4607
|
function toSelectedSet(value) {
|
|
4367
4608
|
return new Set(value ?? []);
|
|
4368
4609
|
}
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4610
|
+
var TREE_ALL_NODE = { id: "__all__", label: "\uC804\uCCB4" };
|
|
4611
|
+
function getSelectionState(node, selectedSet, cascadeSelection) {
|
|
4612
|
+
if (!cascadeSelection) {
|
|
4613
|
+
return { selected: selectedSet.has(node.id), indeterminate: false };
|
|
4372
4614
|
}
|
|
4373
4615
|
const selectableChildren = (node.children ?? []).filter(
|
|
4374
4616
|
(child) => collectSelectableIds(child).length > 0
|
|
4375
4617
|
);
|
|
4376
4618
|
if (selectableChildren.length === 0) {
|
|
4377
|
-
return { selected:
|
|
4619
|
+
return { selected: selectedSet.has(node.id), indeterminate: false };
|
|
4378
4620
|
}
|
|
4379
4621
|
const childStates = selectableChildren.map(
|
|
4380
|
-
(child) => getSelectionState(child, selectedSet)
|
|
4622
|
+
(child) => getSelectionState(child, selectedSet, cascadeSelection)
|
|
4381
4623
|
);
|
|
4382
4624
|
const selectedCount = childStates.filter((state2) => state2.selected).length;
|
|
4383
4625
|
return {
|
|
@@ -4387,6 +4629,7 @@ function getSelectionState(node, selectedSet) {
|
|
|
4387
4629
|
}
|
|
4388
4630
|
function TreeConnector({
|
|
4389
4631
|
guideline,
|
|
4632
|
+
size,
|
|
4390
4633
|
depth,
|
|
4391
4634
|
hasChildren,
|
|
4392
4635
|
isLast,
|
|
@@ -4394,6 +4637,8 @@ function TreeConnector({
|
|
|
4394
4637
|
}) {
|
|
4395
4638
|
if (depth <= 1) return null;
|
|
4396
4639
|
const ancestorConnectors = ancestorLast.slice(0, -1);
|
|
4640
|
+
const branchTop = size === "sm" ? "top-[13px]" : "top-[15px]";
|
|
4641
|
+
const nodeHeight = size === "sm" ? "h-[15px]" : "h-[17px]";
|
|
4397
4642
|
return /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: "flex self-stretch", children: [
|
|
4398
4643
|
ancestorConnectors.map((last, index) => /* @__PURE__ */ jsx(
|
|
4399
4644
|
"span",
|
|
@@ -4407,13 +4652,22 @@ function TreeConnector({
|
|
|
4407
4652
|
/* @__PURE__ */ jsxs("span", { className: "relative block w-[20px] shrink-0", children: [
|
|
4408
4653
|
guideline && !isLast && /* @__PURE__ */ jsx("span", { className: "absolute bottom-0 left-[6px] top-[-1px] w-px bg-(--cmp-tree-connector-line-color)" }),
|
|
4409
4654
|
guideline && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4410
|
-
/* @__PURE__ */ jsx(
|
|
4655
|
+
/* @__PURE__ */ jsx(
|
|
4656
|
+
"span",
|
|
4657
|
+
{
|
|
4658
|
+
className: cn(
|
|
4659
|
+
"absolute left-[6px] top-[-1px] w-px bg-(--cmp-tree-connector-line-color)",
|
|
4660
|
+
nodeHeight
|
|
4661
|
+
)
|
|
4662
|
+
}
|
|
4663
|
+
),
|
|
4411
4664
|
/* @__PURE__ */ jsx(
|
|
4412
4665
|
"span",
|
|
4413
4666
|
{
|
|
4414
4667
|
"data-tree-connector-branch": hasChildren ? "parent" : "leaf",
|
|
4415
4668
|
className: cn(
|
|
4416
|
-
"absolute left-[6px]
|
|
4669
|
+
"absolute left-[6px] h-px bg-(--cmp-tree-connector-line-color)",
|
|
4670
|
+
branchTop,
|
|
4417
4671
|
hasChildren ? "w-[14px]" : "w-[calc(14px+var(--cmp-tree-item-arrow-icon))]"
|
|
4418
4672
|
)
|
|
4419
4673
|
}
|
|
@@ -4422,6 +4676,44 @@ function TreeConnector({
|
|
|
4422
4676
|
] })
|
|
4423
4677
|
] });
|
|
4424
4678
|
}
|
|
4679
|
+
function STreeAllItem({
|
|
4680
|
+
selected,
|
|
4681
|
+
indeterminate,
|
|
4682
|
+
border,
|
|
4683
|
+
size,
|
|
4684
|
+
onSelect
|
|
4685
|
+
}) {
|
|
4686
|
+
const checkboxValue = indeterminate ? null : selected;
|
|
4687
|
+
const typography = TREE_LABEL_TYPOGRAPHY[size];
|
|
4688
|
+
const labelTypo = selected || indeterminate ? typography.selected : typography.default;
|
|
4689
|
+
return /* @__PURE__ */ jsx(
|
|
4690
|
+
"div",
|
|
4691
|
+
{
|
|
4692
|
+
role: "treeitem",
|
|
4693
|
+
"aria-level": 1,
|
|
4694
|
+
"aria-selected": selected,
|
|
4695
|
+
onClick: onSelect,
|
|
4696
|
+
className: cn(
|
|
4697
|
+
"group/tree-item box-border flex w-full cursor-pointer items-center overflow-hidden bg-(--cmp-tree-item-bg-default) px-(--cmp-tree-item-paddingX) text-left hover:bg-(--cmp-tree-item-bg-hover)",
|
|
4698
|
+
typography.rowHeight,
|
|
4699
|
+
border && "border-b border-(--cmp-tree-item-border-default)"
|
|
4700
|
+
),
|
|
4701
|
+
children: /* @__PURE__ */ jsxs("div", { className: "box-border flex min-w-0 flex-1 items-center gap-(--cmp-tree-item-contentGap)", children: [
|
|
4702
|
+
/* @__PURE__ */ jsx("span", { onClick: (event) => event.stopPropagation(), className: "flex shrink-0", children: /* @__PURE__ */ jsx(SCheckbox, { value: checkboxValue, onValueChange: () => onSelect() }) }),
|
|
4703
|
+
/* @__PURE__ */ jsx(
|
|
4704
|
+
"span",
|
|
4705
|
+
{
|
|
4706
|
+
className: cn(
|
|
4707
|
+
"block min-w-0 flex-1 truncate py-(--cmp-tree-item-paddingY) text-(--cmp-tree-item-text-default)",
|
|
4708
|
+
labelTypo
|
|
4709
|
+
),
|
|
4710
|
+
children: "\uC804\uCCB4"
|
|
4711
|
+
}
|
|
4712
|
+
)
|
|
4713
|
+
] })
|
|
4714
|
+
}
|
|
4715
|
+
);
|
|
4716
|
+
}
|
|
4425
4717
|
var STreeItemImpl = /* @__PURE__ */ forwardRef(function STreeItem({
|
|
4426
4718
|
node,
|
|
4427
4719
|
depth = 1,
|
|
@@ -4433,6 +4725,7 @@ var STreeItemImpl = /* @__PURE__ */ forwardRef(function STreeItem({
|
|
|
4433
4725
|
border = true,
|
|
4434
4726
|
indeterminate = false,
|
|
4435
4727
|
selectable = true,
|
|
4728
|
+
size = "sm",
|
|
4436
4729
|
leading,
|
|
4437
4730
|
trailing,
|
|
4438
4731
|
onToggle,
|
|
@@ -4444,6 +4737,7 @@ var STreeItemImpl = /* @__PURE__ */ forwardRef(function STreeItem({
|
|
|
4444
4737
|
const renderState = {
|
|
4445
4738
|
node,
|
|
4446
4739
|
depth,
|
|
4740
|
+
size,
|
|
4447
4741
|
expanded,
|
|
4448
4742
|
selected,
|
|
4449
4743
|
indeterminate,
|
|
@@ -4453,6 +4747,8 @@ var STreeItemImpl = /* @__PURE__ */ forwardRef(function STreeItem({
|
|
|
4453
4747
|
const leadingNode = typeof leading === "function" ? leading(renderState) : leading;
|
|
4454
4748
|
const trailingNode = typeof trailing === "function" ? trailing(renderState) : trailing;
|
|
4455
4749
|
const checkboxValue = indeterminate ? null : selected;
|
|
4750
|
+
const typography = TREE_LABEL_TYPOGRAPHY[size];
|
|
4751
|
+
const labelTypo = selected || indeterminate ? typography.selected : typography.default;
|
|
4456
4752
|
const handleSelect = (event) => {
|
|
4457
4753
|
if (node.disabled) return;
|
|
4458
4754
|
onTreeSelect?.(node, event);
|
|
@@ -4472,7 +4768,8 @@ var STreeItemImpl = /* @__PURE__ */ forwardRef(function STreeItem({
|
|
|
4472
4768
|
"aria-disabled": node.disabled || void 0,
|
|
4473
4769
|
onClick: handleRowClick,
|
|
4474
4770
|
className: cn(
|
|
4475
|
-
"group/tree-item flex
|
|
4771
|
+
"group/tree-item box-border flex w-full items-center gap-(--cmp-tree-item-rowGap) overflow-hidden bg-(--cmp-tree-item-bg-default) px-(--cmp-tree-item-paddingX) text-left",
|
|
4772
|
+
typography.rowHeight,
|
|
4476
4773
|
border && "border-b border-(--cmp-tree-item-border-default)",
|
|
4477
4774
|
!node.disabled && "hover:bg-(--cmp-tree-item-bg-hover)",
|
|
4478
4775
|
node.disabled && "cursor-not-allowed opacity-60",
|
|
@@ -4485,13 +4782,14 @@ var STreeItemImpl = /* @__PURE__ */ forwardRef(function STreeItem({
|
|
|
4485
4782
|
TreeConnector,
|
|
4486
4783
|
{
|
|
4487
4784
|
guideline,
|
|
4785
|
+
size,
|
|
4488
4786
|
depth,
|
|
4489
4787
|
hasChildren,
|
|
4490
4788
|
isLast,
|
|
4491
4789
|
ancestorLast
|
|
4492
4790
|
}
|
|
4493
4791
|
),
|
|
4494
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-(--cmp-tree-item-contentGap)
|
|
4792
|
+
/* @__PURE__ */ jsxs("div", { className: "box-border flex min-w-0 flex-1 items-center gap-(--cmp-tree-item-contentGap)", children: [
|
|
4495
4793
|
hasChildren ? /* @__PURE__ */ jsx(
|
|
4496
4794
|
SGhostButton,
|
|
4497
4795
|
{
|
|
@@ -4527,25 +4825,17 @@ var STreeItemImpl = /* @__PURE__ */ forwardRef(function STreeItem({
|
|
|
4527
4825
|
/* @__PURE__ */ jsx(
|
|
4528
4826
|
"span",
|
|
4529
4827
|
{
|
|
4828
|
+
onClick: (event) => {
|
|
4829
|
+
if (!selectable) return;
|
|
4830
|
+
event.stopPropagation();
|
|
4831
|
+
if (!node.disabled && selectable) onTreeSelect?.(node, event);
|
|
4832
|
+
},
|
|
4530
4833
|
className: cn(
|
|
4531
|
-
"min-w-0 flex-1
|
|
4532
|
-
|
|
4834
|
+
"block min-w-0 flex-1 truncate py-(--cmp-tree-item-paddingY) text-(--cmp-tree-item-text-default)",
|
|
4835
|
+
labelTypo,
|
|
4836
|
+
node.disabled ? "cursor-not-allowed" : selectable ? "cursor-pointer" : void 0
|
|
4533
4837
|
),
|
|
4534
|
-
children:
|
|
4535
|
-
"span",
|
|
4536
|
-
{
|
|
4537
|
-
onClick: (event) => {
|
|
4538
|
-
if (!selectable) return;
|
|
4539
|
-
event.stopPropagation();
|
|
4540
|
-
if (!node.disabled && selectable) onTreeSelect?.(node, event);
|
|
4541
|
-
},
|
|
4542
|
-
className: cn(
|
|
4543
|
-
"inline-block max-w-full truncate",
|
|
4544
|
-
node.disabled ? "cursor-not-allowed" : selectable ? "cursor-pointer" : void 0
|
|
4545
|
-
),
|
|
4546
|
-
children: node.label
|
|
4547
|
-
}
|
|
4548
|
-
)
|
|
4838
|
+
children: node.label
|
|
4549
4839
|
}
|
|
4550
4840
|
),
|
|
4551
4841
|
trailingNode
|
|
@@ -4562,6 +4852,8 @@ var STreeImpl = /* @__PURE__ */ forwardRef(function STree({
|
|
|
4562
4852
|
expandedIds,
|
|
4563
4853
|
defaultExpandedIds,
|
|
4564
4854
|
selectable = true,
|
|
4855
|
+
size = "sm",
|
|
4856
|
+
useAll = false,
|
|
4565
4857
|
cascadeSelection = true,
|
|
4566
4858
|
guideline = true,
|
|
4567
4859
|
border = true,
|
|
@@ -4580,6 +4872,11 @@ var STreeImpl = /* @__PURE__ */ forwardRef(function STree({
|
|
|
4580
4872
|
const currentExpandedIds = expandedIds ?? internalExpandedIds;
|
|
4581
4873
|
const selectedSet = useMemo(() => toSelectedSet(currentValue), [currentValue]);
|
|
4582
4874
|
const expandedSet = useMemo(() => new Set(currentExpandedIds), [currentExpandedIds]);
|
|
4875
|
+
const selectableIds = useMemo(() => items.flatMap(collectSelectableIds), [items]);
|
|
4876
|
+
const allSelected = selectableIds.length > 0 && selectableIds.every((id) => selectedSet.has(id));
|
|
4877
|
+
const someSelected = selectableIds.some((id) => selectedSet.has(id));
|
|
4878
|
+
const allIndeterminate = someSelected && !allSelected;
|
|
4879
|
+
const showAllItem = selectable && useAll;
|
|
4583
4880
|
const updateExpanded = (node) => {
|
|
4584
4881
|
const next = new Set(currentExpandedIds);
|
|
4585
4882
|
if (next.has(node.id)) next.delete(node.id);
|
|
@@ -4591,7 +4888,7 @@ var STreeImpl = /* @__PURE__ */ forwardRef(function STree({
|
|
|
4591
4888
|
const updateSelected = (node) => {
|
|
4592
4889
|
if (node.disabled) return;
|
|
4593
4890
|
const targetIds = cascadeSelection ? collectSelectableIds(node) : [node.id];
|
|
4594
|
-
const everySelected = getSelectionState(node, selectedSet).selected;
|
|
4891
|
+
const everySelected = getSelectionState(node, selectedSet, cascadeSelection).selected;
|
|
4595
4892
|
const next = new Set(selectedSet);
|
|
4596
4893
|
targetIds.forEach((id) => {
|
|
4597
4894
|
if (everySelected) next.delete(id);
|
|
@@ -4601,10 +4898,22 @@ var STreeImpl = /* @__PURE__ */ forwardRef(function STree({
|
|
|
4601
4898
|
if (value === void 0) setInternalValue(orderedIds);
|
|
4602
4899
|
onValueChange?.(orderedIds, node);
|
|
4603
4900
|
};
|
|
4901
|
+
const updateAllSelected = (event) => {
|
|
4902
|
+
event?.stopPropagation();
|
|
4903
|
+
if (selectableIds.length === 0) return;
|
|
4904
|
+
const next = new Set(selectedSet);
|
|
4905
|
+
selectableIds.forEach((id) => {
|
|
4906
|
+
if (allSelected) next.delete(id);
|
|
4907
|
+
else next.add(id);
|
|
4908
|
+
});
|
|
4909
|
+
const orderedIds = collectIds(items).filter((id) => next.has(id));
|
|
4910
|
+
if (value === void 0) setInternalValue(orderedIds);
|
|
4911
|
+
onValueChange?.(orderedIds, TREE_ALL_NODE);
|
|
4912
|
+
};
|
|
4604
4913
|
const renderNodes = (nodes, depth = 1, ancestorLast = []) => nodes.map((node, index) => {
|
|
4605
4914
|
const isLast = index === nodes.length - 1;
|
|
4606
4915
|
const isExpanded = expandedSet.has(node.id);
|
|
4607
|
-
const { selected, indeterminate } = getSelectionState(node, selectedSet);
|
|
4916
|
+
const { selected, indeterminate } = getSelectionState(node, selectedSet, cascadeSelection);
|
|
4608
4917
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
4609
4918
|
/* @__PURE__ */ jsx(
|
|
4610
4919
|
STreeItem2,
|
|
@@ -4617,6 +4926,7 @@ var STreeImpl = /* @__PURE__ */ forwardRef(function STree({
|
|
|
4617
4926
|
selected,
|
|
4618
4927
|
indeterminate,
|
|
4619
4928
|
selectable,
|
|
4929
|
+
size,
|
|
4620
4930
|
guideline,
|
|
4621
4931
|
border,
|
|
4622
4932
|
leading,
|
|
@@ -4638,14 +4948,26 @@ var STreeImpl = /* @__PURE__ */ forwardRef(function STree({
|
|
|
4638
4948
|
) : null
|
|
4639
4949
|
] }, node.id);
|
|
4640
4950
|
});
|
|
4641
|
-
return /* @__PURE__ */
|
|
4951
|
+
return /* @__PURE__ */ jsxs(
|
|
4642
4952
|
"div",
|
|
4643
4953
|
{
|
|
4644
4954
|
ref,
|
|
4645
4955
|
role: "tree",
|
|
4646
4956
|
className: cn("flex w-full flex-col items-start bg-(--cmp-tree-item-bg-default)", className),
|
|
4647
4957
|
...rest,
|
|
4648
|
-
children:
|
|
4958
|
+
children: [
|
|
4959
|
+
showAllItem && /* @__PURE__ */ jsx(
|
|
4960
|
+
STreeAllItem,
|
|
4961
|
+
{
|
|
4962
|
+
selected: allSelected,
|
|
4963
|
+
indeterminate: allIndeterminate,
|
|
4964
|
+
border,
|
|
4965
|
+
size,
|
|
4966
|
+
onSelect: updateAllSelected
|
|
4967
|
+
}
|
|
4968
|
+
),
|
|
4969
|
+
renderNodes(items)
|
|
4970
|
+
]
|
|
4649
4971
|
}
|
|
4650
4972
|
);
|
|
4651
4973
|
});
|
|
@@ -4813,7 +5135,7 @@ var STooltipImpl = /* @__PURE__ */ forwardRef(function STooltip({
|
|
|
4813
5135
|
...restContentProps
|
|
4814
5136
|
} = contentProps ?? {};
|
|
4815
5137
|
const contentClass = cn(
|
|
4816
|
-
"z-50 w-fit
|
|
5138
|
+
"z-50 w-fit max-w-[var(--radix-popover-content-available-width)] rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px] shadow-normal-sm",
|
|
4817
5139
|
FLOATING_SLIDE_ANIM,
|
|
4818
5140
|
className,
|
|
4819
5141
|
contentPropsClassName
|
|
@@ -4825,14 +5147,14 @@ var STooltipImpl = /* @__PURE__ */ forwardRef(function STooltip({
|
|
|
4825
5147
|
...style,
|
|
4826
5148
|
...contentPropsStyle
|
|
4827
5149
|
};
|
|
4828
|
-
return /* @__PURE__ */ jsxs(
|
|
5150
|
+
return /* @__PURE__ */ jsxs(RPopover10.Root, { open, onOpenChange: setOpenState, children: [
|
|
4829
5151
|
isNone ? (
|
|
4830
5152
|
// 트리거 없음: children 을 래퍼 없이 그대로 앵커로 쓴다 (소비자 레이아웃 보존).
|
|
4831
5153
|
// mouse/focus 핸들러가 없으므로 useClose 없이도 자동 닫힘이 발생하지 않는다.
|
|
4832
|
-
/* @__PURE__ */ jsx(
|
|
5154
|
+
/* @__PURE__ */ jsx(RPopover10.Anchor, { asChild: true, children: triggerNode })
|
|
4833
5155
|
) : isHover ? (
|
|
4834
5156
|
// hover: Anchor(위치 기준) + 직접 mouse 핸들러 — 클릭으로 토글되지 않도록 Trigger 미사용
|
|
4835
|
-
/* @__PURE__ */ jsx(
|
|
5157
|
+
/* @__PURE__ */ jsx(RPopover10.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
4836
5158
|
"span",
|
|
4837
5159
|
{
|
|
4838
5160
|
className: "inline-flex",
|
|
@@ -4843,9 +5165,9 @@ var STooltipImpl = /* @__PURE__ */ forwardRef(function STooltip({
|
|
|
4843
5165
|
children: triggerNode
|
|
4844
5166
|
}
|
|
4845
5167
|
) })
|
|
4846
|
-
) : /* @__PURE__ */ jsx(
|
|
4847
|
-
/* @__PURE__ */ jsx(
|
|
4848
|
-
|
|
5168
|
+
) : /* @__PURE__ */ jsx(RPopover10.Trigger, { asChild: true, children: triggerNode }),
|
|
5169
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(
|
|
5170
|
+
RPopover10.Content,
|
|
4849
5171
|
{
|
|
4850
5172
|
side: placement,
|
|
4851
5173
|
sideOffset,
|
|
@@ -4879,7 +5201,7 @@ var STooltipImpl = /* @__PURE__ */ forwardRef(function STooltip({
|
|
|
4879
5201
|
}
|
|
4880
5202
|
)
|
|
4881
5203
|
] }),
|
|
4882
|
-
/* @__PURE__ */ jsx(
|
|
5204
|
+
/* @__PURE__ */ jsx(RPopover10.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
4883
5205
|
]
|
|
4884
5206
|
}
|
|
4885
5207
|
) })
|
|
@@ -4891,6 +5213,10 @@ var BODY_PADDING_CLASS = {
|
|
|
4891
5213
|
wide: "p-(--sys-space-panel-padding-wide)",
|
|
4892
5214
|
none: ""
|
|
4893
5215
|
};
|
|
5216
|
+
var BODY_BACKGROUND_CLASS = {
|
|
5217
|
+
frame: "",
|
|
5218
|
+
neutral: "bg-(--sys-color-bg-neutralLight)"
|
|
5219
|
+
};
|
|
4894
5220
|
var topBorderColorClass = {
|
|
4895
5221
|
default: "bg-(--cmp-sectionHeaderCard-topBorder-color-default)",
|
|
4896
5222
|
accent: "bg-(--cmp-sectionHeaderCard-topBorder-color-accent)"
|
|
@@ -4900,8 +5226,8 @@ var titleSizeClass = {
|
|
|
4900
5226
|
sm: "typo-heading-sm"
|
|
4901
5227
|
};
|
|
4902
5228
|
var SSectionHeaderCardBodyImpl = /* @__PURE__ */ forwardRef(
|
|
4903
|
-
function SSectionHeaderCardBody({ padding = "default",
|
|
4904
|
-
return /* @__PURE__ */ jsx("div", { ref, className: cn(BODY_PADDING_CLASS[padding],
|
|
5229
|
+
function SSectionHeaderCardBody({ padding = "default", background = "frame", children }, ref) {
|
|
5230
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn(BODY_PADDING_CLASS[padding], BODY_BACKGROUND_CLASS[background]), children });
|
|
4905
5231
|
}
|
|
4906
5232
|
);
|
|
4907
5233
|
var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ forwardRef(
|
|
@@ -4914,8 +5240,7 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ forwardRef(
|
|
|
4914
5240
|
subtitle,
|
|
4915
5241
|
slot,
|
|
4916
5242
|
thickness = false,
|
|
4917
|
-
className
|
|
4918
|
-
...rest
|
|
5243
|
+
className
|
|
4919
5244
|
}, ref) {
|
|
4920
5245
|
const hasHelp = helpText != null && helpText.length > 0;
|
|
4921
5246
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -4936,7 +5261,6 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ forwardRef(
|
|
|
4936
5261
|
"box-border flex min-h-(--cmp-sectionHeaderCard-header-minHeight) w-full shrink-0 items-center gap-(--cmp-sectionHeaderCard-header-gap) overflow-hidden border-b border-(--cmp-sectionHeaderCard-header-border) bg-(--cmp-sectionHeaderCard-header-bg) px-(--cmp-sectionHeaderCard-header-paddingX) py-(--cmp-sectionHeaderCard-header-paddingY)",
|
|
4937
5262
|
className
|
|
4938
5263
|
),
|
|
4939
|
-
...rest,
|
|
4940
5264
|
children: [
|
|
4941
5265
|
marker && /* @__PURE__ */ jsx(SBadge, { color: "darkblue", className: "shrink-0" }),
|
|
4942
5266
|
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 shrink-0 items-center gap-[8px]", children: [
|
|
@@ -4980,8 +5304,24 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ forwardRef(
|
|
|
4980
5304
|
}
|
|
4981
5305
|
);
|
|
4982
5306
|
var SSectionHeaderCardRootImpl = /* @__PURE__ */ forwardRef(
|
|
4983
|
-
function SSectionHeaderCard({
|
|
4984
|
-
|
|
5307
|
+
function SSectionHeaderCard({
|
|
5308
|
+
title,
|
|
5309
|
+
titleSize,
|
|
5310
|
+
marker,
|
|
5311
|
+
required,
|
|
5312
|
+
helpText,
|
|
5313
|
+
subtitle,
|
|
5314
|
+
slot,
|
|
5315
|
+
thickness,
|
|
5316
|
+
headerClassName,
|
|
5317
|
+
padding,
|
|
5318
|
+
background,
|
|
5319
|
+
className,
|
|
5320
|
+
children,
|
|
5321
|
+
...rest
|
|
5322
|
+
}, ref) {
|
|
5323
|
+
const hasHeader = title != null;
|
|
5324
|
+
return /* @__PURE__ */ jsxs(
|
|
4985
5325
|
"div",
|
|
4986
5326
|
{
|
|
4987
5327
|
ref,
|
|
@@ -4990,24 +5330,28 @@ var SSectionHeaderCardRootImpl = /* @__PURE__ */ forwardRef(
|
|
|
4990
5330
|
className
|
|
4991
5331
|
),
|
|
4992
5332
|
...rest,
|
|
4993
|
-
children
|
|
5333
|
+
children: [
|
|
5334
|
+
hasHeader && /* @__PURE__ */ jsx(
|
|
5335
|
+
SSectionHeaderCardHeaderImpl,
|
|
5336
|
+
{
|
|
5337
|
+
title,
|
|
5338
|
+
titleSize,
|
|
5339
|
+
marker,
|
|
5340
|
+
required,
|
|
5341
|
+
helpText,
|
|
5342
|
+
subtitle,
|
|
5343
|
+
slot,
|
|
5344
|
+
thickness,
|
|
5345
|
+
className: headerClassName
|
|
5346
|
+
}
|
|
5347
|
+
),
|
|
5348
|
+
/* @__PURE__ */ jsx(SSectionHeaderCardBodyImpl, { padding, background, children })
|
|
5349
|
+
]
|
|
4994
5350
|
}
|
|
4995
5351
|
);
|
|
4996
5352
|
}
|
|
4997
5353
|
);
|
|
4998
|
-
var
|
|
4999
|
-
var SSectionHeaderCardHeader2 = /* @__PURE__ */ withDisplayName(
|
|
5000
|
-
SSectionHeaderCardHeaderImpl,
|
|
5001
|
-
"SSectionHeaderCard.Header"
|
|
5002
|
-
);
|
|
5003
|
-
var SSectionHeaderCardBody2 = /* @__PURE__ */ withDisplayName(
|
|
5004
|
-
SSectionHeaderCardBodyImpl,
|
|
5005
|
-
"SSectionHeaderCard.Body"
|
|
5006
|
-
);
|
|
5007
|
-
var SSectionHeaderCard2 = /* @__PURE__ */ Object.assign(SSectionHeaderCardRoot, {
|
|
5008
|
-
Header: SSectionHeaderCardHeader2,
|
|
5009
|
-
Body: SSectionHeaderCardBody2
|
|
5010
|
-
});
|
|
5354
|
+
var SSectionHeaderCard2 = /* @__PURE__ */ withDisplayName(SSectionHeaderCardRootImpl, "SSectionHeaderCard");
|
|
5011
5355
|
var SDivider = /* @__PURE__ */ forwardRef(function SDivider2({ vertical = false, className, style, ...rest }, ref) {
|
|
5012
5356
|
return /* @__PURE__ */ jsx(
|
|
5013
5357
|
"hr",
|
|
@@ -5528,14 +5872,14 @@ var SCallout = /* @__PURE__ */ forwardRef(function SCallout2({ type = "default",
|
|
|
5528
5872
|
);
|
|
5529
5873
|
});
|
|
5530
5874
|
var FILL_COLOR = {
|
|
5531
|
-
primary: "var(--cmp-progress-active
|
|
5532
|
-
error: "var(--cmp-progress-error
|
|
5533
|
-
complete: "var(--cmp-progress-success
|
|
5875
|
+
primary: "var(--cmp-progress-color-active)",
|
|
5876
|
+
error: "var(--cmp-progress-color-error)",
|
|
5877
|
+
complete: "var(--cmp-progress-color-success)"
|
|
5534
5878
|
};
|
|
5535
|
-
var
|
|
5879
|
+
var clamp2 = (v) => Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;
|
|
5536
5880
|
var SLinearProgress = /* @__PURE__ */ forwardRef(
|
|
5537
5881
|
function SLinearProgress2({ value = 0, type = "primary", indeterminate = false, label, className, style }, ref) {
|
|
5538
|
-
const v =
|
|
5882
|
+
const v = clamp2(value);
|
|
5539
5883
|
const fill = FILL_COLOR[type];
|
|
5540
5884
|
const valueColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : fill;
|
|
5541
5885
|
const valueText = `${Math.round(v)}%`;
|
|
@@ -5582,115 +5926,6 @@ var SLinearProgress = /* @__PURE__ */ forwardRef(
|
|
|
5582
5926
|
);
|
|
5583
5927
|
}
|
|
5584
5928
|
);
|
|
5585
|
-
var VIEWBOX = 80;
|
|
5586
|
-
var RADIUS = 34;
|
|
5587
|
-
var STROKE = 12;
|
|
5588
|
-
var CIRCUMFERENCE = 2 * Math.PI * RADIUS;
|
|
5589
|
-
var COLOR_MAP = {
|
|
5590
|
-
primary: { arc: "var(--cmp-progress-active-color)", track: "var(--cmp-progress-color-track)" },
|
|
5591
|
-
// inverse: 어두운 배경용 — arc 흰색, track 은 흰색 40%(회색 링)
|
|
5592
|
-
inverse: { arc: "var(--color-white)", track: "rgba(255,255,255,0.4)" },
|
|
5593
|
-
error: { arc: "var(--color-red-75)", track: "var(--cmp-progress-color-track)" },
|
|
5594
|
-
complete: { arc: "#01BB4B", track: "var(--cmp-progress-color-track)" }
|
|
5595
|
-
};
|
|
5596
|
-
var clamp2 = (v) => Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;
|
|
5597
|
-
var SCircleProgress = /* @__PURE__ */ forwardRef(
|
|
5598
|
-
function SCircleProgress2({
|
|
5599
|
-
value = 0,
|
|
5600
|
-
type = "primary",
|
|
5601
|
-
indeterminate = false,
|
|
5602
|
-
label,
|
|
5603
|
-
innerValue = false,
|
|
5604
|
-
className,
|
|
5605
|
-
style
|
|
5606
|
-
}, ref) {
|
|
5607
|
-
const v = clamp2(value);
|
|
5608
|
-
const colors = COLOR_MAP[type];
|
|
5609
|
-
const c = VIEWBOX / 2;
|
|
5610
|
-
const percentColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : colors.arc;
|
|
5611
|
-
const filled = v / 100 * CIRCUMFERENCE;
|
|
5612
|
-
const showPercent = !indeterminate;
|
|
5613
|
-
const percentNode = /* @__PURE__ */ jsxs(
|
|
5614
|
-
"span",
|
|
5615
|
-
{
|
|
5616
|
-
className: cn(
|
|
5617
|
-
"text-center text-[16px] font-bold",
|
|
5618
|
-
innerValue ? (
|
|
5619
|
-
// leading-[normal]: 26px leading 은 폰트 content(19px) 위아래로 홀수(7px)만큼 남아
|
|
5620
|
-
// 3px/4px 로 쪼개지고 글자가 링 중심보다 위로 뜬다. (leading-normal 은 1.5 라 동일 문제)
|
|
5621
|
-
"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 leading-[normal]"
|
|
5622
|
-
) : "leading-[26px]"
|
|
5623
|
-
),
|
|
5624
|
-
style: { color: percentColor },
|
|
5625
|
-
children: [
|
|
5626
|
-
Math.round(v),
|
|
5627
|
-
"%"
|
|
5628
|
-
]
|
|
5629
|
-
}
|
|
5630
|
-
);
|
|
5631
|
-
return /* @__PURE__ */ jsxs(
|
|
5632
|
-
"div",
|
|
5633
|
-
{
|
|
5634
|
-
ref,
|
|
5635
|
-
className: cn(
|
|
5636
|
-
"inline-flex flex-col items-center gap-[var(--cmp-progress-circular-gap)]",
|
|
5637
|
-
className
|
|
5638
|
-
),
|
|
5639
|
-
style,
|
|
5640
|
-
children: [
|
|
5641
|
-
/* @__PURE__ */ jsxs("div", { className: cn(innerValue && "relative"), children: [
|
|
5642
|
-
/* @__PURE__ */ jsxs(
|
|
5643
|
-
"svg",
|
|
5644
|
-
{
|
|
5645
|
-
viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
|
|
5646
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
5647
|
-
className: cn(
|
|
5648
|
-
"h-[80px] w-[80px]",
|
|
5649
|
-
indeterminate && "origin-center animate-circle-spin"
|
|
5650
|
-
),
|
|
5651
|
-
children: [
|
|
5652
|
-
/* @__PURE__ */ jsx(
|
|
5653
|
-
"circle",
|
|
5654
|
-
{
|
|
5655
|
-
cx: c,
|
|
5656
|
-
cy: c,
|
|
5657
|
-
r: RADIUS,
|
|
5658
|
-
fill: "none",
|
|
5659
|
-
strokeWidth: STROKE,
|
|
5660
|
-
style: { stroke: colors.track }
|
|
5661
|
-
}
|
|
5662
|
-
),
|
|
5663
|
-
/* @__PURE__ */ jsx(
|
|
5664
|
-
"circle",
|
|
5665
|
-
{
|
|
5666
|
-
cx: c,
|
|
5667
|
-
cy: c,
|
|
5668
|
-
r: RADIUS,
|
|
5669
|
-
fill: "none",
|
|
5670
|
-
strokeWidth: STROKE,
|
|
5671
|
-
strokeLinecap: "round",
|
|
5672
|
-
className: cn(
|
|
5673
|
-
"origin-center",
|
|
5674
|
-
indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
|
|
5675
|
-
),
|
|
5676
|
-
style: {
|
|
5677
|
-
stroke: colors.arc,
|
|
5678
|
-
...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
|
|
5679
|
-
}
|
|
5680
|
-
}
|
|
5681
|
-
)
|
|
5682
|
-
]
|
|
5683
|
-
}
|
|
5684
|
-
),
|
|
5685
|
-
showPercent && innerValue && percentNode
|
|
5686
|
-
] }),
|
|
5687
|
-
showPercent && !innerValue && percentNode,
|
|
5688
|
-
label && /* @__PURE__ */ jsx("span", { className: "text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]", children: label })
|
|
5689
|
-
]
|
|
5690
|
-
}
|
|
5691
|
-
);
|
|
5692
|
-
}
|
|
5693
|
-
);
|
|
5694
5929
|
|
|
5695
5930
|
// src/lib/global-overlay.ts
|
|
5696
5931
|
var GLOBAL_OVERLAY_ATTR = "data-s-global-overlay";
|
|
@@ -5887,6 +6122,15 @@ var STextLink = /* @__PURE__ */ forwardRef(function STextLink2({
|
|
|
5887
6122
|
/* @__PURE__ */ jsx(RTooltip.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(RTooltip.Content, { side: "top", sideOffset: 4, className: cn("z-50", FLOATING_SLIDE_ANIM), children: /* @__PURE__ */ jsx(STag, { shape: "square", size: "xs", color: "grey", label: text }) }) })
|
|
5888
6123
|
] }) });
|
|
5889
6124
|
});
|
|
6125
|
+
|
|
6126
|
+
// src/lib/floating-width.ts
|
|
6127
|
+
var POPOVER_AVAILABLE_WIDTH = "var(--radix-popover-content-available-width)";
|
|
6128
|
+
var DROPDOWN_AVAILABLE_WIDTH = "var(--radix-dropdown-menu-content-available-width)";
|
|
6129
|
+
function clampToAvailableWidth(value, availableWidth) {
|
|
6130
|
+
if (value == null || value === "") return availableWidth;
|
|
6131
|
+
const css = typeof value === "number" ? `${value}px` : value;
|
|
6132
|
+
return `min(${css}, ${availableWidth})`;
|
|
6133
|
+
}
|
|
5890
6134
|
var SIZE2 = {
|
|
5891
6135
|
xs: { height: 24, paddingX: 8, gap: 6, arrow: 12, fontSize: 12, minWidth: 64, splitMinWidth: 72 },
|
|
5892
6136
|
sm: {
|
|
@@ -5923,6 +6167,7 @@ function splitDivider(color, outline) {
|
|
|
5923
6167
|
};
|
|
5924
6168
|
return (outline ? outlined : solid)[color];
|
|
5925
6169
|
}
|
|
6170
|
+
var VIEWPORT_PADDING = 12;
|
|
5926
6171
|
var itemClass = cn(
|
|
5927
6172
|
"flex min-h-[28px] cursor-pointer select-none items-center gap-[8px] rounded-[2px] px-[12px] py-[4px] text-[12px] leading-[20px] outline-none",
|
|
5928
6173
|
"text-[color:var(--sys-color-fg-secondary)]",
|
|
@@ -6004,12 +6249,16 @@ var SDropdownButtonImpl = /* @__PURE__ */ forwardRef(
|
|
|
6004
6249
|
sideOffset: 4,
|
|
6005
6250
|
align: "start",
|
|
6006
6251
|
alignOffset: split ? splitAlignOffset : 0,
|
|
6252
|
+
collisionPadding: VIEWPORT_PADDING,
|
|
6007
6253
|
className: cn(
|
|
6008
6254
|
"z-50 overflow-hidden rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] shadow-normal-sm",
|
|
6009
|
-
|
|
6255
|
+
// 창보다 넓은 메뉴는 창 폭에 맞춰 줄인다. 트리거 너비를 따르는 하한도 같은 상한으로
|
|
6256
|
+
// 감싸야 한다 — min-width 가 max-width 를 이기기 때문이다.
|
|
6257
|
+
"max-w-[var(--radix-dropdown-menu-content-available-width)]",
|
|
6258
|
+
!split && "min-w-[min(var(--radix-dropdown-menu-trigger-width),var(--radix-dropdown-menu-content-available-width))]",
|
|
6010
6259
|
FLOATING_SLIDE_ANIM
|
|
6011
6260
|
),
|
|
6012
|
-
style: split ? { minWidth: splitWidth } : void 0,
|
|
6261
|
+
style: split ? { minWidth: clampToAvailableWidth(splitWidth, DROPDOWN_AVAILABLE_WIDTH) } : void 0,
|
|
6013
6262
|
children: items.map((it) => /* @__PURE__ */ jsxs(
|
|
6014
6263
|
RDropdown.Item,
|
|
6015
6264
|
{
|
|
@@ -6021,7 +6270,7 @@ var SDropdownButtonImpl = /* @__PURE__ */ forwardRef(
|
|
|
6021
6270
|
/* @__PURE__ */ jsx(
|
|
6022
6271
|
"span",
|
|
6023
6272
|
{
|
|
6024
|
-
className: "min-w-0
|
|
6273
|
+
className: "min-w-0 break-words",
|
|
6025
6274
|
dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(it.label) }
|
|
6026
6275
|
}
|
|
6027
6276
|
)
|
|
@@ -6162,10 +6411,15 @@ function SSwitch({
|
|
|
6162
6411
|
}
|
|
6163
6412
|
);
|
|
6164
6413
|
}
|
|
6414
|
+
var SIZE_CLASSES = {
|
|
6415
|
+
xs: "h-[24px] px-[8px] text-[12px] font-normal leading-[20px]",
|
|
6416
|
+
sm: "h-[28px] px-[12px] text-[14px] font-medium leading-[24px]"
|
|
6417
|
+
};
|
|
6165
6418
|
function SToggle({
|
|
6166
6419
|
value = false,
|
|
6167
6420
|
label = "",
|
|
6168
6421
|
disabled = false,
|
|
6422
|
+
size = "sm",
|
|
6169
6423
|
onValueChange,
|
|
6170
6424
|
className,
|
|
6171
6425
|
style
|
|
@@ -6181,7 +6435,8 @@ function SToggle({
|
|
|
6181
6435
|
"aria-pressed": value,
|
|
6182
6436
|
onClick: () => !disabled && onValueChange?.(!value),
|
|
6183
6437
|
className: cn(
|
|
6184
|
-
"box-border inline-flex
|
|
6438
|
+
"box-border inline-flex items-center justify-center whitespace-nowrap rounded-full border border-solid transition-colors",
|
|
6439
|
+
SIZE_CLASSES[size],
|
|
6185
6440
|
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
6186
6441
|
// 미선택(off) hover 시 파란 채움 + 흰 글자
|
|
6187
6442
|
!disabled && !value && "hover:!bg-[var(--cmp-toggle-bg-hover)] hover:!text-[color:var(--cmp-toggle-content-hover)] hover:!border-[color:var(--cmp-toggle-bg-hover)]",
|
|
@@ -6233,16 +6488,20 @@ function SPopover({
|
|
|
6233
6488
|
const descColor = type === "default" ? "var(--cmp-popover-default-description)" : "var(--cmp-popover-light-description)";
|
|
6234
6489
|
const leftLinkLabelClass = type === "default" ? "text-[color:var(--cmp-popover-default-subAction)]" : "text-[color:var(--cmp-popover-light-subAction)]";
|
|
6235
6490
|
const triggerNode = trigger ?? /* @__PURE__ */ jsx("span", { className: "inline-flex cursor-pointer", "aria-label": ariaLabel, children: /* @__PURE__ */ jsx(SIcon, { name: icon, size: iconSize, color }) });
|
|
6236
|
-
return /* @__PURE__ */ jsxs(
|
|
6237
|
-
/* @__PURE__ */ jsx(
|
|
6238
|
-
/* @__PURE__ */ jsx(
|
|
6239
|
-
|
|
6491
|
+
return /* @__PURE__ */ jsxs(RPopover10.Root, { open: actualOpen, onOpenChange: setOpen, children: [
|
|
6492
|
+
/* @__PURE__ */ jsx(RPopover10.Trigger, { asChild: true, children: triggerNode }),
|
|
6493
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(
|
|
6494
|
+
RPopover10.Content,
|
|
6240
6495
|
{
|
|
6241
6496
|
side: placement,
|
|
6242
6497
|
sideOffset: 8,
|
|
6243
6498
|
className: cn(
|
|
6244
6499
|
// 닫기 버튼이 항상 있으므로 우측은 close clearance(36px) 로 고정
|
|
6245
|
-
"relative z-50 flex
|
|
6500
|
+
"relative z-50 flex flex-col gap-[var(--cmp-popover-gap)] rounded-[var(--cmp-popover-radius)] py-[var(--cmp-popover-paddingY)] px-[var(--cmp-popover-paddingX)] text-[12px] leading-[20px] shadow-normal-sm",
|
|
6501
|
+
// 창보다 넓어지면 창 폭에 맞춘다. 최소 너비도 같은 상한으로 감싼다 —
|
|
6502
|
+
// min-width 가 max-width 를 이기므로 감싸지 않으면 상한이 무력화된다.
|
|
6503
|
+
"max-w-[var(--radix-popover-content-available-width)]",
|
|
6504
|
+
"min-w-[min(160px,var(--radix-popover-content-available-width))]",
|
|
6246
6505
|
FLOATING_SLIDE_ANIM,
|
|
6247
6506
|
menuClassName
|
|
6248
6507
|
),
|
|
@@ -6298,7 +6557,7 @@ function SPopover({
|
|
|
6298
6557
|
]
|
|
6299
6558
|
}
|
|
6300
6559
|
),
|
|
6301
|
-
/* @__PURE__ */ jsx(
|
|
6560
|
+
/* @__PURE__ */ jsx(RPopover10.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
6302
6561
|
]
|
|
6303
6562
|
}
|
|
6304
6563
|
) })
|
|
@@ -6327,8 +6586,9 @@ function SPortal({
|
|
|
6327
6586
|
ariaLabel
|
|
6328
6587
|
}) {
|
|
6329
6588
|
const portalContainer = usePortalContainer();
|
|
6589
|
+
const { minWidth: styleMinWidth, maxWidth: styleMaxWidth, ...restStyle } = style ?? {};
|
|
6330
6590
|
return /* @__PURE__ */ jsxs(
|
|
6331
|
-
|
|
6591
|
+
RPopover10.Root,
|
|
6332
6592
|
{
|
|
6333
6593
|
open,
|
|
6334
6594
|
onOpenChange: (next) => {
|
|
@@ -6336,9 +6596,9 @@ function SPortal({
|
|
|
6336
6596
|
if (!next) onClose?.();
|
|
6337
6597
|
},
|
|
6338
6598
|
children: [
|
|
6339
|
-
/* @__PURE__ */ jsx(
|
|
6340
|
-
/* @__PURE__ */ jsx(
|
|
6341
|
-
|
|
6599
|
+
/* @__PURE__ */ jsx(RPopover10.Anchor, { virtualRef: anchorRef }),
|
|
6600
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
6601
|
+
RPopover10.Content,
|
|
6342
6602
|
{
|
|
6343
6603
|
side: placement,
|
|
6344
6604
|
align,
|
|
@@ -6365,11 +6625,18 @@ function SPortal({
|
|
|
6365
6625
|
className: cn(
|
|
6366
6626
|
"z-50 overflow-hidden rounded-(--cmp-listBox-radius) bg-(--cmp-listBox-bg) shadow-normal-sm",
|
|
6367
6627
|
maxHeight != null && "overflow-y-auto",
|
|
6368
|
-
|
|
6628
|
+
// 앵커가 창보다 넓을 수 있는 자리(가로 스크롤 안의 트리거 등)에서도 하한이 상한을
|
|
6629
|
+
// 이기지 않도록, 앵커 너비 역시 가용 폭으로 가둔다.
|
|
6630
|
+
fit && "min-w-[min(var(--radix-popover-trigger-width),var(--radix-popover-content-available-width))]",
|
|
6369
6631
|
FLOATING_SLIDE_ANIM,
|
|
6370
6632
|
className
|
|
6371
6633
|
),
|
|
6372
|
-
style: {
|
|
6634
|
+
style: {
|
|
6635
|
+
maxHeight,
|
|
6636
|
+
...restStyle,
|
|
6637
|
+
...styleMinWidth != null ? { minWidth: clampToAvailableWidth(styleMinWidth, POPOVER_AVAILABLE_WIDTH) } : {},
|
|
6638
|
+
maxWidth: clampToAvailableWidth(styleMaxWidth, POPOVER_AVAILABLE_WIDTH)
|
|
6639
|
+
},
|
|
6373
6640
|
children
|
|
6374
6641
|
}
|
|
6375
6642
|
) })
|
|
@@ -6529,16 +6796,18 @@ function SGuide({
|
|
|
6529
6796
|
);
|
|
6530
6797
|
if (isNotion)
|
|
6531
6798
|
return /* @__PURE__ */ jsx("span", { className, style, children: trigger });
|
|
6532
|
-
return /* @__PURE__ */ jsxs(
|
|
6533
|
-
/* @__PURE__ */ jsx(
|
|
6534
|
-
/* @__PURE__ */ jsx(
|
|
6535
|
-
|
|
6799
|
+
return /* @__PURE__ */ jsxs(RPopover10.Root, { open, onOpenChange: setOpen, children: [
|
|
6800
|
+
/* @__PURE__ */ jsx(RPopover10.Trigger, { asChild: true, children: trigger }),
|
|
6801
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(
|
|
6802
|
+
RPopover10.Content,
|
|
6536
6803
|
{
|
|
6537
6804
|
side: "bottom",
|
|
6538
6805
|
align: "start",
|
|
6539
6806
|
sideOffset: 4,
|
|
6540
6807
|
className: cn(
|
|
6541
6808
|
"relative z-50 rounded-[var(--cmp-guide-contents-radius)] bg-[var(--color-white)]",
|
|
6809
|
+
// popupWidth(기본 426px)가 창보다 넓으면 창 폭에 맞춘다 — max-width 가 width 를 이긴다.
|
|
6810
|
+
"max-w-[var(--radix-popover-content-available-width)]",
|
|
6542
6811
|
FLOATING_SLIDE_ANIM
|
|
6543
6812
|
),
|
|
6544
6813
|
style: {
|
|
@@ -6713,7 +6982,7 @@ function SModalContainer({
|
|
|
6713
6982
|
"div",
|
|
6714
6983
|
{
|
|
6715
6984
|
className: cn(
|
|
6716
|
-
"relative flex max-h-[
|
|
6985
|
+
"relative flex max-h-[85dvh] max-w-[calc(100dvw-48px)] flex-col overflow-hidden rounded-[var(--cmp-modal-radius)] bg-[var(--cmp-modal-bg)] shadow-normal-md",
|
|
6717
6986
|
shaking && "animate-modal-shake",
|
|
6718
6987
|
className
|
|
6719
6988
|
),
|
|
@@ -6970,7 +7239,7 @@ function SActionModal({
|
|
|
6970
7239
|
showClose: true,
|
|
6971
7240
|
width,
|
|
6972
7241
|
height,
|
|
6973
|
-
className: "w-fit min-w-[min(480px,calc(100dvw-48px))] min-h-[min(320px,
|
|
7242
|
+
className: "w-fit min-w-[min(480px,calc(100dvw-48px))] min-h-[min(320px,85dvh)]",
|
|
6974
7243
|
children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-auto flex-col", children: [
|
|
6975
7244
|
/* @__PURE__ */ jsx(SOverlayHeader, { title: modalTitle, description, reserveCloseSpace: true }),
|
|
6976
7245
|
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-auto px-[var(--cmp-modal-action-body-paddingX)] pb-[var(--cmp-modal-action-body-paddingBottom)]", children }),
|
|
@@ -7863,15 +8132,21 @@ var GNB_MENU = {
|
|
|
7863
8132
|
depth2PaddingLeft: box("item-depth2-paddingLeft"),
|
|
7864
8133
|
depth3PaddingLeft: box("item-depth3-paddingLeft"),
|
|
7865
8134
|
depth1Icon: box("item-depth1-icon"),
|
|
8135
|
+
// box 는 depth1 전용 타이포 토큰이 없어 depth1 도 selected 타이포를 따른다
|
|
7866
8136
|
depth1FontSize: 14,
|
|
7867
8137
|
// token: gnb.box.item.typography.selected.fontSize
|
|
7868
8138
|
depth1LineHeight: 24,
|
|
7869
8139
|
// token: gnb.box.item.typography.selected.lineHeight
|
|
7870
|
-
depth1FontWeight:
|
|
8140
|
+
depth1FontWeight: 600,
|
|
8141
|
+
// token: gnb.box.item.typography.selected.fontWeight
|
|
7871
8142
|
itemFontSize: 14,
|
|
7872
8143
|
// token: gnb.box.item.typography.default.fontSize
|
|
7873
|
-
itemLineHeight: 24
|
|
8144
|
+
itemLineHeight: 24,
|
|
7874
8145
|
// token: gnb.box.item.typography.default.lineHeight
|
|
8146
|
+
itemFontWeight: 500,
|
|
8147
|
+
// token: gnb.box.item.typography.default.fontWeight
|
|
8148
|
+
itemFontWeightSelected: 600
|
|
8149
|
+
// token: gnb.box.item.typography.selected.fontWeight
|
|
7875
8150
|
},
|
|
7876
8151
|
belt: {
|
|
7877
8152
|
bodyPaddingY: gnb("body-padding"),
|
|
@@ -7893,10 +8168,15 @@ var GNB_MENU = {
|
|
|
7893
8168
|
depth1LineHeight: 22,
|
|
7894
8169
|
// token: gnb.belt.item.depth1.typography.lineHeight
|
|
7895
8170
|
depth1FontWeight: 700,
|
|
8171
|
+
// token: gnb.belt.item.depth1.typography.fontWeight
|
|
7896
8172
|
itemFontSize: 12,
|
|
7897
8173
|
// token: gnb.belt.item.typography.default.fontSize
|
|
7898
|
-
itemLineHeight: 20
|
|
8174
|
+
itemLineHeight: 20,
|
|
7899
8175
|
// token: gnb.belt.item.typography.default.lineHeight
|
|
8176
|
+
itemFontWeight: 500,
|
|
8177
|
+
// token: gnb.belt.item.typography.default.fontWeight
|
|
8178
|
+
itemFontWeightSelected: 700
|
|
8179
|
+
// token: gnb.belt.item.typography.selected.fontWeight
|
|
7900
8180
|
}
|
|
7901
8181
|
};
|
|
7902
8182
|
var GNB_COLORS = {
|
|
@@ -8194,7 +8474,7 @@ var SGnb = /* @__PURE__ */ forwardRef(function SGnb2({
|
|
|
8194
8474
|
fontFamily: "inherit",
|
|
8195
8475
|
fontSize: depth === 1 ? M.depth1FontSize : M.itemFontSize,
|
|
8196
8476
|
lineHeight: `${depth === 1 ? M.depth1LineHeight : M.itemLineHeight}px`,
|
|
8197
|
-
fontWeight: depth === 1
|
|
8477
|
+
fontWeight: depth === 1 ? M.depth1FontWeight : isSelected ? M.itemFontWeightSelected : M.itemFontWeight,
|
|
8198
8478
|
opacity: item.disabled ? 0.4 : 1,
|
|
8199
8479
|
cursor: item.disabled ? "not-allowed" : "pointer"
|
|
8200
8480
|
};
|
|
@@ -8611,10 +8891,10 @@ var SGnb = /* @__PURE__ */ forwardRef(function SGnb2({
|
|
|
8611
8891
|
}
|
|
8612
8892
|
),
|
|
8613
8893
|
header === "fix" && menuResizeHandle,
|
|
8614
|
-
/* @__PURE__ */ jsxs(
|
|
8615
|
-
/* @__PURE__ */ jsx(
|
|
8616
|
-
/* @__PURE__ */ jsx(
|
|
8617
|
-
|
|
8894
|
+
/* @__PURE__ */ jsxs(RPopover10.Root, { open: labelTip !== null, onOpenChange: (open) => !open && setLabelTip(null), children: [
|
|
8895
|
+
/* @__PURE__ */ jsx(RPopover10.Anchor, { virtualRef: labelTipAnchorRef }),
|
|
8896
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
8897
|
+
RPopover10.Content,
|
|
8618
8898
|
{
|
|
8619
8899
|
side: "right",
|
|
8620
8900
|
sideOffset: 4,
|
|
@@ -8632,41 +8912,310 @@ var SGnb = /* @__PURE__ */ forwardRef(function SGnb2({
|
|
|
8632
8912
|
}
|
|
8633
8913
|
);
|
|
8634
8914
|
});
|
|
8915
|
+
var SPageHeader = /* @__PURE__ */ withDisplayName(
|
|
8916
|
+
forwardRef(function SPageHeader2({ title, subText, fix = false, onBack, slot, scrolled = false, className, style, ...rest }, ref) {
|
|
8917
|
+
const hasBack = onBack != null;
|
|
8918
|
+
return /* @__PURE__ */ jsxs(
|
|
8919
|
+
"header",
|
|
8920
|
+
{
|
|
8921
|
+
ref,
|
|
8922
|
+
className: cn(
|
|
8923
|
+
"relative z-10 box-border flex shrink-0 items-center gap-(--cmp-pageHeader-gap) px-(--cmp-pageHeader-paddingX)",
|
|
8924
|
+
fix ? "h-(--cmp-pageHeader-bar-height) border-b border-(--cmp-pageHeader-bar-border) bg-(--cmp-pageHeader-bar-bg) py-(--cmp-pageHeader-bar-paddingY)" : cn(
|
|
8925
|
+
// 배경은 항상 투명 — 페이지 배경을 따라갈지는 fix 가 정하지 scrolled 가 정하지 않는다.
|
|
8926
|
+
// 스크롤되면 그림자만 더해 콘텐츠 위에 뜬 것처럼 보이게 한다.
|
|
8927
|
+
"bg-transparent pt-(--cmp-pageHeader-plain-paddingTop) pb-(--cmp-pageHeader-plain-paddingBottom)",
|
|
8928
|
+
scrolled && "shadow-floating"
|
|
8929
|
+
),
|
|
8930
|
+
className
|
|
8931
|
+
),
|
|
8932
|
+
style,
|
|
8933
|
+
...rest,
|
|
8934
|
+
children: [
|
|
8935
|
+
hasBack && /* @__PURE__ */ jsx(
|
|
8936
|
+
SGhostButton,
|
|
8937
|
+
{
|
|
8938
|
+
icon: "chevronLeft",
|
|
8939
|
+
size: "xs",
|
|
8940
|
+
ariaLabel: "\uB4A4\uB85C\uAC00\uAE30",
|
|
8941
|
+
onClick: onBack,
|
|
8942
|
+
className: "shrink-0"
|
|
8943
|
+
}
|
|
8944
|
+
),
|
|
8945
|
+
/* @__PURE__ */ jsxs(
|
|
8946
|
+
"div",
|
|
8947
|
+
{
|
|
8948
|
+
className: cn(
|
|
8949
|
+
"flex min-w-0 flex-1 items-center",
|
|
8950
|
+
fix ? "flex-row gap-(--cmp-pageHeader-gap)" : "flex-col items-start gap-(--cmp-pageHeader-plain-title-gap)",
|
|
8951
|
+
!hasBack && "pl-(--cmp-pageHeader-title-paddingLeft)"
|
|
8952
|
+
),
|
|
8953
|
+
children: [
|
|
8954
|
+
/* @__PURE__ */ jsx("span", { className: "typo-heading-lg min-w-0 truncate text-(--cmp-pageHeader-title-text)", children: title }),
|
|
8955
|
+
subText && /* @__PURE__ */ jsx("span", { className: "typo-body-md-default min-w-0 truncate text-(--cmp-pageHeader-subtitle-text)", children: subText })
|
|
8956
|
+
]
|
|
8957
|
+
}
|
|
8958
|
+
),
|
|
8959
|
+
slot && /* @__PURE__ */ jsx("div", { className: "ml-auto flex shrink-0 items-center", children: slot })
|
|
8960
|
+
]
|
|
8961
|
+
}
|
|
8962
|
+
);
|
|
8963
|
+
}),
|
|
8964
|
+
"SPageHeader"
|
|
8965
|
+
);
|
|
8635
8966
|
var MIN_CONTENT_WIDTH = `calc(var(${SLAYOUT_MIN_WIDTH_VAR}, 0px) - 100cqw + 100%)`;
|
|
8636
8967
|
var BACKGROUND_CLASS = {
|
|
8637
|
-
frame:
|
|
8638
|
-
neutral:
|
|
8639
|
-
screen:
|
|
8968
|
+
frame: "bg-[var(--sys-color-bg-frame)]",
|
|
8969
|
+
neutral: "bg-[var(--sys-color-bg-neutralLight)]",
|
|
8970
|
+
screen: "bg-[var(--sys-color-bg-screen)]"
|
|
8971
|
+
};
|
|
8972
|
+
var NATIVE_SCROLLBAR_BACKGROUND_CLASS = {
|
|
8973
|
+
frame: `${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_CLASS}`,
|
|
8974
|
+
neutral: `${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_WHITE_CLASS}`,
|
|
8975
|
+
screen: `${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_CLASS}`
|
|
8976
|
+
};
|
|
8977
|
+
var SCROLLBAR_SIZE = 12;
|
|
8978
|
+
var SCROLLBAR_MIN_THUMB_SIZE = 32;
|
|
8979
|
+
var getMetrics = (viewportSize, contentSize, scrollOffset) => {
|
|
8980
|
+
if (contentSize <= viewportSize) {
|
|
8981
|
+
return { visible: false, thumbSize: 0, thumbOffset: 0 };
|
|
8982
|
+
}
|
|
8983
|
+
const trackSize = viewportSize;
|
|
8984
|
+
const maxScrollOffset = contentSize - viewportSize;
|
|
8985
|
+
const thumbSize = Math.min(
|
|
8986
|
+
trackSize,
|
|
8987
|
+
Math.max(SCROLLBAR_MIN_THUMB_SIZE, viewportSize / contentSize * trackSize)
|
|
8988
|
+
);
|
|
8989
|
+
const maxThumbOffset = trackSize - thumbSize;
|
|
8990
|
+
const thumbOffset = maxScrollOffset > 0 ? scrollOffset / maxScrollOffset * maxThumbOffset : 0;
|
|
8991
|
+
return { visible: true, thumbSize, thumbOffset };
|
|
8640
8992
|
};
|
|
8641
|
-
var
|
|
8993
|
+
var setForwardedRef = (ref, node) => {
|
|
8994
|
+
if (typeof ref === "function") {
|
|
8995
|
+
ref(node);
|
|
8996
|
+
return;
|
|
8997
|
+
}
|
|
8998
|
+
if (ref) ref.current = node;
|
|
8999
|
+
};
|
|
9000
|
+
function SPageOverlayScrollbars({ scrollRef }) {
|
|
9001
|
+
const [vertical, setVertical] = useState({
|
|
9002
|
+
visible: false,
|
|
9003
|
+
thumbSize: 0,
|
|
9004
|
+
thumbOffset: 0
|
|
9005
|
+
});
|
|
9006
|
+
const [horizontal, setHorizontal] = useState({
|
|
9007
|
+
visible: false,
|
|
9008
|
+
thumbSize: 0,
|
|
9009
|
+
thumbOffset: 0
|
|
9010
|
+
});
|
|
9011
|
+
const update = useCallback(() => {
|
|
9012
|
+
const el = scrollRef.current;
|
|
9013
|
+
if (!el) return;
|
|
9014
|
+
setVertical(getMetrics(el.clientHeight, el.scrollHeight, el.scrollTop));
|
|
9015
|
+
setHorizontal(getMetrics(el.clientWidth, el.scrollWidth, el.scrollLeft));
|
|
9016
|
+
}, [scrollRef]);
|
|
9017
|
+
useEffect(() => {
|
|
9018
|
+
const el = scrollRef.current;
|
|
9019
|
+
if (!el) return;
|
|
9020
|
+
update();
|
|
9021
|
+
el.addEventListener("scroll", update, { passive: true });
|
|
9022
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(update);
|
|
9023
|
+
observer?.observe(el);
|
|
9024
|
+
if (el.firstElementChild) observer?.observe(el.firstElementChild);
|
|
9025
|
+
return () => {
|
|
9026
|
+
el.removeEventListener("scroll", update);
|
|
9027
|
+
observer?.disconnect();
|
|
9028
|
+
};
|
|
9029
|
+
}, [scrollRef, update]);
|
|
9030
|
+
const dragVertical = (startEvent) => {
|
|
9031
|
+
const el = scrollRef.current;
|
|
9032
|
+
if (!el || !vertical.visible) return;
|
|
9033
|
+
startEvent.preventDefault();
|
|
9034
|
+
startEvent.currentTarget.setPointerCapture(startEvent.pointerId);
|
|
9035
|
+
const startPointer = startEvent.clientY;
|
|
9036
|
+
const startScrollTop = el.scrollTop;
|
|
9037
|
+
const maxThumbOffset = el.clientHeight - vertical.thumbSize;
|
|
9038
|
+
const maxScrollTop = el.scrollHeight - el.clientHeight;
|
|
9039
|
+
if (maxThumbOffset <= 0 || maxScrollTop <= 0) return;
|
|
9040
|
+
const onPointerMove = (moveEvent) => {
|
|
9041
|
+
const delta = moveEvent.clientY - startPointer;
|
|
9042
|
+
el.scrollTop = startScrollTop + delta / maxThumbOffset * maxScrollTop;
|
|
9043
|
+
};
|
|
9044
|
+
const onPointerUp = () => {
|
|
9045
|
+
window.removeEventListener("pointermove", onPointerMove);
|
|
9046
|
+
window.removeEventListener("pointerup", onPointerUp);
|
|
9047
|
+
};
|
|
9048
|
+
window.addEventListener("pointermove", onPointerMove);
|
|
9049
|
+
window.addEventListener("pointerup", onPointerUp, { once: true });
|
|
9050
|
+
};
|
|
9051
|
+
const dragHorizontal = (startEvent) => {
|
|
9052
|
+
const el = scrollRef.current;
|
|
9053
|
+
if (!el || !horizontal.visible) return;
|
|
9054
|
+
startEvent.preventDefault();
|
|
9055
|
+
startEvent.currentTarget.setPointerCapture(startEvent.pointerId);
|
|
9056
|
+
const startPointer = startEvent.clientX;
|
|
9057
|
+
const startScrollLeft = el.scrollLeft;
|
|
9058
|
+
const maxThumbOffset = el.clientWidth - horizontal.thumbSize;
|
|
9059
|
+
const maxScrollLeft = el.scrollWidth - el.clientWidth;
|
|
9060
|
+
if (maxThumbOffset <= 0 || maxScrollLeft <= 0) return;
|
|
9061
|
+
const onPointerMove = (moveEvent) => {
|
|
9062
|
+
const delta = moveEvent.clientX - startPointer;
|
|
9063
|
+
el.scrollLeft = startScrollLeft + delta / maxThumbOffset * maxScrollLeft;
|
|
9064
|
+
};
|
|
9065
|
+
const onPointerUp = () => {
|
|
9066
|
+
window.removeEventListener("pointermove", onPointerMove);
|
|
9067
|
+
window.removeEventListener("pointerup", onPointerUp);
|
|
9068
|
+
};
|
|
9069
|
+
window.addEventListener("pointermove", onPointerMove);
|
|
9070
|
+
window.addEventListener("pointerup", onPointerUp, { once: true });
|
|
9071
|
+
};
|
|
9072
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9073
|
+
vertical.visible && /* @__PURE__ */ jsx(
|
|
9074
|
+
"div",
|
|
9075
|
+
{
|
|
9076
|
+
"aria-hidden": "true",
|
|
9077
|
+
className: "pointer-events-none absolute bottom-0 right-0 top-0 z-[1] w-[12px]",
|
|
9078
|
+
style: { bottom: horizontal.visible ? SCROLLBAR_SIZE : 0 },
|
|
9079
|
+
children: /* @__PURE__ */ jsx(
|
|
9080
|
+
"div",
|
|
9081
|
+
{
|
|
9082
|
+
className: "pointer-events-auto absolute right-[2px] w-[8px] cursor-default touch-none rounded-full bg-[var(--color-grey-45)]",
|
|
9083
|
+
style: {
|
|
9084
|
+
height: vertical.thumbSize,
|
|
9085
|
+
transform: `translateY(${vertical.thumbOffset}px)`
|
|
9086
|
+
},
|
|
9087
|
+
onPointerDown: dragVertical
|
|
9088
|
+
}
|
|
9089
|
+
)
|
|
9090
|
+
}
|
|
9091
|
+
),
|
|
9092
|
+
horizontal.visible && /* @__PURE__ */ jsx(
|
|
9093
|
+
"div",
|
|
9094
|
+
{
|
|
9095
|
+
"aria-hidden": "true",
|
|
9096
|
+
className: "pointer-events-none absolute bottom-0 left-0 right-0 z-[1] h-[12px]",
|
|
9097
|
+
style: { right: vertical.visible ? SCROLLBAR_SIZE : 0 },
|
|
9098
|
+
children: /* @__PURE__ */ jsx(
|
|
9099
|
+
"div",
|
|
9100
|
+
{
|
|
9101
|
+
className: "pointer-events-auto absolute bottom-[2px] h-[8px] cursor-default touch-none rounded-full bg-[var(--color-grey-45)]",
|
|
9102
|
+
style: {
|
|
9103
|
+
width: horizontal.thumbSize,
|
|
9104
|
+
transform: `translateX(${horizontal.thumbOffset}px)`
|
|
9105
|
+
},
|
|
9106
|
+
onPointerDown: dragHorizontal
|
|
9107
|
+
}
|
|
9108
|
+
)
|
|
9109
|
+
}
|
|
9110
|
+
)
|
|
9111
|
+
] });
|
|
9112
|
+
}
|
|
9113
|
+
var SPage = /* @__PURE__ */ forwardRef(function SPage2({
|
|
9114
|
+
background = "frame",
|
|
9115
|
+
scrollEndSpacing = true,
|
|
9116
|
+
overlayScrollbar = false,
|
|
9117
|
+
contentHeight = "auto",
|
|
9118
|
+
header,
|
|
9119
|
+
className,
|
|
9120
|
+
style,
|
|
9121
|
+
children,
|
|
9122
|
+
onScroll,
|
|
9123
|
+
...rest
|
|
9124
|
+
}, ref) {
|
|
8642
9125
|
const layout = useContext(SLayoutContext);
|
|
8643
9126
|
const gridStyle = layout?.header === "full" ? { gridArea: "page" } : void 0;
|
|
8644
|
-
|
|
9127
|
+
const scrollRef = useRef(null);
|
|
9128
|
+
const setMainRef = useCallback(
|
|
9129
|
+
(node) => {
|
|
9130
|
+
scrollRef.current = node;
|
|
9131
|
+
setForwardedRef(ref, node);
|
|
9132
|
+
},
|
|
9133
|
+
[ref]
|
|
9134
|
+
);
|
|
9135
|
+
const [scrolled, setScrolled] = useState(false);
|
|
9136
|
+
const handleScroll = (e) => {
|
|
9137
|
+
onScroll?.(e);
|
|
9138
|
+
if (header != null && !header.fix) setScrolled(e.currentTarget.scrollTop > 0);
|
|
9139
|
+
};
|
|
9140
|
+
const fill = contentHeight === "fill";
|
|
9141
|
+
const main = /* @__PURE__ */ jsx(
|
|
8645
9142
|
"main",
|
|
8646
9143
|
{
|
|
8647
|
-
ref,
|
|
9144
|
+
ref: setMainRef,
|
|
8648
9145
|
className: cn(
|
|
8649
9146
|
"box-border min-h-0 min-w-0 flex-1 overflow-auto p-[var(--cmp-pageBody-padding-default)]",
|
|
8650
|
-
|
|
8651
|
-
|
|
9147
|
+
overlayScrollbar && "h-full",
|
|
9148
|
+
!fill && scrollEndSpacing && "pb-[var(--cmp-pageBody-padding-scrollEnd)]",
|
|
9149
|
+
overlayScrollbar ? SCROLLBAR_HIDDEN_CLASS : `${SCROLLBAR_CLASS} ${NATIVE_SCROLLBAR_BACKGROUND_CLASS[background]}`,
|
|
8652
9150
|
BACKGROUND_CLASS[background],
|
|
8653
9151
|
className
|
|
8654
9152
|
),
|
|
8655
|
-
style: { ...gridStyle, ...style },
|
|
9153
|
+
style: header == null && !overlayScrollbar ? { ...gridStyle, ...style } : style,
|
|
9154
|
+
onScroll: handleScroll,
|
|
8656
9155
|
...rest,
|
|
8657
|
-
children: /* @__PURE__ */ jsx("div", { style: { minWidth: MIN_CONTENT_WIDTH }, children })
|
|
9156
|
+
children: /* @__PURE__ */ jsx("div", { className: cn(fill && "h-full"), style: { minWidth: MIN_CONTENT_WIDTH }, children })
|
|
8658
9157
|
}
|
|
8659
9158
|
);
|
|
9159
|
+
if (!overlayScrollbar) {
|
|
9160
|
+
if (header == null) return main;
|
|
9161
|
+
return (
|
|
9162
|
+
// fix 가 아닌 헤더는 자기 배경이 투명이라(SPageHeader.tsx) 이 배경이 그대로 비친다.
|
|
9163
|
+
/* @__PURE__ */ jsxs(
|
|
9164
|
+
"div",
|
|
9165
|
+
{
|
|
9166
|
+
className: cn("flex min-h-0 min-w-0 flex-1 flex-col", BACKGROUND_CLASS[background]),
|
|
9167
|
+
style: gridStyle,
|
|
9168
|
+
children: [
|
|
9169
|
+
/* @__PURE__ */ jsx(SPageHeader, { ...header, scrolled }),
|
|
9170
|
+
main
|
|
9171
|
+
]
|
|
9172
|
+
}
|
|
9173
|
+
)
|
|
9174
|
+
);
|
|
9175
|
+
}
|
|
9176
|
+
if (header == null) {
|
|
9177
|
+
return /* @__PURE__ */ jsxs(
|
|
9178
|
+
"div",
|
|
9179
|
+
{
|
|
9180
|
+
className: cn(
|
|
9181
|
+
"relative min-h-0 min-w-0 flex-1 overflow-hidden",
|
|
9182
|
+
BACKGROUND_CLASS[background]
|
|
9183
|
+
),
|
|
9184
|
+
style: gridStyle,
|
|
9185
|
+
children: [
|
|
9186
|
+
main,
|
|
9187
|
+
/* @__PURE__ */ jsx(SPageOverlayScrollbars, { scrollRef })
|
|
9188
|
+
]
|
|
9189
|
+
}
|
|
9190
|
+
);
|
|
9191
|
+
}
|
|
9192
|
+
return (
|
|
9193
|
+
// fix 가 아닌 헤더는 자기 배경이 투명이라(SPageHeader.tsx) 이 배경이 그대로 비친다 —
|
|
9194
|
+
// 그래서 SPage 의 background 를 main 뿐 아니라 여기에도 칠한다(스크롤바 관련 클래스는
|
|
9195
|
+
// 스크롤 요소가 아닌 여기서는 그냥 무시된다). fix 헤더는 자체 흰 배경이 덮으므로 무관하다.
|
|
9196
|
+
/* @__PURE__ */ jsxs(
|
|
9197
|
+
"div",
|
|
9198
|
+
{
|
|
9199
|
+
className: cn("flex min-h-0 min-w-0 flex-1 flex-col", BACKGROUND_CLASS[background]),
|
|
9200
|
+
style: gridStyle,
|
|
9201
|
+
children: [
|
|
9202
|
+
/* @__PURE__ */ jsx(SPageHeader, { ...header, scrolled }),
|
|
9203
|
+
/* @__PURE__ */ jsxs("div", { className: "relative min-h-0 min-w-0 flex-1 overflow-hidden", children: [
|
|
9204
|
+
main,
|
|
9205
|
+
/* @__PURE__ */ jsx(SPageOverlayScrollbars, { scrollRef })
|
|
9206
|
+
] })
|
|
9207
|
+
]
|
|
9208
|
+
}
|
|
9209
|
+
)
|
|
9210
|
+
);
|
|
8660
9211
|
});
|
|
8661
9212
|
|
|
8662
9213
|
// src/components/SPage/page.config.ts
|
|
8663
9214
|
var PAGE_BACKGROUNDS = ["frame", "neutral", "screen"];
|
|
9215
|
+
var PAGE_CONTENT_HEIGHTS = ["auto", "fill"];
|
|
8664
9216
|
|
|
8665
9217
|
// src/components/STabs/tabs.config.ts
|
|
8666
|
-
var TAB_MAIN_SIZE = {
|
|
8667
|
-
md: { height: 36, paddingX: 24 },
|
|
8668
|
-
lg: { height: 44, paddingX: 32 }
|
|
8669
|
-
};
|
|
9218
|
+
var TAB_MAIN_SIZE = { height: 36, paddingX: 24 };
|
|
8670
9219
|
var TAB_TYPOGRAPHY = { fontSize: 12, lineHeight: 20 };
|
|
8671
9220
|
var TAB_MAIN_COLORS = {
|
|
8672
9221
|
selected: {
|
|
@@ -8688,13 +9237,11 @@ function STabs({
|
|
|
8688
9237
|
value,
|
|
8689
9238
|
tabs,
|
|
8690
9239
|
onValueChange,
|
|
8691
|
-
size = "md",
|
|
8692
9240
|
isSub = false,
|
|
8693
9241
|
vertical = false,
|
|
8694
9242
|
className,
|
|
8695
9243
|
style
|
|
8696
9244
|
}) {
|
|
8697
|
-
const s = TAB_MAIN_SIZE[size];
|
|
8698
9245
|
const blue = TAB_MAIN_COLORS.selected.border;
|
|
8699
9246
|
const isVertical = isSub && vertical;
|
|
8700
9247
|
const tabRefs = useRef([]);
|
|
@@ -8735,8 +9282,8 @@ function STabs({
|
|
|
8735
9282
|
const border = selected ? TAB_MAIN_COLORS.selected.border : TAB_MAIN_COLORS.default.border;
|
|
8736
9283
|
const selectedBg = TAB_MAIN_COLORS.selected.bg;
|
|
8737
9284
|
tabStyle = {
|
|
8738
|
-
height:
|
|
8739
|
-
padding: `0 ${
|
|
9285
|
+
height: TAB_MAIN_SIZE.height,
|
|
9286
|
+
padding: `0 ${TAB_MAIN_SIZE.paddingX}px`,
|
|
8740
9287
|
fontSize: TAB_TYPOGRAPHY.fontSize,
|
|
8741
9288
|
lineHeight: `${TAB_TYPOGRAPHY.lineHeight}px`,
|
|
8742
9289
|
background: selected ? TAB_MAIN_COLORS.selected.bg : TAB_MAIN_COLORS.default.bg,
|
|
@@ -9478,6 +10025,7 @@ var SField = /* @__PURE__ */ forwardRef(function SField2({
|
|
|
9478
10025
|
readOnly = false,
|
|
9479
10026
|
width,
|
|
9480
10027
|
minWidth,
|
|
10028
|
+
maxWidth,
|
|
9481
10029
|
multiline = false,
|
|
9482
10030
|
borderless = false,
|
|
9483
10031
|
children,
|
|
@@ -9513,7 +10061,10 @@ var SField = /* @__PURE__ */ forwardRef(function SField2({
|
|
|
9513
10061
|
const resolvedSuccess = status === "pass";
|
|
9514
10062
|
const showError = resolvedError && errorMessage !== "";
|
|
9515
10063
|
const interactive = !disabled && !readOnly;
|
|
9516
|
-
const
|
|
10064
|
+
const isPercentWidth = typeof width === "string" && width.trim().endsWith("%");
|
|
10065
|
+
const hug = cssLen(width) !== void 0 && !isPercentWidth;
|
|
10066
|
+
const addonWidth = effectiveAddonLabel !== "" ? cssLen(labelWidth) : void 0;
|
|
10067
|
+
const resolvedMaxWidth = cssLen(maxWidth) === void 0 || effectiveAddonLabel === "" ? cssLen(maxWidth) : addonWidth ? `calc(${cssLen(maxWidth)} + ${addonWidth})` : void 0;
|
|
9517
10068
|
const borderColor = borderless ? "transparent" : disabled ? "var(--color-grey-45)" : interactive && focused ? "var(--sys-color-field-border-focus)" : resolvedSuccess ? "var(--sys-color-field-border-success)" : resolvedError ? "var(--sys-color-field-border-danger)" : "var(--sys-color-field-border-default)";
|
|
9518
10069
|
const bgColor = borderless ? "transparent" : disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
|
|
9519
10070
|
const textColor = disabled ? "var(--color-grey-65)" : readOnly ? "var(--sys-color-field-text-readOnly)" : "var(--sys-color-field-text-default)";
|
|
@@ -9569,8 +10120,12 @@ var SField = /* @__PURE__ */ forwardRef(function SField2({
|
|
|
9569
10120
|
/* @__PURE__ */ jsxs(
|
|
9570
10121
|
"div",
|
|
9571
10122
|
{
|
|
9572
|
-
className: cn("flex min-w-0 flex-col", !hug && "flex-1"),
|
|
9573
|
-
style: {
|
|
10123
|
+
className: cn("flex min-w-0 flex-col", !hug && !isPercentWidth && "flex-1"),
|
|
10124
|
+
style: {
|
|
10125
|
+
width: cssLen(width),
|
|
10126
|
+
minWidth: cssLen(minWidth),
|
|
10127
|
+
maxWidth: resolvedMaxWidth
|
|
10128
|
+
},
|
|
9574
10129
|
children: [
|
|
9575
10130
|
/* @__PURE__ */ jsxs(
|
|
9576
10131
|
"div",
|
|
@@ -10325,6 +10880,7 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
|
|
|
10325
10880
|
height,
|
|
10326
10881
|
stickyColumn,
|
|
10327
10882
|
radius = "default",
|
|
10883
|
+
bordered = true,
|
|
10328
10884
|
noDataLabel = "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
10329
10885
|
noDataSlot,
|
|
10330
10886
|
isLoading = false,
|
|
@@ -10583,7 +11139,7 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
|
|
|
10583
11139
|
};
|
|
10584
11140
|
const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[var(--cmp-table-radius)] rounded-t-none" : "rounded-[var(--cmp-table-radius)]";
|
|
10585
11141
|
const cellPadY = dense ? "var(--cmp-table-body-paddingY-dense)" : "var(--cmp-table-body-paddingY-default)";
|
|
10586
|
-
const
|
|
11142
|
+
const cellPadXOf = (col) => col.contentType === "control" ? "var(--cmp-table-body-paddingX-default)" : "var(--cmp-table-body-paddingX-wide)";
|
|
10587
11143
|
const rowH = dense ? "var(--cmp-table-body-dense-height)" : "var(--cmp-table-body-default-height)";
|
|
10588
11144
|
const totalColSpan = visibleCols.length + (selectable ? 1 : 0);
|
|
10589
11145
|
const stickyInfo = (i) => {
|
|
@@ -10637,7 +11193,8 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
|
|
|
10637
11193
|
// 만으로는 스태킹 컨텍스트가 생기지 않아, 모달 안에 들어가면 30·31이 모달 Content
|
|
10638
11194
|
// 레벨까지 올라가 같은 컨텍스트의 floating portal 밴드(z-2)를 덮는다.
|
|
10639
11195
|
// 자손은 이미 overflow-hidden으로 클리핑되므로 테이블 내부 순서는 달라지지 않는다.
|
|
10640
|
-
"bg-white relative isolate flex flex-col overflow-hidden
|
|
11196
|
+
"bg-white relative isolate flex flex-col overflow-hidden",
|
|
11197
|
+
bordered && "border border-solid border-[color:var(--cmp-table-border-color)]",
|
|
10641
11198
|
// height가 없으면 루트가 받은 높이를 끝까지 채운다. 호스트가 className으로
|
|
10642
11199
|
// `flex-1 min-h-0` 등을 줘 루트 높이가 확정된 경우, 행이 적어도 테두리 박스가
|
|
10643
11200
|
// 남은 영역을 그대로 차지한다. basis는 auto로 둬 높이가 확정되지 않은
|
|
@@ -10807,9 +11364,10 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
|
|
|
10807
11364
|
stickyShadowClass(i),
|
|
10808
11365
|
typeof col.tdClass === "function" ? col.tdClass(row) : col.tdClass
|
|
10809
11366
|
);
|
|
11367
|
+
const tdPadX = cellPadXOf(col);
|
|
10810
11368
|
const tdStyle = {
|
|
10811
|
-
paddingLeft:
|
|
10812
|
-
paddingRight:
|
|
11369
|
+
paddingLeft: tdPadX,
|
|
11370
|
+
paddingRight: tdPadX,
|
|
10813
11371
|
paddingTop: cellPadY,
|
|
10814
11372
|
paddingBottom: cellPadY,
|
|
10815
11373
|
textAlign: col.align ?? "left",
|
|
@@ -10862,19 +11420,29 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
|
|
|
10862
11420
|
// SPagination은 전체 폭 기준 중앙, rows-per-page SSelect는 우측에 absolute 배치해 중앙 정렬을 유지한다.
|
|
10863
11421
|
// 루트 높이가 확정된 경우(테이블이 남은 영역을 채우는 배치) 페이지네이션 바가
|
|
10864
11422
|
// 눌리지 않도록 shrink-0으로 48px를 보장한다.
|
|
10865
|
-
/* @__PURE__ */ jsxs(
|
|
10866
|
-
|
|
10867
|
-
|
|
10868
|
-
|
|
10869
|
-
|
|
10870
|
-
|
|
10871
|
-
|
|
10872
|
-
|
|
10873
|
-
|
|
10874
|
-
|
|
10875
|
-
|
|
10876
|
-
|
|
10877
|
-
|
|
11423
|
+
/* @__PURE__ */ jsxs(
|
|
11424
|
+
"div",
|
|
11425
|
+
{
|
|
11426
|
+
className: cn(
|
|
11427
|
+
"relative flex h-[48px] shrink-0 items-center justify-center rounded-[var(--cmp-table-radius)] bg-[var(--color-grey-05)]",
|
|
11428
|
+
// 테두리를 끄면 겹칠 대상이 없어진다 — -mt-px 를 남기면 1px 어긋남만 생긴다.
|
|
11429
|
+
bordered && "-mt-px border border-solid border-[color:var(--cmp-table-border-color)]"
|
|
11430
|
+
),
|
|
11431
|
+
children: [
|
|
11432
|
+
/* @__PURE__ */ jsx(SPagination, { currentPage: displayPage, lastPage, onPageChange: changePage }),
|
|
11433
|
+
useRowsPerPageSelect && /* @__PURE__ */ jsx("div", { className: "absolute right-[10px] top-1/2 -translate-y-1/2", children: /* @__PURE__ */ jsx(
|
|
11434
|
+
SSelect2,
|
|
11435
|
+
{
|
|
11436
|
+
options: rowsPerPageOption,
|
|
11437
|
+
value: useInternalPagination ? innerRowsPerPage : pagination?.rowsPerPage,
|
|
11438
|
+
emitValue: true,
|
|
11439
|
+
onValueChange: (v) => changeRowsPerPage(Number(v)),
|
|
11440
|
+
width: 128
|
|
11441
|
+
}
|
|
11442
|
+
) })
|
|
11443
|
+
]
|
|
11444
|
+
}
|
|
11445
|
+
)
|
|
10878
11446
|
]
|
|
10879
11447
|
}
|
|
10880
11448
|
);
|
|
@@ -10937,27 +11505,88 @@ var STableBar = /* @__PURE__ */ forwardRef(function STableBar2({ total, selected
|
|
|
10937
11505
|
|
|
10938
11506
|
// src/lib/autofill.ts
|
|
10939
11507
|
var AUTOFILL_RESET_CLASS = "autofill:[-webkit-text-fill-color:currentColor] autofill:[box-shadow:0_0_0_1000px_var(--sys-color-field-bg-default)_inset] autofill:[transition:background-color_5000s_ease-in-out_0s] [&:-webkit-autofill]:[-webkit-text-fill-color:currentColor] [&:-webkit-autofill]:[box-shadow:0_0_0_1000px_var(--sys-color-field-bg-default)_inset] [&:-webkit-autofill]:[transition:background-color_5000s_ease-in-out_0s]";
|
|
10940
|
-
var
|
|
10941
|
-
|
|
10942
|
-
|
|
10943
|
-
|
|
10944
|
-
|
|
10945
|
-
|
|
10946
|
-
|
|
10947
|
-
|
|
10948
|
-
|
|
10949
|
-
|
|
10950
|
-
|
|
10951
|
-
|
|
10952
|
-
|
|
10953
|
-
|
|
10954
|
-
|
|
10955
|
-
|
|
10956
|
-
|
|
10957
|
-
|
|
10958
|
-
|
|
10959
|
-
|
|
10960
|
-
|
|
11508
|
+
var HIDE_DELAY_MS2 = 100;
|
|
11509
|
+
function mergeRefs(...refs) {
|
|
11510
|
+
return (node) => {
|
|
11511
|
+
for (const ref of refs) {
|
|
11512
|
+
if (!ref) continue;
|
|
11513
|
+
if (typeof ref === "function") ref(node);
|
|
11514
|
+
else ref.current = node;
|
|
11515
|
+
}
|
|
11516
|
+
};
|
|
11517
|
+
}
|
|
11518
|
+
function useTruncatedValueTooltip({
|
|
11519
|
+
enabled,
|
|
11520
|
+
text
|
|
11521
|
+
}) {
|
|
11522
|
+
const portalContainer = usePortalContainer();
|
|
11523
|
+
const elRef = useRef(null);
|
|
11524
|
+
const [open, setOpen] = useState(false);
|
|
11525
|
+
const hideTimer = useRef(void 0);
|
|
11526
|
+
const cancelHide = useCallback(() => {
|
|
11527
|
+
if (hideTimer.current) {
|
|
11528
|
+
clearTimeout(hideTimer.current);
|
|
11529
|
+
hideTimer.current = void 0;
|
|
11530
|
+
}
|
|
11531
|
+
}, []);
|
|
11532
|
+
const startHide = useCallback(() => {
|
|
11533
|
+
cancelHide();
|
|
11534
|
+
hideTimer.current = setTimeout(() => setOpen(false), HIDE_DELAY_MS2);
|
|
11535
|
+
}, [cancelHide]);
|
|
11536
|
+
const onMouseEnter = useCallback(() => {
|
|
11537
|
+
cancelHide();
|
|
11538
|
+
const el = elRef.current;
|
|
11539
|
+
if (!el) return;
|
|
11540
|
+
if (el.scrollWidth - el.clientWidth > 1) setOpen(true);
|
|
11541
|
+
}, [cancelHide]);
|
|
11542
|
+
useEffect(() => {
|
|
11543
|
+
if (!enabled || text === "") setOpen(false);
|
|
11544
|
+
}, [enabled, text]);
|
|
11545
|
+
useEffect(() => cancelHide, [cancelHide]);
|
|
11546
|
+
const active = enabled && text !== "";
|
|
11547
|
+
return {
|
|
11548
|
+
valueRef: elRef,
|
|
11549
|
+
onMouseEnter: active ? onMouseEnter : cancelHide,
|
|
11550
|
+
onMouseLeave: active ? startHide : cancelHide,
|
|
11551
|
+
tooltip: active ? /* @__PURE__ */ jsxs(RPopover10.Root, { open, onOpenChange: setOpen, children: [
|
|
11552
|
+
/* @__PURE__ */ jsx(RPopover10.Anchor, { virtualRef: elRef }),
|
|
11553
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
11554
|
+
RPopover10.Content,
|
|
11555
|
+
{
|
|
11556
|
+
side: "top",
|
|
11557
|
+
sideOffset: 4,
|
|
11558
|
+
"aria-hidden": true,
|
|
11559
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
11560
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
11561
|
+
onMouseEnter: cancelHide,
|
|
11562
|
+
onMouseLeave: startHide,
|
|
11563
|
+
children: /* @__PURE__ */ jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
|
|
11564
|
+
}
|
|
11565
|
+
) })
|
|
11566
|
+
] }) : null
|
|
11567
|
+
};
|
|
11568
|
+
}
|
|
11569
|
+
var FONT = {
|
|
11570
|
+
sm: { fontSize: 12, lineHeight: 20, paddingX: "var(--cmp-textinput-sm-paddingX)" },
|
|
11571
|
+
md: { fontSize: 14, lineHeight: 24, paddingX: "var(--cmp-textinput-md-paddingX)" }
|
|
11572
|
+
};
|
|
11573
|
+
var SInput = /* @__PURE__ */ forwardRef(function SInput2({
|
|
11574
|
+
value,
|
|
11575
|
+
onValueChange,
|
|
11576
|
+
onChange,
|
|
11577
|
+
type = "text",
|
|
11578
|
+
size = "sm",
|
|
11579
|
+
icon,
|
|
11580
|
+
iconColor,
|
|
11581
|
+
prefix,
|
|
11582
|
+
suffix,
|
|
11583
|
+
clearable = false,
|
|
11584
|
+
rules,
|
|
11585
|
+
status,
|
|
11586
|
+
focused,
|
|
11587
|
+
hovered,
|
|
11588
|
+
inputClass,
|
|
11589
|
+
inputStyle,
|
|
10961
11590
|
label,
|
|
10962
11591
|
labelWidth,
|
|
10963
11592
|
labelTooltip,
|
|
@@ -10994,6 +11623,10 @@ var SInput = /* @__PURE__ */ forwardRef(function SInput2({
|
|
|
10994
11623
|
const resolvedError = error || ruleError !== "";
|
|
10995
11624
|
const resolvedErrorMessage = ruleError !== "" ? ruleError : errorMessage;
|
|
10996
11625
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
11626
|
+
const valueTooltip = useTruncatedValueTooltip({
|
|
11627
|
+
enabled: readOnly && !disabled,
|
|
11628
|
+
text: String(value ?? "")
|
|
11629
|
+
});
|
|
10997
11630
|
return /* @__PURE__ */ jsx(
|
|
10998
11631
|
SField,
|
|
10999
11632
|
{
|
|
@@ -11030,11 +11663,11 @@ var SInput = /* @__PURE__ */ forwardRef(function SInput2({
|
|
|
11030
11663
|
lineHeight: `${f.lineHeight}px`
|
|
11031
11664
|
},
|
|
11032
11665
|
children: [
|
|
11033
|
-
prefix != null && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: prefix }),
|
|
11666
|
+
prefix != null && /* @__PURE__ */ jsx("span", { className: "flex flex-shrink-0 items-center", children: prefix }),
|
|
11034
11667
|
/* @__PURE__ */ jsx(
|
|
11035
11668
|
"input",
|
|
11036
11669
|
{
|
|
11037
|
-
ref,
|
|
11670
|
+
ref: mergeRefs(ref, valueTooltip.valueRef),
|
|
11038
11671
|
type: inputType,
|
|
11039
11672
|
value: value ?? "",
|
|
11040
11673
|
disabled,
|
|
@@ -11059,10 +11692,19 @@ var SInput = /* @__PURE__ */ forwardRef(function SInput2({
|
|
|
11059
11692
|
color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--sys-color-field-text-default)",
|
|
11060
11693
|
...inputStyle
|
|
11061
11694
|
},
|
|
11062
|
-
...rest
|
|
11695
|
+
...rest,
|
|
11696
|
+
onMouseEnter: (e) => {
|
|
11697
|
+
rest.onMouseEnter?.(e);
|
|
11698
|
+
valueTooltip.onMouseEnter();
|
|
11699
|
+
},
|
|
11700
|
+
onMouseLeave: (e) => {
|
|
11701
|
+
rest.onMouseLeave?.(e);
|
|
11702
|
+
valueTooltip.onMouseLeave();
|
|
11703
|
+
}
|
|
11063
11704
|
}
|
|
11064
11705
|
),
|
|
11065
|
-
|
|
11706
|
+
valueTooltip.tooltip,
|
|
11707
|
+
suffix != null && /* @__PURE__ */ jsx("span", { className: "flex flex-shrink-0 items-center", children: suffix }),
|
|
11066
11708
|
clearable && hasValue && !disabled && !readOnly && /* @__PURE__ */ jsx(
|
|
11067
11709
|
SGhostButton,
|
|
11068
11710
|
{
|
|
@@ -11295,8 +11937,10 @@ var SNumberInput = /* @__PURE__ */ forwardRef(function SNumberInput2({
|
|
|
11295
11937
|
const [display, setDisplay] = useState(() => formatWithCommas(numValue));
|
|
11296
11938
|
const [ruleError, setRuleError] = useState("");
|
|
11297
11939
|
const innerRef = useRef(null);
|
|
11940
|
+
const valueTooltip = useTruncatedValueTooltip({ enabled: readOnly && !disabled, text: display });
|
|
11298
11941
|
const setRefs2 = (el) => {
|
|
11299
11942
|
innerRef.current = el;
|
|
11943
|
+
valueTooltip.valueRef.current = el;
|
|
11300
11944
|
if (typeof ref === "function") ref(el);
|
|
11301
11945
|
else if (ref) ref.current = el;
|
|
11302
11946
|
};
|
|
@@ -11510,9 +12154,12 @@ var SNumberInput = /* @__PURE__ */ forwardRef(function SNumberInput2({
|
|
|
11510
12154
|
textAlign: useButton ? "center" : "right",
|
|
11511
12155
|
color: disabled ? "var(--cmp-numberInput-text-disabled)" : "var(--cmp-numberInput-text-default)",
|
|
11512
12156
|
...inputStyle
|
|
11513
|
-
}
|
|
12157
|
+
},
|
|
12158
|
+
onMouseEnter: valueTooltip.onMouseEnter,
|
|
12159
|
+
onMouseLeave: valueTooltip.onMouseLeave
|
|
11514
12160
|
}
|
|
11515
12161
|
),
|
|
12162
|
+
valueTooltip.tooltip,
|
|
11516
12163
|
inputSuffix !== "" && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", style: { color: affixColor }, children: inputSuffix }),
|
|
11517
12164
|
useButton && stepper("inc")
|
|
11518
12165
|
]
|
|
@@ -11891,12 +12538,275 @@ function SCalendar({
|
|
|
11891
12538
|
}
|
|
11892
12539
|
);
|
|
11893
12540
|
}
|
|
12541
|
+
var DATEPICKER_MODE_LIST_HEIGHT = 240;
|
|
12542
|
+
var DATEPICKER_MODE_ITEM_HEIGHT = 28;
|
|
12543
|
+
var YEAR_LIST_EDGE_BUFFER = 24;
|
|
12544
|
+
var YEAR_LIST_EXPAND_SIZE = 80;
|
|
12545
|
+
var MONTHS = Array.from({ length: 12 }, (_, i) => i + 1);
|
|
12546
|
+
var getTodayParts = () => {
|
|
12547
|
+
const today = /* @__PURE__ */ new Date();
|
|
12548
|
+
return {
|
|
12549
|
+
year: today.getFullYear(),
|
|
12550
|
+
month: today.getMonth() + 1
|
|
12551
|
+
};
|
|
12552
|
+
};
|
|
12553
|
+
var parseYear = (value) => {
|
|
12554
|
+
const year = Number(value?.slice(0, 4));
|
|
12555
|
+
return Number.isFinite(year) && year > 0 ? year : void 0;
|
|
12556
|
+
};
|
|
12557
|
+
var parseMonth = (value) => {
|
|
12558
|
+
const month = Number(value?.slice(5, 7));
|
|
12559
|
+
return Number.isFinite(month) && month >= 1 && month <= 12 ? month : void 0;
|
|
12560
|
+
};
|
|
12561
|
+
var formatMonthValue = (year, month) => `${year}-${String(month).padStart(2, "0")}`;
|
|
12562
|
+
var isYearDisabled = (year, selectable) => {
|
|
12563
|
+
if (!selectable) return false;
|
|
12564
|
+
const [start, end] = selectable;
|
|
12565
|
+
if (start !== "" && year < Number(start.slice(0, 4))) return true;
|
|
12566
|
+
if (end !== "" && year > Number(end.slice(0, 4))) return true;
|
|
12567
|
+
return false;
|
|
12568
|
+
};
|
|
12569
|
+
var isMonthDisabled = (year, month, selectable) => {
|
|
12570
|
+
if (!selectable) return false;
|
|
12571
|
+
const value = formatMonthValue(year, month);
|
|
12572
|
+
const [start, end] = selectable;
|
|
12573
|
+
if (start !== "" && value < start.slice(0, 7)) return true;
|
|
12574
|
+
if (end !== "" && value > end.slice(0, 7)) return true;
|
|
12575
|
+
return false;
|
|
12576
|
+
};
|
|
12577
|
+
function YearWheel({ value, anchorYear, selectable, onCommit }) {
|
|
12578
|
+
const listRef = useRef(null);
|
|
12579
|
+
const syncingScrollRef = useRef(false);
|
|
12580
|
+
const anchorYearRef = useRef(anchorYear);
|
|
12581
|
+
const [range, setRange] = useState(() => ({
|
|
12582
|
+
start: anchorYear - YEAR_LIST_EXPAND_SIZE,
|
|
12583
|
+
end: anchorYear + YEAR_LIST_EXPAND_SIZE
|
|
12584
|
+
}));
|
|
12585
|
+
const rangeStartRef = useRef(range.start);
|
|
12586
|
+
rangeStartRef.current = range.start;
|
|
12587
|
+
const years = Array.from({ length: range.end - range.start + 1 }, (_, i) => range.start + i);
|
|
12588
|
+
useLayoutEffect(() => {
|
|
12589
|
+
const list = listRef.current;
|
|
12590
|
+
if (!list) return;
|
|
12591
|
+
const index = anchorYearRef.current - rangeStartRef.current;
|
|
12592
|
+
syncingScrollRef.current = true;
|
|
12593
|
+
list.scrollTop = index * DATEPICKER_MODE_ITEM_HEIGHT;
|
|
12594
|
+
requestAnimationFrame(() => {
|
|
12595
|
+
syncingScrollRef.current = false;
|
|
12596
|
+
});
|
|
12597
|
+
}, []);
|
|
12598
|
+
const handleScroll = () => {
|
|
12599
|
+
const list = listRef.current;
|
|
12600
|
+
if (!list) return;
|
|
12601
|
+
if (syncingScrollRef.current) return;
|
|
12602
|
+
if (list.scrollTop < DATEPICKER_MODE_ITEM_HEIGHT * YEAR_LIST_EDGE_BUFFER) {
|
|
12603
|
+
const previousHeight = list.scrollHeight;
|
|
12604
|
+
setRange((current) => ({
|
|
12605
|
+
start: current.start - YEAR_LIST_EXPAND_SIZE,
|
|
12606
|
+
end: current.end
|
|
12607
|
+
}));
|
|
12608
|
+
requestAnimationFrame(() => {
|
|
12609
|
+
if (!listRef.current) return;
|
|
12610
|
+
syncingScrollRef.current = true;
|
|
12611
|
+
listRef.current.scrollTop += listRef.current.scrollHeight - previousHeight;
|
|
12612
|
+
requestAnimationFrame(() => {
|
|
12613
|
+
syncingScrollRef.current = false;
|
|
12614
|
+
});
|
|
12615
|
+
});
|
|
12616
|
+
return;
|
|
12617
|
+
}
|
|
12618
|
+
if (list.scrollHeight - list.scrollTop - list.clientHeight < DATEPICKER_MODE_ITEM_HEIGHT * YEAR_LIST_EDGE_BUFFER) {
|
|
12619
|
+
setRange((current) => ({
|
|
12620
|
+
start: current.start,
|
|
12621
|
+
end: current.end + YEAR_LIST_EXPAND_SIZE
|
|
12622
|
+
}));
|
|
12623
|
+
}
|
|
12624
|
+
};
|
|
12625
|
+
return /* @__PURE__ */ jsx("div", { className: "h-full w-full overflow-hidden bg-[var(--cmp-datepicker-mode-bg)]", children: /* @__PURE__ */ jsx(
|
|
12626
|
+
"div",
|
|
12627
|
+
{
|
|
12628
|
+
ref: listRef,
|
|
12629
|
+
role: "listbox",
|
|
12630
|
+
"aria-label": "year",
|
|
12631
|
+
className: "h-full overflow-y-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
12632
|
+
style: {
|
|
12633
|
+
paddingTop: `calc((${DATEPICKER_MODE_LIST_HEIGHT}px - ${DATEPICKER_MODE_ITEM_HEIGHT}px) / 2)`,
|
|
12634
|
+
paddingBottom: `calc((${DATEPICKER_MODE_LIST_HEIGHT}px - ${DATEPICKER_MODE_ITEM_HEIGHT}px) / 2)`
|
|
12635
|
+
},
|
|
12636
|
+
onScroll: handleScroll,
|
|
12637
|
+
children: years.map((year) => {
|
|
12638
|
+
const selected = year === value;
|
|
12639
|
+
const disabled = isYearDisabled(year, selectable);
|
|
12640
|
+
return /* @__PURE__ */ jsx(
|
|
12641
|
+
"button",
|
|
12642
|
+
{
|
|
12643
|
+
type: "button",
|
|
12644
|
+
role: "option",
|
|
12645
|
+
"aria-selected": selected,
|
|
12646
|
+
disabled,
|
|
12647
|
+
className: cn(
|
|
12648
|
+
"flex w-full items-center justify-center gap-[var(--cmp-datepicker-mode-item-gap)] border-0 px-[var(--cmp-datepicker-mode-item-paddingX)] py-[var(--cmp-datepicker-mode-item-paddingY)] text-center font-base text-12 leading-[20px]",
|
|
12649
|
+
disabled && "cursor-not-allowed bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-disabled)]",
|
|
12650
|
+
!disabled && !selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-default)] hover:bg-[var(--cmp-datepicker-mode-item-bg-hover)] hover:text-[color:var(--cmp-datepicker-mode-item-content-hover)]",
|
|
12651
|
+
!disabled && selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-bold text-[color:var(--cmp-datepicker-mode-item-content-selected)]"
|
|
12652
|
+
),
|
|
12653
|
+
onClick: () => !disabled && onCommit(year),
|
|
12654
|
+
children: year
|
|
12655
|
+
},
|
|
12656
|
+
year
|
|
12657
|
+
);
|
|
12658
|
+
})
|
|
12659
|
+
}
|
|
12660
|
+
) });
|
|
12661
|
+
}
|
|
12662
|
+
function SDatePickerYearListbox({
|
|
12663
|
+
value,
|
|
12664
|
+
anchorYear,
|
|
12665
|
+
selectable,
|
|
12666
|
+
onValueChange,
|
|
12667
|
+
className,
|
|
12668
|
+
style
|
|
12669
|
+
}) {
|
|
12670
|
+
const today = getTodayParts();
|
|
12671
|
+
const resolvedAnchorYear = anchorYear ?? today.year;
|
|
12672
|
+
const [year, setYear] = useState(() => parseYear(value) ?? resolvedAnchorYear);
|
|
12673
|
+
useEffect(() => {
|
|
12674
|
+
setYear(parseYear(value) ?? resolvedAnchorYear);
|
|
12675
|
+
}, [value, resolvedAnchorYear]);
|
|
12676
|
+
const commitYear = (nextYear) => {
|
|
12677
|
+
setYear(nextYear);
|
|
12678
|
+
onValueChange?.(String(nextYear));
|
|
12679
|
+
};
|
|
12680
|
+
return /* @__PURE__ */ jsx(
|
|
12681
|
+
"div",
|
|
12682
|
+
{
|
|
12683
|
+
className: cn(
|
|
12684
|
+
"inline-flex h-[240px] w-[var(--cmp-datepicker-mode-year-width)] overflow-hidden rounded-[var(--cmp-datepicker-mode-radius)] bg-[var(--cmp-datepicker-mode-bg)] shadow-normal-sm",
|
|
12685
|
+
className
|
|
12686
|
+
),
|
|
12687
|
+
style,
|
|
12688
|
+
children: /* @__PURE__ */ jsx(
|
|
12689
|
+
YearWheel,
|
|
12690
|
+
{
|
|
12691
|
+
value: year,
|
|
12692
|
+
anchorYear: resolvedAnchorYear,
|
|
12693
|
+
selectable,
|
|
12694
|
+
onCommit: commitYear
|
|
12695
|
+
}
|
|
12696
|
+
)
|
|
12697
|
+
}
|
|
12698
|
+
);
|
|
12699
|
+
}
|
|
12700
|
+
function MonthWheel({ year, value, selectable, onCommit }) {
|
|
12701
|
+
const listRef = useRef(null);
|
|
12702
|
+
const initialValueRef = useRef(value);
|
|
12703
|
+
useLayoutEffect(() => {
|
|
12704
|
+
const list = listRef.current;
|
|
12705
|
+
if (!list) return;
|
|
12706
|
+
list.scrollTop = Math.max(
|
|
12707
|
+
0,
|
|
12708
|
+
(initialValueRef.current - 1) * DATEPICKER_MODE_ITEM_HEIGHT - (list.clientHeight - DATEPICKER_MODE_ITEM_HEIGHT) / 2
|
|
12709
|
+
);
|
|
12710
|
+
}, []);
|
|
12711
|
+
return /* @__PURE__ */ jsx("div", { className: "h-full w-full overflow-hidden bg-[var(--cmp-datepicker-mode-bg)]", children: /* @__PURE__ */ jsx(
|
|
12712
|
+
"div",
|
|
12713
|
+
{
|
|
12714
|
+
ref: listRef,
|
|
12715
|
+
role: "listbox",
|
|
12716
|
+
"aria-label": "month",
|
|
12717
|
+
className: "h-full overflow-y-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
12718
|
+
children: MONTHS.map((month) => {
|
|
12719
|
+
const selected = month === value;
|
|
12720
|
+
const disabled = isMonthDisabled(year, month, selectable);
|
|
12721
|
+
return /* @__PURE__ */ jsxs(
|
|
12722
|
+
"button",
|
|
12723
|
+
{
|
|
12724
|
+
type: "button",
|
|
12725
|
+
role: "option",
|
|
12726
|
+
"aria-selected": selected,
|
|
12727
|
+
disabled,
|
|
12728
|
+
className: cn(
|
|
12729
|
+
"flex w-full items-center justify-center gap-[var(--cmp-datepicker-mode-item-gap)] border-0 px-[var(--cmp-datepicker-mode-item-paddingX)] py-[var(--cmp-datepicker-mode-item-paddingY)] text-center font-base text-12 leading-[20px]",
|
|
12730
|
+
disabled && "cursor-not-allowed bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-disabled)]",
|
|
12731
|
+
!disabled && !selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-default)] hover:bg-[var(--cmp-datepicker-mode-item-bg-hover)] hover:text-[color:var(--cmp-datepicker-mode-item-content-hover)]",
|
|
12732
|
+
!disabled && selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-bold text-[color:var(--cmp-datepicker-mode-item-content-selected)]"
|
|
12733
|
+
),
|
|
12734
|
+
onClick: () => !disabled && onCommit(month),
|
|
12735
|
+
children: [
|
|
12736
|
+
month,
|
|
12737
|
+
"\uC6D4"
|
|
12738
|
+
]
|
|
12739
|
+
},
|
|
12740
|
+
month
|
|
12741
|
+
);
|
|
12742
|
+
})
|
|
12743
|
+
}
|
|
12744
|
+
) });
|
|
12745
|
+
}
|
|
12746
|
+
function SDatePickerMonthListbox({
|
|
12747
|
+
value,
|
|
12748
|
+
anchorYear,
|
|
12749
|
+
selectable,
|
|
12750
|
+
onValueChange,
|
|
12751
|
+
onMonthSelect,
|
|
12752
|
+
className,
|
|
12753
|
+
style
|
|
12754
|
+
}) {
|
|
12755
|
+
const today = getTodayParts();
|
|
12756
|
+
const resolvedAnchorYear = anchorYear ?? today.year;
|
|
12757
|
+
const [year, setYear] = useState(() => parseYear(value) ?? resolvedAnchorYear);
|
|
12758
|
+
const [month, setMonth] = useState(() => parseMonth(value) ?? today.month);
|
|
12759
|
+
useEffect(() => {
|
|
12760
|
+
setYear(parseYear(value) ?? resolvedAnchorYear);
|
|
12761
|
+
setMonth(parseMonth(value) ?? today.month);
|
|
12762
|
+
}, [value, resolvedAnchorYear, today.month]);
|
|
12763
|
+
const commitYear = (nextYear) => {
|
|
12764
|
+
setYear(nextYear);
|
|
12765
|
+
onValueChange?.(formatMonthValue(nextYear, month));
|
|
12766
|
+
};
|
|
12767
|
+
const commitMonth = (nextMonth) => {
|
|
12768
|
+
setMonth(nextMonth);
|
|
12769
|
+
const nextValue = formatMonthValue(year, nextMonth);
|
|
12770
|
+
onValueChange?.(nextValue);
|
|
12771
|
+
onMonthSelect?.(nextValue);
|
|
12772
|
+
};
|
|
12773
|
+
return /* @__PURE__ */ jsxs(
|
|
12774
|
+
"div",
|
|
12775
|
+
{
|
|
12776
|
+
className: cn(
|
|
12777
|
+
"inline-flex h-[240px] gap-[var(--cmp-datepicker-mode-yearMonth-gap)] overflow-hidden rounded-[var(--cmp-datepicker-mode-radius)] bg-[var(--cmp-datepicker-mode-bg)] shadow-normal-sm",
|
|
12778
|
+
className
|
|
12779
|
+
),
|
|
12780
|
+
style,
|
|
12781
|
+
children: [
|
|
12782
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 w-[var(--cmp-datepicker-mode-yearMonth-column-width)]", children: /* @__PURE__ */ jsx(
|
|
12783
|
+
YearWheel,
|
|
12784
|
+
{
|
|
12785
|
+
value: year,
|
|
12786
|
+
anchorYear: resolvedAnchorYear,
|
|
12787
|
+
selectable,
|
|
12788
|
+
onCommit: commitYear
|
|
12789
|
+
}
|
|
12790
|
+
) }),
|
|
12791
|
+
/* @__PURE__ */ jsx(
|
|
12792
|
+
"div",
|
|
12793
|
+
{
|
|
12794
|
+
"aria-hidden": true,
|
|
12795
|
+
className: "w-[var(--border-width-1)] self-stretch bg-[var(--sys-color-divider-default)]"
|
|
12796
|
+
}
|
|
12797
|
+
),
|
|
12798
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 w-[var(--cmp-datepicker-mode-yearMonth-column-width)]", children: /* @__PURE__ */ jsx(MonthWheel, { year, value: month, selectable, onCommit: commitMonth }) })
|
|
12799
|
+
]
|
|
12800
|
+
}
|
|
12801
|
+
);
|
|
12802
|
+
}
|
|
11894
12803
|
function SDatePicker({
|
|
11895
12804
|
value,
|
|
11896
12805
|
onValueChange,
|
|
11897
12806
|
onViewChange,
|
|
12807
|
+
mode = "date",
|
|
11898
12808
|
size = "sm",
|
|
11899
|
-
placeholder
|
|
12809
|
+
placeholder,
|
|
11900
12810
|
selectable,
|
|
11901
12811
|
disabled = false,
|
|
11902
12812
|
width,
|
|
@@ -11922,6 +12832,7 @@ function SDatePicker({
|
|
|
11922
12832
|
const [focused, setFocused] = useState(false);
|
|
11923
12833
|
const [ruleError, setRuleError] = useState("");
|
|
11924
12834
|
const hasValue = value != null && value !== "";
|
|
12835
|
+
const resolvedPlaceholder = placeholder ?? (mode === "year" ? "YYYY" : mode === "month" ? "YYYY-MM" : "YYYY-MM-DD");
|
|
11925
12836
|
useFormField({
|
|
11926
12837
|
name,
|
|
11927
12838
|
validate: () => {
|
|
@@ -11933,12 +12844,39 @@ function SDatePicker({
|
|
|
11933
12844
|
});
|
|
11934
12845
|
const resolvedError = error || ruleError !== "";
|
|
11935
12846
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
11936
|
-
const dims = size === "md" ? {
|
|
12847
|
+
const dims = size === "md" ? {
|
|
12848
|
+
padX: 16,
|
|
12849
|
+
gap: 12,
|
|
12850
|
+
icon: 20,
|
|
12851
|
+
minW: 104,
|
|
12852
|
+
fieldMinW: 168,
|
|
12853
|
+
// 상한 등급 lg — 값 길이가 YYYY-MM-DD 로 정해져 있어, width="100%" 를 받아도
|
|
12854
|
+
// 행 전체로 늘어나지 않게 막는다 (SKeyValueTable 이 모든 컨트롤에 100% 를 넘긴다)
|
|
12855
|
+
fieldMaxW: 240,
|
|
12856
|
+
fontSize: 14,
|
|
12857
|
+
lineHeight: 24,
|
|
12858
|
+
radius: 6
|
|
12859
|
+
} : {
|
|
12860
|
+
padX: 12,
|
|
12861
|
+
gap: 8,
|
|
12862
|
+
icon: 16,
|
|
12863
|
+
minW: 80,
|
|
12864
|
+
fieldMinW: 128,
|
|
12865
|
+
// 상한 등급 md
|
|
12866
|
+
fieldMaxW: 160,
|
|
12867
|
+
fontSize: 12,
|
|
12868
|
+
lineHeight: 20,
|
|
12869
|
+
radius: 4
|
|
12870
|
+
};
|
|
11937
12871
|
const select = (date) => {
|
|
11938
12872
|
onValueChange?.(date);
|
|
11939
12873
|
if (rules && rules.length > 0) setRuleError(runRules(date, rules));
|
|
11940
12874
|
setOpen(false);
|
|
11941
12875
|
};
|
|
12876
|
+
const selectListboxValue = (nextValue) => {
|
|
12877
|
+
onValueChange?.(nextValue);
|
|
12878
|
+
if (rules && rules.length > 0) setRuleError(runRules(nextValue, rules));
|
|
12879
|
+
};
|
|
11942
12880
|
return /* @__PURE__ */ jsx(
|
|
11943
12881
|
SField,
|
|
11944
12882
|
{
|
|
@@ -11957,11 +12895,13 @@ function SDatePicker({
|
|
|
11957
12895
|
focused: focused || open,
|
|
11958
12896
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
11959
12897
|
width,
|
|
12898
|
+
minWidth: dims.fieldMinW,
|
|
12899
|
+
maxWidth: dims.fieldMaxW,
|
|
11960
12900
|
disabled,
|
|
11961
12901
|
className,
|
|
11962
12902
|
style,
|
|
11963
|
-
children: /* @__PURE__ */ jsxs(
|
|
11964
|
-
/* @__PURE__ */ jsx(
|
|
12903
|
+
children: /* @__PURE__ */ jsxs(RPopover10.Root, { open, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
12904
|
+
/* @__PURE__ */ jsx(RPopover10.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
11965
12905
|
"button",
|
|
11966
12906
|
{
|
|
11967
12907
|
type: "button",
|
|
@@ -11991,20 +12931,23 @@ function SDatePicker({
|
|
|
11991
12931
|
lineHeight: `${dims.lineHeight}px`,
|
|
11992
12932
|
color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasValue ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
|
|
11993
12933
|
},
|
|
11994
|
-
children: hasValue ? value :
|
|
12934
|
+
children: hasValue ? value : resolvedPlaceholder
|
|
11995
12935
|
}
|
|
11996
12936
|
)
|
|
11997
12937
|
]
|
|
11998
12938
|
}
|
|
11999
12939
|
) }),
|
|
12000
|
-
/* @__PURE__ */ jsx(
|
|
12001
|
-
|
|
12940
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
12941
|
+
RPopover10.Content,
|
|
12002
12942
|
{
|
|
12003
12943
|
side: "bottom",
|
|
12004
|
-
align: "start",
|
|
12944
|
+
align: mode === "date" ? "start" : "center",
|
|
12005
12945
|
sideOffset: 4,
|
|
12006
|
-
className: cn(
|
|
12007
|
-
|
|
12946
|
+
className: cn(
|
|
12947
|
+
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
12948
|
+
FLOATING_SLIDE_ANIM
|
|
12949
|
+
),
|
|
12950
|
+
children: mode === "date" ? /* @__PURE__ */ jsx(
|
|
12008
12951
|
SCalendar,
|
|
12009
12952
|
{
|
|
12010
12953
|
value: value ?? void 0,
|
|
@@ -12013,6 +12956,24 @@ function SDatePicker({
|
|
|
12013
12956
|
onValueChange: select,
|
|
12014
12957
|
onViewChange
|
|
12015
12958
|
}
|
|
12959
|
+
) : mode === "year" ? /* @__PURE__ */ jsx(
|
|
12960
|
+
SDatePickerYearListbox,
|
|
12961
|
+
{
|
|
12962
|
+
value,
|
|
12963
|
+
selectable,
|
|
12964
|
+
onValueChange: (nextValue) => {
|
|
12965
|
+
selectListboxValue(nextValue);
|
|
12966
|
+
setOpen(false);
|
|
12967
|
+
}
|
|
12968
|
+
}
|
|
12969
|
+
) : /* @__PURE__ */ jsx(
|
|
12970
|
+
SDatePickerMonthListbox,
|
|
12971
|
+
{
|
|
12972
|
+
value,
|
|
12973
|
+
selectable,
|
|
12974
|
+
onValueChange: selectListboxValue,
|
|
12975
|
+
onMonthSelect: () => setOpen(false)
|
|
12976
|
+
}
|
|
12016
12977
|
)
|
|
12017
12978
|
}
|
|
12018
12979
|
) })
|
|
@@ -12151,78 +13112,81 @@ function RangeCalendar({
|
|
|
12151
13112
|
}
|
|
12152
13113
|
};
|
|
12153
13114
|
const GRID_COLS = "grid grid-cols-[repeat(7,var(--cmp-datepicker-calendar-day-width))]";
|
|
12154
|
-
const renderPanel = (gy, gm, isLeft) =>
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
|
|
12158
|
-
|
|
12159
|
-
|
|
12160
|
-
|
|
12161
|
-
|
|
12162
|
-
|
|
12163
|
-
|
|
12164
|
-
|
|
12165
|
-
|
|
12166
|
-
|
|
12167
|
-
|
|
12168
|
-
"
|
|
12169
|
-
|
|
13115
|
+
const renderPanel = (gy, gm, isLeft) => (
|
|
13116
|
+
// 좁은 창에서 눌려 격자가 깨지지 않도록, 줄이는 대신 부모가 가로 스크롤하게 둔다.
|
|
13117
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col gap-[var(--cmp-datepicker-calendar-gap)]", children: [
|
|
13118
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-[var(--cmp-datepicker-calendar-gap)]", children: [
|
|
13119
|
+
/* @__PURE__ */ jsx(
|
|
13120
|
+
SGhostButton,
|
|
13121
|
+
{
|
|
13122
|
+
icon: "chevronLeft",
|
|
13123
|
+
size: "xxs",
|
|
13124
|
+
ariaLabel: "prevMonth",
|
|
13125
|
+
onClick: goPrevMonth,
|
|
13126
|
+
className: cn(!isLeft && "invisible pointer-events-none")
|
|
13127
|
+
}
|
|
13128
|
+
),
|
|
13129
|
+
/* @__PURE__ */ jsxs("span", { className: "inline-flex min-w-[40px] flex-1 items-center justify-center text-center text-[14px] font-medium leading-[24px]", children: [
|
|
13130
|
+
gy,
|
|
13131
|
+
".",
|
|
13132
|
+
String(gm).padStart(2, "0")
|
|
13133
|
+
] }),
|
|
13134
|
+
/* @__PURE__ */ jsx(
|
|
13135
|
+
SGhostButton,
|
|
13136
|
+
{
|
|
13137
|
+
icon: "chevronRight",
|
|
13138
|
+
size: "xxs",
|
|
13139
|
+
ariaLabel: "nextMonth",
|
|
13140
|
+
onClick: goNextMonth,
|
|
13141
|
+
className: cn(isLeft && "invisible pointer-events-none")
|
|
13142
|
+
}
|
|
13143
|
+
)
|
|
12170
13144
|
] }),
|
|
12171
|
-
/* @__PURE__ */ jsx(
|
|
12172
|
-
|
|
12173
|
-
{
|
|
12174
|
-
icon: "chevronRight",
|
|
12175
|
-
size: "xxs",
|
|
12176
|
-
ariaLabel: "nextMonth",
|
|
12177
|
-
onClick: goNextMonth,
|
|
12178
|
-
className: cn(isLeft && "invisible pointer-events-none")
|
|
12179
|
-
}
|
|
12180
|
-
)
|
|
12181
|
-
] }),
|
|
12182
|
-
/* @__PURE__ */ jsx("div", { className: GRID_COLS, children: WEEK_LABELS.map((l) => /* @__PURE__ */ jsx(
|
|
12183
|
-
"span",
|
|
12184
|
-
{
|
|
12185
|
-
className: "flex h-[20px] items-center justify-center text-[12px] font-normal text-[color:var(--cmp-datepicker-calendar-week-color)]",
|
|
12186
|
-
children: l
|
|
12187
|
-
},
|
|
12188
|
-
l
|
|
12189
|
-
)) }),
|
|
12190
|
-
/* @__PURE__ */ jsx("div", { className: cn(GRID_COLS, "gap-y-[var(--cmp-datepicker-calendar-grid-rowGap)]"), children: monthCells(gy, gm).map((cell) => {
|
|
12191
|
-
const isEdge = cell.inCurrentMonth && (cell.date === rStart || complete && cell.date === rEnd);
|
|
12192
|
-
const between = cell.inCurrentMonth && inRange(cell.date);
|
|
12193
|
-
const disabled = cell.inCurrentMonth && isDisabled(cell.date);
|
|
12194
|
-
const isToday = cell.inCurrentMonth && today === cell.date;
|
|
12195
|
-
let cellBg;
|
|
12196
|
-
if (between) cellBg = RANGE_BG;
|
|
12197
|
-
else if (cell.inCurrentMonth && hasRange && cell.date === rStart)
|
|
12198
|
-
cellBg = `linear-gradient(to right, transparent 50%, ${RANGE_BG} 50%)`;
|
|
12199
|
-
else if (cell.inCurrentMonth && hasRange && cell.date === rEnd) cellBg = RANGE_BG;
|
|
12200
|
-
return /* @__PURE__ */ jsx(
|
|
12201
|
-
"div",
|
|
13145
|
+
/* @__PURE__ */ jsx("div", { className: GRID_COLS, children: WEEK_LABELS.map((l) => /* @__PURE__ */ jsx(
|
|
13146
|
+
"span",
|
|
12202
13147
|
{
|
|
12203
|
-
className: "flex h-[
|
|
12204
|
-
|
|
12205
|
-
children: /* @__PURE__ */ jsx(
|
|
12206
|
-
"button",
|
|
12207
|
-
{
|
|
12208
|
-
type: "button",
|
|
12209
|
-
disabled: !cell.inCurrentMonth || disabled,
|
|
12210
|
-
onMouseEnter: () => setHover(cell.date),
|
|
12211
|
-
onClick: () => cell.inCurrentMonth && click(cell.date),
|
|
12212
|
-
className: cn(
|
|
12213
|
-
"relative z-[1] flex h-[var(--cmp-datepicker-calendar-day-circle-size)] w-[var(--cmp-datepicker-calendar-day-circle-size)] items-center justify-center rounded-[var(--cmp-datepicker-calendar-day-circle-radius)] border border-solid border-transparent bg-transparent text-[14px]",
|
|
12214
|
-
!cell.inCurrentMonth ? "invisible pointer-events-none" : disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
12215
|
-
isEdge ? "bg-[var(--cmp-datepicker-calendar-day-select-bg)] text-[color:var(--cmp-datepicker-calendar-day-select-text)]" : disabled ? "text-[color:var(--cmp-datepicker-calendar-day-disabled-text)]" : "text-[color:var(--cmp-datepicker-calendar-day-default-text)] hover:border-[color:var(--cmp-datepicker-calendar-day-hover-border)] hover:text-[color:var(--cmp-datepicker-calendar-day-hover-text)]",
|
|
12216
|
-
isToday && !disabled && "font-bold"
|
|
12217
|
-
),
|
|
12218
|
-
children: cell.inCurrentMonth ? cell.day : ""
|
|
12219
|
-
}
|
|
12220
|
-
)
|
|
13148
|
+
className: "flex h-[20px] items-center justify-center text-[12px] font-normal text-[color:var(--cmp-datepicker-calendar-week-color)]",
|
|
13149
|
+
children: l
|
|
12221
13150
|
},
|
|
12222
|
-
|
|
12223
|
-
)
|
|
12224
|
-
|
|
12225
|
-
|
|
13151
|
+
l
|
|
13152
|
+
)) }),
|
|
13153
|
+
/* @__PURE__ */ jsx("div", { className: cn(GRID_COLS, "gap-y-[var(--cmp-datepicker-calendar-grid-rowGap)]"), children: monthCells(gy, gm).map((cell) => {
|
|
13154
|
+
const isEdge = cell.inCurrentMonth && (cell.date === rStart || complete && cell.date === rEnd);
|
|
13155
|
+
const between = cell.inCurrentMonth && inRange(cell.date);
|
|
13156
|
+
const disabled = cell.inCurrentMonth && isDisabled(cell.date);
|
|
13157
|
+
const isToday = cell.inCurrentMonth && today === cell.date;
|
|
13158
|
+
let cellBg;
|
|
13159
|
+
if (between) cellBg = RANGE_BG;
|
|
13160
|
+
else if (cell.inCurrentMonth && hasRange && cell.date === rStart)
|
|
13161
|
+
cellBg = `linear-gradient(to right, transparent 50%, ${RANGE_BG} 50%)`;
|
|
13162
|
+
else if (cell.inCurrentMonth && hasRange && cell.date === rEnd) cellBg = RANGE_BG;
|
|
13163
|
+
return /* @__PURE__ */ jsx(
|
|
13164
|
+
"div",
|
|
13165
|
+
{
|
|
13166
|
+
className: "flex h-[var(--cmp-datepicker-calendar-range-height)] w-[var(--cmp-datepicker-calendar-day-width)] items-center justify-center",
|
|
13167
|
+
style: { background: cellBg },
|
|
13168
|
+
children: /* @__PURE__ */ jsx(
|
|
13169
|
+
"button",
|
|
13170
|
+
{
|
|
13171
|
+
type: "button",
|
|
13172
|
+
disabled: !cell.inCurrentMonth || disabled,
|
|
13173
|
+
onMouseEnter: () => setHover(cell.date),
|
|
13174
|
+
onClick: () => cell.inCurrentMonth && click(cell.date),
|
|
13175
|
+
className: cn(
|
|
13176
|
+
"relative z-[1] flex h-[var(--cmp-datepicker-calendar-day-circle-size)] w-[var(--cmp-datepicker-calendar-day-circle-size)] items-center justify-center rounded-[var(--cmp-datepicker-calendar-day-circle-radius)] border border-solid border-transparent bg-transparent text-[14px]",
|
|
13177
|
+
!cell.inCurrentMonth ? "invisible pointer-events-none" : disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
13178
|
+
isEdge ? "bg-[var(--cmp-datepicker-calendar-day-select-bg)] text-[color:var(--cmp-datepicker-calendar-day-select-text)]" : disabled ? "text-[color:var(--cmp-datepicker-calendar-day-disabled-text)]" : "text-[color:var(--cmp-datepicker-calendar-day-default-text)] hover:border-[color:var(--cmp-datepicker-calendar-day-hover-border)] hover:text-[color:var(--cmp-datepicker-calendar-day-hover-text)]",
|
|
13179
|
+
isToday && !disabled && "font-bold"
|
|
13180
|
+
),
|
|
13181
|
+
children: cell.inCurrentMonth ? cell.day : ""
|
|
13182
|
+
}
|
|
13183
|
+
)
|
|
13184
|
+
},
|
|
13185
|
+
cell.date
|
|
13186
|
+
);
|
|
13187
|
+
}) })
|
|
13188
|
+
] })
|
|
13189
|
+
);
|
|
12226
13190
|
const renderTimeSection = (which, date, suffix) => {
|
|
12227
13191
|
const active = !!date;
|
|
12228
13192
|
const [yy = "", mm = "", dd = ""] = date ? date.split("-") : [];
|
|
@@ -12290,8 +13254,11 @@ function RangeCalendar({
|
|
|
12290
13254
|
"div",
|
|
12291
13255
|
{
|
|
12292
13256
|
className: cn(
|
|
12293
|
-
"inline-flex flex-col gap-[var(--cmp-datepicker-calendar-gap)] rounded-[var(--cmp-datepicker-calendar-radius)] bg-[var(--cmp-datepicker-calendar-bg)] p-[var(--cmp-datepicker-calendar-paddingXY)] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.2)] select-none",
|
|
12294
|
-
|
|
13257
|
+
"inline-flex max-w-full flex-col gap-[var(--cmp-datepicker-calendar-gap)] rounded-[var(--cmp-datepicker-calendar-radius)] bg-[var(--cmp-datepicker-calendar-bg)] p-[var(--cmp-datepicker-calendar-paddingXY)] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.2)] select-none",
|
|
13258
|
+
// 높이는 고정이 아니라 하한이다 — 5주/6주 달을 오갈 때의 높이 흔들림만 막으면 되고,
|
|
13259
|
+
// 창이 좁아 패널이 가로 스크롤될 때는 스크롤바 높이만큼 늘어날 수 있어야 한다.
|
|
13260
|
+
// (단일 달 SCalendar 도 min-h 를 쓴다)
|
|
13261
|
+
useTimePicker ? "h-auto" : "min-h-[364px]"
|
|
12295
13262
|
),
|
|
12296
13263
|
children: [
|
|
12297
13264
|
/* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
@@ -12310,11 +13277,20 @@ function RangeCalendar({
|
|
|
12310
13277
|
}
|
|
12311
13278
|
)
|
|
12312
13279
|
] }),
|
|
12313
|
-
/* @__PURE__ */ jsxs(
|
|
12314
|
-
|
|
12315
|
-
|
|
12316
|
-
|
|
12317
|
-
|
|
13280
|
+
/* @__PURE__ */ jsxs(
|
|
13281
|
+
"div",
|
|
13282
|
+
{
|
|
13283
|
+
className: cn(
|
|
13284
|
+
"flex max-w-full gap-[var(--cmp-datepicker-calendar-range-panelGap)] overflow-x-auto",
|
|
13285
|
+
SCROLLBAR_CLASS
|
|
13286
|
+
),
|
|
13287
|
+
children: [
|
|
13288
|
+
renderPanel(y, m, true),
|
|
13289
|
+
/* @__PURE__ */ jsx(SDivider, { vertical: true }),
|
|
13290
|
+
renderPanel(nextMonthYM.year, nextMonthYM.month, false)
|
|
13291
|
+
]
|
|
13292
|
+
}
|
|
13293
|
+
),
|
|
12318
13294
|
useTimePicker && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
12319
13295
|
/* @__PURE__ */ jsx(SDivider, {}),
|
|
12320
13296
|
/* @__PURE__ */ jsxs("div", { className: "flex gap-[var(--cmp-datepicker-calendar-time-gap)]", children: [
|
|
@@ -12373,7 +13349,30 @@ function SDateRangePicker({
|
|
|
12373
13349
|
});
|
|
12374
13350
|
const resolvedError = error || ruleError !== "";
|
|
12375
13351
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
12376
|
-
const dims = size === "md" ? {
|
|
13352
|
+
const dims = size === "md" ? {
|
|
13353
|
+
padX: 16,
|
|
13354
|
+
gap: 12,
|
|
13355
|
+
icon: 20,
|
|
13356
|
+
minW: 104,
|
|
13357
|
+
fieldMinW: 260,
|
|
13358
|
+
// 상한 등급 xl — 값이 `YYYY-MM-DD ~ YYYY-MM-DD` 라 단일 날짜의 두 배가 넘는다.
|
|
13359
|
+
// 최소너비(260)가 이미 lg(240)를 넘으므로 상한도 한 등급 위여야 한다
|
|
13360
|
+
fieldMaxW: 480,
|
|
13361
|
+
fontSize: 14,
|
|
13362
|
+
lineHeight: 24,
|
|
13363
|
+
radius: 6
|
|
13364
|
+
} : {
|
|
13365
|
+
padX: 12,
|
|
13366
|
+
gap: 8,
|
|
13367
|
+
icon: 16,
|
|
13368
|
+
minW: 80,
|
|
13369
|
+
fieldMinW: 216,
|
|
13370
|
+
// 상한 등급 lg — 최소너비 216 이 md(160)를 넘어 md 로는 담기지 않는다
|
|
13371
|
+
fieldMaxW: 240,
|
|
13372
|
+
fontSize: 12,
|
|
13373
|
+
lineHeight: 20,
|
|
13374
|
+
radius: 4
|
|
13375
|
+
};
|
|
12377
13376
|
const select = (r) => {
|
|
12378
13377
|
setPendingStart(null);
|
|
12379
13378
|
onValueChange?.(r);
|
|
@@ -12399,11 +13398,13 @@ function SDateRangePicker({
|
|
|
12399
13398
|
focused: open,
|
|
12400
13399
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
12401
13400
|
width,
|
|
13401
|
+
minWidth: dims.fieldMinW,
|
|
13402
|
+
maxWidth: dims.fieldMaxW,
|
|
12402
13403
|
disabled,
|
|
12403
13404
|
className,
|
|
12404
13405
|
style,
|
|
12405
13406
|
children: /* @__PURE__ */ jsxs(
|
|
12406
|
-
|
|
13407
|
+
RPopover10.Root,
|
|
12407
13408
|
{
|
|
12408
13409
|
open,
|
|
12409
13410
|
onOpenChange: (o) => {
|
|
@@ -12412,7 +13413,7 @@ function SDateRangePicker({
|
|
|
12412
13413
|
if (!o) setPendingStart(null);
|
|
12413
13414
|
},
|
|
12414
13415
|
children: [
|
|
12415
|
-
/* @__PURE__ */ jsx(
|
|
13416
|
+
/* @__PURE__ */ jsx(RPopover10.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
12416
13417
|
"button",
|
|
12417
13418
|
{
|
|
12418
13419
|
type: "button",
|
|
@@ -12453,13 +13454,16 @@ function SDateRangePicker({
|
|
|
12453
13454
|
]
|
|
12454
13455
|
}
|
|
12455
13456
|
) }),
|
|
12456
|
-
/* @__PURE__ */ jsx(
|
|
12457
|
-
|
|
13457
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
13458
|
+
RPopover10.Content,
|
|
12458
13459
|
{
|
|
12459
13460
|
side: "bottom",
|
|
12460
13461
|
align: "start",
|
|
12461
13462
|
sideOffset: 4,
|
|
12462
|
-
className: cn(
|
|
13463
|
+
className: cn(
|
|
13464
|
+
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
13465
|
+
FLOATING_SLIDE_ANIM
|
|
13466
|
+
),
|
|
12463
13467
|
children: /* @__PURE__ */ jsx(
|
|
12464
13468
|
RangeCalendar,
|
|
12465
13469
|
{
|
|
@@ -12860,6 +13864,7 @@ function SKeyValueTable({
|
|
|
12860
13864
|
values = {},
|
|
12861
13865
|
search = false,
|
|
12862
13866
|
radius = "default",
|
|
13867
|
+
bordered = true,
|
|
12863
13868
|
onChange,
|
|
12864
13869
|
onSearch,
|
|
12865
13870
|
className,
|
|
@@ -12924,7 +13929,8 @@ function SKeyValueTable({
|
|
|
12924
13929
|
});
|
|
12925
13930
|
const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[8px] rounded-t-none" : "rounded-[8px]";
|
|
12926
13931
|
const frameClass = cn(
|
|
12927
|
-
"overflow-hidden
|
|
13932
|
+
"overflow-hidden",
|
|
13933
|
+
bordered && "border border-solid border-[color:var(--cmp-table-border-color)]",
|
|
12928
13934
|
radiusClass
|
|
12929
13935
|
);
|
|
12930
13936
|
const table = /* @__PURE__ */ jsxs(
|
|
@@ -13447,7 +14453,7 @@ function SRadioButton({
|
|
|
13447
14453
|
disabled: od,
|
|
13448
14454
|
onClick: () => !od && !selected && onValueChange?.(o.value),
|
|
13449
14455
|
className: cn(
|
|
13450
|
-
"relative box-border inline-flex items-center justify-center whitespace-nowrap border border-solid text-[12px] font-medium leading-[20px] transition-colors",
|
|
14456
|
+
"relative box-border grow inline-flex items-center justify-center whitespace-nowrap border border-solid text-[12px] font-medium leading-[20px] transition-colors",
|
|
13451
14457
|
i === 0 ? "rounded-l-[var(--cmp-radioButton-radius)]" : "-ml-px",
|
|
13452
14458
|
i === options.length - 1 ? "rounded-r-[var(--cmp-radioButton-radius)]" : "",
|
|
13453
14459
|
selected ? "z-10" : "",
|
|
@@ -13469,7 +14475,1565 @@ function SRadioButton({
|
|
|
13469
14475
|
}
|
|
13470
14476
|
);
|
|
13471
14477
|
}
|
|
13472
|
-
var
|
|
14478
|
+
var FONT2 = {
|
|
14479
|
+
sm: {
|
|
14480
|
+
fontSize: 12,
|
|
14481
|
+
lineHeight: 20,
|
|
14482
|
+
paddingX: "var(--cmp-textinput-sm-paddingX)",
|
|
14483
|
+
gap: "var(--cmp-textinput-sm-gap)"
|
|
14484
|
+
},
|
|
14485
|
+
md: {
|
|
14486
|
+
fontSize: 14,
|
|
14487
|
+
lineHeight: 24,
|
|
14488
|
+
paddingX: "var(--cmp-textinput-md-paddingX)",
|
|
14489
|
+
gap: "var(--cmp-textinput-md-gap)"
|
|
14490
|
+
}
|
|
14491
|
+
};
|
|
14492
|
+
var SSearchInput = /* @__PURE__ */ forwardRef(function SSearchInput2({
|
|
14493
|
+
value,
|
|
14494
|
+
onValueChange,
|
|
14495
|
+
onChange,
|
|
14496
|
+
onSearch,
|
|
14497
|
+
size = "sm",
|
|
14498
|
+
placeholder = "\uACB0\uACFC \uB0B4 \uAC80\uC0C9",
|
|
14499
|
+
clearable = false,
|
|
14500
|
+
disabled = false,
|
|
14501
|
+
width,
|
|
14502
|
+
focused,
|
|
14503
|
+
hovered,
|
|
14504
|
+
inputClass,
|
|
14505
|
+
inputStyle,
|
|
14506
|
+
className,
|
|
14507
|
+
style,
|
|
14508
|
+
onKeyDown,
|
|
14509
|
+
...rest
|
|
14510
|
+
}, ref) {
|
|
14511
|
+
const f = FONT2[size];
|
|
14512
|
+
const hasValue = value !== void 0 && value !== null && String(value) !== "";
|
|
14513
|
+
return /* @__PURE__ */ jsx(
|
|
14514
|
+
SField,
|
|
14515
|
+
{
|
|
14516
|
+
size,
|
|
14517
|
+
width,
|
|
14518
|
+
focused,
|
|
14519
|
+
hovered,
|
|
14520
|
+
disabled,
|
|
14521
|
+
className,
|
|
14522
|
+
style,
|
|
14523
|
+
children: /* @__PURE__ */ jsxs(
|
|
14524
|
+
"div",
|
|
14525
|
+
{
|
|
14526
|
+
className: "flex h-full w-full items-center",
|
|
14527
|
+
style: {
|
|
14528
|
+
gap: f.gap,
|
|
14529
|
+
padding: `0 ${f.paddingX}`,
|
|
14530
|
+
fontSize: f.fontSize,
|
|
14531
|
+
lineHeight: `${f.lineHeight}px`
|
|
14532
|
+
},
|
|
14533
|
+
children: [
|
|
14534
|
+
/* @__PURE__ */ jsx(
|
|
14535
|
+
SIcon,
|
|
14536
|
+
{
|
|
14537
|
+
name: "search",
|
|
14538
|
+
size: 16,
|
|
14539
|
+
color: disabled ? "var(--sys-color-disabled-icon)" : "var(--cmp-textinput-icon-default)",
|
|
14540
|
+
className: "flex-shrink-0"
|
|
14541
|
+
}
|
|
14542
|
+
),
|
|
14543
|
+
/* @__PURE__ */ jsx(
|
|
14544
|
+
"input",
|
|
14545
|
+
{
|
|
14546
|
+
ref,
|
|
14547
|
+
type: "search",
|
|
14548
|
+
value: value ?? "",
|
|
14549
|
+
disabled,
|
|
14550
|
+
placeholder,
|
|
14551
|
+
onChange: (e) => {
|
|
14552
|
+
onChange?.(e);
|
|
14553
|
+
onValueChange?.(e.target.value);
|
|
14554
|
+
},
|
|
14555
|
+
onKeyDown: (e) => {
|
|
14556
|
+
onKeyDown?.(e);
|
|
14557
|
+
if (e.key === "Enter" && !e.nativeEvent.isComposing) {
|
|
14558
|
+
onSearch?.(e.currentTarget.value);
|
|
14559
|
+
}
|
|
14560
|
+
},
|
|
14561
|
+
className: cn(
|
|
14562
|
+
// type="search" 의 브라우저 기본 취소 버튼은 clearable 과 겹치므로 지운다
|
|
14563
|
+
"h-full min-w-0 flex-1 border-0 bg-transparent p-0 outline-none placeholder:text-[color:var(--sys-color-field-text-placeholder)] disabled:cursor-not-allowed [&::-webkit-search-cancel-button]:hidden",
|
|
14564
|
+
AUTOFILL_RESET_CLASS,
|
|
14565
|
+
inputClass
|
|
14566
|
+
),
|
|
14567
|
+
style: {
|
|
14568
|
+
// fontSize/lineHeight 는 컨테이너에서 상속 (원본 font-size: inherit)
|
|
14569
|
+
color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--sys-color-field-text-default)",
|
|
14570
|
+
...inputStyle
|
|
14571
|
+
},
|
|
14572
|
+
...rest
|
|
14573
|
+
}
|
|
14574
|
+
),
|
|
14575
|
+
clearable && hasValue && !disabled && /* @__PURE__ */ jsx(
|
|
14576
|
+
SGhostButton,
|
|
14577
|
+
{
|
|
14578
|
+
icon: "close",
|
|
14579
|
+
size: "xxs",
|
|
14580
|
+
ariaLabel: "\uC9C0\uC6B0\uAE30",
|
|
14581
|
+
className: "flex-shrink-0",
|
|
14582
|
+
onClick: () => onValueChange?.("")
|
|
14583
|
+
}
|
|
14584
|
+
)
|
|
14585
|
+
]
|
|
14586
|
+
}
|
|
14587
|
+
)
|
|
14588
|
+
}
|
|
14589
|
+
);
|
|
14590
|
+
});
|
|
14591
|
+
var CHIPFILTER_LISTBOX_WIDTH = 240;
|
|
14592
|
+
var CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH = 246;
|
|
14593
|
+
var CHIPFILTER = {
|
|
14594
|
+
barBg: "var(--cmp-chipFilter-bar-bg)",
|
|
14595
|
+
barBorder: "var(--cmp-chipFilter-bar-border)",
|
|
14596
|
+
barPaddingX: "var(--cmp-chipFilter-bar-paddingX)",
|
|
14597
|
+
barPaddingY: "var(--cmp-chipFilter-bar-paddingY)",
|
|
14598
|
+
barGap: "var(--cmp-chipFilter-bar-gap)",
|
|
14599
|
+
dividerHeight: "var(--cmp-chipFilter-divider-height)",
|
|
14600
|
+
chipHeight: "var(--cmp-chipFilter-chip-height)",
|
|
14601
|
+
chipRadius: "var(--cmp-chipFilter-chip-radius)",
|
|
14602
|
+
chipGap: "var(--cmp-chipFilter-chip-gap)",
|
|
14603
|
+
chipDefaultBg: "var(--cmp-chipFilter-chip-default-bg)",
|
|
14604
|
+
chipDefaultBorder: "var(--cmp-chipFilter-chip-default-border)",
|
|
14605
|
+
chipDefaultText: "var(--cmp-chipFilter-chip-default-text)",
|
|
14606
|
+
chipActiveBorder: "var(--cmp-chipFilter-chip-active-border)",
|
|
14607
|
+
chipWarningBorder: "var(--cmp-chipFilter-chip-warning-border)",
|
|
14608
|
+
chipAppliedBg: "var(--cmp-chipFilter-chip-applied-bg)",
|
|
14609
|
+
chipAppliedBorder: "var(--cmp-chipFilter-chip-applied-border)",
|
|
14610
|
+
chipAppliedLabel: "var(--cmp-chipFilter-chip-applied-text-label)",
|
|
14611
|
+
chipAppliedValue: "var(--color-brilliantblue-80)",
|
|
14612
|
+
chipDisabledBg: "var(--cmp-chipFilter-chip-disabled-bg)",
|
|
14613
|
+
chipDisabledBorder: "var(--cmp-chipFilter-chip-disabled-border)",
|
|
14614
|
+
chipDisabledText: "var(--cmp-chipFilter-chip-disabled-text)",
|
|
14615
|
+
addBorder: "var(--cmp-chipFilter-addButton-border-default)",
|
|
14616
|
+
addBorderDisabled: "var(--cmp-chipFilter-addButton-border-disabled)",
|
|
14617
|
+
addText: "var(--cmp-chipFilter-addButton-text-default)",
|
|
14618
|
+
addTextDisabled: "var(--cmp-chipFilter-addButton-text-disabled)",
|
|
14619
|
+
listboxBg: "var(--cmp-chipFilter-listbox-bg)",
|
|
14620
|
+
listboxBorder: "var(--cmp-chipFilter-listbox-border-color)",
|
|
14621
|
+
listboxRadius: "var(--cmp-chipFilter-listbox-radius)",
|
|
14622
|
+
listboxLabel: "var(--cmp-chipFilter-listbox-top-label-color)",
|
|
14623
|
+
listboxBottomDividerHeight: "var(--cmp-chipFilter-listbox-bottom-divider-height)",
|
|
14624
|
+
itemPaddingLeft: "var(--cmp-chipFilter-item-paddingLeft)",
|
|
14625
|
+
itemPaddingRight: "var(--cmp-chipFilter-item-paddingRight)",
|
|
14626
|
+
itemPaddingY: "var(--cmp-chipFilter-item-paddingY)",
|
|
14627
|
+
itemMultiPaddingX: "var(--cmp-chipFilter-item-multi-paddingX)",
|
|
14628
|
+
itemTextDefault: "var(--cmp-chipFilter-item-text-default)",
|
|
14629
|
+
itemTextSelected: "var(--cmp-chipFilter-item-text-selected)"
|
|
14630
|
+
};
|
|
14631
|
+
var DEFAULT_PERIOD_PRESETS = [
|
|
14632
|
+
{ value: "day", label: "\uC77C\uBCC4" },
|
|
14633
|
+
{ value: "month", label: "\uC6D4\uBCC4" },
|
|
14634
|
+
{ value: "quarter", label: "\uBD84\uAE30\uBCC4" },
|
|
14635
|
+
{ value: "half", label: "\uBC18\uAE30\uBCC4" },
|
|
14636
|
+
{ value: "year", label: "\uC5F0\uB3C4\uBCC4" },
|
|
14637
|
+
{ value: "custom", label: "\uC0AC\uC6A9\uC790 \uC9C0\uC815", custom: true }
|
|
14638
|
+
];
|
|
14639
|
+
var isKeywordValue = (value) => typeof value === "object" && value != null && !Array.isArray(value) && "keywords" in value;
|
|
14640
|
+
var isPeriodValue = (value) => typeof value === "object" && value != null && !Array.isArray(value) && "unit" in value;
|
|
14641
|
+
var keywordEntries = (value) => {
|
|
14642
|
+
if (isKeywordValue(value)) return value.keywords;
|
|
14643
|
+
if (Array.isArray(value)) {
|
|
14644
|
+
return value.filter((v) => typeof v === "string");
|
|
14645
|
+
}
|
|
14646
|
+
return [];
|
|
14647
|
+
};
|
|
14648
|
+
var isEmptyValue = (value) => {
|
|
14649
|
+
if (value == null) return true;
|
|
14650
|
+
if (Array.isArray(value)) return value.length === 0 || value.every((v) => v == null || v === "");
|
|
14651
|
+
if (isKeywordValue(value)) return value.keywords.length === 0;
|
|
14652
|
+
return value === "";
|
|
14653
|
+
};
|
|
14654
|
+
var normalizeValues = (value) => value ?? {};
|
|
14655
|
+
var toArrayValue = (value) => Array.isArray(value) ? value.filter(
|
|
14656
|
+
(v) => typeof v === "string" || typeof v === "number"
|
|
14657
|
+
) : [];
|
|
14658
|
+
var todayIso = () => {
|
|
14659
|
+
const d = /* @__PURE__ */ new Date();
|
|
14660
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
14661
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
14662
|
+
};
|
|
14663
|
+
var isInlineDateField = (field) => field.type === "date" && field.radioButton === true && (field.presets?.length ?? 0) > 0;
|
|
14664
|
+
var getFieldPresets = (field) => {
|
|
14665
|
+
if (field.type === "period") return field.presets ?? DEFAULT_PERIOD_PRESETS;
|
|
14666
|
+
return field.presets ?? [];
|
|
14667
|
+
};
|
|
14668
|
+
var getDefaultPeriodInputValue = (unit) => {
|
|
14669
|
+
const today = todayIso();
|
|
14670
|
+
if (unit === "day") return today;
|
|
14671
|
+
if (unit === "month") return today.slice(0, 7);
|
|
14672
|
+
if (unit === "quarter") return 1;
|
|
14673
|
+
if (unit === "half") return "first";
|
|
14674
|
+
if (unit === "year") return today.slice(0, 4);
|
|
14675
|
+
return [today, today];
|
|
14676
|
+
};
|
|
14677
|
+
var createPeriodValue = (unit) => ({
|
|
14678
|
+
unit,
|
|
14679
|
+
value: getDefaultPeriodInputValue(unit)
|
|
14680
|
+
});
|
|
14681
|
+
var resolveFieldDefault = (field) => {
|
|
14682
|
+
if (field.defaultValue !== void 0) return field.defaultValue;
|
|
14683
|
+
if (isInlineDateField(field)) return todayIso();
|
|
14684
|
+
if (!field.required) return void 0;
|
|
14685
|
+
if (field.type === "single") return field.options?.[0]?.value;
|
|
14686
|
+
if (field.type === "date") return todayIso();
|
|
14687
|
+
if (field.type === "period") {
|
|
14688
|
+
const unit = getFieldPresets(field).find((preset) => !preset.custom)?.value;
|
|
14689
|
+
return unit ? createPeriodValue(unit) : void 0;
|
|
14690
|
+
}
|
|
14691
|
+
return void 0;
|
|
14692
|
+
};
|
|
14693
|
+
var valuesEqual = (a, b) => {
|
|
14694
|
+
if (isKeywordValue(a) || isKeywordValue(b)) {
|
|
14695
|
+
return isKeywordValue(a) && isKeywordValue(b) && a.mode === b.mode && valuesEqual(a.keywords, b.keywords);
|
|
14696
|
+
}
|
|
14697
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
14698
|
+
return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((v, i) => v === b[i]);
|
|
14699
|
+
}
|
|
14700
|
+
return a === b;
|
|
14701
|
+
};
|
|
14702
|
+
var valuesMapEqual = (a, b) => {
|
|
14703
|
+
const keys = /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)]);
|
|
14704
|
+
for (const key of keys) {
|
|
14705
|
+
if (!valuesEqual(a[key], b[key])) return false;
|
|
14706
|
+
}
|
|
14707
|
+
return true;
|
|
14708
|
+
};
|
|
14709
|
+
var isAtDefaultValue = (field, value) => {
|
|
14710
|
+
const def = resolveFieldDefault(field);
|
|
14711
|
+
return def !== void 0 && valuesEqual(value, def);
|
|
14712
|
+
};
|
|
14713
|
+
var isInlineField = (field) => isInlineDateField(field) || field.type === "custom";
|
|
14714
|
+
var isFixedField = (field) => field.fix === true || field.required === true;
|
|
14715
|
+
var isAddableField = (field) => !isFixedField(field);
|
|
14716
|
+
var isGroupedFields = (fields) => fields.length > 0 && "fields" in fields[0];
|
|
14717
|
+
var isGroupSatisfied = (group, values) => {
|
|
14718
|
+
if (!group.rule) return true;
|
|
14719
|
+
const keys = group.fields.map((f) => f.key);
|
|
14720
|
+
if (group.rule.type === "requireKey") return !isEmptyValue(values[group.rule.key]);
|
|
14721
|
+
if (group.rule.type === "requireAll") return keys.every((k) => !isEmptyValue(values[k]));
|
|
14722
|
+
if (group.rule.type === "requireAny") return keys.some((k) => !isEmptyValue(values[k]));
|
|
14723
|
+
return true;
|
|
14724
|
+
};
|
|
14725
|
+
var koreanParticle = (word, consonant, vowel) => {
|
|
14726
|
+
const code = word.charCodeAt(word.length - 1);
|
|
14727
|
+
if (code < 44032 || code > 55203) return consonant;
|
|
14728
|
+
return (code - 44032) % 28 === 0 ? vowel : consonant;
|
|
14729
|
+
};
|
|
14730
|
+
var defaultGroupTooltipMessage = (rule, fields) => {
|
|
14731
|
+
if (rule.type === "requireAll") return "\uD56D\uBAA9\uC744 \uBAA8\uB450 \uC120\uD0DD\uD574 \uC8FC\uC138\uC694.";
|
|
14732
|
+
if (rule.type === "requireAny") {
|
|
14733
|
+
const name = rule.dataGroupName;
|
|
14734
|
+
if (!name) return "\uCD5C\uC18C 1\uAC1C\uC758 \uD544\uD130\uB97C \uC120\uD0DD\uD574\uC8FC\uC138\uC694.";
|
|
14735
|
+
return `\uCD5C\uC18C 1\uAC1C\uC758 ${name}${koreanParticle(name, "\uC744", "\uB97C")} \uC120\uD0DD\uD574\uC8FC\uC138\uC694.`;
|
|
14736
|
+
}
|
|
14737
|
+
const label = fields.find((f) => f.key === rule.key)?.label ?? "\uD56D\uBAA9";
|
|
14738
|
+
return `${label}${koreanParticle(label, "\uC744", "\uB97C")} \uC120\uD0DD\uD574 \uC8FC\uC138\uC694.`;
|
|
14739
|
+
};
|
|
14740
|
+
var matchPresetId = (presets, value) => {
|
|
14741
|
+
if (isEmptyValue(value)) return null;
|
|
14742
|
+
if (isPeriodValue(value)) return value.unit;
|
|
14743
|
+
for (const preset of presets) {
|
|
14744
|
+
if (preset.custom) continue;
|
|
14745
|
+
const resolved = preset.resolve ? preset.resolve() : preset.value;
|
|
14746
|
+
if (Array.isArray(resolved) && Array.isArray(value)) {
|
|
14747
|
+
if (resolved[0] === value[0] && resolved[1] === value[1]) return preset.value;
|
|
14748
|
+
} else if (!Array.isArray(resolved) && !Array.isArray(value) && resolved === value) {
|
|
14749
|
+
return preset.value;
|
|
14750
|
+
}
|
|
14751
|
+
}
|
|
14752
|
+
return presets.find((preset) => preset.custom)?.value ?? null;
|
|
14753
|
+
};
|
|
14754
|
+
var optionLabel = (field, value) => field.options?.find((option) => option.value === value)?.label ?? String(value);
|
|
14755
|
+
var formatValueList = (labels) => {
|
|
14756
|
+
if (labels.length <= 1) return labels[0] ?? "";
|
|
14757
|
+
return `${labels[0]} \uC678 ${labels.length - 1}\uAC1C`;
|
|
14758
|
+
};
|
|
14759
|
+
var displayValue = (field, value) => {
|
|
14760
|
+
if (isEmptyValue(value)) return "";
|
|
14761
|
+
if (field.type === "multi") {
|
|
14762
|
+
const values = toArrayValue(value);
|
|
14763
|
+
const selectableValues = (field.options ?? []).filter((option) => !option.disabled).map((option) => option.value);
|
|
14764
|
+
if (selectableValues.length > 0 && selectableValues.every((selectableValue) => values.includes(selectableValue))) {
|
|
14765
|
+
return "\uC804\uCCB4";
|
|
14766
|
+
}
|
|
14767
|
+
return formatValueList(values.map((v) => optionLabel(field, v)));
|
|
14768
|
+
}
|
|
14769
|
+
if (field.type === "single") return optionLabel(field, value);
|
|
14770
|
+
if (field.type === "date")
|
|
14771
|
+
return Array.isArray(value) ? `${value[0]} ~ ${value[1]}` : String(value);
|
|
14772
|
+
if (field.type === "period") {
|
|
14773
|
+
if (!isPeriodValue(value)) {
|
|
14774
|
+
const preset2 = getFieldPresets(field).find((p) => p.value === value);
|
|
14775
|
+
return preset2?.label ?? String(value);
|
|
14776
|
+
}
|
|
14777
|
+
const preset = getFieldPresets(field).find((p) => p.value === value.unit);
|
|
14778
|
+
const label = preset?.label ?? value.unit;
|
|
14779
|
+
if (value.unit === "quarter") return `${label}(${value.value ?? 1}\uBD84\uAE30)`;
|
|
14780
|
+
if (value.unit === "half") return `${label}(${value.value === "second" ? "\uD558\uBC18\uAE30" : "\uC0C1\uBC18\uAE30"})`;
|
|
14781
|
+
if (Array.isArray(value.value)) return `${value.value[0]} ~ ${value.value[1]}`;
|
|
14782
|
+
return value.value != null && value.value !== "" ? String(value.value) : label;
|
|
14783
|
+
}
|
|
14784
|
+
if (field.type === "keyword") return formatValueList(keywordEntries(value));
|
|
14785
|
+
return String(value);
|
|
14786
|
+
};
|
|
14787
|
+
var chipDisplayValue = (field, value) => {
|
|
14788
|
+
const text = displayValue(field, value);
|
|
14789
|
+
if (field.type !== "date" || isEmptyValue(value)) return text;
|
|
14790
|
+
const presets = getFieldPresets(field);
|
|
14791
|
+
if (presets.length === 0) return text;
|
|
14792
|
+
const preset = presets.find((p) => p.value === matchPresetId(presets, value));
|
|
14793
|
+
return preset && !preset.custom ? `${preset.label}(${text})` : text;
|
|
14794
|
+
};
|
|
14795
|
+
var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
14796
|
+
fields: fieldsProp = [],
|
|
14797
|
+
value,
|
|
14798
|
+
onValueChange,
|
|
14799
|
+
onFilterChange,
|
|
14800
|
+
onSearch,
|
|
14801
|
+
activeKeys,
|
|
14802
|
+
onActiveKeysChange,
|
|
14803
|
+
onReset,
|
|
14804
|
+
onAddFilter,
|
|
14805
|
+
label = "\uAC80\uC0C9 \uD544\uD130",
|
|
14806
|
+
showLabel = false,
|
|
14807
|
+
showReset = true,
|
|
14808
|
+
disabled = false,
|
|
14809
|
+
className,
|
|
14810
|
+
style
|
|
14811
|
+
}, ref) {
|
|
14812
|
+
const usingGroupedFields = isGroupedFields(fieldsProp);
|
|
14813
|
+
const groups = useMemo(
|
|
14814
|
+
() => usingGroupedFields ? fieldsProp : [{ fields: fieldsProp }],
|
|
14815
|
+
[usingGroupedFields, fieldsProp]
|
|
14816
|
+
);
|
|
14817
|
+
const fields = useMemo(() => groups.flatMap((group) => group.fields), [groups]);
|
|
14818
|
+
const values = normalizeValues(value);
|
|
14819
|
+
const portalContainer = usePortalContainer();
|
|
14820
|
+
const [internalActiveKeys, setInternalActiveKeys] = useState(
|
|
14821
|
+
() => fields.filter((field) => isFixedField(field) || field.defaultActive !== false).map((field) => field.key)
|
|
14822
|
+
);
|
|
14823
|
+
const [openKey, setOpenKey] = useState(null);
|
|
14824
|
+
const [addOpen, setAddOpen] = useState(false);
|
|
14825
|
+
const triggerRefs = useRef(/* @__PURE__ */ new Map());
|
|
14826
|
+
const initializedDefaultsRef = useRef(/* @__PURE__ */ new Set());
|
|
14827
|
+
const prevOpenKeyRef = useRef(null);
|
|
14828
|
+
const valuesRef = useRef(values);
|
|
14829
|
+
valuesRef.current = values;
|
|
14830
|
+
const lastSearchedValuesRef = useRef(values);
|
|
14831
|
+
const invalidGroups = useMemo(() => {
|
|
14832
|
+
const invalid = /* @__PURE__ */ new Set();
|
|
14833
|
+
groups.forEach((group, groupIndex) => {
|
|
14834
|
+
if (!isGroupSatisfied(group, values)) invalid.add(groupIndex);
|
|
14835
|
+
});
|
|
14836
|
+
return invalid;
|
|
14837
|
+
}, [groups, values]);
|
|
14838
|
+
const isGroupsValid = useCallback(
|
|
14839
|
+
(current) => groups.every((group) => isGroupSatisfied(group, current)),
|
|
14840
|
+
[groups]
|
|
14841
|
+
);
|
|
14842
|
+
const runSearch = useCallback(
|
|
14843
|
+
(next) => {
|
|
14844
|
+
if (valuesMapEqual(lastSearchedValuesRef.current, next)) return;
|
|
14845
|
+
if (!isGroupsValid(next)) return;
|
|
14846
|
+
lastSearchedValuesRef.current = next;
|
|
14847
|
+
onSearch?.(next);
|
|
14848
|
+
},
|
|
14849
|
+
[isGroupsValid, onSearch]
|
|
14850
|
+
);
|
|
14851
|
+
useEffect(() => {
|
|
14852
|
+
const prevKey = prevOpenKeyRef.current;
|
|
14853
|
+
if (prevKey != null && prevKey !== openKey) {
|
|
14854
|
+
runSearch(valuesRef.current);
|
|
14855
|
+
}
|
|
14856
|
+
prevOpenKeyRef.current = openKey;
|
|
14857
|
+
}, [openKey, runSearch]);
|
|
14858
|
+
useEffect(() => {
|
|
14859
|
+
if (activeKeys) return;
|
|
14860
|
+
setInternalActiveKeys((current) => {
|
|
14861
|
+
const known = new Set(fields.map((field) => field.key));
|
|
14862
|
+
const kept = current.filter((key) => known.has(key));
|
|
14863
|
+
const additions = fields.filter(
|
|
14864
|
+
(field) => (isFixedField(field) || field.defaultActive !== false) && !kept.includes(field.key)
|
|
14865
|
+
).map((field) => field.key);
|
|
14866
|
+
return [...kept, ...additions];
|
|
14867
|
+
});
|
|
14868
|
+
}, [activeKeys, fields]);
|
|
14869
|
+
useEffect(() => {
|
|
14870
|
+
const patch = {};
|
|
14871
|
+
let changed = false;
|
|
14872
|
+
fields.forEach((field) => {
|
|
14873
|
+
if (initializedDefaultsRef.current.has(field.key)) return;
|
|
14874
|
+
if (!isEmptyValue(values[field.key])) {
|
|
14875
|
+
initializedDefaultsRef.current.add(field.key);
|
|
14876
|
+
return;
|
|
14877
|
+
}
|
|
14878
|
+
const def = resolveFieldDefault(field);
|
|
14879
|
+
if (def === void 0) return;
|
|
14880
|
+
patch[field.key] = def;
|
|
14881
|
+
initializedDefaultsRef.current.add(field.key);
|
|
14882
|
+
changed = true;
|
|
14883
|
+
});
|
|
14884
|
+
if (changed) onValueChange?.({ ...values, ...patch });
|
|
14885
|
+
}, [fields, values, onValueChange]);
|
|
14886
|
+
const fixedKeys = fields.filter(isFixedField).map((field) => field.key);
|
|
14887
|
+
const resolvedActiveKeys = Array.from(
|
|
14888
|
+
/* @__PURE__ */ new Set([...activeKeys ?? internalActiveKeys, ...fixedKeys])
|
|
14889
|
+
);
|
|
14890
|
+
const activeFields = fields.filter((field) => resolvedActiveKeys.includes(field.key));
|
|
14891
|
+
const inactiveFields = fields.filter(
|
|
14892
|
+
(field) => isAddableField(field) && !resolvedActiveKeys.includes(field.key)
|
|
14893
|
+
);
|
|
14894
|
+
const groupIndexByKey = /* @__PURE__ */ new Map();
|
|
14895
|
+
groups.forEach((group, groupIndex) => {
|
|
14896
|
+
group.fields.forEach((field) => groupIndexByKey.set(field.key, groupIndex));
|
|
14897
|
+
});
|
|
14898
|
+
const hasValue = fields.some((field) => !isEmptyValue(values[field.key]));
|
|
14899
|
+
const hasAddButton = fields.some(isAddableField);
|
|
14900
|
+
const hasRightActions = hasAddButton || showReset;
|
|
14901
|
+
const currentOpenField = fields.find((field) => field.key === openKey);
|
|
14902
|
+
const editorPopoverStyle = useMemo(() => {
|
|
14903
|
+
if (currentOpenField?.type === "keyword") {
|
|
14904
|
+
return { width: CHIPFILTER_LISTBOX_WIDTH };
|
|
14905
|
+
}
|
|
14906
|
+
if ((currentOpenField?.type === "date" || currentOpenField?.type === "period") && getFieldPresets(currentOpenField).length > 0) {
|
|
14907
|
+
return { width: CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH };
|
|
14908
|
+
}
|
|
14909
|
+
return { width: CHIPFILTER_LISTBOX_WIDTH };
|
|
14910
|
+
}, [currentOpenField]);
|
|
14911
|
+
const setActive = (next) => {
|
|
14912
|
+
if (!activeKeys) setInternalActiveKeys(next);
|
|
14913
|
+
onActiveKeysChange?.(next);
|
|
14914
|
+
};
|
|
14915
|
+
const emitValue = (key, nextValue) => {
|
|
14916
|
+
const next = { ...values, [key]: nextValue };
|
|
14917
|
+
onValueChange?.(next);
|
|
14918
|
+
onFilterChange?.({ key, value: nextValue, values: next });
|
|
14919
|
+
return next;
|
|
14920
|
+
};
|
|
14921
|
+
const emitValueAndSearch = (key, nextValue) => {
|
|
14922
|
+
runSearch(emitValue(key, nextValue));
|
|
14923
|
+
};
|
|
14924
|
+
const clearValue = (key) => {
|
|
14925
|
+
const field = fields.find((f) => f.key === key);
|
|
14926
|
+
const def = field ? resolveFieldDefault(field) : void 0;
|
|
14927
|
+
runSearch(emitValue(key, def !== void 0 ? def : null));
|
|
14928
|
+
};
|
|
14929
|
+
const removeField = (key) => {
|
|
14930
|
+
const nextValues = emitValue(key, null);
|
|
14931
|
+
setActive(resolvedActiveKeys.filter((activeKey) => activeKey !== key));
|
|
14932
|
+
if (openKey === key) setOpenKey(null);
|
|
14933
|
+
runSearch(nextValues);
|
|
14934
|
+
};
|
|
14935
|
+
const reset = useCallback(() => {
|
|
14936
|
+
const next = fields.reduce((acc, field) => {
|
|
14937
|
+
const def = resolveFieldDefault(field);
|
|
14938
|
+
acc[field.key] = def !== void 0 ? def : null;
|
|
14939
|
+
return acc;
|
|
14940
|
+
}, {});
|
|
14941
|
+
onValueChange?.(next);
|
|
14942
|
+
runSearch(next);
|
|
14943
|
+
onReset?.();
|
|
14944
|
+
}, [fields, onReset, onValueChange, runSearch]);
|
|
14945
|
+
const open = useCallback(
|
|
14946
|
+
(key) => {
|
|
14947
|
+
const field = fields.find((f) => f.key === key);
|
|
14948
|
+
if (!field || isInlineField(field)) return;
|
|
14949
|
+
setOpenKey(key);
|
|
14950
|
+
},
|
|
14951
|
+
[fields]
|
|
14952
|
+
);
|
|
14953
|
+
const validate = useCallback(() => invalidGroups.size === 0, [invalidGroups]);
|
|
14954
|
+
useImperativeHandle(ref, () => ({ open, reset, validate }), [open, reset, validate]);
|
|
14955
|
+
const addField = (key) => {
|
|
14956
|
+
const next = [...resolvedActiveKeys, key];
|
|
14957
|
+
setActive(next);
|
|
14958
|
+
onAddFilter?.(key);
|
|
14959
|
+
setAddOpen(false);
|
|
14960
|
+
const field = fields.find((f) => f.key === key);
|
|
14961
|
+
if (field && !isInlineField(field)) requestAnimationFrame(() => setOpenKey(key));
|
|
14962
|
+
};
|
|
14963
|
+
const rootStyle = useMemo(
|
|
14964
|
+
() => ({
|
|
14965
|
+
"--chipfilter-bar-bg": CHIPFILTER.barBg,
|
|
14966
|
+
"--chipfilter-bar-border": CHIPFILTER.barBorder,
|
|
14967
|
+
"--chipfilter-bar-padding-x": CHIPFILTER.barPaddingX,
|
|
14968
|
+
"--chipfilter-bar-padding-y": CHIPFILTER.barPaddingY,
|
|
14969
|
+
"--chipfilter-bar-gap": CHIPFILTER.barGap,
|
|
14970
|
+
"--chipfilter-divider-height": CHIPFILTER.dividerHeight,
|
|
14971
|
+
...style
|
|
14972
|
+
}),
|
|
14973
|
+
[style]
|
|
14974
|
+
);
|
|
14975
|
+
return /* @__PURE__ */ jsxs(
|
|
14976
|
+
"div",
|
|
14977
|
+
{
|
|
14978
|
+
className: cn(
|
|
14979
|
+
"flex w-full items-start gap-[var(--chipfilter-bar-gap)] border-b border-solid bg-[var(--chipfilter-bar-bg)] px-[var(--chipfilter-bar-padding-x)] py-[var(--chipfilter-bar-padding-y)]",
|
|
14980
|
+
className
|
|
14981
|
+
),
|
|
14982
|
+
style: { ...rootStyle, borderColor: "var(--chipfilter-bar-border)" },
|
|
14983
|
+
children: [
|
|
14984
|
+
showLabel && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14985
|
+
/* @__PURE__ */ jsx(STag, { className: "shrink-0", shape: "square", size: "sm", color: "darkblue", label }),
|
|
14986
|
+
/* @__PURE__ */ jsx(Divider, { top: true })
|
|
14987
|
+
] }),
|
|
14988
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-[var(--cmp-chipFilter-chip-group)]", children: [
|
|
14989
|
+
(() => {
|
|
14990
|
+
const nodes = [];
|
|
14991
|
+
let runBuffer = [];
|
|
14992
|
+
let runGroupIndex = null;
|
|
14993
|
+
const flushRun = () => {
|
|
14994
|
+
if (runBuffer.length === 0) return;
|
|
14995
|
+
const group = runGroupIndex != null ? groups[runGroupIndex] : void 0;
|
|
14996
|
+
const message = usingGroupedFields && group?.rule ? group.tooltipMessage ?? defaultGroupTooltipMessage(group.rule, group.fields) : void 0;
|
|
14997
|
+
if (message) {
|
|
14998
|
+
nodes.push(
|
|
14999
|
+
/* @__PURE__ */ jsx(
|
|
15000
|
+
GroupTooltip,
|
|
15001
|
+
{
|
|
15002
|
+
message,
|
|
15003
|
+
open: invalidGroups.has(runGroupIndex),
|
|
15004
|
+
children: runBuffer
|
|
15005
|
+
},
|
|
15006
|
+
`group-${runGroupIndex}`
|
|
15007
|
+
)
|
|
15008
|
+
);
|
|
15009
|
+
} else {
|
|
15010
|
+
nodes.push(...runBuffer);
|
|
15011
|
+
}
|
|
15012
|
+
runBuffer = [];
|
|
15013
|
+
};
|
|
15014
|
+
activeFields.forEach((field, index) => {
|
|
15015
|
+
const inline = isInlineField(field);
|
|
15016
|
+
const groupIndex = groupIndexByKey.get(field.key) ?? 0;
|
|
15017
|
+
const warning = field.warning || invalidGroups.has(groupIndex);
|
|
15018
|
+
const prevField = index > 0 ? activeFields[index - 1] : null;
|
|
15019
|
+
const prevGroupIndex = prevField ? groupIndexByKey.get(prevField.key) ?? 0 : null;
|
|
15020
|
+
const needsLeadingDivider = index === 0 ? false : inline || prevField != null && isInlineField(prevField) || groupIndex !== prevGroupIndex;
|
|
15021
|
+
if (groupIndex !== runGroupIndex) {
|
|
15022
|
+
flushRun();
|
|
15023
|
+
runGroupIndex = groupIndex;
|
|
15024
|
+
}
|
|
15025
|
+
const addable = isAddableField(field);
|
|
15026
|
+
const showClear = addable || !isAtDefaultValue(field, values[field.key]);
|
|
15027
|
+
const handleClear = () => {
|
|
15028
|
+
if (addable) {
|
|
15029
|
+
removeField(field.key);
|
|
15030
|
+
return;
|
|
15031
|
+
}
|
|
15032
|
+
clearValue(field.key);
|
|
15033
|
+
};
|
|
15034
|
+
const node = isInlineDateField(field) ? /* @__PURE__ */ jsx(
|
|
15035
|
+
InlineDatePresetFilter,
|
|
15036
|
+
{
|
|
15037
|
+
field,
|
|
15038
|
+
value: values[field.key],
|
|
15039
|
+
disabled: disabled || field.disabled,
|
|
15040
|
+
warning,
|
|
15041
|
+
showClear,
|
|
15042
|
+
onValueChange: (next) => emitValueAndSearch(field.key, next),
|
|
15043
|
+
onClear: handleClear
|
|
15044
|
+
},
|
|
15045
|
+
field.key
|
|
15046
|
+
) : field.type === "custom" ? /* @__PURE__ */ jsxs("div", { className: "inline-flex shrink-0 items-center gap-[4px]", children: [
|
|
15047
|
+
field.render?.({
|
|
15048
|
+
value: values[field.key],
|
|
15049
|
+
disabled: disabled || field.disabled,
|
|
15050
|
+
warning,
|
|
15051
|
+
onValueChange: (next) => emitValueAndSearch(field.key, next)
|
|
15052
|
+
}),
|
|
15053
|
+
addable && !disabled && !field.disabled && showClear && /* @__PURE__ */ jsx(
|
|
15054
|
+
"button",
|
|
15055
|
+
{
|
|
15056
|
+
type: "button",
|
|
15057
|
+
"aria-label": `${field.label} \uD544\uD130 \uC81C\uAC70`,
|
|
15058
|
+
className: "inline-flex size-[16px] shrink-0 items-center justify-center rounded-[var(--cmp-ghostButton-radius-sm)] border-none bg-transparent p-0",
|
|
15059
|
+
onClick: handleClear,
|
|
15060
|
+
children: /* @__PURE__ */ jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
15061
|
+
}
|
|
15062
|
+
)
|
|
15063
|
+
] }, field.key) : /* @__PURE__ */ jsx(
|
|
15064
|
+
FilterChip,
|
|
15065
|
+
{
|
|
15066
|
+
field,
|
|
15067
|
+
valueText: chipDisplayValue(field, values[field.key]),
|
|
15068
|
+
active: openKey === field.key,
|
|
15069
|
+
applied: !isEmptyValue(values[field.key]),
|
|
15070
|
+
disabled: disabled || field.disabled,
|
|
15071
|
+
warning,
|
|
15072
|
+
showClear,
|
|
15073
|
+
showClearWhenEmpty: addable,
|
|
15074
|
+
refCallback: (node2) => triggerRefs.current.set(field.key, node2),
|
|
15075
|
+
onOpen: () => setOpenKey(openKey === field.key ? null : field.key),
|
|
15076
|
+
onClear: handleClear
|
|
15077
|
+
},
|
|
15078
|
+
field.key
|
|
15079
|
+
);
|
|
15080
|
+
runBuffer.push(
|
|
15081
|
+
needsLeadingDivider ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
15082
|
+
/* @__PURE__ */ jsx(Divider, { inset: true }),
|
|
15083
|
+
node
|
|
15084
|
+
] }, `${field.key}-wrap`) : node
|
|
15085
|
+
);
|
|
15086
|
+
});
|
|
15087
|
+
flushRun();
|
|
15088
|
+
return nodes;
|
|
15089
|
+
})(),
|
|
15090
|
+
(() => {
|
|
15091
|
+
const lastField = activeFields[activeFields.length - 1];
|
|
15092
|
+
const needsTrailingDivider = lastField != null && isInlineField(lastField) && !hasRightActions;
|
|
15093
|
+
return needsTrailingDivider ? /* @__PURE__ */ jsx(Divider, { inset: true }) : null;
|
|
15094
|
+
})(),
|
|
15095
|
+
hasRightActions && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
15096
|
+
/* @__PURE__ */ jsx(Divider, { inset: true }),
|
|
15097
|
+
hasAddButton && /* @__PURE__ */ jsxs(RPopover10.Root, { open: addOpen, onOpenChange: setAddOpen, children: [
|
|
15098
|
+
/* @__PURE__ */ jsx(RPopover10.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
15099
|
+
"button",
|
|
15100
|
+
{
|
|
15101
|
+
type: "button",
|
|
15102
|
+
disabled: disabled || inactiveFields.length === 0,
|
|
15103
|
+
className: "inline-flex shrink-0 cursor-pointer items-center justify-center gap-[var(--cmp-chipFilter-addButton-gap)] whitespace-nowrap border border-solid bg-[var(--cmp-chipFilter-addButton-bg)] px-[var(--cmp-chipFilter-addButton-paddingX)] text-[12px] font-medium leading-[20px] outline-none disabled:cursor-not-allowed",
|
|
15104
|
+
style: {
|
|
15105
|
+
minHeight: "var(--cmp-chipFilter-addButton-height)" ,
|
|
15106
|
+
borderRadius: "var(--cmp-chipFilter-addButton-radius)" ,
|
|
15107
|
+
borderColor: disabled || inactiveFields.length === 0 ? CHIPFILTER.addBorderDisabled : CHIPFILTER.addBorder,
|
|
15108
|
+
color: disabled || inactiveFields.length === 0 ? CHIPFILTER.addTextDisabled : CHIPFILTER.addText
|
|
15109
|
+
},
|
|
15110
|
+
children: [
|
|
15111
|
+
/* @__PURE__ */ jsx(
|
|
15112
|
+
SIcon,
|
|
15113
|
+
{
|
|
15114
|
+
name: "add",
|
|
15115
|
+
size: 12,
|
|
15116
|
+
color: disabled || inactiveFields.length === 0 ? CHIPFILTER.addTextDisabled : CHIPFILTER.addText
|
|
15117
|
+
}
|
|
15118
|
+
),
|
|
15119
|
+
/* @__PURE__ */ jsx("span", { children: "\uD544\uD130 \uCD94\uAC00" })
|
|
15120
|
+
]
|
|
15121
|
+
}
|
|
15122
|
+
) }),
|
|
15123
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
15124
|
+
RPopover10.Content,
|
|
15125
|
+
{
|
|
15126
|
+
side: "bottom",
|
|
15127
|
+
align: "start",
|
|
15128
|
+
sideOffset: 4,
|
|
15129
|
+
className: cn("z-50 min-w-[180px]", FLOATING_SLIDE_ANIM),
|
|
15130
|
+
children: /* @__PURE__ */ jsx(ListBox, { children: inactiveFields.length > 0 ? inactiveFields.map((field) => /* @__PURE__ */ jsx(MenuItem, { onClick: () => addField(field.key), children: field.label }, field.key)) : /* @__PURE__ */ jsx(EmptyItem, { children: "\uCD94\uAC00\uD560 \uD544\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4." }) })
|
|
15131
|
+
}
|
|
15132
|
+
) })
|
|
15133
|
+
] }),
|
|
15134
|
+
showReset && /* @__PURE__ */ jsxs(
|
|
15135
|
+
"button",
|
|
15136
|
+
{
|
|
15137
|
+
type: "button",
|
|
15138
|
+
disabled: disabled || !hasValue,
|
|
15139
|
+
onClick: reset,
|
|
15140
|
+
className: cn(
|
|
15141
|
+
"inline-flex shrink-0 cursor-pointer items-center gap-[4px] border-none bg-transparent p-0 text-[12px] font-medium leading-[20px] disabled:cursor-not-allowed",
|
|
15142
|
+
// 부모 flex gap(6px)은 칩 사이 간격 기준이라, 필터 추가 버튼과의 12px 간격을 맞추려면
|
|
15143
|
+
// 부족한 만큼(12px - gap)을 추가로 띄운다. 필터 추가가 없을 땐 divider와 이미 12px이라 불필요.
|
|
15144
|
+
hasAddButton && "ml-[calc(12px-var(--cmp-chipFilter-chip-group))]"
|
|
15145
|
+
),
|
|
15146
|
+
style: {
|
|
15147
|
+
color: disabled || !hasValue ? "var(--cmp-textLink-content-disabled)" : "var(--cmp-textLink-content-default)"
|
|
15148
|
+
},
|
|
15149
|
+
children: [
|
|
15150
|
+
/* @__PURE__ */ jsx(
|
|
15151
|
+
SIcon,
|
|
15152
|
+
{
|
|
15153
|
+
name: "reset",
|
|
15154
|
+
size: 16,
|
|
15155
|
+
color: disabled || !hasValue ? "var(--cmp-textLink-icon-disabled)" : "var(--cmp-textLink-icon-default)"
|
|
15156
|
+
}
|
|
15157
|
+
),
|
|
15158
|
+
/* @__PURE__ */ jsx("span", { children: "\uAC80\uC0C9 \uCD08\uAE30\uD654" })
|
|
15159
|
+
]
|
|
15160
|
+
}
|
|
15161
|
+
)
|
|
15162
|
+
] })
|
|
15163
|
+
] }),
|
|
15164
|
+
/* @__PURE__ */ jsxs(RPopover10.Root, { open: openKey != null, onOpenChange: (next) => !next && setOpenKey(null), children: [
|
|
15165
|
+
/* @__PURE__ */ jsx(
|
|
15166
|
+
RPopover10.Anchor,
|
|
15167
|
+
{
|
|
15168
|
+
virtualRef: {
|
|
15169
|
+
current: openKey ? triggerRefs.current.get(openKey) : null
|
|
15170
|
+
}
|
|
15171
|
+
}
|
|
15172
|
+
),
|
|
15173
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
15174
|
+
RPopover10.Content,
|
|
15175
|
+
{
|
|
15176
|
+
side: "bottom",
|
|
15177
|
+
align: "start",
|
|
15178
|
+
sideOffset: 4,
|
|
15179
|
+
onOpenAutoFocus: (event) => event.preventDefault(),
|
|
15180
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
15181
|
+
style: editorPopoverStyle,
|
|
15182
|
+
children: currentOpenField && /* @__PURE__ */ jsx(
|
|
15183
|
+
EditorPanel,
|
|
15184
|
+
{
|
|
15185
|
+
field: currentOpenField,
|
|
15186
|
+
value: values[currentOpenField.key],
|
|
15187
|
+
disabled: disabled || currentOpenField.disabled,
|
|
15188
|
+
onValueChange: (next) => emitValue(currentOpenField.key, next),
|
|
15189
|
+
onClose: () => setOpenKey(null)
|
|
15190
|
+
}
|
|
15191
|
+
)
|
|
15192
|
+
}
|
|
15193
|
+
) })
|
|
15194
|
+
] })
|
|
15195
|
+
]
|
|
15196
|
+
}
|
|
15197
|
+
);
|
|
15198
|
+
});
|
|
15199
|
+
function Divider({ inset, top } = {}) {
|
|
15200
|
+
return /* @__PURE__ */ jsx(
|
|
15201
|
+
"span",
|
|
15202
|
+
{
|
|
15203
|
+
"aria-hidden": true,
|
|
15204
|
+
className: cn(
|
|
15205
|
+
"inline-flex w-px shrink-0 bg-[var(--chipfilter-bar-border)]",
|
|
15206
|
+
top ? "mt-[2px] self-start" : "my-auto",
|
|
15207
|
+
inset && "mx-[calc(12px-var(--cmp-chipFilter-chip-group))]"
|
|
15208
|
+
),
|
|
15209
|
+
style: { height: "var(--chipfilter-divider-height)" }
|
|
15210
|
+
}
|
|
15211
|
+
);
|
|
15212
|
+
}
|
|
15213
|
+
function GroupTooltip({
|
|
15214
|
+
message,
|
|
15215
|
+
open,
|
|
15216
|
+
children
|
|
15217
|
+
}) {
|
|
15218
|
+
return /* @__PURE__ */ jsx(STooltip2, { trigger: "none", open, placement: "top", tooltipType: "warning", message: [message], children: /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-[var(--cmp-chipFilter-chip-group)]", children }) });
|
|
15219
|
+
}
|
|
15220
|
+
function FilterChip({
|
|
15221
|
+
field,
|
|
15222
|
+
valueText,
|
|
15223
|
+
active,
|
|
15224
|
+
applied,
|
|
15225
|
+
disabled,
|
|
15226
|
+
warning,
|
|
15227
|
+
showClear,
|
|
15228
|
+
showClearWhenEmpty,
|
|
15229
|
+
refCallback,
|
|
15230
|
+
onOpen,
|
|
15231
|
+
onClear
|
|
15232
|
+
}) {
|
|
15233
|
+
const border = disabled ? CHIPFILTER.chipDisabledBorder : warning ? CHIPFILTER.chipWarningBorder : applied ? active ? "var(--color-blue-strong)" : CHIPFILTER.chipAppliedBorder : active ? CHIPFILTER.chipActiveBorder : CHIPFILTER.chipDefaultBorder;
|
|
15234
|
+
const background = disabled ? CHIPFILTER.chipDisabledBg : applied ? CHIPFILTER.chipAppliedBg : CHIPFILTER.chipDefaultBg;
|
|
15235
|
+
const textColor = disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipDefaultText;
|
|
15236
|
+
return /* @__PURE__ */ jsxs(
|
|
15237
|
+
"button",
|
|
15238
|
+
{
|
|
15239
|
+
ref: refCallback,
|
|
15240
|
+
type: "button",
|
|
15241
|
+
disabled,
|
|
15242
|
+
"aria-expanded": active,
|
|
15243
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
15244
|
+
onClick: onOpen,
|
|
15245
|
+
className: "group/chip-filter inline-flex max-w-full shrink-0 cursor-pointer items-center justify-center whitespace-nowrap border border-solid px-[var(--cmp-chipFilter-chip-paddingX)] text-[12px] leading-[20px] outline-none disabled:cursor-not-allowed",
|
|
15246
|
+
style: {
|
|
15247
|
+
minHeight: CHIPFILTER.chipHeight,
|
|
15248
|
+
gap: CHIPFILTER.chipGap,
|
|
15249
|
+
borderRadius: CHIPFILTER.chipRadius,
|
|
15250
|
+
borderColor: border,
|
|
15251
|
+
background,
|
|
15252
|
+
color: textColor
|
|
15253
|
+
},
|
|
15254
|
+
children: [
|
|
15255
|
+
field.required && /* @__PURE__ */ jsx(
|
|
15256
|
+
SIcon,
|
|
15257
|
+
{
|
|
15258
|
+
name: "asterisk",
|
|
15259
|
+
size: 12,
|
|
15260
|
+
color: disabled ? CHIPFILTER.chipDisabledText : "var(--cmp-tag-darkblue-content)"
|
|
15261
|
+
}
|
|
15262
|
+
),
|
|
15263
|
+
applied ? /* @__PURE__ */ jsxs("span", { className: "inline-flex min-w-0 items-center gap-[4px] truncate", children: [
|
|
15264
|
+
/* @__PURE__ */ jsx(
|
|
15265
|
+
"span",
|
|
15266
|
+
{
|
|
15267
|
+
className: "font-bold",
|
|
15268
|
+
style: { color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedLabel },
|
|
15269
|
+
children: field.label
|
|
15270
|
+
}
|
|
15271
|
+
),
|
|
15272
|
+
/* @__PURE__ */ jsx(
|
|
15273
|
+
"span",
|
|
15274
|
+
{
|
|
15275
|
+
style: { color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedLabel },
|
|
15276
|
+
children: ":"
|
|
15277
|
+
}
|
|
15278
|
+
),
|
|
15279
|
+
/* @__PURE__ */ jsx(
|
|
15280
|
+
"span",
|
|
15281
|
+
{
|
|
15282
|
+
className: "min-w-0 truncate font-bold",
|
|
15283
|
+
style: { color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedValue },
|
|
15284
|
+
children: valueText
|
|
15285
|
+
}
|
|
15286
|
+
)
|
|
15287
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
15288
|
+
/* @__PURE__ */ jsx("span", { className: cn("min-w-0 truncate", active && "font-bold"), children: field.label }),
|
|
15289
|
+
/* @__PURE__ */ jsx(
|
|
15290
|
+
SIcon,
|
|
15291
|
+
{
|
|
15292
|
+
name: "caretDown",
|
|
15293
|
+
size: 12,
|
|
15294
|
+
color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipDefaultText
|
|
15295
|
+
}
|
|
15296
|
+
)
|
|
15297
|
+
] }),
|
|
15298
|
+
!disabled && showClear && (applied || showClearWhenEmpty) && /* @__PURE__ */ jsx(
|
|
15299
|
+
"span",
|
|
15300
|
+
{
|
|
15301
|
+
role: "button",
|
|
15302
|
+
tabIndex: 0,
|
|
15303
|
+
"aria-label": `${field.label} \uD544\uD130 \uC9C0\uC6B0\uAE30`,
|
|
15304
|
+
className: "inline-flex size-[16px] items-center justify-center rounded-[var(--cmp-ghostButton-radius-sm)]",
|
|
15305
|
+
onClick: (event) => {
|
|
15306
|
+
event.preventDefault();
|
|
15307
|
+
event.stopPropagation();
|
|
15308
|
+
onClear();
|
|
15309
|
+
},
|
|
15310
|
+
onKeyDown: (event) => {
|
|
15311
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
15312
|
+
event.preventDefault();
|
|
15313
|
+
event.stopPropagation();
|
|
15314
|
+
onClear();
|
|
15315
|
+
},
|
|
15316
|
+
children: /* @__PURE__ */ jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
15317
|
+
}
|
|
15318
|
+
)
|
|
15319
|
+
]
|
|
15320
|
+
}
|
|
15321
|
+
);
|
|
15322
|
+
}
|
|
15323
|
+
function EditorPanel({
|
|
15324
|
+
field,
|
|
15325
|
+
value,
|
|
15326
|
+
disabled,
|
|
15327
|
+
onValueChange,
|
|
15328
|
+
onClose
|
|
15329
|
+
}) {
|
|
15330
|
+
const wrapsInPaddedTop = field.type === "date" || field.type === "period";
|
|
15331
|
+
const isMulti = field.type === "multi";
|
|
15332
|
+
const selectableValues = isMulti ? (field.options ?? []).filter((option) => !option.disabled).map((option) => option.value) : [];
|
|
15333
|
+
const selectedValues = isMulti ? toArrayValue(value) : [];
|
|
15334
|
+
const allSelected = isMulti && selectableValues.length > 0 && selectableValues.every((v) => selectedValues.includes(v));
|
|
15335
|
+
const toggleSelectAll = () => {
|
|
15336
|
+
onValueChange(
|
|
15337
|
+
allSelected ? selectedValues.filter((v) => !selectableValues.includes(v)) : [...selectedValues, ...selectableValues.filter((v) => !selectedValues.includes(v))]
|
|
15338
|
+
);
|
|
15339
|
+
};
|
|
15340
|
+
return /* @__PURE__ */ jsxs(ListBox, { children: [
|
|
15341
|
+
wrapsInPaddedTop ? /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)] px-[var(--cmp-chipFilter-listbox-top-paddingX)] py-[var(--cmp-chipFilter-listbox-top-paddingY)]", children: /* @__PURE__ */ jsx(
|
|
15342
|
+
FilterEditor,
|
|
15343
|
+
{
|
|
15344
|
+
field,
|
|
15345
|
+
value,
|
|
15346
|
+
disabled,
|
|
15347
|
+
onValueChange
|
|
15348
|
+
}
|
|
15349
|
+
) }) : /* @__PURE__ */ jsx(
|
|
15350
|
+
FilterEditor,
|
|
15351
|
+
{
|
|
15352
|
+
field,
|
|
15353
|
+
value,
|
|
15354
|
+
disabled,
|
|
15355
|
+
onValueChange
|
|
15356
|
+
}
|
|
15357
|
+
),
|
|
15358
|
+
/* @__PURE__ */ jsxs(
|
|
15359
|
+
"div",
|
|
15360
|
+
{
|
|
15361
|
+
className: "flex items-center justify-end gap-[var(--cmp-chipFilter-listbox-bottom-gap)] border-t border-solid px-[var(--cmp-chipFilter-listbox-bottom-paddingX)] py-[var(--cmp-chipFilter-listbox-bottom-paddingY)]",
|
|
15362
|
+
style: { borderColor: CHIPFILTER.listboxBorder },
|
|
15363
|
+
children: [
|
|
15364
|
+
isMulti && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
15365
|
+
/* @__PURE__ */ jsx(
|
|
15366
|
+
STextLink,
|
|
15367
|
+
{
|
|
15368
|
+
size: "sm",
|
|
15369
|
+
label: allSelected ? "\uC120\uD0DD \uD574\uC81C" : "\uC804\uCCB4 \uC120\uD0DD",
|
|
15370
|
+
labelClass: "font-bold",
|
|
15371
|
+
disabled,
|
|
15372
|
+
onClick: toggleSelectAll,
|
|
15373
|
+
style: { color: "var(--sys-color-fg-secondary)" }
|
|
15374
|
+
}
|
|
15375
|
+
),
|
|
15376
|
+
/* @__PURE__ */ jsx(
|
|
15377
|
+
"span",
|
|
15378
|
+
{
|
|
15379
|
+
"aria-hidden": true,
|
|
15380
|
+
className: "inline-flex w-px shrink-0",
|
|
15381
|
+
style: {
|
|
15382
|
+
height: CHIPFILTER.listboxBottomDividerHeight,
|
|
15383
|
+
background: CHIPFILTER.listboxBorder
|
|
15384
|
+
}
|
|
15385
|
+
}
|
|
15386
|
+
)
|
|
15387
|
+
] }),
|
|
15388
|
+
/* @__PURE__ */ jsx(
|
|
15389
|
+
STextLink,
|
|
15390
|
+
{
|
|
15391
|
+
size: "sm",
|
|
15392
|
+
label: "\uAC80\uC0C9",
|
|
15393
|
+
labelClass: "font-bold",
|
|
15394
|
+
onClick: onClose,
|
|
15395
|
+
style: { color: CHIPFILTER.chipAppliedValue }
|
|
15396
|
+
}
|
|
15397
|
+
)
|
|
15398
|
+
]
|
|
15399
|
+
}
|
|
15400
|
+
)
|
|
15401
|
+
] });
|
|
15402
|
+
}
|
|
15403
|
+
function FilterEditor({
|
|
15404
|
+
field,
|
|
15405
|
+
value,
|
|
15406
|
+
disabled,
|
|
15407
|
+
onValueChange
|
|
15408
|
+
}) {
|
|
15409
|
+
if (field.type === "period") {
|
|
15410
|
+
return /* @__PURE__ */ jsx(
|
|
15411
|
+
PeriodPresetEditor,
|
|
15412
|
+
{
|
|
15413
|
+
field,
|
|
15414
|
+
value,
|
|
15415
|
+
disabled,
|
|
15416
|
+
onValueChange
|
|
15417
|
+
}
|
|
15418
|
+
);
|
|
15419
|
+
}
|
|
15420
|
+
if (field.type === "date") {
|
|
15421
|
+
return /* @__PURE__ */ jsx(
|
|
15422
|
+
DatePresetEditor,
|
|
15423
|
+
{
|
|
15424
|
+
field,
|
|
15425
|
+
value,
|
|
15426
|
+
disabled,
|
|
15427
|
+
onValueChange
|
|
15428
|
+
}
|
|
15429
|
+
);
|
|
15430
|
+
}
|
|
15431
|
+
if (field.type === "keyword") {
|
|
15432
|
+
return /* @__PURE__ */ jsx(
|
|
15433
|
+
KeywordEditor,
|
|
15434
|
+
{
|
|
15435
|
+
field,
|
|
15436
|
+
value: isKeywordValue(value) ? value : keywordEntries(value),
|
|
15437
|
+
disabled,
|
|
15438
|
+
onValueChange
|
|
15439
|
+
}
|
|
15440
|
+
);
|
|
15441
|
+
}
|
|
15442
|
+
return /* @__PURE__ */ jsx(
|
|
15443
|
+
OptionList,
|
|
15444
|
+
{
|
|
15445
|
+
field,
|
|
15446
|
+
value: field.type === "multi" ? toArrayValue(value) : value,
|
|
15447
|
+
multiple: field.type === "multi",
|
|
15448
|
+
disabled,
|
|
15449
|
+
onValueChange
|
|
15450
|
+
}
|
|
15451
|
+
);
|
|
15452
|
+
}
|
|
15453
|
+
function DatePresetEditor({
|
|
15454
|
+
field,
|
|
15455
|
+
value,
|
|
15456
|
+
disabled,
|
|
15457
|
+
onValueChange
|
|
15458
|
+
}) {
|
|
15459
|
+
const presets = getFieldPresets(field);
|
|
15460
|
+
const [selectedId, setSelectedId] = useState(() => matchPresetId(presets, value));
|
|
15461
|
+
const syncedInitialValueRef = useRef(!isEmptyValue(value));
|
|
15462
|
+
useEffect(() => {
|
|
15463
|
+
if (syncedInitialValueRef.current || isEmptyValue(value)) return;
|
|
15464
|
+
syncedInitialValueRef.current = true;
|
|
15465
|
+
setSelectedId(matchPresetId(presets, value));
|
|
15466
|
+
}, [value, presets]);
|
|
15467
|
+
const selectedPreset = presets.find((preset) => preset.value === selectedId);
|
|
15468
|
+
const selectPreset = (preset) => {
|
|
15469
|
+
setSelectedId(preset.value);
|
|
15470
|
+
if (!preset.custom) onValueChange(preset.resolve ? preset.resolve() : preset.value);
|
|
15471
|
+
};
|
|
15472
|
+
if (field.type === "date" && presets.length === 0) {
|
|
15473
|
+
return /* @__PURE__ */ jsx(
|
|
15474
|
+
SDatePicker,
|
|
15475
|
+
{
|
|
15476
|
+
value: typeof value === "string" ? value : null,
|
|
15477
|
+
onValueChange,
|
|
15478
|
+
selectable: field.selectable,
|
|
15479
|
+
disabled,
|
|
15480
|
+
placeholder: field.placeholder
|
|
15481
|
+
}
|
|
15482
|
+
);
|
|
15483
|
+
}
|
|
15484
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)]", children: [
|
|
15485
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-[8px]", children: presets.map((preset) => /* @__PURE__ */ jsx(
|
|
15486
|
+
SRadio,
|
|
15487
|
+
{
|
|
15488
|
+
val: preset.value,
|
|
15489
|
+
value: selectedId,
|
|
15490
|
+
label: preset.label,
|
|
15491
|
+
disabled,
|
|
15492
|
+
onValueChange: () => selectPreset(preset)
|
|
15493
|
+
},
|
|
15494
|
+
preset.value
|
|
15495
|
+
)) }),
|
|
15496
|
+
selectedPreset?.custom && /* @__PURE__ */ jsx(
|
|
15497
|
+
SDateRangePicker,
|
|
15498
|
+
{
|
|
15499
|
+
value: Array.isArray(value) && value.length === 2 ? value : null,
|
|
15500
|
+
onValueChange,
|
|
15501
|
+
selectable: field.selectable,
|
|
15502
|
+
maxRange: field.maxRange,
|
|
15503
|
+
disabled
|
|
15504
|
+
}
|
|
15505
|
+
)
|
|
15506
|
+
] });
|
|
15507
|
+
}
|
|
15508
|
+
function PeriodPresetEditor({
|
|
15509
|
+
field,
|
|
15510
|
+
value,
|
|
15511
|
+
disabled,
|
|
15512
|
+
onValueChange
|
|
15513
|
+
}) {
|
|
15514
|
+
const presets = getFieldPresets(field);
|
|
15515
|
+
const firstUnit = presets.find((preset) => !preset.custom)?.value ?? "day";
|
|
15516
|
+
const [selectedId, setSelectedId] = useState(() => matchPresetId(presets, value) ?? firstUnit);
|
|
15517
|
+
const periodValue = isPeriodValue(value) ? value : createPeriodValue(selectedId ?? firstUnit);
|
|
15518
|
+
const selectedUnit = selectedId ?? periodValue.unit;
|
|
15519
|
+
useEffect(() => {
|
|
15520
|
+
if (isEmptyValue(value)) return;
|
|
15521
|
+
setSelectedId(matchPresetId(presets, value) ?? firstUnit);
|
|
15522
|
+
}, [firstUnit, presets, value]);
|
|
15523
|
+
const selectPreset = (preset) => {
|
|
15524
|
+
const nextUnit = preset.value;
|
|
15525
|
+
setSelectedId(nextUnit);
|
|
15526
|
+
onValueChange(createPeriodValue(nextUnit));
|
|
15527
|
+
};
|
|
15528
|
+
const updateInputValue = (nextValue) => {
|
|
15529
|
+
onValueChange({ unit: selectedUnit, value: nextValue });
|
|
15530
|
+
};
|
|
15531
|
+
const renderInput = () => {
|
|
15532
|
+
if (selectedUnit === "day") {
|
|
15533
|
+
return /* @__PURE__ */ jsx(
|
|
15534
|
+
SDatePicker,
|
|
15535
|
+
{
|
|
15536
|
+
value: typeof periodValue.value === "string" ? periodValue.value : null,
|
|
15537
|
+
onValueChange: updateInputValue,
|
|
15538
|
+
selectable: field.selectable,
|
|
15539
|
+
disabled,
|
|
15540
|
+
width: "100%"
|
|
15541
|
+
}
|
|
15542
|
+
);
|
|
15543
|
+
}
|
|
15544
|
+
if (selectedUnit === "month") {
|
|
15545
|
+
return /* @__PURE__ */ jsx(
|
|
15546
|
+
SDatePicker,
|
|
15547
|
+
{
|
|
15548
|
+
mode: "month",
|
|
15549
|
+
value: typeof periodValue.value === "string" ? periodValue.value : null,
|
|
15550
|
+
onValueChange: updateInputValue,
|
|
15551
|
+
selectable: field.selectable,
|
|
15552
|
+
disabled,
|
|
15553
|
+
width: "100%"
|
|
15554
|
+
}
|
|
15555
|
+
);
|
|
15556
|
+
}
|
|
15557
|
+
if (selectedUnit === "quarter") {
|
|
15558
|
+
return /* @__PURE__ */ jsx(
|
|
15559
|
+
SSelect2,
|
|
15560
|
+
{
|
|
15561
|
+
value: typeof periodValue.value === "number" ? periodValue.value : 1,
|
|
15562
|
+
onValueChange: updateInputValue,
|
|
15563
|
+
emitValue: true,
|
|
15564
|
+
disabled,
|
|
15565
|
+
width: "100%",
|
|
15566
|
+
options: [
|
|
15567
|
+
{ value: 1, label: "1\uBD84\uAE30" },
|
|
15568
|
+
{ value: 2, label: "2\uBD84\uAE30" },
|
|
15569
|
+
{ value: 3, label: "3\uBD84\uAE30" },
|
|
15570
|
+
{ value: 4, label: "4\uBD84\uAE30" }
|
|
15571
|
+
]
|
|
15572
|
+
}
|
|
15573
|
+
);
|
|
15574
|
+
}
|
|
15575
|
+
if (selectedUnit === "half") {
|
|
15576
|
+
return /* @__PURE__ */ jsx(
|
|
15577
|
+
SSelect2,
|
|
15578
|
+
{
|
|
15579
|
+
value: typeof periodValue.value === "string" ? periodValue.value : "first",
|
|
15580
|
+
onValueChange: updateInputValue,
|
|
15581
|
+
emitValue: true,
|
|
15582
|
+
disabled,
|
|
15583
|
+
width: "100%",
|
|
15584
|
+
options: [
|
|
15585
|
+
{ value: "first", label: "\uC0C1\uBC18\uAE30" },
|
|
15586
|
+
{ value: "second", label: "\uD558\uBC18\uAE30" }
|
|
15587
|
+
]
|
|
15588
|
+
}
|
|
15589
|
+
);
|
|
15590
|
+
}
|
|
15591
|
+
if (selectedUnit === "year") {
|
|
15592
|
+
return /* @__PURE__ */ jsx(
|
|
15593
|
+
SDatePicker,
|
|
15594
|
+
{
|
|
15595
|
+
mode: "year",
|
|
15596
|
+
value: typeof periodValue.value === "string" ? periodValue.value : null,
|
|
15597
|
+
onValueChange: updateInputValue,
|
|
15598
|
+
selectable: field.selectable,
|
|
15599
|
+
disabled,
|
|
15600
|
+
width: "100%"
|
|
15601
|
+
}
|
|
15602
|
+
);
|
|
15603
|
+
}
|
|
15604
|
+
return /* @__PURE__ */ jsx(
|
|
15605
|
+
SDateRangePicker,
|
|
15606
|
+
{
|
|
15607
|
+
value: Array.isArray(periodValue.value) && periodValue.value.length === 2 ? periodValue.value : null,
|
|
15608
|
+
onValueChange: updateInputValue,
|
|
15609
|
+
selectable: field.selectable,
|
|
15610
|
+
maxRange: field.maxRange,
|
|
15611
|
+
disabled,
|
|
15612
|
+
width: "100%"
|
|
15613
|
+
}
|
|
15614
|
+
);
|
|
15615
|
+
};
|
|
15616
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)]", children: [
|
|
15617
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-[8px]", children: presets.map((preset) => /* @__PURE__ */ jsx(
|
|
15618
|
+
SRadio,
|
|
15619
|
+
{
|
|
15620
|
+
val: preset.value,
|
|
15621
|
+
value: selectedId,
|
|
15622
|
+
label: preset.label,
|
|
15623
|
+
disabled,
|
|
15624
|
+
onValueChange: () => selectPreset(preset)
|
|
15625
|
+
},
|
|
15626
|
+
preset.value
|
|
15627
|
+
)) }),
|
|
15628
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "h-px w-full", style: { background: CHIPFILTER.listboxBorder } }),
|
|
15629
|
+
/* @__PURE__ */ jsx("div", { className: "w-full [&>*]:w-full", children: renderInput() })
|
|
15630
|
+
] });
|
|
15631
|
+
}
|
|
15632
|
+
function InlineDatePresetFilter({
|
|
15633
|
+
field,
|
|
15634
|
+
value,
|
|
15635
|
+
disabled,
|
|
15636
|
+
warning,
|
|
15637
|
+
showClear,
|
|
15638
|
+
onValueChange,
|
|
15639
|
+
onClear
|
|
15640
|
+
}) {
|
|
15641
|
+
const presets = (field.presets ?? []).filter((preset) => !preset.custom);
|
|
15642
|
+
const [selectedId, setSelectedId] = useState(() => matchPresetId(presets, value));
|
|
15643
|
+
const syncedInitialValueRef = useRef(!isEmptyValue(value));
|
|
15644
|
+
useEffect(() => {
|
|
15645
|
+
if (syncedInitialValueRef.current || isEmptyValue(value)) return;
|
|
15646
|
+
syncedInitialValueRef.current = true;
|
|
15647
|
+
setSelectedId(matchPresetId(presets, value));
|
|
15648
|
+
}, [value, presets]);
|
|
15649
|
+
const applied = !isEmptyValue(value);
|
|
15650
|
+
const rangeValue = Array.isArray(value) ? value : typeof value === "string" && value !== "" ? [value, value] : null;
|
|
15651
|
+
const [pickerOpen, setPickerOpen] = useState(false);
|
|
15652
|
+
const portalContainer = usePortalContainer();
|
|
15653
|
+
const selectPreset = (id) => {
|
|
15654
|
+
const preset = presets.find((p) => p.value === id);
|
|
15655
|
+
if (!preset) return;
|
|
15656
|
+
setSelectedId(preset.value);
|
|
15657
|
+
onValueChange(preset.resolve ? preset.resolve() : null);
|
|
15658
|
+
};
|
|
15659
|
+
const badge = applied && /* @__PURE__ */ jsxs(
|
|
15660
|
+
"span",
|
|
15661
|
+
{
|
|
15662
|
+
className: "inline-flex shrink-0 items-center gap-[4px] whitespace-nowrap border border-solid px-[var(--cmp-chipFilter-chip-paddingX)] text-[12px] leading-[20px]",
|
|
15663
|
+
style: {
|
|
15664
|
+
minHeight: CHIPFILTER.chipHeight,
|
|
15665
|
+
borderRadius: CHIPFILTER.chipRadius,
|
|
15666
|
+
borderColor: warning ? CHIPFILTER.chipWarningBorder : CHIPFILTER.chipAppliedBorder,
|
|
15667
|
+
background: CHIPFILTER.chipAppliedBg,
|
|
15668
|
+
color: CHIPFILTER.chipAppliedLabel,
|
|
15669
|
+
cursor: rangeValue ? "pointer" : void 0
|
|
15670
|
+
},
|
|
15671
|
+
children: [
|
|
15672
|
+
/* @__PURE__ */ jsxs("span", { className: "font-bold", children: [
|
|
15673
|
+
field.label,
|
|
15674
|
+
":"
|
|
15675
|
+
] }),
|
|
15676
|
+
/* @__PURE__ */ jsx("span", { className: "font-bold", style: { color: CHIPFILTER.chipAppliedValue }, children: displayValue(field, value) }),
|
|
15677
|
+
!disabled && showClear && /* @__PURE__ */ jsx(
|
|
15678
|
+
"span",
|
|
15679
|
+
{
|
|
15680
|
+
role: "button",
|
|
15681
|
+
tabIndex: 0,
|
|
15682
|
+
"aria-label": `${field.label} \uD544\uD130 \uC9C0\uC6B0\uAE30`,
|
|
15683
|
+
className: "inline-flex size-[16px] items-center justify-center rounded-[var(--cmp-ghostButton-radius-sm)]",
|
|
15684
|
+
onClick: (event) => {
|
|
15685
|
+
event.stopPropagation();
|
|
15686
|
+
onClear();
|
|
15687
|
+
},
|
|
15688
|
+
onKeyDown: (event) => {
|
|
15689
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
15690
|
+
event.preventDefault();
|
|
15691
|
+
event.stopPropagation();
|
|
15692
|
+
onClear();
|
|
15693
|
+
},
|
|
15694
|
+
children: /* @__PURE__ */ jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
15695
|
+
}
|
|
15696
|
+
)
|
|
15697
|
+
]
|
|
15698
|
+
}
|
|
15699
|
+
);
|
|
15700
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-[8px]", children: [
|
|
15701
|
+
/* @__PURE__ */ jsx(
|
|
15702
|
+
SRadioButton,
|
|
15703
|
+
{
|
|
15704
|
+
size: "xs",
|
|
15705
|
+
options: presets.map((preset) => ({ value: preset.value, label: preset.label })),
|
|
15706
|
+
value: selectedId,
|
|
15707
|
+
disabled,
|
|
15708
|
+
onValueChange: (next) => selectPreset(String(next))
|
|
15709
|
+
}
|
|
15710
|
+
),
|
|
15711
|
+
applied && (rangeValue ? (
|
|
15712
|
+
// 뱃지 모양은 그대로 두고, 눌렀을 때 캘린더가 열려 기간을 직접 다시 고를 수 있게 한다.
|
|
15713
|
+
// 직접 고르면 프리셋 선택은 해제된다.
|
|
15714
|
+
/* @__PURE__ */ jsxs(RPopover10.Root, { open: pickerOpen, onOpenChange: setPickerOpen, children: [
|
|
15715
|
+
/* @__PURE__ */ jsx(RPopover10.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
15716
|
+
"button",
|
|
15717
|
+
{
|
|
15718
|
+
type: "button",
|
|
15719
|
+
disabled,
|
|
15720
|
+
className: "border-none bg-transparent p-0 outline-none disabled:cursor-not-allowed",
|
|
15721
|
+
children: badge
|
|
15722
|
+
}
|
|
15723
|
+
) }),
|
|
15724
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
15725
|
+
RPopover10.Content,
|
|
15726
|
+
{
|
|
15727
|
+
side: "bottom",
|
|
15728
|
+
align: "start",
|
|
15729
|
+
sideOffset: 4,
|
|
15730
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
15731
|
+
children: /* @__PURE__ */ jsx(
|
|
15732
|
+
RangeCalendar,
|
|
15733
|
+
{
|
|
15734
|
+
value: rangeValue,
|
|
15735
|
+
selectable: field.selectable,
|
|
15736
|
+
maxRange: field.maxRange,
|
|
15737
|
+
onSelect: (range) => {
|
|
15738
|
+
setSelectedId(null);
|
|
15739
|
+
onValueChange(range);
|
|
15740
|
+
setPickerOpen(false);
|
|
15741
|
+
}
|
|
15742
|
+
}
|
|
15743
|
+
)
|
|
15744
|
+
}
|
|
15745
|
+
) })
|
|
15746
|
+
] })
|
|
15747
|
+
) : badge)
|
|
15748
|
+
] });
|
|
15749
|
+
}
|
|
15750
|
+
var MATCH_MODE_OPTIONS = [
|
|
15751
|
+
{ value: "contains", label: "\uD3EC\uD568" },
|
|
15752
|
+
{ value: "exact", label: "\uC77C\uCE58" }
|
|
15753
|
+
];
|
|
15754
|
+
var EXCLUDE_MATCH_MODE_OPTION = {
|
|
15755
|
+
value: "excludes",
|
|
15756
|
+
label: "\uBBF8\uD3EC\uD568"
|
|
15757
|
+
};
|
|
15758
|
+
function KeywordEditor({
|
|
15759
|
+
field,
|
|
15760
|
+
value,
|
|
15761
|
+
disabled,
|
|
15762
|
+
onValueChange
|
|
15763
|
+
}) {
|
|
15764
|
+
const entries3 = keywordEntries(value);
|
|
15765
|
+
const [draft, setDraft] = useState("");
|
|
15766
|
+
const [mode, setMode] = useState(
|
|
15767
|
+
isKeywordValue(value) ? value.mode : "contains"
|
|
15768
|
+
);
|
|
15769
|
+
const emit3 = (nextEntries) => {
|
|
15770
|
+
onValueChange(field.matchModes ? { keywords: nextEntries, mode } : nextEntries);
|
|
15771
|
+
};
|
|
15772
|
+
const addEntry = (raw) => {
|
|
15773
|
+
const next = raw.trim();
|
|
15774
|
+
if (next === "" || entries3.includes(next)) return;
|
|
15775
|
+
emit3([...entries3, next]);
|
|
15776
|
+
setDraft("");
|
|
15777
|
+
};
|
|
15778
|
+
const removeEntry = (entry) => {
|
|
15779
|
+
emit3(entries3.filter((e) => e !== entry));
|
|
15780
|
+
};
|
|
15781
|
+
const onKeyDown = (event) => {
|
|
15782
|
+
if (event.key === "Enter") {
|
|
15783
|
+
if (event.nativeEvent.isComposing) return;
|
|
15784
|
+
event.preventDefault();
|
|
15785
|
+
addEntry(draft);
|
|
15786
|
+
}
|
|
15787
|
+
};
|
|
15788
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
15789
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)] px-[var(--cmp-chipFilter-listbox-top-paddingX)] py-[var(--cmp-chipFilter-listbox-top-paddingY)]", children: [
|
|
15790
|
+
field.matchModes && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
15791
|
+
/* @__PURE__ */ jsx(
|
|
15792
|
+
"span",
|
|
15793
|
+
{
|
|
15794
|
+
className: "shrink-0 whitespace-nowrap text-[12px] font-medium leading-[20px]",
|
|
15795
|
+
style: { color: CHIPFILTER.listboxLabel },
|
|
15796
|
+
children: "\uAC80\uC0C9 \uC870\uAC74 :"
|
|
15797
|
+
}
|
|
15798
|
+
),
|
|
15799
|
+
/* @__PURE__ */ jsx(
|
|
15800
|
+
SRadioButton,
|
|
15801
|
+
{
|
|
15802
|
+
size: "xs",
|
|
15803
|
+
style: { width: 150 },
|
|
15804
|
+
options: field.excludeMode ? [...MATCH_MODE_OPTIONS, EXCLUDE_MATCH_MODE_OPTION] : MATCH_MODE_OPTIONS,
|
|
15805
|
+
value: mode,
|
|
15806
|
+
disabled,
|
|
15807
|
+
onValueChange: (next) => setMode(next)
|
|
15808
|
+
}
|
|
15809
|
+
)
|
|
15810
|
+
] }),
|
|
15811
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-[6px] rounded-[4px] border border-solid border-[color:var(--sys-color-field-border-default)] bg-[var(--sys-color-field-bg-default)] px-[8px] py-[4px] focus-within:border-[color:var(--sys-color-field-border-focus)]", children: [
|
|
15812
|
+
/* @__PURE__ */ jsx(SIcon, { name: "search", size: 16, color: "var(--sys-color-field-icon-default)" }),
|
|
15813
|
+
/* @__PURE__ */ jsx(
|
|
15814
|
+
"input",
|
|
15815
|
+
{
|
|
15816
|
+
value: draft,
|
|
15817
|
+
disabled,
|
|
15818
|
+
placeholder: field.placeholder ?? "\uC785\uB825 \uD6C4 Enter\uB85C \uCD94\uAC00",
|
|
15819
|
+
onChange: (event) => setDraft(event.target.value),
|
|
15820
|
+
onKeyDown,
|
|
15821
|
+
className: "min-w-0 flex-1 border-none bg-transparent text-[12px] leading-[20px] text-[color:var(--sys-color-field-text-default)] outline-none placeholder:text-[color:var(--sys-color-field-text-placeholder)] disabled:cursor-not-allowed"
|
|
15822
|
+
}
|
|
15823
|
+
)
|
|
15824
|
+
] })
|
|
15825
|
+
] }),
|
|
15826
|
+
entries3.length > 0 && /* @__PURE__ */ jsx(
|
|
15827
|
+
"div",
|
|
15828
|
+
{
|
|
15829
|
+
className: "max-h-[220px] overflow-auto border-t border-solid py-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
15830
|
+
style: { borderColor: CHIPFILTER.listboxBorder },
|
|
15831
|
+
children: entries3.map((entry) => /* @__PURE__ */ jsx(
|
|
15832
|
+
KeywordEntryRow,
|
|
15833
|
+
{
|
|
15834
|
+
label: optionLabel(field, entry),
|
|
15835
|
+
disabled,
|
|
15836
|
+
onRemove: () => removeEntry(entry)
|
|
15837
|
+
},
|
|
15838
|
+
entry
|
|
15839
|
+
))
|
|
15840
|
+
}
|
|
15841
|
+
)
|
|
15842
|
+
] });
|
|
15843
|
+
}
|
|
15844
|
+
function KeywordEntryRow({
|
|
15845
|
+
label,
|
|
15846
|
+
disabled,
|
|
15847
|
+
onRemove
|
|
15848
|
+
}) {
|
|
15849
|
+
return /* @__PURE__ */ jsxs(
|
|
15850
|
+
"div",
|
|
15851
|
+
{
|
|
15852
|
+
className: "group flex w-full items-center justify-between gap-[8px] text-[12px] leading-[20px]",
|
|
15853
|
+
style: {
|
|
15854
|
+
paddingTop: CHIPFILTER.itemPaddingY,
|
|
15855
|
+
paddingBottom: CHIPFILTER.itemPaddingY,
|
|
15856
|
+
paddingLeft: CHIPFILTER.itemPaddingLeft,
|
|
15857
|
+
paddingRight: CHIPFILTER.itemPaddingRight,
|
|
15858
|
+
color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.itemTextDefault
|
|
15859
|
+
},
|
|
15860
|
+
children: [
|
|
15861
|
+
/* @__PURE__ */ jsx("span", { className: cn("min-w-0 truncate", !disabled && "group-hover:font-bold"), children: label }),
|
|
15862
|
+
!disabled && /* @__PURE__ */ jsx(
|
|
15863
|
+
"button",
|
|
15864
|
+
{
|
|
15865
|
+
type: "button",
|
|
15866
|
+
"aria-label": `${label} \uC0AD\uC81C`,
|
|
15867
|
+
className: "invisible inline-flex size-[16px] shrink-0 cursor-pointer items-center justify-center group-hover:visible",
|
|
15868
|
+
onClick: onRemove,
|
|
15869
|
+
children: /* @__PURE__ */ jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
15870
|
+
}
|
|
15871
|
+
)
|
|
15872
|
+
]
|
|
15873
|
+
}
|
|
15874
|
+
);
|
|
15875
|
+
}
|
|
15876
|
+
var OPTION_SEARCH_THRESHOLD = 11;
|
|
15877
|
+
function OptionList({
|
|
15878
|
+
field,
|
|
15879
|
+
value,
|
|
15880
|
+
multiple,
|
|
15881
|
+
disabled,
|
|
15882
|
+
onValueChange
|
|
15883
|
+
}) {
|
|
15884
|
+
const selected = multiple ? toArrayValue(value) : [];
|
|
15885
|
+
const singleValue = !multiple && (typeof value === "string" || typeof value === "number") ? value : null;
|
|
15886
|
+
const [search, setSearch] = useState("");
|
|
15887
|
+
const options = field.options ?? [];
|
|
15888
|
+
const showSearch = options.length >= OPTION_SEARCH_THRESHOLD;
|
|
15889
|
+
const filteredOptions = useMemo(() => {
|
|
15890
|
+
if (!showSearch || search.trim() === "") return options;
|
|
15891
|
+
const query = search.trim().toLowerCase();
|
|
15892
|
+
return options.filter((option) => option.label.toLowerCase().includes(query));
|
|
15893
|
+
}, [options, search, showSearch]);
|
|
15894
|
+
if (options.length === 0) return /* @__PURE__ */ jsx(EmptyItem, { children: "\uD45C\uC2DC\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." });
|
|
15895
|
+
return /* @__PURE__ */ jsxs(
|
|
15896
|
+
"div",
|
|
15897
|
+
{
|
|
15898
|
+
className: cn(
|
|
15899
|
+
"max-h-[240px] overflow-auto",
|
|
15900
|
+
!showSearch && "pt-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
15901
|
+
"pb-[var(--cmp-chipFilter-listbox-list-paddingY)]"
|
|
15902
|
+
),
|
|
15903
|
+
children: [
|
|
15904
|
+
showSearch && /* @__PURE__ */ jsx(
|
|
15905
|
+
"div",
|
|
15906
|
+
{
|
|
15907
|
+
className: "sticky top-0 z-[1] border-b border-solid px-[8px] pb-[4px] pt-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
15908
|
+
style: { background: CHIPFILTER.listboxBg, borderColor: CHIPFILTER.listboxBorder },
|
|
15909
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-[6px] rounded-[4px] border border-solid border-[color:var(--sys-color-field-border-default)] bg-[var(--sys-color-field-bg-default)] px-[8px] py-[4px] focus-within:border-[color:var(--sys-color-field-border-focus)]", children: [
|
|
15910
|
+
/* @__PURE__ */ jsx(SIcon, { name: "search", size: 16, color: "var(--sys-color-field-icon-default)" }),
|
|
15911
|
+
/* @__PURE__ */ jsx(
|
|
15912
|
+
"input",
|
|
15913
|
+
{
|
|
15914
|
+
value: search,
|
|
15915
|
+
disabled,
|
|
15916
|
+
placeholder: "\uAC80\uC0C9",
|
|
15917
|
+
onChange: (event) => setSearch(event.target.value),
|
|
15918
|
+
className: "min-w-0 flex-1 border-none bg-transparent text-[12px] leading-[20px] text-[color:var(--sys-color-field-text-default)] outline-none placeholder:text-[color:var(--sys-color-field-text-placeholder)] disabled:cursor-not-allowed"
|
|
15919
|
+
}
|
|
15920
|
+
),
|
|
15921
|
+
search !== "" && !disabled && /* @__PURE__ */ jsx(
|
|
15922
|
+
SGhostButton,
|
|
15923
|
+
{
|
|
15924
|
+
icon: "close",
|
|
15925
|
+
size: "xxs",
|
|
15926
|
+
ariaLabel: "\uAC80\uC0C9\uC5B4 \uC9C0\uC6B0\uAE30",
|
|
15927
|
+
className: "flex-shrink-0",
|
|
15928
|
+
onClick: () => setSearch("")
|
|
15929
|
+
}
|
|
15930
|
+
)
|
|
15931
|
+
] })
|
|
15932
|
+
}
|
|
15933
|
+
),
|
|
15934
|
+
showSearch && filteredOptions.length === 0 && /* @__PURE__ */ jsx(EmptyItem, { children: "\uAC80\uC0C9 \uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4." }),
|
|
15935
|
+
filteredOptions.map((option) => {
|
|
15936
|
+
const checked = multiple ? selected.includes(option.value) : singleValue === option.value;
|
|
15937
|
+
return /* @__PURE__ */ jsxs(
|
|
15938
|
+
MenuItem,
|
|
15939
|
+
{
|
|
15940
|
+
selected: checked,
|
|
15941
|
+
disabled: disabled || option.disabled,
|
|
15942
|
+
multi: multiple,
|
|
15943
|
+
onClick: () => {
|
|
15944
|
+
if (multiple) {
|
|
15945
|
+
const next = checked ? selected.filter((v) => v !== option.value) : [...selected, option.value];
|
|
15946
|
+
onValueChange(next);
|
|
15947
|
+
} else {
|
|
15948
|
+
onValueChange(option.value);
|
|
15949
|
+
}
|
|
15950
|
+
},
|
|
15951
|
+
children: [
|
|
15952
|
+
multiple && /* @__PURE__ */ jsx(OptionCheckbox, { checked }),
|
|
15953
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: option.label })
|
|
15954
|
+
]
|
|
15955
|
+
},
|
|
15956
|
+
String(option.value)
|
|
15957
|
+
);
|
|
15958
|
+
})
|
|
15959
|
+
]
|
|
15960
|
+
}
|
|
15961
|
+
);
|
|
15962
|
+
}
|
|
15963
|
+
function OptionCheckbox({ checked }) {
|
|
15964
|
+
return /* @__PURE__ */ jsx(
|
|
15965
|
+
"span",
|
|
15966
|
+
{
|
|
15967
|
+
className: cn(
|
|
15968
|
+
"inline-flex size-[16px] shrink-0 items-center justify-center rounded-[2px] border border-solid",
|
|
15969
|
+
checked ? "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)]"
|
|
15970
|
+
),
|
|
15971
|
+
children: checked && /* @__PURE__ */ jsx(SIcon, { name: "checkboxCheck", size: 12, color: "var(--cmp-checkbox-checked-icon-default)" })
|
|
15972
|
+
}
|
|
15973
|
+
);
|
|
15974
|
+
}
|
|
15975
|
+
function ListBox({ children }) {
|
|
15976
|
+
return /* @__PURE__ */ jsx(
|
|
15977
|
+
"div",
|
|
15978
|
+
{
|
|
15979
|
+
className: "overflow-hidden border border-solid shadow-[var(--shadow-overlay)]",
|
|
15980
|
+
style: {
|
|
15981
|
+
borderRadius: CHIPFILTER.listboxRadius,
|
|
15982
|
+
background: CHIPFILTER.listboxBg,
|
|
15983
|
+
borderColor: CHIPFILTER.listboxBorder
|
|
15984
|
+
},
|
|
15985
|
+
children
|
|
15986
|
+
}
|
|
15987
|
+
);
|
|
15988
|
+
}
|
|
15989
|
+
function MenuItem({
|
|
15990
|
+
children,
|
|
15991
|
+
selected,
|
|
15992
|
+
disabled,
|
|
15993
|
+
multi,
|
|
15994
|
+
onMouseEnter,
|
|
15995
|
+
onClick
|
|
15996
|
+
}) {
|
|
15997
|
+
return /* @__PURE__ */ jsx(
|
|
15998
|
+
"button",
|
|
15999
|
+
{
|
|
16000
|
+
type: "button",
|
|
16001
|
+
disabled,
|
|
16002
|
+
onMouseEnter,
|
|
16003
|
+
onClick,
|
|
16004
|
+
className: cn(
|
|
16005
|
+
"flex w-full min-w-0 cursor-pointer items-center gap-[8px] border-none bg-transparent text-left text-[12px] leading-[20px] outline-none disabled:cursor-not-allowed",
|
|
16006
|
+
selected ? "font-bold" : "font-normal",
|
|
16007
|
+
!disabled && "hover:font-bold"
|
|
16008
|
+
),
|
|
16009
|
+
style: {
|
|
16010
|
+
paddingTop: CHIPFILTER.itemPaddingY,
|
|
16011
|
+
paddingBottom: CHIPFILTER.itemPaddingY,
|
|
16012
|
+
paddingLeft: multi ? CHIPFILTER.itemMultiPaddingX : CHIPFILTER.itemPaddingLeft,
|
|
16013
|
+
paddingRight: multi ? CHIPFILTER.itemMultiPaddingX : CHIPFILTER.itemPaddingRight,
|
|
16014
|
+
color: disabled ? CHIPFILTER.chipDisabledText : selected ? CHIPFILTER.itemTextSelected : CHIPFILTER.itemTextDefault
|
|
16015
|
+
},
|
|
16016
|
+
children
|
|
16017
|
+
}
|
|
16018
|
+
);
|
|
16019
|
+
}
|
|
16020
|
+
function EmptyItem({ children }) {
|
|
16021
|
+
return /* @__PURE__ */ jsx(
|
|
16022
|
+
"div",
|
|
16023
|
+
{
|
|
16024
|
+
className: "text-[12px] leading-[20px]",
|
|
16025
|
+
style: {
|
|
16026
|
+
paddingTop: CHIPFILTER.itemPaddingY,
|
|
16027
|
+
paddingBottom: CHIPFILTER.itemPaddingY,
|
|
16028
|
+
paddingLeft: CHIPFILTER.itemPaddingLeft,
|
|
16029
|
+
paddingRight: CHIPFILTER.itemPaddingRight,
|
|
16030
|
+
color: CHIPFILTER.chipDisabledText
|
|
16031
|
+
},
|
|
16032
|
+
children
|
|
16033
|
+
}
|
|
16034
|
+
);
|
|
16035
|
+
}
|
|
16036
|
+
var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
|
|
13473
16037
|
values = [],
|
|
13474
16038
|
onValueChange,
|
|
13475
16039
|
onInput,
|
|
@@ -13907,7 +16471,7 @@ var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
|
|
|
13907
16471
|
}
|
|
13908
16472
|
);
|
|
13909
16473
|
});
|
|
13910
|
-
var
|
|
16474
|
+
var FONT3 = {
|
|
13911
16475
|
sm: {
|
|
13912
16476
|
fontSize: 12,
|
|
13913
16477
|
paddingX: "var(--cmp-textinput-sm-paddingX)",
|
|
@@ -13955,7 +16519,7 @@ var SBarcodeInput = /* @__PURE__ */ forwardRef(
|
|
|
13955
16519
|
className,
|
|
13956
16520
|
style
|
|
13957
16521
|
}, ref) {
|
|
13958
|
-
const f =
|
|
16522
|
+
const f = FONT3[size];
|
|
13959
16523
|
const [ruleError, setRuleError] = useState("");
|
|
13960
16524
|
const hasValue = value !== void 0 && value !== null && String(value) !== "";
|
|
13961
16525
|
useFormField({
|
|
@@ -13969,6 +16533,10 @@ var SBarcodeInput = /* @__PURE__ */ forwardRef(
|
|
|
13969
16533
|
});
|
|
13970
16534
|
const resolvedError = error || ruleError !== "";
|
|
13971
16535
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
16536
|
+
const valueTooltip = useTruncatedValueTooltip({
|
|
16537
|
+
enabled: readOnly && !disabled,
|
|
16538
|
+
text: String(value ?? "")
|
|
16539
|
+
});
|
|
13972
16540
|
return /* @__PURE__ */ jsx(
|
|
13973
16541
|
SField,
|
|
13974
16542
|
{
|
|
@@ -14005,7 +16573,7 @@ var SBarcodeInput = /* @__PURE__ */ forwardRef(
|
|
|
14005
16573
|
/* @__PURE__ */ jsx(
|
|
14006
16574
|
"input",
|
|
14007
16575
|
{
|
|
14008
|
-
ref,
|
|
16576
|
+
ref: mergeRefs(ref, valueTooltip.valueRef),
|
|
14009
16577
|
name,
|
|
14010
16578
|
type: "text",
|
|
14011
16579
|
value: value ?? "",
|
|
@@ -14031,9 +16599,12 @@ var SBarcodeInput = /* @__PURE__ */ forwardRef(
|
|
|
14031
16599
|
fontSize: f.fontSize,
|
|
14032
16600
|
color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--cmp-textinput-text-default)",
|
|
14033
16601
|
...inputStyle
|
|
14034
|
-
}
|
|
16602
|
+
},
|
|
16603
|
+
onMouseEnter: valueTooltip.onMouseEnter,
|
|
16604
|
+
onMouseLeave: valueTooltip.onMouseLeave
|
|
14035
16605
|
}
|
|
14036
16606
|
),
|
|
16607
|
+
valueTooltip.tooltip,
|
|
14037
16608
|
suffix,
|
|
14038
16609
|
clearable && hasValue && !disabled && /* @__PURE__ */ jsx(
|
|
14039
16610
|
SGhostButton,
|
|
@@ -14069,7 +16640,9 @@ var TIMEPICKER_SIZE_CONFIG = {
|
|
|
14069
16640
|
fontSize: 12,
|
|
14070
16641
|
lineHeight: 20,
|
|
14071
16642
|
minWidth: 80,
|
|
14072
|
-
fieldMinWidth: 128
|
|
16643
|
+
fieldMinWidth: 128,
|
|
16644
|
+
// 상한 등급 md
|
|
16645
|
+
fieldMaxWidth: 160
|
|
14073
16646
|
},
|
|
14074
16647
|
md: {
|
|
14075
16648
|
height: V3("md-height"),
|
|
@@ -14081,7 +16654,9 @@ var TIMEPICKER_SIZE_CONFIG = {
|
|
|
14081
16654
|
fontSize: 14,
|
|
14082
16655
|
lineHeight: 24,
|
|
14083
16656
|
minWidth: 96,
|
|
14084
|
-
fieldMinWidth: 160
|
|
16657
|
+
fieldMinWidth: 160,
|
|
16658
|
+
// 상한 등급 lg
|
|
16659
|
+
fieldMaxWidth: 240
|
|
14085
16660
|
}
|
|
14086
16661
|
};
|
|
14087
16662
|
function clampTimePart(value, min, max) {
|
|
@@ -14192,7 +16767,7 @@ function TimeSelector({
|
|
|
14192
16767
|
const renderColumn = (type) => {
|
|
14193
16768
|
const isHour = type === "hour";
|
|
14194
16769
|
const val = isHour ? displayHour : minute;
|
|
14195
|
-
const
|
|
16770
|
+
const displayValue2 = editingPart === type ? inputDraft[type] ?? "" : String(val).padStart(2, "0");
|
|
14196
16771
|
return /* @__PURE__ */ jsxs(
|
|
14197
16772
|
"div",
|
|
14198
16773
|
{
|
|
@@ -14213,7 +16788,7 @@ function TimeSelector({
|
|
|
14213
16788
|
{
|
|
14214
16789
|
"aria-label": isHour ? "\uC2DC" : "\uBD84",
|
|
14215
16790
|
inputMode: "numeric",
|
|
14216
|
-
value:
|
|
16791
|
+
value: displayValue2,
|
|
14217
16792
|
placeholder: "-",
|
|
14218
16793
|
onFocus: () => beginEdit(type, val),
|
|
14219
16794
|
onBlur: () => endEdit(type),
|
|
@@ -14405,11 +16980,12 @@ function STimePicker({
|
|
|
14405
16980
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
14406
16981
|
width,
|
|
14407
16982
|
minWidth: dims.fieldMinWidth,
|
|
16983
|
+
maxWidth: dims.fieldMaxWidth,
|
|
14408
16984
|
disabled,
|
|
14409
16985
|
className,
|
|
14410
16986
|
style,
|
|
14411
|
-
children: /* @__PURE__ */ jsxs(
|
|
14412
|
-
/* @__PURE__ */ jsx(
|
|
16987
|
+
children: /* @__PURE__ */ jsxs(RPopover10.Root, { open, onOpenChange: commitOpen, children: [
|
|
16988
|
+
/* @__PURE__ */ jsx(RPopover10.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
14413
16989
|
"div",
|
|
14414
16990
|
{
|
|
14415
16991
|
ref: triggerRef,
|
|
@@ -14469,14 +17045,17 @@ function STimePicker({
|
|
|
14469
17045
|
]
|
|
14470
17046
|
}
|
|
14471
17047
|
) }),
|
|
14472
|
-
/* @__PURE__ */ jsx(
|
|
14473
|
-
|
|
17048
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
17049
|
+
RPopover10.Content,
|
|
14474
17050
|
{
|
|
14475
17051
|
side: "bottom",
|
|
14476
17052
|
align: "start",
|
|
14477
17053
|
sideOffset: 4,
|
|
14478
17054
|
alignOffset: popoverAlignOffset,
|
|
14479
|
-
className: cn(
|
|
17055
|
+
className: cn(
|
|
17056
|
+
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
17057
|
+
FLOATING_SLIDE_ANIM
|
|
17058
|
+
),
|
|
14480
17059
|
children: /* @__PURE__ */ jsx(
|
|
14481
17060
|
TimeSelector,
|
|
14482
17061
|
{
|
|
@@ -14518,6 +17097,10 @@ var MIDDAY_FIELD_MIN_WIDTH = {
|
|
|
14518
17097
|
sm: 178,
|
|
14519
17098
|
md: 216
|
|
14520
17099
|
};
|
|
17100
|
+
var MIDDAY_FIELD_MAX_WIDTH = {
|
|
17101
|
+
sm: 240,
|
|
17102
|
+
md: 240
|
|
17103
|
+
};
|
|
14521
17104
|
function RangeTimeSelector({
|
|
14522
17105
|
value,
|
|
14523
17106
|
useMeridiem,
|
|
@@ -14635,7 +17218,7 @@ function RangeTimeSelector({
|
|
|
14635
17218
|
const { minute } = getParts(side);
|
|
14636
17219
|
const val = isHour ? getDisplayHour(side) : minute;
|
|
14637
17220
|
const currentEditingKey = getEditingKey(side, kind);
|
|
14638
|
-
const
|
|
17221
|
+
const displayValue2 = editingKey === currentEditingKey ? inputDraft[currentEditingKey] ?? "" : String(val).padStart(2, "0");
|
|
14639
17222
|
return /* @__PURE__ */ jsxs(
|
|
14640
17223
|
"div",
|
|
14641
17224
|
{
|
|
@@ -14656,7 +17239,7 @@ function RangeTimeSelector({
|
|
|
14656
17239
|
{
|
|
14657
17240
|
"aria-label": `${side === "start" ? "\uC2DC\uC791" : "\uC885\uB8CC"} ${isHour ? "\uC2DC" : "\uBD84"}`,
|
|
14658
17241
|
inputMode: "numeric",
|
|
14659
|
-
value:
|
|
17242
|
+
value: displayValue2,
|
|
14660
17243
|
placeholder: "-",
|
|
14661
17244
|
onFocus: () => beginEdit(side, kind, val),
|
|
14662
17245
|
onBlur: () => endEdit(side, kind),
|
|
@@ -14864,11 +17447,12 @@ function STimeRangePicker({
|
|
|
14864
17447
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
14865
17448
|
width,
|
|
14866
17449
|
minWidth: effectiveUseMeridiem ? MIDDAY_FIELD_MIN_WIDTH[size] : dims.fieldMinWidth,
|
|
17450
|
+
maxWidth: effectiveUseMeridiem ? MIDDAY_FIELD_MAX_WIDTH[size] : dims.fieldMaxWidth,
|
|
14867
17451
|
disabled,
|
|
14868
17452
|
className,
|
|
14869
17453
|
style,
|
|
14870
|
-
children: /* @__PURE__ */ jsxs(
|
|
14871
|
-
/* @__PURE__ */ jsx(
|
|
17454
|
+
children: /* @__PURE__ */ jsxs(RPopover10.Root, { open, onOpenChange: commitOpen, children: [
|
|
17455
|
+
/* @__PURE__ */ jsx(RPopover10.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
14872
17456
|
"div",
|
|
14873
17457
|
{
|
|
14874
17458
|
ref: triggerRef,
|
|
@@ -14928,14 +17512,17 @@ function STimeRangePicker({
|
|
|
14928
17512
|
]
|
|
14929
17513
|
}
|
|
14930
17514
|
) }),
|
|
14931
|
-
/* @__PURE__ */ jsx(
|
|
14932
|
-
|
|
17515
|
+
/* @__PURE__ */ jsx(RPopover10.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
17516
|
+
RPopover10.Content,
|
|
14933
17517
|
{
|
|
14934
17518
|
side: "bottom",
|
|
14935
17519
|
align: "start",
|
|
14936
17520
|
sideOffset: 4,
|
|
14937
17521
|
alignOffset: popoverAlignOffset,
|
|
14938
|
-
className: cn(
|
|
17522
|
+
className: cn(
|
|
17523
|
+
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
17524
|
+
FLOATING_SLIDE_ANIM
|
|
17525
|
+
),
|
|
14939
17526
|
children: /* @__PURE__ */ jsx(
|
|
14940
17527
|
RangeTimeSelector,
|
|
14941
17528
|
{
|
|
@@ -14953,6 +17540,6 @@ function STimeRangePicker({
|
|
|
14953
17540
|
);
|
|
14954
17541
|
}
|
|
14955
17542
|
|
|
14956
|
-
export { BADGE_COLORS, BUTTON_COLORS, BUTTON_SIZES, COLOR_KEYS, GNB_COLORS, GNB_COMMON, GNB_FOLD_MS, GNB_FULL_LOGO_WIDTH, GNB_HEADER, GNB_MENU, GNB_MENU_WIDTH, GNB_RAIL, GNB_RAIL_WIDTH, ICONS, PAGE_BACKGROUNDS, SActionModal, SBadge, SBarcodeInput, SButton, SCROLL_AREA_AXES, SCalendar, SCallout, SCard, SCheckbox, SChip2 as SChip, SChipInput, SCircleProgress, SConfirmModal, SDatePicker, SDateRangePicker, SDivider, SDraggableGroup, SDraggableItem2 as SDraggableItem, SDraggableList, SDraggableProvider, SDrawer, SDropdownButton2 as SDropdownButton, SExpansionItem, SExpansionList2 as SExpansionList, SField, SFilePicker, SForm, SGhostButton, SGnb, SGuide, SIcon, SInput, SKeyValueTable, SLAYOUT_MIN_WIDTH, SLayout, SLayoutContext, SLinearProgress, SList2 as SList, SListItem2 as SListItem, SLoadingContainer, SLoadingModal, SLoadingViewport, SModal, SModalOutlet, SNumberInput, SPage, SPagination, SPopover, SPopup, SPortal, SRadio, SRadioButton, SRadioGroup, SSPLITTER_UNITS, SScrollArea, SSectionHeaderCard2 as SSectionHeaderCard, SSelect2 as SSelect, SSplitter2 as SSplitter, SStepper, SSwitch, STEPPER_SIZES, STable, STableBar, STabs, STag, STextLink, STextarea, STimePicker, STimeRangePicker, SToast, SToastContainer, SToggle, STooltip2 as STooltip, STree2 as STree, STreeItem2 as STreeItem, TAG_COLORS, TAG_SHAPES, TAG_SIZES, TIMEPICKER_SIZES, TIMEPICKER_SIZE_CONFIG, buttonPreset, cn, findGnbAncestors, findGnbRailValue, isColorKey, loading, resolveColor, useSLayout };
|
|
17543
|
+
export { BADGE_COLORS, BUTTON_COLORS, BUTTON_SIZES, COLOR_KEYS, GNB_COLORS, GNB_COMMON, GNB_FOLD_MS, GNB_FULL_LOGO_WIDTH, GNB_HEADER, GNB_MENU, GNB_MENU_WIDTH, GNB_RAIL, GNB_RAIL_WIDTH, ICONS, IMAGE_FITS, PAGE_BACKGROUNDS, PAGE_CONTENT_HEIGHTS, RangeCalendar, SActionModal, SBadge, SBarcodeInput, SButton, SCROLL_AREA_AXES, SCalendar, SCallout, SCard, SCheckbox, SChip2 as SChip, SChipFilter, SChipInput, SCircleProgress, SConfirmModal, SDatePicker, SDatePickerMonthListbox, SDatePickerYearListbox, SDateRangePicker, SDivider, SDraggableGroup, SDraggableItem2 as SDraggableItem, SDraggableList, SDraggableProvider, SDrawer, SDropdownButton2 as SDropdownButton, SExpansionItem, SExpansionList2 as SExpansionList, SField, SFilePicker, SForm, SGhostButton, SGnb, SGuide, SIcon, SImage, SInput, SKeyValueTable, SLAYOUT_MIN_WIDTH, SLayout, SLayoutContext, SLinearProgress, SList2 as SList, SListItem2 as SListItem, SLoadingContainer, SLoadingModal, SLoadingViewport, SModal, SModalOutlet, SNumberInput, SPage, SPagination, SPopover, SPopup, SPortal, SRadio, SRadioButton, SRadioGroup, SSPLITTER_UNITS, SScrollArea, SSearchInput, SSectionHeaderCard2 as SSectionHeaderCard, SSelect2 as SSelect, SSplitter2 as SSplitter, SStepper, SSwitch, STEPPER_SIZES, STable, STableBar, STabs, STag, STextLink, STextarea, STimePicker, STimeRangePicker, SToast, SToastContainer, SToggle, STooltip2 as STooltip, STree2 as STree, STreeItem2 as STreeItem, TAG_COLORS, TAG_SHAPES, TAG_SIZES, TIMEPICKER_SIZES, TIMEPICKER_SIZE_CONFIG, buttonPreset, cn, findGnbAncestors, findGnbRailValue, isColorKey, loading, resolveColor, useSLayout };
|
|
14957
17544
|
//# sourceMappingURL=index.js.map
|
|
14958
17545
|
//# sourceMappingURL=index.js.map
|