sellmate-design-system-react 9.0.0-beta.2 → 9.0.0-beta.4
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 +123 -38
- package/dist/components/SChipFilter/README.md +2 -1
- package/dist/components/SChipFilter/SChipFilter.d.ts +13 -6
- package/dist/components/SDatePicker/README.md +41 -3
- package/dist/components/SDatePicker/SDatePicker.d.ts +36 -3
- package/dist/components/SDatePicker/index.d.ts +1 -1
- package/dist/components/SField/README.md +1 -0
- package/dist/components/SField/SField.d.ts +12 -0
- package/dist/components/SKeyValueTable/README.md +1 -0
- package/dist/components/SKeyValueTable/SKeyValueTable.d.ts +8 -1
- package/dist/components/SPage/README.md +1 -0
- package/dist/components/SPage/SPage.d.ts +12 -1
- package/dist/components/SPage/index.d.ts +1 -1
- package/dist/components/SPage/page.config.d.ts +8 -0
- package/dist/components/SSectionHeaderCard/README.md +10 -23
- package/dist/components/SSectionHeaderCard/SSectionHeaderCard.d.ts +21 -14
- package/dist/components/SSectionHeaderCard/index.d.ts +1 -1
- package/dist/components/SSelect/README.md +2 -0
- package/dist/components/STable/README.md +1 -0
- package/dist/components/STable/STable.d.ts +20 -0
- package/dist/components/STimePicker/timepicker.config.d.ts +5 -0
- package/dist/index.cjs +681 -82
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +679 -83
- package/dist/index.js.map +1 -1
- package/dist/llms-full.txt +180 -65
- package/dist/llms.txt +123 -38
- package/dist/styles.css +92 -8
- package/dist/theme.css +14 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5148,6 +5148,10 @@ var BODY_PADDING_CLASS = {
|
|
|
5148
5148
|
wide: "p-(--sys-space-panel-padding-wide)",
|
|
5149
5149
|
none: ""
|
|
5150
5150
|
};
|
|
5151
|
+
var BODY_BACKGROUND_CLASS = {
|
|
5152
|
+
frame: "",
|
|
5153
|
+
neutral: "bg-(--sys-color-bg-neutralLight)"
|
|
5154
|
+
};
|
|
5151
5155
|
var topBorderColorClass = {
|
|
5152
5156
|
default: "bg-(--cmp-sectionHeaderCard-topBorder-color-default)",
|
|
5153
5157
|
accent: "bg-(--cmp-sectionHeaderCard-topBorder-color-accent)"
|
|
@@ -5157,8 +5161,8 @@ var titleSizeClass = {
|
|
|
5157
5161
|
sm: "typo-heading-sm"
|
|
5158
5162
|
};
|
|
5159
5163
|
var SSectionHeaderCardBodyImpl = /* @__PURE__ */ react.forwardRef(
|
|
5160
|
-
function SSectionHeaderCardBody({ padding = "default",
|
|
5161
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn(BODY_PADDING_CLASS[padding],
|
|
5164
|
+
function SSectionHeaderCardBody({ padding = "default", background = "frame", children }, ref) {
|
|
5165
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn(BODY_PADDING_CLASS[padding], BODY_BACKGROUND_CLASS[background]), children });
|
|
5162
5166
|
}
|
|
5163
5167
|
);
|
|
5164
5168
|
var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
|
|
@@ -5171,8 +5175,7 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
5171
5175
|
subtitle,
|
|
5172
5176
|
slot,
|
|
5173
5177
|
thickness = false,
|
|
5174
|
-
className
|
|
5175
|
-
...rest
|
|
5178
|
+
className
|
|
5176
5179
|
}, ref) {
|
|
5177
5180
|
const hasHelp = helpText != null && helpText.length > 0;
|
|
5178
5181
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -5193,7 +5196,6 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
5193
5196
|
"box-border flex min-h-(--cmp-sectionHeaderCard-header-minHeight) w-full shrink-0 items-center gap-(--cmp-sectionHeaderCard-header-gap) overflow-hidden border-b border-(--cmp-sectionHeaderCard-header-border) bg-(--cmp-sectionHeaderCard-header-bg) px-(--cmp-sectionHeaderCard-header-paddingX) py-(--cmp-sectionHeaderCard-header-paddingY)",
|
|
5194
5197
|
className
|
|
5195
5198
|
),
|
|
5196
|
-
...rest,
|
|
5197
5199
|
children: [
|
|
5198
5200
|
marker && /* @__PURE__ */ jsxRuntime.jsx(SBadge, { color: "darkblue", className: "shrink-0" }),
|
|
5199
5201
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 shrink-0 items-center gap-[8px]", children: [
|
|
@@ -5237,8 +5239,24 @@ var SSectionHeaderCardHeaderImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
5237
5239
|
}
|
|
5238
5240
|
);
|
|
5239
5241
|
var SSectionHeaderCardRootImpl = /* @__PURE__ */ react.forwardRef(
|
|
5240
|
-
function SSectionHeaderCard({
|
|
5241
|
-
|
|
5242
|
+
function SSectionHeaderCard({
|
|
5243
|
+
title,
|
|
5244
|
+
titleSize,
|
|
5245
|
+
marker,
|
|
5246
|
+
required,
|
|
5247
|
+
helpText,
|
|
5248
|
+
subtitle,
|
|
5249
|
+
slot,
|
|
5250
|
+
thickness,
|
|
5251
|
+
headerClassName,
|
|
5252
|
+
padding,
|
|
5253
|
+
background,
|
|
5254
|
+
className,
|
|
5255
|
+
children,
|
|
5256
|
+
...rest
|
|
5257
|
+
}, ref) {
|
|
5258
|
+
const hasHeader = title != null;
|
|
5259
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5242
5260
|
"div",
|
|
5243
5261
|
{
|
|
5244
5262
|
ref,
|
|
@@ -5247,24 +5265,28 @@ var SSectionHeaderCardRootImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
5247
5265
|
className
|
|
5248
5266
|
),
|
|
5249
5267
|
...rest,
|
|
5250
|
-
children
|
|
5268
|
+
children: [
|
|
5269
|
+
hasHeader && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5270
|
+
SSectionHeaderCardHeaderImpl,
|
|
5271
|
+
{
|
|
5272
|
+
title,
|
|
5273
|
+
titleSize,
|
|
5274
|
+
marker,
|
|
5275
|
+
required,
|
|
5276
|
+
helpText,
|
|
5277
|
+
subtitle,
|
|
5278
|
+
slot,
|
|
5279
|
+
thickness,
|
|
5280
|
+
className: headerClassName
|
|
5281
|
+
}
|
|
5282
|
+
),
|
|
5283
|
+
/* @__PURE__ */ jsxRuntime.jsx(SSectionHeaderCardBodyImpl, { padding, background, children })
|
|
5284
|
+
]
|
|
5251
5285
|
}
|
|
5252
5286
|
);
|
|
5253
5287
|
}
|
|
5254
5288
|
);
|
|
5255
|
-
var
|
|
5256
|
-
var SSectionHeaderCardHeader2 = /* @__PURE__ */ withDisplayName(
|
|
5257
|
-
SSectionHeaderCardHeaderImpl,
|
|
5258
|
-
"SSectionHeaderCard.Header"
|
|
5259
|
-
);
|
|
5260
|
-
var SSectionHeaderCardBody2 = /* @__PURE__ */ withDisplayName(
|
|
5261
|
-
SSectionHeaderCardBodyImpl,
|
|
5262
|
-
"SSectionHeaderCard.Body"
|
|
5263
|
-
);
|
|
5264
|
-
var SSectionHeaderCard2 = /* @__PURE__ */ Object.assign(SSectionHeaderCardRoot, {
|
|
5265
|
-
Header: SSectionHeaderCardHeader2,
|
|
5266
|
-
Body: SSectionHeaderCardBody2
|
|
5267
|
-
});
|
|
5289
|
+
var SSectionHeaderCard2 = /* @__PURE__ */ withDisplayName(SSectionHeaderCardRootImpl, "SSectionHeaderCard");
|
|
5268
5290
|
var SDivider = /* @__PURE__ */ react.forwardRef(function SDivider2({ vertical = false, className, style, ...rest }, ref) {
|
|
5269
5291
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5270
5292
|
"hr",
|
|
@@ -6895,7 +6917,7 @@ function SModalContainer({
|
|
|
6895
6917
|
"div",
|
|
6896
6918
|
{
|
|
6897
6919
|
className: cn(
|
|
6898
|
-
"relative flex max-h-[
|
|
6920
|
+
"relative flex max-h-[85dvh] max-w-[calc(100dvw-48px)] flex-col overflow-hidden rounded-[var(--cmp-modal-radius)] bg-[var(--cmp-modal-bg)] shadow-normal-md",
|
|
6899
6921
|
shaking && "animate-modal-shake",
|
|
6900
6922
|
className
|
|
6901
6923
|
),
|
|
@@ -7152,7 +7174,7 @@ function SActionModal({
|
|
|
7152
7174
|
showClose: true,
|
|
7153
7175
|
width,
|
|
7154
7176
|
height,
|
|
7155
|
-
className: "w-fit min-w-[min(480px,calc(100dvw-48px))] min-h-[min(320px,
|
|
7177
|
+
className: "w-fit min-w-[min(480px,calc(100dvw-48px))] min-h-[min(320px,85dvh)]",
|
|
7156
7178
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-auto flex-col", children: [
|
|
7157
7179
|
/* @__PURE__ */ jsxRuntime.jsx(SOverlayHeader, { title: modalTitle, description, reserveCloseSpace: true }),
|
|
7158
7180
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1 overflow-auto px-[var(--cmp-modal-action-body-paddingX)] pb-[var(--cmp-modal-action-body-paddingBottom)]", children }),
|
|
@@ -8874,6 +8896,7 @@ var BACKGROUND_CLASS = {
|
|
|
8874
8896
|
var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
|
|
8875
8897
|
background = "frame",
|
|
8876
8898
|
scrollEndSpacing = true,
|
|
8899
|
+
contentHeight = "auto",
|
|
8877
8900
|
header,
|
|
8878
8901
|
className,
|
|
8879
8902
|
style,
|
|
@@ -8888,13 +8911,14 @@ var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
|
|
|
8888
8911
|
onScroll?.(e);
|
|
8889
8912
|
if (header != null && !header.fix) setScrolled(e.currentTarget.scrollTop > 0);
|
|
8890
8913
|
};
|
|
8914
|
+
const fill = contentHeight === "fill";
|
|
8891
8915
|
const main = /* @__PURE__ */ jsxRuntime.jsx(
|
|
8892
8916
|
"main",
|
|
8893
8917
|
{
|
|
8894
8918
|
ref,
|
|
8895
8919
|
className: cn(
|
|
8896
8920
|
"box-border min-h-0 min-w-0 flex-1 overflow-auto p-[var(--cmp-pageBody-padding-default)]",
|
|
8897
|
-
scrollEndSpacing && "pb-[var(--cmp-pageBody-padding-scrollEnd)]",
|
|
8921
|
+
!fill && scrollEndSpacing && "pb-[var(--cmp-pageBody-padding-scrollEnd)]",
|
|
8898
8922
|
SCROLLBAR_CLASS,
|
|
8899
8923
|
BACKGROUND_CLASS[background],
|
|
8900
8924
|
className
|
|
@@ -8902,7 +8926,7 @@ var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
|
|
|
8902
8926
|
style: header == null ? { ...gridStyle, ...style } : style,
|
|
8903
8927
|
onScroll: handleScroll,
|
|
8904
8928
|
...rest,
|
|
8905
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minWidth: MIN_CONTENT_WIDTH }, children })
|
|
8929
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(fill && "h-full"), style: { minWidth: MIN_CONTENT_WIDTH }, children })
|
|
8906
8930
|
}
|
|
8907
8931
|
);
|
|
8908
8932
|
if (header == null) return main;
|
|
@@ -8926,6 +8950,7 @@ var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
|
|
|
8926
8950
|
|
|
8927
8951
|
// src/components/SPage/page.config.ts
|
|
8928
8952
|
var PAGE_BACKGROUNDS = ["frame", "neutral", "screen"];
|
|
8953
|
+
var PAGE_CONTENT_HEIGHTS = ["auto", "fill"];
|
|
8929
8954
|
|
|
8930
8955
|
// src/components/STabs/tabs.config.ts
|
|
8931
8956
|
var TAB_MAIN_SIZE = {
|
|
@@ -9743,6 +9768,7 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
|
|
|
9743
9768
|
readOnly = false,
|
|
9744
9769
|
width,
|
|
9745
9770
|
minWidth,
|
|
9771
|
+
maxWidth,
|
|
9746
9772
|
multiline = false,
|
|
9747
9773
|
borderless = false,
|
|
9748
9774
|
children,
|
|
@@ -9778,7 +9804,10 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
|
|
|
9778
9804
|
const resolvedSuccess = status === "pass";
|
|
9779
9805
|
const showError = resolvedError && errorMessage !== "";
|
|
9780
9806
|
const interactive = !disabled && !readOnly;
|
|
9781
|
-
const
|
|
9807
|
+
const isPercentWidth = typeof width === "string" && width.trim().endsWith("%");
|
|
9808
|
+
const hug = cssLen(width) !== void 0 && !isPercentWidth;
|
|
9809
|
+
const addonWidth = effectiveAddonLabel !== "" ? cssLen(labelWidth) : void 0;
|
|
9810
|
+
const resolvedMaxWidth = cssLen(maxWidth) === void 0 || effectiveAddonLabel === "" ? cssLen(maxWidth) : addonWidth ? `calc(${cssLen(maxWidth)} + ${addonWidth})` : void 0;
|
|
9782
9811
|
const borderColor = borderless ? "transparent" : disabled ? "var(--color-grey-45)" : interactive && focused ? "var(--sys-color-field-border-focus)" : resolvedSuccess ? "var(--sys-color-field-border-success)" : resolvedError ? "var(--sys-color-field-border-danger)" : "var(--sys-color-field-border-default)";
|
|
9783
9812
|
const bgColor = borderless ? "transparent" : disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
|
|
9784
9813
|
const textColor = disabled ? "var(--color-grey-65)" : readOnly ? "var(--sys-color-field-text-readOnly)" : "var(--sys-color-field-text-default)";
|
|
@@ -9834,8 +9863,12 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
|
|
|
9834
9863
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9835
9864
|
"div",
|
|
9836
9865
|
{
|
|
9837
|
-
className: cn("flex min-w-0 flex-col", !hug && "flex-1"),
|
|
9838
|
-
style: {
|
|
9866
|
+
className: cn("flex min-w-0 flex-col", !hug && !isPercentWidth && "flex-1"),
|
|
9867
|
+
style: {
|
|
9868
|
+
width: cssLen(width),
|
|
9869
|
+
minWidth: cssLen(minWidth),
|
|
9870
|
+
maxWidth: resolvedMaxWidth
|
|
9871
|
+
},
|
|
9839
9872
|
children: [
|
|
9840
9873
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9841
9874
|
"div",
|
|
@@ -10590,6 +10623,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
10590
10623
|
height,
|
|
10591
10624
|
stickyColumn,
|
|
10592
10625
|
radius = "default",
|
|
10626
|
+
bordered = true,
|
|
10593
10627
|
noDataLabel = "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
10594
10628
|
noDataSlot,
|
|
10595
10629
|
isLoading = false,
|
|
@@ -10848,7 +10882,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
10848
10882
|
};
|
|
10849
10883
|
const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[var(--cmp-table-radius)] rounded-t-none" : "rounded-[var(--cmp-table-radius)]";
|
|
10850
10884
|
const cellPadY = dense ? "var(--cmp-table-body-paddingY-dense)" : "var(--cmp-table-body-paddingY-default)";
|
|
10851
|
-
const
|
|
10885
|
+
const cellPadXOf = (col) => col.contentType === "control" ? "var(--cmp-table-body-paddingX-default)" : "var(--cmp-table-body-paddingX-wide)";
|
|
10852
10886
|
const rowH = dense ? "var(--cmp-table-body-dense-height)" : "var(--cmp-table-body-default-height)";
|
|
10853
10887
|
const totalColSpan = visibleCols.length + (selectable ? 1 : 0);
|
|
10854
10888
|
const stickyInfo = (i) => {
|
|
@@ -10902,7 +10936,8 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
10902
10936
|
// 만으로는 스태킹 컨텍스트가 생기지 않아, 모달 안에 들어가면 30·31이 모달 Content
|
|
10903
10937
|
// 레벨까지 올라가 같은 컨텍스트의 floating portal 밴드(z-2)를 덮는다.
|
|
10904
10938
|
// 자손은 이미 overflow-hidden으로 클리핑되므로 테이블 내부 순서는 달라지지 않는다.
|
|
10905
|
-
"bg-white relative isolate flex flex-col overflow-hidden
|
|
10939
|
+
"bg-white relative isolate flex flex-col overflow-hidden",
|
|
10940
|
+
bordered && "border border-solid border-[color:var(--cmp-table-border-color)]",
|
|
10906
10941
|
// height가 없으면 루트가 받은 높이를 끝까지 채운다. 호스트가 className으로
|
|
10907
10942
|
// `flex-1 min-h-0` 등을 줘 루트 높이가 확정된 경우, 행이 적어도 테두리 박스가
|
|
10908
10943
|
// 남은 영역을 그대로 차지한다. basis는 auto로 둬 높이가 확정되지 않은
|
|
@@ -11072,9 +11107,10 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
11072
11107
|
stickyShadowClass(i),
|
|
11073
11108
|
typeof col.tdClass === "function" ? col.tdClass(row) : col.tdClass
|
|
11074
11109
|
);
|
|
11110
|
+
const tdPadX = cellPadXOf(col);
|
|
11075
11111
|
const tdStyle = {
|
|
11076
|
-
paddingLeft:
|
|
11077
|
-
paddingRight:
|
|
11112
|
+
paddingLeft: tdPadX,
|
|
11113
|
+
paddingRight: tdPadX,
|
|
11078
11114
|
paddingTop: cellPadY,
|
|
11079
11115
|
paddingBottom: cellPadY,
|
|
11080
11116
|
textAlign: col.align ?? "left",
|
|
@@ -11127,19 +11163,29 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
11127
11163
|
// SPagination은 전체 폭 기준 중앙, rows-per-page SSelect는 우측에 absolute 배치해 중앙 정렬을 유지한다.
|
|
11128
11164
|
// 루트 높이가 확정된 경우(테이블이 남은 영역을 채우는 배치) 페이지네이션 바가
|
|
11129
11165
|
// 눌리지 않도록 shrink-0으로 48px를 보장한다.
|
|
11130
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
11131
|
-
|
|
11132
|
-
|
|
11133
|
-
|
|
11134
|
-
|
|
11135
|
-
|
|
11136
|
-
|
|
11137
|
-
|
|
11138
|
-
|
|
11139
|
-
|
|
11140
|
-
|
|
11141
|
-
|
|
11142
|
-
|
|
11166
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
11167
|
+
"div",
|
|
11168
|
+
{
|
|
11169
|
+
className: cn(
|
|
11170
|
+
"relative flex h-[48px] shrink-0 items-center justify-center rounded-[var(--cmp-table-radius)] bg-[var(--color-grey-05)]",
|
|
11171
|
+
// 테두리를 끄면 겹칠 대상이 없어진다 — -mt-px 를 남기면 1px 어긋남만 생긴다.
|
|
11172
|
+
bordered && "-mt-px border border-solid border-[color:var(--cmp-table-border-color)]"
|
|
11173
|
+
),
|
|
11174
|
+
children: [
|
|
11175
|
+
/* @__PURE__ */ jsxRuntime.jsx(SPagination, { currentPage: displayPage, lastPage, onPageChange: changePage }),
|
|
11176
|
+
useRowsPerPageSelect && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-[10px] top-1/2 -translate-y-1/2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11177
|
+
SSelect2,
|
|
11178
|
+
{
|
|
11179
|
+
options: rowsPerPageOption,
|
|
11180
|
+
value: useInternalPagination ? innerRowsPerPage : pagination?.rowsPerPage,
|
|
11181
|
+
emitValue: true,
|
|
11182
|
+
onValueChange: (v) => changeRowsPerPage(Number(v)),
|
|
11183
|
+
width: 128
|
|
11184
|
+
}
|
|
11185
|
+
) })
|
|
11186
|
+
]
|
|
11187
|
+
}
|
|
11188
|
+
)
|
|
11143
11189
|
]
|
|
11144
11190
|
}
|
|
11145
11191
|
);
|
|
@@ -12156,12 +12202,275 @@ function SCalendar({
|
|
|
12156
12202
|
}
|
|
12157
12203
|
);
|
|
12158
12204
|
}
|
|
12205
|
+
var DATEPICKER_MODE_LIST_HEIGHT = 240;
|
|
12206
|
+
var DATEPICKER_MODE_ITEM_HEIGHT = 28;
|
|
12207
|
+
var YEAR_LIST_EDGE_BUFFER = 24;
|
|
12208
|
+
var YEAR_LIST_EXPAND_SIZE = 80;
|
|
12209
|
+
var MONTHS = Array.from({ length: 12 }, (_, i) => i + 1);
|
|
12210
|
+
var getTodayParts = () => {
|
|
12211
|
+
const today = /* @__PURE__ */ new Date();
|
|
12212
|
+
return {
|
|
12213
|
+
year: today.getFullYear(),
|
|
12214
|
+
month: today.getMonth() + 1
|
|
12215
|
+
};
|
|
12216
|
+
};
|
|
12217
|
+
var parseYear = (value) => {
|
|
12218
|
+
const year = Number(value?.slice(0, 4));
|
|
12219
|
+
return Number.isFinite(year) && year > 0 ? year : void 0;
|
|
12220
|
+
};
|
|
12221
|
+
var parseMonth = (value) => {
|
|
12222
|
+
const month = Number(value?.slice(5, 7));
|
|
12223
|
+
return Number.isFinite(month) && month >= 1 && month <= 12 ? month : void 0;
|
|
12224
|
+
};
|
|
12225
|
+
var formatMonthValue = (year, month) => `${year}-${String(month).padStart(2, "0")}`;
|
|
12226
|
+
var isYearDisabled = (year, selectable) => {
|
|
12227
|
+
if (!selectable) return false;
|
|
12228
|
+
const [start, end] = selectable;
|
|
12229
|
+
if (start !== "" && year < Number(start.slice(0, 4))) return true;
|
|
12230
|
+
if (end !== "" && year > Number(end.slice(0, 4))) return true;
|
|
12231
|
+
return false;
|
|
12232
|
+
};
|
|
12233
|
+
var isMonthDisabled = (year, month, selectable) => {
|
|
12234
|
+
if (!selectable) return false;
|
|
12235
|
+
const value = formatMonthValue(year, month);
|
|
12236
|
+
const [start, end] = selectable;
|
|
12237
|
+
if (start !== "" && value < start.slice(0, 7)) return true;
|
|
12238
|
+
if (end !== "" && value > end.slice(0, 7)) return true;
|
|
12239
|
+
return false;
|
|
12240
|
+
};
|
|
12241
|
+
function YearWheel({ value, anchorYear, selectable, onCommit }) {
|
|
12242
|
+
const listRef = react.useRef(null);
|
|
12243
|
+
const syncingScrollRef = react.useRef(false);
|
|
12244
|
+
const anchorYearRef = react.useRef(anchorYear);
|
|
12245
|
+
const [range, setRange] = react.useState(() => ({
|
|
12246
|
+
start: anchorYear - YEAR_LIST_EXPAND_SIZE,
|
|
12247
|
+
end: anchorYear + YEAR_LIST_EXPAND_SIZE
|
|
12248
|
+
}));
|
|
12249
|
+
const rangeStartRef = react.useRef(range.start);
|
|
12250
|
+
rangeStartRef.current = range.start;
|
|
12251
|
+
const years = Array.from({ length: range.end - range.start + 1 }, (_, i) => range.start + i);
|
|
12252
|
+
react.useLayoutEffect(() => {
|
|
12253
|
+
const list = listRef.current;
|
|
12254
|
+
if (!list) return;
|
|
12255
|
+
const index = anchorYearRef.current - rangeStartRef.current;
|
|
12256
|
+
syncingScrollRef.current = true;
|
|
12257
|
+
list.scrollTop = index * DATEPICKER_MODE_ITEM_HEIGHT;
|
|
12258
|
+
requestAnimationFrame(() => {
|
|
12259
|
+
syncingScrollRef.current = false;
|
|
12260
|
+
});
|
|
12261
|
+
}, []);
|
|
12262
|
+
const handleScroll = () => {
|
|
12263
|
+
const list = listRef.current;
|
|
12264
|
+
if (!list) return;
|
|
12265
|
+
if (syncingScrollRef.current) return;
|
|
12266
|
+
if (list.scrollTop < DATEPICKER_MODE_ITEM_HEIGHT * YEAR_LIST_EDGE_BUFFER) {
|
|
12267
|
+
const previousHeight = list.scrollHeight;
|
|
12268
|
+
setRange((current) => ({
|
|
12269
|
+
start: current.start - YEAR_LIST_EXPAND_SIZE,
|
|
12270
|
+
end: current.end
|
|
12271
|
+
}));
|
|
12272
|
+
requestAnimationFrame(() => {
|
|
12273
|
+
if (!listRef.current) return;
|
|
12274
|
+
syncingScrollRef.current = true;
|
|
12275
|
+
listRef.current.scrollTop += listRef.current.scrollHeight - previousHeight;
|
|
12276
|
+
requestAnimationFrame(() => {
|
|
12277
|
+
syncingScrollRef.current = false;
|
|
12278
|
+
});
|
|
12279
|
+
});
|
|
12280
|
+
return;
|
|
12281
|
+
}
|
|
12282
|
+
if (list.scrollHeight - list.scrollTop - list.clientHeight < DATEPICKER_MODE_ITEM_HEIGHT * YEAR_LIST_EDGE_BUFFER) {
|
|
12283
|
+
setRange((current) => ({
|
|
12284
|
+
start: current.start,
|
|
12285
|
+
end: current.end + YEAR_LIST_EXPAND_SIZE
|
|
12286
|
+
}));
|
|
12287
|
+
}
|
|
12288
|
+
};
|
|
12289
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full overflow-hidden bg-[var(--cmp-datepicker-mode-bg)]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12290
|
+
"div",
|
|
12291
|
+
{
|
|
12292
|
+
ref: listRef,
|
|
12293
|
+
role: "listbox",
|
|
12294
|
+
"aria-label": "year",
|
|
12295
|
+
className: "h-full overflow-y-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
12296
|
+
style: {
|
|
12297
|
+
paddingTop: `calc((${DATEPICKER_MODE_LIST_HEIGHT}px - ${DATEPICKER_MODE_ITEM_HEIGHT}px) / 2)`,
|
|
12298
|
+
paddingBottom: `calc((${DATEPICKER_MODE_LIST_HEIGHT}px - ${DATEPICKER_MODE_ITEM_HEIGHT}px) / 2)`
|
|
12299
|
+
},
|
|
12300
|
+
onScroll: handleScroll,
|
|
12301
|
+
children: years.map((year) => {
|
|
12302
|
+
const selected = year === value;
|
|
12303
|
+
const disabled = isYearDisabled(year, selectable);
|
|
12304
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12305
|
+
"button",
|
|
12306
|
+
{
|
|
12307
|
+
type: "button",
|
|
12308
|
+
role: "option",
|
|
12309
|
+
"aria-selected": selected,
|
|
12310
|
+
disabled,
|
|
12311
|
+
className: cn(
|
|
12312
|
+
"flex w-full items-center justify-center gap-[var(--cmp-datepicker-mode-item-gap)] border-0 px-[var(--cmp-datepicker-mode-item-paddingX)] py-[var(--cmp-datepicker-mode-item-paddingY)] text-center font-base text-12 leading-[20px]",
|
|
12313
|
+
disabled && "cursor-not-allowed bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-disabled)]",
|
|
12314
|
+
!disabled && !selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-default)] hover:bg-[var(--cmp-datepicker-mode-item-bg-hover)] hover:text-[color:var(--cmp-datepicker-mode-item-content-hover)]",
|
|
12315
|
+
!disabled && selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-bold text-[color:var(--cmp-datepicker-mode-item-content-selected)]"
|
|
12316
|
+
),
|
|
12317
|
+
onClick: () => !disabled && onCommit(year),
|
|
12318
|
+
children: year
|
|
12319
|
+
},
|
|
12320
|
+
year
|
|
12321
|
+
);
|
|
12322
|
+
})
|
|
12323
|
+
}
|
|
12324
|
+
) });
|
|
12325
|
+
}
|
|
12326
|
+
function SDatePickerYearListbox({
|
|
12327
|
+
value,
|
|
12328
|
+
anchorYear,
|
|
12329
|
+
selectable,
|
|
12330
|
+
onValueChange,
|
|
12331
|
+
className,
|
|
12332
|
+
style
|
|
12333
|
+
}) {
|
|
12334
|
+
const today = getTodayParts();
|
|
12335
|
+
const resolvedAnchorYear = anchorYear ?? today.year;
|
|
12336
|
+
const [year, setYear] = react.useState(() => parseYear(value) ?? resolvedAnchorYear);
|
|
12337
|
+
react.useEffect(() => {
|
|
12338
|
+
setYear(parseYear(value) ?? resolvedAnchorYear);
|
|
12339
|
+
}, [value, resolvedAnchorYear]);
|
|
12340
|
+
const commitYear = (nextYear) => {
|
|
12341
|
+
setYear(nextYear);
|
|
12342
|
+
onValueChange?.(String(nextYear));
|
|
12343
|
+
};
|
|
12344
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12345
|
+
"div",
|
|
12346
|
+
{
|
|
12347
|
+
className: cn(
|
|
12348
|
+
"inline-flex h-[240px] w-[var(--cmp-datepicker-mode-year-width)] overflow-hidden rounded-[var(--cmp-datepicker-mode-radius)] bg-[var(--cmp-datepicker-mode-bg)] shadow-normal-sm",
|
|
12349
|
+
className
|
|
12350
|
+
),
|
|
12351
|
+
style,
|
|
12352
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12353
|
+
YearWheel,
|
|
12354
|
+
{
|
|
12355
|
+
value: year,
|
|
12356
|
+
anchorYear: resolvedAnchorYear,
|
|
12357
|
+
selectable,
|
|
12358
|
+
onCommit: commitYear
|
|
12359
|
+
}
|
|
12360
|
+
)
|
|
12361
|
+
}
|
|
12362
|
+
);
|
|
12363
|
+
}
|
|
12364
|
+
function MonthWheel({ year, value, selectable, onCommit }) {
|
|
12365
|
+
const listRef = react.useRef(null);
|
|
12366
|
+
const initialValueRef = react.useRef(value);
|
|
12367
|
+
react.useLayoutEffect(() => {
|
|
12368
|
+
const list = listRef.current;
|
|
12369
|
+
if (!list) return;
|
|
12370
|
+
list.scrollTop = Math.max(
|
|
12371
|
+
0,
|
|
12372
|
+
(initialValueRef.current - 1) * DATEPICKER_MODE_ITEM_HEIGHT - (list.clientHeight - DATEPICKER_MODE_ITEM_HEIGHT) / 2
|
|
12373
|
+
);
|
|
12374
|
+
}, []);
|
|
12375
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full overflow-hidden bg-[var(--cmp-datepicker-mode-bg)]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12376
|
+
"div",
|
|
12377
|
+
{
|
|
12378
|
+
ref: listRef,
|
|
12379
|
+
role: "listbox",
|
|
12380
|
+
"aria-label": "month",
|
|
12381
|
+
className: "h-full overflow-y-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
12382
|
+
children: MONTHS.map((month) => {
|
|
12383
|
+
const selected = month === value;
|
|
12384
|
+
const disabled = isMonthDisabled(year, month, selectable);
|
|
12385
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12386
|
+
"button",
|
|
12387
|
+
{
|
|
12388
|
+
type: "button",
|
|
12389
|
+
role: "option",
|
|
12390
|
+
"aria-selected": selected,
|
|
12391
|
+
disabled,
|
|
12392
|
+
className: cn(
|
|
12393
|
+
"flex w-full items-center justify-center gap-[var(--cmp-datepicker-mode-item-gap)] border-0 px-[var(--cmp-datepicker-mode-item-paddingX)] py-[var(--cmp-datepicker-mode-item-paddingY)] text-center font-base text-12 leading-[20px]",
|
|
12394
|
+
disabled && "cursor-not-allowed bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-disabled)]",
|
|
12395
|
+
!disabled && !selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-default)] hover:bg-[var(--cmp-datepicker-mode-item-bg-hover)] hover:text-[color:var(--cmp-datepicker-mode-item-content-hover)]",
|
|
12396
|
+
!disabled && selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-bold text-[color:var(--cmp-datepicker-mode-item-content-selected)]"
|
|
12397
|
+
),
|
|
12398
|
+
onClick: () => !disabled && onCommit(month),
|
|
12399
|
+
children: [
|
|
12400
|
+
month,
|
|
12401
|
+
"\uC6D4"
|
|
12402
|
+
]
|
|
12403
|
+
},
|
|
12404
|
+
month
|
|
12405
|
+
);
|
|
12406
|
+
})
|
|
12407
|
+
}
|
|
12408
|
+
) });
|
|
12409
|
+
}
|
|
12410
|
+
function SDatePickerMonthListbox({
|
|
12411
|
+
value,
|
|
12412
|
+
anchorYear,
|
|
12413
|
+
selectable,
|
|
12414
|
+
onValueChange,
|
|
12415
|
+
onMonthSelect,
|
|
12416
|
+
className,
|
|
12417
|
+
style
|
|
12418
|
+
}) {
|
|
12419
|
+
const today = getTodayParts();
|
|
12420
|
+
const resolvedAnchorYear = anchorYear ?? today.year;
|
|
12421
|
+
const [year, setYear] = react.useState(() => parseYear(value) ?? resolvedAnchorYear);
|
|
12422
|
+
const [month, setMonth] = react.useState(() => parseMonth(value) ?? today.month);
|
|
12423
|
+
react.useEffect(() => {
|
|
12424
|
+
setYear(parseYear(value) ?? resolvedAnchorYear);
|
|
12425
|
+
setMonth(parseMonth(value) ?? today.month);
|
|
12426
|
+
}, [value, resolvedAnchorYear, today.month]);
|
|
12427
|
+
const commitYear = (nextYear) => {
|
|
12428
|
+
setYear(nextYear);
|
|
12429
|
+
onValueChange?.(formatMonthValue(nextYear, month));
|
|
12430
|
+
};
|
|
12431
|
+
const commitMonth = (nextMonth) => {
|
|
12432
|
+
setMonth(nextMonth);
|
|
12433
|
+
const nextValue = formatMonthValue(year, nextMonth);
|
|
12434
|
+
onValueChange?.(nextValue);
|
|
12435
|
+
onMonthSelect?.(nextValue);
|
|
12436
|
+
};
|
|
12437
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12438
|
+
"div",
|
|
12439
|
+
{
|
|
12440
|
+
className: cn(
|
|
12441
|
+
"inline-flex h-[240px] gap-[var(--cmp-datepicker-mode-yearMonth-gap)] overflow-hidden rounded-[var(--cmp-datepicker-mode-radius)] bg-[var(--cmp-datepicker-mode-bg)] shadow-normal-sm",
|
|
12442
|
+
className
|
|
12443
|
+
),
|
|
12444
|
+
style,
|
|
12445
|
+
children: [
|
|
12446
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 w-[var(--cmp-datepicker-mode-yearMonth-column-width)]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12447
|
+
YearWheel,
|
|
12448
|
+
{
|
|
12449
|
+
value: year,
|
|
12450
|
+
anchorYear: resolvedAnchorYear,
|
|
12451
|
+
selectable,
|
|
12452
|
+
onCommit: commitYear
|
|
12453
|
+
}
|
|
12454
|
+
) }),
|
|
12455
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12456
|
+
"div",
|
|
12457
|
+
{
|
|
12458
|
+
"aria-hidden": true,
|
|
12459
|
+
className: "w-[var(--border-width-1)] self-stretch bg-[var(--sys-color-divider-default)]"
|
|
12460
|
+
}
|
|
12461
|
+
),
|
|
12462
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 w-[var(--cmp-datepicker-mode-yearMonth-column-width)]", children: /* @__PURE__ */ jsxRuntime.jsx(MonthWheel, { year, value: month, selectable, onCommit: commitMonth }) })
|
|
12463
|
+
]
|
|
12464
|
+
}
|
|
12465
|
+
);
|
|
12466
|
+
}
|
|
12159
12467
|
function SDatePicker({
|
|
12160
12468
|
value,
|
|
12161
12469
|
onValueChange,
|
|
12162
12470
|
onViewChange,
|
|
12471
|
+
mode = "date",
|
|
12163
12472
|
size = "sm",
|
|
12164
|
-
placeholder
|
|
12473
|
+
placeholder,
|
|
12165
12474
|
selectable,
|
|
12166
12475
|
disabled = false,
|
|
12167
12476
|
width,
|
|
@@ -12187,6 +12496,7 @@ function SDatePicker({
|
|
|
12187
12496
|
const [focused, setFocused] = react.useState(false);
|
|
12188
12497
|
const [ruleError, setRuleError] = react.useState("");
|
|
12189
12498
|
const hasValue = value != null && value !== "";
|
|
12499
|
+
const resolvedPlaceholder = placeholder ?? (mode === "year" ? "YYYY" : mode === "month" ? "YYYY-MM" : "YYYY-MM-DD");
|
|
12190
12500
|
useFormField({
|
|
12191
12501
|
name,
|
|
12192
12502
|
validate: () => {
|
|
@@ -12198,12 +12508,39 @@ function SDatePicker({
|
|
|
12198
12508
|
});
|
|
12199
12509
|
const resolvedError = error || ruleError !== "";
|
|
12200
12510
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
12201
|
-
const dims = size === "md" ? {
|
|
12511
|
+
const dims = size === "md" ? {
|
|
12512
|
+
padX: 16,
|
|
12513
|
+
gap: 12,
|
|
12514
|
+
icon: 20,
|
|
12515
|
+
minW: 104,
|
|
12516
|
+
fieldMinW: 168,
|
|
12517
|
+
// 상한 등급 lg — 값 길이가 YYYY-MM-DD 로 정해져 있어, width="100%" 를 받아도
|
|
12518
|
+
// 행 전체로 늘어나지 않게 막는다 (SKeyValueTable 이 모든 컨트롤에 100% 를 넘긴다)
|
|
12519
|
+
fieldMaxW: 240,
|
|
12520
|
+
fontSize: 14,
|
|
12521
|
+
lineHeight: 24,
|
|
12522
|
+
radius: 6
|
|
12523
|
+
} : {
|
|
12524
|
+
padX: 12,
|
|
12525
|
+
gap: 8,
|
|
12526
|
+
icon: 16,
|
|
12527
|
+
minW: 80,
|
|
12528
|
+
fieldMinW: 128,
|
|
12529
|
+
// 상한 등급 md
|
|
12530
|
+
fieldMaxW: 160,
|
|
12531
|
+
fontSize: 12,
|
|
12532
|
+
lineHeight: 20,
|
|
12533
|
+
radius: 4
|
|
12534
|
+
};
|
|
12202
12535
|
const select = (date) => {
|
|
12203
12536
|
onValueChange?.(date);
|
|
12204
12537
|
if (rules && rules.length > 0) setRuleError(runRules(date, rules));
|
|
12205
12538
|
setOpen(false);
|
|
12206
12539
|
};
|
|
12540
|
+
const selectListboxValue = (nextValue) => {
|
|
12541
|
+
onValueChange?.(nextValue);
|
|
12542
|
+
if (rules && rules.length > 0) setRuleError(runRules(nextValue, rules));
|
|
12543
|
+
};
|
|
12207
12544
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12208
12545
|
SField,
|
|
12209
12546
|
{
|
|
@@ -12222,6 +12559,8 @@ function SDatePicker({
|
|
|
12222
12559
|
focused: focused || open,
|
|
12223
12560
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
12224
12561
|
width,
|
|
12562
|
+
minWidth: dims.fieldMinW,
|
|
12563
|
+
maxWidth: dims.fieldMaxW,
|
|
12225
12564
|
disabled,
|
|
12226
12565
|
className,
|
|
12227
12566
|
style,
|
|
@@ -12256,7 +12595,7 @@ function SDatePicker({
|
|
|
12256
12595
|
lineHeight: `${dims.lineHeight}px`,
|
|
12257
12596
|
color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasValue ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
|
|
12258
12597
|
},
|
|
12259
|
-
children: hasValue ? value :
|
|
12598
|
+
children: hasValue ? value : resolvedPlaceholder
|
|
12260
12599
|
}
|
|
12261
12600
|
)
|
|
12262
12601
|
]
|
|
@@ -12266,13 +12605,13 @@ function SDatePicker({
|
|
|
12266
12605
|
RPopover9__namespace.Content,
|
|
12267
12606
|
{
|
|
12268
12607
|
side: "bottom",
|
|
12269
|
-
align: "start",
|
|
12608
|
+
align: mode === "date" ? "start" : "center",
|
|
12270
12609
|
sideOffset: 4,
|
|
12271
12610
|
className: cn(
|
|
12272
12611
|
"z-50 max-w-[var(--radix-popover-content-available-width)]",
|
|
12273
12612
|
FLOATING_SLIDE_ANIM
|
|
12274
12613
|
),
|
|
12275
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12614
|
+
children: mode === "date" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
12276
12615
|
SCalendar,
|
|
12277
12616
|
{
|
|
12278
12617
|
value: value ?? void 0,
|
|
@@ -12281,6 +12620,24 @@ function SDatePicker({
|
|
|
12281
12620
|
onValueChange: select,
|
|
12282
12621
|
onViewChange
|
|
12283
12622
|
}
|
|
12623
|
+
) : mode === "year" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
12624
|
+
SDatePickerYearListbox,
|
|
12625
|
+
{
|
|
12626
|
+
value,
|
|
12627
|
+
selectable,
|
|
12628
|
+
onValueChange: (nextValue) => {
|
|
12629
|
+
selectListboxValue(nextValue);
|
|
12630
|
+
setOpen(false);
|
|
12631
|
+
}
|
|
12632
|
+
}
|
|
12633
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
12634
|
+
SDatePickerMonthListbox,
|
|
12635
|
+
{
|
|
12636
|
+
value,
|
|
12637
|
+
selectable,
|
|
12638
|
+
onValueChange: selectListboxValue,
|
|
12639
|
+
onMonthSelect: () => setOpen(false)
|
|
12640
|
+
}
|
|
12284
12641
|
)
|
|
12285
12642
|
}
|
|
12286
12643
|
) })
|
|
@@ -12662,6 +13019,9 @@ function SDateRangePicker({
|
|
|
12662
13019
|
icon: 20,
|
|
12663
13020
|
minW: 104,
|
|
12664
13021
|
fieldMinW: 260,
|
|
13022
|
+
// 상한 등급 xl — 값이 `YYYY-MM-DD ~ YYYY-MM-DD` 라 단일 날짜의 두 배가 넘는다.
|
|
13023
|
+
// 최소너비(260)가 이미 lg(240)를 넘으므로 상한도 한 등급 위여야 한다
|
|
13024
|
+
fieldMaxW: 480,
|
|
12665
13025
|
fontSize: 14,
|
|
12666
13026
|
lineHeight: 24,
|
|
12667
13027
|
radius: 6
|
|
@@ -12671,6 +13031,8 @@ function SDateRangePicker({
|
|
|
12671
13031
|
icon: 16,
|
|
12672
13032
|
minW: 80,
|
|
12673
13033
|
fieldMinW: 216,
|
|
13034
|
+
// 상한 등급 lg — 최소너비 216 이 md(160)를 넘어 md 로는 담기지 않는다
|
|
13035
|
+
fieldMaxW: 240,
|
|
12674
13036
|
fontSize: 12,
|
|
12675
13037
|
lineHeight: 20,
|
|
12676
13038
|
radius: 4
|
|
@@ -12701,6 +13063,7 @@ function SDateRangePicker({
|
|
|
12701
13063
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
12702
13064
|
width,
|
|
12703
13065
|
minWidth: dims.fieldMinW,
|
|
13066
|
+
maxWidth: dims.fieldMaxW,
|
|
12704
13067
|
disabled,
|
|
12705
13068
|
className,
|
|
12706
13069
|
style,
|
|
@@ -13165,6 +13528,7 @@ function SKeyValueTable({
|
|
|
13165
13528
|
values = {},
|
|
13166
13529
|
search = false,
|
|
13167
13530
|
radius = "default",
|
|
13531
|
+
bordered = true,
|
|
13168
13532
|
onChange,
|
|
13169
13533
|
onSearch,
|
|
13170
13534
|
className,
|
|
@@ -13229,7 +13593,8 @@ function SKeyValueTable({
|
|
|
13229
13593
|
});
|
|
13230
13594
|
const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[8px] rounded-t-none" : "rounded-[8px]";
|
|
13231
13595
|
const frameClass = cn(
|
|
13232
|
-
"overflow-hidden
|
|
13596
|
+
"overflow-hidden",
|
|
13597
|
+
bordered && "border border-solid border-[color:var(--cmp-table-border-color)]",
|
|
13233
13598
|
radiusClass
|
|
13234
13599
|
);
|
|
13235
13600
|
const table = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -13814,7 +14179,16 @@ var CHIPFILTER = {
|
|
|
13814
14179
|
itemTextDefault: "var(--cmp-chipFilter-item-text-default)",
|
|
13815
14180
|
itemTextSelected: "var(--cmp-chipFilter-item-text-selected)"
|
|
13816
14181
|
};
|
|
14182
|
+
var DEFAULT_PERIOD_PRESETS = [
|
|
14183
|
+
{ value: "day", label: "\uC77C\uBCC4" },
|
|
14184
|
+
{ value: "month", label: "\uC6D4\uBCC4" },
|
|
14185
|
+
{ value: "quarter", label: "\uBD84\uAE30\uBCC4" },
|
|
14186
|
+
{ value: "half", label: "\uBC18\uAE30\uBCC4" },
|
|
14187
|
+
{ value: "year", label: "\uC5F0\uB3C4\uBCC4" },
|
|
14188
|
+
{ value: "custom", label: "\uC0AC\uC6A9\uC790 \uC9C0\uC815", custom: true }
|
|
14189
|
+
];
|
|
13817
14190
|
var isKeywordValue = (value) => typeof value === "object" && value != null && !Array.isArray(value) && "keywords" in value;
|
|
14191
|
+
var isPeriodValue = (value) => typeof value === "object" && value != null && !Array.isArray(value) && "unit" in value;
|
|
13818
14192
|
var keywordEntries = (value) => {
|
|
13819
14193
|
if (isKeywordValue(value)) return value.keywords;
|
|
13820
14194
|
if (Array.isArray(value)) {
|
|
@@ -13838,12 +14212,33 @@ var todayIso = () => {
|
|
|
13838
14212
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
13839
14213
|
};
|
|
13840
14214
|
var isInlineDateField = (field) => field.type === "date" && field.radioButton === true && (field.presets?.length ?? 0) > 0;
|
|
14215
|
+
var getFieldPresets = (field) => {
|
|
14216
|
+
if (field.type === "period") return field.presets ?? DEFAULT_PERIOD_PRESETS;
|
|
14217
|
+
return field.presets ?? [];
|
|
14218
|
+
};
|
|
14219
|
+
var getDefaultPeriodInputValue = (unit) => {
|
|
14220
|
+
const today = todayIso();
|
|
14221
|
+
if (unit === "day") return today;
|
|
14222
|
+
if (unit === "month") return today.slice(0, 7);
|
|
14223
|
+
if (unit === "quarter") return 1;
|
|
14224
|
+
if (unit === "half") return "first";
|
|
14225
|
+
if (unit === "year") return today.slice(0, 4);
|
|
14226
|
+
return [today, today];
|
|
14227
|
+
};
|
|
14228
|
+
var createPeriodValue = (unit) => ({
|
|
14229
|
+
unit,
|
|
14230
|
+
value: getDefaultPeriodInputValue(unit)
|
|
14231
|
+
});
|
|
13841
14232
|
var resolveFieldDefault = (field) => {
|
|
13842
14233
|
if (field.defaultValue !== void 0) return field.defaultValue;
|
|
13843
14234
|
if (isInlineDateField(field)) return todayIso();
|
|
13844
14235
|
if (!field.required) return void 0;
|
|
13845
14236
|
if (field.type === "single") return field.options?.[0]?.value;
|
|
13846
14237
|
if (field.type === "date") return todayIso();
|
|
14238
|
+
if (field.type === "period") {
|
|
14239
|
+
const unit = getFieldPresets(field).find((preset) => !preset.custom)?.value;
|
|
14240
|
+
return unit ? createPeriodValue(unit) : void 0;
|
|
14241
|
+
}
|
|
13847
14242
|
return void 0;
|
|
13848
14243
|
};
|
|
13849
14244
|
var valuesEqual = (a, b) => {
|
|
@@ -13867,6 +14262,8 @@ var isAtDefaultValue = (field, value) => {
|
|
|
13867
14262
|
return def !== void 0 && valuesEqual(value, def);
|
|
13868
14263
|
};
|
|
13869
14264
|
var isInlineField = (field) => isInlineDateField(field) || field.type === "custom";
|
|
14265
|
+
var isFixedField = (field) => field.fix === true || field.required === true;
|
|
14266
|
+
var isAddableField = (field) => !isFixedField(field);
|
|
13870
14267
|
var isGroupedFields = (fields) => fields.length > 0 && "fields" in fields[0];
|
|
13871
14268
|
var isGroupSatisfied = (group, values) => {
|
|
13872
14269
|
if (!group.rule) return true;
|
|
@@ -13893,9 +14290,10 @@ var defaultGroupTooltipMessage = (rule, fields) => {
|
|
|
13893
14290
|
};
|
|
13894
14291
|
var matchPresetId = (presets, value) => {
|
|
13895
14292
|
if (isEmptyValue(value)) return null;
|
|
14293
|
+
if (isPeriodValue(value)) return value.unit;
|
|
13896
14294
|
for (const preset of presets) {
|
|
13897
|
-
if (preset.custom
|
|
13898
|
-
const resolved = preset.resolve();
|
|
14295
|
+
if (preset.custom) continue;
|
|
14296
|
+
const resolved = preset.resolve ? preset.resolve() : preset.value;
|
|
13899
14297
|
if (Array.isArray(resolved) && Array.isArray(value)) {
|
|
13900
14298
|
if (resolved[0] === value[0] && resolved[1] === value[1]) return preset.value;
|
|
13901
14299
|
} else if (!Array.isArray(resolved) && !Array.isArray(value) && resolved === value) {
|
|
@@ -13911,18 +14309,36 @@ var formatValueList = (labels) => {
|
|
|
13911
14309
|
};
|
|
13912
14310
|
var displayValue = (field, value) => {
|
|
13913
14311
|
if (isEmptyValue(value)) return "";
|
|
13914
|
-
if (field.type === "multi")
|
|
13915
|
-
|
|
14312
|
+
if (field.type === "multi") {
|
|
14313
|
+
const values = toArrayValue(value);
|
|
14314
|
+
const selectableValues = (field.options ?? []).filter((option) => !option.disabled).map((option) => option.value);
|
|
14315
|
+
if (selectableValues.length > 0 && selectableValues.every((selectableValue) => values.includes(selectableValue))) {
|
|
14316
|
+
return "\uC804\uCCB4";
|
|
14317
|
+
}
|
|
14318
|
+
return formatValueList(values.map((v) => optionLabel(field, v)));
|
|
14319
|
+
}
|
|
13916
14320
|
if (field.type === "single") return optionLabel(field, value);
|
|
13917
14321
|
if (field.type === "date")
|
|
13918
14322
|
return Array.isArray(value) ? `${value[0]} ~ ${value[1]}` : String(value);
|
|
14323
|
+
if (field.type === "period") {
|
|
14324
|
+
if (!isPeriodValue(value)) {
|
|
14325
|
+
const preset2 = getFieldPresets(field).find((p) => p.value === value);
|
|
14326
|
+
return preset2?.label ?? String(value);
|
|
14327
|
+
}
|
|
14328
|
+
const preset = getFieldPresets(field).find((p) => p.value === value.unit);
|
|
14329
|
+
const label = preset?.label ?? value.unit;
|
|
14330
|
+
if (value.unit === "quarter") return `${label}(${value.value ?? 1}\uBD84\uAE30)`;
|
|
14331
|
+
if (value.unit === "half") return `${label}(${value.value === "second" ? "\uD558\uBC18\uAE30" : "\uC0C1\uBC18\uAE30"})`;
|
|
14332
|
+
if (Array.isArray(value.value)) return `${value.value[0]} ~ ${value.value[1]}`;
|
|
14333
|
+
return value.value != null && value.value !== "" ? String(value.value) : label;
|
|
14334
|
+
}
|
|
13919
14335
|
if (field.type === "keyword") return formatValueList(keywordEntries(value));
|
|
13920
14336
|
return String(value);
|
|
13921
14337
|
};
|
|
13922
14338
|
var chipDisplayValue = (field, value) => {
|
|
13923
14339
|
const text = displayValue(field, value);
|
|
13924
14340
|
if (field.type !== "date" || isEmptyValue(value)) return text;
|
|
13925
|
-
const presets = field
|
|
14341
|
+
const presets = getFieldPresets(field);
|
|
13926
14342
|
if (presets.length === 0) return text;
|
|
13927
14343
|
const preset = presets.find((p) => p.value === matchPresetId(presets, value));
|
|
13928
14344
|
return preset && !preset.custom ? `${preset.label}(${text})` : text;
|
|
@@ -13939,7 +14355,6 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
13939
14355
|
onAddFilter,
|
|
13940
14356
|
label = "\uAC80\uC0C9 \uD544\uD130",
|
|
13941
14357
|
showLabel = false,
|
|
13942
|
-
showAddButton = true,
|
|
13943
14358
|
showReset = true,
|
|
13944
14359
|
disabled = false,
|
|
13945
14360
|
className,
|
|
@@ -13954,7 +14369,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
13954
14369
|
const values = normalizeValues(value);
|
|
13955
14370
|
const portalContainer = usePortalContainer();
|
|
13956
14371
|
const [internalActiveKeys, setInternalActiveKeys] = react.useState(
|
|
13957
|
-
() => fields.filter((field) => field.defaultActive !== false).map((field) => field.key)
|
|
14372
|
+
() => fields.filter((field) => isFixedField(field) || field.defaultActive !== false).map((field) => field.key)
|
|
13958
14373
|
);
|
|
13959
14374
|
const [openKey, setOpenKey] = react.useState(null);
|
|
13960
14375
|
const [addOpen, setAddOpen] = react.useState(false);
|
|
@@ -13996,7 +14411,9 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
13996
14411
|
setInternalActiveKeys((current) => {
|
|
13997
14412
|
const known = new Set(fields.map((field) => field.key));
|
|
13998
14413
|
const kept = current.filter((key) => known.has(key));
|
|
13999
|
-
const additions = fields.filter(
|
|
14414
|
+
const additions = fields.filter(
|
|
14415
|
+
(field) => (isFixedField(field) || field.defaultActive !== false) && !kept.includes(field.key)
|
|
14416
|
+
).map((field) => field.key);
|
|
14000
14417
|
return [...kept, ...additions];
|
|
14001
14418
|
});
|
|
14002
14419
|
}, [activeKeys, fields]);
|
|
@@ -14017,25 +14434,31 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14017
14434
|
});
|
|
14018
14435
|
if (changed) onValueChange?.({ ...values, ...patch });
|
|
14019
14436
|
}, [fields, values, onValueChange]);
|
|
14020
|
-
const
|
|
14437
|
+
const fixedKeys = fields.filter(isFixedField).map((field) => field.key);
|
|
14438
|
+
const resolvedActiveKeys = Array.from(
|
|
14439
|
+
/* @__PURE__ */ new Set([...activeKeys ?? internalActiveKeys, ...fixedKeys])
|
|
14440
|
+
);
|
|
14021
14441
|
const activeFields = fields.filter((field) => resolvedActiveKeys.includes(field.key));
|
|
14022
|
-
const inactiveFields = fields.filter(
|
|
14442
|
+
const inactiveFields = fields.filter(
|
|
14443
|
+
(field) => isAddableField(field) && !resolvedActiveKeys.includes(field.key)
|
|
14444
|
+
);
|
|
14023
14445
|
const groupIndexByKey = /* @__PURE__ */ new Map();
|
|
14024
14446
|
groups.forEach((group, groupIndex) => {
|
|
14025
14447
|
group.fields.forEach((field) => groupIndexByKey.set(field.key, groupIndex));
|
|
14026
14448
|
});
|
|
14027
14449
|
const hasValue = fields.some((field) => !isEmptyValue(values[field.key]));
|
|
14028
|
-
const
|
|
14450
|
+
const hasAddButton = fields.some(isAddableField);
|
|
14451
|
+
const hasRightActions = hasAddButton || showReset;
|
|
14029
14452
|
const currentOpenField = fields.find((field) => field.key === openKey);
|
|
14030
14453
|
const editorPopoverStyle = react.useMemo(() => {
|
|
14031
14454
|
if (currentOpenField?.type === "keyword") {
|
|
14032
14455
|
return { width: CHIPFILTER_LISTBOX_WIDTH };
|
|
14033
14456
|
}
|
|
14034
|
-
if (currentOpenField?.type === "date" && (currentOpenField.
|
|
14457
|
+
if ((currentOpenField?.type === "date" || currentOpenField?.type === "period") && getFieldPresets(currentOpenField).length > 0) {
|
|
14035
14458
|
return { width: CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH };
|
|
14036
14459
|
}
|
|
14037
14460
|
return { width: CHIPFILTER_LISTBOX_WIDTH };
|
|
14038
|
-
}, [currentOpenField
|
|
14461
|
+
}, [currentOpenField]);
|
|
14039
14462
|
const setActive = (next) => {
|
|
14040
14463
|
if (!activeKeys) setInternalActiveKeys(next);
|
|
14041
14464
|
onActiveKeysChange?.(next);
|
|
@@ -14054,6 +14477,12 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14054
14477
|
const def = field ? resolveFieldDefault(field) : void 0;
|
|
14055
14478
|
runSearch(emitValue(key, def !== void 0 ? def : null));
|
|
14056
14479
|
};
|
|
14480
|
+
const removeField = (key) => {
|
|
14481
|
+
const nextValues = emitValue(key, null);
|
|
14482
|
+
setActive(resolvedActiveKeys.filter((activeKey) => activeKey !== key));
|
|
14483
|
+
if (openKey === key) setOpenKey(null);
|
|
14484
|
+
runSearch(nextValues);
|
|
14485
|
+
};
|
|
14057
14486
|
const reset = react.useCallback(() => {
|
|
14058
14487
|
const next = fields.reduce((acc, field) => {
|
|
14059
14488
|
const def = resolveFieldDefault(field);
|
|
@@ -14144,7 +14573,15 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14144
14573
|
flushRun();
|
|
14145
14574
|
runGroupIndex = groupIndex;
|
|
14146
14575
|
}
|
|
14147
|
-
const
|
|
14576
|
+
const addable = isAddableField(field);
|
|
14577
|
+
const showClear = addable || !isAtDefaultValue(field, values[field.key]);
|
|
14578
|
+
const handleClear = () => {
|
|
14579
|
+
if (addable) {
|
|
14580
|
+
removeField(field.key);
|
|
14581
|
+
return;
|
|
14582
|
+
}
|
|
14583
|
+
clearValue(field.key);
|
|
14584
|
+
};
|
|
14148
14585
|
const node = isInlineDateField(field) ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
14149
14586
|
InlineDatePresetFilter,
|
|
14150
14587
|
{
|
|
@@ -14154,15 +14591,27 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14154
14591
|
warning,
|
|
14155
14592
|
showClear,
|
|
14156
14593
|
onValueChange: (next) => emitValueAndSearch(field.key, next),
|
|
14157
|
-
onClear:
|
|
14594
|
+
onClear: handleClear
|
|
14158
14595
|
},
|
|
14159
14596
|
field.key
|
|
14160
|
-
) : field.type === "custom" ? /* @__PURE__ */ jsxRuntime.
|
|
14161
|
-
|
|
14162
|
-
|
|
14163
|
-
|
|
14164
|
-
|
|
14165
|
-
|
|
14597
|
+
) : field.type === "custom" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex shrink-0 items-center gap-[4px]", children: [
|
|
14598
|
+
field.render?.({
|
|
14599
|
+
value: values[field.key],
|
|
14600
|
+
disabled: disabled || field.disabled,
|
|
14601
|
+
warning,
|
|
14602
|
+
onValueChange: (next) => emitValueAndSearch(field.key, next)
|
|
14603
|
+
}),
|
|
14604
|
+
addable && !disabled && !field.disabled && showClear && /* @__PURE__ */ jsxRuntime.jsx(
|
|
14605
|
+
"button",
|
|
14606
|
+
{
|
|
14607
|
+
type: "button",
|
|
14608
|
+
"aria-label": `${field.label} \uD544\uD130 \uC81C\uAC70`,
|
|
14609
|
+
className: "inline-flex size-[16px] shrink-0 items-center justify-center rounded-[var(--cmp-ghostButton-radius-sm)] border-none bg-transparent p-0",
|
|
14610
|
+
onClick: handleClear,
|
|
14611
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "close", size: 12, color: "var(--cmp-ghostButton-default-content)" })
|
|
14612
|
+
}
|
|
14613
|
+
)
|
|
14614
|
+
] }, field.key) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
14166
14615
|
FilterChip,
|
|
14167
14616
|
{
|
|
14168
14617
|
field,
|
|
@@ -14172,9 +14621,10 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14172
14621
|
disabled: disabled || field.disabled,
|
|
14173
14622
|
warning,
|
|
14174
14623
|
showClear,
|
|
14624
|
+
showClearWhenEmpty: addable,
|
|
14175
14625
|
refCallback: (node2) => triggerRefs.current.set(field.key, node2),
|
|
14176
14626
|
onOpen: () => setOpenKey(openKey === field.key ? null : field.key),
|
|
14177
|
-
onClear:
|
|
14627
|
+
onClear: handleClear
|
|
14178
14628
|
},
|
|
14179
14629
|
field.key
|
|
14180
14630
|
);
|
|
@@ -14195,7 +14645,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14195
14645
|
})(),
|
|
14196
14646
|
hasRightActions && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
14197
14647
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, { inset: true }),
|
|
14198
|
-
|
|
14648
|
+
hasAddButton && /* @__PURE__ */ jsxRuntime.jsxs(RPopover9__namespace.Root, { open: addOpen, onOpenChange: setAddOpen, children: [
|
|
14199
14649
|
/* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14200
14650
|
"button",
|
|
14201
14651
|
{
|
|
@@ -14242,7 +14692,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
14242
14692
|
"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",
|
|
14243
14693
|
// 부모 flex gap(6px)은 칩 사이 간격 기준이라, 필터 추가 버튼과의 12px 간격을 맞추려면
|
|
14244
14694
|
// 부족한 만큼(12px - gap)을 추가로 띄운다. 필터 추가가 없을 땐 divider와 이미 12px이라 불필요.
|
|
14245
|
-
|
|
14695
|
+
hasAddButton && "ml-[calc(12px-var(--cmp-chipFilter-chip-group))]"
|
|
14246
14696
|
),
|
|
14247
14697
|
style: {
|
|
14248
14698
|
color: disabled || !hasValue ? "var(--cmp-textLink-content-disabled)" : "var(--cmp-textLink-content-default)"
|
|
@@ -14326,6 +14776,7 @@ function FilterChip({
|
|
|
14326
14776
|
disabled,
|
|
14327
14777
|
warning,
|
|
14328
14778
|
showClear,
|
|
14779
|
+
showClearWhenEmpty,
|
|
14329
14780
|
refCallback,
|
|
14330
14781
|
onOpen,
|
|
14331
14782
|
onClear
|
|
@@ -14395,7 +14846,7 @@ function FilterChip({
|
|
|
14395
14846
|
}
|
|
14396
14847
|
)
|
|
14397
14848
|
] }),
|
|
14398
|
-
|
|
14849
|
+
!disabled && showClear && (applied || showClearWhenEmpty) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
14399
14850
|
"span",
|
|
14400
14851
|
{
|
|
14401
14852
|
role: "button",
|
|
@@ -14427,7 +14878,7 @@ function EditorPanel({
|
|
|
14427
14878
|
onValueChange,
|
|
14428
14879
|
onClose
|
|
14429
14880
|
}) {
|
|
14430
|
-
const wrapsInPaddedTop = field.type === "date";
|
|
14881
|
+
const wrapsInPaddedTop = field.type === "date" || field.type === "period";
|
|
14431
14882
|
const isMulti = field.type === "multi";
|
|
14432
14883
|
const selectableValues = isMulti ? (field.options ?? []).filter((option) => !option.disabled).map((option) => option.value) : [];
|
|
14433
14884
|
const selectedValues = isMulti ? toArrayValue(value) : [];
|
|
@@ -14506,6 +14957,17 @@ function FilterEditor({
|
|
|
14506
14957
|
disabled,
|
|
14507
14958
|
onValueChange
|
|
14508
14959
|
}) {
|
|
14960
|
+
if (field.type === "period") {
|
|
14961
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14962
|
+
PeriodPresetEditor,
|
|
14963
|
+
{
|
|
14964
|
+
field,
|
|
14965
|
+
value,
|
|
14966
|
+
disabled,
|
|
14967
|
+
onValueChange
|
|
14968
|
+
}
|
|
14969
|
+
);
|
|
14970
|
+
}
|
|
14509
14971
|
if (field.type === "date") {
|
|
14510
14972
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14511
14973
|
DatePresetEditor,
|
|
@@ -14545,7 +15007,7 @@ function DatePresetEditor({
|
|
|
14545
15007
|
disabled,
|
|
14546
15008
|
onValueChange
|
|
14547
15009
|
}) {
|
|
14548
|
-
const presets = field
|
|
15010
|
+
const presets = getFieldPresets(field);
|
|
14549
15011
|
const [selectedId, setSelectedId] = react.useState(() => matchPresetId(presets, value));
|
|
14550
15012
|
const syncedInitialValueRef = react.useRef(!isEmptyValue(value));
|
|
14551
15013
|
react.useEffect(() => {
|
|
@@ -14556,9 +15018,9 @@ function DatePresetEditor({
|
|
|
14556
15018
|
const selectedPreset = presets.find((preset) => preset.value === selectedId);
|
|
14557
15019
|
const selectPreset = (preset) => {
|
|
14558
15020
|
setSelectedId(preset.value);
|
|
14559
|
-
if (!preset.custom) onValueChange(preset.resolve ? preset.resolve() :
|
|
15021
|
+
if (!preset.custom) onValueChange(preset.resolve ? preset.resolve() : preset.value);
|
|
14560
15022
|
};
|
|
14561
|
-
if (presets.length === 0) {
|
|
15023
|
+
if (field.type === "date" && presets.length === 0) {
|
|
14562
15024
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14563
15025
|
SDatePicker,
|
|
14564
15026
|
{
|
|
@@ -14594,6 +15056,130 @@ function DatePresetEditor({
|
|
|
14594
15056
|
)
|
|
14595
15057
|
] });
|
|
14596
15058
|
}
|
|
15059
|
+
function PeriodPresetEditor({
|
|
15060
|
+
field,
|
|
15061
|
+
value,
|
|
15062
|
+
disabled,
|
|
15063
|
+
onValueChange
|
|
15064
|
+
}) {
|
|
15065
|
+
const presets = getFieldPresets(field);
|
|
15066
|
+
const firstUnit = presets.find((preset) => !preset.custom)?.value ?? "day";
|
|
15067
|
+
const [selectedId, setSelectedId] = react.useState(() => matchPresetId(presets, value) ?? firstUnit);
|
|
15068
|
+
const periodValue = isPeriodValue(value) ? value : createPeriodValue(selectedId ?? firstUnit);
|
|
15069
|
+
const selectedUnit = selectedId ?? periodValue.unit;
|
|
15070
|
+
react.useEffect(() => {
|
|
15071
|
+
if (isEmptyValue(value)) return;
|
|
15072
|
+
setSelectedId(matchPresetId(presets, value) ?? firstUnit);
|
|
15073
|
+
}, [firstUnit, presets, value]);
|
|
15074
|
+
const selectPreset = (preset) => {
|
|
15075
|
+
const nextUnit = preset.value;
|
|
15076
|
+
setSelectedId(nextUnit);
|
|
15077
|
+
onValueChange(createPeriodValue(nextUnit));
|
|
15078
|
+
};
|
|
15079
|
+
const updateInputValue = (nextValue) => {
|
|
15080
|
+
onValueChange({ unit: selectedUnit, value: nextValue });
|
|
15081
|
+
};
|
|
15082
|
+
const renderInput = () => {
|
|
15083
|
+
if (selectedUnit === "day") {
|
|
15084
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15085
|
+
SDatePicker,
|
|
15086
|
+
{
|
|
15087
|
+
value: typeof periodValue.value === "string" ? periodValue.value : null,
|
|
15088
|
+
onValueChange: updateInputValue,
|
|
15089
|
+
selectable: field.selectable,
|
|
15090
|
+
disabled,
|
|
15091
|
+
width: "100%"
|
|
15092
|
+
}
|
|
15093
|
+
);
|
|
15094
|
+
}
|
|
15095
|
+
if (selectedUnit === "month") {
|
|
15096
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15097
|
+
SDatePicker,
|
|
15098
|
+
{
|
|
15099
|
+
mode: "month",
|
|
15100
|
+
value: typeof periodValue.value === "string" ? periodValue.value : null,
|
|
15101
|
+
onValueChange: updateInputValue,
|
|
15102
|
+
selectable: field.selectable,
|
|
15103
|
+
disabled,
|
|
15104
|
+
width: "100%"
|
|
15105
|
+
}
|
|
15106
|
+
);
|
|
15107
|
+
}
|
|
15108
|
+
if (selectedUnit === "quarter") {
|
|
15109
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15110
|
+
SSelect2,
|
|
15111
|
+
{
|
|
15112
|
+
value: typeof periodValue.value === "number" ? periodValue.value : 1,
|
|
15113
|
+
onValueChange: updateInputValue,
|
|
15114
|
+
emitValue: true,
|
|
15115
|
+
disabled,
|
|
15116
|
+
width: "100%",
|
|
15117
|
+
options: [
|
|
15118
|
+
{ value: 1, label: "1\uBD84\uAE30" },
|
|
15119
|
+
{ value: 2, label: "2\uBD84\uAE30" },
|
|
15120
|
+
{ value: 3, label: "3\uBD84\uAE30" },
|
|
15121
|
+
{ value: 4, label: "4\uBD84\uAE30" }
|
|
15122
|
+
]
|
|
15123
|
+
}
|
|
15124
|
+
);
|
|
15125
|
+
}
|
|
15126
|
+
if (selectedUnit === "half") {
|
|
15127
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15128
|
+
SSelect2,
|
|
15129
|
+
{
|
|
15130
|
+
value: typeof periodValue.value === "string" ? periodValue.value : "first",
|
|
15131
|
+
onValueChange: updateInputValue,
|
|
15132
|
+
emitValue: true,
|
|
15133
|
+
disabled,
|
|
15134
|
+
width: "100%",
|
|
15135
|
+
options: [
|
|
15136
|
+
{ value: "first", label: "\uC0C1\uBC18\uAE30" },
|
|
15137
|
+
{ value: "second", label: "\uD558\uBC18\uAE30" }
|
|
15138
|
+
]
|
|
15139
|
+
}
|
|
15140
|
+
);
|
|
15141
|
+
}
|
|
15142
|
+
if (selectedUnit === "year") {
|
|
15143
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15144
|
+
SDatePicker,
|
|
15145
|
+
{
|
|
15146
|
+
mode: "year",
|
|
15147
|
+
value: typeof periodValue.value === "string" ? periodValue.value : null,
|
|
15148
|
+
onValueChange: updateInputValue,
|
|
15149
|
+
selectable: field.selectable,
|
|
15150
|
+
disabled,
|
|
15151
|
+
width: "100%"
|
|
15152
|
+
}
|
|
15153
|
+
);
|
|
15154
|
+
}
|
|
15155
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15156
|
+
SDateRangePicker,
|
|
15157
|
+
{
|
|
15158
|
+
value: Array.isArray(periodValue.value) && periodValue.value.length === 2 ? periodValue.value : null,
|
|
15159
|
+
onValueChange: updateInputValue,
|
|
15160
|
+
selectable: field.selectable,
|
|
15161
|
+
maxRange: field.maxRange,
|
|
15162
|
+
disabled,
|
|
15163
|
+
width: "100%"
|
|
15164
|
+
}
|
|
15165
|
+
);
|
|
15166
|
+
};
|
|
15167
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)]", children: [
|
|
15168
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-[8px]", children: presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
15169
|
+
SRadio,
|
|
15170
|
+
{
|
|
15171
|
+
val: preset.value,
|
|
15172
|
+
value: selectedId,
|
|
15173
|
+
label: preset.label,
|
|
15174
|
+
disabled,
|
|
15175
|
+
onValueChange: () => selectPreset(preset)
|
|
15176
|
+
},
|
|
15177
|
+
preset.value
|
|
15178
|
+
)) }),
|
|
15179
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, className: "h-px w-full", style: { background: CHIPFILTER.listboxBorder } }),
|
|
15180
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full [&>*]:w-full", children: renderInput() })
|
|
15181
|
+
] });
|
|
15182
|
+
}
|
|
14597
15183
|
function InlineDatePresetFilter({
|
|
14598
15184
|
field,
|
|
14599
15185
|
value,
|
|
@@ -15598,7 +16184,9 @@ var TIMEPICKER_SIZE_CONFIG = {
|
|
|
15598
16184
|
fontSize: 12,
|
|
15599
16185
|
lineHeight: 20,
|
|
15600
16186
|
minWidth: 80,
|
|
15601
|
-
fieldMinWidth: 128
|
|
16187
|
+
fieldMinWidth: 128,
|
|
16188
|
+
// 상한 등급 md
|
|
16189
|
+
fieldMaxWidth: 160
|
|
15602
16190
|
},
|
|
15603
16191
|
md: {
|
|
15604
16192
|
height: V3("md-height"),
|
|
@@ -15610,7 +16198,9 @@ var TIMEPICKER_SIZE_CONFIG = {
|
|
|
15610
16198
|
fontSize: 14,
|
|
15611
16199
|
lineHeight: 24,
|
|
15612
16200
|
minWidth: 96,
|
|
15613
|
-
fieldMinWidth: 160
|
|
16201
|
+
fieldMinWidth: 160,
|
|
16202
|
+
// 상한 등급 lg
|
|
16203
|
+
fieldMaxWidth: 240
|
|
15614
16204
|
}
|
|
15615
16205
|
};
|
|
15616
16206
|
function clampTimePart(value, min, max) {
|
|
@@ -15934,6 +16524,7 @@ function STimePicker({
|
|
|
15934
16524
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
15935
16525
|
width,
|
|
15936
16526
|
minWidth: dims.fieldMinWidth,
|
|
16527
|
+
maxWidth: dims.fieldMaxWidth,
|
|
15937
16528
|
disabled,
|
|
15938
16529
|
className,
|
|
15939
16530
|
style,
|
|
@@ -16050,6 +16641,10 @@ var MIDDAY_FIELD_MIN_WIDTH = {
|
|
|
16050
16641
|
sm: 178,
|
|
16051
16642
|
md: 216
|
|
16052
16643
|
};
|
|
16644
|
+
var MIDDAY_FIELD_MAX_WIDTH = {
|
|
16645
|
+
sm: 240,
|
|
16646
|
+
md: 240
|
|
16647
|
+
};
|
|
16053
16648
|
function RangeTimeSelector({
|
|
16054
16649
|
value,
|
|
16055
16650
|
useMeridiem,
|
|
@@ -16396,6 +16991,7 @@ function STimeRangePicker({
|
|
|
16396
16991
|
errorMessage: ruleError !== "" ? ruleError : errorMessage,
|
|
16397
16992
|
width,
|
|
16398
16993
|
minWidth: effectiveUseMeridiem ? MIDDAY_FIELD_MIN_WIDTH[size] : dims.fieldMinWidth,
|
|
16994
|
+
maxWidth: effectiveUseMeridiem ? MIDDAY_FIELD_MAX_WIDTH[size] : dims.fieldMaxWidth,
|
|
16399
16995
|
disabled,
|
|
16400
16996
|
className,
|
|
16401
16997
|
style,
|
|
@@ -16504,6 +17100,7 @@ exports.GNB_RAIL_WIDTH = GNB_RAIL_WIDTH;
|
|
|
16504
17100
|
exports.ICONS = ICONS;
|
|
16505
17101
|
exports.IMAGE_FITS = IMAGE_FITS;
|
|
16506
17102
|
exports.PAGE_BACKGROUNDS = PAGE_BACKGROUNDS;
|
|
17103
|
+
exports.PAGE_CONTENT_HEIGHTS = PAGE_CONTENT_HEIGHTS;
|
|
16507
17104
|
exports.RangeCalendar = RangeCalendar;
|
|
16508
17105
|
exports.SActionModal = SActionModal;
|
|
16509
17106
|
exports.SBadge = SBadge;
|
|
@@ -16520,6 +17117,8 @@ exports.SChipInput = SChipInput;
|
|
|
16520
17117
|
exports.SCircleProgress = SCircleProgress;
|
|
16521
17118
|
exports.SConfirmModal = SConfirmModal;
|
|
16522
17119
|
exports.SDatePicker = SDatePicker;
|
|
17120
|
+
exports.SDatePickerMonthListbox = SDatePickerMonthListbox;
|
|
17121
|
+
exports.SDatePickerYearListbox = SDatePickerYearListbox;
|
|
16523
17122
|
exports.SDateRangePicker = SDateRangePicker;
|
|
16524
17123
|
exports.SDivider = SDivider;
|
|
16525
17124
|
exports.SDraggableGroup = SDraggableGroup;
|