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.cjs
CHANGED
|
@@ -7,7 +7,7 @@ var react = require('react');
|
|
|
7
7
|
var jsxRuntime = require('react/jsx-runtime');
|
|
8
8
|
var reactDom = require('react-dom');
|
|
9
9
|
var RCheckbox = require('@radix-ui/react-checkbox');
|
|
10
|
-
var
|
|
10
|
+
var RPopover10 = require('@radix-ui/react-popover');
|
|
11
11
|
var client = require('react-dom/client');
|
|
12
12
|
var RTooltip = require('@radix-ui/react-tooltip');
|
|
13
13
|
var RDropdown = require('@radix-ui/react-dropdown-menu');
|
|
@@ -34,7 +34,7 @@ function _interopNamespace(e) {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
var RCheckbox__namespace = /*#__PURE__*/_interopNamespace(RCheckbox);
|
|
37
|
-
var
|
|
37
|
+
var RPopover10__namespace = /*#__PURE__*/_interopNamespace(RPopover10);
|
|
38
38
|
var RTooltip__namespace = /*#__PURE__*/_interopNamespace(RTooltip);
|
|
39
39
|
var RDropdown__namespace = /*#__PURE__*/_interopNamespace(RDropdown);
|
|
40
40
|
var RSwitch__namespace = /*#__PURE__*/_interopNamespace(RSwitch);
|
|
@@ -2593,6 +2593,27 @@ var Icon_sidebar = (p) => {
|
|
|
2593
2593
|
}
|
|
2594
2594
|
);
|
|
2595
2595
|
};
|
|
2596
|
+
var Icon_star = (p) => {
|
|
2597
|
+
const { size = 24, ...rest } = p;
|
|
2598
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2599
|
+
"svg",
|
|
2600
|
+
{
|
|
2601
|
+
width: size,
|
|
2602
|
+
height: size,
|
|
2603
|
+
viewBox: "0 0 24 24",
|
|
2604
|
+
fill: "none",
|
|
2605
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2606
|
+
...rest,
|
|
2607
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2608
|
+
"path",
|
|
2609
|
+
{
|
|
2610
|
+
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",
|
|
2611
|
+
fill: "currentColor"
|
|
2612
|
+
}
|
|
2613
|
+
)
|
|
2614
|
+
}
|
|
2615
|
+
);
|
|
2616
|
+
};
|
|
2596
2617
|
var Icon_store = (p) => {
|
|
2597
2618
|
const { size = 24, ...rest } = p;
|
|
2598
2619
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -3087,6 +3108,7 @@ var ICONS = {
|
|
|
3087
3108
|
settingOutline: Icon_settingOutline,
|
|
3088
3109
|
shield: Icon_shield,
|
|
3089
3110
|
sidebar: Icon_sidebar,
|
|
3111
|
+
star: Icon_star,
|
|
3090
3112
|
store: Icon_store,
|
|
3091
3113
|
synchronize: Icon_synchronize,
|
|
3092
3114
|
thumbsDown: Icon_thumbsDown,
|
|
@@ -3119,6 +3141,209 @@ var SIcon = /* @__PURE__ */ react.forwardRef(function SIcon2({ name, size = 24,
|
|
|
3119
3141
|
}
|
|
3120
3142
|
);
|
|
3121
3143
|
});
|
|
3144
|
+
var VIEWBOX = 80;
|
|
3145
|
+
var RADIUS = 34;
|
|
3146
|
+
var STROKE = 12;
|
|
3147
|
+
var CIRCUMFERENCE = 2 * Math.PI * RADIUS;
|
|
3148
|
+
var COLOR_MAP = {
|
|
3149
|
+
primary: { arc: "var(--cmp-progress-color-active)", track: "var(--cmp-progress-color-track)" },
|
|
3150
|
+
// inverse: 어두운 배경용 — arc 흰색, track 은 흰색 40%(회색 링)
|
|
3151
|
+
inverse: { arc: "var(--color-white)", track: "rgba(255,255,255,0.4)" },
|
|
3152
|
+
error: { arc: "var(--color-red-75)", track: "var(--cmp-progress-color-track)" },
|
|
3153
|
+
complete: { arc: "#01BB4B", track: "var(--cmp-progress-color-track)" },
|
|
3154
|
+
// neutral: 콘텐츠가 아직 없는 자리를 채우는 용도 — arc 도 회색이라 진행률보다 "대기"로 읽힌다
|
|
3155
|
+
neutral: { arc: "var(--color-grey-35)", track: "var(--cmp-progress-color-track)" }
|
|
3156
|
+
};
|
|
3157
|
+
var DEFAULT_SIZE = 80;
|
|
3158
|
+
var clamp = (v) => Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;
|
|
3159
|
+
var SCircleProgress = /* @__PURE__ */ react.forwardRef(
|
|
3160
|
+
function SCircleProgress2({
|
|
3161
|
+
value = 0,
|
|
3162
|
+
type = "primary",
|
|
3163
|
+
indeterminate = false,
|
|
3164
|
+
size = DEFAULT_SIZE,
|
|
3165
|
+
label,
|
|
3166
|
+
innerValue = false,
|
|
3167
|
+
className,
|
|
3168
|
+
style
|
|
3169
|
+
}, ref) {
|
|
3170
|
+
const v = clamp(value);
|
|
3171
|
+
const dimension = typeof size === "number" ? `${size}px` : size;
|
|
3172
|
+
const colors = COLOR_MAP[type];
|
|
3173
|
+
const c = VIEWBOX / 2;
|
|
3174
|
+
const percentColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : colors.arc;
|
|
3175
|
+
const filled = v / 100 * CIRCUMFERENCE;
|
|
3176
|
+
const showPercent = !indeterminate;
|
|
3177
|
+
const percentNode = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3178
|
+
"span",
|
|
3179
|
+
{
|
|
3180
|
+
className: cn(
|
|
3181
|
+
"text-center text-[16px] font-bold",
|
|
3182
|
+
innerValue ? (
|
|
3183
|
+
// leading-[normal]: 26px leading 은 폰트 content(19px) 위아래로 홀수(7px)만큼 남아
|
|
3184
|
+
// 3px/4px 로 쪼개지고 글자가 링 중심보다 위로 뜬다. (leading-normal 은 1.5 라 동일 문제)
|
|
3185
|
+
"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 leading-[normal]"
|
|
3186
|
+
) : "leading-[26px]"
|
|
3187
|
+
),
|
|
3188
|
+
style: { color: percentColor },
|
|
3189
|
+
children: [
|
|
3190
|
+
Math.round(v),
|
|
3191
|
+
"%"
|
|
3192
|
+
]
|
|
3193
|
+
}
|
|
3194
|
+
);
|
|
3195
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3196
|
+
"div",
|
|
3197
|
+
{
|
|
3198
|
+
ref,
|
|
3199
|
+
className: cn(
|
|
3200
|
+
"inline-flex flex-col items-center gap-[var(--cmp-progress-circular-gap)]",
|
|
3201
|
+
className
|
|
3202
|
+
),
|
|
3203
|
+
style,
|
|
3204
|
+
children: [
|
|
3205
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(innerValue && "relative"), children: [
|
|
3206
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3207
|
+
"svg",
|
|
3208
|
+
{
|
|
3209
|
+
viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
|
|
3210
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3211
|
+
className: cn(indeterminate && "origin-center animate-circle-spin"),
|
|
3212
|
+
style: { width: dimension, height: dimension },
|
|
3213
|
+
children: [
|
|
3214
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3215
|
+
"circle",
|
|
3216
|
+
{
|
|
3217
|
+
cx: c,
|
|
3218
|
+
cy: c,
|
|
3219
|
+
r: RADIUS,
|
|
3220
|
+
fill: "none",
|
|
3221
|
+
strokeWidth: STROKE,
|
|
3222
|
+
style: { stroke: colors.track }
|
|
3223
|
+
}
|
|
3224
|
+
),
|
|
3225
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3226
|
+
"circle",
|
|
3227
|
+
{
|
|
3228
|
+
cx: c,
|
|
3229
|
+
cy: c,
|
|
3230
|
+
r: RADIUS,
|
|
3231
|
+
fill: "none",
|
|
3232
|
+
strokeWidth: STROKE,
|
|
3233
|
+
strokeLinecap: "round",
|
|
3234
|
+
className: cn(
|
|
3235
|
+
"origin-center",
|
|
3236
|
+
indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
|
|
3237
|
+
),
|
|
3238
|
+
style: {
|
|
3239
|
+
stroke: colors.arc,
|
|
3240
|
+
...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
)
|
|
3244
|
+
]
|
|
3245
|
+
}
|
|
3246
|
+
),
|
|
3247
|
+
showPercent && innerValue && percentNode
|
|
3248
|
+
] }),
|
|
3249
|
+
showPercent && !innerValue && percentNode,
|
|
3250
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]", children: label })
|
|
3251
|
+
]
|
|
3252
|
+
}
|
|
3253
|
+
);
|
|
3254
|
+
}
|
|
3255
|
+
);
|
|
3256
|
+
var IMAGE_FITS = ["cover", "contain", "fill", "none", "scale-down"];
|
|
3257
|
+
var EMPTY_ICON_SIZE = "60cqh";
|
|
3258
|
+
var SPINNER_SIZE = "45cqh";
|
|
3259
|
+
var SImage = /* @__PURE__ */ react.forwardRef(function SImage2({
|
|
3260
|
+
src,
|
|
3261
|
+
alt = "",
|
|
3262
|
+
ratio = 1,
|
|
3263
|
+
fit = "cover",
|
|
3264
|
+
position = "50% 50%",
|
|
3265
|
+
loading: loading2 = "lazy",
|
|
3266
|
+
loadingShowDelay = 0,
|
|
3267
|
+
noSpinner = false,
|
|
3268
|
+
loadingSlot,
|
|
3269
|
+
errorSlot,
|
|
3270
|
+
imgProps,
|
|
3271
|
+
onLoad,
|
|
3272
|
+
onError,
|
|
3273
|
+
className,
|
|
3274
|
+
style,
|
|
3275
|
+
...rest
|
|
3276
|
+
}, ref) {
|
|
3277
|
+
const [status, setStatus] = react.useState("loading");
|
|
3278
|
+
const [spinnerVisible, setSpinnerVisible] = react.useState(loadingShowDelay <= 0);
|
|
3279
|
+
const [trackedSrc, setTrackedSrc] = react.useState(src);
|
|
3280
|
+
const imgRef = react.useRef(null);
|
|
3281
|
+
if (src !== trackedSrc) {
|
|
3282
|
+
setTrackedSrc(src);
|
|
3283
|
+
setStatus("loading");
|
|
3284
|
+
}
|
|
3285
|
+
react.useEffect(() => {
|
|
3286
|
+
if (!src) return;
|
|
3287
|
+
const node = imgRef.current;
|
|
3288
|
+
if (node?.complete && node.naturalWidth > 0) {
|
|
3289
|
+
setStatus((current) => current === "loading" ? "loaded" : current);
|
|
3290
|
+
}
|
|
3291
|
+
}, [src]);
|
|
3292
|
+
react.useEffect(() => {
|
|
3293
|
+
if (status !== "loading" || loadingShowDelay <= 0) {
|
|
3294
|
+
setSpinnerVisible(status === "loading");
|
|
3295
|
+
return;
|
|
3296
|
+
}
|
|
3297
|
+
setSpinnerVisible(false);
|
|
3298
|
+
const timer = setTimeout(() => setSpinnerVisible(true), loadingShowDelay);
|
|
3299
|
+
return () => clearTimeout(timer);
|
|
3300
|
+
}, [status, loadingShowDelay, src]);
|
|
3301
|
+
const isEmpty = !src;
|
|
3302
|
+
const showFallback = isEmpty || status === "error";
|
|
3303
|
+
const showSpinner = !isEmpty && status === "loading" && !noSpinner && spinnerVisible;
|
|
3304
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3305
|
+
"div",
|
|
3306
|
+
{
|
|
3307
|
+
ref,
|
|
3308
|
+
className: cn("relative overflow-hidden bg-(--cmp-image-bg)", className),
|
|
3309
|
+
style: { containerType: "size", aspectRatio: ratio, ...style },
|
|
3310
|
+
...rest,
|
|
3311
|
+
children: [
|
|
3312
|
+
!isEmpty && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3313
|
+
"img",
|
|
3314
|
+
{
|
|
3315
|
+
...imgProps,
|
|
3316
|
+
ref: imgRef,
|
|
3317
|
+
src,
|
|
3318
|
+
alt,
|
|
3319
|
+
loading: loading2,
|
|
3320
|
+
onLoad: () => {
|
|
3321
|
+
setStatus("loaded");
|
|
3322
|
+
onLoad?.(src);
|
|
3323
|
+
},
|
|
3324
|
+
onError: (event) => {
|
|
3325
|
+
setStatus("error");
|
|
3326
|
+
onError?.(event);
|
|
3327
|
+
},
|
|
3328
|
+
className: cn(
|
|
3329
|
+
"h-full w-full",
|
|
3330
|
+
// 로딩 중에도 자리를 지켜야 브라우저가 계속 받아온다 — 숨기되 없애지 않는다
|
|
3331
|
+
status === "loaded" ? "visible" : "invisible",
|
|
3332
|
+
imgProps?.className
|
|
3333
|
+
),
|
|
3334
|
+
style: {
|
|
3335
|
+
objectFit: fit,
|
|
3336
|
+
objectPosition: position,
|
|
3337
|
+
...imgProps?.style
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
),
|
|
3341
|
+
showFallback && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-0 flex items-center justify-center", children: errorSlot ?? /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "image", size: EMPTY_ICON_SIZE, color: "var(--cmp-image-icon)" }) }),
|
|
3342
|
+
showSpinner && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-0 flex items-center justify-center", children: loadingSlot ?? /* @__PURE__ */ jsxRuntime.jsx(SCircleProgress, { indeterminate: true, type: "neutral", size: SPINNER_SIZE }) })
|
|
3343
|
+
]
|
|
3344
|
+
}
|
|
3345
|
+
);
|
|
3346
|
+
});
|
|
3122
3347
|
var BADGE_COLORS = [
|
|
3123
3348
|
"red",
|
|
3124
3349
|
"orange",
|
|
@@ -3220,12 +3445,13 @@ var SDraggableItemView = /* @__PURE__ */ react.forwardRef(
|
|
|
3220
3445
|
!disabled && !selected && !dragging && "hover:bg-(--cmp-listDraggableItem-bg-hover)",
|
|
3221
3446
|
hasSupportingText && supportingTextPosition === "bottom" ? dense ? "min-h-[52px]" : "min-h-[60px]" : dense ? "h-[32px]" : "h-[40px]",
|
|
3222
3447
|
paddingYClass,
|
|
3223
|
-
|
|
3448
|
+
// 항목 사이 구분선은 리스트가 그린다.
|
|
3449
|
+
bordered && cn(
|
|
3224
3450
|
"rounded-(--cmp-listDraggableItem-radius-bordered) border border-(--cmp-listDraggableItem-border-default)",
|
|
3225
3451
|
!disabled && !selected && !dragging && "hover:border-(--cmp-listDraggableItem-bordered-border-hover)",
|
|
3226
3452
|
!disabled && selected && !dragging && "border-(--cmp-listDraggableItem-bordered-border-selected) bg-(--cmp-listDraggableItem-bordered-bg-selected)",
|
|
3227
3453
|
!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)"
|
|
3228
|
-
)
|
|
3454
|
+
),
|
|
3229
3455
|
disabled && "cursor-not-allowed",
|
|
3230
3456
|
className
|
|
3231
3457
|
),
|
|
@@ -3435,6 +3661,7 @@ var SListImpl = /* @__PURE__ */ react.forwardRef(function SList({ className, chi
|
|
|
3435
3661
|
className: cn(
|
|
3436
3662
|
useGap && "flex flex-col gap-(--cmp-list-group-gap)",
|
|
3437
3663
|
usePadding && "p-(--cmp-list-group-padding)",
|
|
3664
|
+
"[&>*]:border-b [&>*]:border-(--cmp-listItem-border-default)",
|
|
3438
3665
|
className
|
|
3439
3666
|
),
|
|
3440
3667
|
...rest,
|
|
@@ -3806,7 +4033,7 @@ var SExpansionItem = /* @__PURE__ */ react.forwardRef(
|
|
|
3806
4033
|
ref,
|
|
3807
4034
|
className: cn(
|
|
3808
4035
|
"group/expansion-item relative overflow-hidden bg-(--cmp-listExpansionItem-title-bg-default)",
|
|
3809
|
-
|
|
4036
|
+
// 항목 사이 구분선은 리스트가 그린다.
|
|
3810
4037
|
// 보더 색은 시맨틱 토큰(border-default → hover strong → 펼침 accentLight)을 쓴다.
|
|
3811
4038
|
// TODO: expansionItem/bordered/radius 토큰 생성 후 rounded 고정값도 토큰으로 교체한다.
|
|
3812
4039
|
bordered && "rounded-[8px] border border-border-default hover:border-border-strong [&:has(>button:hover)]:border-border-strong",
|
|
@@ -3916,7 +4143,7 @@ var SListItemImpl = /* @__PURE__ */ react.forwardRef(function SListItem({
|
|
|
3916
4143
|
trailing,
|
|
3917
4144
|
bordered = false,
|
|
3918
4145
|
selected = false,
|
|
3919
|
-
clickable =
|
|
4146
|
+
clickable = false,
|
|
3920
4147
|
interaction,
|
|
3921
4148
|
accentStripe = false,
|
|
3922
4149
|
dense = false,
|
|
@@ -3969,10 +4196,10 @@ var SListItemImpl = /* @__PURE__ */ react.forwardRef(function SListItem({
|
|
|
3969
4196
|
"gap-(--cmp-listItem-gap)",
|
|
3970
4197
|
"pr-(--cmp-listItem-paddingX)",
|
|
3971
4198
|
depth === 2 ? "pl-[36px]" : depth === 3 ? "pl-[56px]" : "pl-[16px]",
|
|
3972
|
-
bordered
|
|
4199
|
+
bordered && cn(
|
|
3973
4200
|
"overflow-hidden rounded-(--cmp-listItem-radius-bordered) border border-(--cmp-listItem-border-default)",
|
|
3974
4201
|
isSelected ? "border-(--cmp-listItem-bordered-border-selected)" : isInteractive && "hover:border-(--cmp-listItem-bordered-border-hover)"
|
|
3975
|
-
)
|
|
4202
|
+
),
|
|
3976
4203
|
className
|
|
3977
4204
|
),
|
|
3978
4205
|
...rest,
|
|
@@ -4051,6 +4278,8 @@ var SExpansionListImpl = /* @__PURE__ */ react.forwardRef(function SExpansionLis
|
|
|
4051
4278
|
const depth2 = child.props.depth ?? 1;
|
|
4052
4279
|
const itemKey2 = String(child.key ?? index);
|
|
4053
4280
|
return react.cloneElement(child, {
|
|
4281
|
+
// 선택을 리스트가 관리하는 이상 아이템은 클릭 가능해야 한다 — SListItem 의 기본값(false)을 뒤집는다
|
|
4282
|
+
clickable: child.props.clickable ?? true,
|
|
4054
4283
|
selected: selectedKeys[depth2] === itemKey2,
|
|
4055
4284
|
onClick: (event) => {
|
|
4056
4285
|
setSelectedKeys((current) => ({ ...current, [depth2]: itemKey2 }));
|
|
@@ -4356,8 +4585,8 @@ function SGhostButton({
|
|
|
4356
4585
|
}
|
|
4357
4586
|
);
|
|
4358
4587
|
if (!hasTooltip) return btn;
|
|
4359
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4360
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4588
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: setOpen, children: [
|
|
4589
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4361
4590
|
"span",
|
|
4362
4591
|
{
|
|
4363
4592
|
className: cn("inline-flex", anchorClassName),
|
|
@@ -4369,8 +4598,8 @@ function SGhostButton({
|
|
|
4369
4598
|
children: btn
|
|
4370
4599
|
}
|
|
4371
4600
|
) }),
|
|
4372
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4373
|
-
|
|
4601
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4602
|
+
RPopover10__namespace.Content,
|
|
4374
4603
|
{
|
|
4375
4604
|
side: "top",
|
|
4376
4605
|
sideOffset: 4,
|
|
@@ -4384,6 +4613,18 @@ function SGhostButton({
|
|
|
4384
4613
|
) })
|
|
4385
4614
|
] });
|
|
4386
4615
|
}
|
|
4616
|
+
var TREE_LABEL_TYPOGRAPHY = {
|
|
4617
|
+
sm: {
|
|
4618
|
+
default: "typo-body-sm-medium",
|
|
4619
|
+
selected: "typo-body-sm-bold",
|
|
4620
|
+
rowHeight: "h-[28px]"
|
|
4621
|
+
},
|
|
4622
|
+
md: {
|
|
4623
|
+
default: "typo-body-md-medium",
|
|
4624
|
+
selected: "typo-body-md-bold",
|
|
4625
|
+
rowHeight: "h-[32px]"
|
|
4626
|
+
}
|
|
4627
|
+
};
|
|
4387
4628
|
function collectIds(nodes) {
|
|
4388
4629
|
return nodes.flatMap((node) => [node.id, ...collectIds(node.children ?? [])]);
|
|
4389
4630
|
}
|
|
@@ -4394,18 +4635,19 @@ function collectSelectableIds(node) {
|
|
|
4394
4635
|
function toSelectedSet(value) {
|
|
4395
4636
|
return new Set(value ?? []);
|
|
4396
4637
|
}
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4638
|
+
var TREE_ALL_NODE = { id: "__all__", label: "\uC804\uCCB4" };
|
|
4639
|
+
function getSelectionState(node, selectedSet, cascadeSelection) {
|
|
4640
|
+
if (!cascadeSelection) {
|
|
4641
|
+
return { selected: selectedSet.has(node.id), indeterminate: false };
|
|
4400
4642
|
}
|
|
4401
4643
|
const selectableChildren = (node.children ?? []).filter(
|
|
4402
4644
|
(child) => collectSelectableIds(child).length > 0
|
|
4403
4645
|
);
|
|
4404
4646
|
if (selectableChildren.length === 0) {
|
|
4405
|
-
return { selected:
|
|
4647
|
+
return { selected: selectedSet.has(node.id), indeterminate: false };
|
|
4406
4648
|
}
|
|
4407
4649
|
const childStates = selectableChildren.map(
|
|
4408
|
-
(child) => getSelectionState(child, selectedSet)
|
|
4650
|
+
(child) => getSelectionState(child, selectedSet, cascadeSelection)
|
|
4409
4651
|
);
|
|
4410
4652
|
const selectedCount = childStates.filter((state2) => state2.selected).length;
|
|
4411
4653
|
return {
|
|
@@ -4415,6 +4657,7 @@ function getSelectionState(node, selectedSet) {
|
|
|
4415
4657
|
}
|
|
4416
4658
|
function TreeConnector({
|
|
4417
4659
|
guideline,
|
|
4660
|
+
size,
|
|
4418
4661
|
depth,
|
|
4419
4662
|
hasChildren,
|
|
4420
4663
|
isLast,
|
|
@@ -4422,6 +4665,8 @@ function TreeConnector({
|
|
|
4422
4665
|
}) {
|
|
4423
4666
|
if (depth <= 1) return null;
|
|
4424
4667
|
const ancestorConnectors = ancestorLast.slice(0, -1);
|
|
4668
|
+
const branchTop = size === "sm" ? "top-[13px]" : "top-[15px]";
|
|
4669
|
+
const nodeHeight = size === "sm" ? "h-[15px]" : "h-[17px]";
|
|
4425
4670
|
return /* @__PURE__ */ jsxRuntime.jsxs("span", { "aria-hidden": "true", className: "flex self-stretch", children: [
|
|
4426
4671
|
ancestorConnectors.map((last, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4427
4672
|
"span",
|
|
@@ -4435,13 +4680,22 @@ function TreeConnector({
|
|
|
4435
4680
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative block w-[20px] shrink-0", children: [
|
|
4436
4681
|
guideline && !isLast && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute bottom-0 left-[6px] top-[-1px] w-px bg-(--cmp-tree-connector-line-color)" }),
|
|
4437
4682
|
guideline && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4438
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4683
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4684
|
+
"span",
|
|
4685
|
+
{
|
|
4686
|
+
className: cn(
|
|
4687
|
+
"absolute left-[6px] top-[-1px] w-px bg-(--cmp-tree-connector-line-color)",
|
|
4688
|
+
nodeHeight
|
|
4689
|
+
)
|
|
4690
|
+
}
|
|
4691
|
+
),
|
|
4439
4692
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4440
4693
|
"span",
|
|
4441
4694
|
{
|
|
4442
4695
|
"data-tree-connector-branch": hasChildren ? "parent" : "leaf",
|
|
4443
4696
|
className: cn(
|
|
4444
|
-
"absolute left-[6px]
|
|
4697
|
+
"absolute left-[6px] h-px bg-(--cmp-tree-connector-line-color)",
|
|
4698
|
+
branchTop,
|
|
4445
4699
|
hasChildren ? "w-[14px]" : "w-[calc(14px+var(--cmp-tree-item-arrow-icon))]"
|
|
4446
4700
|
)
|
|
4447
4701
|
}
|
|
@@ -4450,6 +4704,44 @@ function TreeConnector({
|
|
|
4450
4704
|
] })
|
|
4451
4705
|
] });
|
|
4452
4706
|
}
|
|
4707
|
+
function STreeAllItem({
|
|
4708
|
+
selected,
|
|
4709
|
+
indeterminate,
|
|
4710
|
+
border,
|
|
4711
|
+
size,
|
|
4712
|
+
onSelect
|
|
4713
|
+
}) {
|
|
4714
|
+
const checkboxValue = indeterminate ? null : selected;
|
|
4715
|
+
const typography = TREE_LABEL_TYPOGRAPHY[size];
|
|
4716
|
+
const labelTypo = selected || indeterminate ? typography.selected : typography.default;
|
|
4717
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4718
|
+
"div",
|
|
4719
|
+
{
|
|
4720
|
+
role: "treeitem",
|
|
4721
|
+
"aria-level": 1,
|
|
4722
|
+
"aria-selected": selected,
|
|
4723
|
+
onClick: onSelect,
|
|
4724
|
+
className: cn(
|
|
4725
|
+
"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)",
|
|
4726
|
+
typography.rowHeight,
|
|
4727
|
+
border && "border-b border-(--cmp-tree-item-border-default)"
|
|
4728
|
+
),
|
|
4729
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "box-border flex min-w-0 flex-1 items-center gap-(--cmp-tree-item-contentGap)", children: [
|
|
4730
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { onClick: (event) => event.stopPropagation(), className: "flex shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(SCheckbox, { value: checkboxValue, onValueChange: () => onSelect() }) }),
|
|
4731
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4732
|
+
"span",
|
|
4733
|
+
{
|
|
4734
|
+
className: cn(
|
|
4735
|
+
"block min-w-0 flex-1 truncate py-(--cmp-tree-item-paddingY) text-(--cmp-tree-item-text-default)",
|
|
4736
|
+
labelTypo
|
|
4737
|
+
),
|
|
4738
|
+
children: "\uC804\uCCB4"
|
|
4739
|
+
}
|
|
4740
|
+
)
|
|
4741
|
+
] })
|
|
4742
|
+
}
|
|
4743
|
+
);
|
|
4744
|
+
}
|
|
4453
4745
|
var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
4454
4746
|
node,
|
|
4455
4747
|
depth = 1,
|
|
@@ -4461,6 +4753,7 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
|
4461
4753
|
border = true,
|
|
4462
4754
|
indeterminate = false,
|
|
4463
4755
|
selectable = true,
|
|
4756
|
+
size = "sm",
|
|
4464
4757
|
leading,
|
|
4465
4758
|
trailing,
|
|
4466
4759
|
onToggle,
|
|
@@ -4472,6 +4765,7 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
|
4472
4765
|
const renderState = {
|
|
4473
4766
|
node,
|
|
4474
4767
|
depth,
|
|
4768
|
+
size,
|
|
4475
4769
|
expanded,
|
|
4476
4770
|
selected,
|
|
4477
4771
|
indeterminate,
|
|
@@ -4481,6 +4775,8 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
|
4481
4775
|
const leadingNode = typeof leading === "function" ? leading(renderState) : leading;
|
|
4482
4776
|
const trailingNode = typeof trailing === "function" ? trailing(renderState) : trailing;
|
|
4483
4777
|
const checkboxValue = indeterminate ? null : selected;
|
|
4778
|
+
const typography = TREE_LABEL_TYPOGRAPHY[size];
|
|
4779
|
+
const labelTypo = selected || indeterminate ? typography.selected : typography.default;
|
|
4484
4780
|
const handleSelect = (event) => {
|
|
4485
4781
|
if (node.disabled) return;
|
|
4486
4782
|
onTreeSelect?.(node, event);
|
|
@@ -4500,7 +4796,8 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
|
4500
4796
|
"aria-disabled": node.disabled || void 0,
|
|
4501
4797
|
onClick: handleRowClick,
|
|
4502
4798
|
className: cn(
|
|
4503
|
-
"group/tree-item flex
|
|
4799
|
+
"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",
|
|
4800
|
+
typography.rowHeight,
|
|
4504
4801
|
border && "border-b border-(--cmp-tree-item-border-default)",
|
|
4505
4802
|
!node.disabled && "hover:bg-(--cmp-tree-item-bg-hover)",
|
|
4506
4803
|
node.disabled && "cursor-not-allowed opacity-60",
|
|
@@ -4513,13 +4810,14 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
|
4513
4810
|
TreeConnector,
|
|
4514
4811
|
{
|
|
4515
4812
|
guideline,
|
|
4813
|
+
size,
|
|
4516
4814
|
depth,
|
|
4517
4815
|
hasChildren,
|
|
4518
4816
|
isLast,
|
|
4519
4817
|
ancestorLast
|
|
4520
4818
|
}
|
|
4521
4819
|
),
|
|
4522
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-(--cmp-tree-item-contentGap)
|
|
4820
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "box-border flex min-w-0 flex-1 items-center gap-(--cmp-tree-item-contentGap)", children: [
|
|
4523
4821
|
hasChildren ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4524
4822
|
SGhostButton,
|
|
4525
4823
|
{
|
|
@@ -4555,25 +4853,17 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
|
4555
4853
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4556
4854
|
"span",
|
|
4557
4855
|
{
|
|
4856
|
+
onClick: (event) => {
|
|
4857
|
+
if (!selectable) return;
|
|
4858
|
+
event.stopPropagation();
|
|
4859
|
+
if (!node.disabled && selectable) onTreeSelect?.(node, event);
|
|
4860
|
+
},
|
|
4558
4861
|
className: cn(
|
|
4559
|
-
"min-w-0 flex-1
|
|
4560
|
-
|
|
4862
|
+
"block min-w-0 flex-1 truncate py-(--cmp-tree-item-paddingY) text-(--cmp-tree-item-text-default)",
|
|
4863
|
+
labelTypo,
|
|
4864
|
+
node.disabled ? "cursor-not-allowed" : selectable ? "cursor-pointer" : void 0
|
|
4561
4865
|
),
|
|
4562
|
-
children:
|
|
4563
|
-
"span",
|
|
4564
|
-
{
|
|
4565
|
-
onClick: (event) => {
|
|
4566
|
-
if (!selectable) return;
|
|
4567
|
-
event.stopPropagation();
|
|
4568
|
-
if (!node.disabled && selectable) onTreeSelect?.(node, event);
|
|
4569
|
-
},
|
|
4570
|
-
className: cn(
|
|
4571
|
-
"inline-block max-w-full truncate",
|
|
4572
|
-
node.disabled ? "cursor-not-allowed" : selectable ? "cursor-pointer" : void 0
|
|
4573
|
-
),
|
|
4574
|
-
children: node.label
|
|
4575
|
-
}
|
|
4576
|
-
)
|
|
4866
|
+
children: node.label
|
|
4577
4867
|
}
|
|
4578
4868
|
),
|
|
4579
4869
|
trailingNode
|
|
@@ -4590,6 +4880,8 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
|
|
|
4590
4880
|
expandedIds,
|
|
4591
4881
|
defaultExpandedIds,
|
|
4592
4882
|
selectable = true,
|
|
4883
|
+
size = "sm",
|
|
4884
|
+
useAll = false,
|
|
4593
4885
|
cascadeSelection = true,
|
|
4594
4886
|
guideline = true,
|
|
4595
4887
|
border = true,
|
|
@@ -4608,6 +4900,11 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
|
|
|
4608
4900
|
const currentExpandedIds = expandedIds ?? internalExpandedIds;
|
|
4609
4901
|
const selectedSet = react.useMemo(() => toSelectedSet(currentValue), [currentValue]);
|
|
4610
4902
|
const expandedSet = react.useMemo(() => new Set(currentExpandedIds), [currentExpandedIds]);
|
|
4903
|
+
const selectableIds = react.useMemo(() => items.flatMap(collectSelectableIds), [items]);
|
|
4904
|
+
const allSelected = selectableIds.length > 0 && selectableIds.every((id) => selectedSet.has(id));
|
|
4905
|
+
const someSelected = selectableIds.some((id) => selectedSet.has(id));
|
|
4906
|
+
const allIndeterminate = someSelected && !allSelected;
|
|
4907
|
+
const showAllItem = selectable && useAll;
|
|
4611
4908
|
const updateExpanded = (node) => {
|
|
4612
4909
|
const next = new Set(currentExpandedIds);
|
|
4613
4910
|
if (next.has(node.id)) next.delete(node.id);
|
|
@@ -4619,7 +4916,7 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
|
|
|
4619
4916
|
const updateSelected = (node) => {
|
|
4620
4917
|
if (node.disabled) return;
|
|
4621
4918
|
const targetIds = cascadeSelection ? collectSelectableIds(node) : [node.id];
|
|
4622
|
-
const everySelected = getSelectionState(node, selectedSet).selected;
|
|
4919
|
+
const everySelected = getSelectionState(node, selectedSet, cascadeSelection).selected;
|
|
4623
4920
|
const next = new Set(selectedSet);
|
|
4624
4921
|
targetIds.forEach((id) => {
|
|
4625
4922
|
if (everySelected) next.delete(id);
|
|
@@ -4629,10 +4926,22 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
|
|
|
4629
4926
|
if (value === void 0) setInternalValue(orderedIds);
|
|
4630
4927
|
onValueChange?.(orderedIds, node);
|
|
4631
4928
|
};
|
|
4929
|
+
const updateAllSelected = (event) => {
|
|
4930
|
+
event?.stopPropagation();
|
|
4931
|
+
if (selectableIds.length === 0) return;
|
|
4932
|
+
const next = new Set(selectedSet);
|
|
4933
|
+
selectableIds.forEach((id) => {
|
|
4934
|
+
if (allSelected) next.delete(id);
|
|
4935
|
+
else next.add(id);
|
|
4936
|
+
});
|
|
4937
|
+
const orderedIds = collectIds(items).filter((id) => next.has(id));
|
|
4938
|
+
if (value === void 0) setInternalValue(orderedIds);
|
|
4939
|
+
onValueChange?.(orderedIds, TREE_ALL_NODE);
|
|
4940
|
+
};
|
|
4632
4941
|
const renderNodes = (nodes, depth = 1, ancestorLast = []) => nodes.map((node, index) => {
|
|
4633
4942
|
const isLast = index === nodes.length - 1;
|
|
4634
4943
|
const isExpanded = expandedSet.has(node.id);
|
|
4635
|
-
const { selected, indeterminate } = getSelectionState(node, selectedSet);
|
|
4944
|
+
const { selected, indeterminate } = getSelectionState(node, selectedSet, cascadeSelection);
|
|
4636
4945
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
|
|
4637
4946
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4638
4947
|
STreeItem2,
|
|
@@ -4645,6 +4954,7 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
|
|
|
4645
4954
|
selected,
|
|
4646
4955
|
indeterminate,
|
|
4647
4956
|
selectable,
|
|
4957
|
+
size,
|
|
4648
4958
|
guideline,
|
|
4649
4959
|
border,
|
|
4650
4960
|
leading,
|
|
@@ -4666,14 +4976,26 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
|
|
|
4666
4976
|
) : null
|
|
4667
4977
|
] }, node.id);
|
|
4668
4978
|
});
|
|
4669
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
4979
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4670
4980
|
"div",
|
|
4671
4981
|
{
|
|
4672
4982
|
ref,
|
|
4673
4983
|
role: "tree",
|
|
4674
4984
|
className: cn("flex w-full flex-col items-start bg-(--cmp-tree-item-bg-default)", className),
|
|
4675
4985
|
...rest,
|
|
4676
|
-
children:
|
|
4986
|
+
children: [
|
|
4987
|
+
showAllItem && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4988
|
+
STreeAllItem,
|
|
4989
|
+
{
|
|
4990
|
+
selected: allSelected,
|
|
4991
|
+
indeterminate: allIndeterminate,
|
|
4992
|
+
border,
|
|
4993
|
+
size,
|
|
4994
|
+
onSelect: updateAllSelected
|
|
4995
|
+
}
|
|
4996
|
+
),
|
|
4997
|
+
renderNodes(items)
|
|
4998
|
+
]
|
|
4677
4999
|
}
|
|
4678
5000
|
);
|
|
4679
5001
|
});
|
|
@@ -4841,7 +5163,7 @@ var STooltipImpl = /* @__PURE__ */ react.forwardRef(function STooltip({
|
|
|
4841
5163
|
...restContentProps
|
|
4842
5164
|
} = contentProps ?? {};
|
|
4843
5165
|
const contentClass = cn(
|
|
4844
|
-
"z-50 w-fit
|
|
5166
|
+
"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",
|
|
4845
5167
|
FLOATING_SLIDE_ANIM,
|
|
4846
5168
|
className,
|
|
4847
5169
|
contentPropsClassName
|
|
@@ -4853,14 +5175,14 @@ var STooltipImpl = /* @__PURE__ */ react.forwardRef(function STooltip({
|
|
|
4853
5175
|
...style,
|
|
4854
5176
|
...contentPropsStyle
|
|
4855
5177
|
};
|
|
4856
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5178
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: setOpenState, children: [
|
|
4857
5179
|
isNone ? (
|
|
4858
5180
|
// 트리거 없음: children 을 래퍼 없이 그대로 앵커로 쓴다 (소비자 레이아웃 보존).
|
|
4859
5181
|
// mouse/focus 핸들러가 없으므로 useClose 없이도 자동 닫힘이 발생하지 않는다.
|
|
4860
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5182
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { asChild: true, children: triggerNode })
|
|
4861
5183
|
) : isHover ? (
|
|
4862
5184
|
// hover: Anchor(위치 기준) + 직접 mouse 핸들러 — 클릭으로 토글되지 않도록 Trigger 미사용
|
|
4863
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5185
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4864
5186
|
"span",
|
|
4865
5187
|
{
|
|
4866
5188
|
className: "inline-flex",
|
|
@@ -4871,9 +5193,9 @@ var STooltipImpl = /* @__PURE__ */ react.forwardRef(function STooltip({
|
|
|
4871
5193
|
children: triggerNode
|
|
4872
5194
|
}
|
|
4873
5195
|
) })
|
|
4874
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4875
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4876
|
-
|
|
5196
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: triggerNode }),
|
|
5197
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5198
|
+
RPopover10__namespace.Content,
|
|
4877
5199
|
{
|
|
4878
5200
|
side: placement,
|
|
4879
5201
|
sideOffset,
|
|
@@ -4907,7 +5229,7 @@ var STooltipImpl = /* @__PURE__ */ react.forwardRef(function STooltip({
|
|
|
4907
5229
|
}
|
|
4908
5230
|
)
|
|
4909
5231
|
] }),
|
|
4910
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5232
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
4911
5233
|
]
|
|
4912
5234
|
}
|
|
4913
5235
|
) })
|
|
@@ -4919,6 +5241,10 @@ var BODY_PADDING_CLASS = {
|
|
|
4919
5241
|
wide: "p-(--sys-space-panel-padding-wide)",
|
|
4920
5242
|
none: ""
|
|
4921
5243
|
};
|
|
5244
|
+
var BODY_BACKGROUND_CLASS = {
|
|
5245
|
+
frame: "",
|
|
5246
|
+
neutral: "bg-(--sys-color-bg-neutralLight)"
|
|
5247
|
+
};
|
|
4922
5248
|
var topBorderColorClass = {
|
|
4923
5249
|
default: "bg-(--cmp-sectionHeaderCard-topBorder-color-default)",
|
|
4924
5250
|
accent: "bg-(--cmp-sectionHeaderCard-topBorder-color-accent)"
|
|
@@ -4928,8 +5254,8 @@ var titleSizeClass = {
|
|
|
4928
5254
|
sm: "typo-heading-sm"
|
|
4929
5255
|
};
|
|
4930
5256
|
var SSectionHeaderCardBodyImpl = /* @__PURE__ */ react.forwardRef(
|
|
4931
|
-
function SSectionHeaderCardBody({ padding = "default",
|
|
4932
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn(BODY_PADDING_CLASS[padding],
|
|
5257
|
+
function SSectionHeaderCardBody({ padding = "default", background = "frame", children }, ref) {
|
|
5258
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn(BODY_PADDING_CLASS[padding], BODY_BACKGROUND_CLASS[background]), children });
|
|
4933
5259
|
}
|
|
4934
5260
|
);
|
|
4935
5261
|
var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
|
|
@@ -4942,8 +5268,7 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
4942
5268
|
subtitle,
|
|
4943
5269
|
slot,
|
|
4944
5270
|
thickness = false,
|
|
4945
|
-
className
|
|
4946
|
-
...rest
|
|
5271
|
+
className
|
|
4947
5272
|
}, ref) {
|
|
4948
5273
|
const hasHelp = helpText != null && helpText.length > 0;
|
|
4949
5274
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -4964,7 +5289,6 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
4964
5289
|
"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)",
|
|
4965
5290
|
className
|
|
4966
5291
|
),
|
|
4967
|
-
...rest,
|
|
4968
5292
|
children: [
|
|
4969
5293
|
marker && /* @__PURE__ */ jsxRuntime.jsx(SBadge, { color: "darkblue", className: "shrink-0" }),
|
|
4970
5294
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 shrink-0 items-center gap-[8px]", children: [
|
|
@@ -5008,8 +5332,24 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
5008
5332
|
}
|
|
5009
5333
|
);
|
|
5010
5334
|
var SSectionHeaderCardRootImpl = /* @__PURE__ */ react.forwardRef(
|
|
5011
|
-
function SSectionHeaderCard({
|
|
5012
|
-
|
|
5335
|
+
function SSectionHeaderCard({
|
|
5336
|
+
title,
|
|
5337
|
+
titleSize,
|
|
5338
|
+
marker,
|
|
5339
|
+
required,
|
|
5340
|
+
helpText,
|
|
5341
|
+
subtitle,
|
|
5342
|
+
slot,
|
|
5343
|
+
thickness,
|
|
5344
|
+
headerClassName,
|
|
5345
|
+
padding,
|
|
5346
|
+
background,
|
|
5347
|
+
className,
|
|
5348
|
+
children,
|
|
5349
|
+
...rest
|
|
5350
|
+
}, ref) {
|
|
5351
|
+
const hasHeader = title != null;
|
|
5352
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5013
5353
|
"div",
|
|
5014
5354
|
{
|
|
5015
5355
|
ref,
|
|
@@ -5018,24 +5358,28 @@ var SSectionHeaderCardRootImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
5018
5358
|
className
|
|
5019
5359
|
),
|
|
5020
5360
|
...rest,
|
|
5021
|
-
children
|
|
5361
|
+
children: [
|
|
5362
|
+
hasHeader && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5363
|
+
SSectionHeaderCardHeaderImpl,
|
|
5364
|
+
{
|
|
5365
|
+
title,
|
|
5366
|
+
titleSize,
|
|
5367
|
+
marker,
|
|
5368
|
+
required,
|
|
5369
|
+
helpText,
|
|
5370
|
+
subtitle,
|
|
5371
|
+
slot,
|
|
5372
|
+
thickness,
|
|
5373
|
+
className: headerClassName
|
|
5374
|
+
}
|
|
5375
|
+
),
|
|
5376
|
+
/* @__PURE__ */ jsxRuntime.jsx(SSectionHeaderCardBodyImpl, { padding, background, children })
|
|
5377
|
+
]
|
|
5022
5378
|
}
|
|
5023
5379
|
);
|
|
5024
5380
|
}
|
|
5025
5381
|
);
|
|
5026
|
-
var
|
|
5027
|
-
var SSectionHeaderCardHeader2 = /* @__PURE__ */ withDisplayName(
|
|
5028
|
-
SSectionHeaderCardHeaderImpl,
|
|
5029
|
-
"SSectionHeaderCard.Header"
|
|
5030
|
-
);
|
|
5031
|
-
var SSectionHeaderCardBody2 = /* @__PURE__ */ withDisplayName(
|
|
5032
|
-
SSectionHeaderCardBodyImpl,
|
|
5033
|
-
"SSectionHeaderCard.Body"
|
|
5034
|
-
);
|
|
5035
|
-
var SSectionHeaderCard2 = /* @__PURE__ */ Object.assign(SSectionHeaderCardRoot, {
|
|
5036
|
-
Header: SSectionHeaderCardHeader2,
|
|
5037
|
-
Body: SSectionHeaderCardBody2
|
|
5038
|
-
});
|
|
5382
|
+
var SSectionHeaderCard2 = /* @__PURE__ */ withDisplayName(SSectionHeaderCardRootImpl, "SSectionHeaderCard");
|
|
5039
5383
|
var SDivider = /* @__PURE__ */ react.forwardRef(function SDivider2({ vertical = false, className, style, ...rest }, ref) {
|
|
5040
5384
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5041
5385
|
"hr",
|
|
@@ -5556,14 +5900,14 @@ var SCallout = /* @__PURE__ */ react.forwardRef(function SCallout2({ type = "def
|
|
|
5556
5900
|
);
|
|
5557
5901
|
});
|
|
5558
5902
|
var FILL_COLOR = {
|
|
5559
|
-
primary: "var(--cmp-progress-active
|
|
5560
|
-
error: "var(--cmp-progress-error
|
|
5561
|
-
complete: "var(--cmp-progress-success
|
|
5903
|
+
primary: "var(--cmp-progress-color-active)",
|
|
5904
|
+
error: "var(--cmp-progress-color-error)",
|
|
5905
|
+
complete: "var(--cmp-progress-color-success)"
|
|
5562
5906
|
};
|
|
5563
|
-
var
|
|
5907
|
+
var clamp2 = (v) => Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;
|
|
5564
5908
|
var SLinearProgress = /* @__PURE__ */ react.forwardRef(
|
|
5565
5909
|
function SLinearProgress2({ value = 0, type = "primary", indeterminate = false, label, className, style }, ref) {
|
|
5566
|
-
const v =
|
|
5910
|
+
const v = clamp2(value);
|
|
5567
5911
|
const fill = FILL_COLOR[type];
|
|
5568
5912
|
const valueColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : fill;
|
|
5569
5913
|
const valueText = `${Math.round(v)}%`;
|
|
@@ -5610,115 +5954,6 @@ var SLinearProgress = /* @__PURE__ */ react.forwardRef(
|
|
|
5610
5954
|
);
|
|
5611
5955
|
}
|
|
5612
5956
|
);
|
|
5613
|
-
var VIEWBOX = 80;
|
|
5614
|
-
var RADIUS = 34;
|
|
5615
|
-
var STROKE = 12;
|
|
5616
|
-
var CIRCUMFERENCE = 2 * Math.PI * RADIUS;
|
|
5617
|
-
var COLOR_MAP = {
|
|
5618
|
-
primary: { arc: "var(--cmp-progress-active-color)", track: "var(--cmp-progress-color-track)" },
|
|
5619
|
-
// inverse: 어두운 배경용 — arc 흰색, track 은 흰색 40%(회색 링)
|
|
5620
|
-
inverse: { arc: "var(--color-white)", track: "rgba(255,255,255,0.4)" },
|
|
5621
|
-
error: { arc: "var(--color-red-75)", track: "var(--cmp-progress-color-track)" },
|
|
5622
|
-
complete: { arc: "#01BB4B", track: "var(--cmp-progress-color-track)" }
|
|
5623
|
-
};
|
|
5624
|
-
var clamp2 = (v) => Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;
|
|
5625
|
-
var SCircleProgress = /* @__PURE__ */ react.forwardRef(
|
|
5626
|
-
function SCircleProgress2({
|
|
5627
|
-
value = 0,
|
|
5628
|
-
type = "primary",
|
|
5629
|
-
indeterminate = false,
|
|
5630
|
-
label,
|
|
5631
|
-
innerValue = false,
|
|
5632
|
-
className,
|
|
5633
|
-
style
|
|
5634
|
-
}, ref) {
|
|
5635
|
-
const v = clamp2(value);
|
|
5636
|
-
const colors = COLOR_MAP[type];
|
|
5637
|
-
const c = VIEWBOX / 2;
|
|
5638
|
-
const percentColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : colors.arc;
|
|
5639
|
-
const filled = v / 100 * CIRCUMFERENCE;
|
|
5640
|
-
const showPercent = !indeterminate;
|
|
5641
|
-
const percentNode = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5642
|
-
"span",
|
|
5643
|
-
{
|
|
5644
|
-
className: cn(
|
|
5645
|
-
"text-center text-[16px] font-bold",
|
|
5646
|
-
innerValue ? (
|
|
5647
|
-
// leading-[normal]: 26px leading 은 폰트 content(19px) 위아래로 홀수(7px)만큼 남아
|
|
5648
|
-
// 3px/4px 로 쪼개지고 글자가 링 중심보다 위로 뜬다. (leading-normal 은 1.5 라 동일 문제)
|
|
5649
|
-
"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 leading-[normal]"
|
|
5650
|
-
) : "leading-[26px]"
|
|
5651
|
-
),
|
|
5652
|
-
style: { color: percentColor },
|
|
5653
|
-
children: [
|
|
5654
|
-
Math.round(v),
|
|
5655
|
-
"%"
|
|
5656
|
-
]
|
|
5657
|
-
}
|
|
5658
|
-
);
|
|
5659
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5660
|
-
"div",
|
|
5661
|
-
{
|
|
5662
|
-
ref,
|
|
5663
|
-
className: cn(
|
|
5664
|
-
"inline-flex flex-col items-center gap-[var(--cmp-progress-circular-gap)]",
|
|
5665
|
-
className
|
|
5666
|
-
),
|
|
5667
|
-
style,
|
|
5668
|
-
children: [
|
|
5669
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(innerValue && "relative"), children: [
|
|
5670
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5671
|
-
"svg",
|
|
5672
|
-
{
|
|
5673
|
-
viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
|
|
5674
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
5675
|
-
className: cn(
|
|
5676
|
-
"h-[80px] w-[80px]",
|
|
5677
|
-
indeterminate && "origin-center animate-circle-spin"
|
|
5678
|
-
),
|
|
5679
|
-
children: [
|
|
5680
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5681
|
-
"circle",
|
|
5682
|
-
{
|
|
5683
|
-
cx: c,
|
|
5684
|
-
cy: c,
|
|
5685
|
-
r: RADIUS,
|
|
5686
|
-
fill: "none",
|
|
5687
|
-
strokeWidth: STROKE,
|
|
5688
|
-
style: { stroke: colors.track }
|
|
5689
|
-
}
|
|
5690
|
-
),
|
|
5691
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5692
|
-
"circle",
|
|
5693
|
-
{
|
|
5694
|
-
cx: c,
|
|
5695
|
-
cy: c,
|
|
5696
|
-
r: RADIUS,
|
|
5697
|
-
fill: "none",
|
|
5698
|
-
strokeWidth: STROKE,
|
|
5699
|
-
strokeLinecap: "round",
|
|
5700
|
-
className: cn(
|
|
5701
|
-
"origin-center",
|
|
5702
|
-
indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
|
|
5703
|
-
),
|
|
5704
|
-
style: {
|
|
5705
|
-
stroke: colors.arc,
|
|
5706
|
-
...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
|
|
5707
|
-
}
|
|
5708
|
-
}
|
|
5709
|
-
)
|
|
5710
|
-
]
|
|
5711
|
-
}
|
|
5712
|
-
),
|
|
5713
|
-
showPercent && innerValue && percentNode
|
|
5714
|
-
] }),
|
|
5715
|
-
showPercent && !innerValue && percentNode,
|
|
5716
|
-
label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]", children: label })
|
|
5717
|
-
]
|
|
5718
|
-
}
|
|
5719
|
-
);
|
|
5720
|
-
}
|
|
5721
|
-
);
|
|
5722
5957
|
|
|
5723
5958
|
// src/lib/global-overlay.ts
|
|
5724
5959
|
var GLOBAL_OVERLAY_ATTR = "data-s-global-overlay";
|
|
@@ -5915,6 +6150,15 @@ var STextLink = /* @__PURE__ */ react.forwardRef(function STextLink2({
|
|
|
5915
6150
|
/* @__PURE__ */ jsxRuntime.jsx(RTooltip__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(RTooltip__namespace.Content, { side: "top", sideOffset: 4, className: cn("z-50", FLOATING_SLIDE_ANIM), children: /* @__PURE__ */ jsxRuntime.jsx(STag, { shape: "square", size: "xs", color: "grey", label: text }) }) })
|
|
5916
6151
|
] }) });
|
|
5917
6152
|
});
|
|
6153
|
+
|
|
6154
|
+
// src/lib/floating-width.ts
|
|
6155
|
+
var POPOVER_AVAILABLE_WIDTH = "var(--radix-popover-content-available-width)";
|
|
6156
|
+
var DROPDOWN_AVAILABLE_WIDTH = "var(--radix-dropdown-menu-content-available-width)";
|
|
6157
|
+
function clampToAvailableWidth(value, availableWidth) {
|
|
6158
|
+
if (value == null || value === "") return availableWidth;
|
|
6159
|
+
const css = typeof value === "number" ? `${value}px` : value;
|
|
6160
|
+
return `min(${css}, ${availableWidth})`;
|
|
6161
|
+
}
|
|
5918
6162
|
var SIZE2 = {
|
|
5919
6163
|
xs: { height: 24, paddingX: 8, gap: 6, arrow: 12, fontSize: 12, minWidth: 64, splitMinWidth: 72 },
|
|
5920
6164
|
sm: {
|
|
@@ -5951,6 +6195,7 @@ function splitDivider(color, outline) {
|
|
|
5951
6195
|
};
|
|
5952
6196
|
return (outline ? outlined : solid)[color];
|
|
5953
6197
|
}
|
|
6198
|
+
var VIEWPORT_PADDING = 12;
|
|
5954
6199
|
var itemClass = cn(
|
|
5955
6200
|
"flex min-h-[28px] cursor-pointer select-none items-center gap-[8px] rounded-[2px] px-[12px] py-[4px] text-[12px] leading-[20px] outline-none",
|
|
5956
6201
|
"text-[color:var(--sys-color-fg-secondary)]",
|
|
@@ -6032,12 +6277,16 @@ var SDropdownButtonImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
6032
6277
|
sideOffset: 4,
|
|
6033
6278
|
align: "start",
|
|
6034
6279
|
alignOffset: split ? splitAlignOffset : 0,
|
|
6280
|
+
collisionPadding: VIEWPORT_PADDING,
|
|
6035
6281
|
className: cn(
|
|
6036
6282
|
"z-50 overflow-hidden rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] shadow-normal-sm",
|
|
6037
|
-
|
|
6283
|
+
// 창보다 넓은 메뉴는 창 폭에 맞춰 줄인다. 트리거 너비를 따르는 하한도 같은 상한으로
|
|
6284
|
+
// 감싸야 한다 — min-width 가 max-width 를 이기기 때문이다.
|
|
6285
|
+
"max-w-[var(--radix-dropdown-menu-content-available-width)]",
|
|
6286
|
+
!split && "min-w-[min(var(--radix-dropdown-menu-trigger-width),var(--radix-dropdown-menu-content-available-width))]",
|
|
6038
6287
|
FLOATING_SLIDE_ANIM
|
|
6039
6288
|
),
|
|
6040
|
-
style: split ? { minWidth: splitWidth } : void 0,
|
|
6289
|
+
style: split ? { minWidth: clampToAvailableWidth(splitWidth, DROPDOWN_AVAILABLE_WIDTH) } : void 0,
|
|
6041
6290
|
children: items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6042
6291
|
RDropdown__namespace.Item,
|
|
6043
6292
|
{
|
|
@@ -6049,7 +6298,7 @@ var SDropdownButtonImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
6049
6298
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6050
6299
|
"span",
|
|
6051
6300
|
{
|
|
6052
|
-
className: "min-w-0
|
|
6301
|
+
className: "min-w-0 break-words",
|
|
6053
6302
|
dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(it.label) }
|
|
6054
6303
|
}
|
|
6055
6304
|
)
|
|
@@ -6190,10 +6439,15 @@ function SSwitch({
|
|
|
6190
6439
|
}
|
|
6191
6440
|
);
|
|
6192
6441
|
}
|
|
6442
|
+
var SIZE_CLASSES = {
|
|
6443
|
+
xs: "h-[24px] px-[8px] text-[12px] font-normal leading-[20px]",
|
|
6444
|
+
sm: "h-[28px] px-[12px] text-[14px] font-medium leading-[24px]"
|
|
6445
|
+
};
|
|
6193
6446
|
function SToggle({
|
|
6194
6447
|
value = false,
|
|
6195
6448
|
label = "",
|
|
6196
6449
|
disabled = false,
|
|
6450
|
+
size = "sm",
|
|
6197
6451
|
onValueChange,
|
|
6198
6452
|
className,
|
|
6199
6453
|
style
|
|
@@ -6209,7 +6463,8 @@ function SToggle({
|
|
|
6209
6463
|
"aria-pressed": value,
|
|
6210
6464
|
onClick: () => !disabled && onValueChange?.(!value),
|
|
6211
6465
|
className: cn(
|
|
6212
|
-
"box-border inline-flex
|
|
6466
|
+
"box-border inline-flex items-center justify-center whitespace-nowrap rounded-full border border-solid transition-colors",
|
|
6467
|
+
SIZE_CLASSES[size],
|
|
6213
6468
|
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
6214
6469
|
// 미선택(off) hover 시 파란 채움 + 흰 글자
|
|
6215
6470
|
!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)]",
|
|
@@ -6261,16 +6516,20 @@ function SPopover({
|
|
|
6261
6516
|
const descColor = type === "default" ? "var(--cmp-popover-default-description)" : "var(--cmp-popover-light-description)";
|
|
6262
6517
|
const leftLinkLabelClass = type === "default" ? "text-[color:var(--cmp-popover-default-subAction)]" : "text-[color:var(--cmp-popover-light-subAction)]";
|
|
6263
6518
|
const triggerNode = trigger ?? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex cursor-pointer", "aria-label": ariaLabel, children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: iconSize, color }) });
|
|
6264
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6265
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6266
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6267
|
-
|
|
6519
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open: actualOpen, onOpenChange: setOpen, children: [
|
|
6520
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: triggerNode }),
|
|
6521
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6522
|
+
RPopover10__namespace.Content,
|
|
6268
6523
|
{
|
|
6269
6524
|
side: placement,
|
|
6270
6525
|
sideOffset: 8,
|
|
6271
6526
|
className: cn(
|
|
6272
6527
|
// 닫기 버튼이 항상 있으므로 우측은 close clearance(36px) 로 고정
|
|
6273
|
-
"relative z-50 flex
|
|
6528
|
+
"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",
|
|
6529
|
+
// 창보다 넓어지면 창 폭에 맞춘다. 최소 너비도 같은 상한으로 감싼다 —
|
|
6530
|
+
// min-width 가 max-width 를 이기므로 감싸지 않으면 상한이 무력화된다.
|
|
6531
|
+
"max-w-[var(--radix-popover-content-available-width)]",
|
|
6532
|
+
"min-w-[min(160px,var(--radix-popover-content-available-width))]",
|
|
6274
6533
|
FLOATING_SLIDE_ANIM,
|
|
6275
6534
|
menuClassName
|
|
6276
6535
|
),
|
|
@@ -6326,7 +6585,7 @@ function SPopover({
|
|
|
6326
6585
|
]
|
|
6327
6586
|
}
|
|
6328
6587
|
),
|
|
6329
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6588
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
6330
6589
|
]
|
|
6331
6590
|
}
|
|
6332
6591
|
) })
|
|
@@ -6355,8 +6614,9 @@ function SPortal({
|
|
|
6355
6614
|
ariaLabel
|
|
6356
6615
|
}) {
|
|
6357
6616
|
const portalContainer = usePortalContainer();
|
|
6617
|
+
const { minWidth: styleMinWidth, maxWidth: styleMaxWidth, ...restStyle } = style ?? {};
|
|
6358
6618
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6359
|
-
|
|
6619
|
+
RPopover10__namespace.Root,
|
|
6360
6620
|
{
|
|
6361
6621
|
open,
|
|
6362
6622
|
onOpenChange: (next) => {
|
|
@@ -6364,9 +6624,9 @@ function SPortal({
|
|
|
6364
6624
|
if (!next) onClose?.();
|
|
6365
6625
|
},
|
|
6366
6626
|
children: [
|
|
6367
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6368
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6369
|
-
|
|
6627
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { virtualRef: anchorRef }),
|
|
6628
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6629
|
+
RPopover10__namespace.Content,
|
|
6370
6630
|
{
|
|
6371
6631
|
side: placement,
|
|
6372
6632
|
align,
|
|
@@ -6393,11 +6653,18 @@ function SPortal({
|
|
|
6393
6653
|
className: cn(
|
|
6394
6654
|
"z-50 overflow-hidden rounded-(--cmp-listBox-radius) bg-(--cmp-listBox-bg) shadow-normal-sm",
|
|
6395
6655
|
maxHeight != null && "overflow-y-auto",
|
|
6396
|
-
|
|
6656
|
+
// 앵커가 창보다 넓을 수 있는 자리(가로 스크롤 안의 트리거 등)에서도 하한이 상한을
|
|
6657
|
+
// 이기지 않도록, 앵커 너비 역시 가용 폭으로 가둔다.
|
|
6658
|
+
fit && "min-w-[min(var(--radix-popover-trigger-width),var(--radix-popover-content-available-width))]",
|
|
6397
6659
|
FLOATING_SLIDE_ANIM,
|
|
6398
6660
|
className
|
|
6399
6661
|
),
|
|
6400
|
-
style: {
|
|
6662
|
+
style: {
|
|
6663
|
+
maxHeight,
|
|
6664
|
+
...restStyle,
|
|
6665
|
+
...styleMinWidth != null ? { minWidth: clampToAvailableWidth(styleMinWidth, POPOVER_AVAILABLE_WIDTH) } : {},
|
|
6666
|
+
maxWidth: clampToAvailableWidth(styleMaxWidth, POPOVER_AVAILABLE_WIDTH)
|
|
6667
|
+
},
|
|
6401
6668
|
children
|
|
6402
6669
|
}
|
|
6403
6670
|
) })
|
|
@@ -6557,16 +6824,18 @@ function SGuide({
|
|
|
6557
6824
|
);
|
|
6558
6825
|
if (isNotion)
|
|
6559
6826
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { className, style, children: trigger });
|
|
6560
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6561
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6562
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6563
|
-
|
|
6827
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: setOpen, children: [
|
|
6828
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: trigger }),
|
|
6829
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6830
|
+
RPopover10__namespace.Content,
|
|
6564
6831
|
{
|
|
6565
6832
|
side: "bottom",
|
|
6566
6833
|
align: "start",
|
|
6567
6834
|
sideOffset: 4,
|
|
6568
6835
|
className: cn(
|
|
6569
6836
|
"relative z-50 rounded-[var(--cmp-guide-contents-radius)] bg-[var(--color-white)]",
|
|
6837
|
+
// popupWidth(기본 426px)가 창보다 넓으면 창 폭에 맞춘다 — max-width 가 width 를 이긴다.
|
|
6838
|
+
"max-w-[var(--radix-popover-content-available-width)]",
|
|
6570
6839
|
FLOATING_SLIDE_ANIM
|
|
6571
6840
|
),
|
|
6572
6841
|
style: {
|
|
@@ -6741,7 +7010,7 @@ function SModalContainer({
|
|
|
6741
7010
|
"div",
|
|
6742
7011
|
{
|
|
6743
7012
|
className: cn(
|
|
6744
|
-
"relative flex max-h-[
|
|
7013
|
+
"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",
|
|
6745
7014
|
shaking && "animate-modal-shake",
|
|
6746
7015
|
className
|
|
6747
7016
|
),
|
|
@@ -6998,7 +7267,7 @@ function SActionModal({
|
|
|
6998
7267
|
showClose: true,
|
|
6999
7268
|
width,
|
|
7000
7269
|
height,
|
|
7001
|
-
className: "w-fit min-w-[min(480px,calc(100dvw-48px))] min-h-[min(320px,
|
|
7270
|
+
className: "w-fit min-w-[min(480px,calc(100dvw-48px))] min-h-[min(320px,85dvh)]",
|
|
7002
7271
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-auto flex-col", children: [
|
|
7003
7272
|
/* @__PURE__ */ jsxRuntime.jsx(SOverlayHeader, { title: modalTitle, description, reserveCloseSpace: true }),
|
|
7004
7273
|
/* @__PURE__ */ jsxRuntime.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 }),
|
|
@@ -7891,15 +8160,21 @@ var GNB_MENU = {
|
|
|
7891
8160
|
depth2PaddingLeft: box("item-depth2-paddingLeft"),
|
|
7892
8161
|
depth3PaddingLeft: box("item-depth3-paddingLeft"),
|
|
7893
8162
|
depth1Icon: box("item-depth1-icon"),
|
|
8163
|
+
// box 는 depth1 전용 타이포 토큰이 없어 depth1 도 selected 타이포를 따른다
|
|
7894
8164
|
depth1FontSize: 14,
|
|
7895
8165
|
// token: gnb.box.item.typography.selected.fontSize
|
|
7896
8166
|
depth1LineHeight: 24,
|
|
7897
8167
|
// token: gnb.box.item.typography.selected.lineHeight
|
|
7898
|
-
depth1FontWeight:
|
|
8168
|
+
depth1FontWeight: 600,
|
|
8169
|
+
// token: gnb.box.item.typography.selected.fontWeight
|
|
7899
8170
|
itemFontSize: 14,
|
|
7900
8171
|
// token: gnb.box.item.typography.default.fontSize
|
|
7901
|
-
itemLineHeight: 24
|
|
8172
|
+
itemLineHeight: 24,
|
|
7902
8173
|
// token: gnb.box.item.typography.default.lineHeight
|
|
8174
|
+
itemFontWeight: 500,
|
|
8175
|
+
// token: gnb.box.item.typography.default.fontWeight
|
|
8176
|
+
itemFontWeightSelected: 600
|
|
8177
|
+
// token: gnb.box.item.typography.selected.fontWeight
|
|
7903
8178
|
},
|
|
7904
8179
|
belt: {
|
|
7905
8180
|
bodyPaddingY: gnb("body-padding"),
|
|
@@ -7921,10 +8196,15 @@ var GNB_MENU = {
|
|
|
7921
8196
|
depth1LineHeight: 22,
|
|
7922
8197
|
// token: gnb.belt.item.depth1.typography.lineHeight
|
|
7923
8198
|
depth1FontWeight: 700,
|
|
8199
|
+
// token: gnb.belt.item.depth1.typography.fontWeight
|
|
7924
8200
|
itemFontSize: 12,
|
|
7925
8201
|
// token: gnb.belt.item.typography.default.fontSize
|
|
7926
|
-
itemLineHeight: 20
|
|
8202
|
+
itemLineHeight: 20,
|
|
7927
8203
|
// token: gnb.belt.item.typography.default.lineHeight
|
|
8204
|
+
itemFontWeight: 500,
|
|
8205
|
+
// token: gnb.belt.item.typography.default.fontWeight
|
|
8206
|
+
itemFontWeightSelected: 700
|
|
8207
|
+
// token: gnb.belt.item.typography.selected.fontWeight
|
|
7928
8208
|
}
|
|
7929
8209
|
};
|
|
7930
8210
|
var GNB_COLORS = {
|
|
@@ -8222,7 +8502,7 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
|
|
|
8222
8502
|
fontFamily: "inherit",
|
|
8223
8503
|
fontSize: depth === 1 ? M.depth1FontSize : M.itemFontSize,
|
|
8224
8504
|
lineHeight: `${depth === 1 ? M.depth1LineHeight : M.itemLineHeight}px`,
|
|
8225
|
-
fontWeight: depth === 1
|
|
8505
|
+
fontWeight: depth === 1 ? M.depth1FontWeight : isSelected ? M.itemFontWeightSelected : M.itemFontWeight,
|
|
8226
8506
|
opacity: item.disabled ? 0.4 : 1,
|
|
8227
8507
|
cursor: item.disabled ? "not-allowed" : "pointer"
|
|
8228
8508
|
};
|
|
@@ -8639,10 +8919,10 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
|
|
|
8639
8919
|
}
|
|
8640
8920
|
),
|
|
8641
8921
|
header === "fix" && menuResizeHandle,
|
|
8642
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8643
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8644
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8645
|
-
|
|
8922
|
+
/* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open: labelTip !== null, onOpenChange: (open) => !open && setLabelTip(null), children: [
|
|
8923
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { virtualRef: labelTipAnchorRef }),
|
|
8924
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8925
|
+
RPopover10__namespace.Content,
|
|
8646
8926
|
{
|
|
8647
8927
|
side: "right",
|
|
8648
8928
|
sideOffset: 4,
|
|
@@ -8660,41 +8940,310 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
|
|
|
8660
8940
|
}
|
|
8661
8941
|
);
|
|
8662
8942
|
});
|
|
8943
|
+
var SPageHeader = /* @__PURE__ */ withDisplayName(
|
|
8944
|
+
react.forwardRef(function SPageHeader2({ title, subText, fix = false, onBack, slot, scrolled = false, className, style, ...rest }, ref) {
|
|
8945
|
+
const hasBack = onBack != null;
|
|
8946
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8947
|
+
"header",
|
|
8948
|
+
{
|
|
8949
|
+
ref,
|
|
8950
|
+
className: cn(
|
|
8951
|
+
"relative z-10 box-border flex shrink-0 items-center gap-(--cmp-pageHeader-gap) px-(--cmp-pageHeader-paddingX)",
|
|
8952
|
+
fix ? "h-(--cmp-pageHeader-bar-height) border-b border-(--cmp-pageHeader-bar-border) bg-(--cmp-pageHeader-bar-bg) py-(--cmp-pageHeader-bar-paddingY)" : cn(
|
|
8953
|
+
// 배경은 항상 투명 — 페이지 배경을 따라갈지는 fix 가 정하지 scrolled 가 정하지 않는다.
|
|
8954
|
+
// 스크롤되면 그림자만 더해 콘텐츠 위에 뜬 것처럼 보이게 한다.
|
|
8955
|
+
"bg-transparent pt-(--cmp-pageHeader-plain-paddingTop) pb-(--cmp-pageHeader-plain-paddingBottom)",
|
|
8956
|
+
scrolled && "shadow-floating"
|
|
8957
|
+
),
|
|
8958
|
+
className
|
|
8959
|
+
),
|
|
8960
|
+
style,
|
|
8961
|
+
...rest,
|
|
8962
|
+
children: [
|
|
8963
|
+
hasBack && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8964
|
+
SGhostButton,
|
|
8965
|
+
{
|
|
8966
|
+
icon: "chevronLeft",
|
|
8967
|
+
size: "xs",
|
|
8968
|
+
ariaLabel: "\uB4A4\uB85C\uAC00\uAE30",
|
|
8969
|
+
onClick: onBack,
|
|
8970
|
+
className: "shrink-0"
|
|
8971
|
+
}
|
|
8972
|
+
),
|
|
8973
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8974
|
+
"div",
|
|
8975
|
+
{
|
|
8976
|
+
className: cn(
|
|
8977
|
+
"flex min-w-0 flex-1 items-center",
|
|
8978
|
+
fix ? "flex-row gap-(--cmp-pageHeader-gap)" : "flex-col items-start gap-(--cmp-pageHeader-plain-title-gap)",
|
|
8979
|
+
!hasBack && "pl-(--cmp-pageHeader-title-paddingLeft)"
|
|
8980
|
+
),
|
|
8981
|
+
children: [
|
|
8982
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-heading-lg min-w-0 truncate text-(--cmp-pageHeader-title-text)", children: title }),
|
|
8983
|
+
subText && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-body-md-default min-w-0 truncate text-(--cmp-pageHeader-subtitle-text)", children: subText })
|
|
8984
|
+
]
|
|
8985
|
+
}
|
|
8986
|
+
),
|
|
8987
|
+
slot && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto flex shrink-0 items-center", children: slot })
|
|
8988
|
+
]
|
|
8989
|
+
}
|
|
8990
|
+
);
|
|
8991
|
+
}),
|
|
8992
|
+
"SPageHeader"
|
|
8993
|
+
);
|
|
8663
8994
|
var MIN_CONTENT_WIDTH = `calc(var(${SLAYOUT_MIN_WIDTH_VAR}, 0px) - 100cqw + 100%)`;
|
|
8664
8995
|
var BACKGROUND_CLASS = {
|
|
8665
|
-
frame:
|
|
8666
|
-
neutral:
|
|
8667
|
-
screen:
|
|
8996
|
+
frame: "bg-[var(--sys-color-bg-frame)]",
|
|
8997
|
+
neutral: "bg-[var(--sys-color-bg-neutralLight)]",
|
|
8998
|
+
screen: "bg-[var(--sys-color-bg-screen)]"
|
|
8999
|
+
};
|
|
9000
|
+
var NATIVE_SCROLLBAR_BACKGROUND_CLASS = {
|
|
9001
|
+
frame: `${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_CLASS}`,
|
|
9002
|
+
neutral: `${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_WHITE_CLASS}`,
|
|
9003
|
+
screen: `${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_CLASS}`
|
|
9004
|
+
};
|
|
9005
|
+
var SCROLLBAR_SIZE = 12;
|
|
9006
|
+
var SCROLLBAR_MIN_THUMB_SIZE = 32;
|
|
9007
|
+
var getMetrics = (viewportSize, contentSize, scrollOffset) => {
|
|
9008
|
+
if (contentSize <= viewportSize) {
|
|
9009
|
+
return { visible: false, thumbSize: 0, thumbOffset: 0 };
|
|
9010
|
+
}
|
|
9011
|
+
const trackSize = viewportSize;
|
|
9012
|
+
const maxScrollOffset = contentSize - viewportSize;
|
|
9013
|
+
const thumbSize = Math.min(
|
|
9014
|
+
trackSize,
|
|
9015
|
+
Math.max(SCROLLBAR_MIN_THUMB_SIZE, viewportSize / contentSize * trackSize)
|
|
9016
|
+
);
|
|
9017
|
+
const maxThumbOffset = trackSize - thumbSize;
|
|
9018
|
+
const thumbOffset = maxScrollOffset > 0 ? scrollOffset / maxScrollOffset * maxThumbOffset : 0;
|
|
9019
|
+
return { visible: true, thumbSize, thumbOffset };
|
|
8668
9020
|
};
|
|
8669
|
-
var
|
|
9021
|
+
var setForwardedRef = (ref, node) => {
|
|
9022
|
+
if (typeof ref === "function") {
|
|
9023
|
+
ref(node);
|
|
9024
|
+
return;
|
|
9025
|
+
}
|
|
9026
|
+
if (ref) ref.current = node;
|
|
9027
|
+
};
|
|
9028
|
+
function SPageOverlayScrollbars({ scrollRef }) {
|
|
9029
|
+
const [vertical, setVertical] = react.useState({
|
|
9030
|
+
visible: false,
|
|
9031
|
+
thumbSize: 0,
|
|
9032
|
+
thumbOffset: 0
|
|
9033
|
+
});
|
|
9034
|
+
const [horizontal, setHorizontal] = react.useState({
|
|
9035
|
+
visible: false,
|
|
9036
|
+
thumbSize: 0,
|
|
9037
|
+
thumbOffset: 0
|
|
9038
|
+
});
|
|
9039
|
+
const update = react.useCallback(() => {
|
|
9040
|
+
const el = scrollRef.current;
|
|
9041
|
+
if (!el) return;
|
|
9042
|
+
setVertical(getMetrics(el.clientHeight, el.scrollHeight, el.scrollTop));
|
|
9043
|
+
setHorizontal(getMetrics(el.clientWidth, el.scrollWidth, el.scrollLeft));
|
|
9044
|
+
}, [scrollRef]);
|
|
9045
|
+
react.useEffect(() => {
|
|
9046
|
+
const el = scrollRef.current;
|
|
9047
|
+
if (!el) return;
|
|
9048
|
+
update();
|
|
9049
|
+
el.addEventListener("scroll", update, { passive: true });
|
|
9050
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(update);
|
|
9051
|
+
observer?.observe(el);
|
|
9052
|
+
if (el.firstElementChild) observer?.observe(el.firstElementChild);
|
|
9053
|
+
return () => {
|
|
9054
|
+
el.removeEventListener("scroll", update);
|
|
9055
|
+
observer?.disconnect();
|
|
9056
|
+
};
|
|
9057
|
+
}, [scrollRef, update]);
|
|
9058
|
+
const dragVertical = (startEvent) => {
|
|
9059
|
+
const el = scrollRef.current;
|
|
9060
|
+
if (!el || !vertical.visible) return;
|
|
9061
|
+
startEvent.preventDefault();
|
|
9062
|
+
startEvent.currentTarget.setPointerCapture(startEvent.pointerId);
|
|
9063
|
+
const startPointer = startEvent.clientY;
|
|
9064
|
+
const startScrollTop = el.scrollTop;
|
|
9065
|
+
const maxThumbOffset = el.clientHeight - vertical.thumbSize;
|
|
9066
|
+
const maxScrollTop = el.scrollHeight - el.clientHeight;
|
|
9067
|
+
if (maxThumbOffset <= 0 || maxScrollTop <= 0) return;
|
|
9068
|
+
const onPointerMove = (moveEvent) => {
|
|
9069
|
+
const delta = moveEvent.clientY - startPointer;
|
|
9070
|
+
el.scrollTop = startScrollTop + delta / maxThumbOffset * maxScrollTop;
|
|
9071
|
+
};
|
|
9072
|
+
const onPointerUp = () => {
|
|
9073
|
+
window.removeEventListener("pointermove", onPointerMove);
|
|
9074
|
+
window.removeEventListener("pointerup", onPointerUp);
|
|
9075
|
+
};
|
|
9076
|
+
window.addEventListener("pointermove", onPointerMove);
|
|
9077
|
+
window.addEventListener("pointerup", onPointerUp, { once: true });
|
|
9078
|
+
};
|
|
9079
|
+
const dragHorizontal = (startEvent) => {
|
|
9080
|
+
const el = scrollRef.current;
|
|
9081
|
+
if (!el || !horizontal.visible) return;
|
|
9082
|
+
startEvent.preventDefault();
|
|
9083
|
+
startEvent.currentTarget.setPointerCapture(startEvent.pointerId);
|
|
9084
|
+
const startPointer = startEvent.clientX;
|
|
9085
|
+
const startScrollLeft = el.scrollLeft;
|
|
9086
|
+
const maxThumbOffset = el.clientWidth - horizontal.thumbSize;
|
|
9087
|
+
const maxScrollLeft = el.scrollWidth - el.clientWidth;
|
|
9088
|
+
if (maxThumbOffset <= 0 || maxScrollLeft <= 0) return;
|
|
9089
|
+
const onPointerMove = (moveEvent) => {
|
|
9090
|
+
const delta = moveEvent.clientX - startPointer;
|
|
9091
|
+
el.scrollLeft = startScrollLeft + delta / maxThumbOffset * maxScrollLeft;
|
|
9092
|
+
};
|
|
9093
|
+
const onPointerUp = () => {
|
|
9094
|
+
window.removeEventListener("pointermove", onPointerMove);
|
|
9095
|
+
window.removeEventListener("pointerup", onPointerUp);
|
|
9096
|
+
};
|
|
9097
|
+
window.addEventListener("pointermove", onPointerMove);
|
|
9098
|
+
window.addEventListener("pointerup", onPointerUp, { once: true });
|
|
9099
|
+
};
|
|
9100
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9101
|
+
vertical.visible && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9102
|
+
"div",
|
|
9103
|
+
{
|
|
9104
|
+
"aria-hidden": "true",
|
|
9105
|
+
className: "pointer-events-none absolute bottom-0 right-0 top-0 z-[1] w-[12px]",
|
|
9106
|
+
style: { bottom: horizontal.visible ? SCROLLBAR_SIZE : 0 },
|
|
9107
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9108
|
+
"div",
|
|
9109
|
+
{
|
|
9110
|
+
className: "pointer-events-auto absolute right-[2px] w-[8px] cursor-default touch-none rounded-full bg-[var(--color-grey-45)]",
|
|
9111
|
+
style: {
|
|
9112
|
+
height: vertical.thumbSize,
|
|
9113
|
+
transform: `translateY(${vertical.thumbOffset}px)`
|
|
9114
|
+
},
|
|
9115
|
+
onPointerDown: dragVertical
|
|
9116
|
+
}
|
|
9117
|
+
)
|
|
9118
|
+
}
|
|
9119
|
+
),
|
|
9120
|
+
horizontal.visible && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9121
|
+
"div",
|
|
9122
|
+
{
|
|
9123
|
+
"aria-hidden": "true",
|
|
9124
|
+
className: "pointer-events-none absolute bottom-0 left-0 right-0 z-[1] h-[12px]",
|
|
9125
|
+
style: { right: vertical.visible ? SCROLLBAR_SIZE : 0 },
|
|
9126
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9127
|
+
"div",
|
|
9128
|
+
{
|
|
9129
|
+
className: "pointer-events-auto absolute bottom-[2px] h-[8px] cursor-default touch-none rounded-full bg-[var(--color-grey-45)]",
|
|
9130
|
+
style: {
|
|
9131
|
+
width: horizontal.thumbSize,
|
|
9132
|
+
transform: `translateX(${horizontal.thumbOffset}px)`
|
|
9133
|
+
},
|
|
9134
|
+
onPointerDown: dragHorizontal
|
|
9135
|
+
}
|
|
9136
|
+
)
|
|
9137
|
+
}
|
|
9138
|
+
)
|
|
9139
|
+
] });
|
|
9140
|
+
}
|
|
9141
|
+
var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
|
|
9142
|
+
background = "frame",
|
|
9143
|
+
scrollEndSpacing = true,
|
|
9144
|
+
overlayScrollbar = false,
|
|
9145
|
+
contentHeight = "auto",
|
|
9146
|
+
header,
|
|
9147
|
+
className,
|
|
9148
|
+
style,
|
|
9149
|
+
children,
|
|
9150
|
+
onScroll,
|
|
9151
|
+
...rest
|
|
9152
|
+
}, ref) {
|
|
8670
9153
|
const layout = react.useContext(SLayoutContext);
|
|
8671
9154
|
const gridStyle = layout?.header === "full" ? { gridArea: "page" } : void 0;
|
|
8672
|
-
|
|
9155
|
+
const scrollRef = react.useRef(null);
|
|
9156
|
+
const setMainRef = react.useCallback(
|
|
9157
|
+
(node) => {
|
|
9158
|
+
scrollRef.current = node;
|
|
9159
|
+
setForwardedRef(ref, node);
|
|
9160
|
+
},
|
|
9161
|
+
[ref]
|
|
9162
|
+
);
|
|
9163
|
+
const [scrolled, setScrolled] = react.useState(false);
|
|
9164
|
+
const handleScroll = (e) => {
|
|
9165
|
+
onScroll?.(e);
|
|
9166
|
+
if (header != null && !header.fix) setScrolled(e.currentTarget.scrollTop > 0);
|
|
9167
|
+
};
|
|
9168
|
+
const fill = contentHeight === "fill";
|
|
9169
|
+
const main = /* @__PURE__ */ jsxRuntime.jsx(
|
|
8673
9170
|
"main",
|
|
8674
9171
|
{
|
|
8675
|
-
ref,
|
|
9172
|
+
ref: setMainRef,
|
|
8676
9173
|
className: cn(
|
|
8677
9174
|
"box-border min-h-0 min-w-0 flex-1 overflow-auto p-[var(--cmp-pageBody-padding-default)]",
|
|
8678
|
-
|
|
8679
|
-
|
|
9175
|
+
overlayScrollbar && "h-full",
|
|
9176
|
+
!fill && scrollEndSpacing && "pb-[var(--cmp-pageBody-padding-scrollEnd)]",
|
|
9177
|
+
overlayScrollbar ? SCROLLBAR_HIDDEN_CLASS : `${SCROLLBAR_CLASS} ${NATIVE_SCROLLBAR_BACKGROUND_CLASS[background]}`,
|
|
8680
9178
|
BACKGROUND_CLASS[background],
|
|
8681
9179
|
className
|
|
8682
9180
|
),
|
|
8683
|
-
style: { ...gridStyle, ...style },
|
|
9181
|
+
style: header == null && !overlayScrollbar ? { ...gridStyle, ...style } : style,
|
|
9182
|
+
onScroll: handleScroll,
|
|
8684
9183
|
...rest,
|
|
8685
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minWidth: MIN_CONTENT_WIDTH }, children })
|
|
9184
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(fill && "h-full"), style: { minWidth: MIN_CONTENT_WIDTH }, children })
|
|
8686
9185
|
}
|
|
8687
9186
|
);
|
|
9187
|
+
if (!overlayScrollbar) {
|
|
9188
|
+
if (header == null) return main;
|
|
9189
|
+
return (
|
|
9190
|
+
// fix 가 아닌 헤더는 자기 배경이 투명이라(SPageHeader.tsx) 이 배경이 그대로 비친다.
|
|
9191
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9192
|
+
"div",
|
|
9193
|
+
{
|
|
9194
|
+
className: cn("flex min-h-0 min-w-0 flex-1 flex-col", BACKGROUND_CLASS[background]),
|
|
9195
|
+
style: gridStyle,
|
|
9196
|
+
children: [
|
|
9197
|
+
/* @__PURE__ */ jsxRuntime.jsx(SPageHeader, { ...header, scrolled }),
|
|
9198
|
+
main
|
|
9199
|
+
]
|
|
9200
|
+
}
|
|
9201
|
+
)
|
|
9202
|
+
);
|
|
9203
|
+
}
|
|
9204
|
+
if (header == null) {
|
|
9205
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9206
|
+
"div",
|
|
9207
|
+
{
|
|
9208
|
+
className: cn(
|
|
9209
|
+
"relative min-h-0 min-w-0 flex-1 overflow-hidden",
|
|
9210
|
+
BACKGROUND_CLASS[background]
|
|
9211
|
+
),
|
|
9212
|
+
style: gridStyle,
|
|
9213
|
+
children: [
|
|
9214
|
+
main,
|
|
9215
|
+
/* @__PURE__ */ jsxRuntime.jsx(SPageOverlayScrollbars, { scrollRef })
|
|
9216
|
+
]
|
|
9217
|
+
}
|
|
9218
|
+
);
|
|
9219
|
+
}
|
|
9220
|
+
return (
|
|
9221
|
+
// fix 가 아닌 헤더는 자기 배경이 투명이라(SPageHeader.tsx) 이 배경이 그대로 비친다 —
|
|
9222
|
+
// 그래서 SPage 의 background 를 main 뿐 아니라 여기에도 칠한다(스크롤바 관련 클래스는
|
|
9223
|
+
// 스크롤 요소가 아닌 여기서는 그냥 무시된다). fix 헤더는 자체 흰 배경이 덮으므로 무관하다.
|
|
9224
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9225
|
+
"div",
|
|
9226
|
+
{
|
|
9227
|
+
className: cn("flex min-h-0 min-w-0 flex-1 flex-col", BACKGROUND_CLASS[background]),
|
|
9228
|
+
style: gridStyle,
|
|
9229
|
+
children: [
|
|
9230
|
+
/* @__PURE__ */ jsxRuntime.jsx(SPageHeader, { ...header, scrolled }),
|
|
9231
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative min-h-0 min-w-0 flex-1 overflow-hidden", children: [
|
|
9232
|
+
main,
|
|
9233
|
+
/* @__PURE__ */ jsxRuntime.jsx(SPageOverlayScrollbars, { scrollRef })
|
|
9234
|
+
] })
|
|
9235
|
+
]
|
|
9236
|
+
}
|
|
9237
|
+
)
|
|
9238
|
+
);
|
|
8688
9239
|
});
|
|
8689
9240
|
|
|
8690
9241
|
// src/components/SPage/page.config.ts
|
|
8691
9242
|
var PAGE_BACKGROUNDS = ["frame", "neutral", "screen"];
|
|
9243
|
+
var PAGE_CONTENT_HEIGHTS = ["auto", "fill"];
|
|
8692
9244
|
|
|
8693
9245
|
// src/components/STabs/tabs.config.ts
|
|
8694
|
-
var TAB_MAIN_SIZE = {
|
|
8695
|
-
md: { height: 36, paddingX: 24 },
|
|
8696
|
-
lg: { height: 44, paddingX: 32 }
|
|
8697
|
-
};
|
|
9246
|
+
var TAB_MAIN_SIZE = { height: 36, paddingX: 24 };
|
|
8698
9247
|
var TAB_TYPOGRAPHY = { fontSize: 12, lineHeight: 20 };
|
|
8699
9248
|
var TAB_MAIN_COLORS = {
|
|
8700
9249
|
selected: {
|
|
@@ -8716,13 +9265,11 @@ function STabs({
|
|
|
8716
9265
|
value,
|
|
8717
9266
|
tabs,
|
|
8718
9267
|
onValueChange,
|
|
8719
|
-
size = "md",
|
|
8720
9268
|
isSub = false,
|
|
8721
9269
|
vertical = false,
|
|
8722
9270
|
className,
|
|
8723
9271
|
style
|
|
8724
9272
|
}) {
|
|
8725
|
-
const s = TAB_MAIN_SIZE[size];
|
|
8726
9273
|
const blue = TAB_MAIN_COLORS.selected.border;
|
|
8727
9274
|
const isVertical = isSub && vertical;
|
|
8728
9275
|
const tabRefs = react.useRef([]);
|
|
@@ -8763,8 +9310,8 @@ function STabs({
|
|
|
8763
9310
|
const border = selected ? TAB_MAIN_COLORS.selected.border : TAB_MAIN_COLORS.default.border;
|
|
8764
9311
|
const selectedBg = TAB_MAIN_COLORS.selected.bg;
|
|
8765
9312
|
tabStyle = {
|
|
8766
|
-
height:
|
|
8767
|
-
padding: `0 ${
|
|
9313
|
+
height: TAB_MAIN_SIZE.height,
|
|
9314
|
+
padding: `0 ${TAB_MAIN_SIZE.paddingX}px`,
|
|
8768
9315
|
fontSize: TAB_TYPOGRAPHY.fontSize,
|
|
8769
9316
|
lineHeight: `${TAB_TYPOGRAPHY.lineHeight}px`,
|
|
8770
9317
|
background: selected ? TAB_MAIN_COLORS.selected.bg : TAB_MAIN_COLORS.default.bg,
|
|
@@ -9506,6 +10053,7 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
|
|
|
9506
10053
|
readOnly = false,
|
|
9507
10054
|
width,
|
|
9508
10055
|
minWidth,
|
|
10056
|
+
maxWidth,
|
|
9509
10057
|
multiline = false,
|
|
9510
10058
|
borderless = false,
|
|
9511
10059
|
children,
|
|
@@ -9541,7 +10089,10 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
|
|
|
9541
10089
|
const resolvedSuccess = status === "pass";
|
|
9542
10090
|
const showError = resolvedError && errorMessage !== "";
|
|
9543
10091
|
const interactive = !disabled && !readOnly;
|
|
9544
|
-
const
|
|
10092
|
+
const isPercentWidth = typeof width === "string" && width.trim().endsWith("%");
|
|
10093
|
+
const hug = cssLen(width) !== void 0 && !isPercentWidth;
|
|
10094
|
+
const addonWidth = effectiveAddonLabel !== "" ? cssLen(labelWidth) : void 0;
|
|
10095
|
+
const resolvedMaxWidth = cssLen(maxWidth) === void 0 || effectiveAddonLabel === "" ? cssLen(maxWidth) : addonWidth ? `calc(${cssLen(maxWidth)} + ${addonWidth})` : void 0;
|
|
9545
10096
|
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)";
|
|
9546
10097
|
const bgColor = borderless ? "transparent" : disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
|
|
9547
10098
|
const textColor = disabled ? "var(--color-grey-65)" : readOnly ? "var(--sys-color-field-text-readOnly)" : "var(--sys-color-field-text-default)";
|
|
@@ -9597,8 +10148,12 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
|
|
|
9597
10148
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9598
10149
|
"div",
|
|
9599
10150
|
{
|
|
9600
|
-
className: cn("flex min-w-0 flex-col", !hug && "flex-1"),
|
|
9601
|
-
style: {
|
|
10151
|
+
className: cn("flex min-w-0 flex-col", !hug && !isPercentWidth && "flex-1"),
|
|
10152
|
+
style: {
|
|
10153
|
+
width: cssLen(width),
|
|
10154
|
+
minWidth: cssLen(minWidth),
|
|
10155
|
+
maxWidth: resolvedMaxWidth
|
|
10156
|
+
},
|
|
9602
10157
|
children: [
|
|
9603
10158
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9604
10159
|
"div",
|
|
@@ -10353,6 +10908,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
10353
10908
|
height,
|
|
10354
10909
|
stickyColumn,
|
|
10355
10910
|
radius = "default",
|
|
10911
|
+
bordered = true,
|
|
10356
10912
|
noDataLabel = "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
10357
10913
|
noDataSlot,
|
|
10358
10914
|
isLoading = false,
|
|
@@ -10611,7 +11167,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
10611
11167
|
};
|
|
10612
11168
|
const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[var(--cmp-table-radius)] rounded-t-none" : "rounded-[var(--cmp-table-radius)]";
|
|
10613
11169
|
const cellPadY = dense ? "var(--cmp-table-body-paddingY-dense)" : "var(--cmp-table-body-paddingY-default)";
|
|
10614
|
-
const
|
|
11170
|
+
const cellPadXOf = (col) => col.contentType === "control" ? "var(--cmp-table-body-paddingX-default)" : "var(--cmp-table-body-paddingX-wide)";
|
|
10615
11171
|
const rowH = dense ? "var(--cmp-table-body-dense-height)" : "var(--cmp-table-body-default-height)";
|
|
10616
11172
|
const totalColSpan = visibleCols.length + (selectable ? 1 : 0);
|
|
10617
11173
|
const stickyInfo = (i) => {
|
|
@@ -10665,7 +11221,8 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
10665
11221
|
// 만으로는 스태킹 컨텍스트가 생기지 않아, 모달 안에 들어가면 30·31이 모달 Content
|
|
10666
11222
|
// 레벨까지 올라가 같은 컨텍스트의 floating portal 밴드(z-2)를 덮는다.
|
|
10667
11223
|
// 자손은 이미 overflow-hidden으로 클리핑되므로 테이블 내부 순서는 달라지지 않는다.
|
|
10668
|
-
"bg-white relative isolate flex flex-col overflow-hidden
|
|
11224
|
+
"bg-white relative isolate flex flex-col overflow-hidden",
|
|
11225
|
+
bordered && "border border-solid border-[color:var(--cmp-table-border-color)]",
|
|
10669
11226
|
// height가 없으면 루트가 받은 높이를 끝까지 채운다. 호스트가 className으로
|
|
10670
11227
|
// `flex-1 min-h-0` 등을 줘 루트 높이가 확정된 경우, 행이 적어도 테두리 박스가
|
|
10671
11228
|
// 남은 영역을 그대로 차지한다. basis는 auto로 둬 높이가 확정되지 않은
|
|
@@ -10835,9 +11392,10 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
10835
11392
|
stickyShadowClass(i),
|
|
10836
11393
|
typeof col.tdClass === "function" ? col.tdClass(row) : col.tdClass
|
|
10837
11394
|
);
|
|
11395
|
+
const tdPadX = cellPadXOf(col);
|
|
10838
11396
|
const tdStyle = {
|
|
10839
|
-
paddingLeft:
|
|
10840
|
-
paddingRight:
|
|
11397
|
+
paddingLeft: tdPadX,
|
|
11398
|
+
paddingRight: tdPadX,
|
|
10841
11399
|
paddingTop: cellPadY,
|
|
10842
11400
|
paddingBottom: cellPadY,
|
|
10843
11401
|
textAlign: col.align ?? "left",
|
|
@@ -10890,19 +11448,29 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
10890
11448
|
// SPagination은 전체 폭 기준 중앙, rows-per-page SSelect는 우측에 absolute 배치해 중앙 정렬을 유지한다.
|
|
10891
11449
|
// 루트 높이가 확정된 경우(테이블이 남은 영역을 채우는 배치) 페이지네이션 바가
|
|
10892
11450
|
// 눌리지 않도록 shrink-0으로 48px를 보장한다.
|
|
10893
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10894
|
-
|
|
10895
|
-
|
|
10896
|
-
|
|
10897
|
-
|
|
10898
|
-
|
|
10899
|
-
|
|
10900
|
-
|
|
10901
|
-
|
|
10902
|
-
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
|
|
11451
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
11452
|
+
"div",
|
|
11453
|
+
{
|
|
11454
|
+
className: cn(
|
|
11455
|
+
"relative flex h-[48px] shrink-0 items-center justify-center rounded-[var(--cmp-table-radius)] bg-[var(--color-grey-05)]",
|
|
11456
|
+
// 테두리를 끄면 겹칠 대상이 없어진다 — -mt-px 를 남기면 1px 어긋남만 생긴다.
|
|
11457
|
+
bordered && "-mt-px border border-solid border-[color:var(--cmp-table-border-color)]"
|
|
11458
|
+
),
|
|
11459
|
+
children: [
|
|
11460
|
+
/* @__PURE__ */ jsxRuntime.jsx(SPagination, { currentPage: displayPage, lastPage, onPageChange: changePage }),
|
|
11461
|
+
useRowsPerPageSelect && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-[10px] top-1/2 -translate-y-1/2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11462
|
+
SSelect2,
|
|
11463
|
+
{
|
|
11464
|
+
options: rowsPerPageOption,
|
|
11465
|
+
value: useInternalPagination ? innerRowsPerPage : pagination?.rowsPerPage,
|
|
11466
|
+
emitValue: true,
|
|
11467
|
+
onValueChange: (v) => changeRowsPerPage(Number(v)),
|
|
11468
|
+
width: 128
|
|
11469
|
+
}
|
|
11470
|
+
) })
|
|
11471
|
+
]
|
|
11472
|
+
}
|
|
11473
|
+
)
|
|
10906
11474
|
]
|
|
10907
11475
|
}
|
|
10908
11476
|
);
|
|
@@ -10965,27 +11533,88 @@ var STableBar = /* @__PURE__ */ react.forwardRef(function STableBar2({ total, se
|
|
|
10965
11533
|
|
|
10966
11534
|
// src/lib/autofill.ts
|
|
10967
11535
|
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]";
|
|
10968
|
-
var
|
|
10969
|
-
|
|
10970
|
-
|
|
10971
|
-
|
|
10972
|
-
|
|
10973
|
-
|
|
10974
|
-
|
|
10975
|
-
|
|
10976
|
-
|
|
10977
|
-
|
|
10978
|
-
|
|
10979
|
-
|
|
10980
|
-
|
|
10981
|
-
|
|
10982
|
-
|
|
10983
|
-
|
|
10984
|
-
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
11536
|
+
var HIDE_DELAY_MS2 = 100;
|
|
11537
|
+
function mergeRefs(...refs) {
|
|
11538
|
+
return (node) => {
|
|
11539
|
+
for (const ref of refs) {
|
|
11540
|
+
if (!ref) continue;
|
|
11541
|
+
if (typeof ref === "function") ref(node);
|
|
11542
|
+
else ref.current = node;
|
|
11543
|
+
}
|
|
11544
|
+
};
|
|
11545
|
+
}
|
|
11546
|
+
function useTruncatedValueTooltip({
|
|
11547
|
+
enabled,
|
|
11548
|
+
text
|
|
11549
|
+
}) {
|
|
11550
|
+
const portalContainer = usePortalContainer();
|
|
11551
|
+
const elRef = react.useRef(null);
|
|
11552
|
+
const [open, setOpen] = react.useState(false);
|
|
11553
|
+
const hideTimer = react.useRef(void 0);
|
|
11554
|
+
const cancelHide = react.useCallback(() => {
|
|
11555
|
+
if (hideTimer.current) {
|
|
11556
|
+
clearTimeout(hideTimer.current);
|
|
11557
|
+
hideTimer.current = void 0;
|
|
11558
|
+
}
|
|
11559
|
+
}, []);
|
|
11560
|
+
const startHide = react.useCallback(() => {
|
|
11561
|
+
cancelHide();
|
|
11562
|
+
hideTimer.current = setTimeout(() => setOpen(false), HIDE_DELAY_MS2);
|
|
11563
|
+
}, [cancelHide]);
|
|
11564
|
+
const onMouseEnter = react.useCallback(() => {
|
|
11565
|
+
cancelHide();
|
|
11566
|
+
const el = elRef.current;
|
|
11567
|
+
if (!el) return;
|
|
11568
|
+
if (el.scrollWidth - el.clientWidth > 1) setOpen(true);
|
|
11569
|
+
}, [cancelHide]);
|
|
11570
|
+
react.useEffect(() => {
|
|
11571
|
+
if (!enabled || text === "") setOpen(false);
|
|
11572
|
+
}, [enabled, text]);
|
|
11573
|
+
react.useEffect(() => cancelHide, [cancelHide]);
|
|
11574
|
+
const active = enabled && text !== "";
|
|
11575
|
+
return {
|
|
11576
|
+
valueRef: elRef,
|
|
11577
|
+
onMouseEnter: active ? onMouseEnter : cancelHide,
|
|
11578
|
+
onMouseLeave: active ? startHide : cancelHide,
|
|
11579
|
+
tooltip: active ? /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: setOpen, children: [
|
|
11580
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { virtualRef: elRef }),
|
|
11581
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11582
|
+
RPopover10__namespace.Content,
|
|
11583
|
+
{
|
|
11584
|
+
side: "top",
|
|
11585
|
+
sideOffset: 4,
|
|
11586
|
+
"aria-hidden": true,
|
|
11587
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
11588
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
11589
|
+
onMouseEnter: cancelHide,
|
|
11590
|
+
onMouseLeave: startHide,
|
|
11591
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
|
|
11592
|
+
}
|
|
11593
|
+
) })
|
|
11594
|
+
] }) : null
|
|
11595
|
+
};
|
|
11596
|
+
}
|
|
11597
|
+
var FONT = {
|
|
11598
|
+
sm: { fontSize: 12, lineHeight: 20, paddingX: "var(--cmp-textinput-sm-paddingX)" },
|
|
11599
|
+
md: { fontSize: 14, lineHeight: 24, paddingX: "var(--cmp-textinput-md-paddingX)" }
|
|
11600
|
+
};
|
|
11601
|
+
var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
|
|
11602
|
+
value,
|
|
11603
|
+
onValueChange,
|
|
11604
|
+
onChange,
|
|
11605
|
+
type = "text",
|
|
11606
|
+
size = "sm",
|
|
11607
|
+
icon,
|
|
11608
|
+
iconColor,
|
|
11609
|
+
prefix,
|
|
11610
|
+
suffix,
|
|
11611
|
+
clearable = false,
|
|
11612
|
+
rules,
|
|
11613
|
+
status,
|
|
11614
|
+
focused,
|
|
11615
|
+
hovered,
|
|
11616
|
+
inputClass,
|
|
11617
|
+
inputStyle,
|
|
10989
11618
|
label,
|
|
10990
11619
|
labelWidth,
|
|
10991
11620
|
labelTooltip,
|
|
@@ -11022,6 +11651,10 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
|
|
|
11022
11651
|
const resolvedError = error || ruleError !== "";
|
|
11023
11652
|
const resolvedErrorMessage = ruleError !== "" ? ruleError : errorMessage;
|
|
11024
11653
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
11654
|
+
const valueTooltip = useTruncatedValueTooltip({
|
|
11655
|
+
enabled: readOnly && !disabled,
|
|
11656
|
+
text: String(value ?? "")
|
|
11657
|
+
});
|
|
11025
11658
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
11026
11659
|
SField,
|
|
11027
11660
|
{
|
|
@@ -11058,11 +11691,11 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
|
|
|
11058
11691
|
lineHeight: `${f.lineHeight}px`
|
|
11059
11692
|
},
|
|
11060
11693
|
children: [
|
|
11061
|
-
prefix != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: prefix }),
|
|
11694
|
+
prefix != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-shrink-0 items-center", children: prefix }),
|
|
11062
11695
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11063
11696
|
"input",
|
|
11064
11697
|
{
|
|
11065
|
-
ref,
|
|
11698
|
+
ref: mergeRefs(ref, valueTooltip.valueRef),
|
|
11066
11699
|
type: inputType,
|
|
11067
11700
|
value: value ?? "",
|
|
11068
11701
|
disabled,
|
|
@@ -11087,10 +11720,19 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
|
|
|
11087
11720
|
color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--sys-color-field-text-default)",
|
|
11088
11721
|
...inputStyle
|
|
11089
11722
|
},
|
|
11090
|
-
...rest
|
|
11723
|
+
...rest,
|
|
11724
|
+
onMouseEnter: (e) => {
|
|
11725
|
+
rest.onMouseEnter?.(e);
|
|
11726
|
+
valueTooltip.onMouseEnter();
|
|
11727
|
+
},
|
|
11728
|
+
onMouseLeave: (e) => {
|
|
11729
|
+
rest.onMouseLeave?.(e);
|
|
11730
|
+
valueTooltip.onMouseLeave();
|
|
11731
|
+
}
|
|
11091
11732
|
}
|
|
11092
11733
|
),
|
|
11093
|
-
|
|
11734
|
+
valueTooltip.tooltip,
|
|
11735
|
+
suffix != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-shrink-0 items-center", children: suffix }),
|
|
11094
11736
|
clearable && hasValue && !disabled && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11095
11737
|
SGhostButton,
|
|
11096
11738
|
{
|
|
@@ -11323,8 +11965,10 @@ var SNumberInput = /* @__PURE__ */ react.forwardRef(function SNumberInput2({
|
|
|
11323
11965
|
const [display, setDisplay] = react.useState(() => formatWithCommas(numValue));
|
|
11324
11966
|
const [ruleError, setRuleError] = react.useState("");
|
|
11325
11967
|
const innerRef = react.useRef(null);
|
|
11968
|
+
const valueTooltip = useTruncatedValueTooltip({ enabled: readOnly && !disabled, text: display });
|
|
11326
11969
|
const setRefs2 = (el) => {
|
|
11327
11970
|
innerRef.current = el;
|
|
11971
|
+
valueTooltip.valueRef.current = el;
|
|
11328
11972
|
if (typeof ref === "function") ref(el);
|
|
11329
11973
|
else if (ref) ref.current = el;
|
|
11330
11974
|
};
|
|
@@ -11538,9 +12182,12 @@ var SNumberInput = /* @__PURE__ */ react.forwardRef(function SNumberInput2({
|
|
|
11538
12182
|
textAlign: useButton ? "center" : "right",
|
|
11539
12183
|
color: disabled ? "var(--cmp-numberInput-text-disabled)" : "var(--cmp-numberInput-text-default)",
|
|
11540
12184
|
...inputStyle
|
|
11541
|
-
}
|
|
12185
|
+
},
|
|
12186
|
+
onMouseEnter: valueTooltip.onMouseEnter,
|
|
12187
|
+
onMouseLeave: valueTooltip.onMouseLeave
|
|
11542
12188
|
}
|
|
11543
12189
|
),
|
|
12190
|
+
valueTooltip.tooltip,
|
|
11544
12191
|
inputSuffix !== "" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", style: { color: affixColor }, children: inputSuffix }),
|
|
11545
12192
|
useButton && stepper("inc")
|
|
11546
12193
|
]
|
|
@@ -11919,12 +12566,275 @@ function SCalendar({
|
|
|
11919
12566
|
}
|
|
11920
12567
|
);
|
|
11921
12568
|
}
|
|
12569
|
+
var DATEPICKER_MODE_LIST_HEIGHT = 240;
|
|
12570
|
+
var DATEPICKER_MODE_ITEM_HEIGHT = 28;
|
|
12571
|
+
var YEAR_LIST_EDGE_BUFFER = 24;
|
|
12572
|
+
var YEAR_LIST_EXPAND_SIZE = 80;
|
|
12573
|
+
var MONTHS = Array.from({ length: 12 }, (_, i) => i + 1);
|
|
12574
|
+
var getTodayParts = () => {
|
|
12575
|
+
const today = /* @__PURE__ */ new Date();
|
|
12576
|
+
return {
|
|
12577
|
+
year: today.getFullYear(),
|
|
12578
|
+
month: today.getMonth() + 1
|
|
12579
|
+
};
|
|
12580
|
+
};
|
|
12581
|
+
var parseYear = (value) => {
|
|
12582
|
+
const year = Number(value?.slice(0, 4));
|
|
12583
|
+
return Number.isFinite(year) && year > 0 ? year : void 0;
|
|
12584
|
+
};
|
|
12585
|
+
var parseMonth = (value) => {
|
|
12586
|
+
const month = Number(value?.slice(5, 7));
|
|
12587
|
+
return Number.isFinite(month) && month >= 1 && month <= 12 ? month : void 0;
|
|
12588
|
+
};
|
|
12589
|
+
var formatMonthValue = (year, month) => `${year}-${String(month).padStart(2, "0")}`;
|
|
12590
|
+
var isYearDisabled = (year, selectable) => {
|
|
12591
|
+
if (!selectable) return false;
|
|
12592
|
+
const [start, end] = selectable;
|
|
12593
|
+
if (start !== "" && year < Number(start.slice(0, 4))) return true;
|
|
12594
|
+
if (end !== "" && year > Number(end.slice(0, 4))) return true;
|
|
12595
|
+
return false;
|
|
12596
|
+
};
|
|
12597
|
+
var isMonthDisabled = (year, month, selectable) => {
|
|
12598
|
+
if (!selectable) return false;
|
|
12599
|
+
const value = formatMonthValue(year, month);
|
|
12600
|
+
const [start, end] = selectable;
|
|
12601
|
+
if (start !== "" && value < start.slice(0, 7)) return true;
|
|
12602
|
+
if (end !== "" && value > end.slice(0, 7)) return true;
|
|
12603
|
+
return false;
|
|
12604
|
+
};
|
|
12605
|
+
function YearWheel({ value, anchorYear, selectable, onCommit }) {
|
|
12606
|
+
const listRef = react.useRef(null);
|
|
12607
|
+
const syncingScrollRef = react.useRef(false);
|
|
12608
|
+
const anchorYearRef = react.useRef(anchorYear);
|
|
12609
|
+
const [range, setRange] = react.useState(() => ({
|
|
12610
|
+
start: anchorYear - YEAR_LIST_EXPAND_SIZE,
|
|
12611
|
+
end: anchorYear + YEAR_LIST_EXPAND_SIZE
|
|
12612
|
+
}));
|
|
12613
|
+
const rangeStartRef = react.useRef(range.start);
|
|
12614
|
+
rangeStartRef.current = range.start;
|
|
12615
|
+
const years = Array.from({ length: range.end - range.start + 1 }, (_, i) => range.start + i);
|
|
12616
|
+
react.useLayoutEffect(() => {
|
|
12617
|
+
const list = listRef.current;
|
|
12618
|
+
if (!list) return;
|
|
12619
|
+
const index = anchorYearRef.current - rangeStartRef.current;
|
|
12620
|
+
syncingScrollRef.current = true;
|
|
12621
|
+
list.scrollTop = index * DATEPICKER_MODE_ITEM_HEIGHT;
|
|
12622
|
+
requestAnimationFrame(() => {
|
|
12623
|
+
syncingScrollRef.current = false;
|
|
12624
|
+
});
|
|
12625
|
+
}, []);
|
|
12626
|
+
const handleScroll = () => {
|
|
12627
|
+
const list = listRef.current;
|
|
12628
|
+
if (!list) return;
|
|
12629
|
+
if (syncingScrollRef.current) return;
|
|
12630
|
+
if (list.scrollTop < DATEPICKER_MODE_ITEM_HEIGHT * YEAR_LIST_EDGE_BUFFER) {
|
|
12631
|
+
const previousHeight = list.scrollHeight;
|
|
12632
|
+
setRange((current) => ({
|
|
12633
|
+
start: current.start - YEAR_LIST_EXPAND_SIZE,
|
|
12634
|
+
end: current.end
|
|
12635
|
+
}));
|
|
12636
|
+
requestAnimationFrame(() => {
|
|
12637
|
+
if (!listRef.current) return;
|
|
12638
|
+
syncingScrollRef.current = true;
|
|
12639
|
+
listRef.current.scrollTop += listRef.current.scrollHeight - previousHeight;
|
|
12640
|
+
requestAnimationFrame(() => {
|
|
12641
|
+
syncingScrollRef.current = false;
|
|
12642
|
+
});
|
|
12643
|
+
});
|
|
12644
|
+
return;
|
|
12645
|
+
}
|
|
12646
|
+
if (list.scrollHeight - list.scrollTop - list.clientHeight < DATEPICKER_MODE_ITEM_HEIGHT * YEAR_LIST_EDGE_BUFFER) {
|
|
12647
|
+
setRange((current) => ({
|
|
12648
|
+
start: current.start,
|
|
12649
|
+
end: current.end + YEAR_LIST_EXPAND_SIZE
|
|
12650
|
+
}));
|
|
12651
|
+
}
|
|
12652
|
+
};
|
|
12653
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full overflow-hidden bg-[var(--cmp-datepicker-mode-bg)]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12654
|
+
"div",
|
|
12655
|
+
{
|
|
12656
|
+
ref: listRef,
|
|
12657
|
+
role: "listbox",
|
|
12658
|
+
"aria-label": "year",
|
|
12659
|
+
className: "h-full overflow-y-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
12660
|
+
style: {
|
|
12661
|
+
paddingTop: `calc((${DATEPICKER_MODE_LIST_HEIGHT}px - ${DATEPICKER_MODE_ITEM_HEIGHT}px) / 2)`,
|
|
12662
|
+
paddingBottom: `calc((${DATEPICKER_MODE_LIST_HEIGHT}px - ${DATEPICKER_MODE_ITEM_HEIGHT}px) / 2)`
|
|
12663
|
+
},
|
|
12664
|
+
onScroll: handleScroll,
|
|
12665
|
+
children: years.map((year) => {
|
|
12666
|
+
const selected = year === value;
|
|
12667
|
+
const disabled = isYearDisabled(year, selectable);
|
|
12668
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12669
|
+
"button",
|
|
12670
|
+
{
|
|
12671
|
+
type: "button",
|
|
12672
|
+
role: "option",
|
|
12673
|
+
"aria-selected": selected,
|
|
12674
|
+
disabled,
|
|
12675
|
+
className: cn(
|
|
12676
|
+
"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]",
|
|
12677
|
+
disabled && "cursor-not-allowed bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-disabled)]",
|
|
12678
|
+
!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)]",
|
|
12679
|
+
!disabled && selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-bold text-[color:var(--cmp-datepicker-mode-item-content-selected)]"
|
|
12680
|
+
),
|
|
12681
|
+
onClick: () => !disabled && onCommit(year),
|
|
12682
|
+
children: year
|
|
12683
|
+
},
|
|
12684
|
+
year
|
|
12685
|
+
);
|
|
12686
|
+
})
|
|
12687
|
+
}
|
|
12688
|
+
) });
|
|
12689
|
+
}
|
|
12690
|
+
function SDatePickerYearListbox({
|
|
12691
|
+
value,
|
|
12692
|
+
anchorYear,
|
|
12693
|
+
selectable,
|
|
12694
|
+
onValueChange,
|
|
12695
|
+
className,
|
|
12696
|
+
style
|
|
12697
|
+
}) {
|
|
12698
|
+
const today = getTodayParts();
|
|
12699
|
+
const resolvedAnchorYear = anchorYear ?? today.year;
|
|
12700
|
+
const [year, setYear] = react.useState(() => parseYear(value) ?? resolvedAnchorYear);
|
|
12701
|
+
react.useEffect(() => {
|
|
12702
|
+
setYear(parseYear(value) ?? resolvedAnchorYear);
|
|
12703
|
+
}, [value, resolvedAnchorYear]);
|
|
12704
|
+
const commitYear = (nextYear) => {
|
|
12705
|
+
setYear(nextYear);
|
|
12706
|
+
onValueChange?.(String(nextYear));
|
|
12707
|
+
};
|
|
12708
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12709
|
+
"div",
|
|
12710
|
+
{
|
|
12711
|
+
className: cn(
|
|
12712
|
+
"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",
|
|
12713
|
+
className
|
|
12714
|
+
),
|
|
12715
|
+
style,
|
|
12716
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12717
|
+
YearWheel,
|
|
12718
|
+
{
|
|
12719
|
+
value: year,
|
|
12720
|
+
anchorYear: resolvedAnchorYear,
|
|
12721
|
+
selectable,
|
|
12722
|
+
onCommit: commitYear
|
|
12723
|
+
}
|
|
12724
|
+
)
|
|
12725
|
+
}
|
|
12726
|
+
);
|
|
12727
|
+
}
|
|
12728
|
+
function MonthWheel({ year, value, selectable, onCommit }) {
|
|
12729
|
+
const listRef = react.useRef(null);
|
|
12730
|
+
const initialValueRef = react.useRef(value);
|
|
12731
|
+
react.useLayoutEffect(() => {
|
|
12732
|
+
const list = listRef.current;
|
|
12733
|
+
if (!list) return;
|
|
12734
|
+
list.scrollTop = Math.max(
|
|
12735
|
+
0,
|
|
12736
|
+
(initialValueRef.current - 1) * DATEPICKER_MODE_ITEM_HEIGHT - (list.clientHeight - DATEPICKER_MODE_ITEM_HEIGHT) / 2
|
|
12737
|
+
);
|
|
12738
|
+
}, []);
|
|
12739
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full overflow-hidden bg-[var(--cmp-datepicker-mode-bg)]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12740
|
+
"div",
|
|
12741
|
+
{
|
|
12742
|
+
ref: listRef,
|
|
12743
|
+
role: "listbox",
|
|
12744
|
+
"aria-label": "month",
|
|
12745
|
+
className: "h-full overflow-y-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
12746
|
+
children: MONTHS.map((month) => {
|
|
12747
|
+
const selected = month === value;
|
|
12748
|
+
const disabled = isMonthDisabled(year, month, selectable);
|
|
12749
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12750
|
+
"button",
|
|
12751
|
+
{
|
|
12752
|
+
type: "button",
|
|
12753
|
+
role: "option",
|
|
12754
|
+
"aria-selected": selected,
|
|
12755
|
+
disabled,
|
|
12756
|
+
className: cn(
|
|
12757
|
+
"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]",
|
|
12758
|
+
disabled && "cursor-not-allowed bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-disabled)]",
|
|
12759
|
+
!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)]",
|
|
12760
|
+
!disabled && selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-bold text-[color:var(--cmp-datepicker-mode-item-content-selected)]"
|
|
12761
|
+
),
|
|
12762
|
+
onClick: () => !disabled && onCommit(month),
|
|
12763
|
+
children: [
|
|
12764
|
+
month,
|
|
12765
|
+
"\uC6D4"
|
|
12766
|
+
]
|
|
12767
|
+
},
|
|
12768
|
+
month
|
|
12769
|
+
);
|
|
12770
|
+
})
|
|
12771
|
+
}
|
|
12772
|
+
) });
|
|
12773
|
+
}
|
|
12774
|
+
function SDatePickerMonthListbox({
|
|
12775
|
+
value,
|
|
12776
|
+
anchorYear,
|
|
12777
|
+
selectable,
|
|
12778
|
+
onValueChange,
|
|
12779
|
+
onMonthSelect,
|
|
12780
|
+
className,
|
|
12781
|
+
style
|
|
12782
|
+
}) {
|
|
12783
|
+
const today = getTodayParts();
|
|
12784
|
+
const resolvedAnchorYear = anchorYear ?? today.year;
|
|
12785
|
+
const [year, setYear] = react.useState(() => parseYear(value) ?? resolvedAnchorYear);
|
|
12786
|
+
const [month, setMonth] = react.useState(() => parseMonth(value) ?? today.month);
|
|
12787
|
+
react.useEffect(() => {
|
|
12788
|
+
setYear(parseYear(value) ?? resolvedAnchorYear);
|
|
12789
|
+
setMonth(parseMonth(value) ?? today.month);
|
|
12790
|
+
}, [value, resolvedAnchorYear, today.month]);
|
|
12791
|
+
const commitYear = (nextYear) => {
|
|
12792
|
+
setYear(nextYear);
|
|
12793
|
+
onValueChange?.(formatMonthValue(nextYear, month));
|
|
12794
|
+
};
|
|
12795
|
+
const commitMonth = (nextMonth) => {
|
|
12796
|
+
setMonth(nextMonth);
|
|
12797
|
+
const nextValue = formatMonthValue(year, nextMonth);
|
|
12798
|
+
onValueChange?.(nextValue);
|
|
12799
|
+
onMonthSelect?.(nextValue);
|
|
12800
|
+
};
|
|
12801
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12802
|
+
"div",
|
|
12803
|
+
{
|
|
12804
|
+
className: cn(
|
|
12805
|
+
"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",
|
|
12806
|
+
className
|
|
12807
|
+
),
|
|
12808
|
+
style,
|
|
12809
|
+
children: [
|
|
12810
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 w-[var(--cmp-datepicker-mode-yearMonth-column-width)]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12811
|
+
YearWheel,
|
|
12812
|
+
{
|
|
12813
|
+
value: year,
|
|
12814
|
+
anchorYear: resolvedAnchorYear,
|
|
12815
|
+
selectable,
|
|
12816
|
+
onCommit: commitYear
|
|
12817
|
+
}
|
|
12818
|
+
) }),
|
|
12819
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12820
|
+
"div",
|
|
12821
|
+
{
|
|
12822
|
+
"aria-hidden": true,
|
|
12823
|
+
className: "w-[var(--border-width-1)] self-stretch bg-[var(--sys-color-divider-default)]"
|
|
12824
|
+
}
|
|
12825
|
+
),
|
|
12826
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 w-[var(--cmp-datepicker-mode-yearMonth-column-width)]", children: /* @__PURE__ */ jsxRuntime.jsx(MonthWheel, { year, value: month, selectable, onCommit: commitMonth }) })
|
|
12827
|
+
]
|
|
12828
|
+
}
|
|
12829
|
+
);
|
|
12830
|
+
}
|
|
11922
12831
|
function SDatePicker({
|
|
11923
12832
|
value,
|
|
11924
12833
|
onValueChange,
|
|
11925
12834
|
onViewChange,
|
|
12835
|
+
mode = "date",
|
|
11926
12836
|
size = "sm",
|
|
11927
|
-
placeholder
|
|
12837
|
+
placeholder,
|
|
11928
12838
|
selectable,
|
|
11929
12839
|
disabled = false,
|
|
11930
12840
|
width,
|
|
@@ -11950,6 +12860,7 @@ function SDatePicker({
|
|
|
11950
12860
|
const [focused, setFocused] = react.useState(false);
|
|
11951
12861
|
const [ruleError, setRuleError] = react.useState("");
|
|
11952
12862
|
const hasValue = value != null && value !== "";
|
|
12863
|
+
const resolvedPlaceholder = placeholder ?? (mode === "year" ? "YYYY" : mode === "month" ? "YYYY-MM" : "YYYY-MM-DD");
|
|
11953
12864
|
useFormField({
|
|
11954
12865
|
name,
|
|
11955
12866
|
validate: () => {
|
|
@@ -11961,12 +12872,39 @@ function SDatePicker({
|
|
|
11961
12872
|
});
|
|
11962
12873
|
const resolvedError = error || ruleError !== "";
|
|
11963
12874
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
11964
|
-
const dims = size === "md" ? {
|
|
12875
|
+
const dims = size === "md" ? {
|
|
12876
|
+
padX: 16,
|
|
12877
|
+
gap: 12,
|
|
12878
|
+
icon: 20,
|
|
12879
|
+
minW: 104,
|
|
12880
|
+
fieldMinW: 168,
|
|
12881
|
+
// 상한 등급 lg — 값 길이가 YYYY-MM-DD 로 정해져 있어, width="100%" 를 받아도
|
|
12882
|
+
// 행 전체로 늘어나지 않게 막는다 (SKeyValueTable 이 모든 컨트롤에 100% 를 넘긴다)
|
|
12883
|
+
fieldMaxW: 240,
|
|
12884
|
+
fontSize: 14,
|
|
12885
|
+
lineHeight: 24,
|
|
12886
|
+
radius: 6
|
|
12887
|
+
} : {
|
|
12888
|
+
padX: 12,
|
|
12889
|
+
gap: 8,
|
|
12890
|
+
icon: 16,
|
|
12891
|
+
minW: 80,
|
|
12892
|
+
fieldMinW: 128,
|
|
12893
|
+
// 상한 등급 md
|
|
12894
|
+
fieldMaxW: 160,
|
|
12895
|
+
fontSize: 12,
|
|
12896
|
+
lineHeight: 20,
|
|
12897
|
+
radius: 4
|
|
12898
|
+
};
|
|
11965
12899
|
const select = (date) => {
|
|
11966
12900
|
onValueChange?.(date);
|
|
11967
12901
|
if (rules && rules.length > 0) setRuleError(runRules(date, rules));
|
|
11968
12902
|
setOpen(false);
|
|
11969
12903
|
};
|
|
12904
|
+
const selectListboxValue = (nextValue) => {
|
|
12905
|
+
onValueChange?.(nextValue);
|
|
12906
|
+
if (rules && rules.length > 0) setRuleError(runRules(nextValue, rules));
|
|
12907
|
+
};
|
|
11970
12908
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
11971
12909
|
SField,
|
|
11972
12910
|
{
|
|
@@ -11985,11 +12923,13 @@ function SDatePicker({
|
|
|
11985
12923
|
focused: focused || open,
|
|
11986
12924
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
11987
12925
|
width,
|
|
12926
|
+
minWidth: dims.fieldMinW,
|
|
12927
|
+
maxWidth: dims.fieldMaxW,
|
|
11988
12928
|
disabled,
|
|
11989
12929
|
className,
|
|
11990
12930
|
style,
|
|
11991
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11992
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12931
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
12932
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11993
12933
|
"button",
|
|
11994
12934
|
{
|
|
11995
12935
|
type: "button",
|
|
@@ -12019,20 +12959,23 @@ function SDatePicker({
|
|
|
12019
12959
|
lineHeight: `${dims.lineHeight}px`,
|
|
12020
12960
|
color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasValue ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
|
|
12021
12961
|
},
|
|
12022
|
-
children: hasValue ? value :
|
|
12962
|
+
children: hasValue ? value : resolvedPlaceholder
|
|
12023
12963
|
}
|
|
12024
12964
|
)
|
|
12025
12965
|
]
|
|
12026
12966
|
}
|
|
12027
12967
|
) }),
|
|
12028
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12029
|
-
|
|
12968
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12969
|
+
RPopover10__namespace.Content,
|
|
12030
12970
|
{
|
|
12031
12971
|
side: "bottom",
|
|
12032
|
-
align: "start",
|
|
12972
|
+
align: mode === "date" ? "start" : "center",
|
|
12033
12973
|
sideOffset: 4,
|
|
12034
|
-
className: cn(
|
|
12035
|
-
|
|
12974
|
+
className: cn(
|
|
12975
|
+
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
12976
|
+
FLOATING_SLIDE_ANIM
|
|
12977
|
+
),
|
|
12978
|
+
children: mode === "date" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
12036
12979
|
SCalendar,
|
|
12037
12980
|
{
|
|
12038
12981
|
value: value ?? void 0,
|
|
@@ -12041,6 +12984,24 @@ function SDatePicker({
|
|
|
12041
12984
|
onValueChange: select,
|
|
12042
12985
|
onViewChange
|
|
12043
12986
|
}
|
|
12987
|
+
) : mode === "year" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
12988
|
+
SDatePickerYearListbox,
|
|
12989
|
+
{
|
|
12990
|
+
value,
|
|
12991
|
+
selectable,
|
|
12992
|
+
onValueChange: (nextValue) => {
|
|
12993
|
+
selectListboxValue(nextValue);
|
|
12994
|
+
setOpen(false);
|
|
12995
|
+
}
|
|
12996
|
+
}
|
|
12997
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
12998
|
+
SDatePickerMonthListbox,
|
|
12999
|
+
{
|
|
13000
|
+
value,
|
|
13001
|
+
selectable,
|
|
13002
|
+
onValueChange: selectListboxValue,
|
|
13003
|
+
onMonthSelect: () => setOpen(false)
|
|
13004
|
+
}
|
|
12044
13005
|
)
|
|
12045
13006
|
}
|
|
12046
13007
|
) })
|
|
@@ -12179,78 +13140,81 @@ function RangeCalendar({
|
|
|
12179
13140
|
}
|
|
12180
13141
|
};
|
|
12181
13142
|
const GRID_COLS = "grid grid-cols-[repeat(7,var(--cmp-datepicker-calendar-day-width))]";
|
|
12182
|
-
const renderPanel = (gy, gm, isLeft) =>
|
|
12183
|
-
|
|
12184
|
-
|
|
12185
|
-
|
|
12186
|
-
|
|
12187
|
-
|
|
12188
|
-
|
|
12189
|
-
|
|
12190
|
-
|
|
12191
|
-
|
|
12192
|
-
|
|
12193
|
-
|
|
12194
|
-
|
|
12195
|
-
|
|
12196
|
-
|
|
12197
|
-
|
|
13143
|
+
const renderPanel = (gy, gm, isLeft) => (
|
|
13144
|
+
// 좁은 창에서 눌려 격자가 깨지지 않도록, 줄이는 대신 부모가 가로 스크롤하게 둔다.
|
|
13145
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 flex-col gap-[var(--cmp-datepicker-calendar-gap)]", children: [
|
|
13146
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-[var(--cmp-datepicker-calendar-gap)]", children: [
|
|
13147
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13148
|
+
SGhostButton,
|
|
13149
|
+
{
|
|
13150
|
+
icon: "chevronLeft",
|
|
13151
|
+
size: "xxs",
|
|
13152
|
+
ariaLabel: "prevMonth",
|
|
13153
|
+
onClick: goPrevMonth,
|
|
13154
|
+
className: cn(!isLeft && "invisible pointer-events-none")
|
|
13155
|
+
}
|
|
13156
|
+
),
|
|
13157
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex min-w-[40px] flex-1 items-center justify-center text-center text-[14px] font-medium leading-[24px]", children: [
|
|
13158
|
+
gy,
|
|
13159
|
+
".",
|
|
13160
|
+
String(gm).padStart(2, "0")
|
|
13161
|
+
] }),
|
|
13162
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13163
|
+
SGhostButton,
|
|
13164
|
+
{
|
|
13165
|
+
icon: "chevronRight",
|
|
13166
|
+
size: "xxs",
|
|
13167
|
+
ariaLabel: "nextMonth",
|
|
13168
|
+
onClick: goNextMonth,
|
|
13169
|
+
className: cn(isLeft && "invisible pointer-events-none")
|
|
13170
|
+
}
|
|
13171
|
+
)
|
|
12198
13172
|
] }),
|
|
12199
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12200
|
-
|
|
12201
|
-
{
|
|
12202
|
-
icon: "chevronRight",
|
|
12203
|
-
size: "xxs",
|
|
12204
|
-
ariaLabel: "nextMonth",
|
|
12205
|
-
onClick: goNextMonth,
|
|
12206
|
-
className: cn(isLeft && "invisible pointer-events-none")
|
|
12207
|
-
}
|
|
12208
|
-
)
|
|
12209
|
-
] }),
|
|
12210
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: GRID_COLS, children: WEEK_LABELS.map((l) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
12211
|
-
"span",
|
|
12212
|
-
{
|
|
12213
|
-
className: "flex h-[20px] items-center justify-center text-[12px] font-normal text-[color:var(--cmp-datepicker-calendar-week-color)]",
|
|
12214
|
-
children: l
|
|
12215
|
-
},
|
|
12216
|
-
l
|
|
12217
|
-
)) }),
|
|
12218
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(GRID_COLS, "gap-y-[var(--cmp-datepicker-calendar-grid-rowGap)]"), children: monthCells(gy, gm).map((cell) => {
|
|
12219
|
-
const isEdge = cell.inCurrentMonth && (cell.date === rStart || complete && cell.date === rEnd);
|
|
12220
|
-
const between = cell.inCurrentMonth && inRange(cell.date);
|
|
12221
|
-
const disabled = cell.inCurrentMonth && isDisabled(cell.date);
|
|
12222
|
-
const isToday = cell.inCurrentMonth && today === cell.date;
|
|
12223
|
-
let cellBg;
|
|
12224
|
-
if (between) cellBg = RANGE_BG;
|
|
12225
|
-
else if (cell.inCurrentMonth && hasRange && cell.date === rStart)
|
|
12226
|
-
cellBg = `linear-gradient(to right, transparent 50%, ${RANGE_BG} 50%)`;
|
|
12227
|
-
else if (cell.inCurrentMonth && hasRange && cell.date === rEnd) cellBg = RANGE_BG;
|
|
12228
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12229
|
-
"div",
|
|
13173
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: GRID_COLS, children: WEEK_LABELS.map((l) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
13174
|
+
"span",
|
|
12230
13175
|
{
|
|
12231
|
-
className: "flex h-[
|
|
12232
|
-
|
|
12233
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12234
|
-
"button",
|
|
12235
|
-
{
|
|
12236
|
-
type: "button",
|
|
12237
|
-
disabled: !cell.inCurrentMonth || disabled,
|
|
12238
|
-
onMouseEnter: () => setHover(cell.date),
|
|
12239
|
-
onClick: () => cell.inCurrentMonth && click(cell.date),
|
|
12240
|
-
className: cn(
|
|
12241
|
-
"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]",
|
|
12242
|
-
!cell.inCurrentMonth ? "invisible pointer-events-none" : disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
12243
|
-
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)]",
|
|
12244
|
-
isToday && !disabled && "font-bold"
|
|
12245
|
-
),
|
|
12246
|
-
children: cell.inCurrentMonth ? cell.day : ""
|
|
12247
|
-
}
|
|
12248
|
-
)
|
|
13176
|
+
className: "flex h-[20px] items-center justify-center text-[12px] font-normal text-[color:var(--cmp-datepicker-calendar-week-color)]",
|
|
13177
|
+
children: l
|
|
12249
13178
|
},
|
|
12250
|
-
|
|
12251
|
-
)
|
|
12252
|
-
|
|
12253
|
-
|
|
13179
|
+
l
|
|
13180
|
+
)) }),
|
|
13181
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(GRID_COLS, "gap-y-[var(--cmp-datepicker-calendar-grid-rowGap)]"), children: monthCells(gy, gm).map((cell) => {
|
|
13182
|
+
const isEdge = cell.inCurrentMonth && (cell.date === rStart || complete && cell.date === rEnd);
|
|
13183
|
+
const between = cell.inCurrentMonth && inRange(cell.date);
|
|
13184
|
+
const disabled = cell.inCurrentMonth && isDisabled(cell.date);
|
|
13185
|
+
const isToday = cell.inCurrentMonth && today === cell.date;
|
|
13186
|
+
let cellBg;
|
|
13187
|
+
if (between) cellBg = RANGE_BG;
|
|
13188
|
+
else if (cell.inCurrentMonth && hasRange && cell.date === rStart)
|
|
13189
|
+
cellBg = `linear-gradient(to right, transparent 50%, ${RANGE_BG} 50%)`;
|
|
13190
|
+
else if (cell.inCurrentMonth && hasRange && cell.date === rEnd) cellBg = RANGE_BG;
|
|
13191
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13192
|
+
"div",
|
|
13193
|
+
{
|
|
13194
|
+
className: "flex h-[var(--cmp-datepicker-calendar-range-height)] w-[var(--cmp-datepicker-calendar-day-width)] items-center justify-center",
|
|
13195
|
+
style: { background: cellBg },
|
|
13196
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13197
|
+
"button",
|
|
13198
|
+
{
|
|
13199
|
+
type: "button",
|
|
13200
|
+
disabled: !cell.inCurrentMonth || disabled,
|
|
13201
|
+
onMouseEnter: () => setHover(cell.date),
|
|
13202
|
+
onClick: () => cell.inCurrentMonth && click(cell.date),
|
|
13203
|
+
className: cn(
|
|
13204
|
+
"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]",
|
|
13205
|
+
!cell.inCurrentMonth ? "invisible pointer-events-none" : disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
13206
|
+
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)]",
|
|
13207
|
+
isToday && !disabled && "font-bold"
|
|
13208
|
+
),
|
|
13209
|
+
children: cell.inCurrentMonth ? cell.day : ""
|
|
13210
|
+
}
|
|
13211
|
+
)
|
|
13212
|
+
},
|
|
13213
|
+
cell.date
|
|
13214
|
+
);
|
|
13215
|
+
}) })
|
|
13216
|
+
] })
|
|
13217
|
+
);
|
|
12254
13218
|
const renderTimeSection = (which, date, suffix) => {
|
|
12255
13219
|
const active = !!date;
|
|
12256
13220
|
const [yy = "", mm = "", dd = ""] = date ? date.split("-") : [];
|
|
@@ -12318,8 +13282,11 @@ function RangeCalendar({
|
|
|
12318
13282
|
"div",
|
|
12319
13283
|
{
|
|
12320
13284
|
className: cn(
|
|
12321
|
-
"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",
|
|
12322
|
-
|
|
13285
|
+
"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",
|
|
13286
|
+
// 높이는 고정이 아니라 하한이다 — 5주/6주 달을 오갈 때의 높이 흔들림만 막으면 되고,
|
|
13287
|
+
// 창이 좁아 패널이 가로 스크롤될 때는 스크롤바 높이만큼 늘어날 수 있어야 한다.
|
|
13288
|
+
// (단일 달 SCalendar 도 min-h 를 쓴다)
|
|
13289
|
+
useTimePicker ? "h-auto" : "min-h-[364px]"
|
|
12323
13290
|
),
|
|
12324
13291
|
children: [
|
|
12325
13292
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
@@ -12338,11 +13305,20 @@ function RangeCalendar({
|
|
|
12338
13305
|
}
|
|
12339
13306
|
)
|
|
12340
13307
|
] }),
|
|
12341
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
12342
|
-
|
|
12343
|
-
|
|
12344
|
-
|
|
12345
|
-
|
|
13308
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
13309
|
+
"div",
|
|
13310
|
+
{
|
|
13311
|
+
className: cn(
|
|
13312
|
+
"flex max-w-full gap-[var(--cmp-datepicker-calendar-range-panelGap)] overflow-x-auto",
|
|
13313
|
+
SCROLLBAR_CLASS
|
|
13314
|
+
),
|
|
13315
|
+
children: [
|
|
13316
|
+
renderPanel(y, m, true),
|
|
13317
|
+
/* @__PURE__ */ jsxRuntime.jsx(SDivider, { vertical: true }),
|
|
13318
|
+
renderPanel(nextMonthYM.year, nextMonthYM.month, false)
|
|
13319
|
+
]
|
|
13320
|
+
}
|
|
13321
|
+
),
|
|
12346
13322
|
useTimePicker && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
12347
13323
|
/* @__PURE__ */ jsxRuntime.jsx(SDivider, {}),
|
|
12348
13324
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-[var(--cmp-datepicker-calendar-time-gap)]", children: [
|
|
@@ -12401,7 +13377,30 @@ function SDateRangePicker({
|
|
|
12401
13377
|
});
|
|
12402
13378
|
const resolvedError = error || ruleError !== "";
|
|
12403
13379
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
12404
|
-
const dims = size === "md" ? {
|
|
13380
|
+
const dims = size === "md" ? {
|
|
13381
|
+
padX: 16,
|
|
13382
|
+
gap: 12,
|
|
13383
|
+
icon: 20,
|
|
13384
|
+
minW: 104,
|
|
13385
|
+
fieldMinW: 260,
|
|
13386
|
+
// 상한 등급 xl — 값이 `YYYY-MM-DD ~ YYYY-MM-DD` 라 단일 날짜의 두 배가 넘는다.
|
|
13387
|
+
// 최소너비(260)가 이미 lg(240)를 넘으므로 상한도 한 등급 위여야 한다
|
|
13388
|
+
fieldMaxW: 480,
|
|
13389
|
+
fontSize: 14,
|
|
13390
|
+
lineHeight: 24,
|
|
13391
|
+
radius: 6
|
|
13392
|
+
} : {
|
|
13393
|
+
padX: 12,
|
|
13394
|
+
gap: 8,
|
|
13395
|
+
icon: 16,
|
|
13396
|
+
minW: 80,
|
|
13397
|
+
fieldMinW: 216,
|
|
13398
|
+
// 상한 등급 lg — 최소너비 216 이 md(160)를 넘어 md 로는 담기지 않는다
|
|
13399
|
+
fieldMaxW: 240,
|
|
13400
|
+
fontSize: 12,
|
|
13401
|
+
lineHeight: 20,
|
|
13402
|
+
radius: 4
|
|
13403
|
+
};
|
|
12405
13404
|
const select = (r) => {
|
|
12406
13405
|
setPendingStart(null);
|
|
12407
13406
|
onValueChange?.(r);
|
|
@@ -12427,11 +13426,13 @@ function SDateRangePicker({
|
|
|
12427
13426
|
focused: open,
|
|
12428
13427
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
12429
13428
|
width,
|
|
13429
|
+
minWidth: dims.fieldMinW,
|
|
13430
|
+
maxWidth: dims.fieldMaxW,
|
|
12430
13431
|
disabled,
|
|
12431
13432
|
className,
|
|
12432
13433
|
style,
|
|
12433
13434
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12434
|
-
|
|
13435
|
+
RPopover10__namespace.Root,
|
|
12435
13436
|
{
|
|
12436
13437
|
open,
|
|
12437
13438
|
onOpenChange: (o) => {
|
|
@@ -12440,7 +13441,7 @@ function SDateRangePicker({
|
|
|
12440
13441
|
if (!o) setPendingStart(null);
|
|
12441
13442
|
},
|
|
12442
13443
|
children: [
|
|
12443
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13444
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12444
13445
|
"button",
|
|
12445
13446
|
{
|
|
12446
13447
|
type: "button",
|
|
@@ -12481,13 +13482,16 @@ function SDateRangePicker({
|
|
|
12481
13482
|
]
|
|
12482
13483
|
}
|
|
12483
13484
|
) }),
|
|
12484
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12485
|
-
|
|
13485
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13486
|
+
RPopover10__namespace.Content,
|
|
12486
13487
|
{
|
|
12487
13488
|
side: "bottom",
|
|
12488
13489
|
align: "start",
|
|
12489
13490
|
sideOffset: 4,
|
|
12490
|
-
className: cn(
|
|
13491
|
+
className: cn(
|
|
13492
|
+
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
13493
|
+
FLOATING_SLIDE_ANIM
|
|
13494
|
+
),
|
|
12491
13495
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12492
13496
|
RangeCalendar,
|
|
12493
13497
|
{
|
|
@@ -12888,6 +13892,7 @@ function SKeyValueTable({
|
|
|
12888
13892
|
values = {},
|
|
12889
13893
|
search = false,
|
|
12890
13894
|
radius = "default",
|
|
13895
|
+
bordered = true,
|
|
12891
13896
|
onChange,
|
|
12892
13897
|
onSearch,
|
|
12893
13898
|
className,
|
|
@@ -12952,7 +13957,8 @@ function SKeyValueTable({
|
|
|
12952
13957
|
});
|
|
12953
13958
|
const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[8px] rounded-t-none" : "rounded-[8px]";
|
|
12954
13959
|
const frameClass = cn(
|
|
12955
|
-
"overflow-hidden
|
|
13960
|
+
"overflow-hidden",
|
|
13961
|
+
bordered && "border border-solid border-[color:var(--cmp-table-border-color)]",
|
|
12956
13962
|
radiusClass
|
|
12957
13963
|
);
|
|
12958
13964
|
const table = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -13475,7 +14481,7 @@ function SRadioButton({
|
|
|
13475
14481
|
disabled: od,
|
|
13476
14482
|
onClick: () => !od && !selected && onValueChange?.(o.value),
|
|
13477
14483
|
className: cn(
|
|
13478
|
-
"relative box-border inline-flex items-center justify-center whitespace-nowrap border border-solid text-[12px] font-medium leading-[20px] transition-colors",
|
|
14484
|
+
"relative box-border grow inline-flex items-center justify-center whitespace-nowrap border border-solid text-[12px] font-medium leading-[20px] transition-colors",
|
|
13479
14485
|
i === 0 ? "rounded-l-[var(--cmp-radioButton-radius)]" : "-ml-px",
|
|
13480
14486
|
i === options.length - 1 ? "rounded-r-[var(--cmp-radioButton-radius)]" : "",
|
|
13481
14487
|
selected ? "z-10" : "",
|
|
@@ -13497,6 +14503,1564 @@ function SRadioButton({
|
|
|
13497
14503
|
}
|
|
13498
14504
|
);
|
|
13499
14505
|
}
|
|
14506
|
+
var FONT2 = {
|
|
14507
|
+
sm: {
|
|
14508
|
+
fontSize: 12,
|
|
14509
|
+
lineHeight: 20,
|
|
14510
|
+
paddingX: "var(--cmp-textinput-sm-paddingX)",
|
|
14511
|
+
gap: "var(--cmp-textinput-sm-gap)"
|
|
14512
|
+
},
|
|
14513
|
+
md: {
|
|
14514
|
+
fontSize: 14,
|
|
14515
|
+
lineHeight: 24,
|
|
14516
|
+
paddingX: "var(--cmp-textinput-md-paddingX)",
|
|
14517
|
+
gap: "var(--cmp-textinput-md-gap)"
|
|
14518
|
+
}
|
|
14519
|
+
};
|
|
14520
|
+
var SSearchInput = /* @__PURE__ */ react.forwardRef(function SSearchInput2({
|
|
14521
|
+
value,
|
|
14522
|
+
onValueChange,
|
|
14523
|
+
onChange,
|
|
14524
|
+
onSearch,
|
|
14525
|
+
size = "sm",
|
|
14526
|
+
placeholder = "\uACB0\uACFC \uB0B4 \uAC80\uC0C9",
|
|
14527
|
+
clearable = false,
|
|
14528
|
+
disabled = false,
|
|
14529
|
+
width,
|
|
14530
|
+
focused,
|
|
14531
|
+
hovered,
|
|
14532
|
+
inputClass,
|
|
14533
|
+
inputStyle,
|
|
14534
|
+
className,
|
|
14535
|
+
style,
|
|
14536
|
+
onKeyDown,
|
|
14537
|
+
...rest
|
|
14538
|
+
}, ref) {
|
|
14539
|
+
const f = FONT2[size];
|
|
14540
|
+
const hasValue = value !== void 0 && value !== null && String(value) !== "";
|
|
14541
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14542
|
+
SField,
|
|
14543
|
+
{
|
|
14544
|
+
size,
|
|
14545
|
+
width,
|
|
14546
|
+
focused,
|
|
14547
|
+
hovered,
|
|
14548
|
+
disabled,
|
|
14549
|
+
className,
|
|
14550
|
+
style,
|
|
14551
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14552
|
+
"div",
|
|
14553
|
+
{
|
|
14554
|
+
className: "flex h-full w-full items-center",
|
|
14555
|
+
style: {
|
|
14556
|
+
gap: f.gap,
|
|
14557
|
+
padding: `0 ${f.paddingX}`,
|
|
14558
|
+
fontSize: f.fontSize,
|
|
14559
|
+
lineHeight: `${f.lineHeight}px`
|
|
14560
|
+
},
|
|
14561
|
+
children: [
|
|
14562
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14563
|
+
SIcon,
|
|
14564
|
+
{
|
|
14565
|
+
name: "search",
|
|
14566
|
+
size: 16,
|
|
14567
|
+
color: disabled ? "var(--sys-color-disabled-icon)" : "var(--cmp-textinput-icon-default)",
|
|
14568
|
+
className: "flex-shrink-0"
|
|
14569
|
+
}
|
|
14570
|
+
),
|
|
14571
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14572
|
+
"input",
|
|
14573
|
+
{
|
|
14574
|
+
ref,
|
|
14575
|
+
type: "search",
|
|
14576
|
+
value: value ?? "",
|
|
14577
|
+
disabled,
|
|
14578
|
+
placeholder,
|
|
14579
|
+
onChange: (e) => {
|
|
14580
|
+
onChange?.(e);
|
|
14581
|
+
onValueChange?.(e.target.value);
|
|
14582
|
+
},
|
|
14583
|
+
onKeyDown: (e) => {
|
|
14584
|
+
onKeyDown?.(e);
|
|
14585
|
+
if (e.key === "Enter" && !e.nativeEvent.isComposing) {
|
|
14586
|
+
onSearch?.(e.currentTarget.value);
|
|
14587
|
+
}
|
|
14588
|
+
},
|
|
14589
|
+
className: cn(
|
|
14590
|
+
// type="search" 의 브라우저 기본 취소 버튼은 clearable 과 겹치므로 지운다
|
|
14591
|
+
"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",
|
|
14592
|
+
AUTOFILL_RESET_CLASS,
|
|
14593
|
+
inputClass
|
|
14594
|
+
),
|
|
14595
|
+
style: {
|
|
14596
|
+
// fontSize/lineHeight 는 컨테이너에서 상속 (원본 font-size: inherit)
|
|
14597
|
+
color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--sys-color-field-text-default)",
|
|
14598
|
+
...inputStyle
|
|
14599
|
+
},
|
|
14600
|
+
...rest
|
|
14601
|
+
}
|
|
14602
|
+
),
|
|
14603
|
+
clearable && hasValue && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
14604
|
+
SGhostButton,
|
|
14605
|
+
{
|
|
14606
|
+
icon: "close",
|
|
14607
|
+
size: "xxs",
|
|
14608
|
+
ariaLabel: "\uC9C0\uC6B0\uAE30",
|
|
14609
|
+
className: "flex-shrink-0",
|
|
14610
|
+
onClick: () => onValueChange?.("")
|
|
14611
|
+
}
|
|
14612
|
+
)
|
|
14613
|
+
]
|
|
14614
|
+
}
|
|
14615
|
+
)
|
|
14616
|
+
}
|
|
14617
|
+
);
|
|
14618
|
+
});
|
|
14619
|
+
var CHIPFILTER_LISTBOX_WIDTH = 240;
|
|
14620
|
+
var CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH = 246;
|
|
14621
|
+
var CHIPFILTER = {
|
|
14622
|
+
barBg: "var(--cmp-chipFilter-bar-bg)",
|
|
14623
|
+
barBorder: "var(--cmp-chipFilter-bar-border)",
|
|
14624
|
+
barPaddingX: "var(--cmp-chipFilter-bar-paddingX)",
|
|
14625
|
+
barPaddingY: "var(--cmp-chipFilter-bar-paddingY)",
|
|
14626
|
+
barGap: "var(--cmp-chipFilter-bar-gap)",
|
|
14627
|
+
dividerHeight: "var(--cmp-chipFilter-divider-height)",
|
|
14628
|
+
chipHeight: "var(--cmp-chipFilter-chip-height)",
|
|
14629
|
+
chipRadius: "var(--cmp-chipFilter-chip-radius)",
|
|
14630
|
+
chipGap: "var(--cmp-chipFilter-chip-gap)",
|
|
14631
|
+
chipDefaultBg: "var(--cmp-chipFilter-chip-default-bg)",
|
|
14632
|
+
chipDefaultBorder: "var(--cmp-chipFilter-chip-default-border)",
|
|
14633
|
+
chipDefaultText: "var(--cmp-chipFilter-chip-default-text)",
|
|
14634
|
+
chipActiveBorder: "var(--cmp-chipFilter-chip-active-border)",
|
|
14635
|
+
chipWarningBorder: "var(--cmp-chipFilter-chip-warning-border)",
|
|
14636
|
+
chipAppliedBg: "var(--cmp-chipFilter-chip-applied-bg)",
|
|
14637
|
+
chipAppliedBorder: "var(--cmp-chipFilter-chip-applied-border)",
|
|
14638
|
+
chipAppliedLabel: "var(--cmp-chipFilter-chip-applied-text-label)",
|
|
14639
|
+
chipAppliedValue: "var(--color-brilliantblue-80)",
|
|
14640
|
+
chipDisabledBg: "var(--cmp-chipFilter-chip-disabled-bg)",
|
|
14641
|
+
chipDisabledBorder: "var(--cmp-chipFilter-chip-disabled-border)",
|
|
14642
|
+
chipDisabledText: "var(--cmp-chipFilter-chip-disabled-text)",
|
|
14643
|
+
addBorder: "var(--cmp-chipFilter-addButton-border-default)",
|
|
14644
|
+
addBorderDisabled: "var(--cmp-chipFilter-addButton-border-disabled)",
|
|
14645
|
+
addText: "var(--cmp-chipFilter-addButton-text-default)",
|
|
14646
|
+
addTextDisabled: "var(--cmp-chipFilter-addButton-text-disabled)",
|
|
14647
|
+
listboxBg: "var(--cmp-chipFilter-listbox-bg)",
|
|
14648
|
+
listboxBorder: "var(--cmp-chipFilter-listbox-border-color)",
|
|
14649
|
+
listboxRadius: "var(--cmp-chipFilter-listbox-radius)",
|
|
14650
|
+
listboxLabel: "var(--cmp-chipFilter-listbox-top-label-color)",
|
|
14651
|
+
listboxBottomDividerHeight: "var(--cmp-chipFilter-listbox-bottom-divider-height)",
|
|
14652
|
+
itemPaddingLeft: "var(--cmp-chipFilter-item-paddingLeft)",
|
|
14653
|
+
itemPaddingRight: "var(--cmp-chipFilter-item-paddingRight)",
|
|
14654
|
+
itemPaddingY: "var(--cmp-chipFilter-item-paddingY)",
|
|
14655
|
+
itemMultiPaddingX: "var(--cmp-chipFilter-item-multi-paddingX)",
|
|
14656
|
+
itemTextDefault: "var(--cmp-chipFilter-item-text-default)",
|
|
14657
|
+
itemTextSelected: "var(--cmp-chipFilter-item-text-selected)"
|
|
14658
|
+
};
|
|
14659
|
+
var DEFAULT_PERIOD_PRESETS = [
|
|
14660
|
+
{ value: "day", label: "\uC77C\uBCC4" },
|
|
14661
|
+
{ value: "month", label: "\uC6D4\uBCC4" },
|
|
14662
|
+
{ value: "quarter", label: "\uBD84\uAE30\uBCC4" },
|
|
14663
|
+
{ value: "half", label: "\uBC18\uAE30\uBCC4" },
|
|
14664
|
+
{ value: "year", label: "\uC5F0\uB3C4\uBCC4" },
|
|
14665
|
+
{ value: "custom", label: "\uC0AC\uC6A9\uC790 \uC9C0\uC815", custom: true }
|
|
14666
|
+
];
|
|
14667
|
+
var isKeywordValue = (value) => typeof value === "object" && value != null && !Array.isArray(value) && "keywords" in value;
|
|
14668
|
+
var isPeriodValue = (value) => typeof value === "object" && value != null && !Array.isArray(value) && "unit" in value;
|
|
14669
|
+
var keywordEntries = (value) => {
|
|
14670
|
+
if (isKeywordValue(value)) return value.keywords;
|
|
14671
|
+
if (Array.isArray(value)) {
|
|
14672
|
+
return value.filter((v) => typeof v === "string");
|
|
14673
|
+
}
|
|
14674
|
+
return [];
|
|
14675
|
+
};
|
|
14676
|
+
var isEmptyValue = (value) => {
|
|
14677
|
+
if (value == null) return true;
|
|
14678
|
+
if (Array.isArray(value)) return value.length === 0 || value.every((v) => v == null || v === "");
|
|
14679
|
+
if (isKeywordValue(value)) return value.keywords.length === 0;
|
|
14680
|
+
return value === "";
|
|
14681
|
+
};
|
|
14682
|
+
var normalizeValues = (value) => value ?? {};
|
|
14683
|
+
var toArrayValue = (value) => Array.isArray(value) ? value.filter(
|
|
14684
|
+
(v) => typeof v === "string" || typeof v === "number"
|
|
14685
|
+
) : [];
|
|
14686
|
+
var todayIso = () => {
|
|
14687
|
+
const d = /* @__PURE__ */ new Date();
|
|
14688
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
14689
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
14690
|
+
};
|
|
14691
|
+
var isInlineDateField = (field) => field.type === "date" && field.radioButton === true && (field.presets?.length ?? 0) > 0;
|
|
14692
|
+
var getFieldPresets = (field) => {
|
|
14693
|
+
if (field.type === "period") return field.presets ?? DEFAULT_PERIOD_PRESETS;
|
|
14694
|
+
return field.presets ?? [];
|
|
14695
|
+
};
|
|
14696
|
+
var getDefaultPeriodInputValue = (unit) => {
|
|
14697
|
+
const today = todayIso();
|
|
14698
|
+
if (unit === "day") return today;
|
|
14699
|
+
if (unit === "month") return today.slice(0, 7);
|
|
14700
|
+
if (unit === "quarter") return 1;
|
|
14701
|
+
if (unit === "half") return "first";
|
|
14702
|
+
if (unit === "year") return today.slice(0, 4);
|
|
14703
|
+
return [today, today];
|
|
14704
|
+
};
|
|
14705
|
+
var createPeriodValue = (unit) => ({
|
|
14706
|
+
unit,
|
|
14707
|
+
value: getDefaultPeriodInputValue(unit)
|
|
14708
|
+
});
|
|
14709
|
+
var resolveFieldDefault = (field) => {
|
|
14710
|
+
if (field.defaultValue !== void 0) return field.defaultValue;
|
|
14711
|
+
if (isInlineDateField(field)) return todayIso();
|
|
14712
|
+
if (!field.required) return void 0;
|
|
14713
|
+
if (field.type === "single") return field.options?.[0]?.value;
|
|
14714
|
+
if (field.type === "date") return todayIso();
|
|
14715
|
+
if (field.type === "period") {
|
|
14716
|
+
const unit = getFieldPresets(field).find((preset) => !preset.custom)?.value;
|
|
14717
|
+
return unit ? createPeriodValue(unit) : void 0;
|
|
14718
|
+
}
|
|
14719
|
+
return void 0;
|
|
14720
|
+
};
|
|
14721
|
+
var valuesEqual = (a, b) => {
|
|
14722
|
+
if (isKeywordValue(a) || isKeywordValue(b)) {
|
|
14723
|
+
return isKeywordValue(a) && isKeywordValue(b) && a.mode === b.mode && valuesEqual(a.keywords, b.keywords);
|
|
14724
|
+
}
|
|
14725
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
14726
|
+
return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((v, i) => v === b[i]);
|
|
14727
|
+
}
|
|
14728
|
+
return a === b;
|
|
14729
|
+
};
|
|
14730
|
+
var valuesMapEqual = (a, b) => {
|
|
14731
|
+
const keys = /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)]);
|
|
14732
|
+
for (const key of keys) {
|
|
14733
|
+
if (!valuesEqual(a[key], b[key])) return false;
|
|
14734
|
+
}
|
|
14735
|
+
return true;
|
|
14736
|
+
};
|
|
14737
|
+
var isAtDefaultValue = (field, value) => {
|
|
14738
|
+
const def = resolveFieldDefault(field);
|
|
14739
|
+
return def !== void 0 && valuesEqual(value, def);
|
|
14740
|
+
};
|
|
14741
|
+
var isInlineField = (field) => isInlineDateField(field) || field.type === "custom";
|
|
14742
|
+
var isFixedField = (field) => field.fix === true || field.required === true;
|
|
14743
|
+
var isAddableField = (field) => !isFixedField(field);
|
|
14744
|
+
var isGroupedFields = (fields) => fields.length > 0 && "fields" in fields[0];
|
|
14745
|
+
var isGroupSatisfied = (group, values) => {
|
|
14746
|
+
if (!group.rule) return true;
|
|
14747
|
+
const keys = group.fields.map((f) => f.key);
|
|
14748
|
+
if (group.rule.type === "requireKey") return !isEmptyValue(values[group.rule.key]);
|
|
14749
|
+
if (group.rule.type === "requireAll") return keys.every((k) => !isEmptyValue(values[k]));
|
|
14750
|
+
if (group.rule.type === "requireAny") return keys.some((k) => !isEmptyValue(values[k]));
|
|
14751
|
+
return true;
|
|
14752
|
+
};
|
|
14753
|
+
var koreanParticle = (word, consonant, vowel) => {
|
|
14754
|
+
const code = word.charCodeAt(word.length - 1);
|
|
14755
|
+
if (code < 44032 || code > 55203) return consonant;
|
|
14756
|
+
return (code - 44032) % 28 === 0 ? vowel : consonant;
|
|
14757
|
+
};
|
|
14758
|
+
var defaultGroupTooltipMessage = (rule, fields) => {
|
|
14759
|
+
if (rule.type === "requireAll") return "\uD56D\uBAA9\uC744 \uBAA8\uB450 \uC120\uD0DD\uD574 \uC8FC\uC138\uC694.";
|
|
14760
|
+
if (rule.type === "requireAny") {
|
|
14761
|
+
const name = rule.dataGroupName;
|
|
14762
|
+
if (!name) return "\uCD5C\uC18C 1\uAC1C\uC758 \uD544\uD130\uB97C \uC120\uD0DD\uD574\uC8FC\uC138\uC694.";
|
|
14763
|
+
return `\uCD5C\uC18C 1\uAC1C\uC758 ${name}${koreanParticle(name, "\uC744", "\uB97C")} \uC120\uD0DD\uD574\uC8FC\uC138\uC694.`;
|
|
14764
|
+
}
|
|
14765
|
+
const label = fields.find((f) => f.key === rule.key)?.label ?? "\uD56D\uBAA9";
|
|
14766
|
+
return `${label}${koreanParticle(label, "\uC744", "\uB97C")} \uC120\uD0DD\uD574 \uC8FC\uC138\uC694.`;
|
|
14767
|
+
};
|
|
14768
|
+
var matchPresetId = (presets, value) => {
|
|
14769
|
+
if (isEmptyValue(value)) return null;
|
|
14770
|
+
if (isPeriodValue(value)) return value.unit;
|
|
14771
|
+
for (const preset of presets) {
|
|
14772
|
+
if (preset.custom) continue;
|
|
14773
|
+
const resolved = preset.resolve ? preset.resolve() : preset.value;
|
|
14774
|
+
if (Array.isArray(resolved) && Array.isArray(value)) {
|
|
14775
|
+
if (resolved[0] === value[0] && resolved[1] === value[1]) return preset.value;
|
|
14776
|
+
} else if (!Array.isArray(resolved) && !Array.isArray(value) && resolved === value) {
|
|
14777
|
+
return preset.value;
|
|
14778
|
+
}
|
|
14779
|
+
}
|
|
14780
|
+
return presets.find((preset) => preset.custom)?.value ?? null;
|
|
14781
|
+
};
|
|
14782
|
+
var optionLabel = (field, value) => field.options?.find((option) => option.value === value)?.label ?? String(value);
|
|
14783
|
+
var formatValueList = (labels) => {
|
|
14784
|
+
if (labels.length <= 1) return labels[0] ?? "";
|
|
14785
|
+
return `${labels[0]} \uC678 ${labels.length - 1}\uAC1C`;
|
|
14786
|
+
};
|
|
14787
|
+
var displayValue = (field, value) => {
|
|
14788
|
+
if (isEmptyValue(value)) return "";
|
|
14789
|
+
if (field.type === "multi") {
|
|
14790
|
+
const values = toArrayValue(value);
|
|
14791
|
+
const selectableValues = (field.options ?? []).filter((option) => !option.disabled).map((option) => option.value);
|
|
14792
|
+
if (selectableValues.length > 0 && selectableValues.every((selectableValue) => values.includes(selectableValue))) {
|
|
14793
|
+
return "\uC804\uCCB4";
|
|
14794
|
+
}
|
|
14795
|
+
return formatValueList(values.map((v) => optionLabel(field, v)));
|
|
14796
|
+
}
|
|
14797
|
+
if (field.type === "single") return optionLabel(field, value);
|
|
14798
|
+
if (field.type === "date")
|
|
14799
|
+
return Array.isArray(value) ? `${value[0]} ~ ${value[1]}` : String(value);
|
|
14800
|
+
if (field.type === "period") {
|
|
14801
|
+
if (!isPeriodValue(value)) {
|
|
14802
|
+
const preset2 = getFieldPresets(field).find((p) => p.value === value);
|
|
14803
|
+
return preset2?.label ?? String(value);
|
|
14804
|
+
}
|
|
14805
|
+
const preset = getFieldPresets(field).find((p) => p.value === value.unit);
|
|
14806
|
+
const label = preset?.label ?? value.unit;
|
|
14807
|
+
if (value.unit === "quarter") return `${label}(${value.value ?? 1}\uBD84\uAE30)`;
|
|
14808
|
+
if (value.unit === "half") return `${label}(${value.value === "second" ? "\uD558\uBC18\uAE30" : "\uC0C1\uBC18\uAE30"})`;
|
|
14809
|
+
if (Array.isArray(value.value)) return `${value.value[0]} ~ ${value.value[1]}`;
|
|
14810
|
+
return value.value != null && value.value !== "" ? String(value.value) : label;
|
|
14811
|
+
}
|
|
14812
|
+
if (field.type === "keyword") return formatValueList(keywordEntries(value));
|
|
14813
|
+
return String(value);
|
|
14814
|
+
};
|
|
14815
|
+
var chipDisplayValue = (field, value) => {
|
|
14816
|
+
const text = displayValue(field, value);
|
|
14817
|
+
if (field.type !== "date" || isEmptyValue(value)) return text;
|
|
14818
|
+
const presets = getFieldPresets(field);
|
|
14819
|
+
if (presets.length === 0) return text;
|
|
14820
|
+
const preset = presets.find((p) => p.value === matchPresetId(presets, value));
|
|
14821
|
+
return preset && !preset.custom ? `${preset.label}(${text})` : text;
|
|
14822
|
+
};
|
|
14823
|
+
var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
14824
|
+
fields: fieldsProp = [],
|
|
14825
|
+
value,
|
|
14826
|
+
onValueChange,
|
|
14827
|
+
onFilterChange,
|
|
14828
|
+
onSearch,
|
|
14829
|
+
activeKeys,
|
|
14830
|
+
onActiveKeysChange,
|
|
14831
|
+
onReset,
|
|
14832
|
+
onAddFilter,
|
|
14833
|
+
label = "\uAC80\uC0C9 \uD544\uD130",
|
|
14834
|
+
showLabel = false,
|
|
14835
|
+
showReset = true,
|
|
14836
|
+
disabled = false,
|
|
14837
|
+
className,
|
|
14838
|
+
style
|
|
14839
|
+
}, ref) {
|
|
14840
|
+
const usingGroupedFields = isGroupedFields(fieldsProp);
|
|
14841
|
+
const groups = react.useMemo(
|
|
14842
|
+
() => usingGroupedFields ? fieldsProp : [{ fields: fieldsProp }],
|
|
14843
|
+
[usingGroupedFields, fieldsProp]
|
|
14844
|
+
);
|
|
14845
|
+
const fields = react.useMemo(() => groups.flatMap((group) => group.fields), [groups]);
|
|
14846
|
+
const values = normalizeValues(value);
|
|
14847
|
+
const portalContainer = usePortalContainer();
|
|
14848
|
+
const [internalActiveKeys, setInternalActiveKeys] = react.useState(
|
|
14849
|
+
() => fields.filter((field) => isFixedField(field) || field.defaultActive !== false).map((field) => field.key)
|
|
14850
|
+
);
|
|
14851
|
+
const [openKey, setOpenKey] = react.useState(null);
|
|
14852
|
+
const [addOpen, setAddOpen] = react.useState(false);
|
|
14853
|
+
const triggerRefs = react.useRef(/* @__PURE__ */ new Map());
|
|
14854
|
+
const initializedDefaultsRef = react.useRef(/* @__PURE__ */ new Set());
|
|
14855
|
+
const prevOpenKeyRef = react.useRef(null);
|
|
14856
|
+
const valuesRef = react.useRef(values);
|
|
14857
|
+
valuesRef.current = values;
|
|
14858
|
+
const lastSearchedValuesRef = react.useRef(values);
|
|
14859
|
+
const invalidGroups = react.useMemo(() => {
|
|
14860
|
+
const invalid = /* @__PURE__ */ new Set();
|
|
14861
|
+
groups.forEach((group, groupIndex) => {
|
|
14862
|
+
if (!isGroupSatisfied(group, values)) invalid.add(groupIndex);
|
|
14863
|
+
});
|
|
14864
|
+
return invalid;
|
|
14865
|
+
}, [groups, values]);
|
|
14866
|
+
const isGroupsValid = react.useCallback(
|
|
14867
|
+
(current) => groups.every((group) => isGroupSatisfied(group, current)),
|
|
14868
|
+
[groups]
|
|
14869
|
+
);
|
|
14870
|
+
const runSearch = react.useCallback(
|
|
14871
|
+
(next) => {
|
|
14872
|
+
if (valuesMapEqual(lastSearchedValuesRef.current, next)) return;
|
|
14873
|
+
if (!isGroupsValid(next)) return;
|
|
14874
|
+
lastSearchedValuesRef.current = next;
|
|
14875
|
+
onSearch?.(next);
|
|
14876
|
+
},
|
|
14877
|
+
[isGroupsValid, onSearch]
|
|
14878
|
+
);
|
|
14879
|
+
react.useEffect(() => {
|
|
14880
|
+
const prevKey = prevOpenKeyRef.current;
|
|
14881
|
+
if (prevKey != null && prevKey !== openKey) {
|
|
14882
|
+
runSearch(valuesRef.current);
|
|
14883
|
+
}
|
|
14884
|
+
prevOpenKeyRef.current = openKey;
|
|
14885
|
+
}, [openKey, runSearch]);
|
|
14886
|
+
react.useEffect(() => {
|
|
14887
|
+
if (activeKeys) return;
|
|
14888
|
+
setInternalActiveKeys((current) => {
|
|
14889
|
+
const known = new Set(fields.map((field) => field.key));
|
|
14890
|
+
const kept = current.filter((key) => known.has(key));
|
|
14891
|
+
const additions = fields.filter(
|
|
14892
|
+
(field) => (isFixedField(field) || field.defaultActive !== false) && !kept.includes(field.key)
|
|
14893
|
+
).map((field) => field.key);
|
|
14894
|
+
return [...kept, ...additions];
|
|
14895
|
+
});
|
|
14896
|
+
}, [activeKeys, fields]);
|
|
14897
|
+
react.useEffect(() => {
|
|
14898
|
+
const patch = {};
|
|
14899
|
+
let changed = false;
|
|
14900
|
+
fields.forEach((field) => {
|
|
14901
|
+
if (initializedDefaultsRef.current.has(field.key)) return;
|
|
14902
|
+
if (!isEmptyValue(values[field.key])) {
|
|
14903
|
+
initializedDefaultsRef.current.add(field.key);
|
|
14904
|
+
return;
|
|
14905
|
+
}
|
|
14906
|
+
const def = resolveFieldDefault(field);
|
|
14907
|
+
if (def === void 0) return;
|
|
14908
|
+
patch[field.key] = def;
|
|
14909
|
+
initializedDefaultsRef.current.add(field.key);
|
|
14910
|
+
changed = true;
|
|
14911
|
+
});
|
|
14912
|
+
if (changed) onValueChange?.({ ...values, ...patch });
|
|
14913
|
+
}, [fields, values, onValueChange]);
|
|
14914
|
+
const fixedKeys = fields.filter(isFixedField).map((field) => field.key);
|
|
14915
|
+
const resolvedActiveKeys = Array.from(
|
|
14916
|
+
/* @__PURE__ */ new Set([...activeKeys ?? internalActiveKeys, ...fixedKeys])
|
|
14917
|
+
);
|
|
14918
|
+
const activeFields = fields.filter((field) => resolvedActiveKeys.includes(field.key));
|
|
14919
|
+
const inactiveFields = fields.filter(
|
|
14920
|
+
(field) => isAddableField(field) && !resolvedActiveKeys.includes(field.key)
|
|
14921
|
+
);
|
|
14922
|
+
const groupIndexByKey = /* @__PURE__ */ new Map();
|
|
14923
|
+
groups.forEach((group, groupIndex) => {
|
|
14924
|
+
group.fields.forEach((field) => groupIndexByKey.set(field.key, groupIndex));
|
|
14925
|
+
});
|
|
14926
|
+
const hasValue = fields.some((field) => !isEmptyValue(values[field.key]));
|
|
14927
|
+
const hasAddButton = fields.some(isAddableField);
|
|
14928
|
+
const hasRightActions = hasAddButton || showReset;
|
|
14929
|
+
const currentOpenField = fields.find((field) => field.key === openKey);
|
|
14930
|
+
const editorPopoverStyle = react.useMemo(() => {
|
|
14931
|
+
if (currentOpenField?.type === "keyword") {
|
|
14932
|
+
return { width: CHIPFILTER_LISTBOX_WIDTH };
|
|
14933
|
+
}
|
|
14934
|
+
if ((currentOpenField?.type === "date" || currentOpenField?.type === "period") && getFieldPresets(currentOpenField).length > 0) {
|
|
14935
|
+
return { width: CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH };
|
|
14936
|
+
}
|
|
14937
|
+
return { width: CHIPFILTER_LISTBOX_WIDTH };
|
|
14938
|
+
}, [currentOpenField]);
|
|
14939
|
+
const setActive = (next) => {
|
|
14940
|
+
if (!activeKeys) setInternalActiveKeys(next);
|
|
14941
|
+
onActiveKeysChange?.(next);
|
|
14942
|
+
};
|
|
14943
|
+
const emitValue = (key, nextValue) => {
|
|
14944
|
+
const next = { ...values, [key]: nextValue };
|
|
14945
|
+
onValueChange?.(next);
|
|
14946
|
+
onFilterChange?.({ key, value: nextValue, values: next });
|
|
14947
|
+
return next;
|
|
14948
|
+
};
|
|
14949
|
+
const emitValueAndSearch = (key, nextValue) => {
|
|
14950
|
+
runSearch(emitValue(key, nextValue));
|
|
14951
|
+
};
|
|
14952
|
+
const clearValue = (key) => {
|
|
14953
|
+
const field = fields.find((f) => f.key === key);
|
|
14954
|
+
const def = field ? resolveFieldDefault(field) : void 0;
|
|
14955
|
+
runSearch(emitValue(key, def !== void 0 ? def : null));
|
|
14956
|
+
};
|
|
14957
|
+
const removeField = (key) => {
|
|
14958
|
+
const nextValues = emitValue(key, null);
|
|
14959
|
+
setActive(resolvedActiveKeys.filter((activeKey) => activeKey !== key));
|
|
14960
|
+
if (openKey === key) setOpenKey(null);
|
|
14961
|
+
runSearch(nextValues);
|
|
14962
|
+
};
|
|
14963
|
+
const reset = react.useCallback(() => {
|
|
14964
|
+
const next = fields.reduce((acc, field) => {
|
|
14965
|
+
const def = resolveFieldDefault(field);
|
|
14966
|
+
acc[field.key] = def !== void 0 ? def : null;
|
|
14967
|
+
return acc;
|
|
14968
|
+
}, {});
|
|
14969
|
+
onValueChange?.(next);
|
|
14970
|
+
runSearch(next);
|
|
14971
|
+
onReset?.();
|
|
14972
|
+
}, [fields, onReset, onValueChange, runSearch]);
|
|
14973
|
+
const open = react.useCallback(
|
|
14974
|
+
(key) => {
|
|
14975
|
+
const field = fields.find((f) => f.key === key);
|
|
14976
|
+
if (!field || isInlineField(field)) return;
|
|
14977
|
+
setOpenKey(key);
|
|
14978
|
+
},
|
|
14979
|
+
[fields]
|
|
14980
|
+
);
|
|
14981
|
+
const validate = react.useCallback(() => invalidGroups.size === 0, [invalidGroups]);
|
|
14982
|
+
react.useImperativeHandle(ref, () => ({ open, reset, validate }), [open, reset, validate]);
|
|
14983
|
+
const addField = (key) => {
|
|
14984
|
+
const next = [...resolvedActiveKeys, key];
|
|
14985
|
+
setActive(next);
|
|
14986
|
+
onAddFilter?.(key);
|
|
14987
|
+
setAddOpen(false);
|
|
14988
|
+
const field = fields.find((f) => f.key === key);
|
|
14989
|
+
if (field && !isInlineField(field)) requestAnimationFrame(() => setOpenKey(key));
|
|
14990
|
+
};
|
|
14991
|
+
const rootStyle = react.useMemo(
|
|
14992
|
+
() => ({
|
|
14993
|
+
"--chipfilter-bar-bg": CHIPFILTER.barBg,
|
|
14994
|
+
"--chipfilter-bar-border": CHIPFILTER.barBorder,
|
|
14995
|
+
"--chipfilter-bar-padding-x": CHIPFILTER.barPaddingX,
|
|
14996
|
+
"--chipfilter-bar-padding-y": CHIPFILTER.barPaddingY,
|
|
14997
|
+
"--chipfilter-bar-gap": CHIPFILTER.barGap,
|
|
14998
|
+
"--chipfilter-divider-height": CHIPFILTER.dividerHeight,
|
|
14999
|
+
...style
|
|
15000
|
+
}),
|
|
15001
|
+
[style]
|
|
15002
|
+
);
|
|
15003
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15004
|
+
"div",
|
|
15005
|
+
{
|
|
15006
|
+
className: cn(
|
|
15007
|
+
"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)]",
|
|
15008
|
+
className
|
|
15009
|
+
),
|
|
15010
|
+
style: { ...rootStyle, borderColor: "var(--chipfilter-bar-border)" },
|
|
15011
|
+
children: [
|
|
15012
|
+
showLabel && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
15013
|
+
/* @__PURE__ */ jsxRuntime.jsx(STag, { className: "shrink-0", shape: "square", size: "sm", color: "darkblue", label }),
|
|
15014
|
+
/* @__PURE__ */ jsxRuntime.jsx(Divider, { top: true })
|
|
15015
|
+
] }),
|
|
15016
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-[var(--cmp-chipFilter-chip-group)]", children: [
|
|
15017
|
+
(() => {
|
|
15018
|
+
const nodes = [];
|
|
15019
|
+
let runBuffer = [];
|
|
15020
|
+
let runGroupIndex = null;
|
|
15021
|
+
const flushRun = () => {
|
|
15022
|
+
if (runBuffer.length === 0) return;
|
|
15023
|
+
const group = runGroupIndex != null ? groups[runGroupIndex] : void 0;
|
|
15024
|
+
const message = usingGroupedFields && group?.rule ? group.tooltipMessage ?? defaultGroupTooltipMessage(group.rule, group.fields) : void 0;
|
|
15025
|
+
if (message) {
|
|
15026
|
+
nodes.push(
|
|
15027
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15028
|
+
GroupTooltip,
|
|
15029
|
+
{
|
|
15030
|
+
message,
|
|
15031
|
+
open: invalidGroups.has(runGroupIndex),
|
|
15032
|
+
children: runBuffer
|
|
15033
|
+
},
|
|
15034
|
+
`group-${runGroupIndex}`
|
|
15035
|
+
)
|
|
15036
|
+
);
|
|
15037
|
+
} else {
|
|
15038
|
+
nodes.push(...runBuffer);
|
|
15039
|
+
}
|
|
15040
|
+
runBuffer = [];
|
|
15041
|
+
};
|
|
15042
|
+
activeFields.forEach((field, index) => {
|
|
15043
|
+
const inline = isInlineField(field);
|
|
15044
|
+
const groupIndex = groupIndexByKey.get(field.key) ?? 0;
|
|
15045
|
+
const warning = field.warning || invalidGroups.has(groupIndex);
|
|
15046
|
+
const prevField = index > 0 ? activeFields[index - 1] : null;
|
|
15047
|
+
const prevGroupIndex = prevField ? groupIndexByKey.get(prevField.key) ?? 0 : null;
|
|
15048
|
+
const needsLeadingDivider = index === 0 ? false : inline || prevField != null && isInlineField(prevField) || groupIndex !== prevGroupIndex;
|
|
15049
|
+
if (groupIndex !== runGroupIndex) {
|
|
15050
|
+
flushRun();
|
|
15051
|
+
runGroupIndex = groupIndex;
|
|
15052
|
+
}
|
|
15053
|
+
const addable = isAddableField(field);
|
|
15054
|
+
const showClear = addable || !isAtDefaultValue(field, values[field.key]);
|
|
15055
|
+
const handleClear = () => {
|
|
15056
|
+
if (addable) {
|
|
15057
|
+
removeField(field.key);
|
|
15058
|
+
return;
|
|
15059
|
+
}
|
|
15060
|
+
clearValue(field.key);
|
|
15061
|
+
};
|
|
15062
|
+
const node = isInlineDateField(field) ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
15063
|
+
InlineDatePresetFilter,
|
|
15064
|
+
{
|
|
15065
|
+
field,
|
|
15066
|
+
value: values[field.key],
|
|
15067
|
+
disabled: disabled || field.disabled,
|
|
15068
|
+
warning,
|
|
15069
|
+
showClear,
|
|
15070
|
+
onValueChange: (next) => emitValueAndSearch(field.key, next),
|
|
15071
|
+
onClear: handleClear
|
|
15072
|
+
},
|
|
15073
|
+
field.key
|
|
15074
|
+
) : field.type === "custom" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex shrink-0 items-center gap-[4px]", children: [
|
|
15075
|
+
field.render?.({
|
|
15076
|
+
value: values[field.key],
|
|
15077
|
+
disabled: disabled || field.disabled,
|
|
15078
|
+
warning,
|
|
15079
|
+
onValueChange: (next) => emitValueAndSearch(field.key, next)
|
|
15080
|
+
}),
|
|
15081
|
+
addable && !disabled && !field.disabled && showClear && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15082
|
+
"button",
|
|
15083
|
+
{
|
|
15084
|
+
type: "button",
|
|
15085
|
+
"aria-label": `${field.label} \uD544\uD130 \uC81C\uAC70`,
|
|
15086
|
+
className: "inline-flex size-[16px] shrink-0 items-center justify-center rounded-[var(--cmp-ghostButton-radius-sm)] border-none bg-transparent p-0",
|
|
15087
|
+
onClick: handleClear,
|
|
15088
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
15089
|
+
}
|
|
15090
|
+
)
|
|
15091
|
+
] }, field.key) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
15092
|
+
FilterChip,
|
|
15093
|
+
{
|
|
15094
|
+
field,
|
|
15095
|
+
valueText: chipDisplayValue(field, values[field.key]),
|
|
15096
|
+
active: openKey === field.key,
|
|
15097
|
+
applied: !isEmptyValue(values[field.key]),
|
|
15098
|
+
disabled: disabled || field.disabled,
|
|
15099
|
+
warning,
|
|
15100
|
+
showClear,
|
|
15101
|
+
showClearWhenEmpty: addable,
|
|
15102
|
+
refCallback: (node2) => triggerRefs.current.set(field.key, node2),
|
|
15103
|
+
onOpen: () => setOpenKey(openKey === field.key ? null : field.key),
|
|
15104
|
+
onClear: handleClear
|
|
15105
|
+
},
|
|
15106
|
+
field.key
|
|
15107
|
+
);
|
|
15108
|
+
runBuffer.push(
|
|
15109
|
+
needsLeadingDivider ? /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
|
|
15110
|
+
/* @__PURE__ */ jsxRuntime.jsx(Divider, { inset: true }),
|
|
15111
|
+
node
|
|
15112
|
+
] }, `${field.key}-wrap`) : node
|
|
15113
|
+
);
|
|
15114
|
+
});
|
|
15115
|
+
flushRun();
|
|
15116
|
+
return nodes;
|
|
15117
|
+
})(),
|
|
15118
|
+
(() => {
|
|
15119
|
+
const lastField = activeFields[activeFields.length - 1];
|
|
15120
|
+
const needsTrailingDivider = lastField != null && isInlineField(lastField) && !hasRightActions;
|
|
15121
|
+
return needsTrailingDivider ? /* @__PURE__ */ jsxRuntime.jsx(Divider, { inset: true }) : null;
|
|
15122
|
+
})(),
|
|
15123
|
+
hasRightActions && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
15124
|
+
/* @__PURE__ */ jsxRuntime.jsx(Divider, { inset: true }),
|
|
15125
|
+
hasAddButton && /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open: addOpen, onOpenChange: setAddOpen, children: [
|
|
15126
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15127
|
+
"button",
|
|
15128
|
+
{
|
|
15129
|
+
type: "button",
|
|
15130
|
+
disabled: disabled || inactiveFields.length === 0,
|
|
15131
|
+
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",
|
|
15132
|
+
style: {
|
|
15133
|
+
minHeight: "var(--cmp-chipFilter-addButton-height)" ,
|
|
15134
|
+
borderRadius: "var(--cmp-chipFilter-addButton-radius)" ,
|
|
15135
|
+
borderColor: disabled || inactiveFields.length === 0 ? CHIPFILTER.addBorderDisabled : CHIPFILTER.addBorder,
|
|
15136
|
+
color: disabled || inactiveFields.length === 0 ? CHIPFILTER.addTextDisabled : CHIPFILTER.addText
|
|
15137
|
+
},
|
|
15138
|
+
children: [
|
|
15139
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15140
|
+
SIcon,
|
|
15141
|
+
{
|
|
15142
|
+
name: "add",
|
|
15143
|
+
size: 12,
|
|
15144
|
+
color: disabled || inactiveFields.length === 0 ? CHIPFILTER.addTextDisabled : CHIPFILTER.addText
|
|
15145
|
+
}
|
|
15146
|
+
),
|
|
15147
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "\uD544\uD130 \uCD94\uAC00" })
|
|
15148
|
+
]
|
|
15149
|
+
}
|
|
15150
|
+
) }),
|
|
15151
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15152
|
+
RPopover10__namespace.Content,
|
|
15153
|
+
{
|
|
15154
|
+
side: "bottom",
|
|
15155
|
+
align: "start",
|
|
15156
|
+
sideOffset: 4,
|
|
15157
|
+
className: cn("z-50 min-w-[180px]", FLOATING_SLIDE_ANIM),
|
|
15158
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ListBox, { children: inactiveFields.length > 0 ? inactiveFields.map((field) => /* @__PURE__ */ jsxRuntime.jsx(MenuItem, { onClick: () => addField(field.key), children: field.label }, field.key)) : /* @__PURE__ */ jsxRuntime.jsx(EmptyItem, { children: "\uCD94\uAC00\uD560 \uD544\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4." }) })
|
|
15159
|
+
}
|
|
15160
|
+
) })
|
|
15161
|
+
] }),
|
|
15162
|
+
showReset && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15163
|
+
"button",
|
|
15164
|
+
{
|
|
15165
|
+
type: "button",
|
|
15166
|
+
disabled: disabled || !hasValue,
|
|
15167
|
+
onClick: reset,
|
|
15168
|
+
className: cn(
|
|
15169
|
+
"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",
|
|
15170
|
+
// 부모 flex gap(6px)은 칩 사이 간격 기준이라, 필터 추가 버튼과의 12px 간격을 맞추려면
|
|
15171
|
+
// 부족한 만큼(12px - gap)을 추가로 띄운다. 필터 추가가 없을 땐 divider와 이미 12px이라 불필요.
|
|
15172
|
+
hasAddButton && "ml-[calc(12px-var(--cmp-chipFilter-chip-group))]"
|
|
15173
|
+
),
|
|
15174
|
+
style: {
|
|
15175
|
+
color: disabled || !hasValue ? "var(--cmp-textLink-content-disabled)" : "var(--cmp-textLink-content-default)"
|
|
15176
|
+
},
|
|
15177
|
+
children: [
|
|
15178
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15179
|
+
SIcon,
|
|
15180
|
+
{
|
|
15181
|
+
name: "reset",
|
|
15182
|
+
size: 16,
|
|
15183
|
+
color: disabled || !hasValue ? "var(--cmp-textLink-icon-disabled)" : "var(--cmp-textLink-icon-default)"
|
|
15184
|
+
}
|
|
15185
|
+
),
|
|
15186
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "\uAC80\uC0C9 \uCD08\uAE30\uD654" })
|
|
15187
|
+
]
|
|
15188
|
+
}
|
|
15189
|
+
)
|
|
15190
|
+
] })
|
|
15191
|
+
] }),
|
|
15192
|
+
/* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open: openKey != null, onOpenChange: (next) => !next && setOpenKey(null), children: [
|
|
15193
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15194
|
+
RPopover10__namespace.Anchor,
|
|
15195
|
+
{
|
|
15196
|
+
virtualRef: {
|
|
15197
|
+
current: openKey ? triggerRefs.current.get(openKey) : null
|
|
15198
|
+
}
|
|
15199
|
+
}
|
|
15200
|
+
),
|
|
15201
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15202
|
+
RPopover10__namespace.Content,
|
|
15203
|
+
{
|
|
15204
|
+
side: "bottom",
|
|
15205
|
+
align: "start",
|
|
15206
|
+
sideOffset: 4,
|
|
15207
|
+
onOpenAutoFocus: (event) => event.preventDefault(),
|
|
15208
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
15209
|
+
style: editorPopoverStyle,
|
|
15210
|
+
children: currentOpenField && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15211
|
+
EditorPanel,
|
|
15212
|
+
{
|
|
15213
|
+
field: currentOpenField,
|
|
15214
|
+
value: values[currentOpenField.key],
|
|
15215
|
+
disabled: disabled || currentOpenField.disabled,
|
|
15216
|
+
onValueChange: (next) => emitValue(currentOpenField.key, next),
|
|
15217
|
+
onClose: () => setOpenKey(null)
|
|
15218
|
+
}
|
|
15219
|
+
)
|
|
15220
|
+
}
|
|
15221
|
+
) })
|
|
15222
|
+
] })
|
|
15223
|
+
]
|
|
15224
|
+
}
|
|
15225
|
+
);
|
|
15226
|
+
});
|
|
15227
|
+
function Divider({ inset, top } = {}) {
|
|
15228
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15229
|
+
"span",
|
|
15230
|
+
{
|
|
15231
|
+
"aria-hidden": true,
|
|
15232
|
+
className: cn(
|
|
15233
|
+
"inline-flex w-px shrink-0 bg-[var(--chipfilter-bar-border)]",
|
|
15234
|
+
top ? "mt-[2px] self-start" : "my-auto",
|
|
15235
|
+
inset && "mx-[calc(12px-var(--cmp-chipFilter-chip-group))]"
|
|
15236
|
+
),
|
|
15237
|
+
style: { height: "var(--chipfilter-divider-height)" }
|
|
15238
|
+
}
|
|
15239
|
+
);
|
|
15240
|
+
}
|
|
15241
|
+
function GroupTooltip({
|
|
15242
|
+
message,
|
|
15243
|
+
open,
|
|
15244
|
+
children
|
|
15245
|
+
}) {
|
|
15246
|
+
return /* @__PURE__ */ jsxRuntime.jsx(STooltip2, { trigger: "none", open, placement: "top", tooltipType: "warning", message: [message], children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-[var(--cmp-chipFilter-chip-group)]", children }) });
|
|
15247
|
+
}
|
|
15248
|
+
function FilterChip({
|
|
15249
|
+
field,
|
|
15250
|
+
valueText,
|
|
15251
|
+
active,
|
|
15252
|
+
applied,
|
|
15253
|
+
disabled,
|
|
15254
|
+
warning,
|
|
15255
|
+
showClear,
|
|
15256
|
+
showClearWhenEmpty,
|
|
15257
|
+
refCallback,
|
|
15258
|
+
onOpen,
|
|
15259
|
+
onClear
|
|
15260
|
+
}) {
|
|
15261
|
+
const border = disabled ? CHIPFILTER.chipDisabledBorder : warning ? CHIPFILTER.chipWarningBorder : applied ? active ? "var(--color-blue-strong)" : CHIPFILTER.chipAppliedBorder : active ? CHIPFILTER.chipActiveBorder : CHIPFILTER.chipDefaultBorder;
|
|
15262
|
+
const background = disabled ? CHIPFILTER.chipDisabledBg : applied ? CHIPFILTER.chipAppliedBg : CHIPFILTER.chipDefaultBg;
|
|
15263
|
+
const textColor = disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipDefaultText;
|
|
15264
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15265
|
+
"button",
|
|
15266
|
+
{
|
|
15267
|
+
ref: refCallback,
|
|
15268
|
+
type: "button",
|
|
15269
|
+
disabled,
|
|
15270
|
+
"aria-expanded": active,
|
|
15271
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
15272
|
+
onClick: onOpen,
|
|
15273
|
+
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",
|
|
15274
|
+
style: {
|
|
15275
|
+
minHeight: CHIPFILTER.chipHeight,
|
|
15276
|
+
gap: CHIPFILTER.chipGap,
|
|
15277
|
+
borderRadius: CHIPFILTER.chipRadius,
|
|
15278
|
+
borderColor: border,
|
|
15279
|
+
background,
|
|
15280
|
+
color: textColor
|
|
15281
|
+
},
|
|
15282
|
+
children: [
|
|
15283
|
+
field.required && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15284
|
+
SIcon,
|
|
15285
|
+
{
|
|
15286
|
+
name: "asterisk",
|
|
15287
|
+
size: 12,
|
|
15288
|
+
color: disabled ? CHIPFILTER.chipDisabledText : "var(--cmp-tag-darkblue-content)"
|
|
15289
|
+
}
|
|
15290
|
+
),
|
|
15291
|
+
applied ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex min-w-0 items-center gap-[4px] truncate", children: [
|
|
15292
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15293
|
+
"span",
|
|
15294
|
+
{
|
|
15295
|
+
className: "font-bold",
|
|
15296
|
+
style: { color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedLabel },
|
|
15297
|
+
children: field.label
|
|
15298
|
+
}
|
|
15299
|
+
),
|
|
15300
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15301
|
+
"span",
|
|
15302
|
+
{
|
|
15303
|
+
style: { color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedLabel },
|
|
15304
|
+
children: ":"
|
|
15305
|
+
}
|
|
15306
|
+
),
|
|
15307
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15308
|
+
"span",
|
|
15309
|
+
{
|
|
15310
|
+
className: "min-w-0 truncate font-bold",
|
|
15311
|
+
style: { color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedValue },
|
|
15312
|
+
children: valueText
|
|
15313
|
+
}
|
|
15314
|
+
)
|
|
15315
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
15316
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("min-w-0 truncate", active && "font-bold"), children: field.label }),
|
|
15317
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15318
|
+
SIcon,
|
|
15319
|
+
{
|
|
15320
|
+
name: "caretDown",
|
|
15321
|
+
size: 12,
|
|
15322
|
+
color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipDefaultText
|
|
15323
|
+
}
|
|
15324
|
+
)
|
|
15325
|
+
] }),
|
|
15326
|
+
!disabled && showClear && (applied || showClearWhenEmpty) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15327
|
+
"span",
|
|
15328
|
+
{
|
|
15329
|
+
role: "button",
|
|
15330
|
+
tabIndex: 0,
|
|
15331
|
+
"aria-label": `${field.label} \uD544\uD130 \uC9C0\uC6B0\uAE30`,
|
|
15332
|
+
className: "inline-flex size-[16px] items-center justify-center rounded-[var(--cmp-ghostButton-radius-sm)]",
|
|
15333
|
+
onClick: (event) => {
|
|
15334
|
+
event.preventDefault();
|
|
15335
|
+
event.stopPropagation();
|
|
15336
|
+
onClear();
|
|
15337
|
+
},
|
|
15338
|
+
onKeyDown: (event) => {
|
|
15339
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
15340
|
+
event.preventDefault();
|
|
15341
|
+
event.stopPropagation();
|
|
15342
|
+
onClear();
|
|
15343
|
+
},
|
|
15344
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
15345
|
+
}
|
|
15346
|
+
)
|
|
15347
|
+
]
|
|
15348
|
+
}
|
|
15349
|
+
);
|
|
15350
|
+
}
|
|
15351
|
+
function EditorPanel({
|
|
15352
|
+
field,
|
|
15353
|
+
value,
|
|
15354
|
+
disabled,
|
|
15355
|
+
onValueChange,
|
|
15356
|
+
onClose
|
|
15357
|
+
}) {
|
|
15358
|
+
const wrapsInPaddedTop = field.type === "date" || field.type === "period";
|
|
15359
|
+
const isMulti = field.type === "multi";
|
|
15360
|
+
const selectableValues = isMulti ? (field.options ?? []).filter((option) => !option.disabled).map((option) => option.value) : [];
|
|
15361
|
+
const selectedValues = isMulti ? toArrayValue(value) : [];
|
|
15362
|
+
const allSelected = isMulti && selectableValues.length > 0 && selectableValues.every((v) => selectedValues.includes(v));
|
|
15363
|
+
const toggleSelectAll = () => {
|
|
15364
|
+
onValueChange(
|
|
15365
|
+
allSelected ? selectedValues.filter((v) => !selectableValues.includes(v)) : [...selectedValues, ...selectableValues.filter((v) => !selectedValues.includes(v))]
|
|
15366
|
+
);
|
|
15367
|
+
};
|
|
15368
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ListBox, { children: [
|
|
15369
|
+
wrapsInPaddedTop ? /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(
|
|
15370
|
+
FilterEditor,
|
|
15371
|
+
{
|
|
15372
|
+
field,
|
|
15373
|
+
value,
|
|
15374
|
+
disabled,
|
|
15375
|
+
onValueChange
|
|
15376
|
+
}
|
|
15377
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
15378
|
+
FilterEditor,
|
|
15379
|
+
{
|
|
15380
|
+
field,
|
|
15381
|
+
value,
|
|
15382
|
+
disabled,
|
|
15383
|
+
onValueChange
|
|
15384
|
+
}
|
|
15385
|
+
),
|
|
15386
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
15387
|
+
"div",
|
|
15388
|
+
{
|
|
15389
|
+
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)]",
|
|
15390
|
+
style: { borderColor: CHIPFILTER.listboxBorder },
|
|
15391
|
+
children: [
|
|
15392
|
+
isMulti && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
15393
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15394
|
+
STextLink,
|
|
15395
|
+
{
|
|
15396
|
+
size: "sm",
|
|
15397
|
+
label: allSelected ? "\uC120\uD0DD \uD574\uC81C" : "\uC804\uCCB4 \uC120\uD0DD",
|
|
15398
|
+
labelClass: "font-bold",
|
|
15399
|
+
disabled,
|
|
15400
|
+
onClick: toggleSelectAll,
|
|
15401
|
+
style: { color: "var(--sys-color-fg-secondary)" }
|
|
15402
|
+
}
|
|
15403
|
+
),
|
|
15404
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15405
|
+
"span",
|
|
15406
|
+
{
|
|
15407
|
+
"aria-hidden": true,
|
|
15408
|
+
className: "inline-flex w-px shrink-0",
|
|
15409
|
+
style: {
|
|
15410
|
+
height: CHIPFILTER.listboxBottomDividerHeight,
|
|
15411
|
+
background: CHIPFILTER.listboxBorder
|
|
15412
|
+
}
|
|
15413
|
+
}
|
|
15414
|
+
)
|
|
15415
|
+
] }),
|
|
15416
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15417
|
+
STextLink,
|
|
15418
|
+
{
|
|
15419
|
+
size: "sm",
|
|
15420
|
+
label: "\uAC80\uC0C9",
|
|
15421
|
+
labelClass: "font-bold",
|
|
15422
|
+
onClick: onClose,
|
|
15423
|
+
style: { color: CHIPFILTER.chipAppliedValue }
|
|
15424
|
+
}
|
|
15425
|
+
)
|
|
15426
|
+
]
|
|
15427
|
+
}
|
|
15428
|
+
)
|
|
15429
|
+
] });
|
|
15430
|
+
}
|
|
15431
|
+
function FilterEditor({
|
|
15432
|
+
field,
|
|
15433
|
+
value,
|
|
15434
|
+
disabled,
|
|
15435
|
+
onValueChange
|
|
15436
|
+
}) {
|
|
15437
|
+
if (field.type === "period") {
|
|
15438
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15439
|
+
PeriodPresetEditor,
|
|
15440
|
+
{
|
|
15441
|
+
field,
|
|
15442
|
+
value,
|
|
15443
|
+
disabled,
|
|
15444
|
+
onValueChange
|
|
15445
|
+
}
|
|
15446
|
+
);
|
|
15447
|
+
}
|
|
15448
|
+
if (field.type === "date") {
|
|
15449
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15450
|
+
DatePresetEditor,
|
|
15451
|
+
{
|
|
15452
|
+
field,
|
|
15453
|
+
value,
|
|
15454
|
+
disabled,
|
|
15455
|
+
onValueChange
|
|
15456
|
+
}
|
|
15457
|
+
);
|
|
15458
|
+
}
|
|
15459
|
+
if (field.type === "keyword") {
|
|
15460
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15461
|
+
KeywordEditor,
|
|
15462
|
+
{
|
|
15463
|
+
field,
|
|
15464
|
+
value: isKeywordValue(value) ? value : keywordEntries(value),
|
|
15465
|
+
disabled,
|
|
15466
|
+
onValueChange
|
|
15467
|
+
}
|
|
15468
|
+
);
|
|
15469
|
+
}
|
|
15470
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15471
|
+
OptionList,
|
|
15472
|
+
{
|
|
15473
|
+
field,
|
|
15474
|
+
value: field.type === "multi" ? toArrayValue(value) : value,
|
|
15475
|
+
multiple: field.type === "multi",
|
|
15476
|
+
disabled,
|
|
15477
|
+
onValueChange
|
|
15478
|
+
}
|
|
15479
|
+
);
|
|
15480
|
+
}
|
|
15481
|
+
function DatePresetEditor({
|
|
15482
|
+
field,
|
|
15483
|
+
value,
|
|
15484
|
+
disabled,
|
|
15485
|
+
onValueChange
|
|
15486
|
+
}) {
|
|
15487
|
+
const presets = getFieldPresets(field);
|
|
15488
|
+
const [selectedId, setSelectedId] = react.useState(() => matchPresetId(presets, value));
|
|
15489
|
+
const syncedInitialValueRef = react.useRef(!isEmptyValue(value));
|
|
15490
|
+
react.useEffect(() => {
|
|
15491
|
+
if (syncedInitialValueRef.current || isEmptyValue(value)) return;
|
|
15492
|
+
syncedInitialValueRef.current = true;
|
|
15493
|
+
setSelectedId(matchPresetId(presets, value));
|
|
15494
|
+
}, [value, presets]);
|
|
15495
|
+
const selectedPreset = presets.find((preset) => preset.value === selectedId);
|
|
15496
|
+
const selectPreset = (preset) => {
|
|
15497
|
+
setSelectedId(preset.value);
|
|
15498
|
+
if (!preset.custom) onValueChange(preset.resolve ? preset.resolve() : preset.value);
|
|
15499
|
+
};
|
|
15500
|
+
if (field.type === "date" && presets.length === 0) {
|
|
15501
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15502
|
+
SDatePicker,
|
|
15503
|
+
{
|
|
15504
|
+
value: typeof value === "string" ? value : null,
|
|
15505
|
+
onValueChange,
|
|
15506
|
+
selectable: field.selectable,
|
|
15507
|
+
disabled,
|
|
15508
|
+
placeholder: field.placeholder
|
|
15509
|
+
}
|
|
15510
|
+
);
|
|
15511
|
+
}
|
|
15512
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)]", children: [
|
|
15513
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-[8px]", children: presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
15514
|
+
SRadio,
|
|
15515
|
+
{
|
|
15516
|
+
val: preset.value,
|
|
15517
|
+
value: selectedId,
|
|
15518
|
+
label: preset.label,
|
|
15519
|
+
disabled,
|
|
15520
|
+
onValueChange: () => selectPreset(preset)
|
|
15521
|
+
},
|
|
15522
|
+
preset.value
|
|
15523
|
+
)) }),
|
|
15524
|
+
selectedPreset?.custom && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15525
|
+
SDateRangePicker,
|
|
15526
|
+
{
|
|
15527
|
+
value: Array.isArray(value) && value.length === 2 ? value : null,
|
|
15528
|
+
onValueChange,
|
|
15529
|
+
selectable: field.selectable,
|
|
15530
|
+
maxRange: field.maxRange,
|
|
15531
|
+
disabled
|
|
15532
|
+
}
|
|
15533
|
+
)
|
|
15534
|
+
] });
|
|
15535
|
+
}
|
|
15536
|
+
function PeriodPresetEditor({
|
|
15537
|
+
field,
|
|
15538
|
+
value,
|
|
15539
|
+
disabled,
|
|
15540
|
+
onValueChange
|
|
15541
|
+
}) {
|
|
15542
|
+
const presets = getFieldPresets(field);
|
|
15543
|
+
const firstUnit = presets.find((preset) => !preset.custom)?.value ?? "day";
|
|
15544
|
+
const [selectedId, setSelectedId] = react.useState(() => matchPresetId(presets, value) ?? firstUnit);
|
|
15545
|
+
const periodValue = isPeriodValue(value) ? value : createPeriodValue(selectedId ?? firstUnit);
|
|
15546
|
+
const selectedUnit = selectedId ?? periodValue.unit;
|
|
15547
|
+
react.useEffect(() => {
|
|
15548
|
+
if (isEmptyValue(value)) return;
|
|
15549
|
+
setSelectedId(matchPresetId(presets, value) ?? firstUnit);
|
|
15550
|
+
}, [firstUnit, presets, value]);
|
|
15551
|
+
const selectPreset = (preset) => {
|
|
15552
|
+
const nextUnit = preset.value;
|
|
15553
|
+
setSelectedId(nextUnit);
|
|
15554
|
+
onValueChange(createPeriodValue(nextUnit));
|
|
15555
|
+
};
|
|
15556
|
+
const updateInputValue = (nextValue) => {
|
|
15557
|
+
onValueChange({ unit: selectedUnit, value: nextValue });
|
|
15558
|
+
};
|
|
15559
|
+
const renderInput = () => {
|
|
15560
|
+
if (selectedUnit === "day") {
|
|
15561
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15562
|
+
SDatePicker,
|
|
15563
|
+
{
|
|
15564
|
+
value: typeof periodValue.value === "string" ? periodValue.value : null,
|
|
15565
|
+
onValueChange: updateInputValue,
|
|
15566
|
+
selectable: field.selectable,
|
|
15567
|
+
disabled,
|
|
15568
|
+
width: "100%"
|
|
15569
|
+
}
|
|
15570
|
+
);
|
|
15571
|
+
}
|
|
15572
|
+
if (selectedUnit === "month") {
|
|
15573
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15574
|
+
SDatePicker,
|
|
15575
|
+
{
|
|
15576
|
+
mode: "month",
|
|
15577
|
+
value: typeof periodValue.value === "string" ? periodValue.value : null,
|
|
15578
|
+
onValueChange: updateInputValue,
|
|
15579
|
+
selectable: field.selectable,
|
|
15580
|
+
disabled,
|
|
15581
|
+
width: "100%"
|
|
15582
|
+
}
|
|
15583
|
+
);
|
|
15584
|
+
}
|
|
15585
|
+
if (selectedUnit === "quarter") {
|
|
15586
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15587
|
+
SSelect2,
|
|
15588
|
+
{
|
|
15589
|
+
value: typeof periodValue.value === "number" ? periodValue.value : 1,
|
|
15590
|
+
onValueChange: updateInputValue,
|
|
15591
|
+
emitValue: true,
|
|
15592
|
+
disabled,
|
|
15593
|
+
width: "100%",
|
|
15594
|
+
options: [
|
|
15595
|
+
{ value: 1, label: "1\uBD84\uAE30" },
|
|
15596
|
+
{ value: 2, label: "2\uBD84\uAE30" },
|
|
15597
|
+
{ value: 3, label: "3\uBD84\uAE30" },
|
|
15598
|
+
{ value: 4, label: "4\uBD84\uAE30" }
|
|
15599
|
+
]
|
|
15600
|
+
}
|
|
15601
|
+
);
|
|
15602
|
+
}
|
|
15603
|
+
if (selectedUnit === "half") {
|
|
15604
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15605
|
+
SSelect2,
|
|
15606
|
+
{
|
|
15607
|
+
value: typeof periodValue.value === "string" ? periodValue.value : "first",
|
|
15608
|
+
onValueChange: updateInputValue,
|
|
15609
|
+
emitValue: true,
|
|
15610
|
+
disabled,
|
|
15611
|
+
width: "100%",
|
|
15612
|
+
options: [
|
|
15613
|
+
{ value: "first", label: "\uC0C1\uBC18\uAE30" },
|
|
15614
|
+
{ value: "second", label: "\uD558\uBC18\uAE30" }
|
|
15615
|
+
]
|
|
15616
|
+
}
|
|
15617
|
+
);
|
|
15618
|
+
}
|
|
15619
|
+
if (selectedUnit === "year") {
|
|
15620
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15621
|
+
SDatePicker,
|
|
15622
|
+
{
|
|
15623
|
+
mode: "year",
|
|
15624
|
+
value: typeof periodValue.value === "string" ? periodValue.value : null,
|
|
15625
|
+
onValueChange: updateInputValue,
|
|
15626
|
+
selectable: field.selectable,
|
|
15627
|
+
disabled,
|
|
15628
|
+
width: "100%"
|
|
15629
|
+
}
|
|
15630
|
+
);
|
|
15631
|
+
}
|
|
15632
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15633
|
+
SDateRangePicker,
|
|
15634
|
+
{
|
|
15635
|
+
value: Array.isArray(periodValue.value) && periodValue.value.length === 2 ? periodValue.value : null,
|
|
15636
|
+
onValueChange: updateInputValue,
|
|
15637
|
+
selectable: field.selectable,
|
|
15638
|
+
maxRange: field.maxRange,
|
|
15639
|
+
disabled,
|
|
15640
|
+
width: "100%"
|
|
15641
|
+
}
|
|
15642
|
+
);
|
|
15643
|
+
};
|
|
15644
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)]", children: [
|
|
15645
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-[8px]", children: presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
15646
|
+
SRadio,
|
|
15647
|
+
{
|
|
15648
|
+
val: preset.value,
|
|
15649
|
+
value: selectedId,
|
|
15650
|
+
label: preset.label,
|
|
15651
|
+
disabled,
|
|
15652
|
+
onValueChange: () => selectPreset(preset)
|
|
15653
|
+
},
|
|
15654
|
+
preset.value
|
|
15655
|
+
)) }),
|
|
15656
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, className: "h-px w-full", style: { background: CHIPFILTER.listboxBorder } }),
|
|
15657
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full [&>*]:w-full", children: renderInput() })
|
|
15658
|
+
] });
|
|
15659
|
+
}
|
|
15660
|
+
function InlineDatePresetFilter({
|
|
15661
|
+
field,
|
|
15662
|
+
value,
|
|
15663
|
+
disabled,
|
|
15664
|
+
warning,
|
|
15665
|
+
showClear,
|
|
15666
|
+
onValueChange,
|
|
15667
|
+
onClear
|
|
15668
|
+
}) {
|
|
15669
|
+
const presets = (field.presets ?? []).filter((preset) => !preset.custom);
|
|
15670
|
+
const [selectedId, setSelectedId] = react.useState(() => matchPresetId(presets, value));
|
|
15671
|
+
const syncedInitialValueRef = react.useRef(!isEmptyValue(value));
|
|
15672
|
+
react.useEffect(() => {
|
|
15673
|
+
if (syncedInitialValueRef.current || isEmptyValue(value)) return;
|
|
15674
|
+
syncedInitialValueRef.current = true;
|
|
15675
|
+
setSelectedId(matchPresetId(presets, value));
|
|
15676
|
+
}, [value, presets]);
|
|
15677
|
+
const applied = !isEmptyValue(value);
|
|
15678
|
+
const rangeValue = Array.isArray(value) ? value : typeof value === "string" && value !== "" ? [value, value] : null;
|
|
15679
|
+
const [pickerOpen, setPickerOpen] = react.useState(false);
|
|
15680
|
+
const portalContainer = usePortalContainer();
|
|
15681
|
+
const selectPreset = (id) => {
|
|
15682
|
+
const preset = presets.find((p) => p.value === id);
|
|
15683
|
+
if (!preset) return;
|
|
15684
|
+
setSelectedId(preset.value);
|
|
15685
|
+
onValueChange(preset.resolve ? preset.resolve() : null);
|
|
15686
|
+
};
|
|
15687
|
+
const badge = applied && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15688
|
+
"span",
|
|
15689
|
+
{
|
|
15690
|
+
className: "inline-flex shrink-0 items-center gap-[4px] whitespace-nowrap border border-solid px-[var(--cmp-chipFilter-chip-paddingX)] text-[12px] leading-[20px]",
|
|
15691
|
+
style: {
|
|
15692
|
+
minHeight: CHIPFILTER.chipHeight,
|
|
15693
|
+
borderRadius: CHIPFILTER.chipRadius,
|
|
15694
|
+
borderColor: warning ? CHIPFILTER.chipWarningBorder : CHIPFILTER.chipAppliedBorder,
|
|
15695
|
+
background: CHIPFILTER.chipAppliedBg,
|
|
15696
|
+
color: CHIPFILTER.chipAppliedLabel,
|
|
15697
|
+
cursor: rangeValue ? "pointer" : void 0
|
|
15698
|
+
},
|
|
15699
|
+
children: [
|
|
15700
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-bold", children: [
|
|
15701
|
+
field.label,
|
|
15702
|
+
":"
|
|
15703
|
+
] }),
|
|
15704
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold", style: { color: CHIPFILTER.chipAppliedValue }, children: displayValue(field, value) }),
|
|
15705
|
+
!disabled && showClear && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15706
|
+
"span",
|
|
15707
|
+
{
|
|
15708
|
+
role: "button",
|
|
15709
|
+
tabIndex: 0,
|
|
15710
|
+
"aria-label": `${field.label} \uD544\uD130 \uC9C0\uC6B0\uAE30`,
|
|
15711
|
+
className: "inline-flex size-[16px] items-center justify-center rounded-[var(--cmp-ghostButton-radius-sm)]",
|
|
15712
|
+
onClick: (event) => {
|
|
15713
|
+
event.stopPropagation();
|
|
15714
|
+
onClear();
|
|
15715
|
+
},
|
|
15716
|
+
onKeyDown: (event) => {
|
|
15717
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
15718
|
+
event.preventDefault();
|
|
15719
|
+
event.stopPropagation();
|
|
15720
|
+
onClear();
|
|
15721
|
+
},
|
|
15722
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
15723
|
+
}
|
|
15724
|
+
)
|
|
15725
|
+
]
|
|
15726
|
+
}
|
|
15727
|
+
);
|
|
15728
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-[8px]", children: [
|
|
15729
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15730
|
+
SRadioButton,
|
|
15731
|
+
{
|
|
15732
|
+
size: "xs",
|
|
15733
|
+
options: presets.map((preset) => ({ value: preset.value, label: preset.label })),
|
|
15734
|
+
value: selectedId,
|
|
15735
|
+
disabled,
|
|
15736
|
+
onValueChange: (next) => selectPreset(String(next))
|
|
15737
|
+
}
|
|
15738
|
+
),
|
|
15739
|
+
applied && (rangeValue ? (
|
|
15740
|
+
// 뱃지 모양은 그대로 두고, 눌렀을 때 캘린더가 열려 기간을 직접 다시 고를 수 있게 한다.
|
|
15741
|
+
// 직접 고르면 프리셋 선택은 해제된다.
|
|
15742
|
+
/* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open: pickerOpen, onOpenChange: setPickerOpen, children: [
|
|
15743
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15744
|
+
"button",
|
|
15745
|
+
{
|
|
15746
|
+
type: "button",
|
|
15747
|
+
disabled,
|
|
15748
|
+
className: "border-none bg-transparent p-0 outline-none disabled:cursor-not-allowed",
|
|
15749
|
+
children: badge
|
|
15750
|
+
}
|
|
15751
|
+
) }),
|
|
15752
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15753
|
+
RPopover10__namespace.Content,
|
|
15754
|
+
{
|
|
15755
|
+
side: "bottom",
|
|
15756
|
+
align: "start",
|
|
15757
|
+
sideOffset: 4,
|
|
15758
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
15759
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15760
|
+
RangeCalendar,
|
|
15761
|
+
{
|
|
15762
|
+
value: rangeValue,
|
|
15763
|
+
selectable: field.selectable,
|
|
15764
|
+
maxRange: field.maxRange,
|
|
15765
|
+
onSelect: (range) => {
|
|
15766
|
+
setSelectedId(null);
|
|
15767
|
+
onValueChange(range);
|
|
15768
|
+
setPickerOpen(false);
|
|
15769
|
+
}
|
|
15770
|
+
}
|
|
15771
|
+
)
|
|
15772
|
+
}
|
|
15773
|
+
) })
|
|
15774
|
+
] })
|
|
15775
|
+
) : badge)
|
|
15776
|
+
] });
|
|
15777
|
+
}
|
|
15778
|
+
var MATCH_MODE_OPTIONS = [
|
|
15779
|
+
{ value: "contains", label: "\uD3EC\uD568" },
|
|
15780
|
+
{ value: "exact", label: "\uC77C\uCE58" }
|
|
15781
|
+
];
|
|
15782
|
+
var EXCLUDE_MATCH_MODE_OPTION = {
|
|
15783
|
+
value: "excludes",
|
|
15784
|
+
label: "\uBBF8\uD3EC\uD568"
|
|
15785
|
+
};
|
|
15786
|
+
function KeywordEditor({
|
|
15787
|
+
field,
|
|
15788
|
+
value,
|
|
15789
|
+
disabled,
|
|
15790
|
+
onValueChange
|
|
15791
|
+
}) {
|
|
15792
|
+
const entries3 = keywordEntries(value);
|
|
15793
|
+
const [draft, setDraft] = react.useState("");
|
|
15794
|
+
const [mode, setMode] = react.useState(
|
|
15795
|
+
isKeywordValue(value) ? value.mode : "contains"
|
|
15796
|
+
);
|
|
15797
|
+
const emit3 = (nextEntries) => {
|
|
15798
|
+
onValueChange(field.matchModes ? { keywords: nextEntries, mode } : nextEntries);
|
|
15799
|
+
};
|
|
15800
|
+
const addEntry = (raw) => {
|
|
15801
|
+
const next = raw.trim();
|
|
15802
|
+
if (next === "" || entries3.includes(next)) return;
|
|
15803
|
+
emit3([...entries3, next]);
|
|
15804
|
+
setDraft("");
|
|
15805
|
+
};
|
|
15806
|
+
const removeEntry = (entry) => {
|
|
15807
|
+
emit3(entries3.filter((e) => e !== entry));
|
|
15808
|
+
};
|
|
15809
|
+
const onKeyDown = (event) => {
|
|
15810
|
+
if (event.key === "Enter") {
|
|
15811
|
+
if (event.nativeEvent.isComposing) return;
|
|
15812
|
+
event.preventDefault();
|
|
15813
|
+
addEntry(draft);
|
|
15814
|
+
}
|
|
15815
|
+
};
|
|
15816
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
15817
|
+
/* @__PURE__ */ jsxRuntime.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: [
|
|
15818
|
+
field.matchModes && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
15819
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15820
|
+
"span",
|
|
15821
|
+
{
|
|
15822
|
+
className: "shrink-0 whitespace-nowrap text-[12px] font-medium leading-[20px]",
|
|
15823
|
+
style: { color: CHIPFILTER.listboxLabel },
|
|
15824
|
+
children: "\uAC80\uC0C9 \uC870\uAC74 :"
|
|
15825
|
+
}
|
|
15826
|
+
),
|
|
15827
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15828
|
+
SRadioButton,
|
|
15829
|
+
{
|
|
15830
|
+
size: "xs",
|
|
15831
|
+
style: { width: 150 },
|
|
15832
|
+
options: field.excludeMode ? [...MATCH_MODE_OPTIONS, EXCLUDE_MATCH_MODE_OPTION] : MATCH_MODE_OPTIONS,
|
|
15833
|
+
value: mode,
|
|
15834
|
+
disabled,
|
|
15835
|
+
onValueChange: (next) => setMode(next)
|
|
15836
|
+
}
|
|
15837
|
+
)
|
|
15838
|
+
] }),
|
|
15839
|
+
/* @__PURE__ */ jsxRuntime.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: [
|
|
15840
|
+
/* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "search", size: 16, color: "var(--sys-color-field-icon-default)" }),
|
|
15841
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15842
|
+
"input",
|
|
15843
|
+
{
|
|
15844
|
+
value: draft,
|
|
15845
|
+
disabled,
|
|
15846
|
+
placeholder: field.placeholder ?? "\uC785\uB825 \uD6C4 Enter\uB85C \uCD94\uAC00",
|
|
15847
|
+
onChange: (event) => setDraft(event.target.value),
|
|
15848
|
+
onKeyDown,
|
|
15849
|
+
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"
|
|
15850
|
+
}
|
|
15851
|
+
)
|
|
15852
|
+
] })
|
|
15853
|
+
] }),
|
|
15854
|
+
entries3.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15855
|
+
"div",
|
|
15856
|
+
{
|
|
15857
|
+
className: "max-h-[220px] overflow-auto border-t border-solid py-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
15858
|
+
style: { borderColor: CHIPFILTER.listboxBorder },
|
|
15859
|
+
children: entries3.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
15860
|
+
KeywordEntryRow,
|
|
15861
|
+
{
|
|
15862
|
+
label: optionLabel(field, entry),
|
|
15863
|
+
disabled,
|
|
15864
|
+
onRemove: () => removeEntry(entry)
|
|
15865
|
+
},
|
|
15866
|
+
entry
|
|
15867
|
+
))
|
|
15868
|
+
}
|
|
15869
|
+
)
|
|
15870
|
+
] });
|
|
15871
|
+
}
|
|
15872
|
+
function KeywordEntryRow({
|
|
15873
|
+
label,
|
|
15874
|
+
disabled,
|
|
15875
|
+
onRemove
|
|
15876
|
+
}) {
|
|
15877
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15878
|
+
"div",
|
|
15879
|
+
{
|
|
15880
|
+
className: "group flex w-full items-center justify-between gap-[8px] text-[12px] leading-[20px]",
|
|
15881
|
+
style: {
|
|
15882
|
+
paddingTop: CHIPFILTER.itemPaddingY,
|
|
15883
|
+
paddingBottom: CHIPFILTER.itemPaddingY,
|
|
15884
|
+
paddingLeft: CHIPFILTER.itemPaddingLeft,
|
|
15885
|
+
paddingRight: CHIPFILTER.itemPaddingRight,
|
|
15886
|
+
color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.itemTextDefault
|
|
15887
|
+
},
|
|
15888
|
+
children: [
|
|
15889
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("min-w-0 truncate", !disabled && "group-hover:font-bold"), children: label }),
|
|
15890
|
+
!disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15891
|
+
"button",
|
|
15892
|
+
{
|
|
15893
|
+
type: "button",
|
|
15894
|
+
"aria-label": `${label} \uC0AD\uC81C`,
|
|
15895
|
+
className: "invisible inline-flex size-[16px] shrink-0 cursor-pointer items-center justify-center group-hover:visible",
|
|
15896
|
+
onClick: onRemove,
|
|
15897
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
15898
|
+
}
|
|
15899
|
+
)
|
|
15900
|
+
]
|
|
15901
|
+
}
|
|
15902
|
+
);
|
|
15903
|
+
}
|
|
15904
|
+
var OPTION_SEARCH_THRESHOLD = 11;
|
|
15905
|
+
function OptionList({
|
|
15906
|
+
field,
|
|
15907
|
+
value,
|
|
15908
|
+
multiple,
|
|
15909
|
+
disabled,
|
|
15910
|
+
onValueChange
|
|
15911
|
+
}) {
|
|
15912
|
+
const selected = multiple ? toArrayValue(value) : [];
|
|
15913
|
+
const singleValue = !multiple && (typeof value === "string" || typeof value === "number") ? value : null;
|
|
15914
|
+
const [search, setSearch] = react.useState("");
|
|
15915
|
+
const options = field.options ?? [];
|
|
15916
|
+
const showSearch = options.length >= OPTION_SEARCH_THRESHOLD;
|
|
15917
|
+
const filteredOptions = react.useMemo(() => {
|
|
15918
|
+
if (!showSearch || search.trim() === "") return options;
|
|
15919
|
+
const query = search.trim().toLowerCase();
|
|
15920
|
+
return options.filter((option) => option.label.toLowerCase().includes(query));
|
|
15921
|
+
}, [options, search, showSearch]);
|
|
15922
|
+
if (options.length === 0) return /* @__PURE__ */ jsxRuntime.jsx(EmptyItem, { children: "\uD45C\uC2DC\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." });
|
|
15923
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15924
|
+
"div",
|
|
15925
|
+
{
|
|
15926
|
+
className: cn(
|
|
15927
|
+
"max-h-[240px] overflow-auto",
|
|
15928
|
+
!showSearch && "pt-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
15929
|
+
"pb-[var(--cmp-chipFilter-listbox-list-paddingY)]"
|
|
15930
|
+
),
|
|
15931
|
+
children: [
|
|
15932
|
+
showSearch && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15933
|
+
"div",
|
|
15934
|
+
{
|
|
15935
|
+
className: "sticky top-0 z-[1] border-b border-solid px-[8px] pb-[4px] pt-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
15936
|
+
style: { background: CHIPFILTER.listboxBg, borderColor: CHIPFILTER.listboxBorder },
|
|
15937
|
+
children: /* @__PURE__ */ jsxRuntime.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: [
|
|
15938
|
+
/* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "search", size: 16, color: "var(--sys-color-field-icon-default)" }),
|
|
15939
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15940
|
+
"input",
|
|
15941
|
+
{
|
|
15942
|
+
value: search,
|
|
15943
|
+
disabled,
|
|
15944
|
+
placeholder: "\uAC80\uC0C9",
|
|
15945
|
+
onChange: (event) => setSearch(event.target.value),
|
|
15946
|
+
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"
|
|
15947
|
+
}
|
|
15948
|
+
),
|
|
15949
|
+
search !== "" && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15950
|
+
SGhostButton,
|
|
15951
|
+
{
|
|
15952
|
+
icon: "close",
|
|
15953
|
+
size: "xxs",
|
|
15954
|
+
ariaLabel: "\uAC80\uC0C9\uC5B4 \uC9C0\uC6B0\uAE30",
|
|
15955
|
+
className: "flex-shrink-0",
|
|
15956
|
+
onClick: () => setSearch("")
|
|
15957
|
+
}
|
|
15958
|
+
)
|
|
15959
|
+
] })
|
|
15960
|
+
}
|
|
15961
|
+
),
|
|
15962
|
+
showSearch && filteredOptions.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(EmptyItem, { children: "\uAC80\uC0C9 \uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4." }),
|
|
15963
|
+
filteredOptions.map((option) => {
|
|
15964
|
+
const checked = multiple ? selected.includes(option.value) : singleValue === option.value;
|
|
15965
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15966
|
+
MenuItem,
|
|
15967
|
+
{
|
|
15968
|
+
selected: checked,
|
|
15969
|
+
disabled: disabled || option.disabled,
|
|
15970
|
+
multi: multiple,
|
|
15971
|
+
onClick: () => {
|
|
15972
|
+
if (multiple) {
|
|
15973
|
+
const next = checked ? selected.filter((v) => v !== option.value) : [...selected, option.value];
|
|
15974
|
+
onValueChange(next);
|
|
15975
|
+
} else {
|
|
15976
|
+
onValueChange(option.value);
|
|
15977
|
+
}
|
|
15978
|
+
},
|
|
15979
|
+
children: [
|
|
15980
|
+
multiple && /* @__PURE__ */ jsxRuntime.jsx(OptionCheckbox, { checked }),
|
|
15981
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: option.label })
|
|
15982
|
+
]
|
|
15983
|
+
},
|
|
15984
|
+
String(option.value)
|
|
15985
|
+
);
|
|
15986
|
+
})
|
|
15987
|
+
]
|
|
15988
|
+
}
|
|
15989
|
+
);
|
|
15990
|
+
}
|
|
15991
|
+
function OptionCheckbox({ checked }) {
|
|
15992
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15993
|
+
"span",
|
|
15994
|
+
{
|
|
15995
|
+
className: cn(
|
|
15996
|
+
"inline-flex size-[16px] shrink-0 items-center justify-center rounded-[2px] border border-solid",
|
|
15997
|
+
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)]"
|
|
15998
|
+
),
|
|
15999
|
+
children: checked && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "checkboxCheck", size: 12, color: "var(--cmp-checkbox-checked-icon-default)" })
|
|
16000
|
+
}
|
|
16001
|
+
);
|
|
16002
|
+
}
|
|
16003
|
+
function ListBox({ children }) {
|
|
16004
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16005
|
+
"div",
|
|
16006
|
+
{
|
|
16007
|
+
className: "overflow-hidden border border-solid shadow-[var(--shadow-overlay)]",
|
|
16008
|
+
style: {
|
|
16009
|
+
borderRadius: CHIPFILTER.listboxRadius,
|
|
16010
|
+
background: CHIPFILTER.listboxBg,
|
|
16011
|
+
borderColor: CHIPFILTER.listboxBorder
|
|
16012
|
+
},
|
|
16013
|
+
children
|
|
16014
|
+
}
|
|
16015
|
+
);
|
|
16016
|
+
}
|
|
16017
|
+
function MenuItem({
|
|
16018
|
+
children,
|
|
16019
|
+
selected,
|
|
16020
|
+
disabled,
|
|
16021
|
+
multi,
|
|
16022
|
+
onMouseEnter,
|
|
16023
|
+
onClick
|
|
16024
|
+
}) {
|
|
16025
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16026
|
+
"button",
|
|
16027
|
+
{
|
|
16028
|
+
type: "button",
|
|
16029
|
+
disabled,
|
|
16030
|
+
onMouseEnter,
|
|
16031
|
+
onClick,
|
|
16032
|
+
className: cn(
|
|
16033
|
+
"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",
|
|
16034
|
+
selected ? "font-bold" : "font-normal",
|
|
16035
|
+
!disabled && "hover:font-bold"
|
|
16036
|
+
),
|
|
16037
|
+
style: {
|
|
16038
|
+
paddingTop: CHIPFILTER.itemPaddingY,
|
|
16039
|
+
paddingBottom: CHIPFILTER.itemPaddingY,
|
|
16040
|
+
paddingLeft: multi ? CHIPFILTER.itemMultiPaddingX : CHIPFILTER.itemPaddingLeft,
|
|
16041
|
+
paddingRight: multi ? CHIPFILTER.itemMultiPaddingX : CHIPFILTER.itemPaddingRight,
|
|
16042
|
+
color: disabled ? CHIPFILTER.chipDisabledText : selected ? CHIPFILTER.itemTextSelected : CHIPFILTER.itemTextDefault
|
|
16043
|
+
},
|
|
16044
|
+
children
|
|
16045
|
+
}
|
|
16046
|
+
);
|
|
16047
|
+
}
|
|
16048
|
+
function EmptyItem({ children }) {
|
|
16049
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16050
|
+
"div",
|
|
16051
|
+
{
|
|
16052
|
+
className: "text-[12px] leading-[20px]",
|
|
16053
|
+
style: {
|
|
16054
|
+
paddingTop: CHIPFILTER.itemPaddingY,
|
|
16055
|
+
paddingBottom: CHIPFILTER.itemPaddingY,
|
|
16056
|
+
paddingLeft: CHIPFILTER.itemPaddingLeft,
|
|
16057
|
+
paddingRight: CHIPFILTER.itemPaddingRight,
|
|
16058
|
+
color: CHIPFILTER.chipDisabledText
|
|
16059
|
+
},
|
|
16060
|
+
children
|
|
16061
|
+
}
|
|
16062
|
+
);
|
|
16063
|
+
}
|
|
13500
16064
|
var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
|
|
13501
16065
|
values = [],
|
|
13502
16066
|
onValueChange,
|
|
@@ -13935,7 +16499,7 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
|
|
|
13935
16499
|
}
|
|
13936
16500
|
);
|
|
13937
16501
|
});
|
|
13938
|
-
var
|
|
16502
|
+
var FONT3 = {
|
|
13939
16503
|
sm: {
|
|
13940
16504
|
fontSize: 12,
|
|
13941
16505
|
paddingX: "var(--cmp-textinput-sm-paddingX)",
|
|
@@ -13983,7 +16547,7 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
|
|
|
13983
16547
|
className,
|
|
13984
16548
|
style
|
|
13985
16549
|
}, ref) {
|
|
13986
|
-
const f =
|
|
16550
|
+
const f = FONT3[size];
|
|
13987
16551
|
const [ruleError, setRuleError] = react.useState("");
|
|
13988
16552
|
const hasValue = value !== void 0 && value !== null && String(value) !== "";
|
|
13989
16553
|
useFormField({
|
|
@@ -13997,6 +16561,10 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
|
|
|
13997
16561
|
});
|
|
13998
16562
|
const resolvedError = error || ruleError !== "";
|
|
13999
16563
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
16564
|
+
const valueTooltip = useTruncatedValueTooltip({
|
|
16565
|
+
enabled: readOnly && !disabled,
|
|
16566
|
+
text: String(value ?? "")
|
|
16567
|
+
});
|
|
14000
16568
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14001
16569
|
SField,
|
|
14002
16570
|
{
|
|
@@ -14033,7 +16601,7 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
|
|
|
14033
16601
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14034
16602
|
"input",
|
|
14035
16603
|
{
|
|
14036
|
-
ref,
|
|
16604
|
+
ref: mergeRefs(ref, valueTooltip.valueRef),
|
|
14037
16605
|
name,
|
|
14038
16606
|
type: "text",
|
|
14039
16607
|
value: value ?? "",
|
|
@@ -14059,9 +16627,12 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
|
|
|
14059
16627
|
fontSize: f.fontSize,
|
|
14060
16628
|
color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--cmp-textinput-text-default)",
|
|
14061
16629
|
...inputStyle
|
|
14062
|
-
}
|
|
16630
|
+
},
|
|
16631
|
+
onMouseEnter: valueTooltip.onMouseEnter,
|
|
16632
|
+
onMouseLeave: valueTooltip.onMouseLeave
|
|
14063
16633
|
}
|
|
14064
16634
|
),
|
|
16635
|
+
valueTooltip.tooltip,
|
|
14065
16636
|
suffix,
|
|
14066
16637
|
clearable && hasValue && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
14067
16638
|
SGhostButton,
|
|
@@ -14097,7 +16668,9 @@ var TIMEPICKER_SIZE_CONFIG = {
|
|
|
14097
16668
|
fontSize: 12,
|
|
14098
16669
|
lineHeight: 20,
|
|
14099
16670
|
minWidth: 80,
|
|
14100
|
-
fieldMinWidth: 128
|
|
16671
|
+
fieldMinWidth: 128,
|
|
16672
|
+
// 상한 등급 md
|
|
16673
|
+
fieldMaxWidth: 160
|
|
14101
16674
|
},
|
|
14102
16675
|
md: {
|
|
14103
16676
|
height: V3("md-height"),
|
|
@@ -14109,7 +16682,9 @@ var TIMEPICKER_SIZE_CONFIG = {
|
|
|
14109
16682
|
fontSize: 14,
|
|
14110
16683
|
lineHeight: 24,
|
|
14111
16684
|
minWidth: 96,
|
|
14112
|
-
fieldMinWidth: 160
|
|
16685
|
+
fieldMinWidth: 160,
|
|
16686
|
+
// 상한 등급 lg
|
|
16687
|
+
fieldMaxWidth: 240
|
|
14113
16688
|
}
|
|
14114
16689
|
};
|
|
14115
16690
|
function clampTimePart(value, min, max) {
|
|
@@ -14220,7 +16795,7 @@ function TimeSelector({
|
|
|
14220
16795
|
const renderColumn = (type) => {
|
|
14221
16796
|
const isHour = type === "hour";
|
|
14222
16797
|
const val = isHour ? displayHour : minute;
|
|
14223
|
-
const
|
|
16798
|
+
const displayValue2 = editingPart === type ? inputDraft[type] ?? "" : String(val).padStart(2, "0");
|
|
14224
16799
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14225
16800
|
"div",
|
|
14226
16801
|
{
|
|
@@ -14241,7 +16816,7 @@ function TimeSelector({
|
|
|
14241
16816
|
{
|
|
14242
16817
|
"aria-label": isHour ? "\uC2DC" : "\uBD84",
|
|
14243
16818
|
inputMode: "numeric",
|
|
14244
|
-
value:
|
|
16819
|
+
value: displayValue2,
|
|
14245
16820
|
placeholder: "-",
|
|
14246
16821
|
onFocus: () => beginEdit(type, val),
|
|
14247
16822
|
onBlur: () => endEdit(type),
|
|
@@ -14433,11 +17008,12 @@ function STimePicker({
|
|
|
14433
17008
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
14434
17009
|
width,
|
|
14435
17010
|
minWidth: dims.fieldMinWidth,
|
|
17011
|
+
maxWidth: dims.fieldMaxWidth,
|
|
14436
17012
|
disabled,
|
|
14437
17013
|
className,
|
|
14438
17014
|
style,
|
|
14439
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14440
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17015
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: commitOpen, children: [
|
|
17016
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14441
17017
|
"div",
|
|
14442
17018
|
{
|
|
14443
17019
|
ref: triggerRef,
|
|
@@ -14497,14 +17073,17 @@ function STimePicker({
|
|
|
14497
17073
|
]
|
|
14498
17074
|
}
|
|
14499
17075
|
) }),
|
|
14500
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14501
|
-
|
|
17076
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17077
|
+
RPopover10__namespace.Content,
|
|
14502
17078
|
{
|
|
14503
17079
|
side: "bottom",
|
|
14504
17080
|
align: "start",
|
|
14505
17081
|
sideOffset: 4,
|
|
14506
17082
|
alignOffset: popoverAlignOffset,
|
|
14507
|
-
className: cn(
|
|
17083
|
+
className: cn(
|
|
17084
|
+
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
17085
|
+
FLOATING_SLIDE_ANIM
|
|
17086
|
+
),
|
|
14508
17087
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14509
17088
|
TimeSelector,
|
|
14510
17089
|
{
|
|
@@ -14546,6 +17125,10 @@ var MIDDAY_FIELD_MIN_WIDTH = {
|
|
|
14546
17125
|
sm: 178,
|
|
14547
17126
|
md: 216
|
|
14548
17127
|
};
|
|
17128
|
+
var MIDDAY_FIELD_MAX_WIDTH = {
|
|
17129
|
+
sm: 240,
|
|
17130
|
+
md: 240
|
|
17131
|
+
};
|
|
14549
17132
|
function RangeTimeSelector({
|
|
14550
17133
|
value,
|
|
14551
17134
|
useMeridiem,
|
|
@@ -14663,7 +17246,7 @@ function RangeTimeSelector({
|
|
|
14663
17246
|
const { minute } = getParts(side);
|
|
14664
17247
|
const val = isHour ? getDisplayHour(side) : minute;
|
|
14665
17248
|
const currentEditingKey = getEditingKey(side, kind);
|
|
14666
|
-
const
|
|
17249
|
+
const displayValue2 = editingKey === currentEditingKey ? inputDraft[currentEditingKey] ?? "" : String(val).padStart(2, "0");
|
|
14667
17250
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14668
17251
|
"div",
|
|
14669
17252
|
{
|
|
@@ -14684,7 +17267,7 @@ function RangeTimeSelector({
|
|
|
14684
17267
|
{
|
|
14685
17268
|
"aria-label": `${side === "start" ? "\uC2DC\uC791" : "\uC885\uB8CC"} ${isHour ? "\uC2DC" : "\uBD84"}`,
|
|
14686
17269
|
inputMode: "numeric",
|
|
14687
|
-
value:
|
|
17270
|
+
value: displayValue2,
|
|
14688
17271
|
placeholder: "-",
|
|
14689
17272
|
onFocus: () => beginEdit(side, kind, val),
|
|
14690
17273
|
onBlur: () => endEdit(side, kind),
|
|
@@ -14892,11 +17475,12 @@ function STimeRangePicker({
|
|
|
14892
17475
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
14893
17476
|
width,
|
|
14894
17477
|
minWidth: effectiveUseMeridiem ? MIDDAY_FIELD_MIN_WIDTH[size] : dims.fieldMinWidth,
|
|
17478
|
+
maxWidth: effectiveUseMeridiem ? MIDDAY_FIELD_MAX_WIDTH[size] : dims.fieldMaxWidth,
|
|
14895
17479
|
disabled,
|
|
14896
17480
|
className,
|
|
14897
17481
|
style,
|
|
14898
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14899
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17482
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: commitOpen, children: [
|
|
17483
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14900
17484
|
"div",
|
|
14901
17485
|
{
|
|
14902
17486
|
ref: triggerRef,
|
|
@@ -14956,14 +17540,17 @@ function STimeRangePicker({
|
|
|
14956
17540
|
]
|
|
14957
17541
|
}
|
|
14958
17542
|
) }),
|
|
14959
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14960
|
-
|
|
17543
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17544
|
+
RPopover10__namespace.Content,
|
|
14961
17545
|
{
|
|
14962
17546
|
side: "bottom",
|
|
14963
17547
|
align: "start",
|
|
14964
17548
|
sideOffset: 4,
|
|
14965
17549
|
alignOffset: popoverAlignOffset,
|
|
14966
|
-
className: cn(
|
|
17550
|
+
className: cn(
|
|
17551
|
+
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
17552
|
+
FLOATING_SLIDE_ANIM
|
|
17553
|
+
),
|
|
14967
17554
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14968
17555
|
RangeTimeSelector,
|
|
14969
17556
|
{
|
|
@@ -14995,7 +17582,10 @@ exports.GNB_MENU_WIDTH = GNB_MENU_WIDTH;
|
|
|
14995
17582
|
exports.GNB_RAIL = GNB_RAIL;
|
|
14996
17583
|
exports.GNB_RAIL_WIDTH = GNB_RAIL_WIDTH;
|
|
14997
17584
|
exports.ICONS = ICONS;
|
|
17585
|
+
exports.IMAGE_FITS = IMAGE_FITS;
|
|
14998
17586
|
exports.PAGE_BACKGROUNDS = PAGE_BACKGROUNDS;
|
|
17587
|
+
exports.PAGE_CONTENT_HEIGHTS = PAGE_CONTENT_HEIGHTS;
|
|
17588
|
+
exports.RangeCalendar = RangeCalendar;
|
|
14999
17589
|
exports.SActionModal = SActionModal;
|
|
15000
17590
|
exports.SBadge = SBadge;
|
|
15001
17591
|
exports.SBarcodeInput = SBarcodeInput;
|
|
@@ -15006,10 +17596,13 @@ exports.SCallout = SCallout;
|
|
|
15006
17596
|
exports.SCard = SCard;
|
|
15007
17597
|
exports.SCheckbox = SCheckbox;
|
|
15008
17598
|
exports.SChip = SChip2;
|
|
17599
|
+
exports.SChipFilter = SChipFilter;
|
|
15009
17600
|
exports.SChipInput = SChipInput;
|
|
15010
17601
|
exports.SCircleProgress = SCircleProgress;
|
|
15011
17602
|
exports.SConfirmModal = SConfirmModal;
|
|
15012
17603
|
exports.SDatePicker = SDatePicker;
|
|
17604
|
+
exports.SDatePickerMonthListbox = SDatePickerMonthListbox;
|
|
17605
|
+
exports.SDatePickerYearListbox = SDatePickerYearListbox;
|
|
15013
17606
|
exports.SDateRangePicker = SDateRangePicker;
|
|
15014
17607
|
exports.SDivider = SDivider;
|
|
15015
17608
|
exports.SDraggableGroup = SDraggableGroup;
|
|
@@ -15027,6 +17620,7 @@ exports.SGhostButton = SGhostButton;
|
|
|
15027
17620
|
exports.SGnb = SGnb;
|
|
15028
17621
|
exports.SGuide = SGuide;
|
|
15029
17622
|
exports.SIcon = SIcon;
|
|
17623
|
+
exports.SImage = SImage;
|
|
15030
17624
|
exports.SInput = SInput;
|
|
15031
17625
|
exports.SKeyValueTable = SKeyValueTable;
|
|
15032
17626
|
exports.SLAYOUT_MIN_WIDTH = SLAYOUT_MIN_WIDTH;
|
|
@@ -15051,6 +17645,7 @@ exports.SRadioButton = SRadioButton;
|
|
|
15051
17645
|
exports.SRadioGroup = SRadioGroup;
|
|
15052
17646
|
exports.SSPLITTER_UNITS = SSPLITTER_UNITS;
|
|
15053
17647
|
exports.SScrollArea = SScrollArea;
|
|
17648
|
+
exports.SSearchInput = SSearchInput;
|
|
15054
17649
|
exports.SSectionHeaderCard = SSectionHeaderCard2;
|
|
15055
17650
|
exports.SSelect = SSelect2;
|
|
15056
17651
|
exports.SSplitter = SSplitter2;
|