sellmate-design-system-react 9.0.0-beta.26 → 9.0.0-beta.27
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/dist/components/SChipFilter/README.md +10 -5
- package/dist/components/SChipFilter/SChipFilter.d.ts +8 -3
- package/dist/components/SGhostButton/README.md +0 -2
- package/dist/components/SSearchInput/README.md +2 -0
- package/dist/components/SSelect/README.md +1 -1
- package/dist/components/SSelect/SSelect.d.ts +1 -1
- package/dist/index.cjs +141 -85
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +141 -85
- package/dist/index.js.map +1 -1
- package/dist/lib/floating-height.d.ts +15 -0
- package/dist/llms-full.txt +11 -6
- package/dist/styles.css +0 -6
- package/package.json +1 -1
|
@@ -288,12 +288,17 @@ export interface SChipFilterFieldBase {
|
|
|
288
288
|
```ts
|
|
289
289
|
/** 프리셋으로 기간을 고르는 필터 — datepicker-range·datepicker-statistics */
|
|
290
290
|
export interface SChipFilterPresetsField extends SChipFilterFieldBase {
|
|
291
|
-
/** 프리셋 라디오 목록.
|
|
292
|
-
* datepicker-
|
|
291
|
+
/** 프리셋 라디오 목록. 지정하지 않으면 타입별 기본 목록을 쓴다 —
|
|
292
|
+
* datepicker-range: 오늘·지난 7일·지난 30일·사용자 지정,
|
|
293
|
+
* datepicker-statistics: 일별·월별·분기별·반기별·연도별·사용자 지정.
|
|
294
|
+
* 프리셋 라디오 없이 캘린더(datepicker-range) 하나만 두려면 presets: [] 를 명시한다 */
|
|
293
295
|
presets?: SChipFilterDatePreset[];
|
|
294
296
|
/** 선택 가능 범위 */
|
|
295
297
|
selectable?: [string, string];
|
|
296
|
-
/** "사용자 지정" 프리셋으로 기간을 고를 때의 최대 선택
|
|
298
|
+
/** "사용자 지정" 프리셋으로 기간을 고를 때의 최대 선택 일수.
|
|
299
|
+
* 지정하지 않아도 presets에 custom 프리셋이 있으면 기본 90일이 적용된다 — 무제한 기간
|
|
300
|
+
* 집계·조회로 백엔드에 과도한 요청이 가는 것을 막기 위한 안전장치. 다른 상한이 필요하면
|
|
301
|
+
* 이 값을 직접 지정한다 */
|
|
297
302
|
maxRange?: number;
|
|
298
303
|
}
|
|
299
304
|
```
|
|
@@ -350,10 +355,10 @@ export interface SChipFilterDatePreset {
|
|
|
350
355
|
|
|
351
356
|
- [SDatePicker](../SDatePicker)
|
|
352
357
|
- [SDateRangePicker](../SDateRangePicker)
|
|
353
|
-
- [SGhostButton](../SGhostButton)
|
|
354
358
|
- [SIcon](../SIcon)
|
|
355
359
|
- [SRadio](../SRadio)
|
|
356
360
|
- [SRadioButton](../SRadioButton)
|
|
361
|
+
- [SSearchInput](../SSearchInput)
|
|
357
362
|
- [STag](../STag)
|
|
358
363
|
- [STextLink](../STextLink)
|
|
359
364
|
- [STooltip](../STooltip)
|
|
@@ -364,10 +369,10 @@ export interface SChipFilterDatePreset {
|
|
|
364
369
|
graph TD;
|
|
365
370
|
SChipFilter --> SDatePicker
|
|
366
371
|
SChipFilter --> SDateRangePicker
|
|
367
|
-
SChipFilter --> SGhostButton
|
|
368
372
|
SChipFilter --> SIcon
|
|
369
373
|
SChipFilter --> SRadio
|
|
370
374
|
SChipFilter --> SRadioButton
|
|
375
|
+
SChipFilter --> SSearchInput
|
|
371
376
|
SChipFilter --> STag
|
|
372
377
|
SChipFilter --> STextLink
|
|
373
378
|
SChipFilter --> STooltip
|
|
@@ -75,12 +75,17 @@ export interface SChipFilterOptionsField extends SChipFilterFieldBase {
|
|
|
75
75
|
}
|
|
76
76
|
/** 프리셋으로 기간을 고르는 필터 — datepicker-range·datepicker-statistics */
|
|
77
77
|
export interface SChipFilterPresetsField extends SChipFilterFieldBase {
|
|
78
|
-
/** 프리셋 라디오 목록.
|
|
79
|
-
* datepicker-
|
|
78
|
+
/** 프리셋 라디오 목록. 지정하지 않으면 타입별 기본 목록을 쓴다 —
|
|
79
|
+
* datepicker-range: 오늘·지난 7일·지난 30일·사용자 지정,
|
|
80
|
+
* datepicker-statistics: 일별·월별·분기별·반기별·연도별·사용자 지정.
|
|
81
|
+
* 프리셋 라디오 없이 캘린더(datepicker-range) 하나만 두려면 presets: [] 를 명시한다 */
|
|
80
82
|
presets?: SChipFilterDatePreset[];
|
|
81
83
|
/** 선택 가능 범위 */
|
|
82
84
|
selectable?: [string, string];
|
|
83
|
-
/** "사용자 지정" 프리셋으로 기간을 고를 때의 최대 선택
|
|
85
|
+
/** "사용자 지정" 프리셋으로 기간을 고를 때의 최대 선택 일수.
|
|
86
|
+
* 지정하지 않아도 presets에 custom 프리셋이 있으면 기본 90일이 적용된다 — 무제한 기간
|
|
87
|
+
* 집계·조회로 백엔드에 과도한 요청이 가는 것을 막기 위한 안전장치. 다른 상한이 필요하면
|
|
88
|
+
* 이 값을 직접 지정한다 */
|
|
84
89
|
maxRange?: number;
|
|
85
90
|
}
|
|
86
91
|
/** 후보 하나를 고른다 */
|
|
@@ -48,7 +48,6 @@ export type SGhostButtonIntent = 'default' | 'danger' | 'action' | 'subAction' |
|
|
|
48
48
|
- [SBarcodeInput](../SBarcodeInput)
|
|
49
49
|
- [SCalendar](../SCalendar)
|
|
50
50
|
- [SChip](../SChip)
|
|
51
|
-
- [SChipFilter](../SChipFilter)
|
|
52
51
|
- [SDatePicker](../SDatePicker)
|
|
53
52
|
- [SDateRangePicker](../SDateRangePicker)
|
|
54
53
|
- [SFilePicker](../SFilePicker)
|
|
@@ -81,7 +80,6 @@ graph TD;
|
|
|
81
80
|
SBarcodeInput --> SGhostButton
|
|
82
81
|
SCalendar --> SGhostButton
|
|
83
82
|
SChip --> SGhostButton
|
|
84
|
-
SChipFilter --> SGhostButton
|
|
85
83
|
SDatePicker --> SGhostButton
|
|
86
84
|
SDateRangePicker --> SGhostButton
|
|
87
85
|
SFilePicker --> SGhostButton
|
|
@@ -41,6 +41,7 @@ export type SSearchInputSize = SFieldSize;
|
|
|
41
41
|
|
|
42
42
|
### Used by
|
|
43
43
|
|
|
44
|
+
- [SChipFilter](../SChipFilter)
|
|
44
45
|
- [SSelect](../SSelect)
|
|
45
46
|
|
|
46
47
|
### Depends on
|
|
@@ -56,6 +57,7 @@ graph TD;
|
|
|
56
57
|
SSearchInput --> SField
|
|
57
58
|
SSearchInput --> SGhostButton
|
|
58
59
|
SSearchInput --> SIcon
|
|
60
|
+
SChipFilter --> SSearchInput
|
|
59
61
|
SSelect --> SSearchInput
|
|
60
62
|
style SSearchInput fill:#f9f,stroke:#333,stroke-width:4px
|
|
61
63
|
```
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
| `error?` | `boolean` | `false` | 에러 상태 |
|
|
23
23
|
| `rules?` | `Rule[]` | — | 유효성 규칙 — 닫힐 때 자동 검증 |
|
|
24
24
|
| `labelTooltipProps?` | `Partial<STooltipProps>` | — | 레이블 툴팁 상세 옵션 |
|
|
25
|
-
| `dropdownHeight?` | `string` | `'
|
|
25
|
+
| `dropdownHeight?` | `string` | `'640px'` | 드롭다운 최대 높이. 기본 640px — 창이 이보다 작으면 창 안에 남는 만큼까지만 채워진다 |
|
|
26
26
|
| `dropdownWidth?` | `string` | — | 드롭다운 너비 (없으면 트리거 너비). 창보다 넓게 줘도 창 폭까지만 벌어진다. |
|
|
27
27
|
| `maxDropdownWidth?` | `string` | `'640px'` | 드롭다운 최대 너비. 창이 이보다 좁으면 창 폭이 상한이 된다. |
|
|
28
28
|
| `label?` | `string` | — | |
|
|
@@ -49,7 +49,7 @@ export interface SSelectProps {
|
|
|
49
49
|
rules?: Rule[];
|
|
50
50
|
/** 레이블 툴팁 상세 옵션 */
|
|
51
51
|
labelTooltipProps?: Partial<STooltipProps>;
|
|
52
|
-
/** 드롭다운 최대
|
|
52
|
+
/** 드롭다운 최대 높이. 기본 640px — 창이 이보다 작으면 창 안에 남는 만큼까지만 채워진다 */
|
|
53
53
|
dropdownHeight?: string;
|
|
54
54
|
/** 드롭다운 너비 (없으면 트리거 너비). 창보다 넓게 줘도 창 폭까지만 벌어진다. */
|
|
55
55
|
dropdownWidth?: string;
|
package/dist/index.cjs
CHANGED
|
@@ -10444,6 +10444,14 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
|
|
|
10444
10444
|
}
|
|
10445
10445
|
);
|
|
10446
10446
|
});
|
|
10447
|
+
|
|
10448
|
+
// src/lib/floating-height.ts
|
|
10449
|
+
var POPOVER_AVAILABLE_HEIGHT = "var(--radix-popover-content-available-height)";
|
|
10450
|
+
function clampToAvailableHeight(value, availableHeight) {
|
|
10451
|
+
if (value == null || value === "") return availableHeight;
|
|
10452
|
+
const css = typeof value === "number" ? `${value}px` : value;
|
|
10453
|
+
return `min(${css}, ${availableHeight})`;
|
|
10454
|
+
}
|
|
10447
10455
|
function runRules(value, rules) {
|
|
10448
10456
|
if (!rules || rules.length === 0) return "";
|
|
10449
10457
|
for (const rule of rules) {
|
|
@@ -10841,7 +10849,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
10841
10849
|
error = false,
|
|
10842
10850
|
rules,
|
|
10843
10851
|
labelTooltipProps,
|
|
10844
|
-
dropdownHeight = "
|
|
10852
|
+
dropdownHeight = "640px",
|
|
10845
10853
|
dropdownWidth,
|
|
10846
10854
|
maxDropdownWidth = "640px",
|
|
10847
10855
|
label,
|
|
@@ -11202,6 +11210,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
11202
11210
|
placement: "bottom",
|
|
11203
11211
|
align: "start",
|
|
11204
11212
|
offset: 4,
|
|
11213
|
+
viewportPadding: 24,
|
|
11205
11214
|
fit: !dropdownWidth,
|
|
11206
11215
|
onOpenAutoFocus: (event) => {
|
|
11207
11216
|
if (!showSearch) {
|
|
@@ -11234,7 +11243,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
11234
11243
|
SCROLLBAR_TRACK_BG_CLASS,
|
|
11235
11244
|
SCROLLBAR_TRACK_BORDER_CLASS
|
|
11236
11245
|
),
|
|
11237
|
-
style: { maxHeight: dropdownHeight },
|
|
11246
|
+
style: { maxHeight: clampToAvailableHeight(dropdownHeight, POPOVER_AVAILABLE_HEIGHT) },
|
|
11238
11247
|
onMouseLeave: () => setFocusedIndex(-1),
|
|
11239
11248
|
children: [
|
|
11240
11249
|
showSearch && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -17387,6 +17396,8 @@ var SEditor = /* @__PURE__ */ react.forwardRef(function SEditor2({
|
|
|
17387
17396
|
});
|
|
17388
17397
|
var CHIPFILTER_LISTBOX_WIDTH = 240;
|
|
17389
17398
|
var CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH = 246;
|
|
17399
|
+
var EDITOR_LISTBOX_MAX_HEIGHT = "min(640px, var(--radix-popover-content-available-height))";
|
|
17400
|
+
var EDITOR_POPOVER_VIEWPORT_PADDING = 24;
|
|
17390
17401
|
var CHIPFILTER = {
|
|
17391
17402
|
barBg: "var(--cmp-chipFilter-bar-bg)",
|
|
17392
17403
|
barBorder: "var(--cmp-chipFilter-bar-border)",
|
|
@@ -17426,6 +17437,7 @@ var CHIPFILTER = {
|
|
|
17426
17437
|
itemTextDefault: "var(--cmp-chipFilter-item-text-default)",
|
|
17427
17438
|
itemTextSelected: "var(--cmp-chipFilter-item-text-selected)"
|
|
17428
17439
|
};
|
|
17440
|
+
var DEFAULT_CUSTOM_MAX_RANGE = 90;
|
|
17429
17441
|
var DEFAULT_PERIOD_PRESETS = [
|
|
17430
17442
|
{ value: "day", label: "\uC77C\uBCC4" },
|
|
17431
17443
|
{ value: "month", label: "\uC6D4\uBCC4" },
|
|
@@ -17434,6 +17446,20 @@ var DEFAULT_PERIOD_PRESETS = [
|
|
|
17434
17446
|
{ value: "year", label: "\uC5F0\uB3C4\uBCC4" },
|
|
17435
17447
|
{ value: "custom", label: "\uC0AC\uC6A9\uC790 \uC9C0\uC815", custom: true }
|
|
17436
17448
|
];
|
|
17449
|
+
var DEFAULT_DATE_RANGE_PRESETS = [
|
|
17450
|
+
{ value: "today", label: "\uC624\uB298", resolve: () => todayIso() },
|
|
17451
|
+
{
|
|
17452
|
+
value: "last7",
|
|
17453
|
+
label: "\uC9C0\uB09C 7\uC77C",
|
|
17454
|
+
resolve: () => [addDaysIso(todayIso(), -7), todayIso()]
|
|
17455
|
+
},
|
|
17456
|
+
{
|
|
17457
|
+
value: "last30",
|
|
17458
|
+
label: "\uC9C0\uB09C 30\uC77C",
|
|
17459
|
+
resolve: () => [addDaysIso(todayIso(), -30), todayIso()]
|
|
17460
|
+
},
|
|
17461
|
+
{ value: "custom", label: "\uC0AC\uC6A9\uC790 \uC9C0\uC815", custom: true }
|
|
17462
|
+
];
|
|
17437
17463
|
var isKeywordValue = (value) => typeof value === "object" && value != null && !Array.isArray(value) && "keywords" in value;
|
|
17438
17464
|
var isPeriodValue = (value) => typeof value === "object" && value != null && !Array.isArray(value) && "unit" in value;
|
|
17439
17465
|
var keywordEntries = (value) => {
|
|
@@ -17458,23 +17484,39 @@ var todayIso = () => {
|
|
|
17458
17484
|
const pad = (n) => String(n).padStart(2, "0");
|
|
17459
17485
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
17460
17486
|
};
|
|
17487
|
+
var addDaysIso = (iso, n) => {
|
|
17488
|
+
const d = /* @__PURE__ */ new Date(`${iso}T00:00:00`);
|
|
17489
|
+
d.setDate(d.getDate() + n);
|
|
17490
|
+
const pad = (v) => String(v).padStart(2, "0");
|
|
17491
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
17492
|
+
};
|
|
17461
17493
|
var isInlineDateField = (field) => field.type === "datepicker-range" && field.radioButton === true && (field.presets?.length ?? 0) > 0;
|
|
17462
17494
|
var getFieldPresets = (field) => {
|
|
17463
17495
|
if (field.type === "datepicker-statistics") return field.presets ?? DEFAULT_PERIOD_PRESETS;
|
|
17464
|
-
return field.presets ??
|
|
17496
|
+
return field.presets ?? DEFAULT_DATE_RANGE_PRESETS;
|
|
17465
17497
|
};
|
|
17466
|
-
var
|
|
17498
|
+
var getEffectiveMaxRange = (field) => {
|
|
17499
|
+
if (field.maxRange !== void 0) return field.maxRange;
|
|
17500
|
+
const hasCustomPreset = getFieldPresets(field).some((preset) => preset.custom);
|
|
17501
|
+
return hasCustomPreset ? DEFAULT_CUSTOM_MAX_RANGE : void 0;
|
|
17502
|
+
};
|
|
17503
|
+
var getPresetLabel = (preset, maxRange) => {
|
|
17504
|
+
if (!preset.custom || !maxRange || preset.label.includes("\uCD5C\uB300")) return preset.label;
|
|
17505
|
+
return `${preset.label} (\uCD5C\uB300 ${maxRange}\uC77C\uC529)`;
|
|
17506
|
+
};
|
|
17507
|
+
var getDefaultPeriodInputValue = (unit, maxRange) => {
|
|
17467
17508
|
const today = todayIso();
|
|
17468
17509
|
if (unit === "day") return today;
|
|
17469
17510
|
if (unit === "month") return today.slice(0, 7);
|
|
17470
17511
|
if (unit === "quarter") return 1;
|
|
17471
17512
|
if (unit === "half") return "first";
|
|
17472
17513
|
if (unit === "year") return today.slice(0, 4);
|
|
17473
|
-
|
|
17514
|
+
const days = maxRange && maxRange > 0 ? maxRange : DEFAULT_CUSTOM_MAX_RANGE;
|
|
17515
|
+
return [addDaysIso(today, -days), today];
|
|
17474
17516
|
};
|
|
17475
|
-
var createPeriodValue = (unit) => ({
|
|
17517
|
+
var createPeriodValue = (unit, maxRange) => ({
|
|
17476
17518
|
unit,
|
|
17477
|
-
value: getDefaultPeriodInputValue(unit)
|
|
17519
|
+
value: getDefaultPeriodInputValue(unit, maxRange)
|
|
17478
17520
|
});
|
|
17479
17521
|
var resolveFieldDefault = (field) => {
|
|
17480
17522
|
if (field.defaultValue !== void 0 && isFixedField(field)) return field.defaultValue;
|
|
@@ -18023,6 +18065,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
18023
18065
|
side: "bottom",
|
|
18024
18066
|
align: "start",
|
|
18025
18067
|
sideOffset: 4,
|
|
18068
|
+
collisionPadding: EDITOR_POPOVER_VIEWPORT_PADDING,
|
|
18026
18069
|
onOpenAutoFocus: (event) => event.preventDefault(),
|
|
18027
18070
|
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
18028
18071
|
style: editorPopoverStyle,
|
|
@@ -18188,6 +18231,7 @@ function EditorPanel({
|
|
|
18188
18231
|
onClose
|
|
18189
18232
|
}) {
|
|
18190
18233
|
const wrapsInPaddedTop = field.type === "datepicker-day" || field.type === "datepicker-range" || field.type === "datepicker-statistics";
|
|
18234
|
+
const isScrollableListField = field.type === "select" || field.type === "select-multi" || field.type === "keyword";
|
|
18191
18235
|
const isMulti = field.type === "select-multi";
|
|
18192
18236
|
const selectableValues = isMulti ? (field.options ?? []).filter((option) => !option.disabled).map((option) => option.value) : [];
|
|
18193
18237
|
const selectedValues = isMulti ? toArrayValue(value) : [];
|
|
@@ -18197,7 +18241,7 @@ function EditorPanel({
|
|
|
18197
18241
|
allSelected ? selectedValues.filter((v) => !selectableValues.includes(v)) : [...selectedValues, ...selectableValues.filter((v) => !selectedValues.includes(v))]
|
|
18198
18242
|
);
|
|
18199
18243
|
};
|
|
18200
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(ListBox, { children: [
|
|
18244
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ListBox, { maxHeight: isScrollableListField ? EDITOR_LISTBOX_MAX_HEIGHT : void 0, children: [
|
|
18201
18245
|
wrapsInPaddedTop ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)] px-[var(--cmp-chipFilter-listbox-top-paddingX)] py-[var(--cmp-chipFilter-listbox-top-paddingY)]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
18202
18246
|
FilterEditor,
|
|
18203
18247
|
{
|
|
@@ -18220,7 +18264,7 @@ function EditorPanel({
|
|
|
18220
18264
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
18221
18265
|
"div",
|
|
18222
18266
|
{
|
|
18223
|
-
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)]",
|
|
18267
|
+
className: "flex shrink-0 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)]",
|
|
18224
18268
|
style: { borderColor: CHIPFILTER.listboxBorder },
|
|
18225
18269
|
children: [
|
|
18226
18270
|
isMulti && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -18335,6 +18379,7 @@ function DatePresetEditor({
|
|
|
18335
18379
|
onValueChange
|
|
18336
18380
|
}) {
|
|
18337
18381
|
const presets = getFieldPresets(field);
|
|
18382
|
+
const maxRange = getEffectiveMaxRange(field);
|
|
18338
18383
|
const [selectedId, setSelectedId] = react.useState(() => matchPresetId(presets, value));
|
|
18339
18384
|
const syncedInitialValueRef = react.useRef(!isEmptyValue(value));
|
|
18340
18385
|
react.useEffect(() => {
|
|
@@ -18345,7 +18390,13 @@ function DatePresetEditor({
|
|
|
18345
18390
|
const selectedPreset = presets.find((preset) => preset.value === selectedId);
|
|
18346
18391
|
const selectPreset = (preset) => {
|
|
18347
18392
|
setSelectedId(preset.value);
|
|
18348
|
-
if (!preset.custom)
|
|
18393
|
+
if (!preset.custom) {
|
|
18394
|
+
onValueChange(preset.resolve ? preset.resolve() : preset.value);
|
|
18395
|
+
return;
|
|
18396
|
+
}
|
|
18397
|
+
const today = todayIso();
|
|
18398
|
+
const days = maxRange && maxRange > 0 ? maxRange : DEFAULT_CUSTOM_MAX_RANGE;
|
|
18399
|
+
onValueChange([addDaysIso(today, -days), today]);
|
|
18349
18400
|
};
|
|
18350
18401
|
if (presets.length === 0) {
|
|
18351
18402
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -18354,7 +18405,7 @@ function DatePresetEditor({
|
|
|
18354
18405
|
value: Array.isArray(value) && value.length === 2 ? value : null,
|
|
18355
18406
|
onValueChange,
|
|
18356
18407
|
selectable: field.selectable,
|
|
18357
|
-
maxRange
|
|
18408
|
+
maxRange,
|
|
18358
18409
|
disabled,
|
|
18359
18410
|
width: "100%"
|
|
18360
18411
|
}
|
|
@@ -18366,7 +18417,7 @@ function DatePresetEditor({
|
|
|
18366
18417
|
{
|
|
18367
18418
|
val: preset.value,
|
|
18368
18419
|
value: selectedId,
|
|
18369
|
-
label: preset
|
|
18420
|
+
label: getPresetLabel(preset, maxRange),
|
|
18370
18421
|
disabled,
|
|
18371
18422
|
onValueChange: () => selectPreset(preset)
|
|
18372
18423
|
},
|
|
@@ -18378,7 +18429,7 @@ function DatePresetEditor({
|
|
|
18378
18429
|
value: Array.isArray(value) && value.length === 2 ? value : null,
|
|
18379
18430
|
onValueChange,
|
|
18380
18431
|
selectable: field.selectable,
|
|
18381
|
-
maxRange
|
|
18432
|
+
maxRange,
|
|
18382
18433
|
disabled
|
|
18383
18434
|
}
|
|
18384
18435
|
)
|
|
@@ -18391,9 +18442,10 @@ function PeriodPresetEditor({
|
|
|
18391
18442
|
onValueChange
|
|
18392
18443
|
}) {
|
|
18393
18444
|
const presets = getFieldPresets(field);
|
|
18445
|
+
const maxRange = getEffectiveMaxRange(field);
|
|
18394
18446
|
const firstUnit = presets.find((preset) => !preset.custom)?.value ?? "day";
|
|
18395
18447
|
const [selectedId, setSelectedId] = react.useState(() => matchPresetId(presets, value) ?? firstUnit);
|
|
18396
|
-
const periodValue = isPeriodValue(value) ? value : createPeriodValue(selectedId ?? firstUnit);
|
|
18448
|
+
const periodValue = isPeriodValue(value) ? value : createPeriodValue(selectedId ?? firstUnit, maxRange);
|
|
18397
18449
|
const selectedUnit = selectedId ?? periodValue.unit;
|
|
18398
18450
|
react.useEffect(() => {
|
|
18399
18451
|
if (isEmptyValue(value)) return;
|
|
@@ -18402,7 +18454,7 @@ function PeriodPresetEditor({
|
|
|
18402
18454
|
const selectPreset = (preset) => {
|
|
18403
18455
|
const nextUnit = preset.value;
|
|
18404
18456
|
setSelectedId(nextUnit);
|
|
18405
|
-
onValueChange(createPeriodValue(nextUnit));
|
|
18457
|
+
onValueChange(createPeriodValue(nextUnit, maxRange));
|
|
18406
18458
|
};
|
|
18407
18459
|
const updateInputValue = (nextValue) => {
|
|
18408
18460
|
onValueChange({ unit: selectedUnit, value: nextValue });
|
|
@@ -18485,7 +18537,7 @@ function PeriodPresetEditor({
|
|
|
18485
18537
|
value: Array.isArray(periodValue.value) && periodValue.value.length === 2 ? periodValue.value : null,
|
|
18486
18538
|
onValueChange: updateInputValue,
|
|
18487
18539
|
selectable: field.selectable,
|
|
18488
|
-
maxRange
|
|
18540
|
+
maxRange,
|
|
18489
18541
|
disabled,
|
|
18490
18542
|
width: "100%"
|
|
18491
18543
|
}
|
|
@@ -18497,7 +18549,7 @@ function PeriodPresetEditor({
|
|
|
18497
18549
|
{
|
|
18498
18550
|
val: preset.value,
|
|
18499
18551
|
value: selectedId,
|
|
18500
|
-
label: preset
|
|
18552
|
+
label: getPresetLabel(preset, maxRange),
|
|
18501
18553
|
disabled,
|
|
18502
18554
|
onValueChange: () => selectPreset(preset)
|
|
18503
18555
|
},
|
|
@@ -18709,7 +18761,7 @@ function KeywordEditor({
|
|
|
18709
18761
|
}
|
|
18710
18762
|
};
|
|
18711
18763
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
18712
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)] px-[var(--cmp-chipFilter-listbox-top-paddingX)] py-[var(--cmp-chipFilter-listbox-top-paddingY)]", children: [
|
|
18764
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 flex-col gap-[var(--cmp-chipFilter-listbox-top-gap)] px-[var(--cmp-chipFilter-listbox-top-paddingX)] py-[var(--cmp-chipFilter-listbox-top-paddingY)]", children: [
|
|
18713
18765
|
field.matchModes && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
18714
18766
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18715
18767
|
"span",
|
|
@@ -18751,7 +18803,7 @@ function KeywordEditor({
|
|
|
18751
18803
|
entries3.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18752
18804
|
"div",
|
|
18753
18805
|
{
|
|
18754
|
-
className: "
|
|
18806
|
+
className: "min-h-0 flex-1 overflow-auto border-t border-solid py-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
18755
18807
|
style: { borderColor: CHIPFILTER.listboxBorder },
|
|
18756
18808
|
children: entries3.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
18757
18809
|
KeywordEntryRow,
|
|
@@ -18809,6 +18861,7 @@ function OptionList({
|
|
|
18809
18861
|
const selected = multiple ? toArrayValue(value) : [];
|
|
18810
18862
|
const singleValue = !multiple && (typeof value === "string" || typeof value === "number") ? value : null;
|
|
18811
18863
|
const [search, setSearch] = react.useState("");
|
|
18864
|
+
const searchInputRef = react.useRef(null);
|
|
18812
18865
|
const options = field.options ?? [];
|
|
18813
18866
|
const showSearch = options.length >= OPTION_SEARCH_THRESHOLD;
|
|
18814
18867
|
const filteredOptions = react.useMemo(() => {
|
|
@@ -18816,74 +18869,70 @@ function OptionList({
|
|
|
18816
18869
|
const query = search.trim().toLowerCase();
|
|
18817
18870
|
return options.filter((option) => option.label.toLowerCase().includes(query));
|
|
18818
18871
|
}, [options, search, showSearch]);
|
|
18872
|
+
react.useEffect(() => {
|
|
18873
|
+
if (!showSearch || disabled) return;
|
|
18874
|
+
searchInputRef.current?.focus();
|
|
18875
|
+
}, [showSearch, disabled]);
|
|
18819
18876
|
if (options.length === 0) return /* @__PURE__ */ jsxRuntime.jsx(EmptyItem, { children: "\uD45C\uC2DC\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." });
|
|
18820
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18821
|
-
|
|
18822
|
-
|
|
18823
|
-
|
|
18824
|
-
"
|
|
18825
|
-
|
|
18826
|
-
|
|
18827
|
-
|
|
18828
|
-
children: [
|
|
18829
|
-
showSearch && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18830
|
-
"div",
|
|
18877
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [
|
|
18878
|
+
showSearch && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18879
|
+
"div",
|
|
18880
|
+
{
|
|
18881
|
+
className: "shrink-0 border-b border-solid px-[8px] pb-[4px] pt-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
18882
|
+
style: { borderColor: CHIPFILTER.listboxBorder },
|
|
18883
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
18884
|
+
SSearchInput,
|
|
18831
18885
|
{
|
|
18832
|
-
|
|
18833
|
-
|
|
18834
|
-
|
|
18835
|
-
|
|
18836
|
-
|
|
18837
|
-
|
|
18838
|
-
|
|
18839
|
-
|
|
18840
|
-
disabled,
|
|
18841
|
-
placeholder: "\uAC80\uC0C9",
|
|
18842
|
-
onChange: (event) => setSearch(event.target.value),
|
|
18843
|
-
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"
|
|
18844
|
-
}
|
|
18845
|
-
),
|
|
18846
|
-
search !== "" && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18847
|
-
SGhostButton,
|
|
18848
|
-
{
|
|
18849
|
-
icon: "close",
|
|
18850
|
-
size: "xxs",
|
|
18851
|
-
ariaLabel: "\uAC80\uC0C9\uC5B4 \uC9C0\uC6B0\uAE30",
|
|
18852
|
-
className: "flex-shrink-0",
|
|
18853
|
-
onClick: () => setSearch("")
|
|
18854
|
-
}
|
|
18855
|
-
)
|
|
18856
|
-
] })
|
|
18886
|
+
ref: searchInputRef,
|
|
18887
|
+
size: "sm",
|
|
18888
|
+
value: search,
|
|
18889
|
+
onValueChange: setSearch,
|
|
18890
|
+
disabled,
|
|
18891
|
+
placeholder: "\uAC80\uC0C9",
|
|
18892
|
+
clearable: true,
|
|
18893
|
+
width: "100%"
|
|
18857
18894
|
}
|
|
18895
|
+
)
|
|
18896
|
+
}
|
|
18897
|
+
),
|
|
18898
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
18899
|
+
"div",
|
|
18900
|
+
{
|
|
18901
|
+
className: cn(
|
|
18902
|
+
"min-h-0 flex-1 overflow-auto",
|
|
18903
|
+
!showSearch && "pt-[var(--cmp-chipFilter-listbox-list-paddingY)]",
|
|
18904
|
+
"pb-[var(--cmp-chipFilter-listbox-list-paddingY)]"
|
|
18858
18905
|
),
|
|
18859
|
-
|
|
18860
|
-
|
|
18861
|
-
|
|
18862
|
-
|
|
18863
|
-
|
|
18864
|
-
|
|
18865
|
-
|
|
18866
|
-
|
|
18867
|
-
|
|
18868
|
-
|
|
18869
|
-
|
|
18870
|
-
|
|
18871
|
-
|
|
18872
|
-
|
|
18873
|
-
|
|
18874
|
-
|
|
18906
|
+
children: [
|
|
18907
|
+
showSearch && filteredOptions.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(EmptyItem, { children: "\uAC80\uC0C9 \uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4." }),
|
|
18908
|
+
filteredOptions.map((option) => {
|
|
18909
|
+
const checked = multiple ? selected.includes(option.value) : singleValue === option.value;
|
|
18910
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18911
|
+
MenuItem,
|
|
18912
|
+
{
|
|
18913
|
+
selected: checked,
|
|
18914
|
+
disabled: disabled || option.disabled,
|
|
18915
|
+
multi: multiple,
|
|
18916
|
+
onClick: () => {
|
|
18917
|
+
if (multiple) {
|
|
18918
|
+
const next = checked ? selected.filter((v) => v !== option.value) : [...selected, option.value];
|
|
18919
|
+
onValueChange(next);
|
|
18920
|
+
} else {
|
|
18921
|
+
onValueChange(option.value);
|
|
18922
|
+
}
|
|
18923
|
+
},
|
|
18924
|
+
children: [
|
|
18925
|
+
multiple && /* @__PURE__ */ jsxRuntime.jsx(OptionCheckbox, { checked }),
|
|
18926
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: option.label })
|
|
18927
|
+
]
|
|
18875
18928
|
},
|
|
18876
|
-
|
|
18877
|
-
|
|
18878
|
-
|
|
18879
|
-
|
|
18880
|
-
|
|
18881
|
-
|
|
18882
|
-
|
|
18883
|
-
})
|
|
18884
|
-
]
|
|
18885
|
-
}
|
|
18886
|
-
);
|
|
18929
|
+
String(option.value)
|
|
18930
|
+
);
|
|
18931
|
+
})
|
|
18932
|
+
]
|
|
18933
|
+
}
|
|
18934
|
+
)
|
|
18935
|
+
] });
|
|
18887
18936
|
}
|
|
18888
18937
|
function OptionCheckbox({ checked }) {
|
|
18889
18938
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -18897,15 +18946,22 @@ function OptionCheckbox({ checked }) {
|
|
|
18897
18946
|
}
|
|
18898
18947
|
);
|
|
18899
18948
|
}
|
|
18900
|
-
function ListBox({
|
|
18949
|
+
function ListBox({
|
|
18950
|
+
children,
|
|
18951
|
+
maxHeight
|
|
18952
|
+
}) {
|
|
18901
18953
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18902
18954
|
"div",
|
|
18903
18955
|
{
|
|
18904
|
-
className:
|
|
18956
|
+
className: cn(
|
|
18957
|
+
"overflow-hidden border border-solid shadow-[var(--shadow-overlay)]",
|
|
18958
|
+
maxHeight && "flex flex-col"
|
|
18959
|
+
),
|
|
18905
18960
|
style: {
|
|
18906
18961
|
borderRadius: CHIPFILTER.listboxRadius,
|
|
18907
18962
|
background: CHIPFILTER.listboxBg,
|
|
18908
|
-
borderColor: CHIPFILTER.listboxBorder
|
|
18963
|
+
borderColor: CHIPFILTER.listboxBorder,
|
|
18964
|
+
maxHeight
|
|
18909
18965
|
},
|
|
18910
18966
|
children
|
|
18911
18967
|
}
|