sellmate-design-system-react 9.0.0-beta.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 +153 -45
- package/README.md +63 -0
- package/dist/components/SChipFilter/README.md +2 -1
- package/dist/components/SChipFilter/SChipFilter.d.ts +13 -6
- package/dist/components/SCircleProgress/README.md +3 -0
- package/dist/components/SCircleProgress/SCircleProgress.d.ts +7 -1
- package/dist/components/SDatePicker/README.md +41 -3
- package/dist/components/SDatePicker/SDatePicker.d.ts +36 -3
- package/dist/components/SDatePicker/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 +2 -0
- package/dist/components/SGnb/gnb.config.d.ts +2 -0
- package/dist/components/SIcon/README.md +4 -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/SList/README.md +0 -1
- package/dist/components/SList/SList.d.ts +0 -2
- package/dist/components/SPage/README.md +2 -0
- package/dist/components/SPage/SPage.d.ts +17 -1
- package/dist/components/SPage/index.d.ts +1 -1
- package/dist/components/SPage/page.config.d.ts +8 -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 +2 -0
- 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/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/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 +1545 -359
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1540 -360
- package/dist/index.js.map +1 -1
- package/dist/lib/truncated-value-tooltip.d.ts +18 -0
- package/dist/llms-full.txt +300 -69
- package/dist/llms.txt +157 -48
- package/dist/styles.css +201 -32
- 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 +1 -1
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);
|
|
@@ -3141,6 +3141,209 @@ var SIcon = /* @__PURE__ */ react.forwardRef(function SIcon2({ name, size = 24,
|
|
|
3141
3141
|
}
|
|
3142
3142
|
);
|
|
3143
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
|
+
});
|
|
3144
3347
|
var BADGE_COLORS = [
|
|
3145
3348
|
"red",
|
|
3146
3349
|
"orange",
|
|
@@ -3242,7 +3445,7 @@ var SDraggableItemView = /* @__PURE__ */ react.forwardRef(
|
|
|
3242
3445
|
!disabled && !selected && !dragging && "hover:bg-(--cmp-listDraggableItem-bg-hover)",
|
|
3243
3446
|
hasSupportingText && supportingTextPosition === "bottom" ? dense ? "min-h-[52px]" : "min-h-[60px]" : dense ? "h-[32px]" : "h-[40px]",
|
|
3244
3447
|
paddingYClass,
|
|
3245
|
-
// 항목 사이 구분선은 리스트가
|
|
3448
|
+
// 항목 사이 구분선은 리스트가 그린다.
|
|
3246
3449
|
bordered && cn(
|
|
3247
3450
|
"rounded-(--cmp-listDraggableItem-radius-bordered) border border-(--cmp-listDraggableItem-border-default)",
|
|
3248
3451
|
!disabled && !selected && !dragging && "hover:border-(--cmp-listDraggableItem-bordered-border-hover)",
|
|
@@ -3450,7 +3653,7 @@ var SDraggableItemImpl = /* @__PURE__ */ react.forwardRef(function SDraggableIte
|
|
|
3450
3653
|
] });
|
|
3451
3654
|
});
|
|
3452
3655
|
var SDraggableItem2 = /* @__PURE__ */ withDisplayName(SDraggableItemImpl, "SDraggableItem");
|
|
3453
|
-
var SListImpl = /* @__PURE__ */ react.forwardRef(function SList({ className, children, useGap = false, usePadding = false,
|
|
3656
|
+
var SListImpl = /* @__PURE__ */ react.forwardRef(function SList({ className, children, useGap = false, usePadding = false, ...rest }, ref) {
|
|
3454
3657
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3455
3658
|
"div",
|
|
3456
3659
|
{
|
|
@@ -3458,7 +3661,7 @@ var SListImpl = /* @__PURE__ */ react.forwardRef(function SList({ className, chi
|
|
|
3458
3661
|
className: cn(
|
|
3459
3662
|
useGap && "flex flex-col gap-(--cmp-list-group-gap)",
|
|
3460
3663
|
usePadding && "p-(--cmp-list-group-padding)",
|
|
3461
|
-
|
|
3664
|
+
"[&>*]:border-b [&>*]:border-(--cmp-listItem-border-default)",
|
|
3462
3665
|
className
|
|
3463
3666
|
),
|
|
3464
3667
|
...rest,
|
|
@@ -3830,7 +4033,7 @@ var SExpansionItem = /* @__PURE__ */ react.forwardRef(
|
|
|
3830
4033
|
ref,
|
|
3831
4034
|
className: cn(
|
|
3832
4035
|
"group/expansion-item relative overflow-hidden bg-(--cmp-listExpansionItem-title-bg-default)",
|
|
3833
|
-
// 항목 사이 구분선은 리스트가
|
|
4036
|
+
// 항목 사이 구분선은 리스트가 그린다.
|
|
3834
4037
|
// 보더 색은 시맨틱 토큰(border-default → hover strong → 펼침 accentLight)을 쓴다.
|
|
3835
4038
|
// TODO: expansionItem/bordered/radius 토큰 생성 후 rounded 고정값도 토큰으로 교체한다.
|
|
3836
4039
|
bordered && "rounded-[8px] border border-border-default hover:border-border-strong [&:has(>button:hover)]:border-border-strong",
|
|
@@ -4382,8 +4585,8 @@ function SGhostButton({
|
|
|
4382
4585
|
}
|
|
4383
4586
|
);
|
|
4384
4587
|
if (!hasTooltip) return btn;
|
|
4385
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4386
|
-
/* @__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(
|
|
4387
4590
|
"span",
|
|
4388
4591
|
{
|
|
4389
4592
|
className: cn("inline-flex", anchorClassName),
|
|
@@ -4395,8 +4598,8 @@ function SGhostButton({
|
|
|
4395
4598
|
children: btn
|
|
4396
4599
|
}
|
|
4397
4600
|
) }),
|
|
4398
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4399
|
-
|
|
4601
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4602
|
+
RPopover10__namespace.Content,
|
|
4400
4603
|
{
|
|
4401
4604
|
side: "top",
|
|
4402
4605
|
sideOffset: 4,
|
|
@@ -4410,6 +4613,18 @@ function SGhostButton({
|
|
|
4410
4613
|
) })
|
|
4411
4614
|
] });
|
|
4412
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
|
+
};
|
|
4413
4628
|
function collectIds(nodes) {
|
|
4414
4629
|
return nodes.flatMap((node) => [node.id, ...collectIds(node.children ?? [])]);
|
|
4415
4630
|
}
|
|
@@ -4420,18 +4635,19 @@ function collectSelectableIds(node) {
|
|
|
4420
4635
|
function toSelectedSet(value) {
|
|
4421
4636
|
return new Set(value ?? []);
|
|
4422
4637
|
}
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
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 };
|
|
4426
4642
|
}
|
|
4427
4643
|
const selectableChildren = (node.children ?? []).filter(
|
|
4428
4644
|
(child) => collectSelectableIds(child).length > 0
|
|
4429
4645
|
);
|
|
4430
4646
|
if (selectableChildren.length === 0) {
|
|
4431
|
-
return { selected:
|
|
4647
|
+
return { selected: selectedSet.has(node.id), indeterminate: false };
|
|
4432
4648
|
}
|
|
4433
4649
|
const childStates = selectableChildren.map(
|
|
4434
|
-
(child) => getSelectionState(child, selectedSet)
|
|
4650
|
+
(child) => getSelectionState(child, selectedSet, cascadeSelection)
|
|
4435
4651
|
);
|
|
4436
4652
|
const selectedCount = childStates.filter((state2) => state2.selected).length;
|
|
4437
4653
|
return {
|
|
@@ -4441,6 +4657,7 @@ function getSelectionState(node, selectedSet) {
|
|
|
4441
4657
|
}
|
|
4442
4658
|
function TreeConnector({
|
|
4443
4659
|
guideline,
|
|
4660
|
+
size,
|
|
4444
4661
|
depth,
|
|
4445
4662
|
hasChildren,
|
|
4446
4663
|
isLast,
|
|
@@ -4448,6 +4665,8 @@ function TreeConnector({
|
|
|
4448
4665
|
}) {
|
|
4449
4666
|
if (depth <= 1) return null;
|
|
4450
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]";
|
|
4451
4670
|
return /* @__PURE__ */ jsxRuntime.jsxs("span", { "aria-hidden": "true", className: "flex self-stretch", children: [
|
|
4452
4671
|
ancestorConnectors.map((last, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4453
4672
|
"span",
|
|
@@ -4461,13 +4680,22 @@ function TreeConnector({
|
|
|
4461
4680
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative block w-[20px] shrink-0", children: [
|
|
4462
4681
|
guideline && !isLast && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute bottom-0 left-[6px] top-[-1px] w-px bg-(--cmp-tree-connector-line-color)" }),
|
|
4463
4682
|
guideline && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4464
|
-
/* @__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
|
+
),
|
|
4465
4692
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4466
4693
|
"span",
|
|
4467
4694
|
{
|
|
4468
4695
|
"data-tree-connector-branch": hasChildren ? "parent" : "leaf",
|
|
4469
4696
|
className: cn(
|
|
4470
|
-
"absolute left-[6px]
|
|
4697
|
+
"absolute left-[6px] h-px bg-(--cmp-tree-connector-line-color)",
|
|
4698
|
+
branchTop,
|
|
4471
4699
|
hasChildren ? "w-[14px]" : "w-[calc(14px+var(--cmp-tree-item-arrow-icon))]"
|
|
4472
4700
|
)
|
|
4473
4701
|
}
|
|
@@ -4476,6 +4704,44 @@ function TreeConnector({
|
|
|
4476
4704
|
] })
|
|
4477
4705
|
] });
|
|
4478
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
|
+
}
|
|
4479
4745
|
var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
4480
4746
|
node,
|
|
4481
4747
|
depth = 1,
|
|
@@ -4487,6 +4753,7 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
|
4487
4753
|
border = true,
|
|
4488
4754
|
indeterminate = false,
|
|
4489
4755
|
selectable = true,
|
|
4756
|
+
size = "sm",
|
|
4490
4757
|
leading,
|
|
4491
4758
|
trailing,
|
|
4492
4759
|
onToggle,
|
|
@@ -4498,6 +4765,7 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
|
4498
4765
|
const renderState = {
|
|
4499
4766
|
node,
|
|
4500
4767
|
depth,
|
|
4768
|
+
size,
|
|
4501
4769
|
expanded,
|
|
4502
4770
|
selected,
|
|
4503
4771
|
indeterminate,
|
|
@@ -4507,6 +4775,8 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
|
4507
4775
|
const leadingNode = typeof leading === "function" ? leading(renderState) : leading;
|
|
4508
4776
|
const trailingNode = typeof trailing === "function" ? trailing(renderState) : trailing;
|
|
4509
4777
|
const checkboxValue = indeterminate ? null : selected;
|
|
4778
|
+
const typography = TREE_LABEL_TYPOGRAPHY[size];
|
|
4779
|
+
const labelTypo = selected || indeterminate ? typography.selected : typography.default;
|
|
4510
4780
|
const handleSelect = (event) => {
|
|
4511
4781
|
if (node.disabled) return;
|
|
4512
4782
|
onTreeSelect?.(node, event);
|
|
@@ -4526,7 +4796,8 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
|
4526
4796
|
"aria-disabled": node.disabled || void 0,
|
|
4527
4797
|
onClick: handleRowClick,
|
|
4528
4798
|
className: cn(
|
|
4529
|
-
"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,
|
|
4530
4801
|
border && "border-b border-(--cmp-tree-item-border-default)",
|
|
4531
4802
|
!node.disabled && "hover:bg-(--cmp-tree-item-bg-hover)",
|
|
4532
4803
|
node.disabled && "cursor-not-allowed opacity-60",
|
|
@@ -4539,13 +4810,14 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
|
4539
4810
|
TreeConnector,
|
|
4540
4811
|
{
|
|
4541
4812
|
guideline,
|
|
4813
|
+
size,
|
|
4542
4814
|
depth,
|
|
4543
4815
|
hasChildren,
|
|
4544
4816
|
isLast,
|
|
4545
4817
|
ancestorLast
|
|
4546
4818
|
}
|
|
4547
4819
|
),
|
|
4548
|
-
/* @__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: [
|
|
4549
4821
|
hasChildren ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4550
4822
|
SGhostButton,
|
|
4551
4823
|
{
|
|
@@ -4581,25 +4853,17 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
|
|
|
4581
4853
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4582
4854
|
"span",
|
|
4583
4855
|
{
|
|
4856
|
+
onClick: (event) => {
|
|
4857
|
+
if (!selectable) return;
|
|
4858
|
+
event.stopPropagation();
|
|
4859
|
+
if (!node.disabled && selectable) onTreeSelect?.(node, event);
|
|
4860
|
+
},
|
|
4584
4861
|
className: cn(
|
|
4585
|
-
"min-w-0 flex-1
|
|
4586
|
-
|
|
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
|
|
4587
4865
|
),
|
|
4588
|
-
children:
|
|
4589
|
-
"span",
|
|
4590
|
-
{
|
|
4591
|
-
onClick: (event) => {
|
|
4592
|
-
if (!selectable) return;
|
|
4593
|
-
event.stopPropagation();
|
|
4594
|
-
if (!node.disabled && selectable) onTreeSelect?.(node, event);
|
|
4595
|
-
},
|
|
4596
|
-
className: cn(
|
|
4597
|
-
"inline-block max-w-full truncate",
|
|
4598
|
-
node.disabled ? "cursor-not-allowed" : selectable ? "cursor-pointer" : void 0
|
|
4599
|
-
),
|
|
4600
|
-
children: node.label
|
|
4601
|
-
}
|
|
4602
|
-
)
|
|
4866
|
+
children: node.label
|
|
4603
4867
|
}
|
|
4604
4868
|
),
|
|
4605
4869
|
trailingNode
|
|
@@ -4616,6 +4880,8 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
|
|
|
4616
4880
|
expandedIds,
|
|
4617
4881
|
defaultExpandedIds,
|
|
4618
4882
|
selectable = true,
|
|
4883
|
+
size = "sm",
|
|
4884
|
+
useAll = false,
|
|
4619
4885
|
cascadeSelection = true,
|
|
4620
4886
|
guideline = true,
|
|
4621
4887
|
border = true,
|
|
@@ -4634,6 +4900,11 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
|
|
|
4634
4900
|
const currentExpandedIds = expandedIds ?? internalExpandedIds;
|
|
4635
4901
|
const selectedSet = react.useMemo(() => toSelectedSet(currentValue), [currentValue]);
|
|
4636
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;
|
|
4637
4908
|
const updateExpanded = (node) => {
|
|
4638
4909
|
const next = new Set(currentExpandedIds);
|
|
4639
4910
|
if (next.has(node.id)) next.delete(node.id);
|
|
@@ -4645,7 +4916,7 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
|
|
|
4645
4916
|
const updateSelected = (node) => {
|
|
4646
4917
|
if (node.disabled) return;
|
|
4647
4918
|
const targetIds = cascadeSelection ? collectSelectableIds(node) : [node.id];
|
|
4648
|
-
const everySelected = getSelectionState(node, selectedSet).selected;
|
|
4919
|
+
const everySelected = getSelectionState(node, selectedSet, cascadeSelection).selected;
|
|
4649
4920
|
const next = new Set(selectedSet);
|
|
4650
4921
|
targetIds.forEach((id) => {
|
|
4651
4922
|
if (everySelected) next.delete(id);
|
|
@@ -4655,10 +4926,22 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
|
|
|
4655
4926
|
if (value === void 0) setInternalValue(orderedIds);
|
|
4656
4927
|
onValueChange?.(orderedIds, node);
|
|
4657
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
|
+
};
|
|
4658
4941
|
const renderNodes = (nodes, depth = 1, ancestorLast = []) => nodes.map((node, index) => {
|
|
4659
4942
|
const isLast = index === nodes.length - 1;
|
|
4660
4943
|
const isExpanded = expandedSet.has(node.id);
|
|
4661
|
-
const { selected, indeterminate } = getSelectionState(node, selectedSet);
|
|
4944
|
+
const { selected, indeterminate } = getSelectionState(node, selectedSet, cascadeSelection);
|
|
4662
4945
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
|
|
4663
4946
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4664
4947
|
STreeItem2,
|
|
@@ -4671,6 +4954,7 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
|
|
|
4671
4954
|
selected,
|
|
4672
4955
|
indeterminate,
|
|
4673
4956
|
selectable,
|
|
4957
|
+
size,
|
|
4674
4958
|
guideline,
|
|
4675
4959
|
border,
|
|
4676
4960
|
leading,
|
|
@@ -4692,14 +4976,26 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
|
|
|
4692
4976
|
) : null
|
|
4693
4977
|
] }, node.id);
|
|
4694
4978
|
});
|
|
4695
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
4979
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4696
4980
|
"div",
|
|
4697
4981
|
{
|
|
4698
4982
|
ref,
|
|
4699
4983
|
role: "tree",
|
|
4700
4984
|
className: cn("flex w-full flex-col items-start bg-(--cmp-tree-item-bg-default)", className),
|
|
4701
4985
|
...rest,
|
|
4702
|
-
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
|
+
]
|
|
4703
4999
|
}
|
|
4704
5000
|
);
|
|
4705
5001
|
});
|
|
@@ -4879,14 +5175,14 @@ var STooltipImpl = /* @__PURE__ */ react.forwardRef(function STooltip({
|
|
|
4879
5175
|
...style,
|
|
4880
5176
|
...contentPropsStyle
|
|
4881
5177
|
};
|
|
4882
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5178
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: setOpenState, children: [
|
|
4883
5179
|
isNone ? (
|
|
4884
5180
|
// 트리거 없음: children 을 래퍼 없이 그대로 앵커로 쓴다 (소비자 레이아웃 보존).
|
|
4885
5181
|
// mouse/focus 핸들러가 없으므로 useClose 없이도 자동 닫힘이 발생하지 않는다.
|
|
4886
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5182
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { asChild: true, children: triggerNode })
|
|
4887
5183
|
) : isHover ? (
|
|
4888
5184
|
// hover: Anchor(위치 기준) + 직접 mouse 핸들러 — 클릭으로 토글되지 않도록 Trigger 미사용
|
|
4889
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5185
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4890
5186
|
"span",
|
|
4891
5187
|
{
|
|
4892
5188
|
className: "inline-flex",
|
|
@@ -4897,9 +5193,9 @@ var STooltipImpl = /* @__PURE__ */ react.forwardRef(function STooltip({
|
|
|
4897
5193
|
children: triggerNode
|
|
4898
5194
|
}
|
|
4899
5195
|
) })
|
|
4900
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4901
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4902
|
-
|
|
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,
|
|
4903
5199
|
{
|
|
4904
5200
|
side: placement,
|
|
4905
5201
|
sideOffset,
|
|
@@ -4933,7 +5229,7 @@ var STooltipImpl = /* @__PURE__ */ react.forwardRef(function STooltip({
|
|
|
4933
5229
|
}
|
|
4934
5230
|
)
|
|
4935
5231
|
] }),
|
|
4936
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5232
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
4937
5233
|
]
|
|
4938
5234
|
}
|
|
4939
5235
|
) })
|
|
@@ -4945,6 +5241,10 @@ var BODY_PADDING_CLASS = {
|
|
|
4945
5241
|
wide: "p-(--sys-space-panel-padding-wide)",
|
|
4946
5242
|
none: ""
|
|
4947
5243
|
};
|
|
5244
|
+
var BODY_BACKGROUND_CLASS = {
|
|
5245
|
+
frame: "",
|
|
5246
|
+
neutral: "bg-(--sys-color-bg-neutralLight)"
|
|
5247
|
+
};
|
|
4948
5248
|
var topBorderColorClass = {
|
|
4949
5249
|
default: "bg-(--cmp-sectionHeaderCard-topBorder-color-default)",
|
|
4950
5250
|
accent: "bg-(--cmp-sectionHeaderCard-topBorder-color-accent)"
|
|
@@ -4954,8 +5254,8 @@ var titleSizeClass = {
|
|
|
4954
5254
|
sm: "typo-heading-sm"
|
|
4955
5255
|
};
|
|
4956
5256
|
var SSectionHeaderCardBodyImpl = /* @__PURE__ */ react.forwardRef(
|
|
4957
|
-
function SSectionHeaderCardBody({ padding = "default",
|
|
4958
|
-
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 });
|
|
4959
5259
|
}
|
|
4960
5260
|
);
|
|
4961
5261
|
var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
|
|
@@ -4968,8 +5268,7 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
4968
5268
|
subtitle,
|
|
4969
5269
|
slot,
|
|
4970
5270
|
thickness = false,
|
|
4971
|
-
className
|
|
4972
|
-
...rest
|
|
5271
|
+
className
|
|
4973
5272
|
}, ref) {
|
|
4974
5273
|
const hasHelp = helpText != null && helpText.length > 0;
|
|
4975
5274
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -4990,7 +5289,6 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
4990
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)",
|
|
4991
5290
|
className
|
|
4992
5291
|
),
|
|
4993
|
-
...rest,
|
|
4994
5292
|
children: [
|
|
4995
5293
|
marker && /* @__PURE__ */ jsxRuntime.jsx(SBadge, { color: "darkblue", className: "shrink-0" }),
|
|
4996
5294
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 shrink-0 items-center gap-[8px]", children: [
|
|
@@ -5034,8 +5332,24 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
5034
5332
|
}
|
|
5035
5333
|
);
|
|
5036
5334
|
var SSectionHeaderCardRootImpl = /* @__PURE__ */ react.forwardRef(
|
|
5037
|
-
function SSectionHeaderCard({
|
|
5038
|
-
|
|
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(
|
|
5039
5353
|
"div",
|
|
5040
5354
|
{
|
|
5041
5355
|
ref,
|
|
@@ -5044,24 +5358,28 @@ var SSectionHeaderCardRootImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
5044
5358
|
className
|
|
5045
5359
|
),
|
|
5046
5360
|
...rest,
|
|
5047
|
-
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
|
+
]
|
|
5048
5378
|
}
|
|
5049
5379
|
);
|
|
5050
5380
|
}
|
|
5051
5381
|
);
|
|
5052
|
-
var
|
|
5053
|
-
var SSectionHeaderCardHeader2 = /* @__PURE__ */ withDisplayName(
|
|
5054
|
-
SSectionHeaderCardHeaderImpl,
|
|
5055
|
-
"SSectionHeaderCard.Header"
|
|
5056
|
-
);
|
|
5057
|
-
var SSectionHeaderCardBody2 = /* @__PURE__ */ withDisplayName(
|
|
5058
|
-
SSectionHeaderCardBodyImpl,
|
|
5059
|
-
"SSectionHeaderCard.Body"
|
|
5060
|
-
);
|
|
5061
|
-
var SSectionHeaderCard2 = /* @__PURE__ */ Object.assign(SSectionHeaderCardRoot, {
|
|
5062
|
-
Header: SSectionHeaderCardHeader2,
|
|
5063
|
-
Body: SSectionHeaderCardBody2
|
|
5064
|
-
});
|
|
5382
|
+
var SSectionHeaderCard2 = /* @__PURE__ */ withDisplayName(SSectionHeaderCardRootImpl, "SSectionHeaderCard");
|
|
5065
5383
|
var SDivider = /* @__PURE__ */ react.forwardRef(function SDivider2({ vertical = false, className, style, ...rest }, ref) {
|
|
5066
5384
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5067
5385
|
"hr",
|
|
@@ -5578,167 +5896,58 @@ var SCallout = /* @__PURE__ */ react.forwardRef(function SCallout2({ type = "def
|
|
|
5578
5896
|
),
|
|
5579
5897
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-[var(--cmp-callout-body-gap)] px-[var(--cmp-callout-body-paddingX)] py-[var(--cmp-callout-body-paddingY)] text-[12px] font-normal leading-[20px]", children: children ?? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "m-0 flex list-none flex-col justify-center gap-[var(--cmp-callout-body-gap)] p-0", children: renderItems(message) }) })
|
|
5580
5898
|
]
|
|
5581
|
-
}
|
|
5582
|
-
);
|
|
5583
|
-
});
|
|
5584
|
-
var FILL_COLOR = {
|
|
5585
|
-
primary: "var(--cmp-progress-active
|
|
5586
|
-
error: "var(--cmp-progress-error
|
|
5587
|
-
complete: "var(--cmp-progress-success
|
|
5588
|
-
};
|
|
5589
|
-
var
|
|
5590
|
-
var SLinearProgress = /* @__PURE__ */ react.forwardRef(
|
|
5591
|
-
function SLinearProgress2({ value = 0, type = "primary", indeterminate = false, label, className, style }, ref) {
|
|
5592
|
-
const v =
|
|
5593
|
-
const fill = FILL_COLOR[type];
|
|
5594
|
-
const valueColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : fill;
|
|
5595
|
-
const valueText = `${Math.round(v)}%`;
|
|
5596
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5597
|
-
"div",
|
|
5598
|
-
{
|
|
5599
|
-
ref,
|
|
5600
|
-
className: cn("inline-flex w-full flex-col gap-[12px]", className),
|
|
5601
|
-
style,
|
|
5602
|
-
children: [
|
|
5603
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-[20px] w-full overflow-hidden rounded-full bg-[var(--cmp-progress-color-track)]", children: [
|
|
5604
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5605
|
-
"div",
|
|
5606
|
-
{
|
|
5607
|
-
className: cn(
|
|
5608
|
-
"absolute inset-y-0 left-0 h-full rounded-[inherit]",
|
|
5609
|
-
indeterminate ? "w-full origin-left animate-linear-indeterminate" : "transition-[width] duration-[400ms] ease-linear"
|
|
5610
|
-
),
|
|
5611
|
-
style: { background: fill, width: indeterminate ? void 0 : `${v}%` }
|
|
5612
|
-
}
|
|
5613
|
-
),
|
|
5614
|
-
!indeterminate && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5615
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5616
|
-
"span",
|
|
5617
|
-
{
|
|
5618
|
-
className: "pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2 select-none text-center text-[12px] font-bold leading-[20px]",
|
|
5619
|
-
style: { color: valueColor },
|
|
5620
|
-
children: valueText
|
|
5621
|
-
}
|
|
5622
|
-
),
|
|
5623
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5624
|
-
"span",
|
|
5625
|
-
{
|
|
5626
|
-
className: "pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2 select-none text-center text-[12px] font-bold leading-[20px] text-[color:var(--cmp-progress-bar-text)]",
|
|
5627
|
-
style: { clipPath: `inset(0 ${100 - v}% 0 0)` },
|
|
5628
|
-
children: valueText
|
|
5629
|
-
}
|
|
5630
|
-
)
|
|
5631
|
-
] })
|
|
5632
|
-
] }),
|
|
5633
|
-
label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]", children: label })
|
|
5634
|
-
]
|
|
5635
|
-
}
|
|
5636
|
-
);
|
|
5637
|
-
}
|
|
5638
|
-
);
|
|
5639
|
-
var VIEWBOX = 80;
|
|
5640
|
-
var RADIUS = 34;
|
|
5641
|
-
var STROKE = 12;
|
|
5642
|
-
var CIRCUMFERENCE = 2 * Math.PI * RADIUS;
|
|
5643
|
-
var COLOR_MAP = {
|
|
5644
|
-
primary: { arc: "var(--cmp-progress-active-color)", track: "var(--cmp-progress-color-track)" },
|
|
5645
|
-
// inverse: 어두운 배경용 — arc 흰색, track 은 흰색 40%(회색 링)
|
|
5646
|
-
inverse: { arc: "var(--color-white)", track: "rgba(255,255,255,0.4)" },
|
|
5647
|
-
error: { arc: "var(--color-red-75)", track: "var(--cmp-progress-color-track)" },
|
|
5648
|
-
complete: { arc: "#01BB4B", track: "var(--cmp-progress-color-track)" }
|
|
5649
|
-
};
|
|
5650
|
-
var clamp2 = (v) => Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;
|
|
5651
|
-
var SCircleProgress = /* @__PURE__ */ react.forwardRef(
|
|
5652
|
-
function SCircleProgress2({
|
|
5653
|
-
value = 0,
|
|
5654
|
-
type = "primary",
|
|
5655
|
-
indeterminate = false,
|
|
5656
|
-
label,
|
|
5657
|
-
innerValue = false,
|
|
5658
|
-
className,
|
|
5659
|
-
style
|
|
5660
|
-
}, ref) {
|
|
5661
|
-
const v = clamp2(value);
|
|
5662
|
-
const colors = COLOR_MAP[type];
|
|
5663
|
-
const c = VIEWBOX / 2;
|
|
5664
|
-
const percentColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : colors.arc;
|
|
5665
|
-
const filled = v / 100 * CIRCUMFERENCE;
|
|
5666
|
-
const showPercent = !indeterminate;
|
|
5667
|
-
const percentNode = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5668
|
-
"span",
|
|
5669
|
-
{
|
|
5670
|
-
className: cn(
|
|
5671
|
-
"text-center text-[16px] font-bold",
|
|
5672
|
-
innerValue ? (
|
|
5673
|
-
// leading-[normal]: 26px leading 은 폰트 content(19px) 위아래로 홀수(7px)만큼 남아
|
|
5674
|
-
// 3px/4px 로 쪼개지고 글자가 링 중심보다 위로 뜬다. (leading-normal 은 1.5 라 동일 문제)
|
|
5675
|
-
"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 leading-[normal]"
|
|
5676
|
-
) : "leading-[26px]"
|
|
5677
|
-
),
|
|
5678
|
-
style: { color: percentColor },
|
|
5679
|
-
children: [
|
|
5680
|
-
Math.round(v),
|
|
5681
|
-
"%"
|
|
5682
|
-
]
|
|
5683
|
-
}
|
|
5684
|
-
);
|
|
5685
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5686
|
-
"div",
|
|
5687
|
-
{
|
|
5688
|
-
ref,
|
|
5689
|
-
className: cn(
|
|
5690
|
-
"inline-flex flex-col items-center gap-[var(--cmp-progress-circular-gap)]",
|
|
5691
|
-
className
|
|
5692
|
-
),
|
|
5693
|
-
style,
|
|
5694
|
-
children: [
|
|
5695
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(innerValue && "relative"), children: [
|
|
5696
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5697
|
-
"svg",
|
|
5698
|
-
{
|
|
5699
|
-
viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
|
|
5700
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
5701
|
-
className: cn(
|
|
5702
|
-
"h-[80px] w-[80px]",
|
|
5703
|
-
indeterminate && "origin-center animate-circle-spin"
|
|
5704
|
-
),
|
|
5705
|
-
children: [
|
|
5706
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5707
|
-
"circle",
|
|
5708
|
-
{
|
|
5709
|
-
cx: c,
|
|
5710
|
-
cy: c,
|
|
5711
|
-
r: RADIUS,
|
|
5712
|
-
fill: "none",
|
|
5713
|
-
strokeWidth: STROKE,
|
|
5714
|
-
style: { stroke: colors.track }
|
|
5715
|
-
}
|
|
5716
|
-
),
|
|
5717
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5718
|
-
"circle",
|
|
5719
|
-
{
|
|
5720
|
-
cx: c,
|
|
5721
|
-
cy: c,
|
|
5722
|
-
r: RADIUS,
|
|
5723
|
-
fill: "none",
|
|
5724
|
-
strokeWidth: STROKE,
|
|
5725
|
-
strokeLinecap: "round",
|
|
5726
|
-
className: cn(
|
|
5727
|
-
"origin-center",
|
|
5728
|
-
indeterminate ? "animate-circle-arc" : "-rotate-90 transition-[stroke-dasharray] duration-[400ms] ease-linear"
|
|
5729
|
-
),
|
|
5730
|
-
style: {
|
|
5731
|
-
stroke: colors.arc,
|
|
5732
|
-
...indeterminate ? {} : { strokeDasharray: `${filled} ${CIRCUMFERENCE}`, strokeDashoffset: 0 }
|
|
5733
|
-
}
|
|
5734
|
-
}
|
|
5735
|
-
)
|
|
5736
|
-
]
|
|
5899
|
+
}
|
|
5900
|
+
);
|
|
5901
|
+
});
|
|
5902
|
+
var FILL_COLOR = {
|
|
5903
|
+
primary: "var(--cmp-progress-color-active)",
|
|
5904
|
+
error: "var(--cmp-progress-color-error)",
|
|
5905
|
+
complete: "var(--cmp-progress-color-success)"
|
|
5906
|
+
};
|
|
5907
|
+
var clamp2 = (v) => Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;
|
|
5908
|
+
var SLinearProgress = /* @__PURE__ */ react.forwardRef(
|
|
5909
|
+
function SLinearProgress2({ value = 0, type = "primary", indeterminate = false, label, className, style }, ref) {
|
|
5910
|
+
const v = clamp2(value);
|
|
5911
|
+
const fill = FILL_COLOR[type];
|
|
5912
|
+
const valueColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : fill;
|
|
5913
|
+
const valueText = `${Math.round(v)}%`;
|
|
5914
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5915
|
+
"div",
|
|
5916
|
+
{
|
|
5917
|
+
ref,
|
|
5918
|
+
className: cn("inline-flex w-full flex-col gap-[12px]", className),
|
|
5919
|
+
style,
|
|
5920
|
+
children: [
|
|
5921
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-[20px] w-full overflow-hidden rounded-full bg-[var(--cmp-progress-color-track)]", children: [
|
|
5922
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5923
|
+
"div",
|
|
5924
|
+
{
|
|
5925
|
+
className: cn(
|
|
5926
|
+
"absolute inset-y-0 left-0 h-full rounded-[inherit]",
|
|
5927
|
+
indeterminate ? "w-full origin-left animate-linear-indeterminate" : "transition-[width] duration-[400ms] ease-linear"
|
|
5928
|
+
),
|
|
5929
|
+
style: { background: fill, width: indeterminate ? void 0 : `${v}%` }
|
|
5737
5930
|
}
|
|
5738
5931
|
),
|
|
5739
|
-
|
|
5932
|
+
!indeterminate && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5933
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5934
|
+
"span",
|
|
5935
|
+
{
|
|
5936
|
+
className: "pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2 select-none text-center text-[12px] font-bold leading-[20px]",
|
|
5937
|
+
style: { color: valueColor },
|
|
5938
|
+
children: valueText
|
|
5939
|
+
}
|
|
5940
|
+
),
|
|
5941
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5942
|
+
"span",
|
|
5943
|
+
{
|
|
5944
|
+
className: "pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2 select-none text-center text-[12px] font-bold leading-[20px] text-[color:var(--cmp-progress-bar-text)]",
|
|
5945
|
+
style: { clipPath: `inset(0 ${100 - v}% 0 0)` },
|
|
5946
|
+
children: valueText
|
|
5947
|
+
}
|
|
5948
|
+
)
|
|
5949
|
+
] })
|
|
5740
5950
|
] }),
|
|
5741
|
-
showPercent && !innerValue && percentNode,
|
|
5742
5951
|
label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]", children: label })
|
|
5743
5952
|
]
|
|
5744
5953
|
}
|
|
@@ -6230,10 +6439,15 @@ function SSwitch({
|
|
|
6230
6439
|
}
|
|
6231
6440
|
);
|
|
6232
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
|
+
};
|
|
6233
6446
|
function SToggle({
|
|
6234
6447
|
value = false,
|
|
6235
6448
|
label = "",
|
|
6236
6449
|
disabled = false,
|
|
6450
|
+
size = "sm",
|
|
6237
6451
|
onValueChange,
|
|
6238
6452
|
className,
|
|
6239
6453
|
style
|
|
@@ -6249,7 +6463,8 @@ function SToggle({
|
|
|
6249
6463
|
"aria-pressed": value,
|
|
6250
6464
|
onClick: () => !disabled && onValueChange?.(!value),
|
|
6251
6465
|
className: cn(
|
|
6252
|
-
"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],
|
|
6253
6468
|
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
6254
6469
|
// 미선택(off) hover 시 파란 채움 + 흰 글자
|
|
6255
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)]",
|
|
@@ -6301,10 +6516,10 @@ function SPopover({
|
|
|
6301
6516
|
const descColor = type === "default" ? "var(--cmp-popover-default-description)" : "var(--cmp-popover-light-description)";
|
|
6302
6517
|
const leftLinkLabelClass = type === "default" ? "text-[color:var(--cmp-popover-default-subAction)]" : "text-[color:var(--cmp-popover-light-subAction)]";
|
|
6303
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 }) });
|
|
6304
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6305
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6306
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6307
|
-
|
|
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,
|
|
6308
6523
|
{
|
|
6309
6524
|
side: placement,
|
|
6310
6525
|
sideOffset: 8,
|
|
@@ -6370,7 +6585,7 @@ function SPopover({
|
|
|
6370
6585
|
]
|
|
6371
6586
|
}
|
|
6372
6587
|
),
|
|
6373
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6588
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
6374
6589
|
]
|
|
6375
6590
|
}
|
|
6376
6591
|
) })
|
|
@@ -6401,7 +6616,7 @@ function SPortal({
|
|
|
6401
6616
|
const portalContainer = usePortalContainer();
|
|
6402
6617
|
const { minWidth: styleMinWidth, maxWidth: styleMaxWidth, ...restStyle } = style ?? {};
|
|
6403
6618
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6404
|
-
|
|
6619
|
+
RPopover10__namespace.Root,
|
|
6405
6620
|
{
|
|
6406
6621
|
open,
|
|
6407
6622
|
onOpenChange: (next) => {
|
|
@@ -6409,9 +6624,9 @@ function SPortal({
|
|
|
6409
6624
|
if (!next) onClose?.();
|
|
6410
6625
|
},
|
|
6411
6626
|
children: [
|
|
6412
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6413
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6414
|
-
|
|
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,
|
|
6415
6630
|
{
|
|
6416
6631
|
side: placement,
|
|
6417
6632
|
align,
|
|
@@ -6609,10 +6824,10 @@ function SGuide({
|
|
|
6609
6824
|
);
|
|
6610
6825
|
if (isNotion)
|
|
6611
6826
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { className, style, children: trigger });
|
|
6612
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6613
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6614
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6615
|
-
|
|
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,
|
|
6616
6831
|
{
|
|
6617
6832
|
side: "bottom",
|
|
6618
6833
|
align: "start",
|
|
@@ -6795,7 +7010,7 @@ function SModalContainer({
|
|
|
6795
7010
|
"div",
|
|
6796
7011
|
{
|
|
6797
7012
|
className: cn(
|
|
6798
|
-
"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",
|
|
6799
7014
|
shaking && "animate-modal-shake",
|
|
6800
7015
|
className
|
|
6801
7016
|
),
|
|
@@ -7052,7 +7267,7 @@ function SActionModal({
|
|
|
7052
7267
|
showClose: true,
|
|
7053
7268
|
width,
|
|
7054
7269
|
height,
|
|
7055
|
-
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)]",
|
|
7056
7271
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-auto flex-col", children: [
|
|
7057
7272
|
/* @__PURE__ */ jsxRuntime.jsx(SOverlayHeader, { title: modalTitle, description, reserveCloseSpace: true }),
|
|
7058
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 }),
|
|
@@ -7945,15 +8160,21 @@ var GNB_MENU = {
|
|
|
7945
8160
|
depth2PaddingLeft: box("item-depth2-paddingLeft"),
|
|
7946
8161
|
depth3PaddingLeft: box("item-depth3-paddingLeft"),
|
|
7947
8162
|
depth1Icon: box("item-depth1-icon"),
|
|
8163
|
+
// box 는 depth1 전용 타이포 토큰이 없어 depth1 도 selected 타이포를 따른다
|
|
7948
8164
|
depth1FontSize: 14,
|
|
7949
8165
|
// token: gnb.box.item.typography.selected.fontSize
|
|
7950
8166
|
depth1LineHeight: 24,
|
|
7951
8167
|
// token: gnb.box.item.typography.selected.lineHeight
|
|
7952
|
-
depth1FontWeight:
|
|
8168
|
+
depth1FontWeight: 600,
|
|
8169
|
+
// token: gnb.box.item.typography.selected.fontWeight
|
|
7953
8170
|
itemFontSize: 14,
|
|
7954
8171
|
// token: gnb.box.item.typography.default.fontSize
|
|
7955
|
-
itemLineHeight: 24
|
|
8172
|
+
itemLineHeight: 24,
|
|
7956
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
|
|
7957
8178
|
},
|
|
7958
8179
|
belt: {
|
|
7959
8180
|
bodyPaddingY: gnb("body-padding"),
|
|
@@ -7975,10 +8196,15 @@ var GNB_MENU = {
|
|
|
7975
8196
|
depth1LineHeight: 22,
|
|
7976
8197
|
// token: gnb.belt.item.depth1.typography.lineHeight
|
|
7977
8198
|
depth1FontWeight: 700,
|
|
8199
|
+
// token: gnb.belt.item.depth1.typography.fontWeight
|
|
7978
8200
|
itemFontSize: 12,
|
|
7979
8201
|
// token: gnb.belt.item.typography.default.fontSize
|
|
7980
|
-
itemLineHeight: 20
|
|
8202
|
+
itemLineHeight: 20,
|
|
7981
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
|
|
7982
8208
|
}
|
|
7983
8209
|
};
|
|
7984
8210
|
var GNB_COLORS = {
|
|
@@ -8276,7 +8502,7 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
|
|
|
8276
8502
|
fontFamily: "inherit",
|
|
8277
8503
|
fontSize: depth === 1 ? M.depth1FontSize : M.itemFontSize,
|
|
8278
8504
|
lineHeight: `${depth === 1 ? M.depth1LineHeight : M.itemLineHeight}px`,
|
|
8279
|
-
fontWeight: depth === 1
|
|
8505
|
+
fontWeight: depth === 1 ? M.depth1FontWeight : isSelected ? M.itemFontWeightSelected : M.itemFontWeight,
|
|
8280
8506
|
opacity: item.disabled ? 0.4 : 1,
|
|
8281
8507
|
cursor: item.disabled ? "not-allowed" : "pointer"
|
|
8282
8508
|
};
|
|
@@ -8693,10 +8919,10 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
|
|
|
8693
8919
|
}
|
|
8694
8920
|
),
|
|
8695
8921
|
header === "fix" && menuResizeHandle,
|
|
8696
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8697
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8698
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8699
|
-
|
|
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,
|
|
8700
8926
|
{
|
|
8701
8927
|
side: "right",
|
|
8702
8928
|
sideOffset: 4,
|
|
@@ -8767,13 +8993,156 @@ var SPageHeader = /* @__PURE__ */ withDisplayName(
|
|
|
8767
8993
|
);
|
|
8768
8994
|
var MIN_CONTENT_WIDTH = `calc(var(${SLAYOUT_MIN_WIDTH_VAR}, 0px) - 100cqw + 100%)`;
|
|
8769
8995
|
var BACKGROUND_CLASS = {
|
|
8770
|
-
frame:
|
|
8771
|
-
neutral:
|
|
8772
|
-
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 };
|
|
9020
|
+
};
|
|
9021
|
+
var setForwardedRef = (ref, node) => {
|
|
9022
|
+
if (typeof ref === "function") {
|
|
9023
|
+
ref(node);
|
|
9024
|
+
return;
|
|
9025
|
+
}
|
|
9026
|
+
if (ref) ref.current = node;
|
|
8773
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
|
+
}
|
|
8774
9141
|
var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
|
|
8775
9142
|
background = "frame",
|
|
8776
9143
|
scrollEndSpacing = true,
|
|
9144
|
+
overlayScrollbar = false,
|
|
9145
|
+
contentHeight = "auto",
|
|
8777
9146
|
header,
|
|
8778
9147
|
className,
|
|
8779
9148
|
style,
|
|
@@ -8783,29 +9152,71 @@ var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
|
|
|
8783
9152
|
}, ref) {
|
|
8784
9153
|
const layout = react.useContext(SLayoutContext);
|
|
8785
9154
|
const gridStyle = layout?.header === "full" ? { gridArea: "page" } : void 0;
|
|
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
|
+
);
|
|
8786
9163
|
const [scrolled, setScrolled] = react.useState(false);
|
|
8787
9164
|
const handleScroll = (e) => {
|
|
8788
9165
|
onScroll?.(e);
|
|
8789
9166
|
if (header != null && !header.fix) setScrolled(e.currentTarget.scrollTop > 0);
|
|
8790
9167
|
};
|
|
9168
|
+
const fill = contentHeight === "fill";
|
|
8791
9169
|
const main = /* @__PURE__ */ jsxRuntime.jsx(
|
|
8792
9170
|
"main",
|
|
8793
9171
|
{
|
|
8794
|
-
ref,
|
|
9172
|
+
ref: setMainRef,
|
|
8795
9173
|
className: cn(
|
|
8796
9174
|
"box-border min-h-0 min-w-0 flex-1 overflow-auto p-[var(--cmp-pageBody-padding-default)]",
|
|
8797
|
-
|
|
8798
|
-
|
|
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]}`,
|
|
8799
9178
|
BACKGROUND_CLASS[background],
|
|
8800
9179
|
className
|
|
8801
9180
|
),
|
|
8802
|
-
style: header == null ? { ...gridStyle, ...style } : style,
|
|
9181
|
+
style: header == null && !overlayScrollbar ? { ...gridStyle, ...style } : style,
|
|
8803
9182
|
onScroll: handleScroll,
|
|
8804
9183
|
...rest,
|
|
8805
|
-
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 })
|
|
8806
9185
|
}
|
|
8807
9186
|
);
|
|
8808
|
-
if (
|
|
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
|
+
}
|
|
8809
9220
|
return (
|
|
8810
9221
|
// fix 가 아닌 헤더는 자기 배경이 투명이라(SPageHeader.tsx) 이 배경이 그대로 비친다 —
|
|
8811
9222
|
// 그래서 SPage 의 background 를 main 뿐 아니라 여기에도 칠한다(스크롤바 관련 클래스는
|
|
@@ -8817,7 +9228,10 @@ var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
|
|
|
8817
9228
|
style: gridStyle,
|
|
8818
9229
|
children: [
|
|
8819
9230
|
/* @__PURE__ */ jsxRuntime.jsx(SPageHeader, { ...header, scrolled }),
|
|
8820
|
-
|
|
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
|
+
] })
|
|
8821
9235
|
]
|
|
8822
9236
|
}
|
|
8823
9237
|
)
|
|
@@ -8826,12 +9240,10 @@ var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
|
|
|
8826
9240
|
|
|
8827
9241
|
// src/components/SPage/page.config.ts
|
|
8828
9242
|
var PAGE_BACKGROUNDS = ["frame", "neutral", "screen"];
|
|
9243
|
+
var PAGE_CONTENT_HEIGHTS = ["auto", "fill"];
|
|
8829
9244
|
|
|
8830
9245
|
// src/components/STabs/tabs.config.ts
|
|
8831
|
-
var TAB_MAIN_SIZE = {
|
|
8832
|
-
md: { height: 36, paddingX: 24 },
|
|
8833
|
-
lg: { height: 44, paddingX: 32 }
|
|
8834
|
-
};
|
|
9246
|
+
var TAB_MAIN_SIZE = { height: 36, paddingX: 24 };
|
|
8835
9247
|
var TAB_TYPOGRAPHY = { fontSize: 12, lineHeight: 20 };
|
|
8836
9248
|
var TAB_MAIN_COLORS = {
|
|
8837
9249
|
selected: {
|
|
@@ -8853,13 +9265,11 @@ function STabs({
|
|
|
8853
9265
|
value,
|
|
8854
9266
|
tabs,
|
|
8855
9267
|
onValueChange,
|
|
8856
|
-
size = "md",
|
|
8857
9268
|
isSub = false,
|
|
8858
9269
|
vertical = false,
|
|
8859
9270
|
className,
|
|
8860
9271
|
style
|
|
8861
9272
|
}) {
|
|
8862
|
-
const s = TAB_MAIN_SIZE[size];
|
|
8863
9273
|
const blue = TAB_MAIN_COLORS.selected.border;
|
|
8864
9274
|
const isVertical = isSub && vertical;
|
|
8865
9275
|
const tabRefs = react.useRef([]);
|
|
@@ -8900,8 +9310,8 @@ function STabs({
|
|
|
8900
9310
|
const border = selected ? TAB_MAIN_COLORS.selected.border : TAB_MAIN_COLORS.default.border;
|
|
8901
9311
|
const selectedBg = TAB_MAIN_COLORS.selected.bg;
|
|
8902
9312
|
tabStyle = {
|
|
8903
|
-
height:
|
|
8904
|
-
padding: `0 ${
|
|
9313
|
+
height: TAB_MAIN_SIZE.height,
|
|
9314
|
+
padding: `0 ${TAB_MAIN_SIZE.paddingX}px`,
|
|
8905
9315
|
fontSize: TAB_TYPOGRAPHY.fontSize,
|
|
8906
9316
|
lineHeight: `${TAB_TYPOGRAPHY.lineHeight}px`,
|
|
8907
9317
|
background: selected ? TAB_MAIN_COLORS.selected.bg : TAB_MAIN_COLORS.default.bg,
|
|
@@ -9643,6 +10053,7 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
|
|
|
9643
10053
|
readOnly = false,
|
|
9644
10054
|
width,
|
|
9645
10055
|
minWidth,
|
|
10056
|
+
maxWidth,
|
|
9646
10057
|
multiline = false,
|
|
9647
10058
|
borderless = false,
|
|
9648
10059
|
children,
|
|
@@ -9678,7 +10089,10 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
|
|
|
9678
10089
|
const resolvedSuccess = status === "pass";
|
|
9679
10090
|
const showError = resolvedError && errorMessage !== "";
|
|
9680
10091
|
const interactive = !disabled && !readOnly;
|
|
9681
|
-
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;
|
|
9682
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)";
|
|
9683
10097
|
const bgColor = borderless ? "transparent" : disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
|
|
9684
10098
|
const textColor = disabled ? "var(--color-grey-65)" : readOnly ? "var(--sys-color-field-text-readOnly)" : "var(--sys-color-field-text-default)";
|
|
@@ -9734,8 +10148,12 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
|
|
|
9734
10148
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9735
10149
|
"div",
|
|
9736
10150
|
{
|
|
9737
|
-
className: cn("flex min-w-0 flex-col", !hug && "flex-1"),
|
|
9738
|
-
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
|
+
},
|
|
9739
10157
|
children: [
|
|
9740
10158
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9741
10159
|
"div",
|
|
@@ -10490,6 +10908,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
10490
10908
|
height,
|
|
10491
10909
|
stickyColumn,
|
|
10492
10910
|
radius = "default",
|
|
10911
|
+
bordered = true,
|
|
10493
10912
|
noDataLabel = "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
10494
10913
|
noDataSlot,
|
|
10495
10914
|
isLoading = false,
|
|
@@ -10748,7 +11167,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
10748
11167
|
};
|
|
10749
11168
|
const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[var(--cmp-table-radius)] rounded-t-none" : "rounded-[var(--cmp-table-radius)]";
|
|
10750
11169
|
const cellPadY = dense ? "var(--cmp-table-body-paddingY-dense)" : "var(--cmp-table-body-paddingY-default)";
|
|
10751
|
-
const
|
|
11170
|
+
const cellPadXOf = (col) => col.contentType === "control" ? "var(--cmp-table-body-paddingX-default)" : "var(--cmp-table-body-paddingX-wide)";
|
|
10752
11171
|
const rowH = dense ? "var(--cmp-table-body-dense-height)" : "var(--cmp-table-body-default-height)";
|
|
10753
11172
|
const totalColSpan = visibleCols.length + (selectable ? 1 : 0);
|
|
10754
11173
|
const stickyInfo = (i) => {
|
|
@@ -10802,7 +11221,8 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
10802
11221
|
// 만으로는 스태킹 컨텍스트가 생기지 않아, 모달 안에 들어가면 30·31이 모달 Content
|
|
10803
11222
|
// 레벨까지 올라가 같은 컨텍스트의 floating portal 밴드(z-2)를 덮는다.
|
|
10804
11223
|
// 자손은 이미 overflow-hidden으로 클리핑되므로 테이블 내부 순서는 달라지지 않는다.
|
|
10805
|
-
"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)]",
|
|
10806
11226
|
// height가 없으면 루트가 받은 높이를 끝까지 채운다. 호스트가 className으로
|
|
10807
11227
|
// `flex-1 min-h-0` 등을 줘 루트 높이가 확정된 경우, 행이 적어도 테두리 박스가
|
|
10808
11228
|
// 남은 영역을 그대로 차지한다. basis는 auto로 둬 높이가 확정되지 않은
|
|
@@ -10972,9 +11392,10 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
10972
11392
|
stickyShadowClass(i),
|
|
10973
11393
|
typeof col.tdClass === "function" ? col.tdClass(row) : col.tdClass
|
|
10974
11394
|
);
|
|
11395
|
+
const tdPadX = cellPadXOf(col);
|
|
10975
11396
|
const tdStyle = {
|
|
10976
|
-
paddingLeft:
|
|
10977
|
-
paddingRight:
|
|
11397
|
+
paddingLeft: tdPadX,
|
|
11398
|
+
paddingRight: tdPadX,
|
|
10978
11399
|
paddingTop: cellPadY,
|
|
10979
11400
|
paddingBottom: cellPadY,
|
|
10980
11401
|
textAlign: col.align ?? "left",
|
|
@@ -11027,19 +11448,29 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
11027
11448
|
// SPagination은 전체 폭 기준 중앙, rows-per-page SSelect는 우측에 absolute 배치해 중앙 정렬을 유지한다.
|
|
11028
11449
|
// 루트 높이가 확정된 경우(테이블이 남은 영역을 채우는 배치) 페이지네이션 바가
|
|
11029
11450
|
// 눌리지 않도록 shrink-0으로 48px를 보장한다.
|
|
11030
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
11031
|
-
|
|
11032
|
-
|
|
11033
|
-
|
|
11034
|
-
|
|
11035
|
-
|
|
11036
|
-
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
|
|
11040
|
-
|
|
11041
|
-
|
|
11042
|
-
|
|
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
|
+
)
|
|
11043
11474
|
]
|
|
11044
11475
|
}
|
|
11045
11476
|
);
|
|
@@ -11102,6 +11533,67 @@ var STableBar = /* @__PURE__ */ react.forwardRef(function STableBar2({ total, se
|
|
|
11102
11533
|
|
|
11103
11534
|
// src/lib/autofill.ts
|
|
11104
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]";
|
|
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
|
+
}
|
|
11105
11597
|
var FONT = {
|
|
11106
11598
|
sm: { fontSize: 12, lineHeight: 20, paddingX: "var(--cmp-textinput-sm-paddingX)" },
|
|
11107
11599
|
md: { fontSize: 14, lineHeight: 24, paddingX: "var(--cmp-textinput-md-paddingX)" }
|
|
@@ -11159,6 +11651,10 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
|
|
|
11159
11651
|
const resolvedError = error || ruleError !== "";
|
|
11160
11652
|
const resolvedErrorMessage = ruleError !== "" ? ruleError : errorMessage;
|
|
11161
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
|
+
});
|
|
11162
11658
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
11163
11659
|
SField,
|
|
11164
11660
|
{
|
|
@@ -11199,7 +11695,7 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
|
|
|
11199
11695
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11200
11696
|
"input",
|
|
11201
11697
|
{
|
|
11202
|
-
ref,
|
|
11698
|
+
ref: mergeRefs(ref, valueTooltip.valueRef),
|
|
11203
11699
|
type: inputType,
|
|
11204
11700
|
value: value ?? "",
|
|
11205
11701
|
disabled,
|
|
@@ -11224,9 +11720,18 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
|
|
|
11224
11720
|
color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--sys-color-field-text-default)",
|
|
11225
11721
|
...inputStyle
|
|
11226
11722
|
},
|
|
11227
|
-
...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
|
+
}
|
|
11228
11732
|
}
|
|
11229
11733
|
),
|
|
11734
|
+
valueTooltip.tooltip,
|
|
11230
11735
|
suffix != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-shrink-0 items-center", children: suffix }),
|
|
11231
11736
|
clearable && hasValue && !disabled && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11232
11737
|
SGhostButton,
|
|
@@ -11460,8 +11965,10 @@ var SNumberInput = /* @__PURE__ */ react.forwardRef(function SNumberInput2({
|
|
|
11460
11965
|
const [display, setDisplay] = react.useState(() => formatWithCommas(numValue));
|
|
11461
11966
|
const [ruleError, setRuleError] = react.useState("");
|
|
11462
11967
|
const innerRef = react.useRef(null);
|
|
11968
|
+
const valueTooltip = useTruncatedValueTooltip({ enabled: readOnly && !disabled, text: display });
|
|
11463
11969
|
const setRefs2 = (el) => {
|
|
11464
11970
|
innerRef.current = el;
|
|
11971
|
+
valueTooltip.valueRef.current = el;
|
|
11465
11972
|
if (typeof ref === "function") ref(el);
|
|
11466
11973
|
else if (ref) ref.current = el;
|
|
11467
11974
|
};
|
|
@@ -11675,9 +12182,12 @@ var SNumberInput = /* @__PURE__ */ react.forwardRef(function SNumberInput2({
|
|
|
11675
12182
|
textAlign: useButton ? "center" : "right",
|
|
11676
12183
|
color: disabled ? "var(--cmp-numberInput-text-disabled)" : "var(--cmp-numberInput-text-default)",
|
|
11677
12184
|
...inputStyle
|
|
11678
|
-
}
|
|
12185
|
+
},
|
|
12186
|
+
onMouseEnter: valueTooltip.onMouseEnter,
|
|
12187
|
+
onMouseLeave: valueTooltip.onMouseLeave
|
|
11679
12188
|
}
|
|
11680
12189
|
),
|
|
12190
|
+
valueTooltip.tooltip,
|
|
11681
12191
|
inputSuffix !== "" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", style: { color: affixColor }, children: inputSuffix }),
|
|
11682
12192
|
useButton && stepper("inc")
|
|
11683
12193
|
]
|
|
@@ -12056,12 +12566,275 @@ function SCalendar({
|
|
|
12056
12566
|
}
|
|
12057
12567
|
);
|
|
12058
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
|
+
}
|
|
12059
12831
|
function SDatePicker({
|
|
12060
12832
|
value,
|
|
12061
12833
|
onValueChange,
|
|
12062
12834
|
onViewChange,
|
|
12835
|
+
mode = "date",
|
|
12063
12836
|
size = "sm",
|
|
12064
|
-
placeholder
|
|
12837
|
+
placeholder,
|
|
12065
12838
|
selectable,
|
|
12066
12839
|
disabled = false,
|
|
12067
12840
|
width,
|
|
@@ -12087,6 +12860,7 @@ function SDatePicker({
|
|
|
12087
12860
|
const [focused, setFocused] = react.useState(false);
|
|
12088
12861
|
const [ruleError, setRuleError] = react.useState("");
|
|
12089
12862
|
const hasValue = value != null && value !== "";
|
|
12863
|
+
const resolvedPlaceholder = placeholder ?? (mode === "year" ? "YYYY" : mode === "month" ? "YYYY-MM" : "YYYY-MM-DD");
|
|
12090
12864
|
useFormField({
|
|
12091
12865
|
name,
|
|
12092
12866
|
validate: () => {
|
|
@@ -12098,12 +12872,39 @@ function SDatePicker({
|
|
|
12098
12872
|
});
|
|
12099
12873
|
const resolvedError = error || ruleError !== "";
|
|
12100
12874
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
12101
|
-
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
|
+
};
|
|
12102
12899
|
const select = (date) => {
|
|
12103
12900
|
onValueChange?.(date);
|
|
12104
12901
|
if (rules && rules.length > 0) setRuleError(runRules(date, rules));
|
|
12105
12902
|
setOpen(false);
|
|
12106
12903
|
};
|
|
12904
|
+
const selectListboxValue = (nextValue) => {
|
|
12905
|
+
onValueChange?.(nextValue);
|
|
12906
|
+
if (rules && rules.length > 0) setRuleError(runRules(nextValue, rules));
|
|
12907
|
+
};
|
|
12107
12908
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12108
12909
|
SField,
|
|
12109
12910
|
{
|
|
@@ -12122,11 +12923,13 @@ function SDatePicker({
|
|
|
12122
12923
|
focused: focused || open,
|
|
12123
12924
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
12124
12925
|
width,
|
|
12926
|
+
minWidth: dims.fieldMinW,
|
|
12927
|
+
maxWidth: dims.fieldMaxW,
|
|
12125
12928
|
disabled,
|
|
12126
12929
|
className,
|
|
12127
12930
|
style,
|
|
12128
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12129
|
-
/* @__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(
|
|
12130
12933
|
"button",
|
|
12131
12934
|
{
|
|
12132
12935
|
type: "button",
|
|
@@ -12156,23 +12959,23 @@ function SDatePicker({
|
|
|
12156
12959
|
lineHeight: `${dims.lineHeight}px`,
|
|
12157
12960
|
color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasValue ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
|
|
12158
12961
|
},
|
|
12159
|
-
children: hasValue ? value :
|
|
12962
|
+
children: hasValue ? value : resolvedPlaceholder
|
|
12160
12963
|
}
|
|
12161
12964
|
)
|
|
12162
12965
|
]
|
|
12163
12966
|
}
|
|
12164
12967
|
) }),
|
|
12165
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12166
|
-
|
|
12968
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12969
|
+
RPopover10__namespace.Content,
|
|
12167
12970
|
{
|
|
12168
12971
|
side: "bottom",
|
|
12169
|
-
align: "start",
|
|
12972
|
+
align: mode === "date" ? "start" : "center",
|
|
12170
12973
|
sideOffset: 4,
|
|
12171
12974
|
className: cn(
|
|
12172
12975
|
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
12173
12976
|
FLOATING_SLIDE_ANIM
|
|
12174
12977
|
),
|
|
12175
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12978
|
+
children: mode === "date" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
12176
12979
|
SCalendar,
|
|
12177
12980
|
{
|
|
12178
12981
|
value: value ?? void 0,
|
|
@@ -12181,6 +12984,24 @@ function SDatePicker({
|
|
|
12181
12984
|
onValueChange: select,
|
|
12182
12985
|
onViewChange
|
|
12183
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
|
+
}
|
|
12184
13005
|
)
|
|
12185
13006
|
}
|
|
12186
13007
|
) })
|
|
@@ -12562,6 +13383,9 @@ function SDateRangePicker({
|
|
|
12562
13383
|
icon: 20,
|
|
12563
13384
|
minW: 104,
|
|
12564
13385
|
fieldMinW: 260,
|
|
13386
|
+
// 상한 등급 xl — 값이 `YYYY-MM-DD ~ YYYY-MM-DD` 라 단일 날짜의 두 배가 넘는다.
|
|
13387
|
+
// 최소너비(260)가 이미 lg(240)를 넘으므로 상한도 한 등급 위여야 한다
|
|
13388
|
+
fieldMaxW: 480,
|
|
12565
13389
|
fontSize: 14,
|
|
12566
13390
|
lineHeight: 24,
|
|
12567
13391
|
radius: 6
|
|
@@ -12571,6 +13395,8 @@ function SDateRangePicker({
|
|
|
12571
13395
|
icon: 16,
|
|
12572
13396
|
minW: 80,
|
|
12573
13397
|
fieldMinW: 216,
|
|
13398
|
+
// 상한 등급 lg — 최소너비 216 이 md(160)를 넘어 md 로는 담기지 않는다
|
|
13399
|
+
fieldMaxW: 240,
|
|
12574
13400
|
fontSize: 12,
|
|
12575
13401
|
lineHeight: 20,
|
|
12576
13402
|
radius: 4
|
|
@@ -12601,11 +13427,12 @@ function SDateRangePicker({
|
|
|
12601
13427
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
12602
13428
|
width,
|
|
12603
13429
|
minWidth: dims.fieldMinW,
|
|
13430
|
+
maxWidth: dims.fieldMaxW,
|
|
12604
13431
|
disabled,
|
|
12605
13432
|
className,
|
|
12606
13433
|
style,
|
|
12607
13434
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12608
|
-
|
|
13435
|
+
RPopover10__namespace.Root,
|
|
12609
13436
|
{
|
|
12610
13437
|
open,
|
|
12611
13438
|
onOpenChange: (o) => {
|
|
@@ -12614,7 +13441,7 @@ function SDateRangePicker({
|
|
|
12614
13441
|
if (!o) setPendingStart(null);
|
|
12615
13442
|
},
|
|
12616
13443
|
children: [
|
|
12617
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13444
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12618
13445
|
"button",
|
|
12619
13446
|
{
|
|
12620
13447
|
type: "button",
|
|
@@ -12655,8 +13482,8 @@ function SDateRangePicker({
|
|
|
12655
13482
|
]
|
|
12656
13483
|
}
|
|
12657
13484
|
) }),
|
|
12658
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12659
|
-
|
|
13485
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13486
|
+
RPopover10__namespace.Content,
|
|
12660
13487
|
{
|
|
12661
13488
|
side: "bottom",
|
|
12662
13489
|
align: "start",
|
|
@@ -13065,6 +13892,7 @@ function SKeyValueTable({
|
|
|
13065
13892
|
values = {},
|
|
13066
13893
|
search = false,
|
|
13067
13894
|
radius = "default",
|
|
13895
|
+
bordered = true,
|
|
13068
13896
|
onChange,
|
|
13069
13897
|
onSearch,
|
|
13070
13898
|
className,
|
|
@@ -13129,7 +13957,8 @@ function SKeyValueTable({
|
|
|
13129
13957
|
});
|
|
13130
13958
|
const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[8px] rounded-t-none" : "rounded-[8px]";
|
|
13131
13959
|
const frameClass = cn(
|
|
13132
|
-
"overflow-hidden
|
|
13960
|
+
"overflow-hidden",
|
|
13961
|
+
bordered && "border border-solid border-[color:var(--cmp-table-border-color)]",
|
|
13133
13962
|
radiusClass
|
|
13134
13963
|
);
|
|
13135
13964
|
const table = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -13674,6 +14503,119 @@ function SRadioButton({
|
|
|
13674
14503
|
}
|
|
13675
14504
|
);
|
|
13676
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
|
+
});
|
|
13677
14619
|
var CHIPFILTER_LISTBOX_WIDTH = 240;
|
|
13678
14620
|
var CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH = 246;
|
|
13679
14621
|
var CHIPFILTER = {
|
|
@@ -13714,7 +14656,16 @@ var CHIPFILTER = {
|
|
|
13714
14656
|
itemTextDefault: "var(--cmp-chipFilter-item-text-default)",
|
|
13715
14657
|
itemTextSelected: "var(--cmp-chipFilter-item-text-selected)"
|
|
13716
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
|
+
];
|
|
13717
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;
|
|
13718
14669
|
var keywordEntries = (value) => {
|
|
13719
14670
|
if (isKeywordValue(value)) return value.keywords;
|
|
13720
14671
|
if (Array.isArray(value)) {
|
|
@@ -13738,12 +14689,33 @@ var todayIso = () => {
|
|
|
13738
14689
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
13739
14690
|
};
|
|
13740
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
|
+
});
|
|
13741
14709
|
var resolveFieldDefault = (field) => {
|
|
13742
14710
|
if (field.defaultValue !== void 0) return field.defaultValue;
|
|
13743
14711
|
if (isInlineDateField(field)) return todayIso();
|
|
13744
14712
|
if (!field.required) return void 0;
|
|
13745
14713
|
if (field.type === "single") return field.options?.[0]?.value;
|
|
13746
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
|
+
}
|
|
13747
14719
|
return void 0;
|
|
13748
14720
|
};
|
|
13749
14721
|
var valuesEqual = (a, b) => {
|
|
@@ -13767,6 +14739,8 @@ var isAtDefaultValue = (field, value) => {
|
|
|
13767
14739
|
return def !== void 0 && valuesEqual(value, def);
|
|
13768
14740
|
};
|
|
13769
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);
|
|
13770
14744
|
var isGroupedFields = (fields) => fields.length > 0 && "fields" in fields[0];
|
|
13771
14745
|
var isGroupSatisfied = (group, values) => {
|
|
13772
14746
|
if (!group.rule) return true;
|
|
@@ -13793,9 +14767,10 @@ var defaultGroupTooltipMessage = (rule, fields) => {
|
|
|
13793
14767
|
};
|
|
13794
14768
|
var matchPresetId = (presets, value) => {
|
|
13795
14769
|
if (isEmptyValue(value)) return null;
|
|
14770
|
+
if (isPeriodValue(value)) return value.unit;
|
|
13796
14771
|
for (const preset of presets) {
|
|
13797
|
-
if (preset.custom
|
|
13798
|
-
const resolved = preset.resolve();
|
|
14772
|
+
if (preset.custom) continue;
|
|
14773
|
+
const resolved = preset.resolve ? preset.resolve() : preset.value;
|
|
13799
14774
|
if (Array.isArray(resolved) && Array.isArray(value)) {
|
|
13800
14775
|
if (resolved[0] === value[0] && resolved[1] === value[1]) return preset.value;
|
|
13801
14776
|
} else if (!Array.isArray(resolved) && !Array.isArray(value) && resolved === value) {
|
|
@@ -13811,18 +14786,36 @@ var formatValueList = (labels) => {
|
|
|
13811
14786
|
};
|
|
13812
14787
|
var displayValue = (field, value) => {
|
|
13813
14788
|
if (isEmptyValue(value)) return "";
|
|
13814
|
-
if (field.type === "multi")
|
|
13815
|
-
|
|
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
|
+
}
|
|
13816
14797
|
if (field.type === "single") return optionLabel(field, value);
|
|
13817
14798
|
if (field.type === "date")
|
|
13818
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
|
+
}
|
|
13819
14812
|
if (field.type === "keyword") return formatValueList(keywordEntries(value));
|
|
13820
14813
|
return String(value);
|
|
13821
14814
|
};
|
|
13822
14815
|
var chipDisplayValue = (field, value) => {
|
|
13823
14816
|
const text = displayValue(field, value);
|
|
13824
14817
|
if (field.type !== "date" || isEmptyValue(value)) return text;
|
|
13825
|
-
const presets = field
|
|
14818
|
+
const presets = getFieldPresets(field);
|
|
13826
14819
|
if (presets.length === 0) return text;
|
|
13827
14820
|
const preset = presets.find((p) => p.value === matchPresetId(presets, value));
|
|
13828
14821
|
return preset && !preset.custom ? `${preset.label}(${text})` : text;
|
|
@@ -13839,7 +14832,6 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
13839
14832
|
onAddFilter,
|
|
13840
14833
|
label = "\uAC80\uC0C9 \uD544\uD130",
|
|
13841
14834
|
showLabel = false,
|
|
13842
|
-
showAddButton = true,
|
|
13843
14835
|
showReset = true,
|
|
13844
14836
|
disabled = false,
|
|
13845
14837
|
className,
|
|
@@ -13854,7 +14846,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
13854
14846
|
const values = normalizeValues(value);
|
|
13855
14847
|
const portalContainer = usePortalContainer();
|
|
13856
14848
|
const [internalActiveKeys, setInternalActiveKeys] = react.useState(
|
|
13857
|
-
() => fields.filter((field) => field.defaultActive !== false).map((field) => field.key)
|
|
14849
|
+
() => fields.filter((field) => isFixedField(field) || field.defaultActive !== false).map((field) => field.key)
|
|
13858
14850
|
);
|
|
13859
14851
|
const [openKey, setOpenKey] = react.useState(null);
|
|
13860
14852
|
const [addOpen, setAddOpen] = react.useState(false);
|
|
@@ -13896,7 +14888,9 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
13896
14888
|
setInternalActiveKeys((current) => {
|
|
13897
14889
|
const known = new Set(fields.map((field) => field.key));
|
|
13898
14890
|
const kept = current.filter((key) => known.has(key));
|
|
13899
|
-
const additions = fields.filter(
|
|
14891
|
+
const additions = fields.filter(
|
|
14892
|
+
(field) => (isFixedField(field) || field.defaultActive !== false) && !kept.includes(field.key)
|
|
14893
|
+
).map((field) => field.key);
|
|
13900
14894
|
return [...kept, ...additions];
|
|
13901
14895
|
});
|
|
13902
14896
|
}, [activeKeys, fields]);
|
|
@@ -13917,25 +14911,31 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
13917
14911
|
});
|
|
13918
14912
|
if (changed) onValueChange?.({ ...values, ...patch });
|
|
13919
14913
|
}, [fields, values, onValueChange]);
|
|
13920
|
-
const
|
|
14914
|
+
const fixedKeys = fields.filter(isFixedField).map((field) => field.key);
|
|
14915
|
+
const resolvedActiveKeys = Array.from(
|
|
14916
|
+
/* @__PURE__ */ new Set([...activeKeys ?? internalActiveKeys, ...fixedKeys])
|
|
14917
|
+
);
|
|
13921
14918
|
const activeFields = fields.filter((field) => resolvedActiveKeys.includes(field.key));
|
|
13922
|
-
const inactiveFields = fields.filter(
|
|
14919
|
+
const inactiveFields = fields.filter(
|
|
14920
|
+
(field) => isAddableField(field) && !resolvedActiveKeys.includes(field.key)
|
|
14921
|
+
);
|
|
13923
14922
|
const groupIndexByKey = /* @__PURE__ */ new Map();
|
|
13924
14923
|
groups.forEach((group, groupIndex) => {
|
|
13925
14924
|
group.fields.forEach((field) => groupIndexByKey.set(field.key, groupIndex));
|
|
13926
14925
|
});
|
|
13927
14926
|
const hasValue = fields.some((field) => !isEmptyValue(values[field.key]));
|
|
13928
|
-
const
|
|
14927
|
+
const hasAddButton = fields.some(isAddableField);
|
|
14928
|
+
const hasRightActions = hasAddButton || showReset;
|
|
13929
14929
|
const currentOpenField = fields.find((field) => field.key === openKey);
|
|
13930
14930
|
const editorPopoverStyle = react.useMemo(() => {
|
|
13931
14931
|
if (currentOpenField?.type === "keyword") {
|
|
13932
14932
|
return { width: CHIPFILTER_LISTBOX_WIDTH };
|
|
13933
14933
|
}
|
|
13934
|
-
if (currentOpenField?.type === "date" && (currentOpenField.
|
|
14934
|
+
if ((currentOpenField?.type === "date" || currentOpenField?.type === "period") && getFieldPresets(currentOpenField).length > 0) {
|
|
13935
14935
|
return { width: CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH };
|
|
13936
14936
|
}
|
|
13937
14937
|
return { width: CHIPFILTER_LISTBOX_WIDTH };
|
|
13938
|
-
}, [currentOpenField
|
|
14938
|
+
}, [currentOpenField]);
|
|
13939
14939
|
const setActive = (next) => {
|
|
13940
14940
|
if (!activeKeys) setInternalActiveKeys(next);
|
|
13941
14941
|
onActiveKeysChange?.(next);
|
|
@@ -13954,6 +14954,12 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
13954
14954
|
const def = field ? resolveFieldDefault(field) : void 0;
|
|
13955
14955
|
runSearch(emitValue(key, def !== void 0 ? def : null));
|
|
13956
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
|
+
};
|
|
13957
14963
|
const reset = react.useCallback(() => {
|
|
13958
14964
|
const next = fields.reduce((acc, field) => {
|
|
13959
14965
|
const def = resolveFieldDefault(field);
|
|
@@ -14044,7 +15050,15 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14044
15050
|
flushRun();
|
|
14045
15051
|
runGroupIndex = groupIndex;
|
|
14046
15052
|
}
|
|
14047
|
-
const
|
|
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
|
+
};
|
|
14048
15062
|
const node = isInlineDateField(field) ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
14049
15063
|
InlineDatePresetFilter,
|
|
14050
15064
|
{
|
|
@@ -14054,15 +15068,27 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14054
15068
|
warning,
|
|
14055
15069
|
showClear,
|
|
14056
15070
|
onValueChange: (next) => emitValueAndSearch(field.key, next),
|
|
14057
|
-
onClear:
|
|
15071
|
+
onClear: handleClear
|
|
14058
15072
|
},
|
|
14059
15073
|
field.key
|
|
14060
|
-
) : field.type === "custom" ? /* @__PURE__ */ jsxRuntime.
|
|
14061
|
-
|
|
14062
|
-
|
|
14063
|
-
|
|
14064
|
-
|
|
14065
|
-
|
|
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(
|
|
14066
15092
|
FilterChip,
|
|
14067
15093
|
{
|
|
14068
15094
|
field,
|
|
@@ -14072,9 +15098,10 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14072
15098
|
disabled: disabled || field.disabled,
|
|
14073
15099
|
warning,
|
|
14074
15100
|
showClear,
|
|
15101
|
+
showClearWhenEmpty: addable,
|
|
14075
15102
|
refCallback: (node2) => triggerRefs.current.set(field.key, node2),
|
|
14076
15103
|
onOpen: () => setOpenKey(openKey === field.key ? null : field.key),
|
|
14077
|
-
onClear:
|
|
15104
|
+
onClear: handleClear
|
|
14078
15105
|
},
|
|
14079
15106
|
field.key
|
|
14080
15107
|
);
|
|
@@ -14095,8 +15122,8 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14095
15122
|
})(),
|
|
14096
15123
|
hasRightActions && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
14097
15124
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, { inset: true }),
|
|
14098
|
-
|
|
14099
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
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(
|
|
14100
15127
|
"button",
|
|
14101
15128
|
{
|
|
14102
15129
|
type: "button",
|
|
@@ -14121,8 +15148,8 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14121
15148
|
]
|
|
14122
15149
|
}
|
|
14123
15150
|
) }),
|
|
14124
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14125
|
-
|
|
15151
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15152
|
+
RPopover10__namespace.Content,
|
|
14126
15153
|
{
|
|
14127
15154
|
side: "bottom",
|
|
14128
15155
|
align: "start",
|
|
@@ -14142,7 +15169,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14142
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",
|
|
14143
15170
|
// 부모 flex gap(6px)은 칩 사이 간격 기준이라, 필터 추가 버튼과의 12px 간격을 맞추려면
|
|
14144
15171
|
// 부족한 만큼(12px - gap)을 추가로 띄운다. 필터 추가가 없을 땐 divider와 이미 12px이라 불필요.
|
|
14145
|
-
|
|
15172
|
+
hasAddButton && "ml-[calc(12px-var(--cmp-chipFilter-chip-group))]"
|
|
14146
15173
|
),
|
|
14147
15174
|
style: {
|
|
14148
15175
|
color: disabled || !hasValue ? "var(--cmp-textLink-content-disabled)" : "var(--cmp-textLink-content-default)"
|
|
@@ -14162,17 +15189,17 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14162
15189
|
)
|
|
14163
15190
|
] })
|
|
14164
15191
|
] }),
|
|
14165
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
15192
|
+
/* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open: openKey != null, onOpenChange: (next) => !next && setOpenKey(null), children: [
|
|
14166
15193
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14167
|
-
|
|
15194
|
+
RPopover10__namespace.Anchor,
|
|
14168
15195
|
{
|
|
14169
15196
|
virtualRef: {
|
|
14170
15197
|
current: openKey ? triggerRefs.current.get(openKey) : null
|
|
14171
15198
|
}
|
|
14172
15199
|
}
|
|
14173
15200
|
),
|
|
14174
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14175
|
-
|
|
15201
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15202
|
+
RPopover10__namespace.Content,
|
|
14176
15203
|
{
|
|
14177
15204
|
side: "bottom",
|
|
14178
15205
|
align: "start",
|
|
@@ -14226,6 +15253,7 @@ function FilterChip({
|
|
|
14226
15253
|
disabled,
|
|
14227
15254
|
warning,
|
|
14228
15255
|
showClear,
|
|
15256
|
+
showClearWhenEmpty,
|
|
14229
15257
|
refCallback,
|
|
14230
15258
|
onOpen,
|
|
14231
15259
|
onClear
|
|
@@ -14295,7 +15323,7 @@ function FilterChip({
|
|
|
14295
15323
|
}
|
|
14296
15324
|
)
|
|
14297
15325
|
] }),
|
|
14298
|
-
|
|
15326
|
+
!disabled && showClear && (applied || showClearWhenEmpty) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
14299
15327
|
"span",
|
|
14300
15328
|
{
|
|
14301
15329
|
role: "button",
|
|
@@ -14327,7 +15355,7 @@ function EditorPanel({
|
|
|
14327
15355
|
onValueChange,
|
|
14328
15356
|
onClose
|
|
14329
15357
|
}) {
|
|
14330
|
-
const wrapsInPaddedTop = field.type === "date";
|
|
15358
|
+
const wrapsInPaddedTop = field.type === "date" || field.type === "period";
|
|
14331
15359
|
const isMulti = field.type === "multi";
|
|
14332
15360
|
const selectableValues = isMulti ? (field.options ?? []).filter((option) => !option.disabled).map((option) => option.value) : [];
|
|
14333
15361
|
const selectedValues = isMulti ? toArrayValue(value) : [];
|
|
@@ -14406,6 +15434,17 @@ function FilterEditor({
|
|
|
14406
15434
|
disabled,
|
|
14407
15435
|
onValueChange
|
|
14408
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
|
+
}
|
|
14409
15448
|
if (field.type === "date") {
|
|
14410
15449
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14411
15450
|
DatePresetEditor,
|
|
@@ -14445,7 +15484,7 @@ function DatePresetEditor({
|
|
|
14445
15484
|
disabled,
|
|
14446
15485
|
onValueChange
|
|
14447
15486
|
}) {
|
|
14448
|
-
const presets = field
|
|
15487
|
+
const presets = getFieldPresets(field);
|
|
14449
15488
|
const [selectedId, setSelectedId] = react.useState(() => matchPresetId(presets, value));
|
|
14450
15489
|
const syncedInitialValueRef = react.useRef(!isEmptyValue(value));
|
|
14451
15490
|
react.useEffect(() => {
|
|
@@ -14456,9 +15495,9 @@ function DatePresetEditor({
|
|
|
14456
15495
|
const selectedPreset = presets.find((preset) => preset.value === selectedId);
|
|
14457
15496
|
const selectPreset = (preset) => {
|
|
14458
15497
|
setSelectedId(preset.value);
|
|
14459
|
-
if (!preset.custom) onValueChange(preset.resolve ? preset.resolve() :
|
|
15498
|
+
if (!preset.custom) onValueChange(preset.resolve ? preset.resolve() : preset.value);
|
|
14460
15499
|
};
|
|
14461
|
-
if (presets.length === 0) {
|
|
15500
|
+
if (field.type === "date" && presets.length === 0) {
|
|
14462
15501
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14463
15502
|
SDatePicker,
|
|
14464
15503
|
{
|
|
@@ -14494,6 +15533,130 @@ function DatePresetEditor({
|
|
|
14494
15533
|
)
|
|
14495
15534
|
] });
|
|
14496
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
|
+
}
|
|
14497
15660
|
function InlineDatePresetFilter({
|
|
14498
15661
|
field,
|
|
14499
15662
|
value,
|
|
@@ -14576,8 +15739,8 @@ function InlineDatePresetFilter({
|
|
|
14576
15739
|
applied && (rangeValue ? (
|
|
14577
15740
|
// 뱃지 모양은 그대로 두고, 눌렀을 때 캘린더가 열려 기간을 직접 다시 고를 수 있게 한다.
|
|
14578
15741
|
// 직접 고르면 프리셋 선택은 해제된다.
|
|
14579
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
14580
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
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(
|
|
14581
15744
|
"button",
|
|
14582
15745
|
{
|
|
14583
15746
|
type: "button",
|
|
@@ -14586,8 +15749,8 @@ function InlineDatePresetFilter({
|
|
|
14586
15749
|
children: badge
|
|
14587
15750
|
}
|
|
14588
15751
|
) }),
|
|
14589
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14590
|
-
|
|
15752
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15753
|
+
RPopover10__namespace.Content,
|
|
14591
15754
|
{
|
|
14592
15755
|
side: "bottom",
|
|
14593
15756
|
align: "start",
|
|
@@ -15336,7 +16499,7 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
|
|
|
15336
16499
|
}
|
|
15337
16500
|
);
|
|
15338
16501
|
});
|
|
15339
|
-
var
|
|
16502
|
+
var FONT3 = {
|
|
15340
16503
|
sm: {
|
|
15341
16504
|
fontSize: 12,
|
|
15342
16505
|
paddingX: "var(--cmp-textinput-sm-paddingX)",
|
|
@@ -15384,7 +16547,7 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
|
|
|
15384
16547
|
className,
|
|
15385
16548
|
style
|
|
15386
16549
|
}, ref) {
|
|
15387
|
-
const f =
|
|
16550
|
+
const f = FONT3[size];
|
|
15388
16551
|
const [ruleError, setRuleError] = react.useState("");
|
|
15389
16552
|
const hasValue = value !== void 0 && value !== null && String(value) !== "";
|
|
15390
16553
|
useFormField({
|
|
@@ -15398,6 +16561,10 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
|
|
|
15398
16561
|
});
|
|
15399
16562
|
const resolvedError = error || ruleError !== "";
|
|
15400
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
|
+
});
|
|
15401
16568
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15402
16569
|
SField,
|
|
15403
16570
|
{
|
|
@@ -15434,7 +16601,7 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
|
|
|
15434
16601
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15435
16602
|
"input",
|
|
15436
16603
|
{
|
|
15437
|
-
ref,
|
|
16604
|
+
ref: mergeRefs(ref, valueTooltip.valueRef),
|
|
15438
16605
|
name,
|
|
15439
16606
|
type: "text",
|
|
15440
16607
|
value: value ?? "",
|
|
@@ -15460,9 +16627,12 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
|
|
|
15460
16627
|
fontSize: f.fontSize,
|
|
15461
16628
|
color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--cmp-textinput-text-default)",
|
|
15462
16629
|
...inputStyle
|
|
15463
|
-
}
|
|
16630
|
+
},
|
|
16631
|
+
onMouseEnter: valueTooltip.onMouseEnter,
|
|
16632
|
+
onMouseLeave: valueTooltip.onMouseLeave
|
|
15464
16633
|
}
|
|
15465
16634
|
),
|
|
16635
|
+
valueTooltip.tooltip,
|
|
15466
16636
|
suffix,
|
|
15467
16637
|
clearable && hasValue && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15468
16638
|
SGhostButton,
|
|
@@ -15498,7 +16668,9 @@ var TIMEPICKER_SIZE_CONFIG = {
|
|
|
15498
16668
|
fontSize: 12,
|
|
15499
16669
|
lineHeight: 20,
|
|
15500
16670
|
minWidth: 80,
|
|
15501
|
-
fieldMinWidth: 128
|
|
16671
|
+
fieldMinWidth: 128,
|
|
16672
|
+
// 상한 등급 md
|
|
16673
|
+
fieldMaxWidth: 160
|
|
15502
16674
|
},
|
|
15503
16675
|
md: {
|
|
15504
16676
|
height: V3("md-height"),
|
|
@@ -15510,7 +16682,9 @@ var TIMEPICKER_SIZE_CONFIG = {
|
|
|
15510
16682
|
fontSize: 14,
|
|
15511
16683
|
lineHeight: 24,
|
|
15512
16684
|
minWidth: 96,
|
|
15513
|
-
fieldMinWidth: 160
|
|
16685
|
+
fieldMinWidth: 160,
|
|
16686
|
+
// 상한 등급 lg
|
|
16687
|
+
fieldMaxWidth: 240
|
|
15514
16688
|
}
|
|
15515
16689
|
};
|
|
15516
16690
|
function clampTimePart(value, min, max) {
|
|
@@ -15834,11 +17008,12 @@ function STimePicker({
|
|
|
15834
17008
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
15835
17009
|
width,
|
|
15836
17010
|
minWidth: dims.fieldMinWidth,
|
|
17011
|
+
maxWidth: dims.fieldMaxWidth,
|
|
15837
17012
|
disabled,
|
|
15838
17013
|
className,
|
|
15839
17014
|
style,
|
|
15840
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15841
|
-
/* @__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(
|
|
15842
17017
|
"div",
|
|
15843
17018
|
{
|
|
15844
17019
|
ref: triggerRef,
|
|
@@ -15898,8 +17073,8 @@ function STimePicker({
|
|
|
15898
17073
|
]
|
|
15899
17074
|
}
|
|
15900
17075
|
) }),
|
|
15901
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15902
|
-
|
|
17076
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17077
|
+
RPopover10__namespace.Content,
|
|
15903
17078
|
{
|
|
15904
17079
|
side: "bottom",
|
|
15905
17080
|
align: "start",
|
|
@@ -15950,6 +17125,10 @@ var MIDDAY_FIELD_MIN_WIDTH = {
|
|
|
15950
17125
|
sm: 178,
|
|
15951
17126
|
md: 216
|
|
15952
17127
|
};
|
|
17128
|
+
var MIDDAY_FIELD_MAX_WIDTH = {
|
|
17129
|
+
sm: 240,
|
|
17130
|
+
md: 240
|
|
17131
|
+
};
|
|
15953
17132
|
function RangeTimeSelector({
|
|
15954
17133
|
value,
|
|
15955
17134
|
useMeridiem,
|
|
@@ -16296,11 +17475,12 @@ function STimeRangePicker({
|
|
|
16296
17475
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
16297
17476
|
width,
|
|
16298
17477
|
minWidth: effectiveUseMeridiem ? MIDDAY_FIELD_MIN_WIDTH[size] : dims.fieldMinWidth,
|
|
17478
|
+
maxWidth: effectiveUseMeridiem ? MIDDAY_FIELD_MAX_WIDTH[size] : dims.fieldMaxWidth,
|
|
16299
17479
|
disabled,
|
|
16300
17480
|
className,
|
|
16301
17481
|
style,
|
|
16302
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16303
|
-
/* @__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(
|
|
16304
17484
|
"div",
|
|
16305
17485
|
{
|
|
16306
17486
|
ref: triggerRef,
|
|
@@ -16360,8 +17540,8 @@ function STimeRangePicker({
|
|
|
16360
17540
|
]
|
|
16361
17541
|
}
|
|
16362
17542
|
) }),
|
|
16363
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16364
|
-
|
|
17543
|
+
/* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17544
|
+
RPopover10__namespace.Content,
|
|
16365
17545
|
{
|
|
16366
17546
|
side: "bottom",
|
|
16367
17547
|
align: "start",
|
|
@@ -16402,7 +17582,9 @@ exports.GNB_MENU_WIDTH = GNB_MENU_WIDTH;
|
|
|
16402
17582
|
exports.GNB_RAIL = GNB_RAIL;
|
|
16403
17583
|
exports.GNB_RAIL_WIDTH = GNB_RAIL_WIDTH;
|
|
16404
17584
|
exports.ICONS = ICONS;
|
|
17585
|
+
exports.IMAGE_FITS = IMAGE_FITS;
|
|
16405
17586
|
exports.PAGE_BACKGROUNDS = PAGE_BACKGROUNDS;
|
|
17587
|
+
exports.PAGE_CONTENT_HEIGHTS = PAGE_CONTENT_HEIGHTS;
|
|
16406
17588
|
exports.RangeCalendar = RangeCalendar;
|
|
16407
17589
|
exports.SActionModal = SActionModal;
|
|
16408
17590
|
exports.SBadge = SBadge;
|
|
@@ -16419,6 +17601,8 @@ exports.SChipInput = SChipInput;
|
|
|
16419
17601
|
exports.SCircleProgress = SCircleProgress;
|
|
16420
17602
|
exports.SConfirmModal = SConfirmModal;
|
|
16421
17603
|
exports.SDatePicker = SDatePicker;
|
|
17604
|
+
exports.SDatePickerMonthListbox = SDatePickerMonthListbox;
|
|
17605
|
+
exports.SDatePickerYearListbox = SDatePickerYearListbox;
|
|
16422
17606
|
exports.SDateRangePicker = SDateRangePicker;
|
|
16423
17607
|
exports.SDivider = SDivider;
|
|
16424
17608
|
exports.SDraggableGroup = SDraggableGroup;
|
|
@@ -16436,6 +17620,7 @@ exports.SGhostButton = SGhostButton;
|
|
|
16436
17620
|
exports.SGnb = SGnb;
|
|
16437
17621
|
exports.SGuide = SGuide;
|
|
16438
17622
|
exports.SIcon = SIcon;
|
|
17623
|
+
exports.SImage = SImage;
|
|
16439
17624
|
exports.SInput = SInput;
|
|
16440
17625
|
exports.SKeyValueTable = SKeyValueTable;
|
|
16441
17626
|
exports.SLAYOUT_MIN_WIDTH = SLAYOUT_MIN_WIDTH;
|
|
@@ -16460,6 +17645,7 @@ exports.SRadioButton = SRadioButton;
|
|
|
16460
17645
|
exports.SRadioGroup = SRadioGroup;
|
|
16461
17646
|
exports.SSPLITTER_UNITS = SSPLITTER_UNITS;
|
|
16462
17647
|
exports.SScrollArea = SScrollArea;
|
|
17648
|
+
exports.SSearchInput = SSearchInput;
|
|
16463
17649
|
exports.SSectionHeaderCard = SSectionHeaderCard2;
|
|
16464
17650
|
exports.SSelect = SSelect2;
|
|
16465
17651
|
exports.SSplitter = SSplitter2;
|