sellmate-design-system-react 9.0.0-beta.10 → 9.0.0-beta.12
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 +3 -3
- package/dist/components/SBadge/README.md +24 -0
- package/dist/components/SBadge/SBadge.d.ts +1 -1
- package/dist/components/SBarcodeInput/README.md +8 -0
- package/dist/components/SButton/README.md +34 -0
- package/dist/components/SCalendar/README.md +13 -0
- package/dist/components/SCallout/README.md +15 -0
- package/dist/components/SCheckbox/README.md +8 -0
- package/dist/components/SChipFilter/README.md +276 -3
- package/dist/components/SChipFilter/SChipFilter.d.ts +78 -37
- package/dist/components/SChipFilter/index.d.ts +1 -1
- package/dist/components/SChipInput/README.md +14 -0
- package/dist/components/SCircleProgress/README.md +8 -0
- package/dist/components/SConfirmModal/README.md +16 -0
- package/dist/components/SDatePicker/README.md +14 -0
- package/dist/components/SDateRangePicker/README.md +14 -0
- package/dist/components/SDraggableItem/README.md +36 -0
- package/dist/components/SDraggableList/README.md +24 -0
- package/dist/components/SDrawer/README.md +8 -0
- package/dist/components/SDropdownButton/README.md +19 -0
- package/dist/components/SExpansionItem/README.md +36 -0
- package/dist/components/SField/README.md +20 -0
- package/dist/components/SFilePicker/README.md +14 -0
- package/dist/components/SFooter/README.md +21 -0
- package/dist/components/SForm/README.md +11 -0
- package/dist/components/SGhostButton/README.md +14 -2
- package/dist/components/SGnb/README.md +45 -0
- package/dist/components/SGuide/README.md +15 -0
- package/dist/components/SImage/README.md +14 -0
- package/dist/components/SKeyValueTable/README.md +83 -0
- package/dist/components/SLayout/README.md +16 -0
- package/dist/components/SLinearProgress/README.md +8 -0
- package/dist/components/SListItem/README.md +41 -0
- package/dist/components/SLoadingModal/README.md +8 -0
- package/dist/components/SNumberInput/README.md +8 -0
- package/dist/components/SPage/README.md +38 -0
- package/dist/components/SPopover/README.md +15 -0
- package/dist/components/SPopup/README.md +19 -0
- package/dist/components/SPortal/README.md +14 -0
- package/dist/components/SRadio/README.md +20 -0
- package/dist/components/SRadioButton/README.md +18 -0
- package/dist/components/SScrollArea/README.md +14 -0
- package/dist/components/SSearchInput/README.md +13 -0
- package/dist/components/SSectionHeaderCard/README.md +32 -0
- package/dist/components/SSelect/README.md +21 -2
- package/dist/components/SSplitter/README.md +15 -0
- package/dist/components/SStepper/README.md +26 -0
- package/dist/components/STable/README.md +103 -0
- package/dist/components/STabs/README.md +12 -0
- package/dist/components/STag/README.md +47 -0
- package/dist/components/STextLink/README.md +14 -0
- package/dist/components/STimePicker/README.md +14 -0
- package/dist/components/STimeRangePicker/README.md +26 -0
- package/dist/components/SToast/README.md +24 -0
- package/dist/components/SToggle/README.md +8 -0
- package/dist/components/STooltip/README.md +20 -0
- package/dist/components/STree/README.md +38 -0
- package/dist/index.cjs +170 -186
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +170 -186
- package/dist/index.js.map +1 -1
- package/dist/lib/story-docs.d.ts +19 -3
- package/dist/llms-full.txt +1444 -15
- package/dist/llms.txt +3 -3
- package/dist/styles.css +5 -16
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **대상**: 이 패키지로 화면을 만드는 소비 앱의 개발자와 AI 코딩 에이전트(Claude 등).
|
|
4
4
|
> 이 문서는 "무엇을 언제 쓰고, 무엇을 쓰면 안 되는지"의 단일 기준이다.
|
|
5
|
-
> 개별 컴포넌트의 상세 Props/Events는 `node_modules/sellmate-design-system-react/dist/components/<이름>/README.md` 를 참조한다.
|
|
5
|
+
> 개별 컴포넌트의 상세 Props/Events와 그 Props 가 쓰는 타입 정의(Types)는 `node_modules/sellmate-design-system-react/dist/components/<이름>/README.md` 를 참조한다.
|
|
6
6
|
|
|
7
7
|
## 0. 최우선 원칙 — 디자인 시스템 컴포넌트가 먼저다
|
|
8
8
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
### 0-1. 전체 컴포넌트 인덱스
|
|
22
22
|
|
|
23
|
-
무엇을 만들지 정했으면 **이 표에서 먼저 찾는다.** 상세 Props 는 `dist/components/<이름>/README.md` 참조.
|
|
23
|
+
무엇을 만들지 정했으면 **이 표에서 먼저 찾는다.** 상세 Props·Types 는 `dist/components/<이름>/README.md` 참조.
|
|
24
24
|
|
|
25
25
|
**이 표에서 어느 것을 골라야 할지 모르겠으면 §3-0 "의도 → 컴포넌트 라우팅" 으로 간다.** 하려는 일을 문장으로 찾으면 답이 하나 나온다 — 여기 인덱스는 "무엇이 있는지", §3-0 은 "언제 그걸 쓰는지" 를 담당한다.
|
|
26
26
|
|
|
@@ -1163,7 +1163,7 @@ const columns: STableColumn[] = [
|
|
|
1163
1163
|
- **기본은 `SKeyValueTable` 이다** (§4-2). 조건이 대여섯 개 이하로 고정이면 표로 펼쳐 두는 편이 한눈에 읽힌다.
|
|
1164
1164
|
- `SChipFilter` 는 조건을 **칩 한 줄**로 접고, "필터 추가" 로 필요한 것만 꺼내 쓰게 한다. 칩을 누르면 편집 팝오버가 열리고, 날짜는 프리셋(오늘·지난 7일·사용자 지정)으로 고른다. 조건 후보가 많은 목록 화면에서 필터가 화면을 세로로 잡아먹는 것을 막는 용도다.
|
|
1165
1165
|
- 검색 실행 시점이 다르다 — `SKeyValueTable` 필터는 앱이 검색 버튼을 직접 놓지만, `SChipFilter` 는 편집 팝오버가 닫히거나 "검색" 을 누를 때 `onSearch` 가 값 맵과 함께 호출된다. 값이 바뀌지 않았으면 호출되지 않는다.
|
|
1166
|
-
- 함께 걸어야 하는 조건(예: 기간 중 하나는 필수)이 있으면 `
|
|
1166
|
+
- **`fields` 는 항상 그룹 배열이다.** 묶을 것이 없어도 `[{ fields: [...] }]` 로 한 겹 감싼다. 함께 걸어야 하는 조건(예: 기간 중 하나는 필수)이 있으면 그 필드들만 별도 그룹으로 떼어 `rule` 을 준다 — 규칙을 못 채운 동안 경고 툴팁이 떠 있고 `onSearch` 가 막힌다. 그룹 앞 구분선은 `divider` 로 켠다. 검증 단위와 구분선은 별개라, 묶어서 검증만 하고 싶으면 `divider` 를 주지 않는다.
|
|
1167
1167
|
|
|
1168
1168
|
#### 3-7-12. 이미지 — SImage
|
|
1169
1169
|
|
|
@@ -10,6 +10,30 @@
|
|
|
10
10
|
|------|------|---------|-------------|
|
|
11
11
|
| `color?` | `SBadgeColor` | `'blue'` | 뱃지 색상 |
|
|
12
12
|
|
|
13
|
+
## Types
|
|
14
|
+
|
|
15
|
+
### SBadgeColor
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
export type SBadgeColor = (typeof BADGE_COLORS)[number];
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### BADGE_COLORS
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
export const BADGE_COLORS = [
|
|
25
|
+
'red',
|
|
26
|
+
'orange',
|
|
27
|
+
'yellow',
|
|
28
|
+
'green',
|
|
29
|
+
'lightblue',
|
|
30
|
+
'blue',
|
|
31
|
+
'darkblue',
|
|
32
|
+
'indigo',
|
|
33
|
+
'grey',
|
|
34
|
+
] as const;
|
|
35
|
+
```
|
|
36
|
+
|
|
13
37
|
## Dependencies
|
|
14
38
|
|
|
15
39
|
### Used by
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type HTMLAttributes } from 'react';
|
|
2
|
-
export declare const BADGE_COLORS: readonly ["red", "orange", "yellow", "green", "blue", "darkblue", "indigo", "grey"];
|
|
2
|
+
export declare const BADGE_COLORS: readonly ["red", "orange", "yellow", "green", "lightblue", "blue", "darkblue", "indigo", "grey"];
|
|
3
3
|
export type SBadgeColor = (typeof BADGE_COLORS)[number];
|
|
4
4
|
export interface SBadgeProps extends HTMLAttributes<HTMLSpanElement> {
|
|
5
5
|
/** 뱃지 색상 */
|
|
@@ -15,6 +15,40 @@
|
|
|
15
15
|
| `rightIcon?` | `SIconName` | — | 레이블 오른쪽 아이콘 |
|
|
16
16
|
| `label?` | `string` | — | 버튼 텍스트 (문자열만 — 아이콘은 icon/rightIcon 사용) |
|
|
17
17
|
|
|
18
|
+
## Types
|
|
19
|
+
|
|
20
|
+
### SButtonColor
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
export type SButtonColor = (typeof BUTTON_COLORS)[number];
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### SButtonSize
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
export type SButtonSize = (typeof BUTTON_SIZES)[number];
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### BUTTON_COLORS
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
/**
|
|
36
|
+
* SButton 색상/사이즈 설정 — sd-button(component.button 토큰) 충실 포팅.
|
|
37
|
+
* Stencil `name`(예: primary_sm)의 preset을 color + outline(boolean) + size 로 분리.
|
|
38
|
+
* - primary / danger : solid·outline 모두 지원
|
|
39
|
+
* - secondary : solid 전용 (outline 스타일 없음 → outline 무시)
|
|
40
|
+
* - neutral : 흰 배경 고정, outline 은 회색 테두리만 추가(solid = 테두리 없는 흰 버튼)
|
|
41
|
+
* 색상은 theme.css의 `--cmp-button-*` CSS 변수를 참조한다.
|
|
42
|
+
*/
|
|
43
|
+
export const BUTTON_COLORS = ['primary', 'secondary', 'neutral', 'danger'] as const;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### BUTTON_SIZES
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
export const BUTTON_SIZES = ['xs', 'sm', 'md', 'lg'] as const;
|
|
50
|
+
```
|
|
51
|
+
|
|
18
52
|
## Dependencies
|
|
19
53
|
|
|
20
54
|
### Used by
|
|
@@ -22,6 +22,19 @@
|
|
|
22
22
|
| `onValueChange` | `(date: string) => void` | 선택 변경 (sdUpdate) |
|
|
23
23
|
| `onViewChange` | `(v: { year: number; month: number }) => void` | 보이는 연·월 변경 (sdViewChange) |
|
|
24
24
|
|
|
25
|
+
## Types
|
|
26
|
+
|
|
27
|
+
### SCalendarEventGroup
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
export interface SCalendarEventGroup {
|
|
31
|
+
/** 도트 색상. 팔레트 키(`grey_65`, `red_95` …) 또는 임의 CSS 색상 */
|
|
32
|
+
color: SColor;
|
|
33
|
+
label: string;
|
|
34
|
+
dates: string[];
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
25
38
|
## Dependencies
|
|
26
39
|
|
|
27
40
|
### Used by
|
|
@@ -14,6 +14,21 @@
|
|
|
14
14
|
| `className?` | `string` | — | |
|
|
15
15
|
| `style?` | `CSSProperties` | — | |
|
|
16
16
|
|
|
17
|
+
## Types
|
|
18
|
+
|
|
19
|
+
### SCalloutType
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
export type SCalloutType = 'default' | 'danger';
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### SCalloutMessage
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
/** 중첩 메시지: 문자열 또는 (한 단계 더 들어간) 문자열 배열 */
|
|
29
|
+
export type SCalloutMessage = string | SCalloutMessage[];
|
|
30
|
+
```
|
|
31
|
+
|
|
17
32
|
## Dependencies
|
|
18
33
|
|
|
19
34
|
### Depends on
|
|
@@ -22,6 +22,14 @@
|
|
|
22
22
|
|-------|------|-------------|
|
|
23
23
|
| `onValueChange` | `(value: boolean \| unknown[]) => void` | 값 변경 (sdUpdate) |
|
|
24
24
|
|
|
25
|
+
## Types
|
|
26
|
+
|
|
27
|
+
### SCheckboxValue
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
export type SCheckboxValue = boolean | unknown[] | null;
|
|
31
|
+
```
|
|
32
|
+
|
|
25
33
|
## Dependencies
|
|
26
34
|
|
|
27
35
|
### Used by
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
| Prop | Type | Default | Description |
|
|
10
10
|
|------|------|---------|-------------|
|
|
11
|
-
| `fields?` | `
|
|
11
|
+
| `fields?` | `SChipFilterGroup[]` | — | 필터 정의 목록. 묶을 것이 없어도 한 그룹으로 감싸 넘긴다 — `[{ fields: [...] }]`. 그룹은 rule로 함께 검증하거나 divider로 갈라 놓을 때 나눈다. |
|
|
12
12
|
| `value?` | `SChipFilterValueMap` | — | 필터 값 맵 |
|
|
13
|
-
| `activeKeys?` | `string[]` | — | 노출 필터 key 목록. 지정하면 제어 컴포넌트로 동작 — "필터 추가"로 고른 필드를 이 배열에 직접 넣어줘야 칩이 나타난다(onActiveKeysChange에서 받은 keys로 갱신). 지정하지 않으면
|
|
13
|
+
| `activeKeys?` | `string[]` | — | 노출 필터 key 목록. 지정하면 제어 컴포넌트로 동작 — "필터 추가"로 고른 필드를 이 배열에 직접 넣어줘야 칩이 나타난다(onActiveKeysChange에서 받은 keys로 갱신). 지정하지 않으면 fixed·required 필드만 노출된 상태로 시작해 컴포넌트가 내부 상태로 관리하는 비제어 방식으로 동작한다. fixed·required 필드는 이 배열에 없어도 항상 노출된다 |
|
|
14
14
|
| `label?` | `string` | `'검색 필터'` | 좌측 태그 텍스트 |
|
|
15
15
|
| `showLabel?` | `boolean` | `false` | 좌측 태그(label)·구분선 표시 여부 |
|
|
16
16
|
| `showReset?` | `boolean` | `true` | 검색 초기화 링크 표시 여부 |
|
|
@@ -35,7 +35,280 @@
|
|
|
35
35
|
|--------|------|-------------|
|
|
36
36
|
| `open` | `(key: string) => void` | 특정 필터 편집 팝오버를 엽니다. |
|
|
37
37
|
| `reset` | `() => void` | 모든 필터 값을 초기화합니다. |
|
|
38
|
-
| `validate` | `() => boolean` |
|
|
38
|
+
| `validate` | `() => boolean` | 현재 값 기준으로 각 그룹의 rule을 만족하는지 반환합니다. rule을 준 그룹이 없으면 항상 true. 경고 툴팁은 이 호출과 무관하게 rule 위반 상태인 동안 항상 실시간으로 떠 있으므로, 이 메서드는 그 상태를 그대로 읽어오는 용도다(예: 검색 버튼을 눌러도 되는지 사전 확인) |
|
|
39
|
+
|
|
40
|
+
## Types
|
|
41
|
+
|
|
42
|
+
### SChipFilterGroup
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
/** fields를 이루는 단위. 묶을 것이 없어도 한 그룹으로 감싸 넘긴다 — `[{ fields: [...] }]` */
|
|
46
|
+
export interface SChipFilterGroup {
|
|
47
|
+
fields: SChipFilterField[];
|
|
48
|
+
/** 지정하면 이 규칙으로 그룹을 검증한다. values가 바뀔 때마다 즉시 재평가되는 실시간 검증이라 —
|
|
49
|
+
* 그룹이 rule을 만족하지 못하면 검색 시도 여부와 무관하게 그 즉시 그룹 중앙에 경고 툴팁이 뜬다.
|
|
50
|
+
* 지정 안 하면 검증하지 않는다. */
|
|
51
|
+
rule?: SChipFilterGroupRule;
|
|
52
|
+
/** rule을 만족하지 않을 때 그룹 중앙에 띄울 툴팁 메시지. 지정 안 하면 rule 종류에 따른 기본 문구를 쓴다 */
|
|
53
|
+
tooltipMessage?: string;
|
|
54
|
+
/** 이 그룹 앞에 구분선을 넣을지. 검증(rule)과 구분선은 별개라 — 묶어서 검증만 하고 싶으면
|
|
55
|
+
* 주지 않는다. 첫 그룹에는 앞에 가를 것이 없으므로 무시된다(showLabel의 구분선이 이미 있다) */
|
|
56
|
+
divider?: boolean;
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### SChipFilterValueMap
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
export type SChipFilterValueMap = Record<string, SChipFilterValue>;
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### SChipFilterChangeDetail
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
export interface SChipFilterChangeDetail {
|
|
70
|
+
key: string;
|
|
71
|
+
value: SChipFilterValue;
|
|
72
|
+
values: SChipFilterValueMap;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### SChipFilterField
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
/** 필터 하나의 정의. type에 따라 쓸 수 있는 속성이 달라진다 —
|
|
80
|
+
* options는 single·multi·keyword, presets·selectable·maxRange는 date·period,
|
|
81
|
+
* render는 custom 에만 있다 */
|
|
82
|
+
export type SChipFilterField =
|
|
83
|
+
| SChipFilterSingleField
|
|
84
|
+
| SChipFilterMultiField
|
|
85
|
+
| SChipFilterKeywordField
|
|
86
|
+
| SChipFilterDateField
|
|
87
|
+
| SChipFilterPeriodField
|
|
88
|
+
| SChipFilterCustomField;
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### SChipFilterGroupRule
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
/** 필터 그룹 검증 규칙 */
|
|
95
|
+
export type SChipFilterGroupRule =
|
|
96
|
+
| { type: 'requireKey'; key: string }
|
|
97
|
+
| { type: 'requireAll' }
|
|
98
|
+
| { type: 'requireAny'; dataGroupName?: string };
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### SChipFilterValue
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
export type SChipFilterValue =
|
|
105
|
+
| SChipFilterOptionValue
|
|
106
|
+
| SChipFilterOptionValue[]
|
|
107
|
+
| SDateRangeValue
|
|
108
|
+
| SChipFilterKeywordValue
|
|
109
|
+
| SChipFilterPeriodValue
|
|
110
|
+
| SChipFilterCustomValue
|
|
111
|
+
| null
|
|
112
|
+
| undefined;
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### SChipFilterSingleField
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
/** 후보 하나를 고른다 */
|
|
119
|
+
export interface SChipFilterSingleField extends SChipFilterOptionsField {
|
|
120
|
+
type: 'single';
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### SChipFilterMultiField
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
/** 후보 여럿을 고른다 */
|
|
128
|
+
export interface SChipFilterMultiField extends SChipFilterOptionsField {
|
|
129
|
+
type: 'multi';
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### SChipFilterKeywordField
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
/** 키워드를 입력해 누적한다. options는 입력 중 후보로만 뜬다 */
|
|
137
|
+
export interface SChipFilterKeywordField extends SChipFilterOptionsField {
|
|
138
|
+
type: 'keyword';
|
|
139
|
+
/** 입력 placeholder */
|
|
140
|
+
placeholder?: string;
|
|
141
|
+
/** 검색조건(포함/일치) 토글 표시 여부 */
|
|
142
|
+
matchModes?: boolean;
|
|
143
|
+
/** matchModes 활성 시 "미포함"까지 포함해 3개(포함/일치/미포함)로 노출할지.
|
|
144
|
+
* 기본 false — 2개(포함/일치)만 */
|
|
145
|
+
excludeMode?: boolean;
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### SChipFilterDateField
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
/** 날짜 하나 또는 기간을 고른다 */
|
|
153
|
+
export interface SChipFilterDateField extends SChipFilterPresetsField {
|
|
154
|
+
type: 'date';
|
|
155
|
+
/** presets 없이 단일 캘린더 트리거로 동작할 때의 placeholder */
|
|
156
|
+
placeholder?: string;
|
|
157
|
+
/** presets를 필터 바에 세그먼트 라디오로 펼쳐 놓는다(팝오버 없음).
|
|
158
|
+
* 기본 false — 칩 클릭 시 팝오버 안에 세로 라디오 목록(+사용자 지정 선택 시 기간 피커) */
|
|
159
|
+
radioButton?: boolean;
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### SChipFilterPeriodField
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
/** 집계 단위(일·월·분기·반기·연)와 그 단위의 값을 함께 고른다 */
|
|
167
|
+
export interface SChipFilterPeriodField extends SChipFilterPresetsField {
|
|
168
|
+
type: 'period';
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### SChipFilterCustomField
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
/** 칩+팝오버를 거치지 않고 바에 놓을 노드를 앱이 직접 그린다 */
|
|
176
|
+
export interface SChipFilterCustomField extends SChipFilterFieldBase {
|
|
177
|
+
type: 'custom';
|
|
178
|
+
/** 필터 바의 이 필드 자리에 놓일 노드를 직접 그린다. 반환한 노드가 그대로 바에 노출된다 —
|
|
179
|
+
* SSelect를 그대로 놓거나 SInput을 바로 노출하는 식으로 렌더 방식을 자유롭게 구성한다. */
|
|
180
|
+
render?: (ctx: {
|
|
181
|
+
value: SChipFilterValue;
|
|
182
|
+
disabled?: boolean;
|
|
183
|
+
warning?: boolean;
|
|
184
|
+
onValueChange: (value: SChipFilterValue) => void;
|
|
185
|
+
}) => ReactNode;
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### SChipFilterOptionValue
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
export type SChipFilterOptionValue = string | number;
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### SChipFilterKeywordValue
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
/** keyword 필드에서 matchModes 활성 시 사용하는 값 형태 — 입력해 추가한 키워드 목록 */
|
|
199
|
+
export interface SChipFilterKeywordValue {
|
|
200
|
+
keywords: string[];
|
|
201
|
+
mode: SChipFilterMatchMode;
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### SChipFilterPeriodValue
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
/** period 필드 값 — 선택 단위(unit)와 그 단위의 입력값(value)을 함께 보관한다 */
|
|
209
|
+
export interface SChipFilterPeriodValue {
|
|
210
|
+
unit: SChipFilterPeriodUnit;
|
|
211
|
+
value?: string | number | SDateRangeValue | null;
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### SChipFilterCustomValue
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
/** custom 필드가 자유롭게 담는 값. 형태를 강제하지 않는다 — render에서 직접 정의한 그대로 읽고 쓴다 */
|
|
219
|
+
export type SChipFilterCustomValue = Record<string, unknown>;
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### SChipFilterOptionsField
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
/** 후보 목록에서 고르는 필터 — single·multi·keyword */
|
|
226
|
+
export interface SChipFilterOptionsField extends SChipFilterFieldBase {
|
|
227
|
+
/** 고를 수 있는 후보 목록 */
|
|
228
|
+
options?: SChipFilterOption[];
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### SChipFilterPresetsField
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
/** 프리셋으로 기간을 고르는 필터 — date·period */
|
|
236
|
+
export interface SChipFilterPresetsField extends SChipFilterFieldBase {
|
|
237
|
+
/** 프리셋 라디오 목록. date에서 지정하지 않으면 단일 캘린더 트리거로 동작하고,
|
|
238
|
+
* period에서 지정하지 않으면 일별·월별·분기별·반기별·연도별·사용자 지정 기본 목록을 쓴다 */
|
|
239
|
+
presets?: SChipFilterDatePreset[];
|
|
240
|
+
/** 선택 가능 범위 */
|
|
241
|
+
selectable?: [string, string];
|
|
242
|
+
/** "사용자 지정" 프리셋으로 기간을 고를 때의 최대 선택 일수 */
|
|
243
|
+
maxRange?: number;
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### SChipFilterFieldBase
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
/** 타입과 무관하게 모든 필터가 갖는 속성 */
|
|
251
|
+
export interface SChipFilterFieldBase {
|
|
252
|
+
/** 필터 식별자 */
|
|
253
|
+
key: string;
|
|
254
|
+
/** 칩에 표시할 레이블 */
|
|
255
|
+
label: string;
|
|
256
|
+
/** 필수 필터 표시. true면 값이 비어 있을 때 기본값(defaultValue 또는 타입별 내장 기본값)이
|
|
257
|
+
* 자동으로 채워지고, clearable은 현재 값이 기본값과 같을 땐 숨겨지며 클릭 시 기본값으로 되돌아간다 */
|
|
258
|
+
required?: boolean;
|
|
259
|
+
/** 고정 필터. true면 activeKeys와 무관하게 항상 노출되고 "필터 추가" 목록에는 나타나지 않는다.
|
|
260
|
+
* required도 같은 효과를 낸다 — 처음부터 바에 보이는 것은 fixed이거나 required인 필드뿐이고,
|
|
261
|
+
* 나머지는 전부 "필터 추가"에서 골라야 나타난다 */
|
|
262
|
+
fixed?: boolean;
|
|
263
|
+
/** 초기값 및 clearable 클릭 시 되돌아갈 값. required 여부와 무관하게 적용된다 — 값이 비어 있으면
|
|
264
|
+
* 마운트(또는 "필터 추가"로 활성화) 시 이 값이 자동으로 채워진다. required인데 지정하지 않으면
|
|
265
|
+
* 타입별 내장 기본값(single: 첫 번째 옵션, date: 오늘 날짜)을 대신 쓴다 */
|
|
266
|
+
defaultValue?: SChipFilterValue;
|
|
267
|
+
/** 경고 테두리 표시. 바 전체를 잠그는 SChipFilterProps.disabled와 달리 이 필터에만 적용된다 */
|
|
268
|
+
warning?: boolean;
|
|
269
|
+
/** 이 필터만 비활성. 바에 남아 있되 팝오버가 열리지 않고 clearable도 눌리지 않는다.
|
|
270
|
+
* 바 전체를 잠그려면 SChipFilterProps.disabled를 쓴다 — 둘은 OR로 합쳐진다 */
|
|
271
|
+
disabled?: boolean;
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### SChipFilterMatchMode
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
export type SChipFilterMatchMode = 'contains' | 'exact' | 'excludes';
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### SChipFilterPeriodUnit
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
export type SChipFilterPeriodUnit = 'day' | 'month' | 'quarter' | 'half' | 'year' | 'custom';
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### SChipFilterOption
|
|
288
|
+
|
|
289
|
+
```ts
|
|
290
|
+
export interface SChipFilterOption {
|
|
291
|
+
value: SChipFilterOptionValue;
|
|
292
|
+
label: string;
|
|
293
|
+
disabled?: boolean;
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### SChipFilterDatePreset
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
/** date/period 필드의 프리셋 라디오 항목 (오늘/지난 7일/일별/월별/사용자 지정 등) */
|
|
301
|
+
export interface SChipFilterDatePreset {
|
|
302
|
+
/** 프리셋 식별자 */
|
|
303
|
+
value: string;
|
|
304
|
+
/** 라벨 */
|
|
305
|
+
label: string;
|
|
306
|
+
/** true면 "사용자 지정" — 선택 시 날짜/기간 피커가 추가로 노출된다. resolve는 무시된다. */
|
|
307
|
+
custom?: boolean;
|
|
308
|
+
/** custom이 아닐 때 실제 값을 계산한다. 단일 날짜(string) 또는 기간([start,end]) 모두 가능 */
|
|
309
|
+
resolve?: () => string | SDateRangeValue;
|
|
310
|
+
}
|
|
311
|
+
```
|
|
39
312
|
|
|
40
313
|
## Dependencies
|
|
41
314
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
2
|
import { type SDateRangeValue } from '../SDateRangePicker';
|
|
3
|
-
|
|
3
|
+
/** 필터가 값을 받는 방식. 각 값에 대응하는 필드 인터페이스가 따로 있다 —
|
|
4
|
+
* SChipFilterSingleField·SChipFilterMultiField·SChipFilterKeywordField·
|
|
5
|
+
* SChipFilterDateField·SChipFilterPeriodField·SChipFilterCustomField */
|
|
6
|
+
export type SChipFilterType = SChipFilterField['type'];
|
|
4
7
|
export type SChipFilterOptionValue = string | number;
|
|
5
8
|
export type SChipFilterMatchMode = 'contains' | 'exact' | 'excludes';
|
|
6
9
|
export type SChipFilterPeriodUnit = 'day' | 'month' | 'quarter' | 'half' | 'year' | 'custom';
|
|
@@ -34,51 +37,81 @@ export interface SChipFilterPeriodValue {
|
|
|
34
37
|
export type SChipFilterCustomValue = Record<string, unknown>;
|
|
35
38
|
export type SChipFilterValue = SChipFilterOptionValue | SChipFilterOptionValue[] | SDateRangeValue | SChipFilterKeywordValue | SChipFilterPeriodValue | SChipFilterCustomValue | null | undefined;
|
|
36
39
|
export type SChipFilterValueMap = Record<string, SChipFilterValue>;
|
|
37
|
-
|
|
40
|
+
/** 타입과 무관하게 모든 필터가 갖는 속성 */
|
|
41
|
+
export interface SChipFilterFieldBase {
|
|
38
42
|
/** 필터 식별자 */
|
|
39
43
|
key: string;
|
|
40
44
|
/** 칩에 표시할 레이블 */
|
|
41
45
|
label: string;
|
|
42
|
-
/** 필터 타입 */
|
|
43
|
-
type: SChipFilterType;
|
|
44
|
-
/** single/multi/keyword 후보 목록 */
|
|
45
|
-
options?: SChipFilterOption[];
|
|
46
46
|
/** 필수 필터 표시. true면 값이 비어 있을 때 기본값(defaultValue 또는 타입별 내장 기본값)이
|
|
47
47
|
* 자동으로 채워지고, clearable은 현재 값이 기본값과 같을 땐 숨겨지며 클릭 시 기본값으로 되돌아간다 */
|
|
48
48
|
required?: boolean;
|
|
49
|
-
/** 고정 필터. true면 activeKeys
|
|
50
|
-
|
|
49
|
+
/** 고정 필터. true면 activeKeys와 무관하게 항상 노출되고 "필터 추가" 목록에는 나타나지 않는다.
|
|
50
|
+
* required도 같은 효과를 낸다 — 처음부터 바에 보이는 것은 fixed이거나 required인 필드뿐이고,
|
|
51
|
+
* 나머지는 전부 "필터 추가"에서 골라야 나타난다 */
|
|
52
|
+
fixed?: boolean;
|
|
51
53
|
/** 초기값 및 clearable 클릭 시 되돌아갈 값. required 여부와 무관하게 적용된다 — 값이 비어 있으면
|
|
52
54
|
* 마운트(또는 "필터 추가"로 활성화) 시 이 값이 자동으로 채워진다. required인데 지정하지 않으면
|
|
53
55
|
* 타입별 내장 기본값(single: 첫 번째 옵션, date: 오늘 날짜)을 대신 쓴다 */
|
|
54
56
|
defaultValue?: SChipFilterValue;
|
|
55
|
-
/** 경고 테두리
|
|
57
|
+
/** 경고 테두리 표시. 바 전체를 잠그는 SChipFilterProps.disabled와 달리 이 필터에만 적용된다 */
|
|
56
58
|
warning?: boolean;
|
|
57
|
-
/**
|
|
59
|
+
/** 이 필터만 비활성. 바에 남아 있되 팝오버가 열리지 않고 clearable도 눌리지 않는다.
|
|
60
|
+
* 바 전체를 잠그려면 SChipFilterProps.disabled를 쓴다 — 둘은 OR로 합쳐진다 */
|
|
58
61
|
disabled?: boolean;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
}
|
|
63
|
+
/** 후보 목록에서 고르는 필터 — single·multi·keyword */
|
|
64
|
+
export interface SChipFilterOptionsField extends SChipFilterFieldBase {
|
|
65
|
+
/** 고를 수 있는 후보 목록 */
|
|
66
|
+
options?: SChipFilterOption[];
|
|
67
|
+
}
|
|
68
|
+
/** 프리셋으로 기간을 고르는 필터 — date·period */
|
|
69
|
+
export interface SChipFilterPresetsField extends SChipFilterFieldBase {
|
|
70
|
+
/** 프리셋 라디오 목록. date에서 지정하지 않으면 단일 캘린더 트리거로 동작하고,
|
|
71
|
+
* period에서 지정하지 않으면 일별·월별·분기별·반기별·연도별·사용자 지정 기본 목록을 쓴다 */
|
|
72
|
+
presets?: SChipFilterDatePreset[];
|
|
73
|
+
/** 선택 가능 범위 */
|
|
74
|
+
selectable?: [string, string];
|
|
75
|
+
/** "사용자 지정" 프리셋으로 기간을 고를 때의 최대 선택 일수 */
|
|
76
|
+
maxRange?: number;
|
|
77
|
+
}
|
|
78
|
+
/** 후보 하나를 고른다 */
|
|
79
|
+
export interface SChipFilterSingleField extends SChipFilterOptionsField {
|
|
80
|
+
type: 'single';
|
|
81
|
+
}
|
|
82
|
+
/** 후보 여럿을 고른다 */
|
|
83
|
+
export interface SChipFilterMultiField extends SChipFilterOptionsField {
|
|
84
|
+
type: 'multi';
|
|
85
|
+
}
|
|
86
|
+
/** 키워드를 입력해 누적한다. options는 입력 중 후보로만 뜬다 */
|
|
87
|
+
export interface SChipFilterKeywordField extends SChipFilterOptionsField {
|
|
88
|
+
type: 'keyword';
|
|
89
|
+
/** 입력 placeholder */
|
|
64
90
|
placeholder?: string;
|
|
65
|
-
/**
|
|
91
|
+
/** 검색조건(포함/일치) 토글 표시 여부 */
|
|
66
92
|
matchModes?: boolean;
|
|
67
|
-
/** matchModes 활성 시 "미포함"까지 포함해 3개(포함/일치/미포함)로 노출할지.
|
|
93
|
+
/** matchModes 활성 시 "미포함"까지 포함해 3개(포함/일치/미포함)로 노출할지.
|
|
94
|
+
* 기본 false — 2개(포함/일치)만 */
|
|
68
95
|
excludeMode?: boolean;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
|
|
75
|
-
presets
|
|
76
|
-
|
|
77
|
-
* false(기본): 칩 클릭 시 팝오버 안에 세로 라디오 목록(+사용자 지정 선택 시 기간 피커) */
|
|
96
|
+
}
|
|
97
|
+
/** 날짜 하나 또는 기간을 고른다 */
|
|
98
|
+
export interface SChipFilterDateField extends SChipFilterPresetsField {
|
|
99
|
+
type: 'date';
|
|
100
|
+
/** presets 없이 단일 캘린더 트리거로 동작할 때의 placeholder */
|
|
101
|
+
placeholder?: string;
|
|
102
|
+
/** presets를 필터 바에 세그먼트 라디오로 펼쳐 놓는다(팝오버 없음).
|
|
103
|
+
* 기본 false — 칩 클릭 시 팝오버 안에 세로 라디오 목록(+사용자 지정 선택 시 기간 피커) */
|
|
78
104
|
radioButton?: boolean;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
105
|
+
}
|
|
106
|
+
/** 집계 단위(일·월·분기·반기·연)와 그 단위의 값을 함께 고른다 */
|
|
107
|
+
export interface SChipFilterPeriodField extends SChipFilterPresetsField {
|
|
108
|
+
type: 'period';
|
|
109
|
+
}
|
|
110
|
+
/** 칩+팝오버를 거치지 않고 바에 놓을 노드를 앱이 직접 그린다 */
|
|
111
|
+
export interface SChipFilterCustomField extends SChipFilterFieldBase {
|
|
112
|
+
type: 'custom';
|
|
113
|
+
/** 필터 바의 이 필드 자리에 놓일 노드를 직접 그린다. 반환한 노드가 그대로 바에 노출된다 —
|
|
114
|
+
* SSelect를 그대로 놓거나 SInput을 바로 노출하는 식으로 렌더 방식을 자유롭게 구성한다. */
|
|
82
115
|
render?: (ctx: {
|
|
83
116
|
value: SChipFilterValue;
|
|
84
117
|
disabled?: boolean;
|
|
@@ -86,6 +119,10 @@ export interface SChipFilterField {
|
|
|
86
119
|
onValueChange: (value: SChipFilterValue) => void;
|
|
87
120
|
}) => ReactNode;
|
|
88
121
|
}
|
|
122
|
+
/** 필터 하나의 정의. type에 따라 쓸 수 있는 속성이 달라진다 —
|
|
123
|
+
* options는 single·multi·keyword, presets·selectable·maxRange는 date·period,
|
|
124
|
+
* render는 custom 에만 있다 */
|
|
125
|
+
export type SChipFilterField = SChipFilterSingleField | SChipFilterMultiField | SChipFilterKeywordField | SChipFilterDateField | SChipFilterPeriodField | SChipFilterCustomField;
|
|
89
126
|
export interface SChipFilterChangeDetail {
|
|
90
127
|
key: string;
|
|
91
128
|
value: SChipFilterValue;
|
|
@@ -101,7 +138,7 @@ export type SChipFilterGroupRule = {
|
|
|
101
138
|
type: 'requireAny';
|
|
102
139
|
dataGroupName?: string;
|
|
103
140
|
};
|
|
104
|
-
/**
|
|
141
|
+
/** fields를 이루는 단위. 묶을 것이 없어도 한 그룹으로 감싸 넘긴다 — `[{ fields: [...] }]` */
|
|
105
142
|
export interface SChipFilterGroup {
|
|
106
143
|
fields: SChipFilterField[];
|
|
107
144
|
/** 지정하면 이 규칙으로 그룹을 검증한다. values가 바뀔 때마다 즉시 재평가되는 실시간 검증이라 —
|
|
@@ -110,21 +147,24 @@ export interface SChipFilterGroup {
|
|
|
110
147
|
rule?: SChipFilterGroupRule;
|
|
111
148
|
/** rule을 만족하지 않을 때 그룹 중앙에 띄울 툴팁 메시지. 지정 안 하면 rule 종류에 따른 기본 문구를 쓴다 */
|
|
112
149
|
tooltipMessage?: string;
|
|
150
|
+
/** 이 그룹 앞에 구분선을 넣을지. 검증(rule)과 구분선은 별개라 — 묶어서 검증만 하고 싶으면
|
|
151
|
+
* 주지 않는다. 첫 그룹에는 앞에 가를 것이 없으므로 무시된다(showLabel의 구분선이 이미 있다) */
|
|
152
|
+
divider?: boolean;
|
|
113
153
|
}
|
|
114
154
|
export interface SChipFilterHandle {
|
|
115
155
|
/** 특정 필터 편집 팝오버를 엽니다. */
|
|
116
156
|
open: (key: string) => void;
|
|
117
157
|
/** 모든 필터 값을 초기화합니다. */
|
|
118
158
|
reset: () => void;
|
|
119
|
-
/**
|
|
120
|
-
*
|
|
159
|
+
/** 현재 값 기준으로 각 그룹의 rule을 만족하는지 반환합니다. rule을 준 그룹이 없으면 항상 true.
|
|
160
|
+
* 경고 툴팁은 이 호출과 무관하게 rule 위반 상태인 동안 항상 실시간으로 떠 있으므로,
|
|
121
161
|
* 이 메서드는 그 상태를 그대로 읽어오는 용도다(예: 검색 버튼을 눌러도 되는지 사전 확인) */
|
|
122
162
|
validate: () => boolean;
|
|
123
163
|
}
|
|
124
164
|
export interface SChipFilterProps {
|
|
125
|
-
/** 필터 정의 목록. 그룹으로
|
|
126
|
-
*
|
|
127
|
-
fields?:
|
|
165
|
+
/** 필터 정의 목록. 묶을 것이 없어도 한 그룹으로 감싸 넘긴다 — `[{ fields: [...] }]`.
|
|
166
|
+
* 그룹은 rule로 함께 검증하거나 divider로 갈라 놓을 때 나눈다. */
|
|
167
|
+
fields?: SChipFilterGroup[];
|
|
128
168
|
/** 필터 값 맵 */
|
|
129
169
|
value?: SChipFilterValueMap;
|
|
130
170
|
/** 전체 값 변경 — 편집 중인 값이 바뀔 때마다(선택할 때마다) 호출된다. 실제 검색 실행은 onSearch를 쓴다 */
|
|
@@ -140,8 +180,9 @@ export interface SChipFilterProps {
|
|
|
140
180
|
* 실시간으로 떠 있다(별도로 validate()를 호출할 필요 없음) */
|
|
141
181
|
onSearch?: (value: SChipFilterValueMap) => void;
|
|
142
182
|
/** 노출 필터 key 목록. 지정하면 제어 컴포넌트로 동작 — "필터 추가"로 고른 필드를 이 배열에 직접
|
|
143
|
-
* 넣어줘야 칩이 나타난다(onActiveKeysChange에서 받은 keys로 갱신). 지정하지 않으면
|
|
144
|
-
*
|
|
183
|
+
* 넣어줘야 칩이 나타난다(onActiveKeysChange에서 받은 keys로 갱신). 지정하지 않으면
|
|
184
|
+
* fixed·required 필드만 노출된 상태로 시작해 컴포넌트가 내부 상태로 관리하는 비제어 방식으로
|
|
185
|
+
* 동작한다. fixed·required 필드는 이 배열에 없어도 항상 노출된다 */
|
|
145
186
|
activeKeys?: string[];
|
|
146
187
|
/** 노출 필터 key 변경(칩 추가·제거) — 비제어 방식에서도 참고용으로 호출된다.
|
|
147
188
|
* activeKeys를 직접 제어할 때는 이 값을 그대로 activeKeys에 반영해야 한다 */
|