sellmate-design-system-react 8.1.0 → 9.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +156 -109
- package/README.md +38 -8
- package/dist/components/SChipFilter/README.md +69 -0
- package/dist/components/SChipFilter/SChipFilter.d.ts +160 -0
- package/dist/components/SChipFilter/index.d.ts +1 -0
- package/dist/components/SDatePicker/README.md +2 -0
- package/dist/components/SDateRangePicker/README.md +21 -0
- package/dist/components/SDateRangePicker/SDateRangePicker.d.ts +16 -0
- package/dist/components/SDateRangePicker/index.d.ts +1 -1
- package/dist/components/SGhostButton/README.md +4 -0
- package/dist/components/SGuide/README.md +1 -1
- package/dist/components/SGuide/SGuide.d.ts +1 -1
- package/dist/components/SIcon/README.md +2 -0
- package/dist/components/SIcon/icons.gen.d.ts +1 -0
- package/dist/components/SList/README.md +1 -0
- package/dist/components/SList/SList.d.ts +2 -0
- package/dist/components/SListItem/README.md +2 -2
- package/dist/components/SListItem/SListItem.d.ts +2 -2
- package/dist/components/SPage/README.md +21 -0
- package/dist/components/SPage/SPage.d.ts +10 -0
- package/dist/components/SPage/SPageHeader.d.ts +32 -0
- package/dist/components/SPage/index.d.ts +1 -0
- package/dist/components/SPortal/README.md +1 -1
- package/dist/components/SPortal/SPortal.d.ts +7 -1
- package/dist/components/SRadio/README.md +2 -0
- package/dist/components/SRadioButton/README.md +13 -0
- package/dist/components/SSelect/README.md +2 -2
- package/dist/components/SSelect/SSelect.d.ts +2 -2
- package/dist/components/STag/README.md +2 -0
- package/dist/components/STextLink/README.md +2 -0
- package/dist/components/STooltip/README.md +2 -0
- package/dist/index.cjs +1632 -223
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1644 -237
- package/dist/index.js.map +1 -1
- package/dist/lib/floating-width.d.ts +22 -0
- package/dist/llms-full.txt +277 -115
- package/dist/llms.txt +158 -111
- package/dist/styles.css +197 -5
- package/package.json +7 -4
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { forwardRef, useState, useRef, useEffect, createContext, useContext, use
|
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
7
7
|
import * as RCheckbox from '@radix-ui/react-checkbox';
|
|
8
|
-
import * as
|
|
8
|
+
import * as RPopover9 from '@radix-ui/react-popover';
|
|
9
9
|
import { createRoot } from 'react-dom/client';
|
|
10
10
|
import * as RTooltip from '@radix-ui/react-tooltip';
|
|
11
11
|
import * as RDropdown from '@radix-ui/react-dropdown-menu';
|
|
@@ -2565,6 +2565,27 @@ var Icon_sidebar = (p) => {
|
|
|
2565
2565
|
}
|
|
2566
2566
|
);
|
|
2567
2567
|
};
|
|
2568
|
+
var Icon_star = (p) => {
|
|
2569
|
+
const { size = 24, ...rest } = p;
|
|
2570
|
+
return /* @__PURE__ */ jsx(
|
|
2571
|
+
"svg",
|
|
2572
|
+
{
|
|
2573
|
+
width: size,
|
|
2574
|
+
height: size,
|
|
2575
|
+
viewBox: "0 0 24 24",
|
|
2576
|
+
fill: "none",
|
|
2577
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2578
|
+
...rest,
|
|
2579
|
+
children: /* @__PURE__ */ jsx(
|
|
2580
|
+
"path",
|
|
2581
|
+
{
|
|
2582
|
+
d: "M12.3358 3.45335C12.0755 2.84888 11.2185 2.84888 10.9582 3.45335L8.78136 8.50811C8.67278 8.76024 8.43512 8.93291 8.16178 8.95826L2.68175 9.46652C2.02642 9.5273 1.76157 10.3424 2.25602 10.7768L6.39071 14.409C6.59695 14.5902 6.68773 14.8696 6.62737 15.1374L5.41733 20.5063C5.27263 21.1483 5.966 21.6521 6.5319 21.3161L11.2641 18.5062C11.5001 18.366 11.7939 18.366 12.0299 18.5062L16.7621 21.3161C17.328 21.6521 18.0214 21.1483 17.8767 20.5063L16.6666 15.1374C16.6063 14.8696 16.6971 14.5902 16.9033 14.409L21.038 10.7768C21.5324 10.3424 21.2676 9.5273 20.6123 9.46652L15.1322 8.95826C14.8589 8.93291 14.6212 8.76024 14.5126 8.50811L12.3358 3.45335Z",
|
|
2583
|
+
fill: "currentColor"
|
|
2584
|
+
}
|
|
2585
|
+
)
|
|
2586
|
+
}
|
|
2587
|
+
);
|
|
2588
|
+
};
|
|
2568
2589
|
var Icon_store = (p) => {
|
|
2569
2590
|
const { size = 24, ...rest } = p;
|
|
2570
2591
|
return /* @__PURE__ */ jsxs(
|
|
@@ -3059,6 +3080,7 @@ var ICONS = {
|
|
|
3059
3080
|
settingOutline: Icon_settingOutline,
|
|
3060
3081
|
shield: Icon_shield,
|
|
3061
3082
|
sidebar: Icon_sidebar,
|
|
3083
|
+
star: Icon_star,
|
|
3062
3084
|
store: Icon_store,
|
|
3063
3085
|
synchronize: Icon_synchronize,
|
|
3064
3086
|
thumbsDown: Icon_thumbsDown,
|
|
@@ -3192,12 +3214,13 @@ var SDraggableItemView = /* @__PURE__ */ forwardRef(
|
|
|
3192
3214
|
!disabled && !selected && !dragging && "hover:bg-(--cmp-listDraggableItem-bg-hover)",
|
|
3193
3215
|
hasSupportingText && supportingTextPosition === "bottom" ? dense ? "min-h-[52px]" : "min-h-[60px]" : dense ? "h-[32px]" : "h-[40px]",
|
|
3194
3216
|
paddingYClass,
|
|
3195
|
-
|
|
3217
|
+
// 항목 사이 구분선은 리스트가 그린다 — SDraggableList 의 separator (SList.tsx)
|
|
3218
|
+
bordered && cn(
|
|
3196
3219
|
"rounded-(--cmp-listDraggableItem-radius-bordered) border border-(--cmp-listDraggableItem-border-default)",
|
|
3197
3220
|
!disabled && !selected && !dragging && "hover:border-(--cmp-listDraggableItem-bordered-border-hover)",
|
|
3198
3221
|
!disabled && selected && !dragging && "border-(--cmp-listDraggableItem-bordered-border-selected) bg-(--cmp-listDraggableItem-bordered-bg-selected)",
|
|
3199
3222
|
!disabled && selected && dragging && "border-[length:var(--cmp-listDraggableItem-bordered-dragging-border-width)] border-(--cmp-listDraggableItem-bordered-dragging-border-color) bg-(--cmp-listDraggableItem-bordered-dragging-bg)"
|
|
3200
|
-
)
|
|
3223
|
+
),
|
|
3201
3224
|
disabled && "cursor-not-allowed",
|
|
3202
3225
|
className
|
|
3203
3226
|
),
|
|
@@ -3399,7 +3422,7 @@ var SDraggableItemImpl = /* @__PURE__ */ forwardRef(function SDraggableItem({
|
|
|
3399
3422
|
] });
|
|
3400
3423
|
});
|
|
3401
3424
|
var SDraggableItem2 = /* @__PURE__ */ withDisplayName(SDraggableItemImpl, "SDraggableItem");
|
|
3402
|
-
var SListImpl = /* @__PURE__ */ forwardRef(function SList({ className, children, useGap = false, usePadding = false, ...rest }, ref) {
|
|
3425
|
+
var SListImpl = /* @__PURE__ */ forwardRef(function SList({ className, children, useGap = false, usePadding = false, separator = false, ...rest }, ref) {
|
|
3403
3426
|
return /* @__PURE__ */ jsx(
|
|
3404
3427
|
"div",
|
|
3405
3428
|
{
|
|
@@ -3407,6 +3430,7 @@ var SListImpl = /* @__PURE__ */ forwardRef(function SList({ className, children,
|
|
|
3407
3430
|
className: cn(
|
|
3408
3431
|
useGap && "flex flex-col gap-(--cmp-list-group-gap)",
|
|
3409
3432
|
usePadding && "p-(--cmp-list-group-padding)",
|
|
3433
|
+
separator && "[&>*]:border-b [&>*]:border-(--cmp-listItem-border-default)",
|
|
3410
3434
|
className
|
|
3411
3435
|
),
|
|
3412
3436
|
...rest,
|
|
@@ -3778,7 +3802,7 @@ var SExpansionItem = /* @__PURE__ */ forwardRef(
|
|
|
3778
3802
|
ref,
|
|
3779
3803
|
className: cn(
|
|
3780
3804
|
"group/expansion-item relative overflow-hidden bg-(--cmp-listExpansionItem-title-bg-default)",
|
|
3781
|
-
|
|
3805
|
+
// 항목 사이 구분선은 리스트가 그린다 — SList/SExpansionList 의 separator (SList.tsx)
|
|
3782
3806
|
// 보더 색은 시맨틱 토큰(border-default → hover strong → 펼침 accentLight)을 쓴다.
|
|
3783
3807
|
// TODO: expansionItem/bordered/radius 토큰 생성 후 rounded 고정값도 토큰으로 교체한다.
|
|
3784
3808
|
bordered && "rounded-[8px] border border-border-default hover:border-border-strong [&:has(>button:hover)]:border-border-strong",
|
|
@@ -3888,7 +3912,7 @@ var SListItemImpl = /* @__PURE__ */ forwardRef(function SListItem({
|
|
|
3888
3912
|
trailing,
|
|
3889
3913
|
bordered = false,
|
|
3890
3914
|
selected = false,
|
|
3891
|
-
clickable =
|
|
3915
|
+
clickable = false,
|
|
3892
3916
|
interaction,
|
|
3893
3917
|
accentStripe = false,
|
|
3894
3918
|
dense = false,
|
|
@@ -3941,10 +3965,10 @@ var SListItemImpl = /* @__PURE__ */ forwardRef(function SListItem({
|
|
|
3941
3965
|
"gap-(--cmp-listItem-gap)",
|
|
3942
3966
|
"pr-(--cmp-listItem-paddingX)",
|
|
3943
3967
|
depth === 2 ? "pl-[36px]" : depth === 3 ? "pl-[56px]" : "pl-[16px]",
|
|
3944
|
-
bordered
|
|
3968
|
+
bordered && cn(
|
|
3945
3969
|
"overflow-hidden rounded-(--cmp-listItem-radius-bordered) border border-(--cmp-listItem-border-default)",
|
|
3946
3970
|
isSelected ? "border-(--cmp-listItem-bordered-border-selected)" : isInteractive && "hover:border-(--cmp-listItem-bordered-border-hover)"
|
|
3947
|
-
)
|
|
3971
|
+
),
|
|
3948
3972
|
className
|
|
3949
3973
|
),
|
|
3950
3974
|
...rest,
|
|
@@ -4023,6 +4047,8 @@ var SExpansionListImpl = /* @__PURE__ */ forwardRef(function SExpansionList({ ch
|
|
|
4023
4047
|
const depth2 = child.props.depth ?? 1;
|
|
4024
4048
|
const itemKey2 = String(child.key ?? index);
|
|
4025
4049
|
return cloneElement(child, {
|
|
4050
|
+
// 선택을 리스트가 관리하는 이상 아이템은 클릭 가능해야 한다 — SListItem 의 기본값(false)을 뒤집는다
|
|
4051
|
+
clickable: child.props.clickable ?? true,
|
|
4026
4052
|
selected: selectedKeys[depth2] === itemKey2,
|
|
4027
4053
|
onClick: (event) => {
|
|
4028
4054
|
setSelectedKeys((current) => ({ ...current, [depth2]: itemKey2 }));
|
|
@@ -4328,8 +4354,8 @@ function SGhostButton({
|
|
|
4328
4354
|
}
|
|
4329
4355
|
);
|
|
4330
4356
|
if (!hasTooltip) return btn;
|
|
4331
|
-
return /* @__PURE__ */ jsxs(
|
|
4332
|
-
/* @__PURE__ */ jsx(
|
|
4357
|
+
return /* @__PURE__ */ jsxs(RPopover9.Root, { open, onOpenChange: setOpen, children: [
|
|
4358
|
+
/* @__PURE__ */ jsx(RPopover9.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
4333
4359
|
"span",
|
|
4334
4360
|
{
|
|
4335
4361
|
className: cn("inline-flex", anchorClassName),
|
|
@@ -4341,8 +4367,8 @@ function SGhostButton({
|
|
|
4341
4367
|
children: btn
|
|
4342
4368
|
}
|
|
4343
4369
|
) }),
|
|
4344
|
-
/* @__PURE__ */ jsx(
|
|
4345
|
-
|
|
4370
|
+
/* @__PURE__ */ jsx(RPopover9.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
4371
|
+
RPopover9.Content,
|
|
4346
4372
|
{
|
|
4347
4373
|
side: "top",
|
|
4348
4374
|
sideOffset: 4,
|
|
@@ -4813,7 +4839,7 @@ var STooltipImpl = /* @__PURE__ */ forwardRef(function STooltip({
|
|
|
4813
4839
|
...restContentProps
|
|
4814
4840
|
} = contentProps ?? {};
|
|
4815
4841
|
const contentClass = cn(
|
|
4816
|
-
"z-50 w-fit
|
|
4842
|
+
"z-50 w-fit max-w-[var(--radix-popover-content-available-width)] rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px] shadow-normal-sm",
|
|
4817
4843
|
FLOATING_SLIDE_ANIM,
|
|
4818
4844
|
className,
|
|
4819
4845
|
contentPropsClassName
|
|
@@ -4825,14 +4851,14 @@ var STooltipImpl = /* @__PURE__ */ forwardRef(function STooltip({
|
|
|
4825
4851
|
...style,
|
|
4826
4852
|
...contentPropsStyle
|
|
4827
4853
|
};
|
|
4828
|
-
return /* @__PURE__ */ jsxs(
|
|
4854
|
+
return /* @__PURE__ */ jsxs(RPopover9.Root, { open, onOpenChange: setOpenState, children: [
|
|
4829
4855
|
isNone ? (
|
|
4830
4856
|
// 트리거 없음: children 을 래퍼 없이 그대로 앵커로 쓴다 (소비자 레이아웃 보존).
|
|
4831
4857
|
// mouse/focus 핸들러가 없으므로 useClose 없이도 자동 닫힘이 발생하지 않는다.
|
|
4832
|
-
/* @__PURE__ */ jsx(
|
|
4858
|
+
/* @__PURE__ */ jsx(RPopover9.Anchor, { asChild: true, children: triggerNode })
|
|
4833
4859
|
) : isHover ? (
|
|
4834
4860
|
// hover: Anchor(위치 기준) + 직접 mouse 핸들러 — 클릭으로 토글되지 않도록 Trigger 미사용
|
|
4835
|
-
/* @__PURE__ */ jsx(
|
|
4861
|
+
/* @__PURE__ */ jsx(RPopover9.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
4836
4862
|
"span",
|
|
4837
4863
|
{
|
|
4838
4864
|
className: "inline-flex",
|
|
@@ -4843,9 +4869,9 @@ var STooltipImpl = /* @__PURE__ */ forwardRef(function STooltip({
|
|
|
4843
4869
|
children: triggerNode
|
|
4844
4870
|
}
|
|
4845
4871
|
) })
|
|
4846
|
-
) : /* @__PURE__ */ jsx(
|
|
4847
|
-
/* @__PURE__ */ jsx(
|
|
4848
|
-
|
|
4872
|
+
) : /* @__PURE__ */ jsx(RPopover9.Trigger, { asChild: true, children: triggerNode }),
|
|
4873
|
+
/* @__PURE__ */ jsx(RPopover9.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(
|
|
4874
|
+
RPopover9.Content,
|
|
4849
4875
|
{
|
|
4850
4876
|
side: placement,
|
|
4851
4877
|
sideOffset,
|
|
@@ -4879,7 +4905,7 @@ var STooltipImpl = /* @__PURE__ */ forwardRef(function STooltip({
|
|
|
4879
4905
|
}
|
|
4880
4906
|
)
|
|
4881
4907
|
] }),
|
|
4882
|
-
/* @__PURE__ */ jsx(
|
|
4908
|
+
/* @__PURE__ */ jsx(RPopover9.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
4883
4909
|
]
|
|
4884
4910
|
}
|
|
4885
4911
|
) })
|
|
@@ -5887,6 +5913,15 @@ var STextLink = /* @__PURE__ */ forwardRef(function STextLink2({
|
|
|
5887
5913
|
/* @__PURE__ */ jsx(RTooltip.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(RTooltip.Content, { side: "top", sideOffset: 4, className: cn("z-50", FLOATING_SLIDE_ANIM), children: /* @__PURE__ */ jsx(STag, { shape: "square", size: "xs", color: "grey", label: text }) }) })
|
|
5888
5914
|
] }) });
|
|
5889
5915
|
});
|
|
5916
|
+
|
|
5917
|
+
// src/lib/floating-width.ts
|
|
5918
|
+
var POPOVER_AVAILABLE_WIDTH = "var(--radix-popover-content-available-width)";
|
|
5919
|
+
var DROPDOWN_AVAILABLE_WIDTH = "var(--radix-dropdown-menu-content-available-width)";
|
|
5920
|
+
function clampToAvailableWidth(value, availableWidth) {
|
|
5921
|
+
if (value == null || value === "") return availableWidth;
|
|
5922
|
+
const css = typeof value === "number" ? `${value}px` : value;
|
|
5923
|
+
return `min(${css}, ${availableWidth})`;
|
|
5924
|
+
}
|
|
5890
5925
|
var SIZE2 = {
|
|
5891
5926
|
xs: { height: 24, paddingX: 8, gap: 6, arrow: 12, fontSize: 12, minWidth: 64, splitMinWidth: 72 },
|
|
5892
5927
|
sm: {
|
|
@@ -5923,6 +5958,7 @@ function splitDivider(color, outline) {
|
|
|
5923
5958
|
};
|
|
5924
5959
|
return (outline ? outlined : solid)[color];
|
|
5925
5960
|
}
|
|
5961
|
+
var VIEWPORT_PADDING = 12;
|
|
5926
5962
|
var itemClass = cn(
|
|
5927
5963
|
"flex min-h-[28px] cursor-pointer select-none items-center gap-[8px] rounded-[2px] px-[12px] py-[4px] text-[12px] leading-[20px] outline-none",
|
|
5928
5964
|
"text-[color:var(--sys-color-fg-secondary)]",
|
|
@@ -6004,12 +6040,16 @@ var SDropdownButtonImpl = /* @__PURE__ */ forwardRef(
|
|
|
6004
6040
|
sideOffset: 4,
|
|
6005
6041
|
align: "start",
|
|
6006
6042
|
alignOffset: split ? splitAlignOffset : 0,
|
|
6043
|
+
collisionPadding: VIEWPORT_PADDING,
|
|
6007
6044
|
className: cn(
|
|
6008
6045
|
"z-50 overflow-hidden rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] shadow-normal-sm",
|
|
6009
|
-
|
|
6046
|
+
// 창보다 넓은 메뉴는 창 폭에 맞춰 줄인다. 트리거 너비를 따르는 하한도 같은 상한으로
|
|
6047
|
+
// 감싸야 한다 — min-width 가 max-width 를 이기기 때문이다.
|
|
6048
|
+
"max-w-[var(--radix-dropdown-menu-content-available-width)]",
|
|
6049
|
+
!split && "min-w-[min(var(--radix-dropdown-menu-trigger-width),var(--radix-dropdown-menu-content-available-width))]",
|
|
6010
6050
|
FLOATING_SLIDE_ANIM
|
|
6011
6051
|
),
|
|
6012
|
-
style: split ? { minWidth: splitWidth } : void 0,
|
|
6052
|
+
style: split ? { minWidth: clampToAvailableWidth(splitWidth, DROPDOWN_AVAILABLE_WIDTH) } : void 0,
|
|
6013
6053
|
children: items.map((it) => /* @__PURE__ */ jsxs(
|
|
6014
6054
|
RDropdown.Item,
|
|
6015
6055
|
{
|
|
@@ -6021,7 +6061,7 @@ var SDropdownButtonImpl = /* @__PURE__ */ forwardRef(
|
|
|
6021
6061
|
/* @__PURE__ */ jsx(
|
|
6022
6062
|
"span",
|
|
6023
6063
|
{
|
|
6024
|
-
className: "min-w-0
|
|
6064
|
+
className: "min-w-0 break-words",
|
|
6025
6065
|
dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(it.label) }
|
|
6026
6066
|
}
|
|
6027
6067
|
)
|
|
@@ -6233,16 +6273,20 @@ function SPopover({
|
|
|
6233
6273
|
const descColor = type === "default" ? "var(--cmp-popover-default-description)" : "var(--cmp-popover-light-description)";
|
|
6234
6274
|
const leftLinkLabelClass = type === "default" ? "text-[color:var(--cmp-popover-default-subAction)]" : "text-[color:var(--cmp-popover-light-subAction)]";
|
|
6235
6275
|
const triggerNode = trigger ?? /* @__PURE__ */ jsx("span", { className: "inline-flex cursor-pointer", "aria-label": ariaLabel, children: /* @__PURE__ */ jsx(SIcon, { name: icon, size: iconSize, color }) });
|
|
6236
|
-
return /* @__PURE__ */ jsxs(
|
|
6237
|
-
/* @__PURE__ */ jsx(
|
|
6238
|
-
/* @__PURE__ */ jsx(
|
|
6239
|
-
|
|
6276
|
+
return /* @__PURE__ */ jsxs(RPopover9.Root, { open: actualOpen, onOpenChange: setOpen, children: [
|
|
6277
|
+
/* @__PURE__ */ jsx(RPopover9.Trigger, { asChild: true, children: triggerNode }),
|
|
6278
|
+
/* @__PURE__ */ jsx(RPopover9.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(
|
|
6279
|
+
RPopover9.Content,
|
|
6240
6280
|
{
|
|
6241
6281
|
side: placement,
|
|
6242
6282
|
sideOffset: 8,
|
|
6243
6283
|
className: cn(
|
|
6244
6284
|
// 닫기 버튼이 항상 있으므로 우측은 close clearance(36px) 로 고정
|
|
6245
|
-
"relative z-50 flex
|
|
6285
|
+
"relative z-50 flex flex-col gap-[var(--cmp-popover-gap)] rounded-[var(--cmp-popover-radius)] py-[var(--cmp-popover-paddingY)] px-[var(--cmp-popover-paddingX)] text-[12px] leading-[20px] shadow-normal-sm",
|
|
6286
|
+
// 창보다 넓어지면 창 폭에 맞춘다. 최소 너비도 같은 상한으로 감싼다 —
|
|
6287
|
+
// min-width 가 max-width 를 이기므로 감싸지 않으면 상한이 무력화된다.
|
|
6288
|
+
"max-w-[var(--radix-popover-content-available-width)]",
|
|
6289
|
+
"min-w-[min(160px,var(--radix-popover-content-available-width))]",
|
|
6246
6290
|
FLOATING_SLIDE_ANIM,
|
|
6247
6291
|
menuClassName
|
|
6248
6292
|
),
|
|
@@ -6298,7 +6342,7 @@ function SPopover({
|
|
|
6298
6342
|
]
|
|
6299
6343
|
}
|
|
6300
6344
|
),
|
|
6301
|
-
/* @__PURE__ */ jsx(
|
|
6345
|
+
/* @__PURE__ */ jsx(RPopover9.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
6302
6346
|
]
|
|
6303
6347
|
}
|
|
6304
6348
|
) })
|
|
@@ -6327,8 +6371,9 @@ function SPortal({
|
|
|
6327
6371
|
ariaLabel
|
|
6328
6372
|
}) {
|
|
6329
6373
|
const portalContainer = usePortalContainer();
|
|
6374
|
+
const { minWidth: styleMinWidth, maxWidth: styleMaxWidth, ...restStyle } = style ?? {};
|
|
6330
6375
|
return /* @__PURE__ */ jsxs(
|
|
6331
|
-
|
|
6376
|
+
RPopover9.Root,
|
|
6332
6377
|
{
|
|
6333
6378
|
open,
|
|
6334
6379
|
onOpenChange: (next) => {
|
|
@@ -6336,9 +6381,9 @@ function SPortal({
|
|
|
6336
6381
|
if (!next) onClose?.();
|
|
6337
6382
|
},
|
|
6338
6383
|
children: [
|
|
6339
|
-
/* @__PURE__ */ jsx(
|
|
6340
|
-
/* @__PURE__ */ jsx(
|
|
6341
|
-
|
|
6384
|
+
/* @__PURE__ */ jsx(RPopover9.Anchor, { virtualRef: anchorRef }),
|
|
6385
|
+
/* @__PURE__ */ jsx(RPopover9.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
6386
|
+
RPopover9.Content,
|
|
6342
6387
|
{
|
|
6343
6388
|
side: placement,
|
|
6344
6389
|
align,
|
|
@@ -6365,11 +6410,18 @@ function SPortal({
|
|
|
6365
6410
|
className: cn(
|
|
6366
6411
|
"z-50 overflow-hidden rounded-(--cmp-listBox-radius) bg-(--cmp-listBox-bg) shadow-normal-sm",
|
|
6367
6412
|
maxHeight != null && "overflow-y-auto",
|
|
6368
|
-
|
|
6413
|
+
// 앵커가 창보다 넓을 수 있는 자리(가로 스크롤 안의 트리거 등)에서도 하한이 상한을
|
|
6414
|
+
// 이기지 않도록, 앵커 너비 역시 가용 폭으로 가둔다.
|
|
6415
|
+
fit && "min-w-[min(var(--radix-popover-trigger-width),var(--radix-popover-content-available-width))]",
|
|
6369
6416
|
FLOATING_SLIDE_ANIM,
|
|
6370
6417
|
className
|
|
6371
6418
|
),
|
|
6372
|
-
style: {
|
|
6419
|
+
style: {
|
|
6420
|
+
maxHeight,
|
|
6421
|
+
...restStyle,
|
|
6422
|
+
...styleMinWidth != null ? { minWidth: clampToAvailableWidth(styleMinWidth, POPOVER_AVAILABLE_WIDTH) } : {},
|
|
6423
|
+
maxWidth: clampToAvailableWidth(styleMaxWidth, POPOVER_AVAILABLE_WIDTH)
|
|
6424
|
+
},
|
|
6373
6425
|
children
|
|
6374
6426
|
}
|
|
6375
6427
|
) })
|
|
@@ -6529,16 +6581,18 @@ function SGuide({
|
|
|
6529
6581
|
);
|
|
6530
6582
|
if (isNotion)
|
|
6531
6583
|
return /* @__PURE__ */ jsx("span", { className, style, children: trigger });
|
|
6532
|
-
return /* @__PURE__ */ jsxs(
|
|
6533
|
-
/* @__PURE__ */ jsx(
|
|
6534
|
-
/* @__PURE__ */ jsx(
|
|
6535
|
-
|
|
6584
|
+
return /* @__PURE__ */ jsxs(RPopover9.Root, { open, onOpenChange: setOpen, children: [
|
|
6585
|
+
/* @__PURE__ */ jsx(RPopover9.Trigger, { asChild: true, children: trigger }),
|
|
6586
|
+
/* @__PURE__ */ jsx(RPopover9.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(
|
|
6587
|
+
RPopover9.Content,
|
|
6536
6588
|
{
|
|
6537
6589
|
side: "bottom",
|
|
6538
6590
|
align: "start",
|
|
6539
6591
|
sideOffset: 4,
|
|
6540
6592
|
className: cn(
|
|
6541
6593
|
"relative z-50 rounded-[var(--cmp-guide-contents-radius)] bg-[var(--color-white)]",
|
|
6594
|
+
// popupWidth(기본 426px)가 창보다 넓으면 창 폭에 맞춘다 — max-width 가 width 를 이긴다.
|
|
6595
|
+
"max-w-[var(--radix-popover-content-available-width)]",
|
|
6542
6596
|
FLOATING_SLIDE_ANIM
|
|
6543
6597
|
),
|
|
6544
6598
|
style: {
|
|
@@ -8611,10 +8665,10 @@ var SGnb = /* @__PURE__ */ forwardRef(function SGnb2({
|
|
|
8611
8665
|
}
|
|
8612
8666
|
),
|
|
8613
8667
|
header === "fix" && menuResizeHandle,
|
|
8614
|
-
/* @__PURE__ */ jsxs(
|
|
8615
|
-
/* @__PURE__ */ jsx(
|
|
8616
|
-
/* @__PURE__ */ jsx(
|
|
8617
|
-
|
|
8668
|
+
/* @__PURE__ */ jsxs(RPopover9.Root, { open: labelTip !== null, onOpenChange: (open) => !open && setLabelTip(null), children: [
|
|
8669
|
+
/* @__PURE__ */ jsx(RPopover9.Anchor, { virtualRef: labelTipAnchorRef }),
|
|
8670
|
+
/* @__PURE__ */ jsx(RPopover9.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
8671
|
+
RPopover9.Content,
|
|
8618
8672
|
{
|
|
8619
8673
|
side: "right",
|
|
8620
8674
|
sideOffset: 4,
|
|
@@ -8632,16 +8686,81 @@ var SGnb = /* @__PURE__ */ forwardRef(function SGnb2({
|
|
|
8632
8686
|
}
|
|
8633
8687
|
);
|
|
8634
8688
|
});
|
|
8689
|
+
var SPageHeader = /* @__PURE__ */ withDisplayName(
|
|
8690
|
+
forwardRef(function SPageHeader2({ title, subText, fix = false, onBack, slot, scrolled = false, className, style, ...rest }, ref) {
|
|
8691
|
+
const hasBack = onBack != null;
|
|
8692
|
+
return /* @__PURE__ */ jsxs(
|
|
8693
|
+
"header",
|
|
8694
|
+
{
|
|
8695
|
+
ref,
|
|
8696
|
+
className: cn(
|
|
8697
|
+
"relative z-10 box-border flex shrink-0 items-center gap-(--cmp-pageHeader-gap) px-(--cmp-pageHeader-paddingX)",
|
|
8698
|
+
fix ? "h-(--cmp-pageHeader-bar-height) border-b border-(--cmp-pageHeader-bar-border) bg-(--cmp-pageHeader-bar-bg) py-(--cmp-pageHeader-bar-paddingY)" : cn(
|
|
8699
|
+
// 배경은 항상 투명 — 페이지 배경을 따라갈지는 fix 가 정하지 scrolled 가 정하지 않는다.
|
|
8700
|
+
// 스크롤되면 그림자만 더해 콘텐츠 위에 뜬 것처럼 보이게 한다.
|
|
8701
|
+
"bg-transparent pt-(--cmp-pageHeader-plain-paddingTop) pb-(--cmp-pageHeader-plain-paddingBottom)",
|
|
8702
|
+
scrolled && "shadow-floating"
|
|
8703
|
+
),
|
|
8704
|
+
className
|
|
8705
|
+
),
|
|
8706
|
+
style,
|
|
8707
|
+
...rest,
|
|
8708
|
+
children: [
|
|
8709
|
+
hasBack && /* @__PURE__ */ jsx(
|
|
8710
|
+
SGhostButton,
|
|
8711
|
+
{
|
|
8712
|
+
icon: "chevronLeft",
|
|
8713
|
+
size: "xs",
|
|
8714
|
+
ariaLabel: "\uB4A4\uB85C\uAC00\uAE30",
|
|
8715
|
+
onClick: onBack,
|
|
8716
|
+
className: "shrink-0"
|
|
8717
|
+
}
|
|
8718
|
+
),
|
|
8719
|
+
/* @__PURE__ */ jsxs(
|
|
8720
|
+
"div",
|
|
8721
|
+
{
|
|
8722
|
+
className: cn(
|
|
8723
|
+
"flex min-w-0 flex-1 items-center",
|
|
8724
|
+
fix ? "flex-row gap-(--cmp-pageHeader-gap)" : "flex-col items-start gap-(--cmp-pageHeader-plain-title-gap)",
|
|
8725
|
+
!hasBack && "pl-(--cmp-pageHeader-title-paddingLeft)"
|
|
8726
|
+
),
|
|
8727
|
+
children: [
|
|
8728
|
+
/* @__PURE__ */ jsx("span", { className: "typo-heading-lg min-w-0 truncate text-(--cmp-pageHeader-title-text)", children: title }),
|
|
8729
|
+
subText && /* @__PURE__ */ jsx("span", { className: "typo-body-md-default min-w-0 truncate text-(--cmp-pageHeader-subtitle-text)", children: subText })
|
|
8730
|
+
]
|
|
8731
|
+
}
|
|
8732
|
+
),
|
|
8733
|
+
slot && /* @__PURE__ */ jsx("div", { className: "ml-auto flex shrink-0 items-center", children: slot })
|
|
8734
|
+
]
|
|
8735
|
+
}
|
|
8736
|
+
);
|
|
8737
|
+
}),
|
|
8738
|
+
"SPageHeader"
|
|
8739
|
+
);
|
|
8635
8740
|
var MIN_CONTENT_WIDTH = `calc(var(${SLAYOUT_MIN_WIDTH_VAR}, 0px) - 100cqw + 100%)`;
|
|
8636
8741
|
var BACKGROUND_CLASS = {
|
|
8637
8742
|
frame: `bg-[var(--sys-color-bg-frame)] ${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_CLASS}`,
|
|
8638
8743
|
neutral: `bg-[var(--sys-color-bg-neutralLight)] ${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_WHITE_CLASS}`,
|
|
8639
8744
|
screen: `bg-[var(--sys-color-bg-screen)] ${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_CLASS}`
|
|
8640
8745
|
};
|
|
8641
|
-
var SPage = /* @__PURE__ */ forwardRef(function SPage2({
|
|
8746
|
+
var SPage = /* @__PURE__ */ forwardRef(function SPage2({
|
|
8747
|
+
background = "frame",
|
|
8748
|
+
scrollEndSpacing = true,
|
|
8749
|
+
header,
|
|
8750
|
+
className,
|
|
8751
|
+
style,
|
|
8752
|
+
children,
|
|
8753
|
+
onScroll,
|
|
8754
|
+
...rest
|
|
8755
|
+
}, ref) {
|
|
8642
8756
|
const layout = useContext(SLayoutContext);
|
|
8643
8757
|
const gridStyle = layout?.header === "full" ? { gridArea: "page" } : void 0;
|
|
8644
|
-
|
|
8758
|
+
const [scrolled, setScrolled] = useState(false);
|
|
8759
|
+
const handleScroll = (e) => {
|
|
8760
|
+
onScroll?.(e);
|
|
8761
|
+
if (header != null && !header.fix) setScrolled(e.currentTarget.scrollTop > 0);
|
|
8762
|
+
};
|
|
8763
|
+
const main = /* @__PURE__ */ jsx(
|
|
8645
8764
|
"main",
|
|
8646
8765
|
{
|
|
8647
8766
|
ref,
|
|
@@ -8652,11 +8771,29 @@ var SPage = /* @__PURE__ */ forwardRef(function SPage2({ background = "frame", s
|
|
|
8652
8771
|
BACKGROUND_CLASS[background],
|
|
8653
8772
|
className
|
|
8654
8773
|
),
|
|
8655
|
-
style: { ...gridStyle, ...style },
|
|
8774
|
+
style: header == null ? { ...gridStyle, ...style } : style,
|
|
8775
|
+
onScroll: handleScroll,
|
|
8656
8776
|
...rest,
|
|
8657
8777
|
children: /* @__PURE__ */ jsx("div", { style: { minWidth: MIN_CONTENT_WIDTH }, children })
|
|
8658
8778
|
}
|
|
8659
8779
|
);
|
|
8780
|
+
if (header == null) return main;
|
|
8781
|
+
return (
|
|
8782
|
+
// fix 가 아닌 헤더는 자기 배경이 투명이라(SPageHeader.tsx) 이 배경이 그대로 비친다 —
|
|
8783
|
+
// 그래서 SPage 의 background 를 main 뿐 아니라 여기에도 칠한다(스크롤바 관련 클래스는
|
|
8784
|
+
// 스크롤 요소가 아닌 여기서는 그냥 무시된다). fix 헤더는 자체 흰 배경이 덮으므로 무관하다.
|
|
8785
|
+
/* @__PURE__ */ jsxs(
|
|
8786
|
+
"div",
|
|
8787
|
+
{
|
|
8788
|
+
className: cn("flex min-h-0 min-w-0 flex-1 flex-col", BACKGROUND_CLASS[background]),
|
|
8789
|
+
style: gridStyle,
|
|
8790
|
+
children: [
|
|
8791
|
+
/* @__PURE__ */ jsx(SPageHeader, { ...header, scrolled }),
|
|
8792
|
+
main
|
|
8793
|
+
]
|
|
8794
|
+
}
|
|
8795
|
+
)
|
|
8796
|
+
);
|
|
8660
8797
|
});
|
|
8661
8798
|
|
|
8662
8799
|
// src/components/SPage/page.config.ts
|
|
@@ -11030,7 +11167,7 @@ var SInput = /* @__PURE__ */ forwardRef(function SInput2({
|
|
|
11030
11167
|
lineHeight: `${f.lineHeight}px`
|
|
11031
11168
|
},
|
|
11032
11169
|
children: [
|
|
11033
|
-
prefix != null && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: prefix }),
|
|
11170
|
+
prefix != null && /* @__PURE__ */ jsx("span", { className: "flex flex-shrink-0 items-center", children: prefix }),
|
|
11034
11171
|
/* @__PURE__ */ jsx(
|
|
11035
11172
|
"input",
|
|
11036
11173
|
{
|
|
@@ -11062,7 +11199,7 @@ var SInput = /* @__PURE__ */ forwardRef(function SInput2({
|
|
|
11062
11199
|
...rest
|
|
11063
11200
|
}
|
|
11064
11201
|
),
|
|
11065
|
-
suffix != null && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: suffix }),
|
|
11202
|
+
suffix != null && /* @__PURE__ */ jsx("span", { className: "flex flex-shrink-0 items-center", children: suffix }),
|
|
11066
11203
|
clearable && hasValue && !disabled && !readOnly && /* @__PURE__ */ jsx(
|
|
11067
11204
|
SGhostButton,
|
|
11068
11205
|
{
|
|
@@ -11960,8 +12097,8 @@ function SDatePicker({
|
|
|
11960
12097
|
disabled,
|
|
11961
12098
|
className,
|
|
11962
12099
|
style,
|
|
11963
|
-
children: /* @__PURE__ */ jsxs(
|
|
11964
|
-
/* @__PURE__ */ jsx(
|
|
12100
|
+
children: /* @__PURE__ */ jsxs(RPopover9.Root, { open, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
12101
|
+
/* @__PURE__ */ jsx(RPopover9.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
11965
12102
|
"button",
|
|
11966
12103
|
{
|
|
11967
12104
|
type: "button",
|
|
@@ -11997,13 +12134,16 @@ function SDatePicker({
|
|
|
11997
12134
|
]
|
|
11998
12135
|
}
|
|
11999
12136
|
) }),
|
|
12000
|
-
/* @__PURE__ */ jsx(
|
|
12001
|
-
|
|
12137
|
+
/* @__PURE__ */ jsx(RPopover9.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
12138
|
+
RPopover9.Content,
|
|
12002
12139
|
{
|
|
12003
12140
|
side: "bottom",
|
|
12004
12141
|
align: "start",
|
|
12005
12142
|
sideOffset: 4,
|
|
12006
|
-
className: cn(
|
|
12143
|
+
className: cn(
|
|
12144
|
+
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
12145
|
+
FLOATING_SLIDE_ANIM
|
|
12146
|
+
),
|
|
12007
12147
|
children: /* @__PURE__ */ jsx(
|
|
12008
12148
|
SCalendar,
|
|
12009
12149
|
{
|
|
@@ -12151,78 +12291,81 @@ function RangeCalendar({
|
|
|
12151
12291
|
}
|
|
12152
12292
|
};
|
|
12153
12293
|
const GRID_COLS = "grid grid-cols-[repeat(7,var(--cmp-datepicker-calendar-day-width))]";
|
|
12154
|
-
const renderPanel = (gy, gm, isLeft) =>
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
|
|
12158
|
-
|
|
12159
|
-
|
|
12160
|
-
|
|
12161
|
-
|
|
12162
|
-
|
|
12163
|
-
|
|
12164
|
-
|
|
12165
|
-
|
|
12166
|
-
|
|
12167
|
-
|
|
12168
|
-
"
|
|
12169
|
-
|
|
12294
|
+
const renderPanel = (gy, gm, isLeft) => (
|
|
12295
|
+
// 좁은 창에서 눌려 격자가 깨지지 않도록, 줄이는 대신 부모가 가로 스크롤하게 둔다.
|
|
12296
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col gap-[var(--cmp-datepicker-calendar-gap)]", children: [
|
|
12297
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-[var(--cmp-datepicker-calendar-gap)]", children: [
|
|
12298
|
+
/* @__PURE__ */ jsx(
|
|
12299
|
+
SGhostButton,
|
|
12300
|
+
{
|
|
12301
|
+
icon: "chevronLeft",
|
|
12302
|
+
size: "xxs",
|
|
12303
|
+
ariaLabel: "prevMonth",
|
|
12304
|
+
onClick: goPrevMonth,
|
|
12305
|
+
className: cn(!isLeft && "invisible pointer-events-none")
|
|
12306
|
+
}
|
|
12307
|
+
),
|
|
12308
|
+
/* @__PURE__ */ jsxs("span", { className: "inline-flex min-w-[40px] flex-1 items-center justify-center text-center text-[14px] font-medium leading-[24px]", children: [
|
|
12309
|
+
gy,
|
|
12310
|
+
".",
|
|
12311
|
+
String(gm).padStart(2, "0")
|
|
12312
|
+
] }),
|
|
12313
|
+
/* @__PURE__ */ jsx(
|
|
12314
|
+
SGhostButton,
|
|
12315
|
+
{
|
|
12316
|
+
icon: "chevronRight",
|
|
12317
|
+
size: "xxs",
|
|
12318
|
+
ariaLabel: "nextMonth",
|
|
12319
|
+
onClick: goNextMonth,
|
|
12320
|
+
className: cn(isLeft && "invisible pointer-events-none")
|
|
12321
|
+
}
|
|
12322
|
+
)
|
|
12170
12323
|
] }),
|
|
12171
|
-
/* @__PURE__ */ jsx(
|
|
12172
|
-
|
|
12173
|
-
{
|
|
12174
|
-
icon: "chevronRight",
|
|
12175
|
-
size: "xxs",
|
|
12176
|
-
ariaLabel: "nextMonth",
|
|
12177
|
-
onClick: goNextMonth,
|
|
12178
|
-
className: cn(isLeft && "invisible pointer-events-none")
|
|
12179
|
-
}
|
|
12180
|
-
)
|
|
12181
|
-
] }),
|
|
12182
|
-
/* @__PURE__ */ jsx("div", { className: GRID_COLS, children: WEEK_LABELS.map((l) => /* @__PURE__ */ jsx(
|
|
12183
|
-
"span",
|
|
12184
|
-
{
|
|
12185
|
-
className: "flex h-[20px] items-center justify-center text-[12px] font-normal text-[color:var(--cmp-datepicker-calendar-week-color)]",
|
|
12186
|
-
children: l
|
|
12187
|
-
},
|
|
12188
|
-
l
|
|
12189
|
-
)) }),
|
|
12190
|
-
/* @__PURE__ */ jsx("div", { className: cn(GRID_COLS, "gap-y-[var(--cmp-datepicker-calendar-grid-rowGap)]"), children: monthCells(gy, gm).map((cell) => {
|
|
12191
|
-
const isEdge = cell.inCurrentMonth && (cell.date === rStart || complete && cell.date === rEnd);
|
|
12192
|
-
const between = cell.inCurrentMonth && inRange(cell.date);
|
|
12193
|
-
const disabled = cell.inCurrentMonth && isDisabled(cell.date);
|
|
12194
|
-
const isToday = cell.inCurrentMonth && today === cell.date;
|
|
12195
|
-
let cellBg;
|
|
12196
|
-
if (between) cellBg = RANGE_BG;
|
|
12197
|
-
else if (cell.inCurrentMonth && hasRange && cell.date === rStart)
|
|
12198
|
-
cellBg = `linear-gradient(to right, transparent 50%, ${RANGE_BG} 50%)`;
|
|
12199
|
-
else if (cell.inCurrentMonth && hasRange && cell.date === rEnd) cellBg = RANGE_BG;
|
|
12200
|
-
return /* @__PURE__ */ jsx(
|
|
12201
|
-
"div",
|
|
12324
|
+
/* @__PURE__ */ jsx("div", { className: GRID_COLS, children: WEEK_LABELS.map((l) => /* @__PURE__ */ jsx(
|
|
12325
|
+
"span",
|
|
12202
12326
|
{
|
|
12203
|
-
className: "flex h-[
|
|
12204
|
-
|
|
12205
|
-
children: /* @__PURE__ */ jsx(
|
|
12206
|
-
"button",
|
|
12207
|
-
{
|
|
12208
|
-
type: "button",
|
|
12209
|
-
disabled: !cell.inCurrentMonth || disabled,
|
|
12210
|
-
onMouseEnter: () => setHover(cell.date),
|
|
12211
|
-
onClick: () => cell.inCurrentMonth && click(cell.date),
|
|
12212
|
-
className: cn(
|
|
12213
|
-
"relative z-[1] flex h-[var(--cmp-datepicker-calendar-day-circle-size)] w-[var(--cmp-datepicker-calendar-day-circle-size)] items-center justify-center rounded-[var(--cmp-datepicker-calendar-day-circle-radius)] border border-solid border-transparent bg-transparent text-[14px]",
|
|
12214
|
-
!cell.inCurrentMonth ? "invisible pointer-events-none" : disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
12215
|
-
isEdge ? "bg-[var(--cmp-datepicker-calendar-day-select-bg)] text-[color:var(--cmp-datepicker-calendar-day-select-text)]" : disabled ? "text-[color:var(--cmp-datepicker-calendar-day-disabled-text)]" : "text-[color:var(--cmp-datepicker-calendar-day-default-text)] hover:border-[color:var(--cmp-datepicker-calendar-day-hover-border)] hover:text-[color:var(--cmp-datepicker-calendar-day-hover-text)]",
|
|
12216
|
-
isToday && !disabled && "font-bold"
|
|
12217
|
-
),
|
|
12218
|
-
children: cell.inCurrentMonth ? cell.day : ""
|
|
12219
|
-
}
|
|
12220
|
-
)
|
|
12327
|
+
className: "flex h-[20px] items-center justify-center text-[12px] font-normal text-[color:var(--cmp-datepicker-calendar-week-color)]",
|
|
12328
|
+
children: l
|
|
12221
12329
|
},
|
|
12222
|
-
|
|
12223
|
-
)
|
|
12224
|
-
|
|
12225
|
-
|
|
12330
|
+
l
|
|
12331
|
+
)) }),
|
|
12332
|
+
/* @__PURE__ */ jsx("div", { className: cn(GRID_COLS, "gap-y-[var(--cmp-datepicker-calendar-grid-rowGap)]"), children: monthCells(gy, gm).map((cell) => {
|
|
12333
|
+
const isEdge = cell.inCurrentMonth && (cell.date === rStart || complete && cell.date === rEnd);
|
|
12334
|
+
const between = cell.inCurrentMonth && inRange(cell.date);
|
|
12335
|
+
const disabled = cell.inCurrentMonth && isDisabled(cell.date);
|
|
12336
|
+
const isToday = cell.inCurrentMonth && today === cell.date;
|
|
12337
|
+
let cellBg;
|
|
12338
|
+
if (between) cellBg = RANGE_BG;
|
|
12339
|
+
else if (cell.inCurrentMonth && hasRange && cell.date === rStart)
|
|
12340
|
+
cellBg = `linear-gradient(to right, transparent 50%, ${RANGE_BG} 50%)`;
|
|
12341
|
+
else if (cell.inCurrentMonth && hasRange && cell.date === rEnd) cellBg = RANGE_BG;
|
|
12342
|
+
return /* @__PURE__ */ jsx(
|
|
12343
|
+
"div",
|
|
12344
|
+
{
|
|
12345
|
+
className: "flex h-[var(--cmp-datepicker-calendar-range-height)] w-[var(--cmp-datepicker-calendar-day-width)] items-center justify-center",
|
|
12346
|
+
style: { background: cellBg },
|
|
12347
|
+
children: /* @__PURE__ */ jsx(
|
|
12348
|
+
"button",
|
|
12349
|
+
{
|
|
12350
|
+
type: "button",
|
|
12351
|
+
disabled: !cell.inCurrentMonth || disabled,
|
|
12352
|
+
onMouseEnter: () => setHover(cell.date),
|
|
12353
|
+
onClick: () => cell.inCurrentMonth && click(cell.date),
|
|
12354
|
+
className: cn(
|
|
12355
|
+
"relative z-[1] flex h-[var(--cmp-datepicker-calendar-day-circle-size)] w-[var(--cmp-datepicker-calendar-day-circle-size)] items-center justify-center rounded-[var(--cmp-datepicker-calendar-day-circle-radius)] border border-solid border-transparent bg-transparent text-[14px]",
|
|
12356
|
+
!cell.inCurrentMonth ? "invisible pointer-events-none" : disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
12357
|
+
isEdge ? "bg-[var(--cmp-datepicker-calendar-day-select-bg)] text-[color:var(--cmp-datepicker-calendar-day-select-text)]" : disabled ? "text-[color:var(--cmp-datepicker-calendar-day-disabled-text)]" : "text-[color:var(--cmp-datepicker-calendar-day-default-text)] hover:border-[color:var(--cmp-datepicker-calendar-day-hover-border)] hover:text-[color:var(--cmp-datepicker-calendar-day-hover-text)]",
|
|
12358
|
+
isToday && !disabled && "font-bold"
|
|
12359
|
+
),
|
|
12360
|
+
children: cell.inCurrentMonth ? cell.day : ""
|
|
12361
|
+
}
|
|
12362
|
+
)
|
|
12363
|
+
},
|
|
12364
|
+
cell.date
|
|
12365
|
+
);
|
|
12366
|
+
}) })
|
|
12367
|
+
] })
|
|
12368
|
+
);
|
|
12226
12369
|
const renderTimeSection = (which, date, suffix) => {
|
|
12227
12370
|
const active = !!date;
|
|
12228
12371
|
const [yy = "", mm = "", dd = ""] = date ? date.split("-") : [];
|
|
@@ -12290,8 +12433,11 @@ function RangeCalendar({
|
|
|
12290
12433
|
"div",
|
|
12291
12434
|
{
|
|
12292
12435
|
className: cn(
|
|
12293
|
-
"inline-flex flex-col gap-[var(--cmp-datepicker-calendar-gap)] rounded-[var(--cmp-datepicker-calendar-radius)] bg-[var(--cmp-datepicker-calendar-bg)] p-[var(--cmp-datepicker-calendar-paddingXY)] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.2)] select-none",
|
|
12294
|
-
|
|
12436
|
+
"inline-flex max-w-full flex-col gap-[var(--cmp-datepicker-calendar-gap)] rounded-[var(--cmp-datepicker-calendar-radius)] bg-[var(--cmp-datepicker-calendar-bg)] p-[var(--cmp-datepicker-calendar-paddingXY)] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.2)] select-none",
|
|
12437
|
+
// 높이는 고정이 아니라 하한이다 — 5주/6주 달을 오갈 때의 높이 흔들림만 막으면 되고,
|
|
12438
|
+
// 창이 좁아 패널이 가로 스크롤될 때는 스크롤바 높이만큼 늘어날 수 있어야 한다.
|
|
12439
|
+
// (단일 달 SCalendar 도 min-h 를 쓴다)
|
|
12440
|
+
useTimePicker ? "h-auto" : "min-h-[364px]"
|
|
12295
12441
|
),
|
|
12296
12442
|
children: [
|
|
12297
12443
|
/* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
@@ -12310,11 +12456,20 @@ function RangeCalendar({
|
|
|
12310
12456
|
}
|
|
12311
12457
|
)
|
|
12312
12458
|
] }),
|
|
12313
|
-
/* @__PURE__ */ jsxs(
|
|
12314
|
-
|
|
12315
|
-
|
|
12316
|
-
|
|
12317
|
-
|
|
12459
|
+
/* @__PURE__ */ jsxs(
|
|
12460
|
+
"div",
|
|
12461
|
+
{
|
|
12462
|
+
className: cn(
|
|
12463
|
+
"flex max-w-full gap-[var(--cmp-datepicker-calendar-range-panelGap)] overflow-x-auto",
|
|
12464
|
+
SCROLLBAR_CLASS
|
|
12465
|
+
),
|
|
12466
|
+
children: [
|
|
12467
|
+
renderPanel(y, m, true),
|
|
12468
|
+
/* @__PURE__ */ jsx(SDivider, { vertical: true }),
|
|
12469
|
+
renderPanel(nextMonthYM.year, nextMonthYM.month, false)
|
|
12470
|
+
]
|
|
12471
|
+
}
|
|
12472
|
+
),
|
|
12318
12473
|
useTimePicker && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
12319
12474
|
/* @__PURE__ */ jsx(SDivider, {}),
|
|
12320
12475
|
/* @__PURE__ */ jsxs("div", { className: "flex gap-[var(--cmp-datepicker-calendar-time-gap)]", children: [
|
|
@@ -12373,7 +12528,25 @@ function SDateRangePicker({
|
|
|
12373
12528
|
});
|
|
12374
12529
|
const resolvedError = error || ruleError !== "";
|
|
12375
12530
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
12376
|
-
const dims = size === "md" ? {
|
|
12531
|
+
const dims = size === "md" ? {
|
|
12532
|
+
padX: 16,
|
|
12533
|
+
gap: 12,
|
|
12534
|
+
icon: 20,
|
|
12535
|
+
minW: 104,
|
|
12536
|
+
fieldMinW: 260,
|
|
12537
|
+
fontSize: 14,
|
|
12538
|
+
lineHeight: 24,
|
|
12539
|
+
radius: 6
|
|
12540
|
+
} : {
|
|
12541
|
+
padX: 12,
|
|
12542
|
+
gap: 8,
|
|
12543
|
+
icon: 16,
|
|
12544
|
+
minW: 80,
|
|
12545
|
+
fieldMinW: 216,
|
|
12546
|
+
fontSize: 12,
|
|
12547
|
+
lineHeight: 20,
|
|
12548
|
+
radius: 4
|
|
12549
|
+
};
|
|
12377
12550
|
const select = (r) => {
|
|
12378
12551
|
setPendingStart(null);
|
|
12379
12552
|
onValueChange?.(r);
|
|
@@ -12399,11 +12572,12 @@ function SDateRangePicker({
|
|
|
12399
12572
|
focused: open,
|
|
12400
12573
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
12401
12574
|
width,
|
|
12575
|
+
minWidth: dims.fieldMinW,
|
|
12402
12576
|
disabled,
|
|
12403
12577
|
className,
|
|
12404
12578
|
style,
|
|
12405
12579
|
children: /* @__PURE__ */ jsxs(
|
|
12406
|
-
|
|
12580
|
+
RPopover9.Root,
|
|
12407
12581
|
{
|
|
12408
12582
|
open,
|
|
12409
12583
|
onOpenChange: (o) => {
|
|
@@ -12412,7 +12586,7 @@ function SDateRangePicker({
|
|
|
12412
12586
|
if (!o) setPendingStart(null);
|
|
12413
12587
|
},
|
|
12414
12588
|
children: [
|
|
12415
|
-
/* @__PURE__ */ jsx(
|
|
12589
|
+
/* @__PURE__ */ jsx(RPopover9.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
12416
12590
|
"button",
|
|
12417
12591
|
{
|
|
12418
12592
|
type: "button",
|
|
@@ -12453,13 +12627,16 @@ function SDateRangePicker({
|
|
|
12453
12627
|
]
|
|
12454
12628
|
}
|
|
12455
12629
|
) }),
|
|
12456
|
-
/* @__PURE__ */ jsx(
|
|
12457
|
-
|
|
12630
|
+
/* @__PURE__ */ jsx(RPopover9.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
12631
|
+
RPopover9.Content,
|
|
12458
12632
|
{
|
|
12459
12633
|
side: "bottom",
|
|
12460
12634
|
align: "start",
|
|
12461
12635
|
sideOffset: 4,
|
|
12462
|
-
className: cn(
|
|
12636
|
+
className: cn(
|
|
12637
|
+
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
12638
|
+
FLOATING_SLIDE_ANIM
|
|
12639
|
+
),
|
|
12463
12640
|
children: /* @__PURE__ */ jsx(
|
|
12464
12641
|
RangeCalendar,
|
|
12465
12642
|
{
|
|
@@ -13447,7 +13624,7 @@ function SRadioButton({
|
|
|
13447
13624
|
disabled: od,
|
|
13448
13625
|
onClick: () => !od && !selected && onValueChange?.(o.value),
|
|
13449
13626
|
className: cn(
|
|
13450
|
-
"relative box-border inline-flex items-center justify-center whitespace-nowrap border border-solid text-[12px] font-medium leading-[20px] transition-colors",
|
|
13627
|
+
"relative box-border grow inline-flex items-center justify-center whitespace-nowrap border border-solid text-[12px] font-medium leading-[20px] transition-colors",
|
|
13451
13628
|
i === 0 ? "rounded-l-[var(--cmp-radioButton-radius)]" : "-ml-px",
|
|
13452
13629
|
i === options.length - 1 ? "rounded-r-[var(--cmp-radioButton-radius)]" : "",
|
|
13453
13630
|
selected ? "z-10" : "",
|
|
@@ -13469,99 +13646,1323 @@ function SRadioButton({
|
|
|
13469
13646
|
}
|
|
13470
13647
|
);
|
|
13471
13648
|
}
|
|
13472
|
-
var
|
|
13473
|
-
|
|
13649
|
+
var CHIPFILTER_LISTBOX_WIDTH = 240;
|
|
13650
|
+
var CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH = 246;
|
|
13651
|
+
var CHIPFILTER = {
|
|
13652
|
+
barBg: "var(--cmp-chipFilter-bar-bg)",
|
|
13653
|
+
barBorder: "var(--cmp-chipFilter-bar-border)",
|
|
13654
|
+
barPaddingX: "var(--cmp-chipFilter-bar-paddingX)",
|
|
13655
|
+
barPaddingY: "var(--cmp-chipFilter-bar-paddingY)",
|
|
13656
|
+
barGap: "var(--cmp-chipFilter-bar-gap)",
|
|
13657
|
+
dividerHeight: "var(--cmp-chipFilter-divider-height)",
|
|
13658
|
+
chipHeight: "var(--cmp-chipFilter-chip-height)",
|
|
13659
|
+
chipRadius: "var(--cmp-chipFilter-chip-radius)",
|
|
13660
|
+
chipGap: "var(--cmp-chipFilter-chip-gap)",
|
|
13661
|
+
chipDefaultBg: "var(--cmp-chipFilter-chip-default-bg)",
|
|
13662
|
+
chipDefaultBorder: "var(--cmp-chipFilter-chip-default-border)",
|
|
13663
|
+
chipDefaultText: "var(--cmp-chipFilter-chip-default-text)",
|
|
13664
|
+
chipActiveBorder: "var(--cmp-chipFilter-chip-active-border)",
|
|
13665
|
+
chipWarningBorder: "var(--cmp-chipFilter-chip-warning-border)",
|
|
13666
|
+
chipAppliedBg: "var(--cmp-chipFilter-chip-applied-bg)",
|
|
13667
|
+
chipAppliedBorder: "var(--cmp-chipFilter-chip-applied-border)",
|
|
13668
|
+
chipAppliedLabel: "var(--cmp-chipFilter-chip-applied-text-label)",
|
|
13669
|
+
chipAppliedValue: "var(--color-brilliantblue-80)",
|
|
13670
|
+
chipDisabledBg: "var(--cmp-chipFilter-chip-disabled-bg)",
|
|
13671
|
+
chipDisabledBorder: "var(--cmp-chipFilter-chip-disabled-border)",
|
|
13672
|
+
chipDisabledText: "var(--cmp-chipFilter-chip-disabled-text)",
|
|
13673
|
+
addBorder: "var(--cmp-chipFilter-addButton-border-default)",
|
|
13674
|
+
addBorderDisabled: "var(--cmp-chipFilter-addButton-border-disabled)",
|
|
13675
|
+
addText: "var(--cmp-chipFilter-addButton-text-default)",
|
|
13676
|
+
addTextDisabled: "var(--cmp-chipFilter-addButton-text-disabled)",
|
|
13677
|
+
listboxBg: "var(--cmp-chipFilter-listbox-bg)",
|
|
13678
|
+
listboxBorder: "var(--cmp-chipFilter-listbox-border-color)",
|
|
13679
|
+
listboxRadius: "var(--cmp-chipFilter-listbox-radius)",
|
|
13680
|
+
listboxLabel: "var(--cmp-chipFilter-listbox-top-label-color)",
|
|
13681
|
+
listboxBottomDividerHeight: "var(--cmp-chipFilter-listbox-bottom-divider-height)",
|
|
13682
|
+
itemPaddingLeft: "var(--cmp-chipFilter-item-paddingLeft)",
|
|
13683
|
+
itemPaddingRight: "var(--cmp-chipFilter-item-paddingRight)",
|
|
13684
|
+
itemPaddingY: "var(--cmp-chipFilter-item-paddingY)",
|
|
13685
|
+
itemMultiPaddingX: "var(--cmp-chipFilter-item-multi-paddingX)",
|
|
13686
|
+
itemTextDefault: "var(--cmp-chipFilter-item-text-default)",
|
|
13687
|
+
itemTextSelected: "var(--cmp-chipFilter-item-text-selected)"
|
|
13688
|
+
};
|
|
13689
|
+
var isKeywordValue = (value) => typeof value === "object" && value != null && !Array.isArray(value) && "keywords" in value;
|
|
13690
|
+
var keywordEntries = (value) => {
|
|
13691
|
+
if (isKeywordValue(value)) return value.keywords;
|
|
13692
|
+
if (Array.isArray(value)) {
|
|
13693
|
+
return value.filter((v) => typeof v === "string");
|
|
13694
|
+
}
|
|
13695
|
+
return [];
|
|
13696
|
+
};
|
|
13697
|
+
var isEmptyValue = (value) => {
|
|
13698
|
+
if (value == null) return true;
|
|
13699
|
+
if (Array.isArray(value)) return value.length === 0 || value.every((v) => v == null || v === "");
|
|
13700
|
+
if (isKeywordValue(value)) return value.keywords.length === 0;
|
|
13701
|
+
return value === "";
|
|
13702
|
+
};
|
|
13703
|
+
var normalizeValues = (value) => value ?? {};
|
|
13704
|
+
var toArrayValue = (value) => Array.isArray(value) ? value.filter(
|
|
13705
|
+
(v) => typeof v === "string" || typeof v === "number"
|
|
13706
|
+
) : [];
|
|
13707
|
+
var todayIso = () => {
|
|
13708
|
+
const d = /* @__PURE__ */ new Date();
|
|
13709
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
13710
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
13711
|
+
};
|
|
13712
|
+
var isInlineDateField = (field) => field.type === "date" && field.radioButton === true && (field.presets?.length ?? 0) > 0;
|
|
13713
|
+
var resolveFieldDefault = (field) => {
|
|
13714
|
+
if (field.defaultValue !== void 0) return field.defaultValue;
|
|
13715
|
+
if (isInlineDateField(field)) return todayIso();
|
|
13716
|
+
if (!field.required) return void 0;
|
|
13717
|
+
if (field.type === "single") return field.options?.[0]?.value;
|
|
13718
|
+
if (field.type === "date") return todayIso();
|
|
13719
|
+
return void 0;
|
|
13720
|
+
};
|
|
13721
|
+
var valuesEqual = (a, b) => {
|
|
13722
|
+
if (isKeywordValue(a) || isKeywordValue(b)) {
|
|
13723
|
+
return isKeywordValue(a) && isKeywordValue(b) && a.mode === b.mode && valuesEqual(a.keywords, b.keywords);
|
|
13724
|
+
}
|
|
13725
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
13726
|
+
return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((v, i) => v === b[i]);
|
|
13727
|
+
}
|
|
13728
|
+
return a === b;
|
|
13729
|
+
};
|
|
13730
|
+
var valuesMapEqual = (a, b) => {
|
|
13731
|
+
const keys = /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)]);
|
|
13732
|
+
for (const key of keys) {
|
|
13733
|
+
if (!valuesEqual(a[key], b[key])) return false;
|
|
13734
|
+
}
|
|
13735
|
+
return true;
|
|
13736
|
+
};
|
|
13737
|
+
var isAtDefaultValue = (field, value) => {
|
|
13738
|
+
const def = resolveFieldDefault(field);
|
|
13739
|
+
return def !== void 0 && valuesEqual(value, def);
|
|
13740
|
+
};
|
|
13741
|
+
var isInlineField = (field) => isInlineDateField(field) || field.type === "custom";
|
|
13742
|
+
var isGroupedFields = (fields) => fields.length > 0 && "fields" in fields[0];
|
|
13743
|
+
var isGroupSatisfied = (group, values) => {
|
|
13744
|
+
if (!group.rule) return true;
|
|
13745
|
+
const keys = group.fields.map((f) => f.key);
|
|
13746
|
+
if (group.rule.type === "requireKey") return !isEmptyValue(values[group.rule.key]);
|
|
13747
|
+
if (group.rule.type === "requireAll") return keys.every((k) => !isEmptyValue(values[k]));
|
|
13748
|
+
if (group.rule.type === "requireAny") return keys.some((k) => !isEmptyValue(values[k]));
|
|
13749
|
+
return true;
|
|
13750
|
+
};
|
|
13751
|
+
var koreanParticle = (word, consonant, vowel) => {
|
|
13752
|
+
const code = word.charCodeAt(word.length - 1);
|
|
13753
|
+
if (code < 44032 || code > 55203) return consonant;
|
|
13754
|
+
return (code - 44032) % 28 === 0 ? vowel : consonant;
|
|
13755
|
+
};
|
|
13756
|
+
var defaultGroupTooltipMessage = (rule, fields) => {
|
|
13757
|
+
if (rule.type === "requireAll") return "\uD56D\uBAA9\uC744 \uBAA8\uB450 \uC120\uD0DD\uD574 \uC8FC\uC138\uC694.";
|
|
13758
|
+
if (rule.type === "requireAny") {
|
|
13759
|
+
const name = rule.dataGroupName;
|
|
13760
|
+
if (!name) return "\uCD5C\uC18C 1\uAC1C\uC758 \uD544\uD130\uB97C \uC120\uD0DD\uD574\uC8FC\uC138\uC694.";
|
|
13761
|
+
return `\uCD5C\uC18C 1\uAC1C\uC758 ${name}${koreanParticle(name, "\uC744", "\uB97C")} \uC120\uD0DD\uD574\uC8FC\uC138\uC694.`;
|
|
13762
|
+
}
|
|
13763
|
+
const label = fields.find((f) => f.key === rule.key)?.label ?? "\uD56D\uBAA9";
|
|
13764
|
+
return `${label}${koreanParticle(label, "\uC744", "\uB97C")} \uC120\uD0DD\uD574 \uC8FC\uC138\uC694.`;
|
|
13765
|
+
};
|
|
13766
|
+
var matchPresetId = (presets, value) => {
|
|
13767
|
+
if (isEmptyValue(value)) return null;
|
|
13768
|
+
for (const preset of presets) {
|
|
13769
|
+
if (preset.custom || !preset.resolve) continue;
|
|
13770
|
+
const resolved = preset.resolve();
|
|
13771
|
+
if (Array.isArray(resolved) && Array.isArray(value)) {
|
|
13772
|
+
if (resolved[0] === value[0] && resolved[1] === value[1]) return preset.value;
|
|
13773
|
+
} else if (!Array.isArray(resolved) && !Array.isArray(value) && resolved === value) {
|
|
13774
|
+
return preset.value;
|
|
13775
|
+
}
|
|
13776
|
+
}
|
|
13777
|
+
return presets.find((preset) => preset.custom)?.value ?? null;
|
|
13778
|
+
};
|
|
13779
|
+
var optionLabel = (field, value) => field.options?.find((option) => option.value === value)?.label ?? String(value);
|
|
13780
|
+
var formatValueList = (labels) => {
|
|
13781
|
+
if (labels.length <= 1) return labels[0] ?? "";
|
|
13782
|
+
return `${labels[0]} \uC678 ${labels.length - 1}\uAC1C`;
|
|
13783
|
+
};
|
|
13784
|
+
var displayValue = (field, value) => {
|
|
13785
|
+
if (isEmptyValue(value)) return "";
|
|
13786
|
+
if (field.type === "multi")
|
|
13787
|
+
return formatValueList(toArrayValue(value).map((v) => optionLabel(field, v)));
|
|
13788
|
+
if (field.type === "single") return optionLabel(field, value);
|
|
13789
|
+
if (field.type === "date")
|
|
13790
|
+
return Array.isArray(value) ? `${value[0]} ~ ${value[1]}` : String(value);
|
|
13791
|
+
if (field.type === "keyword") return formatValueList(keywordEntries(value));
|
|
13792
|
+
return String(value);
|
|
13793
|
+
};
|
|
13794
|
+
var chipDisplayValue = (field, value) => {
|
|
13795
|
+
const text = displayValue(field, value);
|
|
13796
|
+
if (field.type !== "date" || isEmptyValue(value)) return text;
|
|
13797
|
+
const presets = field.presets ?? [];
|
|
13798
|
+
if (presets.length === 0) return text;
|
|
13799
|
+
const preset = presets.find((p) => p.value === matchPresetId(presets, value));
|
|
13800
|
+
return preset && !preset.custom ? `${preset.label}(${text})` : text;
|
|
13801
|
+
};
|
|
13802
|
+
var SChipFilter = /* @__PURE__ */ forwardRef(function SChipFilter2({
|
|
13803
|
+
fields: fieldsProp = [],
|
|
13804
|
+
value,
|
|
13474
13805
|
onValueChange,
|
|
13475
|
-
|
|
13476
|
-
|
|
13477
|
-
|
|
13478
|
-
|
|
13479
|
-
|
|
13480
|
-
|
|
13806
|
+
onFilterChange,
|
|
13807
|
+
onSearch,
|
|
13808
|
+
activeKeys,
|
|
13809
|
+
onActiveKeysChange,
|
|
13810
|
+
onReset,
|
|
13811
|
+
onAddFilter,
|
|
13812
|
+
label = "\uAC80\uC0C9 \uD544\uD130",
|
|
13813
|
+
showLabel = false,
|
|
13814
|
+
showAddButton = true,
|
|
13815
|
+
showReset = true,
|
|
13481
13816
|
disabled = false,
|
|
13482
|
-
placeholder = "\uD0DC\uADF8 \uC785\uB825 (Enter\uB85C \uB4F1\uB85D / \uCF64\uB9C8\uB85C \uAD6C\uBD84 / \uB744\uC5B4\uC4F0\uAE30 \uBD88\uAC00)",
|
|
13483
|
-
name,
|
|
13484
|
-
rules,
|
|
13485
|
-
error,
|
|
13486
|
-
useReset = false,
|
|
13487
|
-
maxCount,
|
|
13488
|
-
metaPlacement = "end",
|
|
13489
|
-
duplicateLabel,
|
|
13490
|
-
suggestions = [],
|
|
13491
|
-
loadingSuggestions = false,
|
|
13492
|
-
recommendedItems = [],
|
|
13493
|
-
loadingRecommendedItems = false,
|
|
13494
|
-
dropdownMinWidth = 200,
|
|
13495
|
-
label,
|
|
13496
|
-
labelWidth,
|
|
13497
|
-
hint,
|
|
13498
|
-
errorMessage,
|
|
13499
|
-
width,
|
|
13500
|
-
status,
|
|
13501
|
-
icon,
|
|
13502
|
-
iconColor,
|
|
13503
|
-
labelTooltip,
|
|
13504
|
-
labelTooltipProps,
|
|
13505
13817
|
className,
|
|
13506
13818
|
style
|
|
13507
13819
|
}, ref) {
|
|
13508
|
-
const
|
|
13509
|
-
const
|
|
13510
|
-
|
|
13511
|
-
|
|
13512
|
-
|
|
13513
|
-
const
|
|
13514
|
-
const
|
|
13515
|
-
const
|
|
13516
|
-
const
|
|
13517
|
-
|
|
13518
|
-
|
|
13519
|
-
const
|
|
13520
|
-
|
|
13521
|
-
const
|
|
13522
|
-
|
|
13523
|
-
|
|
13524
|
-
|
|
13525
|
-
|
|
13526
|
-
const
|
|
13527
|
-
|
|
13528
|
-
|
|
13529
|
-
|
|
13530
|
-
|
|
13531
|
-
|
|
13532
|
-
|
|
13533
|
-
|
|
13534
|
-
|
|
13535
|
-
|
|
13536
|
-
|
|
13537
|
-
|
|
13538
|
-
|
|
13539
|
-
|
|
13540
|
-
|
|
13541
|
-
|
|
13542
|
-
|
|
13543
|
-
|
|
13544
|
-
|
|
13545
|
-
|
|
13546
|
-
|
|
13547
|
-
|
|
13820
|
+
const usingGroupedFields = isGroupedFields(fieldsProp);
|
|
13821
|
+
const groups = useMemo(
|
|
13822
|
+
() => usingGroupedFields ? fieldsProp : [{ fields: fieldsProp }],
|
|
13823
|
+
[usingGroupedFields, fieldsProp]
|
|
13824
|
+
);
|
|
13825
|
+
const fields = useMemo(() => groups.flatMap((group) => group.fields), [groups]);
|
|
13826
|
+
const values = normalizeValues(value);
|
|
13827
|
+
const portalContainer = usePortalContainer();
|
|
13828
|
+
const [internalActiveKeys, setInternalActiveKeys] = useState(
|
|
13829
|
+
() => fields.filter((field) => field.defaultActive !== false).map((field) => field.key)
|
|
13830
|
+
);
|
|
13831
|
+
const [openKey, setOpenKey] = useState(null);
|
|
13832
|
+
const [addOpen, setAddOpen] = useState(false);
|
|
13833
|
+
const triggerRefs = useRef(/* @__PURE__ */ new Map());
|
|
13834
|
+
const initializedDefaultsRef = useRef(/* @__PURE__ */ new Set());
|
|
13835
|
+
const prevOpenKeyRef = useRef(null);
|
|
13836
|
+
const valuesRef = useRef(values);
|
|
13837
|
+
valuesRef.current = values;
|
|
13838
|
+
const lastSearchedValuesRef = useRef(values);
|
|
13839
|
+
const invalidGroups = useMemo(() => {
|
|
13840
|
+
const invalid = /* @__PURE__ */ new Set();
|
|
13841
|
+
groups.forEach((group, groupIndex) => {
|
|
13842
|
+
if (!isGroupSatisfied(group, values)) invalid.add(groupIndex);
|
|
13843
|
+
});
|
|
13844
|
+
return invalid;
|
|
13845
|
+
}, [groups, values]);
|
|
13846
|
+
const isGroupsValid = useCallback(
|
|
13847
|
+
(current) => groups.every((group) => isGroupSatisfied(group, current)),
|
|
13848
|
+
[groups]
|
|
13849
|
+
);
|
|
13850
|
+
const runSearch = useCallback(
|
|
13851
|
+
(next) => {
|
|
13852
|
+
if (valuesMapEqual(lastSearchedValuesRef.current, next)) return;
|
|
13853
|
+
if (!isGroupsValid(next)) return;
|
|
13854
|
+
lastSearchedValuesRef.current = next;
|
|
13855
|
+
onSearch?.(next);
|
|
13856
|
+
},
|
|
13857
|
+
[isGroupsValid, onSearch]
|
|
13858
|
+
);
|
|
13859
|
+
useEffect(() => {
|
|
13860
|
+
const prevKey = prevOpenKeyRef.current;
|
|
13861
|
+
if (prevKey != null && prevKey !== openKey) {
|
|
13862
|
+
runSearch(valuesRef.current);
|
|
13548
13863
|
}
|
|
13864
|
+
prevOpenKeyRef.current = openKey;
|
|
13865
|
+
}, [openKey, runSearch]);
|
|
13866
|
+
useEffect(() => {
|
|
13867
|
+
if (activeKeys) return;
|
|
13868
|
+
setInternalActiveKeys((current) => {
|
|
13869
|
+
const known = new Set(fields.map((field) => field.key));
|
|
13870
|
+
const kept = current.filter((key) => known.has(key));
|
|
13871
|
+
const additions = fields.filter((field) => field.defaultActive !== false && !kept.includes(field.key)).map((field) => field.key);
|
|
13872
|
+
return [...kept, ...additions];
|
|
13873
|
+
});
|
|
13874
|
+
}, [activeKeys, fields]);
|
|
13875
|
+
useEffect(() => {
|
|
13876
|
+
const patch = {};
|
|
13877
|
+
let changed = false;
|
|
13878
|
+
fields.forEach((field) => {
|
|
13879
|
+
if (initializedDefaultsRef.current.has(field.key)) return;
|
|
13880
|
+
if (!isEmptyValue(values[field.key])) {
|
|
13881
|
+
initializedDefaultsRef.current.add(field.key);
|
|
13882
|
+
return;
|
|
13883
|
+
}
|
|
13884
|
+
const def = resolveFieldDefault(field);
|
|
13885
|
+
if (def === void 0) return;
|
|
13886
|
+
patch[field.key] = def;
|
|
13887
|
+
initializedDefaultsRef.current.add(field.key);
|
|
13888
|
+
changed = true;
|
|
13889
|
+
});
|
|
13890
|
+
if (changed) onValueChange?.({ ...values, ...patch });
|
|
13891
|
+
}, [fields, values, onValueChange]);
|
|
13892
|
+
const resolvedActiveKeys = activeKeys ?? internalActiveKeys;
|
|
13893
|
+
const activeFields = fields.filter((field) => resolvedActiveKeys.includes(field.key));
|
|
13894
|
+
const inactiveFields = fields.filter((field) => !resolvedActiveKeys.includes(field.key));
|
|
13895
|
+
const groupIndexByKey = /* @__PURE__ */ new Map();
|
|
13896
|
+
groups.forEach((group, groupIndex) => {
|
|
13897
|
+
group.fields.forEach((field) => groupIndexByKey.set(field.key, groupIndex));
|
|
13549
13898
|
});
|
|
13550
|
-
const
|
|
13551
|
-
const
|
|
13552
|
-
const
|
|
13553
|
-
const
|
|
13554
|
-
if (
|
|
13555
|
-
|
|
13556
|
-
|
|
13557
|
-
|
|
13558
|
-
|
|
13559
|
-
|
|
13560
|
-
|
|
13561
|
-
|
|
13562
|
-
|
|
13563
|
-
|
|
13564
|
-
|
|
13899
|
+
const hasValue = fields.some((field) => !isEmptyValue(values[field.key]));
|
|
13900
|
+
const hasRightActions = showAddButton || showReset;
|
|
13901
|
+
const currentOpenField = fields.find((field) => field.key === openKey);
|
|
13902
|
+
const editorPopoverStyle = useMemo(() => {
|
|
13903
|
+
if (currentOpenField?.type === "keyword") {
|
|
13904
|
+
return { width: CHIPFILTER_LISTBOX_WIDTH };
|
|
13905
|
+
}
|
|
13906
|
+
if (currentOpenField?.type === "date" && (currentOpenField.presets?.length ?? 0) > 0) {
|
|
13907
|
+
return { width: CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH };
|
|
13908
|
+
}
|
|
13909
|
+
return { width: CHIPFILTER_LISTBOX_WIDTH };
|
|
13910
|
+
}, [currentOpenField?.type, currentOpenField?.presets?.length]);
|
|
13911
|
+
const setActive = (next) => {
|
|
13912
|
+
if (!activeKeys) setInternalActiveKeys(next);
|
|
13913
|
+
onActiveKeysChange?.(next);
|
|
13914
|
+
};
|
|
13915
|
+
const emitValue = (key, nextValue) => {
|
|
13916
|
+
const next = { ...values, [key]: nextValue };
|
|
13917
|
+
onValueChange?.(next);
|
|
13918
|
+
onFilterChange?.({ key, value: nextValue, values: next });
|
|
13919
|
+
return next;
|
|
13920
|
+
};
|
|
13921
|
+
const emitValueAndSearch = (key, nextValue) => {
|
|
13922
|
+
runSearch(emitValue(key, nextValue));
|
|
13923
|
+
};
|
|
13924
|
+
const clearValue = (key) => {
|
|
13925
|
+
const field = fields.find((f) => f.key === key);
|
|
13926
|
+
const def = field ? resolveFieldDefault(field) : void 0;
|
|
13927
|
+
runSearch(emitValue(key, def !== void 0 ? def : null));
|
|
13928
|
+
};
|
|
13929
|
+
const reset = useCallback(() => {
|
|
13930
|
+
const next = fields.reduce((acc, field) => {
|
|
13931
|
+
const def = resolveFieldDefault(field);
|
|
13932
|
+
acc[field.key] = def !== void 0 ? def : null;
|
|
13933
|
+
return acc;
|
|
13934
|
+
}, {});
|
|
13935
|
+
onValueChange?.(next);
|
|
13936
|
+
runSearch(next);
|
|
13937
|
+
onReset?.();
|
|
13938
|
+
}, [fields, onReset, onValueChange, runSearch]);
|
|
13939
|
+
const open = useCallback(
|
|
13940
|
+
(key) => {
|
|
13941
|
+
const field = fields.find((f) => f.key === key);
|
|
13942
|
+
if (!field || isInlineField(field)) return;
|
|
13943
|
+
setOpenKey(key);
|
|
13944
|
+
},
|
|
13945
|
+
[fields]
|
|
13946
|
+
);
|
|
13947
|
+
const validate = useCallback(() => invalidGroups.size === 0, [invalidGroups]);
|
|
13948
|
+
useImperativeHandle(ref, () => ({ open, reset, validate }), [open, reset, validate]);
|
|
13949
|
+
const addField = (key) => {
|
|
13950
|
+
const next = [...resolvedActiveKeys, key];
|
|
13951
|
+
setActive(next);
|
|
13952
|
+
onAddFilter?.(key);
|
|
13953
|
+
setAddOpen(false);
|
|
13954
|
+
const field = fields.find((f) => f.key === key);
|
|
13955
|
+
if (field && !isInlineField(field)) requestAnimationFrame(() => setOpenKey(key));
|
|
13956
|
+
};
|
|
13957
|
+
const rootStyle = useMemo(
|
|
13958
|
+
() => ({
|
|
13959
|
+
"--chipfilter-bar-bg": CHIPFILTER.barBg,
|
|
13960
|
+
"--chipfilter-bar-border": CHIPFILTER.barBorder,
|
|
13961
|
+
"--chipfilter-bar-padding-x": CHIPFILTER.barPaddingX,
|
|
13962
|
+
"--chipfilter-bar-padding-y": CHIPFILTER.barPaddingY,
|
|
13963
|
+
"--chipfilter-bar-gap": CHIPFILTER.barGap,
|
|
13964
|
+
"--chipfilter-divider-height": CHIPFILTER.dividerHeight,
|
|
13965
|
+
...style
|
|
13966
|
+
}),
|
|
13967
|
+
[style]
|
|
13968
|
+
);
|
|
13969
|
+
return /* @__PURE__ */ jsxs(
|
|
13970
|
+
"div",
|
|
13971
|
+
{
|
|
13972
|
+
className: cn(
|
|
13973
|
+
"flex w-full items-start gap-[var(--chipfilter-bar-gap)] border-b border-solid bg-[var(--chipfilter-bar-bg)] px-[var(--chipfilter-bar-padding-x)] py-[var(--chipfilter-bar-padding-y)]",
|
|
13974
|
+
className
|
|
13975
|
+
),
|
|
13976
|
+
style: { ...rootStyle, borderColor: "var(--chipfilter-bar-border)" },
|
|
13977
|
+
children: [
|
|
13978
|
+
showLabel && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
13979
|
+
/* @__PURE__ */ jsx(STag, { className: "shrink-0", shape: "square", size: "sm", color: "darkblue", label }),
|
|
13980
|
+
/* @__PURE__ */ jsx(Divider, { top: true })
|
|
13981
|
+
] }),
|
|
13982
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-[var(--cmp-chipFilter-chip-group)]", children: [
|
|
13983
|
+
(() => {
|
|
13984
|
+
const nodes = [];
|
|
13985
|
+
let runBuffer = [];
|
|
13986
|
+
let runGroupIndex = null;
|
|
13987
|
+
const flushRun = () => {
|
|
13988
|
+
if (runBuffer.length === 0) return;
|
|
13989
|
+
const group = runGroupIndex != null ? groups[runGroupIndex] : void 0;
|
|
13990
|
+
const message = usingGroupedFields && group?.rule ? group.tooltipMessage ?? defaultGroupTooltipMessage(group.rule, group.fields) : void 0;
|
|
13991
|
+
if (message) {
|
|
13992
|
+
nodes.push(
|
|
13993
|
+
/* @__PURE__ */ jsx(
|
|
13994
|
+
GroupTooltip,
|
|
13995
|
+
{
|
|
13996
|
+
message,
|
|
13997
|
+
open: invalidGroups.has(runGroupIndex),
|
|
13998
|
+
children: runBuffer
|
|
13999
|
+
},
|
|
14000
|
+
`group-${runGroupIndex}`
|
|
14001
|
+
)
|
|
14002
|
+
);
|
|
14003
|
+
} else {
|
|
14004
|
+
nodes.push(...runBuffer);
|
|
14005
|
+
}
|
|
14006
|
+
runBuffer = [];
|
|
14007
|
+
};
|
|
14008
|
+
activeFields.forEach((field, index) => {
|
|
14009
|
+
const inline = isInlineField(field);
|
|
14010
|
+
const groupIndex = groupIndexByKey.get(field.key) ?? 0;
|
|
14011
|
+
const warning = field.warning || invalidGroups.has(groupIndex);
|
|
14012
|
+
const prevField = index > 0 ? activeFields[index - 1] : null;
|
|
14013
|
+
const prevGroupIndex = prevField ? groupIndexByKey.get(prevField.key) ?? 0 : null;
|
|
14014
|
+
const needsLeadingDivider = index === 0 ? false : inline || prevField != null && isInlineField(prevField) || groupIndex !== prevGroupIndex;
|
|
14015
|
+
if (groupIndex !== runGroupIndex) {
|
|
14016
|
+
flushRun();
|
|
14017
|
+
runGroupIndex = groupIndex;
|
|
14018
|
+
}
|
|
14019
|
+
const showClear = !isAtDefaultValue(field, values[field.key]);
|
|
14020
|
+
const node = isInlineDateField(field) ? /* @__PURE__ */ jsx(
|
|
14021
|
+
InlineDatePresetFilter,
|
|
14022
|
+
{
|
|
14023
|
+
field,
|
|
14024
|
+
value: values[field.key],
|
|
14025
|
+
disabled: disabled || field.disabled,
|
|
14026
|
+
warning,
|
|
14027
|
+
showClear,
|
|
14028
|
+
onValueChange: (next) => emitValueAndSearch(field.key, next),
|
|
14029
|
+
onClear: () => clearValue(field.key)
|
|
14030
|
+
},
|
|
14031
|
+
field.key
|
|
14032
|
+
) : field.type === "custom" ? /* @__PURE__ */ jsx(Fragment$1, { children: field.render?.({
|
|
14033
|
+
value: values[field.key],
|
|
14034
|
+
disabled: disabled || field.disabled,
|
|
14035
|
+
warning,
|
|
14036
|
+
onValueChange: (next) => emitValueAndSearch(field.key, next)
|
|
14037
|
+
}) }, field.key) : /* @__PURE__ */ jsx(
|
|
14038
|
+
FilterChip,
|
|
14039
|
+
{
|
|
14040
|
+
field,
|
|
14041
|
+
valueText: chipDisplayValue(field, values[field.key]),
|
|
14042
|
+
active: openKey === field.key,
|
|
14043
|
+
applied: !isEmptyValue(values[field.key]),
|
|
14044
|
+
disabled: disabled || field.disabled,
|
|
14045
|
+
warning,
|
|
14046
|
+
showClear,
|
|
14047
|
+
refCallback: (node2) => triggerRefs.current.set(field.key, node2),
|
|
14048
|
+
onOpen: () => setOpenKey(openKey === field.key ? null : field.key),
|
|
14049
|
+
onClear: () => clearValue(field.key)
|
|
14050
|
+
},
|
|
14051
|
+
field.key
|
|
14052
|
+
);
|
|
14053
|
+
runBuffer.push(
|
|
14054
|
+
needsLeadingDivider ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
14055
|
+
/* @__PURE__ */ jsx(Divider, { inset: true }),
|
|
14056
|
+
node
|
|
14057
|
+
] }, `${field.key}-wrap`) : node
|
|
14058
|
+
);
|
|
14059
|
+
});
|
|
14060
|
+
flushRun();
|
|
14061
|
+
return nodes;
|
|
14062
|
+
})(),
|
|
14063
|
+
(() => {
|
|
14064
|
+
const lastField = activeFields[activeFields.length - 1];
|
|
14065
|
+
const needsTrailingDivider = lastField != null && isInlineField(lastField) && !hasRightActions;
|
|
14066
|
+
return needsTrailingDivider ? /* @__PURE__ */ jsx(Divider, { inset: true }) : null;
|
|
14067
|
+
})(),
|
|
14068
|
+
hasRightActions && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14069
|
+
/* @__PURE__ */ jsx(Divider, { inset: true }),
|
|
14070
|
+
showAddButton && /* @__PURE__ */ jsxs(RPopover9.Root, { open: addOpen, onOpenChange: setAddOpen, children: [
|
|
14071
|
+
/* @__PURE__ */ jsx(RPopover9.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
14072
|
+
"button",
|
|
14073
|
+
{
|
|
14074
|
+
type: "button",
|
|
14075
|
+
disabled: disabled || inactiveFields.length === 0,
|
|
14076
|
+
className: "inline-flex shrink-0 cursor-pointer items-center justify-center gap-[var(--cmp-chipFilter-addButton-gap)] whitespace-nowrap border border-solid bg-[var(--cmp-chipFilter-addButton-bg)] px-[var(--cmp-chipFilter-addButton-paddingX)] text-[12px] font-medium leading-[20px] outline-none disabled:cursor-not-allowed",
|
|
14077
|
+
style: {
|
|
14078
|
+
minHeight: "var(--cmp-chipFilter-addButton-height)" ,
|
|
14079
|
+
borderRadius: "var(--cmp-chipFilter-addButton-radius)" ,
|
|
14080
|
+
borderColor: disabled || inactiveFields.length === 0 ? CHIPFILTER.addBorderDisabled : CHIPFILTER.addBorder,
|
|
14081
|
+
color: disabled || inactiveFields.length === 0 ? CHIPFILTER.addTextDisabled : CHIPFILTER.addText
|
|
14082
|
+
},
|
|
14083
|
+
children: [
|
|
14084
|
+
/* @__PURE__ */ jsx(
|
|
14085
|
+
SIcon,
|
|
14086
|
+
{
|
|
14087
|
+
name: "add",
|
|
14088
|
+
size: 12,
|
|
14089
|
+
color: disabled || inactiveFields.length === 0 ? CHIPFILTER.addTextDisabled : CHIPFILTER.addText
|
|
14090
|
+
}
|
|
14091
|
+
),
|
|
14092
|
+
/* @__PURE__ */ jsx("span", { children: "\uD544\uD130 \uCD94\uAC00" })
|
|
14093
|
+
]
|
|
14094
|
+
}
|
|
14095
|
+
) }),
|
|
14096
|
+
/* @__PURE__ */ jsx(RPopover9.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
14097
|
+
RPopover9.Content,
|
|
14098
|
+
{
|
|
14099
|
+
side: "bottom",
|
|
14100
|
+
align: "start",
|
|
14101
|
+
sideOffset: 4,
|
|
14102
|
+
className: cn("z-50 min-w-[180px]", FLOATING_SLIDE_ANIM),
|
|
14103
|
+
children: /* @__PURE__ */ jsx(ListBox, { children: inactiveFields.length > 0 ? inactiveFields.map((field) => /* @__PURE__ */ jsx(MenuItem, { onClick: () => addField(field.key), children: field.label }, field.key)) : /* @__PURE__ */ jsx(EmptyItem, { children: "\uCD94\uAC00\uD560 \uD544\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4." }) })
|
|
14104
|
+
}
|
|
14105
|
+
) })
|
|
14106
|
+
] }),
|
|
14107
|
+
showReset && /* @__PURE__ */ jsxs(
|
|
14108
|
+
"button",
|
|
14109
|
+
{
|
|
14110
|
+
type: "button",
|
|
14111
|
+
disabled: disabled || !hasValue,
|
|
14112
|
+
onClick: reset,
|
|
14113
|
+
className: cn(
|
|
14114
|
+
"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",
|
|
14115
|
+
// 부모 flex gap(6px)은 칩 사이 간격 기준이라, 필터 추가 버튼과의 12px 간격을 맞추려면
|
|
14116
|
+
// 부족한 만큼(12px - gap)을 추가로 띄운다. 필터 추가가 없을 땐 divider와 이미 12px이라 불필요.
|
|
14117
|
+
showAddButton && "ml-[calc(12px-var(--cmp-chipFilter-chip-group))]"
|
|
14118
|
+
),
|
|
14119
|
+
style: {
|
|
14120
|
+
color: disabled || !hasValue ? "var(--cmp-textLink-content-disabled)" : "var(--cmp-textLink-content-default)"
|
|
14121
|
+
},
|
|
14122
|
+
children: [
|
|
14123
|
+
/* @__PURE__ */ jsx(
|
|
14124
|
+
SIcon,
|
|
14125
|
+
{
|
|
14126
|
+
name: "reset",
|
|
14127
|
+
size: 16,
|
|
14128
|
+
color: disabled || !hasValue ? "var(--cmp-textLink-icon-disabled)" : "var(--cmp-textLink-icon-default)"
|
|
14129
|
+
}
|
|
14130
|
+
),
|
|
14131
|
+
/* @__PURE__ */ jsx("span", { children: "\uAC80\uC0C9 \uCD08\uAE30\uD654" })
|
|
14132
|
+
]
|
|
14133
|
+
}
|
|
14134
|
+
)
|
|
14135
|
+
] })
|
|
14136
|
+
] }),
|
|
14137
|
+
/* @__PURE__ */ jsxs(RPopover9.Root, { open: openKey != null, onOpenChange: (next) => !next && setOpenKey(null), children: [
|
|
14138
|
+
/* @__PURE__ */ jsx(
|
|
14139
|
+
RPopover9.Anchor,
|
|
14140
|
+
{
|
|
14141
|
+
virtualRef: {
|
|
14142
|
+
current: openKey ? triggerRefs.current.get(openKey) : null
|
|
14143
|
+
}
|
|
14144
|
+
}
|
|
14145
|
+
),
|
|
14146
|
+
/* @__PURE__ */ jsx(RPopover9.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
14147
|
+
RPopover9.Content,
|
|
14148
|
+
{
|
|
14149
|
+
side: "bottom",
|
|
14150
|
+
align: "start",
|
|
14151
|
+
sideOffset: 4,
|
|
14152
|
+
onOpenAutoFocus: (event) => event.preventDefault(),
|
|
14153
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
14154
|
+
style: editorPopoverStyle,
|
|
14155
|
+
children: currentOpenField && /* @__PURE__ */ jsx(
|
|
14156
|
+
EditorPanel,
|
|
14157
|
+
{
|
|
14158
|
+
field: currentOpenField,
|
|
14159
|
+
value: values[currentOpenField.key],
|
|
14160
|
+
disabled: disabled || currentOpenField.disabled,
|
|
14161
|
+
onValueChange: (next) => emitValue(currentOpenField.key, next),
|
|
14162
|
+
onClose: () => setOpenKey(null)
|
|
14163
|
+
}
|
|
14164
|
+
)
|
|
14165
|
+
}
|
|
14166
|
+
) })
|
|
14167
|
+
] })
|
|
14168
|
+
]
|
|
14169
|
+
}
|
|
14170
|
+
);
|
|
14171
|
+
});
|
|
14172
|
+
function Divider({ inset, top } = {}) {
|
|
14173
|
+
return /* @__PURE__ */ jsx(
|
|
14174
|
+
"span",
|
|
14175
|
+
{
|
|
14176
|
+
"aria-hidden": true,
|
|
14177
|
+
className: cn(
|
|
14178
|
+
"inline-flex w-px shrink-0 bg-[var(--chipfilter-bar-border)]",
|
|
14179
|
+
top ? "mt-[2px] self-start" : "my-auto",
|
|
14180
|
+
inset && "mx-[calc(12px-var(--cmp-chipFilter-chip-group))]"
|
|
14181
|
+
),
|
|
14182
|
+
style: { height: "var(--chipfilter-divider-height)" }
|
|
14183
|
+
}
|
|
14184
|
+
);
|
|
14185
|
+
}
|
|
14186
|
+
function GroupTooltip({
|
|
14187
|
+
message,
|
|
14188
|
+
open,
|
|
14189
|
+
children
|
|
14190
|
+
}) {
|
|
14191
|
+
return /* @__PURE__ */ jsx(STooltip2, { trigger: "none", open, placement: "top", tooltipType: "warning", message: [message], children: /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-[var(--cmp-chipFilter-chip-group)]", children }) });
|
|
14192
|
+
}
|
|
14193
|
+
function FilterChip({
|
|
14194
|
+
field,
|
|
14195
|
+
valueText,
|
|
14196
|
+
active,
|
|
14197
|
+
applied,
|
|
14198
|
+
disabled,
|
|
14199
|
+
warning,
|
|
14200
|
+
showClear,
|
|
14201
|
+
refCallback,
|
|
14202
|
+
onOpen,
|
|
14203
|
+
onClear
|
|
14204
|
+
}) {
|
|
14205
|
+
const border = disabled ? CHIPFILTER.chipDisabledBorder : warning ? CHIPFILTER.chipWarningBorder : applied ? active ? "var(--color-blue-strong)" : CHIPFILTER.chipAppliedBorder : active ? CHIPFILTER.chipActiveBorder : CHIPFILTER.chipDefaultBorder;
|
|
14206
|
+
const background = disabled ? CHIPFILTER.chipDisabledBg : applied ? CHIPFILTER.chipAppliedBg : CHIPFILTER.chipDefaultBg;
|
|
14207
|
+
const textColor = disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipDefaultText;
|
|
14208
|
+
return /* @__PURE__ */ jsxs(
|
|
14209
|
+
"button",
|
|
14210
|
+
{
|
|
14211
|
+
ref: refCallback,
|
|
14212
|
+
type: "button",
|
|
14213
|
+
disabled,
|
|
14214
|
+
"aria-expanded": active,
|
|
14215
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
14216
|
+
onClick: onOpen,
|
|
14217
|
+
className: "group/chip-filter inline-flex max-w-full shrink-0 cursor-pointer items-center justify-center whitespace-nowrap border border-solid px-[var(--cmp-chipFilter-chip-paddingX)] text-[12px] leading-[20px] outline-none disabled:cursor-not-allowed",
|
|
14218
|
+
style: {
|
|
14219
|
+
minHeight: CHIPFILTER.chipHeight,
|
|
14220
|
+
gap: CHIPFILTER.chipGap,
|
|
14221
|
+
borderRadius: CHIPFILTER.chipRadius,
|
|
14222
|
+
borderColor: border,
|
|
14223
|
+
background,
|
|
14224
|
+
color: textColor
|
|
14225
|
+
},
|
|
14226
|
+
children: [
|
|
14227
|
+
field.required && /* @__PURE__ */ jsx(
|
|
14228
|
+
SIcon,
|
|
14229
|
+
{
|
|
14230
|
+
name: "asterisk",
|
|
14231
|
+
size: 12,
|
|
14232
|
+
color: disabled ? CHIPFILTER.chipDisabledText : "var(--cmp-tag-darkblue-content)"
|
|
14233
|
+
}
|
|
14234
|
+
),
|
|
14235
|
+
applied ? /* @__PURE__ */ jsxs("span", { className: "inline-flex min-w-0 items-center gap-[4px] truncate", children: [
|
|
14236
|
+
/* @__PURE__ */ jsx(
|
|
14237
|
+
"span",
|
|
14238
|
+
{
|
|
14239
|
+
className: "font-bold",
|
|
14240
|
+
style: { color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedLabel },
|
|
14241
|
+
children: field.label
|
|
14242
|
+
}
|
|
14243
|
+
),
|
|
14244
|
+
/* @__PURE__ */ jsx(
|
|
14245
|
+
"span",
|
|
14246
|
+
{
|
|
14247
|
+
style: { color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedLabel },
|
|
14248
|
+
children: ":"
|
|
14249
|
+
}
|
|
14250
|
+
),
|
|
14251
|
+
/* @__PURE__ */ jsx(
|
|
14252
|
+
"span",
|
|
14253
|
+
{
|
|
14254
|
+
className: "min-w-0 truncate font-bold",
|
|
14255
|
+
style: { color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipAppliedValue },
|
|
14256
|
+
children: valueText
|
|
14257
|
+
}
|
|
14258
|
+
)
|
|
14259
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14260
|
+
/* @__PURE__ */ jsx("span", { className: cn("min-w-0 truncate", active && "font-bold"), children: field.label }),
|
|
14261
|
+
/* @__PURE__ */ jsx(
|
|
14262
|
+
SIcon,
|
|
14263
|
+
{
|
|
14264
|
+
name: "caretDown",
|
|
14265
|
+
size: 12,
|
|
14266
|
+
color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.chipDefaultText
|
|
14267
|
+
}
|
|
14268
|
+
)
|
|
14269
|
+
] }),
|
|
14270
|
+
applied && !disabled && showClear && /* @__PURE__ */ jsx(
|
|
14271
|
+
"span",
|
|
14272
|
+
{
|
|
14273
|
+
role: "button",
|
|
14274
|
+
tabIndex: 0,
|
|
14275
|
+
"aria-label": `${field.label} \uD544\uD130 \uC9C0\uC6B0\uAE30`,
|
|
14276
|
+
className: "inline-flex size-[16px] items-center justify-center rounded-[var(--cmp-ghostButton-radius-sm)]",
|
|
14277
|
+
onClick: (event) => {
|
|
14278
|
+
event.preventDefault();
|
|
14279
|
+
event.stopPropagation();
|
|
14280
|
+
onClear();
|
|
14281
|
+
},
|
|
14282
|
+
onKeyDown: (event) => {
|
|
14283
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
14284
|
+
event.preventDefault();
|
|
14285
|
+
event.stopPropagation();
|
|
14286
|
+
onClear();
|
|
14287
|
+
},
|
|
14288
|
+
children: /* @__PURE__ */ jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
14289
|
+
}
|
|
14290
|
+
)
|
|
14291
|
+
]
|
|
14292
|
+
}
|
|
14293
|
+
);
|
|
14294
|
+
}
|
|
14295
|
+
function EditorPanel({
|
|
14296
|
+
field,
|
|
14297
|
+
value,
|
|
14298
|
+
disabled,
|
|
14299
|
+
onValueChange,
|
|
14300
|
+
onClose
|
|
14301
|
+
}) {
|
|
14302
|
+
const wrapsInPaddedTop = field.type === "date";
|
|
14303
|
+
const isMulti = field.type === "multi";
|
|
14304
|
+
const selectableValues = isMulti ? (field.options ?? []).filter((option) => !option.disabled).map((option) => option.value) : [];
|
|
14305
|
+
const selectedValues = isMulti ? toArrayValue(value) : [];
|
|
14306
|
+
const allSelected = isMulti && selectableValues.length > 0 && selectableValues.every((v) => selectedValues.includes(v));
|
|
14307
|
+
const toggleSelectAll = () => {
|
|
14308
|
+
onValueChange(
|
|
14309
|
+
allSelected ? selectedValues.filter((v) => !selectableValues.includes(v)) : [...selectedValues, ...selectableValues.filter((v) => !selectedValues.includes(v))]
|
|
14310
|
+
);
|
|
14311
|
+
};
|
|
14312
|
+
return /* @__PURE__ */ jsxs(ListBox, { children: [
|
|
14313
|
+
wrapsInPaddedTop ? /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)] px-[var(--cmp-chipFilter-listbox-top-paddingX)] py-[var(--cmp-chipFilter-listbox-top-paddingY)]", children: /* @__PURE__ */ jsx(
|
|
14314
|
+
FilterEditor,
|
|
14315
|
+
{
|
|
14316
|
+
field,
|
|
14317
|
+
value,
|
|
14318
|
+
disabled,
|
|
14319
|
+
onValueChange
|
|
14320
|
+
}
|
|
14321
|
+
) }) : /* @__PURE__ */ jsx(
|
|
14322
|
+
FilterEditor,
|
|
14323
|
+
{
|
|
14324
|
+
field,
|
|
14325
|
+
value,
|
|
14326
|
+
disabled,
|
|
14327
|
+
onValueChange
|
|
14328
|
+
}
|
|
14329
|
+
),
|
|
14330
|
+
/* @__PURE__ */ jsxs(
|
|
14331
|
+
"div",
|
|
14332
|
+
{
|
|
14333
|
+
className: "flex items-center justify-end gap-[var(--cmp-chipFilter-listbox-bottom-gap)] border-t border-solid px-[var(--cmp-chipFilter-listbox-bottom-paddingX)] py-[var(--cmp-chipFilter-listbox-bottom-paddingY)]",
|
|
14334
|
+
style: { borderColor: CHIPFILTER.listboxBorder },
|
|
14335
|
+
children: [
|
|
14336
|
+
isMulti && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14337
|
+
/* @__PURE__ */ jsx(
|
|
14338
|
+
STextLink,
|
|
14339
|
+
{
|
|
14340
|
+
size: "sm",
|
|
14341
|
+
label: allSelected ? "\uC120\uD0DD \uD574\uC81C" : "\uC804\uCCB4 \uC120\uD0DD",
|
|
14342
|
+
labelClass: "font-bold",
|
|
14343
|
+
disabled,
|
|
14344
|
+
onClick: toggleSelectAll,
|
|
14345
|
+
style: { color: "var(--sys-color-fg-secondary)" }
|
|
14346
|
+
}
|
|
14347
|
+
),
|
|
14348
|
+
/* @__PURE__ */ jsx(
|
|
14349
|
+
"span",
|
|
14350
|
+
{
|
|
14351
|
+
"aria-hidden": true,
|
|
14352
|
+
className: "inline-flex w-px shrink-0",
|
|
14353
|
+
style: {
|
|
14354
|
+
height: CHIPFILTER.listboxBottomDividerHeight,
|
|
14355
|
+
background: CHIPFILTER.listboxBorder
|
|
14356
|
+
}
|
|
14357
|
+
}
|
|
14358
|
+
)
|
|
14359
|
+
] }),
|
|
14360
|
+
/* @__PURE__ */ jsx(
|
|
14361
|
+
STextLink,
|
|
14362
|
+
{
|
|
14363
|
+
size: "sm",
|
|
14364
|
+
label: "\uAC80\uC0C9",
|
|
14365
|
+
labelClass: "font-bold",
|
|
14366
|
+
onClick: onClose,
|
|
14367
|
+
style: { color: CHIPFILTER.chipAppliedValue }
|
|
14368
|
+
}
|
|
14369
|
+
)
|
|
14370
|
+
]
|
|
14371
|
+
}
|
|
14372
|
+
)
|
|
14373
|
+
] });
|
|
14374
|
+
}
|
|
14375
|
+
function FilterEditor({
|
|
14376
|
+
field,
|
|
14377
|
+
value,
|
|
14378
|
+
disabled,
|
|
14379
|
+
onValueChange
|
|
14380
|
+
}) {
|
|
14381
|
+
if (field.type === "date") {
|
|
14382
|
+
return /* @__PURE__ */ jsx(
|
|
14383
|
+
DatePresetEditor,
|
|
14384
|
+
{
|
|
14385
|
+
field,
|
|
14386
|
+
value,
|
|
14387
|
+
disabled,
|
|
14388
|
+
onValueChange
|
|
14389
|
+
}
|
|
14390
|
+
);
|
|
14391
|
+
}
|
|
14392
|
+
if (field.type === "keyword") {
|
|
14393
|
+
return /* @__PURE__ */ jsx(
|
|
14394
|
+
KeywordEditor,
|
|
14395
|
+
{
|
|
14396
|
+
field,
|
|
14397
|
+
value: isKeywordValue(value) ? value : keywordEntries(value),
|
|
14398
|
+
disabled,
|
|
14399
|
+
onValueChange
|
|
14400
|
+
}
|
|
14401
|
+
);
|
|
14402
|
+
}
|
|
14403
|
+
return /* @__PURE__ */ jsx(
|
|
14404
|
+
OptionList,
|
|
14405
|
+
{
|
|
14406
|
+
field,
|
|
14407
|
+
value: field.type === "multi" ? toArrayValue(value) : value,
|
|
14408
|
+
multiple: field.type === "multi",
|
|
14409
|
+
disabled,
|
|
14410
|
+
onValueChange
|
|
14411
|
+
}
|
|
14412
|
+
);
|
|
14413
|
+
}
|
|
14414
|
+
function DatePresetEditor({
|
|
14415
|
+
field,
|
|
14416
|
+
value,
|
|
14417
|
+
disabled,
|
|
14418
|
+
onValueChange
|
|
14419
|
+
}) {
|
|
14420
|
+
const presets = field.presets ?? [];
|
|
14421
|
+
const [selectedId, setSelectedId] = useState(() => matchPresetId(presets, value));
|
|
14422
|
+
const syncedInitialValueRef = useRef(!isEmptyValue(value));
|
|
14423
|
+
useEffect(() => {
|
|
14424
|
+
if (syncedInitialValueRef.current || isEmptyValue(value)) return;
|
|
14425
|
+
syncedInitialValueRef.current = true;
|
|
14426
|
+
setSelectedId(matchPresetId(presets, value));
|
|
14427
|
+
}, [value, presets]);
|
|
14428
|
+
const selectedPreset = presets.find((preset) => preset.value === selectedId);
|
|
14429
|
+
const selectPreset = (preset) => {
|
|
14430
|
+
setSelectedId(preset.value);
|
|
14431
|
+
if (!preset.custom) onValueChange(preset.resolve ? preset.resolve() : null);
|
|
14432
|
+
};
|
|
14433
|
+
if (presets.length === 0) {
|
|
14434
|
+
return /* @__PURE__ */ jsx(
|
|
14435
|
+
SDatePicker,
|
|
14436
|
+
{
|
|
14437
|
+
value: typeof value === "string" ? value : null,
|
|
14438
|
+
onValueChange,
|
|
14439
|
+
selectable: field.selectable,
|
|
14440
|
+
disabled,
|
|
14441
|
+
placeholder: field.placeholder
|
|
14442
|
+
}
|
|
14443
|
+
);
|
|
14444
|
+
}
|
|
14445
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)]", children: [
|
|
14446
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-[8px]", children: presets.map((preset) => /* @__PURE__ */ jsx(
|
|
14447
|
+
SRadio,
|
|
14448
|
+
{
|
|
14449
|
+
val: preset.value,
|
|
14450
|
+
value: selectedId,
|
|
14451
|
+
label: preset.label,
|
|
14452
|
+
disabled,
|
|
14453
|
+
onValueChange: () => selectPreset(preset)
|
|
14454
|
+
},
|
|
14455
|
+
preset.value
|
|
14456
|
+
)) }),
|
|
14457
|
+
selectedPreset?.custom && /* @__PURE__ */ jsx(
|
|
14458
|
+
SDateRangePicker,
|
|
14459
|
+
{
|
|
14460
|
+
value: Array.isArray(value) && value.length === 2 ? value : null,
|
|
14461
|
+
onValueChange,
|
|
14462
|
+
selectable: field.selectable,
|
|
14463
|
+
maxRange: field.maxRange,
|
|
14464
|
+
disabled
|
|
14465
|
+
}
|
|
14466
|
+
)
|
|
14467
|
+
] });
|
|
14468
|
+
}
|
|
14469
|
+
function InlineDatePresetFilter({
|
|
14470
|
+
field,
|
|
14471
|
+
value,
|
|
14472
|
+
disabled,
|
|
14473
|
+
warning,
|
|
14474
|
+
showClear,
|
|
14475
|
+
onValueChange,
|
|
14476
|
+
onClear
|
|
14477
|
+
}) {
|
|
14478
|
+
const presets = (field.presets ?? []).filter((preset) => !preset.custom);
|
|
14479
|
+
const [selectedId, setSelectedId] = useState(() => matchPresetId(presets, value));
|
|
14480
|
+
const syncedInitialValueRef = useRef(!isEmptyValue(value));
|
|
14481
|
+
useEffect(() => {
|
|
14482
|
+
if (syncedInitialValueRef.current || isEmptyValue(value)) return;
|
|
14483
|
+
syncedInitialValueRef.current = true;
|
|
14484
|
+
setSelectedId(matchPresetId(presets, value));
|
|
14485
|
+
}, [value, presets]);
|
|
14486
|
+
const applied = !isEmptyValue(value);
|
|
14487
|
+
const rangeValue = Array.isArray(value) ? value : typeof value === "string" && value !== "" ? [value, value] : null;
|
|
14488
|
+
const [pickerOpen, setPickerOpen] = useState(false);
|
|
14489
|
+
const portalContainer = usePortalContainer();
|
|
14490
|
+
const selectPreset = (id) => {
|
|
14491
|
+
const preset = presets.find((p) => p.value === id);
|
|
14492
|
+
if (!preset) return;
|
|
14493
|
+
setSelectedId(preset.value);
|
|
14494
|
+
onValueChange(preset.resolve ? preset.resolve() : null);
|
|
14495
|
+
};
|
|
14496
|
+
const badge = applied && /* @__PURE__ */ jsxs(
|
|
14497
|
+
"span",
|
|
14498
|
+
{
|
|
14499
|
+
className: "inline-flex shrink-0 items-center gap-[4px] whitespace-nowrap border border-solid px-[var(--cmp-chipFilter-chip-paddingX)] text-[12px] leading-[20px]",
|
|
14500
|
+
style: {
|
|
14501
|
+
minHeight: CHIPFILTER.chipHeight,
|
|
14502
|
+
borderRadius: CHIPFILTER.chipRadius,
|
|
14503
|
+
borderColor: warning ? CHIPFILTER.chipWarningBorder : CHIPFILTER.chipAppliedBorder,
|
|
14504
|
+
background: CHIPFILTER.chipAppliedBg,
|
|
14505
|
+
color: CHIPFILTER.chipAppliedLabel,
|
|
14506
|
+
cursor: rangeValue ? "pointer" : void 0
|
|
14507
|
+
},
|
|
14508
|
+
children: [
|
|
14509
|
+
/* @__PURE__ */ jsxs("span", { className: "font-bold", children: [
|
|
14510
|
+
field.label,
|
|
14511
|
+
":"
|
|
14512
|
+
] }),
|
|
14513
|
+
/* @__PURE__ */ jsx("span", { className: "font-bold", style: { color: CHIPFILTER.chipAppliedValue }, children: displayValue(field, value) }),
|
|
14514
|
+
!disabled && showClear && /* @__PURE__ */ jsx(
|
|
14515
|
+
"span",
|
|
14516
|
+
{
|
|
14517
|
+
role: "button",
|
|
14518
|
+
tabIndex: 0,
|
|
14519
|
+
"aria-label": `${field.label} \uD544\uD130 \uC9C0\uC6B0\uAE30`,
|
|
14520
|
+
className: "inline-flex size-[16px] items-center justify-center rounded-[var(--cmp-ghostButton-radius-sm)]",
|
|
14521
|
+
onClick: (event) => {
|
|
14522
|
+
event.stopPropagation();
|
|
14523
|
+
onClear();
|
|
14524
|
+
},
|
|
14525
|
+
onKeyDown: (event) => {
|
|
14526
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
14527
|
+
event.preventDefault();
|
|
14528
|
+
event.stopPropagation();
|
|
14529
|
+
onClear();
|
|
14530
|
+
},
|
|
14531
|
+
children: /* @__PURE__ */ jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
14532
|
+
}
|
|
14533
|
+
)
|
|
14534
|
+
]
|
|
14535
|
+
}
|
|
14536
|
+
);
|
|
14537
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-[8px]", children: [
|
|
14538
|
+
/* @__PURE__ */ jsx(
|
|
14539
|
+
SRadioButton,
|
|
14540
|
+
{
|
|
14541
|
+
size: "xs",
|
|
14542
|
+
options: presets.map((preset) => ({ value: preset.value, label: preset.label })),
|
|
14543
|
+
value: selectedId,
|
|
14544
|
+
disabled,
|
|
14545
|
+
onValueChange: (next) => selectPreset(String(next))
|
|
14546
|
+
}
|
|
14547
|
+
),
|
|
14548
|
+
applied && (rangeValue ? (
|
|
14549
|
+
// 뱃지 모양은 그대로 두고, 눌렀을 때 캘린더가 열려 기간을 직접 다시 고를 수 있게 한다.
|
|
14550
|
+
// 직접 고르면 프리셋 선택은 해제된다.
|
|
14551
|
+
/* @__PURE__ */ jsxs(RPopover9.Root, { open: pickerOpen, onOpenChange: setPickerOpen, children: [
|
|
14552
|
+
/* @__PURE__ */ jsx(RPopover9.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
14553
|
+
"button",
|
|
14554
|
+
{
|
|
14555
|
+
type: "button",
|
|
14556
|
+
disabled,
|
|
14557
|
+
className: "border-none bg-transparent p-0 outline-none disabled:cursor-not-allowed",
|
|
14558
|
+
children: badge
|
|
14559
|
+
}
|
|
14560
|
+
) }),
|
|
14561
|
+
/* @__PURE__ */ jsx(RPopover9.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
14562
|
+
RPopover9.Content,
|
|
14563
|
+
{
|
|
14564
|
+
side: "bottom",
|
|
14565
|
+
align: "start",
|
|
14566
|
+
sideOffset: 4,
|
|
14567
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
14568
|
+
children: /* @__PURE__ */ jsx(
|
|
14569
|
+
RangeCalendar,
|
|
14570
|
+
{
|
|
14571
|
+
value: rangeValue,
|
|
14572
|
+
selectable: field.selectable,
|
|
14573
|
+
maxRange: field.maxRange,
|
|
14574
|
+
onSelect: (range) => {
|
|
14575
|
+
setSelectedId(null);
|
|
14576
|
+
onValueChange(range);
|
|
14577
|
+
setPickerOpen(false);
|
|
14578
|
+
}
|
|
14579
|
+
}
|
|
14580
|
+
)
|
|
14581
|
+
}
|
|
14582
|
+
) })
|
|
14583
|
+
] })
|
|
14584
|
+
) : badge)
|
|
14585
|
+
] });
|
|
14586
|
+
}
|
|
14587
|
+
var MATCH_MODE_OPTIONS = [
|
|
14588
|
+
{ value: "contains", label: "\uD3EC\uD568" },
|
|
14589
|
+
{ value: "exact", label: "\uC77C\uCE58" }
|
|
14590
|
+
];
|
|
14591
|
+
var EXCLUDE_MATCH_MODE_OPTION = {
|
|
14592
|
+
value: "excludes",
|
|
14593
|
+
label: "\uBBF8\uD3EC\uD568"
|
|
14594
|
+
};
|
|
14595
|
+
function KeywordEditor({
|
|
14596
|
+
field,
|
|
14597
|
+
value,
|
|
14598
|
+
disabled,
|
|
14599
|
+
onValueChange
|
|
14600
|
+
}) {
|
|
14601
|
+
const entries3 = keywordEntries(value);
|
|
14602
|
+
const [draft, setDraft] = useState("");
|
|
14603
|
+
const [mode, setMode] = useState(
|
|
14604
|
+
isKeywordValue(value) ? value.mode : "contains"
|
|
14605
|
+
);
|
|
14606
|
+
const emit3 = (nextEntries) => {
|
|
14607
|
+
onValueChange(field.matchModes ? { keywords: nextEntries, mode } : nextEntries);
|
|
14608
|
+
};
|
|
14609
|
+
const addEntry = (raw) => {
|
|
14610
|
+
const next = raw.trim();
|
|
14611
|
+
if (next === "" || entries3.includes(next)) return;
|
|
14612
|
+
emit3([...entries3, next]);
|
|
14613
|
+
setDraft("");
|
|
14614
|
+
};
|
|
14615
|
+
const removeEntry = (entry) => {
|
|
14616
|
+
emit3(entries3.filter((e) => e !== entry));
|
|
14617
|
+
};
|
|
14618
|
+
const onKeyDown = (event) => {
|
|
14619
|
+
if (event.key === "Enter") {
|
|
14620
|
+
if (event.nativeEvent.isComposing) return;
|
|
14621
|
+
event.preventDefault();
|
|
14622
|
+
addEntry(draft);
|
|
14623
|
+
}
|
|
14624
|
+
};
|
|
14625
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14626
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)] px-[var(--cmp-chipFilter-listbox-top-paddingX)] py-[var(--cmp-chipFilter-listbox-top-paddingY)]", children: [
|
|
14627
|
+
field.matchModes && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
14628
|
+
/* @__PURE__ */ jsx(
|
|
14629
|
+
"span",
|
|
14630
|
+
{
|
|
14631
|
+
className: "shrink-0 whitespace-nowrap text-[12px] font-medium leading-[20px]",
|
|
14632
|
+
style: { color: CHIPFILTER.listboxLabel },
|
|
14633
|
+
children: "\uAC80\uC0C9 \uC870\uAC74 :"
|
|
14634
|
+
}
|
|
14635
|
+
),
|
|
14636
|
+
/* @__PURE__ */ jsx(
|
|
14637
|
+
SRadioButton,
|
|
14638
|
+
{
|
|
14639
|
+
size: "xs",
|
|
14640
|
+
style: { width: 150 },
|
|
14641
|
+
options: field.excludeMode ? [...MATCH_MODE_OPTIONS, EXCLUDE_MATCH_MODE_OPTION] : MATCH_MODE_OPTIONS,
|
|
14642
|
+
value: mode,
|
|
14643
|
+
disabled,
|
|
14644
|
+
onValueChange: (next) => setMode(next)
|
|
14645
|
+
}
|
|
14646
|
+
)
|
|
14647
|
+
] }),
|
|
14648
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-[6px] rounded-[4px] border border-solid border-[color:var(--sys-color-field-border-default)] bg-[var(--sys-color-field-bg-default)] px-[8px] py-[4px] focus-within:border-[color:var(--sys-color-field-border-focus)]", children: [
|
|
14649
|
+
/* @__PURE__ */ jsx(SIcon, { name: "search", size: 16, color: "var(--sys-color-field-icon-default)" }),
|
|
14650
|
+
/* @__PURE__ */ jsx(
|
|
14651
|
+
"input",
|
|
14652
|
+
{
|
|
14653
|
+
value: draft,
|
|
14654
|
+
disabled,
|
|
14655
|
+
placeholder: field.placeholder ?? "\uC785\uB825 \uD6C4 Enter\uB85C \uCD94\uAC00",
|
|
14656
|
+
onChange: (event) => setDraft(event.target.value),
|
|
14657
|
+
onKeyDown,
|
|
14658
|
+
className: "min-w-0 flex-1 border-none bg-transparent text-[12px] leading-[20px] text-[color:var(--sys-color-field-text-default)] outline-none placeholder:text-[color:var(--sys-color-field-text-placeholder)] disabled:cursor-not-allowed"
|
|
14659
|
+
}
|
|
14660
|
+
)
|
|
14661
|
+
] })
|
|
14662
|
+
] }),
|
|
14663
|
+
entries3.length > 0 && /* @__PURE__ */ jsx(
|
|
14664
|
+
"div",
|
|
14665
|
+
{
|
|
14666
|
+
className: "max-h-[220px] overflow-auto border-t border-solid py-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
14667
|
+
style: { borderColor: CHIPFILTER.listboxBorder },
|
|
14668
|
+
children: entries3.map((entry) => /* @__PURE__ */ jsx(
|
|
14669
|
+
KeywordEntryRow,
|
|
14670
|
+
{
|
|
14671
|
+
label: optionLabel(field, entry),
|
|
14672
|
+
disabled,
|
|
14673
|
+
onRemove: () => removeEntry(entry)
|
|
14674
|
+
},
|
|
14675
|
+
entry
|
|
14676
|
+
))
|
|
14677
|
+
}
|
|
14678
|
+
)
|
|
14679
|
+
] });
|
|
14680
|
+
}
|
|
14681
|
+
function KeywordEntryRow({
|
|
14682
|
+
label,
|
|
14683
|
+
disabled,
|
|
14684
|
+
onRemove
|
|
14685
|
+
}) {
|
|
14686
|
+
return /* @__PURE__ */ jsxs(
|
|
14687
|
+
"div",
|
|
14688
|
+
{
|
|
14689
|
+
className: "group flex w-full items-center justify-between gap-[8px] text-[12px] leading-[20px]",
|
|
14690
|
+
style: {
|
|
14691
|
+
paddingTop: CHIPFILTER.itemPaddingY,
|
|
14692
|
+
paddingBottom: CHIPFILTER.itemPaddingY,
|
|
14693
|
+
paddingLeft: CHIPFILTER.itemPaddingLeft,
|
|
14694
|
+
paddingRight: CHIPFILTER.itemPaddingRight,
|
|
14695
|
+
color: disabled ? CHIPFILTER.chipDisabledText : CHIPFILTER.itemTextDefault
|
|
14696
|
+
},
|
|
14697
|
+
children: [
|
|
14698
|
+
/* @__PURE__ */ jsx("span", { className: cn("min-w-0 truncate", !disabled && "group-hover:font-bold"), children: label }),
|
|
14699
|
+
!disabled && /* @__PURE__ */ jsx(
|
|
14700
|
+
"button",
|
|
14701
|
+
{
|
|
14702
|
+
type: "button",
|
|
14703
|
+
"aria-label": `${label} \uC0AD\uC81C`,
|
|
14704
|
+
className: "invisible inline-flex size-[16px] shrink-0 cursor-pointer items-center justify-center group-hover:visible",
|
|
14705
|
+
onClick: onRemove,
|
|
14706
|
+
children: /* @__PURE__ */ jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
14707
|
+
}
|
|
14708
|
+
)
|
|
14709
|
+
]
|
|
14710
|
+
}
|
|
14711
|
+
);
|
|
14712
|
+
}
|
|
14713
|
+
var OPTION_SEARCH_THRESHOLD = 11;
|
|
14714
|
+
function OptionList({
|
|
14715
|
+
field,
|
|
14716
|
+
value,
|
|
14717
|
+
multiple,
|
|
14718
|
+
disabled,
|
|
14719
|
+
onValueChange
|
|
14720
|
+
}) {
|
|
14721
|
+
const selected = multiple ? toArrayValue(value) : [];
|
|
14722
|
+
const singleValue = !multiple && (typeof value === "string" || typeof value === "number") ? value : null;
|
|
14723
|
+
const [search, setSearch] = useState("");
|
|
14724
|
+
const options = field.options ?? [];
|
|
14725
|
+
const showSearch = options.length >= OPTION_SEARCH_THRESHOLD;
|
|
14726
|
+
const filteredOptions = useMemo(() => {
|
|
14727
|
+
if (!showSearch || search.trim() === "") return options;
|
|
14728
|
+
const query = search.trim().toLowerCase();
|
|
14729
|
+
return options.filter((option) => option.label.toLowerCase().includes(query));
|
|
14730
|
+
}, [options, search, showSearch]);
|
|
14731
|
+
if (options.length === 0) return /* @__PURE__ */ jsx(EmptyItem, { children: "\uD45C\uC2DC\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." });
|
|
14732
|
+
return /* @__PURE__ */ jsxs(
|
|
14733
|
+
"div",
|
|
14734
|
+
{
|
|
14735
|
+
className: cn(
|
|
14736
|
+
"max-h-[240px] overflow-auto",
|
|
14737
|
+
!showSearch && "pt-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
14738
|
+
"pb-[var(--cmp-chipFilter-listbox-list-paddingY)]"
|
|
14739
|
+
),
|
|
14740
|
+
children: [
|
|
14741
|
+
showSearch && /* @__PURE__ */ jsx(
|
|
14742
|
+
"div",
|
|
14743
|
+
{
|
|
14744
|
+
className: "sticky top-0 z-[1] border-b border-solid px-[8px] pb-[4px] pt-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
14745
|
+
style: { background: CHIPFILTER.listboxBg, borderColor: CHIPFILTER.listboxBorder },
|
|
14746
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-[6px] rounded-[4px] border border-solid border-[color:var(--sys-color-field-border-default)] bg-[var(--sys-color-field-bg-default)] px-[8px] py-[4px] focus-within:border-[color:var(--sys-color-field-border-focus)]", children: [
|
|
14747
|
+
/* @__PURE__ */ jsx(SIcon, { name: "search", size: 16, color: "var(--sys-color-field-icon-default)" }),
|
|
14748
|
+
/* @__PURE__ */ jsx(
|
|
14749
|
+
"input",
|
|
14750
|
+
{
|
|
14751
|
+
value: search,
|
|
14752
|
+
disabled,
|
|
14753
|
+
placeholder: "\uAC80\uC0C9",
|
|
14754
|
+
onChange: (event) => setSearch(event.target.value),
|
|
14755
|
+
className: "min-w-0 flex-1 border-none bg-transparent text-[12px] leading-[20px] text-[color:var(--sys-color-field-text-default)] outline-none placeholder:text-[color:var(--sys-color-field-text-placeholder)] disabled:cursor-not-allowed"
|
|
14756
|
+
}
|
|
14757
|
+
),
|
|
14758
|
+
search !== "" && !disabled && /* @__PURE__ */ jsx(
|
|
14759
|
+
SGhostButton,
|
|
14760
|
+
{
|
|
14761
|
+
icon: "close",
|
|
14762
|
+
size: "xxs",
|
|
14763
|
+
ariaLabel: "\uAC80\uC0C9\uC5B4 \uC9C0\uC6B0\uAE30",
|
|
14764
|
+
className: "flex-shrink-0",
|
|
14765
|
+
onClick: () => setSearch("")
|
|
14766
|
+
}
|
|
14767
|
+
)
|
|
14768
|
+
] })
|
|
14769
|
+
}
|
|
14770
|
+
),
|
|
14771
|
+
showSearch && filteredOptions.length === 0 && /* @__PURE__ */ jsx(EmptyItem, { children: "\uAC80\uC0C9 \uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4." }),
|
|
14772
|
+
filteredOptions.map((option) => {
|
|
14773
|
+
const checked = multiple ? selected.includes(option.value) : singleValue === option.value;
|
|
14774
|
+
return /* @__PURE__ */ jsxs(
|
|
14775
|
+
MenuItem,
|
|
14776
|
+
{
|
|
14777
|
+
selected: checked,
|
|
14778
|
+
disabled: disabled || option.disabled,
|
|
14779
|
+
multi: multiple,
|
|
14780
|
+
onClick: () => {
|
|
14781
|
+
if (multiple) {
|
|
14782
|
+
const next = checked ? selected.filter((v) => v !== option.value) : [...selected, option.value];
|
|
14783
|
+
onValueChange(next);
|
|
14784
|
+
} else {
|
|
14785
|
+
onValueChange(option.value);
|
|
14786
|
+
}
|
|
14787
|
+
},
|
|
14788
|
+
children: [
|
|
14789
|
+
multiple && /* @__PURE__ */ jsx(OptionCheckbox, { checked }),
|
|
14790
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: option.label })
|
|
14791
|
+
]
|
|
14792
|
+
},
|
|
14793
|
+
String(option.value)
|
|
14794
|
+
);
|
|
14795
|
+
})
|
|
14796
|
+
]
|
|
14797
|
+
}
|
|
14798
|
+
);
|
|
14799
|
+
}
|
|
14800
|
+
function OptionCheckbox({ checked }) {
|
|
14801
|
+
return /* @__PURE__ */ jsx(
|
|
14802
|
+
"span",
|
|
14803
|
+
{
|
|
14804
|
+
className: cn(
|
|
14805
|
+
"inline-flex size-[16px] shrink-0 items-center justify-center rounded-[2px] border border-solid",
|
|
14806
|
+
checked ? "border-[color:var(--cmp-checkbox-checked-bg-default)] bg-[var(--cmp-checkbox-checked-bg-default)]" : "border-[color:var(--cmp-checkbox-unchecked-border-default)] bg-[var(--cmp-checkbox-unchecked-bg-default)]"
|
|
14807
|
+
),
|
|
14808
|
+
children: checked && /* @__PURE__ */ jsx(SIcon, { name: "checkboxCheck", size: 12, color: "var(--cmp-checkbox-checked-icon-default)" })
|
|
14809
|
+
}
|
|
14810
|
+
);
|
|
14811
|
+
}
|
|
14812
|
+
function ListBox({ children }) {
|
|
14813
|
+
return /* @__PURE__ */ jsx(
|
|
14814
|
+
"div",
|
|
14815
|
+
{
|
|
14816
|
+
className: "overflow-hidden border border-solid shadow-[var(--shadow-overlay)]",
|
|
14817
|
+
style: {
|
|
14818
|
+
borderRadius: CHIPFILTER.listboxRadius,
|
|
14819
|
+
background: CHIPFILTER.listboxBg,
|
|
14820
|
+
borderColor: CHIPFILTER.listboxBorder
|
|
14821
|
+
},
|
|
14822
|
+
children
|
|
14823
|
+
}
|
|
14824
|
+
);
|
|
14825
|
+
}
|
|
14826
|
+
function MenuItem({
|
|
14827
|
+
children,
|
|
14828
|
+
selected,
|
|
14829
|
+
disabled,
|
|
14830
|
+
multi,
|
|
14831
|
+
onMouseEnter,
|
|
14832
|
+
onClick
|
|
14833
|
+
}) {
|
|
14834
|
+
return /* @__PURE__ */ jsx(
|
|
14835
|
+
"button",
|
|
14836
|
+
{
|
|
14837
|
+
type: "button",
|
|
14838
|
+
disabled,
|
|
14839
|
+
onMouseEnter,
|
|
14840
|
+
onClick,
|
|
14841
|
+
className: cn(
|
|
14842
|
+
"flex w-full min-w-0 cursor-pointer items-center gap-[8px] border-none bg-transparent text-left text-[12px] leading-[20px] outline-none disabled:cursor-not-allowed",
|
|
14843
|
+
selected ? "font-bold" : "font-normal",
|
|
14844
|
+
!disabled && "hover:font-bold"
|
|
14845
|
+
),
|
|
14846
|
+
style: {
|
|
14847
|
+
paddingTop: CHIPFILTER.itemPaddingY,
|
|
14848
|
+
paddingBottom: CHIPFILTER.itemPaddingY,
|
|
14849
|
+
paddingLeft: multi ? CHIPFILTER.itemMultiPaddingX : CHIPFILTER.itemPaddingLeft,
|
|
14850
|
+
paddingRight: multi ? CHIPFILTER.itemMultiPaddingX : CHIPFILTER.itemPaddingRight,
|
|
14851
|
+
color: disabled ? CHIPFILTER.chipDisabledText : selected ? CHIPFILTER.itemTextSelected : CHIPFILTER.itemTextDefault
|
|
14852
|
+
},
|
|
14853
|
+
children
|
|
14854
|
+
}
|
|
14855
|
+
);
|
|
14856
|
+
}
|
|
14857
|
+
function EmptyItem({ children }) {
|
|
14858
|
+
return /* @__PURE__ */ jsx(
|
|
14859
|
+
"div",
|
|
14860
|
+
{
|
|
14861
|
+
className: "text-[12px] leading-[20px]",
|
|
14862
|
+
style: {
|
|
14863
|
+
paddingTop: CHIPFILTER.itemPaddingY,
|
|
14864
|
+
paddingBottom: CHIPFILTER.itemPaddingY,
|
|
14865
|
+
paddingLeft: CHIPFILTER.itemPaddingLeft,
|
|
14866
|
+
paddingRight: CHIPFILTER.itemPaddingRight,
|
|
14867
|
+
color: CHIPFILTER.chipDisabledText
|
|
14868
|
+
},
|
|
14869
|
+
children
|
|
14870
|
+
}
|
|
14871
|
+
);
|
|
14872
|
+
}
|
|
14873
|
+
var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
|
|
14874
|
+
values = [],
|
|
14875
|
+
onValueChange,
|
|
14876
|
+
onInput,
|
|
14877
|
+
onFocus,
|
|
14878
|
+
onBlur,
|
|
14879
|
+
errors = [],
|
|
14880
|
+
disabledChips = [],
|
|
14881
|
+
size = "sm",
|
|
14882
|
+
disabled = false,
|
|
14883
|
+
placeholder = "\uD0DC\uADF8 \uC785\uB825 (Enter\uB85C \uB4F1\uB85D / \uCF64\uB9C8\uB85C \uAD6C\uBD84 / \uB744\uC5B4\uC4F0\uAE30 \uBD88\uAC00)",
|
|
14884
|
+
name,
|
|
14885
|
+
rules,
|
|
14886
|
+
error,
|
|
14887
|
+
useReset = false,
|
|
14888
|
+
maxCount,
|
|
14889
|
+
metaPlacement = "end",
|
|
14890
|
+
duplicateLabel,
|
|
14891
|
+
suggestions = [],
|
|
14892
|
+
loadingSuggestions = false,
|
|
14893
|
+
recommendedItems = [],
|
|
14894
|
+
loadingRecommendedItems = false,
|
|
14895
|
+
dropdownMinWidth = 200,
|
|
14896
|
+
label,
|
|
14897
|
+
labelWidth,
|
|
14898
|
+
hint,
|
|
14899
|
+
errorMessage,
|
|
14900
|
+
width,
|
|
14901
|
+
status,
|
|
14902
|
+
icon,
|
|
14903
|
+
iconColor,
|
|
14904
|
+
labelTooltip,
|
|
14905
|
+
labelTooltipProps,
|
|
14906
|
+
className,
|
|
14907
|
+
style
|
|
14908
|
+
}, ref) {
|
|
14909
|
+
const autoId = useId();
|
|
14910
|
+
const resolvedName = name ?? autoId;
|
|
14911
|
+
const [inputValue, setInputValue] = useState("");
|
|
14912
|
+
const [focused, setFocused] = useState(false);
|
|
14913
|
+
const [hovered, setHovered] = useState(false);
|
|
14914
|
+
const [activeIndex, setActiveIndex] = useState(-1);
|
|
14915
|
+
const [suppressSuggestions, setSuppressSuggestions] = useState(false);
|
|
14916
|
+
const [suppressRecommendations, setSuppressRecommendations] = useState(false);
|
|
14917
|
+
const inputRef = useRef(null);
|
|
14918
|
+
const containerRef = useRef(null);
|
|
14919
|
+
const inputShellRef = useRef(null);
|
|
14920
|
+
const isComposingRef = useRef(false);
|
|
14921
|
+
useImperativeHandle(ref, () => ({ focus: () => inputRef.current?.focus() }), []);
|
|
14922
|
+
const chipError = (i) => {
|
|
14923
|
+
if (values.indexOf(values[i]) !== i) return true;
|
|
14924
|
+
if (typeof errors === "function") return errors(values[i] ?? "");
|
|
14925
|
+
return errors[i] ?? false;
|
|
14926
|
+
};
|
|
14927
|
+
const chipDisabled = (i) => {
|
|
14928
|
+
if (disabled) return true;
|
|
14929
|
+
if (typeof disabledChips === "function") return disabledChips(values[i] ?? "");
|
|
14930
|
+
return disabledChips[i] ?? false;
|
|
14931
|
+
};
|
|
14932
|
+
const duplicateMessage = useMemo(() => {
|
|
14933
|
+
const seen = /* @__PURE__ */ new Set();
|
|
14934
|
+
for (const v of values) {
|
|
14935
|
+
if (seen.has(v))
|
|
14936
|
+
return duplicateLabel ? `\uC774\uBBF8 \uC785\uB825\uB41C ${duplicateLabel}\uC785\uB2C8\uB2E4.` : "\uC911\uBCF5\uB41C \uAC12\uC774 \uC874\uC7AC\uD569\uB2C8\uB2E4.";
|
|
14937
|
+
seen.add(v);
|
|
14938
|
+
}
|
|
14939
|
+
return "";
|
|
14940
|
+
}, [values, duplicateLabel]);
|
|
14941
|
+
const ruleMessage = useMemo(() => runRules(values, rules), [values, rules]);
|
|
14942
|
+
const resolvedErrorMessage = duplicateMessage || ruleMessage || errorMessage;
|
|
14943
|
+
const resolvedError = error || duplicateMessage !== "" || ruleMessage !== "";
|
|
14944
|
+
const resolvedStatus = status ?? (resolvedError ? "error" : void 0);
|
|
14945
|
+
useFormField({
|
|
14946
|
+
name,
|
|
14947
|
+
validate: () => runRules(values, rules) === "" && duplicateMessage === "",
|
|
14948
|
+
resetValidation: () => {
|
|
14949
|
+
}
|
|
14950
|
+
});
|
|
14951
|
+
const isMax = maxCount != null && values.length >= maxCount;
|
|
14952
|
+
const resolvedDropdownMinWidth = dropdownMinWidth == null ? void 0 : typeof dropdownMinWidth === "number" ? `${dropdownMinWidth}px` : dropdownMinWidth;
|
|
14953
|
+
const commit = (next) => onValueChange?.(next);
|
|
14954
|
+
const addChip = (v) => {
|
|
14955
|
+
if (maxCount != null && values.length >= maxCount) return;
|
|
14956
|
+
commit([...values, v]);
|
|
14957
|
+
setInputValue("");
|
|
14958
|
+
setActiveIndex(-1);
|
|
14959
|
+
onInput?.("");
|
|
14960
|
+
inputRef.current?.focus();
|
|
14961
|
+
};
|
|
14962
|
+
const removeChip = (i) => {
|
|
14963
|
+
commit(values.filter((_, idx) => idx !== i));
|
|
14964
|
+
inputRef.current?.focus();
|
|
14965
|
+
setSuppressRecommendations(true);
|
|
13565
14966
|
};
|
|
13566
14967
|
const reset = () => {
|
|
13567
14968
|
const kept = values.filter((_, i) => chipDisabled(i));
|
|
@@ -14192,7 +15593,7 @@ function TimeSelector({
|
|
|
14192
15593
|
const renderColumn = (type) => {
|
|
14193
15594
|
const isHour = type === "hour";
|
|
14194
15595
|
const val = isHour ? displayHour : minute;
|
|
14195
|
-
const
|
|
15596
|
+
const displayValue2 = editingPart === type ? inputDraft[type] ?? "" : String(val).padStart(2, "0");
|
|
14196
15597
|
return /* @__PURE__ */ jsxs(
|
|
14197
15598
|
"div",
|
|
14198
15599
|
{
|
|
@@ -14213,7 +15614,7 @@ function TimeSelector({
|
|
|
14213
15614
|
{
|
|
14214
15615
|
"aria-label": isHour ? "\uC2DC" : "\uBD84",
|
|
14215
15616
|
inputMode: "numeric",
|
|
14216
|
-
value:
|
|
15617
|
+
value: displayValue2,
|
|
14217
15618
|
placeholder: "-",
|
|
14218
15619
|
onFocus: () => beginEdit(type, val),
|
|
14219
15620
|
onBlur: () => endEdit(type),
|
|
@@ -14408,8 +15809,8 @@ function STimePicker({
|
|
|
14408
15809
|
disabled,
|
|
14409
15810
|
className,
|
|
14410
15811
|
style,
|
|
14411
|
-
children: /* @__PURE__ */ jsxs(
|
|
14412
|
-
/* @__PURE__ */ jsx(
|
|
15812
|
+
children: /* @__PURE__ */ jsxs(RPopover9.Root, { open, onOpenChange: commitOpen, children: [
|
|
15813
|
+
/* @__PURE__ */ jsx(RPopover9.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
14413
15814
|
"div",
|
|
14414
15815
|
{
|
|
14415
15816
|
ref: triggerRef,
|
|
@@ -14469,14 +15870,17 @@ function STimePicker({
|
|
|
14469
15870
|
]
|
|
14470
15871
|
}
|
|
14471
15872
|
) }),
|
|
14472
|
-
/* @__PURE__ */ jsx(
|
|
14473
|
-
|
|
15873
|
+
/* @__PURE__ */ jsx(RPopover9.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
15874
|
+
RPopover9.Content,
|
|
14474
15875
|
{
|
|
14475
15876
|
side: "bottom",
|
|
14476
15877
|
align: "start",
|
|
14477
15878
|
sideOffset: 4,
|
|
14478
15879
|
alignOffset: popoverAlignOffset,
|
|
14479
|
-
className: cn(
|
|
15880
|
+
className: cn(
|
|
15881
|
+
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
15882
|
+
FLOATING_SLIDE_ANIM
|
|
15883
|
+
),
|
|
14480
15884
|
children: /* @__PURE__ */ jsx(
|
|
14481
15885
|
TimeSelector,
|
|
14482
15886
|
{
|
|
@@ -14635,7 +16039,7 @@ function RangeTimeSelector({
|
|
|
14635
16039
|
const { minute } = getParts(side);
|
|
14636
16040
|
const val = isHour ? getDisplayHour(side) : minute;
|
|
14637
16041
|
const currentEditingKey = getEditingKey(side, kind);
|
|
14638
|
-
const
|
|
16042
|
+
const displayValue2 = editingKey === currentEditingKey ? inputDraft[currentEditingKey] ?? "" : String(val).padStart(2, "0");
|
|
14639
16043
|
return /* @__PURE__ */ jsxs(
|
|
14640
16044
|
"div",
|
|
14641
16045
|
{
|
|
@@ -14656,7 +16060,7 @@ function RangeTimeSelector({
|
|
|
14656
16060
|
{
|
|
14657
16061
|
"aria-label": `${side === "start" ? "\uC2DC\uC791" : "\uC885\uB8CC"} ${isHour ? "\uC2DC" : "\uBD84"}`,
|
|
14658
16062
|
inputMode: "numeric",
|
|
14659
|
-
value:
|
|
16063
|
+
value: displayValue2,
|
|
14660
16064
|
placeholder: "-",
|
|
14661
16065
|
onFocus: () => beginEdit(side, kind, val),
|
|
14662
16066
|
onBlur: () => endEdit(side, kind),
|
|
@@ -14867,8 +16271,8 @@ function STimeRangePicker({
|
|
|
14867
16271
|
disabled,
|
|
14868
16272
|
className,
|
|
14869
16273
|
style,
|
|
14870
|
-
children: /* @__PURE__ */ jsxs(
|
|
14871
|
-
/* @__PURE__ */ jsx(
|
|
16274
|
+
children: /* @__PURE__ */ jsxs(RPopover9.Root, { open, onOpenChange: commitOpen, children: [
|
|
16275
|
+
/* @__PURE__ */ jsx(RPopover9.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
14872
16276
|
"div",
|
|
14873
16277
|
{
|
|
14874
16278
|
ref: triggerRef,
|
|
@@ -14928,14 +16332,17 @@ function STimeRangePicker({
|
|
|
14928
16332
|
]
|
|
14929
16333
|
}
|
|
14930
16334
|
) }),
|
|
14931
|
-
/* @__PURE__ */ jsx(
|
|
14932
|
-
|
|
16335
|
+
/* @__PURE__ */ jsx(RPopover9.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
16336
|
+
RPopover9.Content,
|
|
14933
16337
|
{
|
|
14934
16338
|
side: "bottom",
|
|
14935
16339
|
align: "start",
|
|
14936
16340
|
sideOffset: 4,
|
|
14937
16341
|
alignOffset: popoverAlignOffset,
|
|
14938
|
-
className: cn(
|
|
16342
|
+
className: cn(
|
|
16343
|
+
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
16344
|
+
FLOATING_SLIDE_ANIM
|
|
16345
|
+
),
|
|
14939
16346
|
children: /* @__PURE__ */ jsx(
|
|
14940
16347
|
RangeTimeSelector,
|
|
14941
16348
|
{
|
|
@@ -14953,6 +16360,6 @@ function STimeRangePicker({
|
|
|
14953
16360
|
);
|
|
14954
16361
|
}
|
|
14955
16362
|
|
|
14956
|
-
export { BADGE_COLORS, BUTTON_COLORS, BUTTON_SIZES, COLOR_KEYS, GNB_COLORS, GNB_COMMON, GNB_FOLD_MS, GNB_FULL_LOGO_WIDTH, GNB_HEADER, GNB_MENU, GNB_MENU_WIDTH, GNB_RAIL, GNB_RAIL_WIDTH, ICONS, PAGE_BACKGROUNDS, SActionModal, SBadge, SBarcodeInput, SButton, SCROLL_AREA_AXES, SCalendar, SCallout, SCard, SCheckbox, SChip2 as SChip, SChipInput, SCircleProgress, SConfirmModal, SDatePicker, SDateRangePicker, SDivider, SDraggableGroup, SDraggableItem2 as SDraggableItem, SDraggableList, SDraggableProvider, SDrawer, SDropdownButton2 as SDropdownButton, SExpansionItem, SExpansionList2 as SExpansionList, SField, SFilePicker, SForm, SGhostButton, SGnb, SGuide, SIcon, SInput, SKeyValueTable, SLAYOUT_MIN_WIDTH, SLayout, SLayoutContext, SLinearProgress, SList2 as SList, SListItem2 as SListItem, SLoadingContainer, SLoadingModal, SLoadingViewport, SModal, SModalOutlet, SNumberInput, SPage, SPagination, SPopover, SPopup, SPortal, SRadio, SRadioButton, SRadioGroup, SSPLITTER_UNITS, SScrollArea, SSectionHeaderCard2 as SSectionHeaderCard, SSelect2 as SSelect, SSplitter2 as SSplitter, SStepper, SSwitch, STEPPER_SIZES, STable, STableBar, STabs, STag, STextLink, STextarea, STimePicker, STimeRangePicker, SToast, SToastContainer, SToggle, STooltip2 as STooltip, STree2 as STree, STreeItem2 as STreeItem, TAG_COLORS, TAG_SHAPES, TAG_SIZES, TIMEPICKER_SIZES, TIMEPICKER_SIZE_CONFIG, buttonPreset, cn, findGnbAncestors, findGnbRailValue, isColorKey, loading, resolveColor, useSLayout };
|
|
16363
|
+
export { BADGE_COLORS, BUTTON_COLORS, BUTTON_SIZES, COLOR_KEYS, GNB_COLORS, GNB_COMMON, GNB_FOLD_MS, GNB_FULL_LOGO_WIDTH, GNB_HEADER, GNB_MENU, GNB_MENU_WIDTH, GNB_RAIL, GNB_RAIL_WIDTH, ICONS, PAGE_BACKGROUNDS, RangeCalendar, SActionModal, SBadge, SBarcodeInput, SButton, SCROLL_AREA_AXES, SCalendar, SCallout, SCard, SCheckbox, SChip2 as SChip, SChipFilter, SChipInput, SCircleProgress, SConfirmModal, SDatePicker, SDateRangePicker, SDivider, SDraggableGroup, SDraggableItem2 as SDraggableItem, SDraggableList, SDraggableProvider, SDrawer, SDropdownButton2 as SDropdownButton, SExpansionItem, SExpansionList2 as SExpansionList, SField, SFilePicker, SForm, SGhostButton, SGnb, SGuide, SIcon, SInput, SKeyValueTable, SLAYOUT_MIN_WIDTH, SLayout, SLayoutContext, SLinearProgress, SList2 as SList, SListItem2 as SListItem, SLoadingContainer, SLoadingModal, SLoadingViewport, SModal, SModalOutlet, SNumberInput, SPage, SPagination, SPopover, SPopup, SPortal, SRadio, SRadioButton, SRadioGroup, SSPLITTER_UNITS, SScrollArea, SSectionHeaderCard2 as SSectionHeaderCard, SSelect2 as SSelect, SSplitter2 as SSplitter, SStepper, SSwitch, STEPPER_SIZES, STable, STableBar, STabs, STag, STextLink, STextarea, STimePicker, STimeRangePicker, SToast, SToastContainer, SToggle, STooltip2 as STooltip, STree2 as STree, STreeItem2 as STreeItem, TAG_COLORS, TAG_SHAPES, TAG_SIZES, TIMEPICKER_SIZES, TIMEPICKER_SIZE_CONFIG, buttonPreset, cn, findGnbAncestors, findGnbRailValue, isColorKey, loading, resolveColor, useSLayout };
|
|
14957
16364
|
//# sourceMappingURL=index.js.map
|
|
14958
16365
|
//# sourceMappingURL=index.js.map
|