@makitt.io/mds-mcp-server 0.1.3 → 0.2.1
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/README.md +151 -34
- package/dist/catalog.d.ts +16 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +383 -0
- package/dist/catalog.js.map +1 -0
- package/dist/data/catalog.json +41955 -4439
- package/dist/data/playbook/ai-fill.md +61 -48
- package/dist/data/playbook/anti-patterns.md +112 -110
- package/dist/data/playbook/array-input.md +94 -49
- package/dist/data/playbook/async-states.md +71 -61
- package/dist/data/playbook/data-grid.md +118 -101
- package/dist/data/playbook/feedback.md +103 -84
- package/dist/data/playbook/form.md +164 -134
- package/dist/data/playbook/overlay.md +97 -88
- package/dist/data/playbook/page-layout.md +95 -76
- package/dist/data/playbook/responsive-tokens.md +77 -58
- package/dist/data/recipes/admin-list-page.md +86 -0
- package/dist/data/recipes/async-state-section.md +60 -0
- package/dist/data/recipes/dashboard-overview.md +65 -0
- package/dist/data/recipes/detail-drawer.md +69 -0
- package/dist/data/recipes/modal-form.md +67 -0
- package/dist/data/recipes/settings-form-page.md +79 -0
- package/dist/index.d.ts +4 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -338
- package/dist/index.js.map +1 -1
- package/dist/loaders.d.ts +8 -0
- package/dist/loaders.d.ts.map +1 -0
- package/dist/loaders.js +120 -0
- package/dist/loaders.js.map +1 -0
- package/dist/recipes.d.ts +13 -0
- package/dist/recipes.d.ts.map +1 -0
- package/dist/recipes.js +82 -0
- package/dist/recipes.js.map +1 -0
- package/dist/responses.d.ts +8 -0
- package/dist/responses.d.ts.map +1 -0
- package/dist/responses.js +25 -0
- package/dist/responses.js.map +1 -0
- package/dist/text.d.ts +4 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +20 -0
- package/dist/text.js.map +1 -0
- package/dist/tool-definitions.d.ts +3 -0
- package/dist/tool-definitions.d.ts.map +1 -0
- package/dist/tool-definitions.js +199 -0
- package/dist/tool-definitions.js.map +1 -0
- package/dist/tools.d.ts +4 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +233 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +107 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +21 -16
|
@@ -5,17 +5,33 @@
|
|
|
5
5
|
> 인용 컴포넌트는 모두 `packages/mds/src/` 에 실재 — fabrication 0. 임의 룰은
|
|
6
6
|
> **TBD** 명시 — 사용자 합의 후 결정.
|
|
7
7
|
|
|
8
|
+
## Scope
|
|
9
|
+
|
|
10
|
+
이 문서는 **MDS component usage** 를 정한다.
|
|
11
|
+
|
|
12
|
+
- 컨테이너: page-form / drawer-form / modal-form
|
|
13
|
+
- 배치: vertical stack / 2-col pair / Section + AnchorNav
|
|
14
|
+
- 필드: `Field` compound + input component mapping
|
|
15
|
+
- 피드백: `Field.Error` / `Banner` / `toast` / `Notification`
|
|
16
|
+
- 기본 form library guidance: simple/medium form 은 RHF + Zod 기본/권장
|
|
17
|
+
|
|
18
|
+
도메인 form architecture 는 각 app 의 playbook 이 정한다. MDS 는 UI/a11y/layout
|
|
19
|
+
contract 를 강제하고, state model 은 강제하지 않는다. 단, RHF + Zod 가
|
|
20
|
+
기본값이다. 커스텀 store/reducer 는 RHF 로 표현하면 도메인 모델을 왜곡하거나
|
|
21
|
+
기존 동작을 깨는 경우에만 허용하고, 그 사유와 adapter contract 를 app playbook
|
|
22
|
+
에 명시해야 한다.
|
|
23
|
+
|
|
8
24
|
---
|
|
9
25
|
|
|
10
26
|
## 1. 컨테이너 결정
|
|
11
27
|
|
|
12
|
-
| 상황
|
|
13
|
-
|
|
14
|
-
| 페이지 본문 메인 작업 (상품 생성/수정, 설정 페이지)
|
|
15
|
-
| 목록 화면 옆에서 행 1개 부분 편집 (이름·상태 빠른 수정) | **drawer-form** (`Drawer` 안 Form)
|
|
16
|
-
| 짧은 입력 (필드 ≤ 5 · 확인성 액션, 쿠폰 발급)
|
|
17
|
-
| 메인 form 안 sub-entity 편집 (variant 추가)
|
|
18
|
-
| 단순 확인 ("정말 삭제?")
|
|
28
|
+
| 상황 | 컨테이너 | 이유 | Mobile 변형 |
|
|
29
|
+
| ------------------------------------------------------- | ---------------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------- |
|
|
30
|
+
| 페이지 본문 메인 작업 (상품 생성/수정, 설정 페이지) | **page-form** (`Page` shell 안 직접 Form) | 본업 — 가장 큰 공간 | Sidebar → drawer, content full-width, sticky action bar bottom |
|
|
31
|
+
| 목록 화면 옆에서 행 1개 부분 편집 (이름·상태 빠른 수정) | **drawer-form** (`Drawer` 안 Form) | 목록 컨텍스트 유지 + side-by-side | `Drawer side="bottom"` (Sheet style) |
|
|
32
|
+
| 짧은 입력 (필드 ≤ 5 · 확인성 액션, 쿠폰 발급) | **modal-form** (`Modal` 안 Form) | 짧은 입력 + 강제 집중. 5 초과면 page 또는 drawer 로 | `Modal` → full-screen Sheet |
|
|
33
|
+
| 메인 form 안 sub-entity 편집 (variant 추가) | **nested drawer-form** (메인 form 살아있는 채 Drawer 오픈) | nested modal 보다 mental stack 얕음 | 동일 — Drawer 가 적합 |
|
|
34
|
+
| 단순 확인 ("정말 삭제?") | **`Dialog` (confirm)** — Form 아님 | input 없음, action 만 | `Modal.confirm` 그대로 |
|
|
19
35
|
|
|
20
36
|
### 절대 금지
|
|
21
37
|
|
|
@@ -26,47 +42,52 @@
|
|
|
26
42
|
|
|
27
43
|
## 2. Form 안 input 배치 — Section 개수 기준 + caller 재량
|
|
28
44
|
|
|
29
|
-
| 패턴
|
|
30
|
-
|
|
31
|
-
| **vertical stack** (단일 column) | **1 section** (단일 의미 단위)
|
|
32
|
-
| **2-col pair** (horizontal grid) | 의미상 쌍 (시작-종료, 가로-세로, 이름-이메일) — section 내부 또는 단독 | 주소 입력 (이름&이메일 가로 / 도시&우편 가로)
|
|
33
|
-
| **Section + AnchorNav**
|
|
34
|
-
| **2-5 section**
|
|
45
|
+
| 패턴 | 사용 시점 | 예시 | Mobile 변형 |
|
|
46
|
+
| -------------------------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------- | -------------------------------------- |
|
|
47
|
+
| **vertical stack** (단일 column) | **1 section** (단일 의미 단위) | 회원가입, 단순 modal-form (쿠폰 발급), 단일 entity 의 simple form | 그대로 |
|
|
48
|
+
| **2-col pair** (horizontal grid) | 의미상 쌍 (시작-종료, 가로-세로, 이름-이메일) — section 내부 또는 단독 | 주소 입력 (이름&이메일 가로 / 도시&우편 가로) | 1-col vertical |
|
|
49
|
+
| **Section + AnchorNav** | **6+ section** (큰 form, 의미 단위 분명) | 상품 등록 (9 section), 큰 설정 페이지 | AnchorNav → drawer (좌측 sidebar 모드) |
|
|
50
|
+
| **2-5 section** | 의미 단위 명확 시 vertical or 2-col pair — caller 재량 | 정책 편집 (3 section), 사용자 프로필 (4 section) | 그대로 또는 1-col |
|
|
35
51
|
|
|
36
|
-
> **결정 근거** — Section 개수가 form 의 정신적 무게의 진짜 기준. 필드 수보다
|
|
37
|
-
> 동일 9 필드라도 1 section (단순 form) vs 6 section (복잡 form)
|
|
52
|
+
> **결정 근거** — Section 개수가 form 의 정신적 무게의 진짜 기준. 필드 수보다
|
|
53
|
+
> 의미 단위 분명. 동일 9 필드라도 1 section (단순 form) vs 6 section (복잡 form)
|
|
54
|
+
> 의 UX 가 다름.
|
|
38
55
|
|
|
39
56
|
---
|
|
40
57
|
|
|
41
58
|
## 3. Field 타입 매핑 (데이터 → MDS 컴포넌트)
|
|
42
59
|
|
|
43
|
-
> 모든 컴포넌트 `packages/mds/src/primitives/inputs/` + `compounds/` 실재
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
| 단일 선택 (
|
|
53
|
-
|
|
|
54
|
-
| 다중 선택 (
|
|
55
|
-
|
|
|
56
|
-
| boolean
|
|
57
|
-
|
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
60
|
+
> 모든 컴포넌트 `packages/mds/src/primitives/inputs/` + `compounds/` 실재
|
|
61
|
+
> 검증됨.
|
|
62
|
+
|
|
63
|
+
| 데이터 형태 | MDS 컴포넌트 | 비고 |
|
|
64
|
+
| -------------------------- | --------------------------------------------- | ------------------------------------------------------------------------- |
|
|
65
|
+
| 짧은 문자열 (이름, 슬러그) | `TextField` | |
|
|
66
|
+
| 긴 문자열 (설명, 메모) | `Textarea` | |
|
|
67
|
+
| 리치 텍스트 (블로그 본문) | `RichText` (compounds) | 도메인 한정 |
|
|
68
|
+
| 정수 / 통화 / 수량 | `NumberInput` | ArrowUp/Down + Shift x10 + Home/End 키보드 ✓ |
|
|
69
|
+
| 단일 선택 (≤ 7) | `RadioGroup` | 시각적 비교 가능 |
|
|
70
|
+
| 단일 선택 (8+) | `Select` | dropdown |
|
|
71
|
+
| 다중 선택 (작은, ≤ 5) | `Checkbox` ×N | 시각적 비교 |
|
|
72
|
+
| 다중 선택 (큰, 6+) | `<Select multiple>` | discriminated union — `multiple: true` 시 value 가 array. token chip 표시 |
|
|
73
|
+
| boolean 즉시 효과 toggle | `Switch` | TBD: 자동 저장 / 수동 저장 |
|
|
74
|
+
| boolean 약관 동의 | `Checkbox` | submit 시 평가 |
|
|
75
|
+
| 날짜 1개 | `DatePicker` | |
|
|
76
|
+
| 시간 | `TimePicker` | |
|
|
77
|
+
| 숫자 슬라이더 | `Slider` / `RangeSlider` | |
|
|
78
|
+
| 색상 / 토큰 선택 | `Swatch` | |
|
|
79
|
+
| chip 형태 다중 토글 | `ChipToggle` | |
|
|
80
|
+
| 단계형 입력 (1→2→3) | `Stepper` (primitives/feedback) + 페이지 분할 | wizard |
|
|
63
81
|
|
|
64
82
|
### `Field` compound — label + control + error + hint
|
|
65
83
|
|
|
66
84
|
`packages/mds/src/compounds/Field/` 가 input 을 감싸는 표준 compound:
|
|
85
|
+
|
|
67
86
|
- `Field.Label`, control (TextField 등), `Field.Error`, `Field.Hint`
|
|
68
|
-
- input 의 a11y attribute (htmlFor / aria-describedby / aria-errormessage /
|
|
69
|
-
-
|
|
87
|
+
- input 의 a11y attribute (htmlFor / aria-describedby / aria-errormessage /
|
|
88
|
+
aria-invalid) 자동 wire
|
|
89
|
+
- 원자 input 직접 사용 보다 `Field` compound 권장 (Storybook 의 stories 도 Field
|
|
90
|
+
사용 예시)
|
|
70
91
|
|
|
71
92
|
### 파일 / 이미지 — `FileUpload` (Step 13 완료)
|
|
72
93
|
|
|
@@ -94,83 +115,85 @@
|
|
|
94
115
|
</Field.Root>
|
|
95
116
|
```
|
|
96
117
|
|
|
97
|
-
- mds 는 picker / drag-drop / preview / progress UI 만 책임. server upload (S3 /
|
|
98
|
-
|
|
118
|
+
- mds 는 picker / drag-drop / preview / progress UI 만 책임. server upload (S3 /
|
|
119
|
+
Cloudinary / 자체 API / multipart) 는 caller 결정.
|
|
120
|
+
- `upload` 안 주면 deferred mode (File 객체 만 보관, form submit 시 caller 가
|
|
121
|
+
처리).
|
|
99
122
|
- Controlled (`value` + `onChange`) + Uncontrolled (`defaultValue`) 둘 다 지원.
|
|
100
|
-
- `FileItem`:
|
|
123
|
+
- `FileItem`:
|
|
124
|
+
`{ id, file?, url?, name, size, type, status: 'pending'|'uploading'|'success'|'error', progress?, error? }`
|
|
125
|
+
— File 객체 + server URL 양쪽 표현 가능 (편집 시 기존 URL 도 자연 처리).
|
|
101
126
|
- `onReject` callback — `accept` / `maxSize` / `maxFiles` validation fail 시.
|
|
102
127
|
|
|
103
128
|
---
|
|
104
129
|
|
|
105
130
|
## 4. 검증 + 에러 표시
|
|
106
131
|
|
|
107
|
-
| 에러 종류
|
|
108
|
-
|
|
109
|
-
| 단일 필드 검증 (format / 필수 / length)
|
|
110
|
-
| Cross-field (비밀번호 ≠ 확인)
|
|
111
|
-
| Form 전체 검증 (서버 422 + 필드 에러)
|
|
112
|
-
| 비검증성 서버 에러 (500, 네트워크) — **일시적** | **toast.error**
|
|
113
|
-
| 단순 정보 (저장됐다) — **일시적**
|
|
114
|
-
| **영속** 경고 (라이선스 만료, 결제 만료)
|
|
132
|
+
| 에러 종류 | 표시 위치 | 컴포넌트 |
|
|
133
|
+
| ----------------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
|
|
134
|
+
| 단일 필드 검증 (format / 필수 / length) | **inline 필드 아래** | `Field.Error` slot |
|
|
135
|
+
| Cross-field (비밀번호 ≠ 확인) | inline 두 필드 + form summary | `Field.Error` + `Banner` 상단 |
|
|
136
|
+
| Form 전체 검증 (서버 422 + 필드 에러) | 필드별 분배 + 상단 `Banner` 요약 | `Banner` + `Field.Error` |
|
|
137
|
+
| 비검증성 서버 에러 (500, 네트워크) — **일시적** | **toast.error** | `toast.error(title, {description})` |
|
|
138
|
+
| 단순 정보 (저장됐다) — **일시적** | **toast.success** | `toast.success(...)` |
|
|
139
|
+
| **영속** 경고 (라이선스 만료, 결제 만료) | **Notification** (banner, 직접 닫기) | mds 의 영속 Notification — Step 14 별도 신규 작업. 임시 — `Banner` (variant=`warning` / `error`) 의 dismissible mode 활용 |
|
|
115
140
|
|
|
116
|
-
> **핵심 구분**: **Toast = 일시적** (자동 사라짐), **Notification = 영속**
|
|
141
|
+
> **핵심 구분**: **Toast = 일시적** (자동 사라짐), **Notification = 영속**
|
|
142
|
+
> (명시적 닫기 전 유지).
|
|
117
143
|
|
|
118
144
|
### 검증 시점 (RHF mode)
|
|
119
145
|
|
|
120
|
-
| Form 종류
|
|
121
|
-
|
|
122
|
-
| **default** (modal-form / drawer-form / 작은 form) | `onSubmit` (RHF default) | submit 시 검증. 입력 중 방해 X
|
|
123
|
-
| **page-form** (큰 form / multi-section)
|
|
124
|
-
| **특수 케이스** (비밀번호 강도, slug 중복)
|
|
146
|
+
| Form 종류 | RHF mode | 동작 |
|
|
147
|
+
| -------------------------------------------------- | ------------------------ | -------------------------------------------------------------------------------- |
|
|
148
|
+
| **default** (modal-form / drawer-form / 작은 form) | `onSubmit` (RHF default) | submit 시 검증. 입력 중 방해 X |
|
|
149
|
+
| **page-form** (큰 form / multi-section) | `onTouched` 권장 | blur 후 첫 검증 + 이후 change 시 즉시 재검증 (한 번 틀린 필드는 실시간 fix 도움) |
|
|
150
|
+
| **특수 케이스** (비밀번호 강도, slug 중복) | `onChange` (caller 결정) | 실시간 도움 필수 |
|
|
125
151
|
|
|
126
|
-
확정 룰:
|
|
127
|
-
|
|
|
128
|
-
|---|---|
|
|
129
|
-
| submit | 전체 form 검증 + 첫 에러 필드로 scroll/focus |
|
|
130
|
-
| 서버 응답 422 | 서버 에러를 RHF `setError` 로 필드 분배 |
|
|
152
|
+
확정 룰: | 시점 | 동작 | |---|---| | submit | 전체 form 검증 + 첫 에러 필드로
|
|
153
|
+
scroll/focus | | 서버 응답 422 | 서버 에러를 RHF `setError` 로 필드 분배 |
|
|
131
154
|
|
|
132
155
|
---
|
|
133
156
|
|
|
134
157
|
## 5. 저장 액션
|
|
135
158
|
|
|
136
|
-
| 액션 종류
|
|
137
|
-
|
|
138
|
-
| 페이지 form 저장
|
|
139
|
-
| Modal/Drawer form 저장 | Footer 우측 primary
|
|
140
|
-
| 위험 액션 (삭제, 환불) | `Modal.confirm` + 빨간 primary
|
|
159
|
+
| 액션 종류 | 버튼 위치 | 비활성 조건 |
|
|
160
|
+
| ---------------------- | ----------------------------------------------------------- | --------------------------------------- |
|
|
161
|
+
| 페이지 form 저장 | 페이지 하단 sticky `Toolbar` 또는 `PageHeader` 우측 primary | `isDirty === false` 또는 `isSubmitting` |
|
|
162
|
+
| Modal/Drawer form 저장 | Footer 우측 primary | 동일 |
|
|
163
|
+
| 위험 액션 (삭제, 환불) | `Modal.confirm` + 빨간 primary | 항상 |
|
|
141
164
|
|
|
142
165
|
### Inline 편집 (DataGrid 의 1 필드 빠른 수정)
|
|
143
166
|
|
|
144
|
-
| 동작
|
|
145
|
-
|
|
146
|
-
| 활성화
|
|
147
|
-
| **저장**
|
|
148
|
-
| 취소
|
|
149
|
-
| 위험 / 큰 필드 변경 | Inline 안 함 — drawer / modal 사용 (caller 재량)
|
|
167
|
+
| 동작 | 결정 |
|
|
168
|
+
| ------------------- | ---------------------------------------------------------- |
|
|
169
|
+
| 활성화 | cell click → input mode (pencil icon optional) |
|
|
170
|
+
| **저장** | **Enter 키 또는 체크 버튼 명시 click** (blur 자동 저장 ❌) |
|
|
171
|
+
| 취소 | Esc 키 또는 X 버튼 |
|
|
172
|
+
| 위험 / 큰 필드 변경 | Inline 안 함 — drawer / modal 사용 (caller 재량) |
|
|
150
173
|
|
|
151
|
-
> **이유** — Notion/Airtable 같은 blur 자동 저장은 실수 위험 + 의도 불명확.
|
|
152
|
-
>
|
|
174
|
+
> **이유** — Notion/Airtable 같은 blur 자동 저장은 실수 위험 + 의도 불명확. 명시
|
|
175
|
+
> 저장 = click 1 회 더지만 의도 확실.
|
|
153
176
|
|
|
154
177
|
### Submit 후 결과 처리
|
|
155
178
|
|
|
156
|
-
| 결과
|
|
157
|
-
|
|
179
|
+
| 결과 | 처리 |
|
|
180
|
+
| --------------------- | ------------------------------------------------------- |
|
|
158
181
|
| 200 OK (modal/drawer) | 컨테이너 닫기 + 부모 query invalidate + `toast.success` |
|
|
159
|
-
| 200 OK (페이지)
|
|
160
|
-
| 4xx 검증
|
|
161
|
-
| 5xx / 네트워크
|
|
182
|
+
| 200 OK (페이지) | 페이지 유지 + `isDirty=false` reset + `toast.success` |
|
|
183
|
+
| 4xx 검증 | 컨테이너 유지 + 필드 에러 분배 + 첫 에러 scroll |
|
|
184
|
+
| 5xx / 네트워크 | 컨테이너 유지 + `toast.error` |
|
|
162
185
|
|
|
163
186
|
### Optimistic update — 기본 적용
|
|
164
187
|
|
|
165
|
-
| 결정
|
|
166
|
-
|
|
167
|
-
| **기본**
|
|
168
|
-
| Rollback
|
|
169
|
-
| 4xx 검증 에러
|
|
188
|
+
| 결정 | 동작 |
|
|
189
|
+
| ---------------------- | ------------------------------------------------------------------------ |
|
|
190
|
+
| **기본** | **모든 mutation optimistic** — UI 즉시 갱신, 서버 응답 비동기 |
|
|
191
|
+
| Rollback | 5xx / network error 시 자동 rollback + `toast.error("저장 실패")` |
|
|
192
|
+
| 4xx 검증 에러 | rollback + 필드 에러 분배 + 첫 에러 scroll |
|
|
170
193
|
| **예외** (caller 결정) | 결제 / 환불 / 큰 금액 mutation — 명시 응답 대기 (`isSubmitting` loading) |
|
|
171
194
|
|
|
172
|
-
> **이유** — UX 가장 빠름. React Query 의 `onMutate` + `setQueryData` +
|
|
173
|
-
> 패턴 표준화.
|
|
195
|
+
> **이유** — UX 가장 빠름. React Query 의 `onMutate` + `setQueryData` +
|
|
196
|
+
> `onError rollback` 패턴 표준화.
|
|
174
197
|
|
|
175
198
|
---
|
|
176
199
|
|
|
@@ -178,12 +201,12 @@
|
|
|
178
201
|
|
|
179
202
|
상세 → [array-input Playbook](./array-input.md) (Step 4.6).
|
|
180
203
|
|
|
181
|
-
| 패턴
|
|
182
|
-
|
|
183
|
-
| 짧은 동질 배열 (태그)
|
|
184
|
-
| 가변 row (variant 가격)
|
|
185
|
-
| nested entity 다수 (정책, 결제 옵션) | `useFieldArray` + row 클릭 시 **drawer 편집**
|
|
186
|
-
| reorder
|
|
204
|
+
| 패턴 | 컴포넌트 | 비고 |
|
|
205
|
+
| ------------------------------------ | --------------------------------------------------------- | ------------------ |
|
|
206
|
+
| 짧은 동질 배열 (태그) | `ChipToggle` | item = 단순 string |
|
|
207
|
+
| 가변 row (variant 가격) | RHF `useFieldArray` + `Stack` | 각 row = sub-form |
|
|
208
|
+
| nested entity 다수 (정책, 결제 옵션) | `useFieldArray` + row 클릭 시 **drawer 편집** | row = 요약 |
|
|
209
|
+
| reorder | `Tree` 또는 `useFieldArray` + dnd-kit (mds 자체 dnd 없음) | |
|
|
187
210
|
|
|
188
211
|
---
|
|
189
212
|
|
|
@@ -194,29 +217,30 @@
|
|
|
194
217
|
- `useSkillAutofill(agentType)` — generic hook
|
|
195
218
|
- `FormFillApprovalBanner` — Apply / Reject UI
|
|
196
219
|
- `skill-registry` — 등록 → AI 가 catalog query
|
|
197
|
-
- 도메인별 fill hook / Banner / Prompt 작성 금지 (`useSkillAutofill` + shared
|
|
220
|
+
- 도메인별 fill hook / Banner / Prompt 작성 금지 (`useSkillAutofill` + shared
|
|
221
|
+
사용)
|
|
198
222
|
|
|
199
223
|
---
|
|
200
224
|
|
|
201
225
|
## 8. 사용 시점 결정표 (lookup)
|
|
202
226
|
|
|
203
|
-
| 케이스
|
|
204
|
-
|
|
205
|
-
| "필드 ≤ 5 짧은 입력"
|
|
206
|
-
| "10+ 필드 + 설정 페이지"
|
|
207
|
-
| "리스트 행 빠른 편집"
|
|
208
|
-
| "정말 삭제?"
|
|
209
|
-
| "저장됐다 일시 알림"
|
|
210
|
-
| "서버 500 일시 알림"
|
|
211
|
-
| "라이선스 만료 영속 경고" | `Notification` (TBD)
|
|
212
|
-
| "input 옆 즉시 검증"
|
|
213
|
-
| "form 위 전체 요약 에러"
|
|
214
|
-
| "variant 줄 추가"
|
|
215
|
-
| "boolean 즉시 효과"
|
|
216
|
-
| "boolean submit 시 평가"
|
|
217
|
-
| "8+ 선택지"
|
|
218
|
-
| "≤ 7 선택지"
|
|
219
|
-
| "숫자 ↑↓ 키보드"
|
|
227
|
+
| 케이스 | 답 |
|
|
228
|
+
| ------------------------- | ---------------------------------------- |
|
|
229
|
+
| "필드 ≤ 5 짧은 입력" | modal-form |
|
|
230
|
+
| "10+ 필드 + 설정 페이지" | page-form |
|
|
231
|
+
| "리스트 행 빠른 편집" | drawer-form |
|
|
232
|
+
| "정말 삭제?" | `Modal.confirm` |
|
|
233
|
+
| "저장됐다 일시 알림" | `toast.success` |
|
|
234
|
+
| "서버 500 일시 알림" | `toast.error` |
|
|
235
|
+
| "라이선스 만료 영속 경고" | `Notification` (TBD) |
|
|
236
|
+
| "input 옆 즉시 검증" | `Field.Error` inline |
|
|
237
|
+
| "form 위 전체 요약 에러" | `Banner` 상단 |
|
|
238
|
+
| "variant 줄 추가" | `useFieldArray` + 행 편집 = drawer |
|
|
239
|
+
| "boolean 즉시 효과" | `Switch` (TBD 자동 저장 여부) |
|
|
240
|
+
| "boolean submit 시 평가" | `Checkbox` |
|
|
241
|
+
| "8+ 선택지" | `Select` |
|
|
242
|
+
| "≤ 7 선택지" | `RadioGroup` |
|
|
243
|
+
| "숫자 ↑↓ 키보드" | `NumberInput` (ArrowUp/Down + Shift x10) |
|
|
220
244
|
|
|
221
245
|
---
|
|
222
246
|
|
|
@@ -228,7 +252,8 @@
|
|
|
228
252
|
- ❌ `Notification` 으로 "저장됨" — toast 가 맞음 (일시적)
|
|
229
253
|
- ❌ Toast 로 "라이선스 만료" — Notification (영속)
|
|
230
254
|
- ❌ raw `<input>` / `<textarea>` 사용 — mds `TextField` / `Textarea` 만
|
|
231
|
-
- ❌ form value 를 `useState` 로
|
|
255
|
+
- ❌ simple/medium form value 를 ad-hoc `useState` 로 흩어 관리 — RHF + Zod 또는
|
|
256
|
+
app-level form adapter 사용
|
|
232
257
|
- ❌ Field compound 외부에 input — Field 의 a11y wire 누락
|
|
233
258
|
- ❌ 도메인별 fill hook 작성 — `useSkillAutofill` 사용
|
|
234
259
|
|
|
@@ -236,13 +261,13 @@
|
|
|
236
261
|
|
|
237
262
|
## 10. Cross-cutting
|
|
238
263
|
|
|
239
|
-
| Axis
|
|
240
|
-
|
|
241
|
-
| **Responsive** | 모든 표의 "Mobile 변형" 컬럼 — 자동 적용
|
|
242
|
-
| **A11y**
|
|
243
|
-
| **i18n**
|
|
244
|
-
| **AI fill**
|
|
245
|
-
| **Catalog**
|
|
264
|
+
| Axis | 적용 |
|
|
265
|
+
| -------------- | ----------------------------------------------------------------------------------- |
|
|
266
|
+
| **Responsive** | 모든 표의 "Mobile 변형" 컬럼 — 자동 적용 |
|
|
267
|
+
| **A11y** | Field compound 의 aria-\* 자동 wire / RHF 의 setFocus 첫 에러 |
|
|
268
|
+
| **i18n** | label / error / placeholder 모두 `t()` 통과 — apps/web 의 ESLint rule 강제 (Step 7) |
|
|
269
|
+
| **AI fill** | skill-registry 등록만 — AI 가 자동 query |
|
|
270
|
+
| **Catalog** | 각 컴포넌트 (TextField / Select / Field 등) 의 catalog.json 자동 추출 (Step 5) |
|
|
246
271
|
|
|
247
272
|
---
|
|
248
273
|
|
|
@@ -250,37 +275,42 @@
|
|
|
250
275
|
|
|
251
276
|
### 확정 (cycle 1)
|
|
252
277
|
|
|
253
|
-
| §
|
|
254
|
-
|
|
255
|
-
| §2 Form 배치
|
|
256
|
-
| §4 RHF mode
|
|
257
|
-
| §5 Inline 편집 | 허용 + Enter/체크 명시 저장 (blur 자동 ❌) + Esc 취소
|
|
258
|
-
| §5 Optimistic
|
|
278
|
+
| § | 결정 |
|
|
279
|
+
| -------------- | ---------------------------------------------------------------- |
|
|
280
|
+
| §2 Form 배치 | Section 개수 기준 (1 vertical / 2-5 caller 재량 / 6+ AnchorNav) |
|
|
281
|
+
| §4 RHF mode | default `onSubmit`, page-form `onTouched`, 특수 `onChange` |
|
|
282
|
+
| §5 Inline 편집 | 허용 + Enter/체크 명시 저장 (blur 자동 ❌) + Esc 취소 |
|
|
283
|
+
| §5 Optimistic | 모든 mutation 기본 적용 + rollback + error toast. 결제/환불 예외 |
|
|
259
284
|
|
|
260
285
|
### 확정 (cycle 2 — Step 4.1)
|
|
261
286
|
|
|
262
|
-
| §
|
|
263
|
-
|
|
264
|
-
| §3 다중 선택 (큰 list)
|
|
265
|
-
| §5 저장 button i18n key
|
|
266
|
-
| §5 위험 액션 typing rule
|
|
267
|
-
| §5 위험 액션 typing 표준 문구 | i18n key `confirm.typeXToConfirm` + `{x}` 가 entity name (shop slug / customer email / etc.) — 영문 또는 일치 텍스트
|
|
287
|
+
| § | 결정 | 근거 |
|
|
288
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------- |
|
|
289
|
+
| §3 다중 선택 (큰 list) | `<Select multiple>` 사용 — discriminated union (SelectSingleProps vs SelectMultipleProps) | mds 의 Select 가 이미 multiple prop 지원 검증됨 (Select.types.ts §79 + tests §102-194 + stories §100-151) |
|
|
290
|
+
| §5 저장 button i18n key | `t('common.save')` / `t('common.cancel')` / `t('common.delete')` / `t('common.discard')` — 공통 namespace | apps/web 의 i18n.md §3 — common namespace |
|
|
291
|
+
| §5 위험 액션 typing rule | 일반 삭제 = `Modal.confirm` (단순). **영향 큰 액션** (계정 삭제 / 가입자 전체 삭제 / DB drop / 환불 전체) = typing confirm — Modal 안 input + 정확한 문구 입력 시에만 destructive button enabled | 실수 방지 — confirm click 한 번보다 typing 이 의도 명시가 강함. caller 가 판단 ("이게 영향 큰가") |
|
|
292
|
+
| §5 위험 액션 typing 표준 문구 | i18n key `confirm.typeXToConfirm` + `{x}` 가 entity name (shop slug / customer email / etc.) — 영문 또는 일치 텍스트 | 일관 UX (caller 별 다른 typing rule 안 됨) |
|
|
268
293
|
|
|
269
294
|
### 별도 step (큰 작업 — Phase 2 계획)
|
|
270
295
|
|
|
271
|
-
| 항목
|
|
272
|
-
|
|
273
|
-
| §3 FileUpload
|
|
296
|
+
| 항목 | 별도 step |
|
|
297
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
298
|
+
| §3 FileUpload | **Step 13 — mds FileUpload 추가** (필요한 a11y / drag-drop / 진행률 / multi / preview / type validation 전체 컴포넌트 설계) |
|
|
274
299
|
| §4 Notification 영속 | **Step 14 — mds Notification 추가** (Toast 와 분리 — Toast 는 일시, Notification 은 영속. 직접 닫기 전 유지. badge 또는 inline) |
|
|
275
300
|
|
|
276
|
-
> cycle 2 마무리 — form.md 의 모든 TBD 확정 또는 별도 step 으로 이관. mds Form
|
|
301
|
+
> cycle 2 마무리 — form.md 의 모든 TBD 확정 또는 별도 step 으로 이관. mds Form
|
|
302
|
+
> 영역 = 완벽 마무리.
|
|
277
303
|
|
|
278
304
|
---
|
|
279
305
|
|
|
280
306
|
## Related Playbooks
|
|
281
307
|
|
|
282
|
-
- [feedback.md](./feedback.md) — Toast / Notification / Banner / Modal Dialog
|
|
308
|
+
- [feedback.md](./feedback.md) — Toast / Notification / Banner / Modal Dialog
|
|
309
|
+
(Step 4.2)
|
|
283
310
|
- [overlay.md](./overlay.md) — Modal / Drawer / Sheet / Dialog (Step 4.4)
|
|
284
311
|
- [array-input.md](./array-input.md) — useFieldArray + drawer 편집 (Step 4.6)
|
|
285
312
|
- [async-states.md](./async-states.md) — loading/error/empty/skeleton (Step 4.7)
|
|
286
|
-
- [ai-fill.md](./ai-fill.md) — skill-registry + FormFillApprovalBanner (Step
|
|
313
|
+
- [ai-fill.md](./ai-fill.md) — skill-registry + FormFillApprovalBanner (Step
|
|
314
|
+
4.8)
|
|
315
|
+
- [apps/web form-architecture.md](../../../../apps/web/docs/playbook/form-architecture.md)
|
|
316
|
+
— MAKITT web domain form adapter / shell rules
|