@ncds/ui-admin-mcp 1.0.0-alpha.16 → 1.0.0-alpha.17

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.
@@ -0,0 +1,1302 @@
1
+ {
2
+ "_comment": "MCP composition sidecar — extract-mcp-data.ts 산출물(data/*.json) 위에 병합되는 추가 메타. 컴포넌트 디렉토리 무수정 원칙을 지키면서 P1-4(allowedChildren/Parents), P1-6(canonicalExample), P0-3c(bemClassesExtra) 를 한곳에서 관리.",
3
+ "data-grid": {
4
+ "_note": "P5/P10: DataGrid 는 compound — DataGrid.Table(필수) + DataGrid.Summary / DataGrid.Pagination / DataGrid.SearchFilter / DataGrid.FilterBar / DataGrid.ActionBar 자식. 검색결과 목록 화면 표준. forbiddenInContext: DataGrid.Table 안에 Table.Pagination 금지 — DataGrid.Pagination 슬롯 사용.",
5
+ "descriptionExtra": "[중요] 검색결과·관리자 목록 화면 표준 컴포넌트. DataGrid.Table(필수, NCDS Table 자동 감싸기) + Summary(건수 표시) + ActionBar(상단 일괄 액션) + Pagination(하단). DataGrid 안에서 Table 의 Pagination 슬롯은 사용 금지 — DataGrid.Pagination 으로 분리. variant: search-result(검색결과 페이지 표준) / simple(단순 목록) / readonly(편집 불가). Storybook DataGrid SearchResultDemo 의 children 트리와 동일 구조 유지.",
6
+ "aliasesExtra": [
7
+ "데이터 그리드", "데이터그리드", "목록 그리드", "검색 결과 그리드", "관리자 목록",
8
+ "list grid", "result grid", "admin list", "search result list", "table grid",
9
+ "페이지네이션 테이블", "필터 테이블", "선택 가능 테이블", "ActionBar 테이블",
10
+ "주문 목록", "상품 목록", "회원 목록"
11
+ ],
12
+ "bemClassesExtra": [],
13
+ "allowedChildren": {
14
+ "DataGrid": {
15
+ "required": ["DataGrid.Table"],
16
+ "recommended": ["DataGrid.Summary", "DataGrid.Pagination"],
17
+ "optional": ["DataGrid.SearchFilter", "DataGrid.FilterBar", "DataGrid.ActionBar"],
18
+ "forbiddenInContext": {
19
+ "Table.Pagination": "Inside DataGrid, use DataGrid.Pagination slot (NCUA Pagination component) — Table.Pagination is for standalone Table only."
20
+ }
21
+ },
22
+ "DataGrid.Table": {
23
+ "required": ["Table.Header", "Table.Body"],
24
+ "recommended": ["Table.ColGroup"],
25
+ "optional": ["Table.Footer", "Table.Empty"],
26
+ "forbiddenInContext": {
27
+ "Table.Pagination": "Inside DataGrid.Table, use DataGrid.Pagination slot at the DataGrid level — never embed Table.Pagination here."
28
+ }
29
+ },
30
+ "DataGrid.Pagination": ["Pagination"]
31
+ },
32
+ "canonicalExample": {
33
+ "_note": "검색결과(주문/회원/상품 등) 목록 표준 레이아웃. Storybook DataGrid SearchResultDemo 와 동일 구조. AI 는 컬럼 수/라벨/데이터만 교체하고 트리 자체는 유지한다. checkbox 컬럼이 필요 없으면 제거, 필터/정렬 SelectBox 가 필요 없으면 actionBarTopRight 만 비우는 식으로 가지치기.",
34
+ "props": {
35
+ "variant": "search-result",
36
+ "children": [
37
+ {
38
+ "component": "data-grid.summary",
39
+ "children": ["검색 5건 / 전체 128건"]
40
+ },
41
+ {
42
+ "component": "data-grid.action-bar",
43
+ "_note": "align=space-between 은 직속 children 2개를 좌/우 끝으로 분배한다. 그래서 좌측 그룹과 우측 그룹을 각각 'block-container' 로 묶어 children=2 로 만들어야 의도된 분할이 나온다. 좌측: 선택 일괄 액션 버튼, 우측: 정렬/페이지크기 SelectBox.",
44
+ "props": { "position": "top", "align": "space-between" },
45
+ "children": [
46
+ {
47
+ "component": "block-container",
48
+ "props": { "className": "data-grid__action-bar-group--left" },
49
+ "children": [
50
+ { "component": "button", "props": { "label": "송장 번호 저장", "size": "xs", "hierarchy": "secondary-gray" } },
51
+ { "component": "button", "props": { "label": "묶음 배송해제", "size": "xs", "hierarchy": "secondary" } }
52
+ ]
53
+ },
54
+ {
55
+ "component": "block-container",
56
+ "props": { "className": "data-grid__action-bar-group--right" },
57
+ "children": [
58
+ { "component": "select-box", "props": { "size": "xs", "options": [{ "id": "recent", "label": "최근 등록순" }] } },
59
+ { "component": "select-box", "props": { "size": "xs", "options": [{ "id": "10", "label": "10개 보기" }] } }
60
+ ]
61
+ }
62
+ ]
63
+ },
64
+ {
65
+ "component": "data-grid.table",
66
+ "props": {
67
+ "type": "horizontal",
68
+ "hoverable": true,
69
+ "selectable": true,
70
+ "fixedHeader": true,
71
+ "maxHeight": 600
72
+ },
73
+ "children": [
74
+ {
75
+ "component": "table.col-group",
76
+ "props": { "widths": [56, "auto", "auto", "auto", 140, 120, 160] }
77
+ },
78
+ {
79
+ "component": "table.header",
80
+ "children": [
81
+ {
82
+ "component": "table.row",
83
+ "children": [
84
+ { "component": "table.header-cell", "children": [{ "component": "checkbox", "props": { "size": "sm" } }] },
85
+ { "component": "table.header-cell", "children": ["주문번호"] },
86
+ { "component": "table.header-cell", "children": ["상품명"] },
87
+ { "component": "table.header-cell", "children": ["주문자"] },
88
+ { "component": "table.header-cell", "children": ["결제금액"] },
89
+ { "component": "table.header-cell", "children": ["상태"] },
90
+ { "component": "table.header-cell", "children": ["주문일시"] }
91
+ ]
92
+ }
93
+ ]
94
+ },
95
+ {
96
+ "component": "table.body",
97
+ "children": [
98
+ {
99
+ "component": "table.row",
100
+ "children": [
101
+ { "component": "table.cell", "children": [{ "component": "checkbox", "props": { "size": "sm" } }] },
102
+ { "component": "table.cell", "children": ["2508081832000001"] },
103
+ { "component": "table.cell", "children": ["프리미엄 노트북"] },
104
+ { "component": "table.cell", "children": ["홍길동"] },
105
+ { "component": "table.cell", "children": ["1,500,000"] },
106
+ {
107
+ "component": "table.cell",
108
+ "children": [
109
+ { "component": "badge", "props": { "label": "배송완료", "size": "xs", "type": "pill-outline", "color": "success" } }
110
+ ]
111
+ },
112
+ { "component": "table.cell", "children": ["2025-08-08 18:32"] }
113
+ ]
114
+ },
115
+ {
116
+ "component": "table.row",
117
+ "children": [
118
+ { "component": "table.cell", "children": [{ "component": "checkbox", "props": { "size": "sm" } }] },
119
+ { "component": "table.cell", "children": ["2508081832000002"] },
120
+ { "component": "table.cell", "children": ["무선 마우스"] },
121
+ { "component": "table.cell", "children": ["김철수"] },
122
+ { "component": "table.cell", "children": ["35,000"] },
123
+ {
124
+ "component": "table.cell",
125
+ "children": [
126
+ { "component": "badge", "props": { "label": "배송중", "size": "xs", "type": "pill-outline", "color": "blue" } }
127
+ ]
128
+ },
129
+ { "component": "table.cell", "children": ["2025-08-08 15:20"] }
130
+ ]
131
+ }
132
+ ]
133
+ }
134
+ ]
135
+ },
136
+ {
137
+ "component": "data-grid.action-bar",
138
+ "props": { "position": "bottom", "align": "space-between" },
139
+ "children": [
140
+ {
141
+ "component": "block-container",
142
+ "props": { "className": "data-grid__action-bar-group--left" },
143
+ "children": [
144
+ { "component": "button", "props": { "label": "송장 번호 저장", "size": "xs", "hierarchy": "secondary-gray" } },
145
+ { "component": "button", "props": { "label": "묶음 배송해제", "size": "xs", "hierarchy": "secondary" } }
146
+ ]
147
+ }
148
+ ]
149
+ },
150
+ {
151
+ "component": "data-grid.pagination",
152
+ "children": [
153
+ { "component": "pagination", "props": { "totalCount": 128, "currentPage": 1 } }
154
+ ]
155
+ }
156
+ ]
157
+ }
158
+ },
159
+ "canonicalExamples": {
160
+ "_note": "P5-1 다중 시나리오 맵. AI 는 사용자 의도에 따라 하나의 키를 명시적으로 선택해 시작점으로 사용한다. 트리 구조는 유지하고 라벨/컬럼 수/데이터만 교체. 시나리오 사이의 부분 혼합은 금지.",
161
+ "search-result-with-selection-rich": {
162
+ "description": "검색결과 + 선택 일괄 액션 + Summary 좌/우(SMS/인쇄/엑셀) + ActionBar 좌(prefix+버튼)/우(정렬+페이지+설정) + 7컬럼 + 양쪽 ActionBar. 가장 풍부한 표준 형태.",
163
+ "props": {
164
+ "variant": "search-result",
165
+ "children": [
166
+ {
167
+ "component": "data-grid.summary",
168
+ "children": [
169
+ {
170
+ "component": "block-container",
171
+ "props": { "className": "data-grid__summary-group--left" },
172
+ "children": ["검색 5건 / 전체 128건"]
173
+ },
174
+ {
175
+ "component": "block-container",
176
+ "props": { "className": "data-grid__summary-group--right" },
177
+ "children": [
178
+ { "component": "button", "props": { "label": "SMS 발송", "size": "xs", "hierarchy": "secondary-gray" } },
179
+ { "component": "button", "props": { "label": "인쇄", "size": "xs", "hierarchy": "secondary-gray" } },
180
+ { "component": "button", "props": { "label": "엑셀 다운로드", "size": "xs", "hierarchy": "secondary-gray" } }
181
+ ]
182
+ }
183
+ ]
184
+ },
185
+ {
186
+ "component": "data-grid.action-bar",
187
+ "props": { "position": "top", "align": "space-between" },
188
+ "children": [
189
+ {
190
+ "component": "block-container",
191
+ "props": { "className": "data-grid__action-bar-group--left" },
192
+ "children": [
193
+ "선택한 주문을 ",
194
+ { "component": "button", "props": { "label": "송장 번호 저장", "size": "xs", "hierarchy": "secondary-gray" } },
195
+ { "component": "button", "props": { "label": "묶음 배송해제", "size": "xs", "hierarchy": "secondary" } }
196
+ ]
197
+ },
198
+ {
199
+ "component": "block-container",
200
+ "props": { "className": "data-grid__action-bar-group--right" },
201
+ "children": [
202
+ { "component": "select-box", "props": { "size": "xs", "options": [{ "id": "recent", "label": "최근 등록순" }] } },
203
+ { "component": "select-box", "props": { "size": "xs", "options": [{ "id": "10", "label": "10개 보기" }] } },
204
+ { "component": "button", "props": { "label": "설정", "size": "xs", "hierarchy": "secondary-gray", "onlyIcon": true } }
205
+ ]
206
+ }
207
+ ]
208
+ },
209
+ {
210
+ "component": "data-grid.table",
211
+ "props": { "type": "horizontal", "hoverable": true, "selectable": true, "fixedHeader": true, "maxHeight": 600 },
212
+ "children": [
213
+ { "component": "table.col-group", "props": { "widths": [56, "auto", "auto", "auto", 140, 120, 160] } },
214
+ {
215
+ "component": "table.header",
216
+ "children": [
217
+ {
218
+ "component": "table.row",
219
+ "children": [
220
+ { "component": "table.header-cell", "children": [{ "component": "checkbox", "props": { "size": "sm" } }] },
221
+ { "component": "table.header-cell", "children": ["주문번호"] },
222
+ { "component": "table.header-cell", "children": ["상품명"] },
223
+ { "component": "table.header-cell", "children": ["주문자"] },
224
+ { "component": "table.header-cell", "children": ["결제금액"] },
225
+ { "component": "table.header-cell", "children": ["상태"] },
226
+ { "component": "table.header-cell", "children": ["주문일시"] }
227
+ ]
228
+ }
229
+ ]
230
+ },
231
+ {
232
+ "component": "table.body",
233
+ "children": [
234
+ {
235
+ "component": "table.row",
236
+ "children": [
237
+ { "component": "table.cell", "children": [{ "component": "checkbox", "props": { "size": "sm" } }] },
238
+ { "component": "table.cell", "children": ["2508081832000001"] },
239
+ { "component": "table.cell", "children": ["프리미엄 노트북"] },
240
+ { "component": "table.cell", "children": ["홍길동"] },
241
+ { "component": "table.cell", "children": ["1,500,000"] },
242
+ { "component": "table.cell", "children": [{ "component": "badge", "props": { "label": "배송완료", "size": "xs", "type": "pill-outline", "color": "success" } }] },
243
+ { "component": "table.cell", "children": ["2025-08-08 18:32"] }
244
+ ]
245
+ }
246
+ ]
247
+ }
248
+ ]
249
+ },
250
+ {
251
+ "component": "data-grid.action-bar",
252
+ "props": { "position": "bottom", "align": "space-between" },
253
+ "children": [
254
+ {
255
+ "component": "block-container",
256
+ "props": { "className": "data-grid__action-bar-group--left" },
257
+ "children": [
258
+ "선택한 주문을 ",
259
+ { "component": "button", "props": { "label": "송장 번호 저장", "size": "xs", "hierarchy": "secondary-gray" } },
260
+ { "component": "button", "props": { "label": "묶음 배송해제", "size": "xs", "hierarchy": "secondary" } }
261
+ ]
262
+ },
263
+ {
264
+ "component": "block-container",
265
+ "props": { "className": "data-grid__action-bar-group--right" },
266
+ "children": [
267
+ { "component": "select-box", "props": { "size": "xs", "options": [{ "id": "recent", "label": "최근 등록순" }] } },
268
+ { "component": "select-box", "props": { "size": "xs", "options": [{ "id": "10", "label": "10개 보기" }] } }
269
+ ]
270
+ }
271
+ ]
272
+ },
273
+ {
274
+ "component": "data-grid.pagination",
275
+ "children": [{ "component": "pagination", "props": { "totalCount": 128, "currentPage": 1 } }]
276
+ }
277
+ ]
278
+ }
279
+ },
280
+ "search-result-with-selection-simple": {
281
+ "description": "검색결과 + 선택 일괄 액션 (Summary 단일, ActionBar 단순 좌/우, bottom ActionBar 좌측만). 디테일 부족하나 짧고 명확.",
282
+ "props": {
283
+ "variant": "search-result",
284
+ "children": [
285
+ { "component": "data-grid.summary", "children": ["검색 5건 / 전체 128건"] },
286
+ {
287
+ "component": "data-grid.action-bar",
288
+ "props": { "position": "top", "align": "space-between" },
289
+ "children": [
290
+ {
291
+ "component": "block-container",
292
+ "children": [
293
+ { "component": "button", "props": { "label": "송장 번호 저장", "size": "xs", "hierarchy": "secondary-gray" } },
294
+ { "component": "button", "props": { "label": "묶음 배송해제", "size": "xs", "hierarchy": "secondary" } }
295
+ ]
296
+ },
297
+ {
298
+ "component": "block-container",
299
+ "children": [
300
+ { "component": "select-box", "props": { "size": "xs", "options": [{ "id": "recent", "label": "최근 등록순" }] } },
301
+ { "component": "select-box", "props": { "size": "xs", "options": [{ "id": "10", "label": "10개 보기" }] } }
302
+ ]
303
+ }
304
+ ]
305
+ },
306
+ {
307
+ "component": "data-grid.table",
308
+ "props": { "type": "horizontal", "hoverable": true, "selectable": true },
309
+ "children": [
310
+ {
311
+ "component": "table.header",
312
+ "children": [
313
+ {
314
+ "component": "table.row",
315
+ "children": [
316
+ { "component": "table.header-cell", "children": ["주문번호"] },
317
+ { "component": "table.header-cell", "children": ["상태"] }
318
+ ]
319
+ }
320
+ ]
321
+ },
322
+ {
323
+ "component": "table.body",
324
+ "children": [
325
+ {
326
+ "component": "table.row",
327
+ "children": [
328
+ { "component": "table.cell", "children": ["2508081832000001"] },
329
+ { "component": "table.cell", "children": [{ "component": "badge", "props": { "label": "배송완료", "size": "xs", "type": "pill-outline", "color": "success" } }] }
330
+ ]
331
+ }
332
+ ]
333
+ }
334
+ ]
335
+ },
336
+ {
337
+ "component": "data-grid.pagination",
338
+ "children": [{ "component": "pagination", "props": { "totalCount": 128, "currentPage": 1 } }]
339
+ }
340
+ ]
341
+ }
342
+ },
343
+ "search-result-readonly": {
344
+ "description": "검색결과 + 선택 없음(체크박스 없음, ActionBar 없음). Summary + Table + Pagination 만. 단순 조회 화면.",
345
+ "props": {
346
+ "variant": "search-result",
347
+ "children": [
348
+ { "component": "data-grid.summary", "children": ["전체 128건"] },
349
+ {
350
+ "component": "data-grid.table",
351
+ "props": { "type": "horizontal", "hoverable": true },
352
+ "children": [
353
+ {
354
+ "component": "table.header",
355
+ "children": [
356
+ {
357
+ "component": "table.row",
358
+ "children": [
359
+ { "component": "table.header-cell", "children": ["번호"] },
360
+ { "component": "table.header-cell", "children": ["제목"] },
361
+ { "component": "table.header-cell", "children": ["등록일"] }
362
+ ]
363
+ }
364
+ ]
365
+ },
366
+ {
367
+ "component": "table.body",
368
+ "children": [
369
+ {
370
+ "component": "table.row",
371
+ "children": [
372
+ { "component": "table.cell", "children": ["1"] },
373
+ { "component": "table.cell", "children": ["샘플 항목"] },
374
+ { "component": "table.cell", "children": ["2026-05-08"] }
375
+ ]
376
+ }
377
+ ]
378
+ }
379
+ ]
380
+ },
381
+ {
382
+ "component": "data-grid.pagination",
383
+ "children": [{ "component": "pagination", "props": { "totalCount": 128, "currentPage": 1 } }]
384
+ }
385
+ ]
386
+ }
387
+ }
388
+ }
389
+ },
390
+ "table": {
391
+ "_note_required": "P7: ncua-table__required 는 NCDS Table SCSS([_table.scss:619]) 와 VanillaJS classNames 상수([classNames.ts:26])에는 정의되어 있으나 React Table.tsx 본체가 사용하지 않아 자동 추출되지 않음. Vertical Table 의 필수 라벨에 `<span class='ncua-table__required'>*</span>` 형태로 라벨 텍스트 앞에 prepend 하여 사용. validate_html 화이트리스트 통과를 위해 bemClassesExtra 에 명시 등록.",
392
+ "descriptionExtra": "[중요] table 컴포넌트는 두 가지 모드 지원: (1) type=horizontal — 데이터 그리드(thead+tbody, 컬럼별 헤더). (2) type=vertical — 폼 레이아웃(tbody only, 좌측 라벨-우측 값 2-cell row). 폼의 라벨-입력 쌍 구성 시 vertical 모드 사용 — 절대 BEM 수동 작성 금지. canonicalExamples 의 'vertical-form-label' / 'vertical-form-label-with-required' 시나리오 참고. ⚠️ <th class='ncua-table__header-cell'> 은 horizontal 컬럼 헤더 전용 — vertical 라벨에는 <th scope='row' class='ncua-table__cell'> 사용 (Table.Cell with isHeader=true).",
393
+ "aliasesExtra": [
394
+ "vertical-table", "form-table", "form-layout", "label-value", "vertical-form", "form table",
395
+ "폼 레이아웃", "라벨-입력", "세로 테이블", "vertical form", "폼 테이블", "수직 테이블", "form-vertical-table"
396
+ ],
397
+ "bemClassesExtra": [
398
+ "ncua-table--in-data-grid",
399
+ "ncua-table__required",
400
+ "ncua-table__cell--with-tooltip",
401
+ "ncua-table__cell-inner",
402
+ "ncua-table__cell-label"
403
+ ],
404
+ "allowedChildren": {
405
+ "Table": ["Table.Header", "Table.Body", "Table.Footer", "Table.ColGroup", "Table.Empty"],
406
+ "Table.Header": ["Table.Row"],
407
+ "Table.Body": ["Table.Row"],
408
+ "Table.Footer": ["Table.Row"],
409
+ "Table.Row": ["Table.HeaderCell", "Table.Cell"]
410
+ },
411
+ "allowedParents": {
412
+ "Table.Row": ["Table.Header", "Table.Body", "Table.Footer"],
413
+ "Table.HeaderCell": ["Table.Row"],
414
+ "Table.Cell": ["Table.Row"]
415
+ },
416
+ "canonicalExample": {
417
+ "props": {
418
+ "type": "horizontal",
419
+ "hoverable": true,
420
+ "children": [
421
+ {
422
+ "component": "table.header",
423
+ "children": [
424
+ {
425
+ "component": "table.row",
426
+ "children": [
427
+ { "component": "table.header-cell", "children": ["주문번호"] },
428
+ { "component": "table.header-cell", "children": ["상품명"] }
429
+ ]
430
+ }
431
+ ]
432
+ },
433
+ {
434
+ "component": "table.body",
435
+ "children": [
436
+ {
437
+ "component": "table.row",
438
+ "children": [
439
+ { "component": "table.cell", "children": ["1001"] },
440
+ { "component": "table.cell", "children": ["샘플 상품"] }
441
+ ]
442
+ }
443
+ ]
444
+ }
445
+ ]
446
+ }
447
+ },
448
+ "canonicalExamples": {
449
+ "_note": "P6: NCDS Table 은 같은 <th> 태그를 두 컨텍스트로 사용한다. Horizontal=컬럼 헤더(Table.HeaderCell→ncua-table__header-cell), Vertical=행 라벨(Table.Cell with isHeader=true→<th scope='row' class='ncua-table__cell'>). 두 시나리오를 분리 등록하여 AI 가 정확히 분기 학습하도록 한다. 절대 vertical 에 Table.HeaderCell 을 사용하지 말 것.",
450
+ "horizontal-with-page-scroll-wrapper": {
451
+ "description": "P10: 컬럼 수가 많아 페이지 너비 초과 시 NCDS Table 외곽을 페이지 prefix wrapper 로 감싸 가로 스크롤 처리. 표준 wrapper 이름은 'page-table__scroll' (또는 프로젝트 prefix 통일, 예: 'shop-table__scroll'). wrapper 안에 'page-table__scroll-inner' (min-width 적용) 한 단계 더, 그 안에 ncua-table-wrapper. CSS: .page-table__scroll { overflow-x: auto; } .page-table__scroll-inner { min-width: 1200px; }. 동일 프로젝트 내에서 같은 wrapper 이름 사용 — 매번 다른 이름(sgr-comb-scroll/opt-scroll 등) 생성 금지. 트리 내부의 Table 구조는 horizontal-with-header-cell 과 동일.",
452
+ "props": {
453
+ "type": "horizontal",
454
+ "hoverable": true,
455
+ "children": [
456
+ {
457
+ "component": "table.header",
458
+ "children": [
459
+ {
460
+ "component": "table.row",
461
+ "children": [
462
+ { "component": "table.header-cell", "children": ["컬럼 1"] },
463
+ { "component": "table.header-cell", "children": ["컬럼 2"] },
464
+ { "component": "table.header-cell", "children": ["컬럼 3"] }
465
+ ]
466
+ }
467
+ ]
468
+ },
469
+ { "component": "table.body", "children": [] }
470
+ ]
471
+ }
472
+ },
473
+ "horizontal-with-header-cell": {
474
+ "description": "Horizontal Table — 컬럼 헤더는 Table.HeaderCell (출력: <th class='ncua-table__header-cell'>). 정렬 가능 컬럼은 sortDirection + onSort prop 추가. thead/tbody 분리.",
475
+ "props": {
476
+ "type": "horizontal",
477
+ "hoverable": true,
478
+ "children": [
479
+ {
480
+ "component": "table.header",
481
+ "children": [
482
+ {
483
+ "component": "table.row",
484
+ "children": [
485
+ { "component": "table.header-cell", "children": ["주문번호"] },
486
+ { "component": "table.header-cell", "children": ["상품명"] },
487
+ { "component": "table.header-cell", "children": ["주문일시"] }
488
+ ]
489
+ }
490
+ ]
491
+ },
492
+ {
493
+ "component": "table.body",
494
+ "children": [
495
+ {
496
+ "component": "table.row",
497
+ "children": [
498
+ { "component": "table.cell", "children": ["2508081832000001"] },
499
+ { "component": "table.cell", "children": ["프리미엄 노트북"] },
500
+ { "component": "table.cell", "children": ["2025-08-08 18:32"] }
501
+ ]
502
+ }
503
+ ]
504
+ }
505
+ ]
506
+ }
507
+ },
508
+ "vertical-form-label-with-required": {
509
+ "description": "P7/P12: Vertical Table 필수 라벨 표기 표준. ⚠️ ncua-table__required 는 NCDS Table SCSS 에서 font-size: var(--font-size-sm) (14px) 로 정의되는데 라벨 텍스트는 var(--font-size-xs) (13px) — baseline 이 어긋남. 정렬 보정을 위해 페이지 prefix wrapper 로 inline-flex + align-items: center 적용 권장. wrapper 클래스명은 페이지 prefix 통일 (예: 'page-vlabel') — 페이지 SCSS 에 .page-vlabel { display: inline-flex; align-items: center; gap: 4px; } .page-vlabel .ncua-table__required { line-height: 1; } 정의. component descriptor 트리로는 wrapper + raw span 을 한 번에 표현 불가 → render_to_html 출력 후 페이지 코드에서 wrapper 추가하거나, 라벨 텍스트 자체에 markup 포함 string 으로 전달. P16: 안내 Tooltip 이 필요하면 본 시나리오 대신 'vertical-form-label-with-tooltip' 을 사용하거나, 본 시나리오의 라벨 Cell 에 `tooltip: TooltipProps` prop 을 추가하면 된다 (Cell 내부 ncua-table__cell-inner / ncua-table__cell-label 로 자동 wrapping — 별도 페이지 wrapper 불필요).",
510
+ "props": {
511
+ "type": "vertical",
512
+ "children": [
513
+ {
514
+ "component": "table.body",
515
+ "children": [
516
+ {
517
+ "component": "table.row",
518
+ "_note": "필수 라벨 — children 첫 자식은 ncua-table__required span 의 raw HTML markup string, 그 다음 라벨 텍스트.",
519
+ "children": [
520
+ { "component": "table.cell", "props": { "isHeader": true }, "children": ["<span class=\"ncua-table__required\">*</span>", "상품명"] },
521
+ { "component": "table.cell", "children": ["프리미엄 노트북"] }
522
+ ]
523
+ },
524
+ {
525
+ "component": "table.row",
526
+ "children": [
527
+ { "component": "table.cell", "props": { "isHeader": true }, "children": ["<span class=\"ncua-table__required\">*</span>", "카테고리"] },
528
+ { "component": "table.cell", "children": ["전자기기"] }
529
+ ]
530
+ },
531
+ {
532
+ "component": "table.row",
533
+ "_note": "비필수 라벨 — required span 없이 텍스트만.",
534
+ "children": [
535
+ { "component": "table.cell", "props": { "isHeader": true }, "children": ["설명"] },
536
+ { "component": "table.cell", "children": ["고성능 프로세서와 16GB RAM 을 탑재."] }
537
+ ]
538
+ }
539
+ ]
540
+ }
541
+ ]
542
+ }
543
+ },
544
+ "vertical-form-label-with-tooltip": {
545
+ "description": "P16: Vertical Table 라벨 + 안내 Tooltip 표준. 라벨 옆 안내 아이콘은 Table.Cell.tooltip prop 으로 전달 — Cell 내부에 ncua-table__cell-inner / ncua-table__cell-label / .ncua-tooltip 구조로 자동 wrapping (ncua-table__cell--with-tooltip modifier 적용). 페이지 prefix wrapper(예: page-vlabel, sgr-tooltip-wrapper) 또는 라벨 셀 외부에 별도 Tooltip 컴포넌트 배치 금지 — 정렬 어긋남 + 발명 클래스 hallucination 의 주원인. tooltip 값은 NCDS Tooltip 의 React props 그대로 (type='short'/'long', tooltipType='black'/'white', content/title 등).",
546
+ "props": {
547
+ "type": "vertical",
548
+ "children": [
549
+ {
550
+ "component": "table.body",
551
+ "children": [
552
+ {
553
+ "component": "table.row",
554
+ "_note": "필수 + 안내 tooltip 라벨. children 첫 자식은 ncua-table__required span raw markup, 두 번째는 라벨 텍스트. tooltip 은 props.tooltip 으로 전달 — Cell 내부에서 라벨과 함께 inline-flex wrapping.",
555
+ "children": [
556
+ { "component": "table.cell", "props": { "isHeader": true, "tooltip": { "type": "short", "tooltipType": "black", "content": "외부에 노출되는 상품명입니다. 50자 이내로 입력하세요." } }, "children": ["<span class=\"ncua-table__required\">*</span>", "상품명"] },
557
+ { "component": "table.cell", "children": ["프리미엄 노트북"] }
558
+ ]
559
+ },
560
+ {
561
+ "component": "table.row",
562
+ "_note": "비필수 + 안내 tooltip. required span 없이 텍스트 + tooltip prop.",
563
+ "children": [
564
+ { "component": "table.cell", "props": { "isHeader": true, "tooltip": { "type": "long", "tooltipType": "white", "title": "카테고리 안내", "content": "상품을 분류하는 최상위 카테고리입니다. 변경 시 검색·노출 영역에 영향." } }, "children": ["카테고리"] },
565
+ { "component": "table.cell", "children": ["전자기기"] }
566
+ ]
567
+ }
568
+ ]
569
+ }
570
+ ]
571
+ }
572
+ },
573
+ "vertical-form-label": {
574
+ "description": "Vertical Table — 폼 라벨 레이아웃 (필수 마크 없는 버전). 각 row 의 좌측 라벨 셀은 Table.Cell with isHeader=true (출력: <th scope='row' class='ncua-table__cell'>). Table.HeaderCell 사용 금지 — 그 클래스는 Horizontal Table 의 thead 컬럼 헤더 전용. thead 없이 tbody 만 사용하며, 각 row 는 [라벨 cell(isHeader), 값 cell] 의 2-cell 구조. 필수 라벨 표기가 필요하면 'vertical-form-label-with-required', 라벨 옆 안내 tooltip 이 필요하면 'vertical-form-label-with-tooltip' 시나리오 사용.",
575
+ "props": {
576
+ "type": "vertical",
577
+ "children": [
578
+ {
579
+ "component": "table.body",
580
+ "children": [
581
+ {
582
+ "component": "table.row",
583
+ "children": [
584
+ { "component": "table.cell", "props": { "isHeader": true }, "children": ["상품명"] },
585
+ { "component": "table.cell", "children": ["프리미엄 노트북"] }
586
+ ]
587
+ },
588
+ {
589
+ "component": "table.row",
590
+ "children": [
591
+ { "component": "table.cell", "props": { "isHeader": true }, "children": ["카테고리"] },
592
+ { "component": "table.cell", "children": ["전자기기"] }
593
+ ]
594
+ },
595
+ {
596
+ "component": "table.row",
597
+ "children": [
598
+ { "component": "table.cell", "props": { "isHeader": true }, "children": ["가격"] },
599
+ { "component": "table.cell", "children": ["1,500,000"] }
600
+ ]
601
+ },
602
+ {
603
+ "component": "table.row",
604
+ "children": [
605
+ { "component": "table.cell", "props": { "isHeader": true }, "children": ["상태"] },
606
+ {
607
+ "component": "table.cell",
608
+ "children": [
609
+ { "component": "badge", "props": { "label": "판매중", "size": "xs", "type": "pill-outline", "color": "success" } }
610
+ ]
611
+ }
612
+ ]
613
+ }
614
+ ]
615
+ }
616
+ ]
617
+ }
618
+ }
619
+ }
620
+ },
621
+ "modal": {
622
+ "_note": "P18: Modal 은 Modal.Header / Modal.Content / Modal.Actions 3 compound 가 표준. 단일 시나리오(confirm) 가 가장 흔하지만 alert(단일 액션) / form(입력 폼) 도 자주 등장 — 세 가지 canonicalExamples 로 분기.",
623
+ "descriptionExtra": "[중요] 다이얼로그/팝업 표준 컴포넌트. 3 compound (Header/Content/Actions) 필수 — 직접 <div class='ncua-modal'> 마크업 작성 금지. size: xs/sm/md/lg/xl (콘텐츠 양에 따라). Actions.layout='horizontal' + align='stretch' 가 확인+취소 표준, align='center' 는 단일 액션. featuredIcon(Header) 으로 색상 강조 가능 (success/warning/error). Modal.Header.onClose 는 backdrop click 도 동일 핸들러로 동작.",
624
+ "aliasesExtra": [
625
+ "모달", "팝업", "다이얼로그", "dialog", "popup", "modal-dialog",
626
+ "확인 모달", "알림 모달", "입력 모달", "form modal", "confirm dialog", "alert dialog",
627
+ "오버레이", "overlay-dialog", "모달창", "팝업창"
628
+ ],
629
+ "bemClassesExtra": [],
630
+ "allowedChildren": {
631
+ "Modal": ["Modal.Header", "Modal.Content", "Modal.Actions"]
632
+ },
633
+ "canonicalExamples": {
634
+ "confirm": {
635
+ "description": "P18: 가장 일반적인 확인 모달. 취소 + 확인 두 버튼. modal.actions.align='stretch' 로 두 버튼이 같은 너비 분할. hierarchy='secondary-gray'(취소) + 'primary'(확인) 표준 쌍.",
636
+ "props": {
637
+ "open": true,
638
+ "size": "md",
639
+ "children": [
640
+ { "component": "modal.header", "props": { "title": "삭제하시겠습니까?", "onClose": "noop" } },
641
+ { "component": "modal.content", "children": ["삭제 후에는 복구할 수 없습니다."] },
642
+ {
643
+ "component": "modal.actions",
644
+ "props": { "layout": "horizontal", "align": "stretch" },
645
+ "children": [
646
+ { "component": "button", "props": { "label": "취소", "hierarchy": "secondary-gray", "size": "sm" } },
647
+ { "component": "button", "props": { "label": "삭제", "hierarchy": "primary", "size": "sm", "destructive": true } }
648
+ ]
649
+ }
650
+ ]
651
+ }
652
+ },
653
+ "alert": {
654
+ "description": "P18: 단일 액션 알림 모달 (정보 전달 후 확인만 받는 케이스). modal.actions 에 단일 버튼만 — align='center' 로 버튼 중앙 배치. 취소 버튼 없음.",
655
+ "props": {
656
+ "open": true,
657
+ "size": "sm",
658
+ "children": [
659
+ { "component": "modal.header", "props": { "title": "저장 완료", "onClose": "noop" } },
660
+ { "component": "modal.content", "children": ["변경사항이 정상적으로 저장되었습니다."] },
661
+ {
662
+ "component": "modal.actions",
663
+ "props": { "layout": "horizontal", "align": "center" },
664
+ "children": [
665
+ { "component": "button", "props": { "label": "확인", "hierarchy": "primary", "size": "sm" } }
666
+ ]
667
+ }
668
+ ]
669
+ }
670
+ },
671
+ "form": {
672
+ "description": "P18: 입력 폼 모달. modal.content 안에 input / select-box / textarea 등 폼 컴포넌트 배치. size='lg' 권장 (입력 영역 확보). 폼 라벨이 여러 개면 modal.content 안에 table type='vertical' 배치하는 패턴도 가능 (vertical-form-label 시나리오 참고).",
673
+ "props": {
674
+ "open": true,
675
+ "size": "lg",
676
+ "children": [
677
+ { "component": "modal.header", "props": { "title": "새 카테고리 추가", "onClose": "noop" } },
678
+ {
679
+ "component": "modal.content",
680
+ "children": [
681
+ { "component": "input", "props": { "label": "카테고리명", "placeholder": "예: 의류", "required": true } },
682
+ { "component": "select-box", "props": { "label": "상위 카테고리", "placeholder": "선택해주세요", "optionItems": [{ "id": "root", "label": "(최상위)" }, { "id": "fashion", "label": "패션" }] } }
683
+ ]
684
+ },
685
+ {
686
+ "component": "modal.actions",
687
+ "props": { "layout": "horizontal", "align": "stretch" },
688
+ "children": [
689
+ { "component": "button", "props": { "label": "취소", "hierarchy": "secondary-gray", "size": "sm" } },
690
+ { "component": "button", "props": { "label": "추가", "hierarchy": "primary", "size": "sm" } }
691
+ ]
692
+ }
693
+ ]
694
+ }
695
+ }
696
+ }
697
+ },
698
+ "block-container": {
699
+ "_note": "P10: BlockContainer 는 페이지 블록의 외곽 컨테이너. children 으로 block-header + 본문 컴포넌트(table/data-grid/자유영역) 조합. AI 가 sgr-block / sgr-block-container 로 우회하지 않도록 다중 시나리오 등록.",
700
+ "descriptionExtra": "[중요] 페이지 블록 외곽 컨테이너. 표준 자식 구조: BlockHeader + BlockContainer.Body(필수 wrapping — P14 룰). 본문은 Body 안에 table/data-grid/form 컴포넌트 배치. 직접 <section class='ncua-block-container'> 마크업 금지 — overflow:hidden / border-radius 등 CDN CSS 보호 받지 못함. 페이지 prefix wrapper (sgr-block / page-section) 우회 절대 금지.",
701
+ "aliasesExtra": [
702
+ "블록 컨테이너", "블록", "섹션", "section", "panel", "패널", "페이지 블록", "박스 컨테이너",
703
+ "card-container", "page-section", "content-section", "form-section", "info-section",
704
+ "white-box", "흰 박스", "정보 블록", "폼 블록", "데이터 블록"
705
+ ],
706
+ "bemClassesExtra": [],
707
+ "allowedChildren": {
708
+ "BlockContainer": {
709
+ "recommended": ["BlockHeader", "BlockContainer.Body"],
710
+ "optional": ["Table", "DataGrid"]
711
+ }
712
+ },
713
+ "canonicalExample": {
714
+ "props": {
715
+ "children": [
716
+ { "component": "block-header", "props": { "title": "기본 정보" } },
717
+ { "component": "button", "props": { "label": "저장", "hierarchy": "primary", "size": "sm" } }
718
+ ]
719
+ }
720
+ },
721
+ "canonicalExamples": {
722
+ "_note": "P14: BlockContainer 의 본문은 반드시 BlockContainer.Body subcomponent 로 wrap. 직접 children 으로 table/data-grid 를 넣으면 ncua-block-container__body 패딩(16px 24px) 누락 — 시각적 호흡 없음. 정확한 구조: <section.ncua-block-container> > <header.ncua-block-header> + <div.ncua-block-container__body> > [실제 컨텐츠].",
723
+ "form-block": {
724
+ "description": "P14: 폼 페이지 표준 블록 — BlockHeader(필수 입력 안내 포함) + BlockContainer.Body wrapping > Vertical Table. 간편상품등록 같은 다중 필드 폼.",
725
+ "props": {
726
+ "children": [
727
+ { "component": "block-header", "props": { "title": "기본정보", "showRequiredNotice": true } },
728
+ {
729
+ "component": "block-container.body",
730
+ "children": [
731
+ {
732
+ "component": "table",
733
+ "props": {
734
+ "type": "vertical",
735
+ "children": [
736
+ {
737
+ "component": "table.body",
738
+ "children": [
739
+ {
740
+ "component": "table.row",
741
+ "children": [
742
+ { "component": "table.cell", "props": { "isHeader": true }, "children": ["상품명"] },
743
+ { "component": "table.cell", "children": ["프리미엄 노트북"] }
744
+ ]
745
+ }
746
+ ]
747
+ }
748
+ ]
749
+ }
750
+ }
751
+ ]
752
+ }
753
+ ]
754
+ }
755
+ },
756
+ "data-block": {
757
+ "description": "P14: 목록 블록 — BlockHeader + BlockContainer.Body wrapping > DataGrid. 검색결과/주문목록/회원목록 등 표 형식 데이터 페이지.",
758
+ "props": {
759
+ "children": [
760
+ { "component": "block-header", "props": { "title": "주문 목록" } },
761
+ {
762
+ "component": "block-container.body",
763
+ "children": [
764
+ {
765
+ "component": "data-grid",
766
+ "props": {
767
+ "variant": "search-result",
768
+ "children": [
769
+ { "component": "data-grid.summary", "children": ["전체 128건"] },
770
+ {
771
+ "component": "data-grid.table",
772
+ "children": [
773
+ {
774
+ "component": "table.header",
775
+ "children": [
776
+ {
777
+ "component": "table.row",
778
+ "children": [
779
+ { "component": "table.header-cell", "children": ["주문번호"] },
780
+ { "component": "table.header-cell", "children": ["상태"] }
781
+ ]
782
+ }
783
+ ]
784
+ },
785
+ { "component": "table.body", "children": [] }
786
+ ]
787
+ }
788
+ ]
789
+ }
790
+ }
791
+ ]
792
+ }
793
+ ]
794
+ }
795
+ },
796
+ "info-block": {
797
+ "description": "P14: 안내/설명 블록 — BlockHeader + BlockContainer.Body wrapping > 자유 텍스트. 페이지 안내, 도움말, 정책 안내 등 텍스트 위주.",
798
+ "props": {
799
+ "children": [
800
+ { "component": "block-header", "props": { "title": "이용 안내", "description": "본 페이지에서는 상품을 간편하게 등록할 수 있습니다." } },
801
+ {
802
+ "component": "block-container.body",
803
+ "children": ["본 화면에서 입력한 정보는 저장 후에도 수정할 수 있습니다."]
804
+ }
805
+ ]
806
+ }
807
+ }
808
+ }
809
+ },
810
+ "block-header": {
811
+ "_note": "P10: BlockHeader 는 props 기반. title(필수) + description / action / badge / tooltip / showRequiredNotice / collapsible / showDivider 등 풍부한 props. ⚠️ showRequiredNotice=true 면 '*는 필수 입력 항목입니다.' 안내가 자동 렌더 — 페이지 prefix(sgr-block-header__required 등) 로 직접 만들 필요 없음. AI 가 BEM 모방하지 않도록 props 사용을 canonical 로 명시.",
812
+ "descriptionExtra": "[중요] BlockContainer 의 헤더 영역 표준 컴포넌트. title(필수) + description + action(우측 버튼) + badge + tooltip + showRequiredNotice + collapsible. BlockHeader.SubTitle 으로 섹션 내 하위 제목 분리 가능 (action/required/divider 자체 지원). 필수 안내 텍스트는 showRequiredNotice prop 으로 자동 — 페이지 prefix span 으로 직접 작성 금지.",
813
+ "aliasesExtra": [
814
+ "블록 헤더", "섹션 제목", "섹션 헤더", "패널 헤더", "block-title", "section-header",
815
+ "section-title", "form-section-header", "panel-title", "card-header",
816
+ "서브 타이틀", "subtitle", "BlockHeader.SubTitle", "필수 안내", "required-notice"
817
+ ],
818
+ "allowedChildren": {
819
+ "BlockHeader": ["BlockHeader.SubTitle"]
820
+ },
821
+ "bemClassesExtra": [],
822
+ "canonicalExamples": {
823
+ "default": {
824
+ "description": "기본 블록 헤더 — title 만. 가장 단순한 형태.",
825
+ "props": {
826
+ "title": "기본정보"
827
+ }
828
+ },
829
+ "with-required-notice": {
830
+ "description": "⚠️ NCDS 가 제공하는 표준 패턴 — showRequiredNotice=true 로 '*는 필수 입력 항목입니다.' 안내를 컴포넌트가 자동 렌더. 페이지 prefix(sgr-block-header__required / page-form__required-notice 등) 로 직접 만들지 말 것. BlockHeader props 하나로 해결.",
831
+ "props": {
832
+ "title": "기본정보",
833
+ "showRequiredNotice": true
834
+ }
835
+ },
836
+ "with-tooltip": {
837
+ "description": "라벨 옆 도움말 툴팁. tooltip prop 이 ReactNode 라 객체로 전달 — content/iconStyle/position 등 tooltip 의 props 객체.",
838
+ "props": {
839
+ "title": "상품 정보",
840
+ "tooltip": {
841
+ "tooltipType": "white",
842
+ "type": "long",
843
+ "size": "sm",
844
+ "iconStyle": "help-circle",
845
+ "iconType": "stroke",
846
+ "position": "auto",
847
+ "content": "쇼핑몰에 노출되는 핵심 상품 정보입니다."
848
+ }
849
+ }
850
+ },
851
+ "with-action-buttons": {
852
+ "description": "헤더 우측 action 영역에 버튼 배치. action prop 은 ReactNode — 단일 버튼 또는 버튼 배열.",
853
+ "props": {
854
+ "title": "상품 목록",
855
+ "action": [
856
+ { "component": "button", "props": { "label": "초기화", "size": "xs", "hierarchy": "secondary-gray" } },
857
+ { "component": "button", "props": { "label": "검색", "size": "xs", "hierarchy": "primary" } }
858
+ ]
859
+ }
860
+ },
861
+ "collapsible": {
862
+ "description": "접고 펼치는 헤더. collapsible=true 면 우측에 chevron 토글 노출. 긴 폼 페이지에서 섹션별 접기 용도.",
863
+ "props": {
864
+ "title": "고급 설정",
865
+ "collapsible": true
866
+ }
867
+ }
868
+ }
869
+ },
870
+ "tooltip": {
871
+ "_note": "P9/P11: Tooltip 은 단일 컴포넌트. ⚠️⚠️ React props 와 CDN JS options 가 다름. React 모드는 iconStyle (help-circle | alert-circle) prop 사용 가능. CDN HTML 모드는 window.ncua.Tooltip.createShort(title, content, options) / createLong 정적 팩토리만 사용 — new Tooltip(...) 금지. CDN options 에는 iconStyle 없음(iconType 만). 자세한 CDN spec 은 render_to_html 응답의 js.api 필드 참조 (constructor / constructorParams / example). ⚠️ P19: tooltipType 의 React 기본값(white) 과 CDN 기본값(black) 이 다르다 — godomall5 페이지에서 발견된 색상 mismatch 의 근원. CDN HTML 모드에서는 반드시 options.tooltipType 명시. 라벨 옆 인라인 배치 시 세로 정렬 어긋남 방지 페이지 SCSS 보정(`.ncua-tooltip { display: inline-flex; vertical-align: middle; }`) 필수 — 'inline-with-label-alignment' 시나리오 참고.",
872
+ "descriptionExtra": "[중요] 폼 필드 라벨 옆 도움말 / 정보 안내용 단일 컴포넌트. ⚠️ React props default tooltipType='white', CDN cdnDefaults.tooltipType='black' — 두 환경 default 가 다르다. HTML 모드에서는 항상 options.tooltipType 명시. type='short' (단일 라인 본문) / type='long' (헤더 + 본문) 두 형태. CDN 팩토리는 createShort/createLong 분기 — type 옵션을 다시 지정하면 충돌 가능하므로 팩토리 이름과 type 옵션은 일치시킬 것. iconStyle prop 은 React 전용 — CDN options 에 넣지 말 것 (대신 iconType=stroke|fill). 라벨 옆 인라인 배치는 부모 inline-flex + .ncua-tooltip { display: inline-flex; vertical-align: middle; } 보정 필수.",
873
+ "aliasesExtra": [
874
+ "툴팁", "툴팁 색상", "툴팁 위치", "툴팁 정렬", "라벨 옆 도움말", "도움말 아이콘", "물음표 아이콘",
875
+ "help icon", "help tooltip", "info tooltip", "안내 툴팁", "정보 툴팁",
876
+ "createShort", "createLong", "tooltipType-default", "iconStyle React-only",
877
+ "baseline 정렬 보정", "inline-flex 보정"
878
+ ],
879
+ "_cdnApiReference": {
880
+ "constructor": "window.ncua.Tooltip.createShort(title, content?, options?) | window.ncua.Tooltip.createLong(title, content?, options?)",
881
+ "allowedOptions": ["position", "type", "tooltipType", "iconType", "size", "hideArrow", "zIndex", "useShadowDOM", "className"],
882
+ "forbiddenAsOption": ["iconStyle", "iconColor", "content (it's the 2nd arg, not an option)", "title (it's the 1st arg, not an option)"],
883
+ "example": "const tip = window.ncua.Tooltip.createShort('도움말', '상품 검색에 사용되는 키워드입니다.', { tooltipType: 'white', iconType: 'stroke', size: 'sm', position: 'auto' });\\nel.appendChild(tip.getElement());"
884
+ },
885
+ "canonicalExamples": {
886
+ "icon-help-form-field": {
887
+ "description": "P14: 폼 필드 라벨 옆 도움말 툴팁 NCDS 표준. type=short (NCDS docs 권장 — long 은 헤더+본문 분리형). iconStyle=help-circle, size=sm, position=auto. tooltipType 기본값: React props=white / CDN cdnDefaults=black — 사용 환경에 맞춰 명시. Vertical Table 라벨 셀 안에서 라벨 텍스트 우측에 인라인 배치.",
888
+ "props": {
889
+ "tooltipType": "white",
890
+ "type": "short",
891
+ "size": "sm",
892
+ "iconStyle": "help-circle",
893
+ "iconType": "stroke",
894
+ "position": "auto",
895
+ "content": "쇼핑몰에 노출되는 상품 이름입니다. 고객이 검색할 때 사용되므로 핵심 키워드를 포함하여 작성하세요."
896
+ }
897
+ },
898
+ "with-title-and-body": {
899
+ "description": "헤더(title) + 본문(content) 분리형 툴팁. long type 은 헤더가 있을 때만 사용 — 단순 한 줄 안내에는 short 사용. tooltipType 은 React props/CDN cdnDefaults 분기 참고.",
900
+ "props": {
901
+ "tooltipType": "white",
902
+ "type": "long",
903
+ "size": "sm",
904
+ "iconStyle": "help-circle",
905
+ "iconType": "stroke",
906
+ "position": "auto",
907
+ "title": "검색 키워드",
908
+ "content": "상품 검색 시 매칭되는 키워드입니다. 콤마(,)로 구분하여 입력하세요."
909
+ }
910
+ },
911
+ "alert-warning": {
912
+ "description": "경고/에러 안내용. iconStyle=alert-circle, tooltipType=black 으로 강조. (React 전용 prop iconStyle 포함)",
913
+ "props": {
914
+ "tooltipType": "black",
915
+ "type": "short",
916
+ "size": "sm",
917
+ "iconStyle": "alert-circle",
918
+ "iconType": "stroke",
919
+ "position": "auto",
920
+ "content": "노출안함 상태에서는 판매함이어도 쇼핑몰에서 보이지 않습니다."
921
+ }
922
+ },
923
+ "inline-with-label-alignment": {
924
+ "description": "P15: 폼 라벨 텍스트 옆 인라인 배치 시 SVG 가 baseline 위로 튀어오르는 정렬 갭 보정. NCDS CDN CSS 는 .ncua-tooltip 에 display/vertical-align 을 비워둠(inline default) — 라벨 옆 배치 시 SVG 가 텍스트 baseline 에 걸려 위로 올라감. 페이지 SCSS 에 `.ncua-tooltip { display: inline-flex; vertical-align: middle; }` 한 줄 추가 또는 라벨 wrapper(예: .sgr-label-tooltip) 에 `display: inline-flex; align-items: center;` 적용 + 자식 SVG 에 vertical-align: middle 강제. wrapper 자체에 inline-flex 만 적용하면 부족 — .ncua-tooltip 이 inline 이라 flex 컨텍스트가 끊김. 부모 wrapper 와 .ncua-tooltip 양쪽에 정렬 보정 필요. (NCDS docs Tooltip §3.6 참조)",
925
+ "props": {
926
+ "tooltipType": "white",
927
+ "type": "short",
928
+ "size": "sm",
929
+ "iconStyle": "help-circle",
930
+ "iconType": "stroke",
931
+ "position": "auto",
932
+ "content": "라벨 텍스트 옆 인라인 배치 시 페이지 SCSS 에서 .ncua-tooltip { display: inline-flex; vertical-align: middle; } 보정 필수"
933
+ }
934
+ },
935
+ "cdn-html-factory": {
936
+ "description": "⚠️ CDN HTML 모드 전용 — window.ncua.Tooltip.createShort(title, content, options) / createLong(title, content, options) 정적 팩토리. js.api.cdnDefaults 의 NCDS 표준값: type=short, tooltipType=black, iconType=stroke, position=auto, size=sm (React props default 와 다름 — React 는 tooltipType=white 가 default). 한 줄 안내는 createShort, 헤더+본문 분리는 createLong. iconStyle / iconColor 는 CDN options 에 없음. render_to_html 응답의 js.api.example 그대로 복사 — new Tooltip(options) 패턴 금지.",
937
+ "props": {
938
+ "type": "short",
939
+ "tooltipType": "black",
940
+ "iconType": "stroke",
941
+ "size": "sm",
942
+ "position": "auto",
943
+ "title": "도움말",
944
+ "content": "상품 검색에 사용되는 키워드입니다."
945
+ }
946
+ }
947
+ }
948
+ },
949
+ "page-title": {
950
+ "_note": "P7: PageTitle 은 props 기반 (subComponents 없음). breadcrumbItems / title / primaryAction / secondaryAction / guideButton / onBack / variant prop 으로 구성. AI 가 sgr-page-title 같은 페이지-prefix 로 우회하지 않도록 명시적 canonicalExamples 등록. 출력은 ncua-page-title__page-header / __title-container / __title-row / __title / __action-area 등 정밀 BEM.",
951
+ "descriptionExtra": "[중요] 페이지 최상단 타이틀 영역 표준. breadcrumbItems + title + primaryAction(우측 강조 버튼) + secondaryAction(취소/목록) + guideButton + onBack + variant(default/detail/fixed). detail variant 는 onBack 으로 좌측 back button 노출. fixed variant 는 스크롤 시 상단 고정. 페이지 prefix(sgr-page-title / page-header) 우회 금지.",
952
+ "aliasesExtra": [
953
+ "페이지 타이틀", "페이지 제목", "페이지 헤더", "page header", "page-heading",
954
+ "breadcrumb header", "타이틀 바", "상단 타이틀", "header section",
955
+ "back-button page", "상세 페이지 헤더", "fixed page header", "sticky header"
956
+ ],
957
+ "canonicalExamples": {
958
+ "default": {
959
+ "description": "일반 목록/설정 페이지 표준. Breadcrumb + Title + Secondary/Primary Action 버튼 조합. variant 미지정 시 Default.",
960
+ "props": {
961
+ "breadcrumbItems": [
962
+ { "label": "상품", "href": "/goods" },
963
+ { "label": "상품 관리", "href": "/goods/list" },
964
+ { "label": "상품 간편 등록" }
965
+ ],
966
+ "title": "상품 간편 등록",
967
+ "secondaryAction": { "component": "button", "props": { "label": "목록", "size": "md", "hierarchy": "secondary-gray" } },
968
+ "primaryAction": { "component": "button", "props": { "label": "저장", "size": "md", "hierarchy": "primary" } }
969
+ }
970
+ },
971
+ "with-guide-button": {
972
+ "description": "타이틀 우측 가이드 버튼 포함. 사용자가 화면 사용법을 즉시 확인할 수 있는 인라인 가이드 트리거.",
973
+ "props": {
974
+ "breadcrumbItems": [
975
+ { "label": "상품", "href": "/goods" },
976
+ { "label": "상품 간편 등록" }
977
+ ],
978
+ "title": "상품 간편 등록",
979
+ "guideButton": { "component": "button", "props": { "label": "가이드", "size": "xs", "hierarchy": "secondary-gray" } },
980
+ "secondaryAction": { "component": "button", "props": { "label": "목록", "size": "md", "hierarchy": "secondary-gray" } },
981
+ "primaryAction": { "component": "button", "props": { "label": "저장", "size": "md", "hierarchy": "primary" } }
982
+ }
983
+ },
984
+ "detail-with-back": {
985
+ "description": "상세 조회/수정 페이지. variant=detail + onBack 사용 — 좌측 back button 노출. 4 depth 이하에서 사용.",
986
+ "props": {
987
+ "variant": "detail",
988
+ "breadcrumbItems": [
989
+ { "label": "상품", "href": "/goods" },
990
+ { "label": "상품 관리", "href": "/goods/list" },
991
+ { "label": "상품 상세" }
992
+ ],
993
+ "title": "상품 상세",
994
+ "onBack": "noop",
995
+ "secondaryAction": { "label": "삭제", "size": "md", "hierarchy": "destructive-secondary" },
996
+ "primaryAction": { "label": "수정", "size": "md", "hierarchy": "primary" }
997
+ }
998
+ },
999
+ "fixed-on-scroll": {
1000
+ "description": "스크롤 시 상단 고정. variant=fixed — Breadcrumb 자동 숨김. 페이지 상단 sticky 영역 용도.",
1001
+ "props": {
1002
+ "variant": "fixed",
1003
+ "title": "상품 간편 등록",
1004
+ "secondaryAction": { "component": "button", "props": { "label": "목록", "size": "md", "hierarchy": "secondary-gray" } },
1005
+ "primaryAction": { "component": "button", "props": { "label": "저장", "size": "md", "hierarchy": "primary" } }
1006
+ }
1007
+ }
1008
+ }
1009
+ },
1010
+ "horizontal-tab": {
1011
+ "_note": "P5-4b: HorizontalTab 은 compound 가 아닌 menus 배열 prop 으로 메뉴를 받는다. 자식 컴포넌트로 Tab.Item 을 만들지 말고 menus 데이터 배열만 전달. 우측에 다른 인라인 컨트롤(체크박스, 버튼 등) 을 함께 배치할 때는 페이지 prefix wrapper(예: 'sgr-tab-row') 로 flex 정렬 — inline style 금지, NCDS spacing token 만 사용. ⚠️ P17: Swiper.js JS-instantiated 컴포넌트. render_to_html 의 정적 HTML 출력은 swiper wrapper + 모든 menu 의 <button class='ncua-tab-button'> (active 표시 없음) — CDN JS 가 DOMContentLoaded 에서 swiper 인스턴스 생성 + activeTab 매칭 menu 의 button 에 'is-active' 클래스 동적 부착. 정적 HTML 시점에 active 표시 부재는 정상 동작이며 js.required=true placeholder 패턴이다.",
1012
+ "descriptionExtra": "[중요] 가로 탭 컴포넌트. type: underline / underline-fill / button-primary / button-white / line-vertical. size: sm/md/lg. menus 배열 + activeTab(id 매칭). ⚠️ Swiper.js JS-instantiated — 정적 HTML 에 active 표시 없음(CDN JS 마운트 시 .ncua-tab-button.is-active 자동 부착). 발명 modifier(--active / is-current) 수동 추가 금지. swiper-wrapper / swiper-slide 마크업 직접 작성 금지.",
1013
+ "aliasesExtra": [
1014
+ "가로 탭", "탭", "탭 메뉴", "tabs", "tab-bar", "tab-strip", "tab navigation",
1015
+ "underline tabs", "button tabs", "필터 탭", "상태 탭", "카테고리 탭",
1016
+ "Swiper tab", "horizontal navigation", "탭 네비게이션"
1017
+ ],
1018
+ "canonicalExamples": {
1019
+ "default": {
1020
+ "description": "기본 가로 탭. menus 배열로 항목 정의. activeTab 으로 현재 선택 (menu.id 일치). activeTab 미지정 시 CDN JS 가 첫 menu 를 자동 활성화. ⚠️ 출력 HTML 의 <button> 에 '--active' / 'is-current' 같은 modifier 를 수동 추가 금지 — CDN JS 가 마운트 시 '.ncua-tab-button.is-active' 를 자동 부착한다 (state class, BEM modifier 아님).",
1021
+ "props": {
1022
+ "size": "md",
1023
+ "type": "underline",
1024
+ "activeTab": "all",
1025
+ "menus": [
1026
+ { "id": "all", "label": "전체" },
1027
+ { "id": "active", "label": "활성" },
1028
+ { "id": "inactive", "label": "비활성" }
1029
+ ]
1030
+ }
1031
+ },
1032
+ "with-inline-right-control": {
1033
+ "description": "P9: HorizontalTab 우측에 인라인 컨트롤(체크박스/버튼) 을 배치하는 패턴. 페이지 prefix wrapper(예: <div class='sgr-tab-row'>) 로 flex row + space-between 적용. wrapper CSS 는 페이지 SCSS 에 정의 (예: { display: flex; align-items: center; gap: var(--spacing-md); justify-content: space-between }). inline style 사용 금지. canonicalExamples 의 component descriptor 트리로는 wrapper 를 직접 표현할 수 없으므로 별도 페이지 BEM 으로 render_to_html_batch 호출 후 wrapper 로 감싸기. P17: 본 시나리오도 Swiper JS-instantiated — 정적 HTML 시점에 activeTab 매칭 button 에 시각적 active 표시는 없다. CDN JS 마운트 후 .ncua-tab-button.is-active 자동 적용.",
1034
+ "props": {
1035
+ "size": "sm",
1036
+ "type": "button-white",
1037
+ "activeTab": "pc",
1038
+ "menus": [
1039
+ { "id": "pc", "label": "PC 쇼핑몰 상세설명" },
1040
+ { "id": "mobile", "label": "모바일 쇼핑몰 상세설명" }
1041
+ ]
1042
+ }
1043
+ }
1044
+ }
1045
+ },
1046
+ "vertical-tab": {
1047
+ "_note": "P5-4b: VerticalTab 은 menus 배열 prop 으로 메뉴를 받는다. 자식 컴포넌트로 Tab.Item 을 만들지 말 것. P18: 페이지 좌측 nav (설정 페이지·관리자 sub-section 진입) 와 폼 단계 표시(step-nav) 가 가장 흔한 사용 패턴.",
1048
+ "descriptionExtra": "[중요] 세로 탭/사이드 nav 컴포넌트. menus 배열 + activeTab(id). 설정 페이지 좌측 nav / 폼 멀티스텝 표시 / 관리자 sub-section 진입의 표준. 활성 클래스는 .ncua-tab-button.is-active (CDN JS 마운트 시 자동). 페이지 prefix wrapper (sgr-side-nav / page-vnav) 로 우회 금지 — type prop 으로 디자인 분기 (default 등).",
1049
+ "aliasesExtra": [
1050
+ "세로 탭", "사이드 탭", "사이드 nav", "side-nav", "side-tab", "vertical-nav",
1051
+ "left-nav", "settings sidebar", "step-nav", "스텝 탭", "단계 탭",
1052
+ "설정 좌측 메뉴", "관리자 nav", "관리자 사이드바", "wizard nav"
1053
+ ],
1054
+ "canonicalExamples": {
1055
+ "default": {
1056
+ "description": "P18: 기본 세로 탭 (설정 페이지 좌측 nav 표준). menus 배열로 항목 정의, activeTab 으로 현재 선택. 출력 HTML 의 active 클래스는 CDN JS 가 마운트 시 부착 — 정적 마크업에 수동 추가 금지. 활성 클래스는 .ncua-tab-button.is-active (state class).",
1057
+ "props": {
1058
+ "type": "default",
1059
+ "activeTab": "general",
1060
+ "menus": [
1061
+ { "id": "general", "label": "일반 설정" },
1062
+ { "id": "security", "label": "보안 설정" },
1063
+ { "id": "notification", "label": "알림 설정" }
1064
+ ]
1065
+ }
1066
+ },
1067
+ "settings-many-sections": {
1068
+ "description": "P18: 관리자 설정 페이지의 다중 섹션 nav. 6~10개 메뉴 항목까지 확장. 항목이 많을 때도 menus 배열만 늘리고 별도 그룹 컴포넌트(GroupHeader 등) 만들지 말 것 — NCDS 표준에 없음. 그룹 구분이 시각적으로 필요하면 라벨 자체에 '— 운영' 같은 표기 또는 페이지 prefix wrapper 로 분리.",
1069
+ "props": {
1070
+ "type": "default",
1071
+ "activeTab": "shop-info",
1072
+ "menus": [
1073
+ { "id": "shop-info", "label": "쇼핑몰 정보" },
1074
+ { "id": "domain", "label": "도메인 설정" },
1075
+ { "id": "payment", "label": "결제 설정" },
1076
+ { "id": "delivery", "label": "배송 설정" },
1077
+ { "id": "tax", "label": "세금 설정" },
1078
+ { "id": "member-policy", "label": "회원 정책" },
1079
+ { "id": "order-policy", "label": "주문 정책" }
1080
+ ]
1081
+ }
1082
+ },
1083
+ "step-nav": {
1084
+ "description": "P18: 멀티 스텝 폼 좌측 진행 상태 표시. menus 의 label 에 'STEP 1. 기본정보' 같은 순서 prefix 포함. activeTab 으로 현재 단계 표시 — 완료 단계 시각화는 CDN JS 동적 처리 또는 페이지 prefix wrapper 로 별도. label 안에 SVG icon 임베드 금지.",
1085
+ "props": {
1086
+ "type": "default",
1087
+ "activeTab": "step-2",
1088
+ "menus": [
1089
+ { "id": "step-1", "label": "STEP 1. 기본 정보" },
1090
+ { "id": "step-2", "label": "STEP 2. 옵션·재고" },
1091
+ { "id": "step-3", "label": "STEP 3. 이미지·상세" },
1092
+ { "id": "step-4", "label": "STEP 4. 노출 설정" }
1093
+ ]
1094
+ }
1095
+ }
1096
+ }
1097
+ },
1098
+ "dropdown": {
1099
+ "_note": "P5-4b: Dropdown 은 trigger + groups 배열 props 로 구조 정의. 자식 컴포넌트로 Dropdown.Item 만들지 말 것. P18: 가장 흔한 패턴은 단일 그룹 액션 메뉴(default) / 그룹 구분선 포함 메뉴(grouped-with-divider) / 아이콘 trigger (icon-trigger) 세 가지.",
1100
+ "descriptionExtra": "[중요] 액션 메뉴/선택 메뉴 표준. trigger(ReactNode) + groups(2차원 배열 — 구분선 자동) props 기반. align: left/right (테이블 우측 컬럼은 right 권장 — 화면 밖 잘림 방지). destructive 액션은 별도 그룹 마지막에 단독. native <select> 또는 div 로 우회 금지.",
1101
+ "aliasesExtra": [
1102
+ "드롭다운", "더보기 메뉴", "액션 메뉴", "action-menu", "context-menu", "kebab-menu",
1103
+ "more-menu", "row-actions", "row 액션", "케밥 메뉴", "옵션 메뉴",
1104
+ "정렬 메뉴", "필터 메뉴", "선택 메뉴"
1105
+ ],
1106
+ "canonicalExamples": {
1107
+ "default": {
1108
+ "description": "P18: 단순 액션 메뉴 (구분선 없는 단일 그룹). groups 는 배열의 배열이지만 그룹 1개만 사용. trigger 는 일반 Button (라벨 텍스트).",
1109
+ "props": {
1110
+ "align": "left",
1111
+ "trigger": { "component": "button", "props": { "label": "정렬 기준", "size": "sm", "hierarchy": "secondary-gray" } },
1112
+ "groups": [
1113
+ [
1114
+ { "id": "recent", "label": "최근 등록순" },
1115
+ { "id": "popular", "label": "인기순" },
1116
+ { "id": "price-low", "label": "가격 낮은순" },
1117
+ { "id": "price-high", "label": "가격 높은순" }
1118
+ ]
1119
+ ]
1120
+ }
1121
+ },
1122
+ "grouped-with-divider": {
1123
+ "description": "P18: 그룹 구분선 포함 액션 메뉴 (편집/삭제 등 행 액션의 표준). groups 배열의 각 sub-array 사이에 구분선 자동. 위험 액션(삭제 등) 은 destructive=true 로 마지막 그룹에 단독 배치 권장.",
1124
+ "props": {
1125
+ "align": "left",
1126
+ "trigger": { "component": "button", "props": { "label": "더보기", "size": "sm", "hierarchy": "secondary-gray" } },
1127
+ "groups": [
1128
+ [
1129
+ { "id": "edit", "label": "수정" },
1130
+ { "id": "duplicate", "label": "복제" },
1131
+ { "id": "export", "label": "내보내기" }
1132
+ ],
1133
+ [
1134
+ { "id": "archive", "label": "보관함으로 이동" }
1135
+ ],
1136
+ [
1137
+ { "id": "delete", "label": "삭제", "destructive": true }
1138
+ ]
1139
+ ]
1140
+ }
1141
+ },
1142
+ "icon-trigger": {
1143
+ "description": "P18: 아이콘 버튼 trigger (테이블 row 의 inline 액션 / kebab 메뉴 등). trigger 의 Button 에 iconLeft + onlyIcon=true 또는 IconButton 컴포넌트 사용. align='right' 로 메뉴 우측 정렬 (테이블 우측 끝 컬럼에서 화면 밖 잘림 방지).",
1144
+ "props": {
1145
+ "align": "right",
1146
+ "trigger": { "component": "icon-button", "props": { "iconStyle": "more-vertical", "size": "sm", "hierarchy": "tertiary-gray" } },
1147
+ "groups": [
1148
+ [
1149
+ { "id": "view", "label": "상세 보기" },
1150
+ { "id": "edit", "label": "수정" }
1151
+ ],
1152
+ [
1153
+ { "id": "delete", "label": "삭제", "destructive": true }
1154
+ ]
1155
+ ]
1156
+ }
1157
+ }
1158
+ }
1159
+ },
1160
+ "select-box": {
1161
+ "_note": "P5-4b: SelectBox 는 optionItems 배열로 항목 정의. value 는 선택된 항목 객체 또는 id. 자식 컴포넌트로 만들지 말 것. P18: native <select> 또는 dropdown 으로 우회하지 말 것 — select-box 가 NCDS 표준 진입점.",
1162
+ "descriptionExtra": "[중요] 단일/복수 항목 선택 입력 컴포넌트. value 가 단일이면 multiple=false (기본), 배열이면 multiple=true. 한국어 검색 시 '셀렉트', '드롭다운', '선택상자' 등 다양한 표기 — sidecar aliases 로 매칭 보강.",
1163
+ "aliasesExtra": [
1164
+ "selectbox", "select", "셀렉트", "셀렉트박스", "선택상자", "선택박스", "드롭다운 선택", "옵션 선택", "select-input", "dropdown-input", "option-picker", "콤보박스", "combobox"
1165
+ ],
1166
+ "canonicalExamples": {
1167
+ "default": {
1168
+ "description": "기본 선택. optionItems 로 옵션 정의, value 로 선택값.",
1169
+ "props": {
1170
+ "size": "md",
1171
+ "placeholder": "선택해주세요",
1172
+ "optionItems": [
1173
+ { "id": "option-1", "label": "옵션 1" },
1174
+ { "id": "option-2", "label": "옵션 2" },
1175
+ { "id": "option-3", "label": "옵션 3" }
1176
+ ]
1177
+ }
1178
+ },
1179
+ "multiple": {
1180
+ "description": "복수 선택. multiple=true + value 는 배열.",
1181
+ "props": {
1182
+ "size": "md",
1183
+ "multiple": true,
1184
+ "placeholder": "여러 개 선택",
1185
+ "optionItems": [
1186
+ { "id": "tag-1", "label": "태그 1" },
1187
+ { "id": "tag-2", "label": "태그 2" }
1188
+ ]
1189
+ }
1190
+ }
1191
+ }
1192
+ },
1193
+ "switch": {
1194
+ "_note": "P22: Switch 는 좌/우 두 옵션 토글 컴포넌트 (Apple segment-control 패턴). left/right props 로 두 옵션 정의, value 로 현재 선택. 사이즈: xxs/xs/sm/md. ⚠️ godomall5 페이지에서 'CDN 미제공 active/inactive 스타일' 이라 단언하고 fallback CSS 직접 작성한 hallucination 발생 — NCDS CDN CSS 가 .ncua-switch__option--active / --inactive 등 모든 modifier 완비. 반드시 render_to_html('switch', {left, right, value, size}) 호출해 정확한 BEM 출력 사용. ncua-switch__option--active 를 페이지 SCSS 에서 override 하지 말 것.",
1195
+ "descriptionExtra": "[중요] 두 선택지 토글 컴포넌트 (좌/우 영역 선택). left/right props (각각 { id, label }) + value(선택된 id) + size(xxs/xs/sm/md) + disabled. 출력 BEM: ncua-switch + --{size} modifier + ncua-switch__option + --active/--inactive/--left/--right. ⚠️ 페이지 SCSS 에서 .ncua-switch__option--active 등 override CSS 작성 금지 — CDN CSS 가 완비. 발명 modifier(--toggled / --selected) 사용 금지.",
1196
+ "aliasesExtra": [
1197
+ "스위치", "토글", "토글 스위치", "segment control", "segment-control",
1198
+ "온오프", "on-off", "양자택일", "binary toggle", "선택 토글", "라디오 스위치",
1199
+ "탭 스위치", "duo-toggle", "이분법 선택", "ncua-switch"
1200
+ ],
1201
+ "bemClassesExtra": [],
1202
+ "canonicalExamples": {
1203
+ "default": {
1204
+ "description": "P22: 기본 토글 스위치 (좌/우 두 옵션). value 로 현재 선택, size='md' 기본. left/right 의 id 는 value 와 매칭.",
1205
+ "props": {
1206
+ "size": "md",
1207
+ "left": { "id": "list", "label": "목록" },
1208
+ "right": { "id": "grid", "label": "그리드" },
1209
+ "value": "list"
1210
+ }
1211
+ },
1212
+ "active-inactive-pattern": {
1213
+ "description": "P22: 활성/비활성 표시 토글 (콘텐츠 상태 관리). 좌측을 활성(기본 선택), 우측을 비활성으로 라벨링. size='sm' 으로 폼 안 인라인 배치.",
1214
+ "props": {
1215
+ "size": "sm",
1216
+ "left": { "id": "active", "label": "활성" },
1217
+ "right": { "id": "inactive", "label": "비활성" },
1218
+ "value": "active"
1219
+ }
1220
+ },
1221
+ "disabled": {
1222
+ "description": "P22: 권한/상태로 인해 변경 불가한 토글. disabled=true 로 회색 처리 + 인터랙션 차단. CDN CSS 가 .ncua-switch--disabled modifier 적용 — 페이지 측 opacity / pointer-events override 불필요.",
1223
+ "props": {
1224
+ "size": "md",
1225
+ "left": { "id": "yes", "label": "사용함" },
1226
+ "right": { "id": "no", "label": "사용 안 함" },
1227
+ "value": "yes",
1228
+ "disabled": true
1229
+ }
1230
+ }
1231
+ }
1232
+ },
1233
+ "notification": {
1234
+ "_note": "P20/P22: Notification 은 비차단 알림 컴포넌트. type ∈ {floating, full-width, message} × color ∈ {neutral, error, warning, success, info} 매트릭스 (단, floating 은 info 색상 미지원). props 기반 — subComponents 없음. ⚠️⚠️ BEM prefix 는 type 별로 분리: type='floating' → `ncua-floating-notification__*`, type='full-width' → `ncua-full-width-notification__*`, type='message' → `ncua-message-notification__*`. **generic 한 `ncua-notification__*` prefix 는 존재하지 않음** — godomall5 페이지에서 발견된 가짜 BEM. floating 은 페이지 우측 영역 자동 노출(autoClose 지원), full-width 는 화면 상단 가로 배너, message 는 인라인 메시지 박스. onHidePermanently 는 message / full-width 에서만 동작. React 컴포넌트 + CDN CSS 완비 — 반드시 render_to_html('notification', {...}) 호출해 정확한 type-prefix BEM 출력을 받아 그대로 사용.",
1235
+ "descriptionExtra": "[중요] 비차단 알림 컴포넌트. type 으로 표현 형태(floating/full-width/message) 결정, color 로 상태(neutral/error/warning/success/info) 결정. ⚠️ BEM prefix 가 type 별로 다름: floating→ncua-floating-notification__*, full-width→ncua-full-width-notification__*, message→ncua-message-notification__*. generic ncua-notification__* prefix 는 존재하지 않으니 절대 직접 작성 금지 — render_to_html 출력 그대로 사용. type='floating' 은 color='info' 미지원. autoClose 는 floating 전용 (밀리초). onHidePermanently 는 message / full-width 전용. 페이지 prefix wrapper(toast-wrapper, alert-banner 등) 우회 금지.",
1236
+ "bemClassesExtra": [
1237
+ "ncua-floating-notification",
1238
+ "ncua-floating-notification__container",
1239
+ "ncua-floating-notification__content",
1240
+ "ncua-floating-notification__title",
1241
+ "ncua-floating-notification__icon",
1242
+ "ncua-full-width-notification",
1243
+ "ncua-full-width-notification__container",
1244
+ "ncua-full-width-notification__content",
1245
+ "ncua-full-width-notification__title",
1246
+ "ncua-message-notification",
1247
+ "ncua-message-notification__container",
1248
+ "ncua-message-notification__content",
1249
+ "ncua-message-notification__title"
1250
+ ],
1251
+ "aliasesExtra": [
1252
+ "알림", "알림창", "알림박스", "안내 알림", "토스트", "toast", "snackbar",
1253
+ "배너 알림", "banner alert", "인라인 메시지", "inline message", "콜아웃", "callout",
1254
+ "상태 메시지", "status message", "feedback message", "에러 알림", "성공 알림", "경고 알림",
1255
+ "notification toast", "in-page notification"
1256
+ ],
1257
+ "allowedChildren": {},
1258
+ "canonicalExamples": {
1259
+ "floating-success-autoclose": {
1260
+ "description": "P20: 작업 완료 후 우상단 자동 사라지는 알림 (저장/등록/삭제 성공 시 표준). type='floating' + color='success' + autoClose (3000ms 권장). floating 은 info 색상 미지원 — info 가 필요하면 type='message' 또는 'full-width' 로 변경. 출력 BEM: ncua-floating-notification + --success 등 modifier. (`ncua-notification__*` 같은 generic prefix 는 가짜 — 사용 금지.)",
1261
+ "props": {
1262
+ "type": "floating",
1263
+ "color": "success",
1264
+ "title": "저장되었습니다",
1265
+ "supportingText": "변경사항이 정상적으로 반영되었습니다.",
1266
+ "autoClose": 3000,
1267
+ "onClose": "noop"
1268
+ }
1269
+ },
1270
+ "floating-error": {
1271
+ "description": "P20: 작업 실패 알림. type='floating' + color='error'. autoClose 없이 사용자가 onClose 로 직접 닫는 패턴 권장 (에러는 충분히 인지되어야 함). title 에 한줄 요약, supportingText 에 원인/해결책.",
1272
+ "props": {
1273
+ "type": "floating",
1274
+ "color": "error",
1275
+ "title": "저장에 실패했습니다",
1276
+ "supportingText": "네트워크 연결을 확인하고 다시 시도해주세요.",
1277
+ "onClose": "noop"
1278
+ }
1279
+ },
1280
+ "full-width-warning-dismissible": {
1281
+ "description": "P20: 화면 상단 전체 너비 경고 배너. type='full-width' + color='warning'. onHidePermanently 로 '다시 보지 않기' 옵션 제공 — 사용자가 이미 인지한 안내는 영구 숨김 가능. 정책 변경 / 중요 공지 / 점검 안내 등 페이지 진입 시 즉시 노출되어야 하는 메시지 표준. 출력 BEM prefix: ncua-full-width-notification__* (generic ncua-notification__* 아님).",
1282
+ "props": {
1283
+ "type": "full-width",
1284
+ "color": "warning",
1285
+ "title": "결제 정책 변경 안내",
1286
+ "supportingText": "2025-06-01부터 카드 결제 시 PG사 수수료 정책이 변경됩니다. 자세한 내용은 공지사항을 확인해주세요.",
1287
+ "onClose": "noop",
1288
+ "onHidePermanently": "noop"
1289
+ }
1290
+ },
1291
+ "message-info-inline": {
1292
+ "description": "P20: 폼 영역 내부 인라인 안내 메시지 (page-title 아래 또는 폼 섹션 사이). type='message' + color='info'. floating 과 달리 자동 사라짐 없음 — 페이지에 영구 노출. 단순 안내는 supportingText 없이 title 만, 보충 설명이 필요하면 두 줄 구조. 출력 BEM prefix: ncua-message-notification__* (generic ncua-notification__* 아님).",
1293
+ "props": {
1294
+ "type": "message",
1295
+ "color": "info",
1296
+ "title": "이미지 파일은 5MB 이하 JPG/PNG/WebP 형식만 지원됩니다.",
1297
+ "onClose": "noop"
1298
+ }
1299
+ }
1300
+ }
1301
+ }
1302
+ }