@ncds/ui-admin-mcp 1.0.0-alpha.28 → 1.0.0-alpha.29
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/bin/components.bundle.js +8 -8
- package/bin/definitions/external/step-guide.d.ts +5 -1
- package/bin/definitions/external/step-guide.js +1 -1
- package/bin/overrides/composition.json +208 -181
- package/bin/tools/renderToHtml.js +1 -1
- package/bin/version.d.ts +1 -1
- package/bin/version.js +1 -1
- package/data/_tokens.json +1 -1
- package/data/file-input.json +11 -2
- package/data/image-file-input.json +21 -0
- package/data/select.json +2 -1
- package/package.json +1 -1
|
@@ -22,7 +22,13 @@
|
|
|
22
22
|
"상품 목록",
|
|
23
23
|
"회원 목록"
|
|
24
24
|
],
|
|
25
|
-
"
|
|
25
|
+
"_note_bemClassesExtra": "아래 4개는 SCSS([_data-grid.scss] __summary-count / __summary-actions / __action-bar-group / --right) 에만 정의되어 있고 React DataGrid 본체가 사용하지 않아 pnpm extract 가 bemClasses 로 자동 추출하지 못한다. canonicalExample 이 이 클래스들을 사용하므로 validate_html 화이트리스트 통과를 위해 명시 등록한다(table.bemClassesExtra 와 동일 관행). 미등록 시 validate_html 이 invalid_element 로 거부하고 fixed_html 이 클래스를 제거해 레이아웃이 깨진다.",
|
|
26
|
+
"bemClassesExtra": [
|
|
27
|
+
"ncua-data-grid__summary-count",
|
|
28
|
+
"ncua-data-grid__summary-actions",
|
|
29
|
+
"ncua-data-grid__action-bar-group",
|
|
30
|
+
"ncua-data-grid__action-bar-group--right"
|
|
31
|
+
],
|
|
26
32
|
"allowedChildren": {
|
|
27
33
|
"DataGrid": {
|
|
28
34
|
"required": ["DataGrid.Table"],
|
|
@@ -43,74 +49,94 @@
|
|
|
43
49
|
"DataGrid.Pagination": ["Pagination"]
|
|
44
50
|
},
|
|
45
51
|
"canonicalExample": {
|
|
46
|
-
"_note": "검색결과(주문/회원/상품 등) 목록 표준 레이아웃. Storybook DataGrid SearchResultDemo 와 동일 구조. AI 는 컬럼 수/라벨/데이터만 교체하고 트리 자체는 유지한다. checkbox 컬럼이 필요 없으면 제거, 필터/정렬
|
|
52
|
+
"_note": "검색결과(주문/회원/상품 등) 목록 표준 레이아웃. Storybook DataGrid SearchResultDemo 와 동일 구조. AI 는 컬럼 수/라벨/데이터만 교체하고 트리 자체는 유지한다. checkbox 컬럼이 필요 없으면 제거, 필터/정렬 UI 가 필요 없으면 상단 action-bar 의 우측 그룹만 비우는 식으로 가지치기. ⚠️ 이 예제의 필터/정렬 자리에 select-box 가 아닌 select 를 쓰는 이유: select-box 는 jsRequired 라 정적 렌더에서 옵션이 나오지 않는다(select-box._note 의 P18 예외 참조). 실제 구현물에서는 select-box 를 사용할 것.",
|
|
47
53
|
"props": {
|
|
48
54
|
"variant": "search-result",
|
|
49
55
|
"children": [
|
|
50
56
|
{
|
|
51
57
|
"component": "data-grid.summary",
|
|
52
|
-
"
|
|
58
|
+
"_note": "ncua-data-grid__summary는 justify-content:space-between 내장 — 직속 자식 2개를 두면 자동 좌/우 배치. 좌측: component='span' 안에 텍스트와 component='strong' + className='ncua-data-grid__summary-count'로 건수 강조. 우측 버튼 그룹: component='div' + className='ncua-data-grid__summary-actions'로 묶는다 — block-container 사용 금지(section 태그 생성).",
|
|
59
|
+
"children": [
|
|
60
|
+
{
|
|
61
|
+
"component": "span",
|
|
62
|
+
"children": [
|
|
63
|
+
"검색 ",
|
|
64
|
+
{
|
|
65
|
+
"component": "strong",
|
|
66
|
+
"props": {
|
|
67
|
+
"className": "ncua-data-grid__summary-count"
|
|
68
|
+
},
|
|
69
|
+
"children": "5"
|
|
70
|
+
},
|
|
71
|
+
"건 / 전체 ",
|
|
72
|
+
{
|
|
73
|
+
"component": "strong",
|
|
74
|
+
"props": {
|
|
75
|
+
"className": "ncua-data-grid__summary-count"
|
|
76
|
+
},
|
|
77
|
+
"children": "128"
|
|
78
|
+
},
|
|
79
|
+
"건"
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"component": "div",
|
|
84
|
+
"props": { "className": "ncua-data-grid__summary-actions" },
|
|
85
|
+
"children": [
|
|
86
|
+
{
|
|
87
|
+
"component": "button",
|
|
88
|
+
"props": { "label": "SMS 발송", "size": "xs", "hierarchy": "secondary-gray" }
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"component": "button",
|
|
92
|
+
"props": { "label": "인쇄", "size": "xs", "hierarchy": "secondary-gray" }
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"component": "button",
|
|
96
|
+
"props": { "label": "엑셀 다운로드", "size": "xs", "hierarchy": "secondary-gray" }
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
]
|
|
53
101
|
},
|
|
54
102
|
{
|
|
55
103
|
"component": "data-grid.action-bar",
|
|
56
|
-
"_note": "
|
|
104
|
+
"_note": "action-bar 의 자식은 그룹 개수와 무관하게 항상 component='div' + className='ncua-data-grid__action-bar-group' 로 묶는다 — 버튼을 action-bar 직속 자식으로 두지 않는다. 우측 그룹은 className='ncua-data-grid__action-bar-group ncua-data-grid__action-bar-group--right'. align=space-between 이 좌/우 끝 분배를 담당한다. block-container 사용 금지(section 태그+ncua-block-container CSS 오염). 좌: 선택 일괄 액션 버튼, 우: 정렬/페이지크기 select.",
|
|
57
105
|
"props": {
|
|
58
106
|
"position": "top",
|
|
59
107
|
"align": "space-between"
|
|
60
108
|
},
|
|
61
109
|
"children": [
|
|
62
110
|
{
|
|
63
|
-
"component": "
|
|
64
|
-
"props": {
|
|
65
|
-
"className": "data-grid__action-bar-group--left"
|
|
66
|
-
},
|
|
111
|
+
"component": "div",
|
|
112
|
+
"props": { "className": "ncua-data-grid__action-bar-group" },
|
|
67
113
|
"children": [
|
|
68
114
|
{
|
|
69
115
|
"component": "button",
|
|
70
|
-
"props": {
|
|
71
|
-
"label": "송장 번호 저장",
|
|
72
|
-
"size": "xs",
|
|
73
|
-
"hierarchy": "secondary-gray"
|
|
74
|
-
}
|
|
116
|
+
"props": { "label": "송장 번호 저장", "size": "xs", "hierarchy": "secondary-gray" }
|
|
75
117
|
},
|
|
76
118
|
{
|
|
77
119
|
"component": "button",
|
|
78
|
-
"props": {
|
|
79
|
-
"label": "묶음 배송해제",
|
|
80
|
-
"size": "xs",
|
|
81
|
-
"hierarchy": "secondary"
|
|
82
|
-
}
|
|
120
|
+
"props": { "label": "묶음 배송해제", "size": "xs", "hierarchy": "secondary" }
|
|
83
121
|
}
|
|
84
122
|
]
|
|
85
123
|
},
|
|
86
124
|
{
|
|
87
|
-
"component": "
|
|
88
|
-
"props": {
|
|
89
|
-
"className": "data-grid__action-bar-group--right"
|
|
90
|
-
},
|
|
125
|
+
"component": "div",
|
|
126
|
+
"props": { "className": "ncua-data-grid__action-bar-group ncua-data-grid__action-bar-group--right" },
|
|
91
127
|
"children": [
|
|
92
128
|
{
|
|
93
|
-
"component": "select
|
|
129
|
+
"component": "select",
|
|
94
130
|
"props": {
|
|
95
131
|
"size": "xs",
|
|
96
|
-
"
|
|
97
|
-
{
|
|
98
|
-
"id": "recent",
|
|
99
|
-
"label": "최근 등록순"
|
|
100
|
-
}
|
|
101
|
-
]
|
|
132
|
+
"optionItems": [{ "id": "recent", "label": "최근 등록순" }]
|
|
102
133
|
}
|
|
103
134
|
},
|
|
104
135
|
{
|
|
105
|
-
"component": "select
|
|
136
|
+
"component": "select",
|
|
106
137
|
"props": {
|
|
107
138
|
"size": "xs",
|
|
108
|
-
"
|
|
109
|
-
{
|
|
110
|
-
"id": "10",
|
|
111
|
-
"label": "10개 보기"
|
|
112
|
-
}
|
|
113
|
-
]
|
|
139
|
+
"optionItems": [{ "id": "10", "label": "10개 보기" }]
|
|
114
140
|
}
|
|
115
141
|
}
|
|
116
142
|
]
|
|
@@ -287,32 +313,23 @@
|
|
|
287
313
|
},
|
|
288
314
|
{
|
|
289
315
|
"component": "data-grid.action-bar",
|
|
316
|
+
"_note": "action-bar 의 자식은 그룹 개수와 무관하게 항상 __action-bar-group wrapper 로 묶는다 — 버튼을 action-bar 직속 자식으로 두지 않는다. 상단/하단 action-bar 의 골격을 통일해 두면, 우측에 정렬/페이지크기 select 가 추가되는 흔한 유지보수 경로에서 wrapper 를 새로 만들 필요 없이 그룹만 추가하면 된다. 현재 이 노드는 좌측 그룹 하나뿐이라 align=space-between 이 시각적으로는 작동하지 않지만, 동일 골격 유지를 위해 함께 둔다. 좌/우 두 그룹을 모두 채운 형태는 canonicalExamples.search-result-with-selection-rich 참고.",
|
|
290
317
|
"props": {
|
|
291
318
|
"position": "bottom",
|
|
292
319
|
"align": "space-between"
|
|
293
320
|
},
|
|
294
321
|
"children": [
|
|
295
322
|
{
|
|
296
|
-
"component": "
|
|
297
|
-
"props": {
|
|
298
|
-
"className": "data-grid__action-bar-group--left"
|
|
299
|
-
},
|
|
323
|
+
"component": "div",
|
|
324
|
+
"props": { "className": "ncua-data-grid__action-bar-group" },
|
|
300
325
|
"children": [
|
|
301
326
|
{
|
|
302
327
|
"component": "button",
|
|
303
|
-
"props": {
|
|
304
|
-
"label": "송장 번호 저장",
|
|
305
|
-
"size": "xs",
|
|
306
|
-
"hierarchy": "secondary-gray"
|
|
307
|
-
}
|
|
328
|
+
"props": { "label": "송장 번호 저장", "size": "xs", "hierarchy": "secondary-gray" }
|
|
308
329
|
},
|
|
309
330
|
{
|
|
310
331
|
"component": "button",
|
|
311
|
-
"props": {
|
|
312
|
-
"label": "묶음 배송해제",
|
|
313
|
-
"size": "xs",
|
|
314
|
-
"hierarchy": "secondary"
|
|
315
|
-
}
|
|
332
|
+
"props": { "label": "묶음 배송해제", "size": "xs", "hierarchy": "secondary" }
|
|
316
333
|
}
|
|
317
334
|
]
|
|
318
335
|
}
|
|
@@ -342,43 +359,41 @@
|
|
|
342
359
|
"children": [
|
|
343
360
|
{
|
|
344
361
|
"component": "data-grid.summary",
|
|
362
|
+
"_note": "직속 자식 2개 — 좌측: component='span' 안에 텍스트와 component='strong' + className='ncua-data-grid__summary-count'로 건수 강조. 우측: component='div' + className='ncua-data-grid__summary-actions'로 버튼들 묶기. block-container 사용 금지(section 태그 생성).",
|
|
345
363
|
"children": [
|
|
346
364
|
{
|
|
347
|
-
"component": "
|
|
348
|
-
"
|
|
349
|
-
"
|
|
350
|
-
|
|
351
|
-
|
|
365
|
+
"component": "span",
|
|
366
|
+
"children": [
|
|
367
|
+
"검색 ",
|
|
368
|
+
{
|
|
369
|
+
"component": "strong",
|
|
370
|
+
"props": { "className": "ncua-data-grid__summary-count" },
|
|
371
|
+
"children": "5"
|
|
372
|
+
},
|
|
373
|
+
"건 / 전체 ",
|
|
374
|
+
{
|
|
375
|
+
"component": "strong",
|
|
376
|
+
"props": { "className": "ncua-data-grid__summary-count" },
|
|
377
|
+
"children": "128"
|
|
378
|
+
},
|
|
379
|
+
"건"
|
|
380
|
+
]
|
|
352
381
|
},
|
|
353
382
|
{
|
|
354
|
-
"component": "
|
|
355
|
-
"props": {
|
|
356
|
-
"className": "data-grid__summary-group--right"
|
|
357
|
-
},
|
|
383
|
+
"component": "div",
|
|
384
|
+
"props": { "className": "ncua-data-grid__summary-actions" },
|
|
358
385
|
"children": [
|
|
359
386
|
{
|
|
360
387
|
"component": "button",
|
|
361
|
-
"props": {
|
|
362
|
-
"label": "SMS 발송",
|
|
363
|
-
"size": "xs",
|
|
364
|
-
"hierarchy": "secondary-gray"
|
|
365
|
-
}
|
|
388
|
+
"props": { "label": "SMS 발송", "size": "xs", "hierarchy": "secondary-gray" }
|
|
366
389
|
},
|
|
367
390
|
{
|
|
368
391
|
"component": "button",
|
|
369
|
-
"props": {
|
|
370
|
-
"label": "인쇄",
|
|
371
|
-
"size": "xs",
|
|
372
|
-
"hierarchy": "secondary-gray"
|
|
373
|
-
}
|
|
392
|
+
"props": { "label": "인쇄", "size": "xs", "hierarchy": "secondary-gray" }
|
|
374
393
|
},
|
|
375
394
|
{
|
|
376
395
|
"component": "button",
|
|
377
|
-
"props": {
|
|
378
|
-
"label": "엑셀 다운로드",
|
|
379
|
-
"size": "xs",
|
|
380
|
-
"hierarchy": "secondary-gray"
|
|
381
|
-
}
|
|
396
|
+
"props": { "label": "엑셀 다운로드", "size": "xs", "hierarchy": "secondary-gray" }
|
|
382
397
|
}
|
|
383
398
|
]
|
|
384
399
|
}
|
|
@@ -386,74 +401,48 @@
|
|
|
386
401
|
},
|
|
387
402
|
{
|
|
388
403
|
"component": "data-grid.action-bar",
|
|
404
|
+
"_note": "align=space-between 시 좌측 그룹은 component='div' + className='ncua-data-grid__action-bar-group', 우측 그룹은 className='ncua-data-grid__action-bar-group ncua-data-grid__action-bar-group--right'로 묶는다. block-container 사용 금지(section 태그+ncua-block-container CSS 오염). 좌: 텍스트+일괄 액션 버튼, 우: 정렬/페이지크기 select + 설정 버튼.",
|
|
389
405
|
"props": {
|
|
390
406
|
"position": "top",
|
|
391
407
|
"align": "space-between"
|
|
392
408
|
},
|
|
393
409
|
"children": [
|
|
394
410
|
{
|
|
395
|
-
"component": "
|
|
396
|
-
"props": {
|
|
397
|
-
"className": "data-grid__action-bar-group--left"
|
|
398
|
-
},
|
|
411
|
+
"component": "div",
|
|
412
|
+
"props": { "className": "ncua-data-grid__action-bar-group" },
|
|
399
413
|
"children": [
|
|
400
414
|
"선택한 주문을 ",
|
|
401
415
|
{
|
|
402
416
|
"component": "button",
|
|
403
|
-
"props": {
|
|
404
|
-
"label": "송장 번호 저장",
|
|
405
|
-
"size": "xs",
|
|
406
|
-
"hierarchy": "secondary-gray"
|
|
407
|
-
}
|
|
417
|
+
"props": { "label": "송장 번호 저장", "size": "xs", "hierarchy": "secondary-gray" }
|
|
408
418
|
},
|
|
409
419
|
{
|
|
410
420
|
"component": "button",
|
|
411
|
-
"props": {
|
|
412
|
-
"label": "묶음 배송해제",
|
|
413
|
-
"size": "xs",
|
|
414
|
-
"hierarchy": "secondary"
|
|
415
|
-
}
|
|
421
|
+
"props": { "label": "묶음 배송해제", "size": "xs", "hierarchy": "secondary" }
|
|
416
422
|
}
|
|
417
423
|
]
|
|
418
424
|
},
|
|
419
425
|
{
|
|
420
|
-
"component": "
|
|
421
|
-
"props": {
|
|
422
|
-
"className": "data-grid__action-bar-group--right"
|
|
423
|
-
},
|
|
426
|
+
"component": "div",
|
|
427
|
+
"props": { "className": "ncua-data-grid__action-bar-group ncua-data-grid__action-bar-group--right" },
|
|
424
428
|
"children": [
|
|
425
429
|
{
|
|
426
|
-
"component": "select
|
|
430
|
+
"component": "select",
|
|
427
431
|
"props": {
|
|
428
432
|
"size": "xs",
|
|
429
|
-
"
|
|
430
|
-
{
|
|
431
|
-
"id": "recent",
|
|
432
|
-
"label": "최근 등록순"
|
|
433
|
-
}
|
|
434
|
-
]
|
|
433
|
+
"optionItems": [{ "id": "recent", "label": "최근 등록순" }]
|
|
435
434
|
}
|
|
436
435
|
},
|
|
437
436
|
{
|
|
438
|
-
"component": "select
|
|
437
|
+
"component": "select",
|
|
439
438
|
"props": {
|
|
440
439
|
"size": "xs",
|
|
441
|
-
"
|
|
442
|
-
{
|
|
443
|
-
"id": "10",
|
|
444
|
-
"label": "10개 보기"
|
|
445
|
-
}
|
|
446
|
-
]
|
|
440
|
+
"optionItems": [{ "id": "10", "label": "10개 보기" }]
|
|
447
441
|
}
|
|
448
442
|
},
|
|
449
443
|
{
|
|
450
444
|
"component": "button",
|
|
451
|
-
"props": {
|
|
452
|
-
"label": "설정",
|
|
453
|
-
"size": "xs",
|
|
454
|
-
"hierarchy": "secondary-gray",
|
|
455
|
-
"onlyIcon": true
|
|
456
|
-
}
|
|
445
|
+
"props": { "label": "설정", "size": "xs", "hierarchy": "secondary-gray", "onlyIcon": true }
|
|
457
446
|
}
|
|
458
447
|
]
|
|
459
448
|
}
|
|
@@ -585,58 +574,36 @@
|
|
|
585
574
|
},
|
|
586
575
|
"children": [
|
|
587
576
|
{
|
|
588
|
-
"component": "
|
|
589
|
-
"props": {
|
|
590
|
-
"className": "data-grid__action-bar-group--left"
|
|
591
|
-
},
|
|
577
|
+
"component": "div",
|
|
578
|
+
"props": { "className": "ncua-data-grid__action-bar-group" },
|
|
592
579
|
"children": [
|
|
593
580
|
"선택한 주문을 ",
|
|
594
581
|
{
|
|
595
582
|
"component": "button",
|
|
596
|
-
"props": {
|
|
597
|
-
"label": "송장 번호 저장",
|
|
598
|
-
"size": "xs",
|
|
599
|
-
"hierarchy": "secondary-gray"
|
|
600
|
-
}
|
|
583
|
+
"props": { "label": "송장 번호 저장", "size": "xs", "hierarchy": "secondary-gray" }
|
|
601
584
|
},
|
|
602
585
|
{
|
|
603
586
|
"component": "button",
|
|
604
|
-
"props": {
|
|
605
|
-
"label": "묶음 배송해제",
|
|
606
|
-
"size": "xs",
|
|
607
|
-
"hierarchy": "secondary"
|
|
608
|
-
}
|
|
587
|
+
"props": { "label": "묶음 배송해제", "size": "xs", "hierarchy": "secondary" }
|
|
609
588
|
}
|
|
610
589
|
]
|
|
611
590
|
},
|
|
612
591
|
{
|
|
613
|
-
"component": "
|
|
614
|
-
"props": {
|
|
615
|
-
"className": "data-grid__action-bar-group--right"
|
|
616
|
-
},
|
|
592
|
+
"component": "div",
|
|
593
|
+
"props": { "className": "ncua-data-grid__action-bar-group ncua-data-grid__action-bar-group--right" },
|
|
617
594
|
"children": [
|
|
618
595
|
{
|
|
619
|
-
"component": "select
|
|
596
|
+
"component": "select",
|
|
620
597
|
"props": {
|
|
621
598
|
"size": "xs",
|
|
622
|
-
"
|
|
623
|
-
{
|
|
624
|
-
"id": "recent",
|
|
625
|
-
"label": "최근 등록순"
|
|
626
|
-
}
|
|
627
|
-
]
|
|
599
|
+
"optionItems": [{ "id": "recent", "label": "최근 등록순" }]
|
|
628
600
|
}
|
|
629
601
|
},
|
|
630
602
|
{
|
|
631
|
-
"component": "select
|
|
603
|
+
"component": "select",
|
|
632
604
|
"props": {
|
|
633
605
|
"size": "xs",
|
|
634
|
-
"
|
|
635
|
-
{
|
|
636
|
-
"id": "10",
|
|
637
|
-
"label": "10개 보기"
|
|
638
|
-
}
|
|
639
|
-
]
|
|
606
|
+
"optionItems": [{ "id": "10", "label": "10개 보기" }]
|
|
640
607
|
}
|
|
641
608
|
}
|
|
642
609
|
]
|
|
@@ -665,61 +632,66 @@
|
|
|
665
632
|
"children": [
|
|
666
633
|
{
|
|
667
634
|
"component": "data-grid.summary",
|
|
668
|
-
"
|
|
635
|
+
"_note": "건수 강조(strong + ncua-data-grid__summary-count)는 시나리오와 무관한 디자인시스템 규칙 — 모든 시나리오에서 동일하게 적용한다. 이 시나리오가 'simple' 인 것은 ActionBar 구성이 단순하다는 뜻이지 summary 마크업을 생략한다는 뜻이 아니다.",
|
|
636
|
+
"children": [
|
|
637
|
+
{
|
|
638
|
+
"component": "span",
|
|
639
|
+
"children": [
|
|
640
|
+
"검색 ",
|
|
641
|
+
{
|
|
642
|
+
"component": "strong",
|
|
643
|
+
"props": { "className": "ncua-data-grid__summary-count" },
|
|
644
|
+
"children": "5"
|
|
645
|
+
},
|
|
646
|
+
"건 / 전체 ",
|
|
647
|
+
{
|
|
648
|
+
"component": "strong",
|
|
649
|
+
"props": { "className": "ncua-data-grid__summary-count" },
|
|
650
|
+
"children": "128"
|
|
651
|
+
},
|
|
652
|
+
"건"
|
|
653
|
+
]
|
|
654
|
+
}
|
|
655
|
+
]
|
|
669
656
|
},
|
|
670
657
|
{
|
|
671
658
|
"component": "data-grid.action-bar",
|
|
659
|
+
"_note": "align=space-between 시 좌측 그룹은 component='div' + className='ncua-data-grid__action-bar-group', 우측 그룹은 className='ncua-data-grid__action-bar-group ncua-data-grid__action-bar-group--right'로 묶는다. block-container 사용 금지.",
|
|
672
660
|
"props": {
|
|
673
661
|
"position": "top",
|
|
674
662
|
"align": "space-between"
|
|
675
663
|
},
|
|
676
664
|
"children": [
|
|
677
665
|
{
|
|
678
|
-
"component": "
|
|
666
|
+
"component": "div",
|
|
667
|
+
"props": { "className": "ncua-data-grid__action-bar-group" },
|
|
679
668
|
"children": [
|
|
680
669
|
{
|
|
681
670
|
"component": "button",
|
|
682
|
-
"props": {
|
|
683
|
-
"label": "송장 번호 저장",
|
|
684
|
-
"size": "xs",
|
|
685
|
-
"hierarchy": "secondary-gray"
|
|
686
|
-
}
|
|
671
|
+
"props": { "label": "송장 번호 저장", "size": "xs", "hierarchy": "secondary-gray" }
|
|
687
672
|
},
|
|
688
673
|
{
|
|
689
674
|
"component": "button",
|
|
690
|
-
"props": {
|
|
691
|
-
"label": "묶음 배송해제",
|
|
692
|
-
"size": "xs",
|
|
693
|
-
"hierarchy": "secondary"
|
|
694
|
-
}
|
|
675
|
+
"props": { "label": "묶음 배송해제", "size": "xs", "hierarchy": "secondary" }
|
|
695
676
|
}
|
|
696
677
|
]
|
|
697
678
|
},
|
|
698
679
|
{
|
|
699
|
-
"component": "
|
|
680
|
+
"component": "div",
|
|
681
|
+
"props": { "className": "ncua-data-grid__action-bar-group ncua-data-grid__action-bar-group--right" },
|
|
700
682
|
"children": [
|
|
701
683
|
{
|
|
702
|
-
"component": "select
|
|
684
|
+
"component": "select",
|
|
703
685
|
"props": {
|
|
704
686
|
"size": "xs",
|
|
705
|
-
"
|
|
706
|
-
{
|
|
707
|
-
"id": "recent",
|
|
708
|
-
"label": "최근 등록순"
|
|
709
|
-
}
|
|
710
|
-
]
|
|
687
|
+
"optionItems": [{ "id": "recent", "label": "최근 등록순" }]
|
|
711
688
|
}
|
|
712
689
|
},
|
|
713
690
|
{
|
|
714
|
-
"component": "select
|
|
691
|
+
"component": "select",
|
|
715
692
|
"props": {
|
|
716
693
|
"size": "xs",
|
|
717
|
-
"
|
|
718
|
-
{
|
|
719
|
-
"id": "10",
|
|
720
|
-
"label": "10개 보기"
|
|
721
|
-
}
|
|
722
|
-
]
|
|
694
|
+
"optionItems": [{ "id": "10", "label": "10개 보기" }]
|
|
723
695
|
}
|
|
724
696
|
}
|
|
725
697
|
]
|
|
@@ -798,18 +770,18 @@
|
|
|
798
770
|
}
|
|
799
771
|
},
|
|
800
772
|
"dnd-with-selectable": {
|
|
801
|
-
"description": "DataGrid + 체크박스 선택 + 행 드래그앤드롭 + 이동 버튼 조합. CDN HTML 모드 전용 완전 구조. ⚠️ 필수 규칙 — 아래
|
|
773
|
+
"description": "DataGrid + 체크박스 선택 + 행 드래그앤드롭 + 이동 버튼 조합. CDN HTML 모드 전용 완전 구조. ⚠️ 필수 규칙 — 아래 6가지를 모두 지켜야 올바른 렌더링이 보장된다: (1) ncua-table div에 ncua-table--selectable ncua-table--draggable ncua-table--in-data-grid 3개 클래스 모두 포함 — ncua-table--in-data-grid 누락 시 좌측 2px 이중 테두리 발생. (2) ncua-table-wrapper style에 --ncua-table-header-height:40px CSS 변수 설정 — 드래그 미리보기 오프셋 계산에 사용. (3) 이동 버튼(ButtonGroup)은 ncua-data-grid__action-bar ncua-data-grid__action-bar--top ncua-data-grid__action-bar--left 안에 배치, disabled 상태로 초기화 — --left 모디파이어가 활성화돼야 ButtonGroup(좌측) + select·설정버튼(margin-left:auto 우측) 레이아웃이 바르게 적용된다. 버튼 순서: 맨아래(double-down)→아래(down)→위(up)→맨위(double-up). (4) ncua-data-grid__table-wrapper 마지막 자식으로 빈 ncua-data-grid__action-bar--bottom div 추가 — 누락 시 테이블 하단 여백 소멸. (5) CDN JS: const d = new window.ncua.Draggable(tbody, { onDrop, onSelect, onMove }); d.setMoveButtonsEnabled(true) 로 이동 버튼 연결. onDrop: 페이지가 DOM 행 이동 + 서버 API 처리. onMove: Draggable이 DOM 이동 완료 후 호출하는 알림 — 페이지에서 DOM 조작 금지. (6) th 체크박스 indeterminate 상태(부분 선택): selectAllEl 옵션에 select-all input을 전달하면 Draggable이 선택 변경 시 자동으로 has-indeterminate 클래스를 span(.ncua-checkbox-input)에 토글한다 — 1개 이상 & 전체 미만: has-indeterminate 추가(indeterminate 아이콘 표시). 전체 선택: has-indeterminate 제거 + checked=true. 선택 없음: has-indeterminate 제거 + checked=false. 페이지에서 별도 처리 불필요.",
|
|
802
774
|
"_htmlStructure": {
|
|
803
775
|
"_note": "CDN HTML 모드 전용 구조. React 모드에서는 DataGrid.Table + Table.DragHeaderCell + Table.DragCell + selectable 조합으로 대체.",
|
|
804
776
|
"outerStructure": "<div class='ncua-data-grid'><div class='ncua-data-grid__table-wrapper'>[action-bar--top][ncua-data-grid__table][action-bar--bottom(빈 div)]</div></div>",
|
|
805
777
|
"tableDivClasses": "ncua-table ncua-table--horizontal ncua-table--hoverable ncua-table--selectable ncua-table--draggable ncua-table--in-data-grid",
|
|
806
778
|
"tableWrapperStyle": "--ncua-table-header-height:40px",
|
|
807
|
-
"actionBarTop": "<div class='ncua-data-grid__action-bar ncua-data-grid__action-bar--top'><div class='ncua-button-group ncua-button-group--xs has-border'><button class='ncua-button-group__item is-only-icon' id='btn-move-bottom' disabled
|
|
779
|
+
"actionBarTop": "<div class='ncua-data-grid__action-bar ncua-data-grid__action-bar--top ncua-data-grid__action-bar--left'><div class='ncua-button-group ncua-button-group--xs has-border'><button class='ncua-button-group__item is-only-icon' id='btn-move-bottom' disabled type='button'><svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' viewBox='0 0 24 24' stroke='none' color='currentColor'><path stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m7 13 5 5 5-5M7 6l5 5 5-5'></path></svg></button><button class='ncua-button-group__item is-only-icon' id='btn-move-down' disabled type='button'><svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' viewBox='0 0 24 24' stroke='none' color='currentColor'><path stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m6 9 6 6 6-6'></path></svg></button><button class='ncua-button-group__item is-only-icon' id='btn-move-up' disabled type='button'><svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' viewBox='0 0 24 24' stroke='none' color='currentColor'><path stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m18 15-6-6-6 6'></path></svg></button><button class='ncua-button-group__item is-only-icon' id='btn-move-top' disabled type='button'><svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' viewBox='0 0 24 24' stroke='none' color='currentColor'><path stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m17 18-5-5-5 5m10-7-5-5-5 5'></path></svg></button></div><div style='display:flex;align-items:center;gap:4px;margin-left:auto'><span class='ncua-select ncua-select--xs'><span class='ncua-select__content'><select class='ncua-select__tag' aria-readonly='false'><option value='recent' selected>최근 등록순</option><option value='oldest'>과거 등록순</option></select></span></span><span class='ncua-select ncua-select--xs'><span class='ncua-select__content'><select class='ncua-select__tag' aria-readonly='false'><option value='10' selected>10개 보기</option><option value='20'>20개 보기</option></select></span></span><button class='ncua-btn ncua-btn--xs only-icon ncua-btn--secondary-gray'><svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' viewBox='0 0 24 24' stroke='none'><path stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6'></path><path stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m9.308 19.371.604 1.315c.179.39.472.723.842.957.371.233.804.357 1.246.357a2.34 2.34 0 0 0 1.245-.357c.371-.234.664-.566.843-.957l.604-1.315a2.46 2.46 0 0 1 1.033-1.111 2.6 2.6 0 0 1 1.518-.312l1.477.152c.44.045.883-.034 1.277-.229.394-.194.721-.495.942-.865a2.16 2.16 0 0 0-.13-2.408l-.875-1.164A2.38 2.38 0 0 1 19.459 12c0-.513.168-1.014.48-1.429l.874-1.163A2.155 2.155 0 0 0 20.943 7a2.26 2.26 0 0 0-.942-.866 2.35 2.35 0 0 0-1.277-.228l-1.477.152a2.6 2.6 0 0 1-1.518-.312 2.45 2.45 0 0 1-1.032-1.117l-.609-1.315a2.23 2.23 0 0 0-.842-.957A2.34 2.34 0 0 0 12 2a2.34 2.34 0 0 0-1.245.357c-.371.234-.664.566-.843.957L9.308 4.63c-.214.468-.575.86-1.033 1.117-.46.256-.99.365-1.518.312l-1.481-.152a2.35 2.35 0 0 0-1.277.228A2.26 2.26 0 0 0 3.057 7a2.155 2.155 0 0 0 .13 2.408l.875 1.163c.312.415.48.916.48 1.429s-.168 1.014-.48 1.429l-.875 1.163A2.155 2.155 0 0 0 3.057 17c.22.37.548.671.942.865.394.195.837.274 1.277.23l1.477-.153a2.6 2.6 0 0 1 1.518.312c.459.257.822.648 1.037 1.117'></path></svg></button></div></div>",
|
|
808
780
|
"actionBarBottom": "<div class='ncua-data-grid__action-bar ncua-data-grid__action-bar--bottom'></div>",
|
|
809
|
-
"dragHeaderCell": "<th class='ncua-table__header-cell ncua-table__drag-header-cell'><span class='ncua-table__drag-cell-inner'><span class='ncua-table__drag-header-icon'
|
|
810
|
-
"dragDataCell": "<td class='ncua-table__drag-cell'><span class='ncua-table__drag-cell-inner'><button class='ncua-table__drag-handle' type='button' aria-label='행 순서 변경'
|
|
781
|
+
"dragHeaderCell": "<th class='ncua-table__header-cell ncua-table__drag-header-cell'><span class='ncua-table__drag-cell-inner'><span class='ncua-table__drag-header-icon' aria-hidden='true'><svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' viewBox='0 0 16 16' stroke='none'><path stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.333' d='M10.665 4.001a.667.667 0 1 0 0-1.333.667.667 0 0 0 0 1.333M10.665 8.668a.667.667 0 1 0 0-1.333.667.667 0 0 0 0 1.333M10.665 13.335a.667.667 0 1 0 0-1.333.667.667 0 0 0 0 1.333M5.999 4.001a.667.667 0 1 0 0-1.333.667.667 0 0 0 0 1.333M5.999 8.668a.667.667 0 1 0 0-1.333.667.667 0 0 0 0 1.333M5.999 13.335a.667.667 0 1 0 0-1.334.667.667 0 0 0 0 1.334'></path></svg></span><span class='ncua-checkbox-input ncua-checkbox-input--sm'><input id='select-all' type='checkbox' aria-label='전체 선택'></span></span></th>",
|
|
782
|
+
"dragDataCell": "<td class='ncua-table__drag-cell'><span class='ncua-table__drag-cell-inner'><button class='ncua-table__drag-handle' type='button' aria-label='행 순서 변경' draggable='true'><svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' viewBox='0 0 16 16' stroke='none'><path stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.333' d='M10.665 4.001a.667.667 0 1 0 0-1.333.667.667 0 0 0 0 1.333M10.665 8.668a.667.667 0 1 0 0-1.333.667.667 0 0 0 0 1.333M10.665 13.335a.667.667 0 1 0 0-1.333.667.667 0 0 0 0 1.333M5.999 4.001a.667.667 0 1 0 0-1.333.667.667 0 0 0 0 1.333M5.999 8.668a.667.667 0 1 0 0-1.333.667.667 0 0 0 0 1.333M5.999 13.335a.667.667 0 1 0 0-1.334.667.667 0 0 0 0 1.334'></path></svg></button><span class='ncua-checkbox-input ncua-checkbox-input--sm'><input type='checkbox' aria-label='행 선택'></span></span></td>",
|
|
811
783
|
"trAttr": "data-draggable-id='row-1'",
|
|
812
|
-
"cdnInit": "const tbody = document.querySelector('tbody'); const d = new window.ncua.Draggable(tbody, { onDrop: (fromId, toId, edge) => { /* 서버 API */ }, onSelect: (ids) => { /* 선택 변경 */ }, onMove: (dir, ids) => { /* 알림만 — DOM 이동은 Draggable 내부 처리 */ } }); d.setMoveButtonsEnabled(true);"
|
|
784
|
+
"cdnInit": "const tbody = document.querySelector('tbody'); const d = new window.ncua.Draggable(tbody, { selectAllEl: document.getElementById('select-all'), onDrop: (fromId, toId, edge, selectedIds) => { /* DOM 행 이동 처리 (예: insertBefore) + 서버 API */ }, onSelect: (ids) => { /* 선택 변경 알림 — th has-indeterminate 동기화는 Draggable 내부 처리 */ }, onMove: (dir, ids) => { /* 알림만 — DOM 이동은 Draggable 내부 처리 */ } }); d.setMoveButtonsEnabled(true);"
|
|
813
785
|
}
|
|
814
786
|
},
|
|
815
787
|
"search-result-readonly": {
|
|
@@ -819,7 +791,21 @@
|
|
|
819
791
|
"children": [
|
|
820
792
|
{
|
|
821
793
|
"component": "data-grid.summary",
|
|
822
|
-
"
|
|
794
|
+
"_note": "건수 강조(strong + ncua-data-grid__summary-count)는 시나리오와 무관한 디자인시스템 규칙 — readonly 에서도 동일하게 적용한다. readonly 는 선택/액션이 없다는 뜻이지 summary 마크업을 생략한다는 뜻이 아니다.",
|
|
795
|
+
"children": [
|
|
796
|
+
{
|
|
797
|
+
"component": "span",
|
|
798
|
+
"children": [
|
|
799
|
+
"전체 ",
|
|
800
|
+
{
|
|
801
|
+
"component": "strong",
|
|
802
|
+
"props": { "className": "ncua-data-grid__summary-count" },
|
|
803
|
+
"children": "128"
|
|
804
|
+
},
|
|
805
|
+
"건"
|
|
806
|
+
]
|
|
807
|
+
}
|
|
808
|
+
]
|
|
823
809
|
},
|
|
824
810
|
{
|
|
825
811
|
"component": "data-grid.table",
|
|
@@ -889,8 +875,7 @@
|
|
|
889
875
|
]
|
|
890
876
|
}
|
|
891
877
|
}
|
|
892
|
-
}
|
|
893
|
-
"notApplicableAreas": ["bemClassesExtra"]
|
|
878
|
+
}
|
|
894
879
|
},
|
|
895
880
|
"table": {
|
|
896
881
|
"_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 에 명시 등록.",
|
|
@@ -1192,7 +1177,7 @@
|
|
|
1192
1177
|
}
|
|
1193
1178
|
},
|
|
1194
1179
|
"dnd-row-sorting": {
|
|
1195
|
-
"description": "Horizontal Table — 행 드래그앤드롭 정렬. [React 모드] draggable=true + Table.DragHeaderCell(헤더) + Table.DragCell(각 행) + Table.Row.dragId(문자열 식별자) + Table.Body.onRowDrop(콜백). 반드시 type='horizontal'. DragCell에는 CheckboxInput 등 공동 배치 가능. useState로 rows 배열을 관리하고 onRowDrop에서 배열 재정렬: const [rows, setRows] = useState(initialRows); const handleDrop = (fromId, toId, edge) => { setRows(prev => { const from = prev.findIndex(r => r.id === fromId); const to = prev.findIndex(r => r.id === toId); const next = [...prev]; const [item] = next.splice(from, 1); const insertAt = edge === 'top' ? to : to + 1; next.splice(insertAt > from ? insertAt - 1 : insertAt, 0, item); return next; }); }; [CDN 모드] React DnD props(draggable/dragId/onRowDrop) 대신 window.ncua.Draggable 사용. 각 <tr>에 data-draggable-id 속성 필수. CDN 초기화: const sortable = new window.ncua.Draggable(tbodyEl, { onDrop: function(fromId, toId, edge) { /*
|
|
1180
|
+
"description": "Horizontal Table — 행 드래그앤드롭 정렬. [React 모드] draggable=true + Table.DragHeaderCell(헤더) + Table.DragCell(각 행) + Table.Row.dragId(문자열 식별자) + Table.Body.onRowDrop(콜백). 반드시 type='horizontal'. DragCell에는 CheckboxInput 등 공동 배치 가능. useState로 rows 배열을 관리하고 onRowDrop에서 배열 재정렬: const [rows, setRows] = useState(initialRows); const handleDrop = (fromId, toId, edge) => { setRows(prev => { const from = prev.findIndex(r => r.id === fromId); const to = prev.findIndex(r => r.id === toId); const next = [...prev]; const [item] = next.splice(from, 1); const insertAt = edge === 'top' ? to : to + 1; next.splice(insertAt > from ? insertAt - 1 : insertAt, 0, item); return next; }); }; [CDN 모드] React DnD props(draggable/dragId/onRowDrop) 대신 window.ncua.Draggable 사용. 각 <tr>에 data-draggable-id 속성 필수. CDN 초기화: const sortable = new window.ncua.Draggable(tbodyEl, { onDrop: function(fromId, toId, edge, selectedIds) { /* DOM 행 이동 처리 (insertBefore) + 서버 API 호출 */ }, onSelect: function(selectedIds) { /* 선택 상태 변경 알림 */ }, onMove: function(direction, selectedIds) { /* 이동 버튼 클릭 알림 — DOM 이동은 Draggable 내부 처리 후 호출 */ } }); ⚠️ onDrop: 드래그 종료 시 페이지가 DOM 행 이동 + 서버 API 처리. ⚠️ onMove: Draggable이 DOM 행 이동을 완료한 후 호출되는 알림 — 페이지에서 DOM 재정렬 코드를 작성하지 말 것. ⚠️ DataGrid 안에 배치 시 CDN HTML 모드 필수 조건: (1) ncua-table div에 ncua-table--in-data-grid 클래스 추가(누락 시 2px 이중 테두리), (2) ncua-table-wrapper에 --ncua-table-header-height: 40px CSS 변수 설정. 이동 버튼 그룹은 ncua-data-grid__action-bar 안에 ncua-button-group--xs 패턴으로 배치 + Draggable.setMoveButtonsEnabled(true)로 활성화. data-grid.canonicalExamples.dnd-with-selectable 시나리오 참고.",
|
|
1196
1181
|
"props": {
|
|
1197
1182
|
"type": "horizontal",
|
|
1198
1183
|
"draggable": true,
|
|
@@ -2364,7 +2349,7 @@
|
|
|
2364
2349
|
"notApplicableAreas": ["bemClassesExtra"]
|
|
2365
2350
|
},
|
|
2366
2351
|
"select-box": {
|
|
2367
|
-
"_note": "P5-4b: SelectBox 는 optionItems 배열로 항목 정의. value 는 선택된 항목 객체 또는 id. 자식 컴포넌트로 만들지 말 것. P18: native <select> 또는 dropdown 으로 우회하지 말 것 — select-box 가 NCDS 표준 진입점.",
|
|
2352
|
+
"_note": "P5-4b: SelectBox 는 optionItems 배열로 항목 정의. value 는 선택된 항목 객체 또는 id. 자식 컴포넌트로 만들지 말 것. P18: native <select> 또는 dropdown 으로 우회하지 말 것 — select-box 가 NCDS 표준 진입점. ⚠️ P18 예외 — 정적 렌더 컨텍스트: select-box 는 jsRequired 이고 중첩 children 경로는 CDN init 패턴을 타지 않아, MCP canonicalExample 처럼 스크립트 없이 마크업만 보여주는 자리에서는 optionItems 를 넣어도 옵션이 렌더되지 않고 플레이스홀더만 남는다. 그래서 canonicalExample 안의 필터/정렬 자리에 한해 select 를 사용한다. 실제 구현물에서는 반드시 select-box 를 쓸 것 — 이 예외는 '정적 예제 마크업' 에만 적용된다.",
|
|
2368
2353
|
"descriptionExtra": "[중요] 단일/복수 항목 선택 입력 컴포넌트. value 가 단일이면 multiple=false (기본), 배열이면 multiple=true. 한국어 검색 시 '셀렉트', '드롭다운', '선택상자' 등 다양한 표기 — composition overrides aliases 로 매칭 보강.",
|
|
2369
2354
|
"aliasesExtra": [
|
|
2370
2355
|
"selectbox",
|
|
@@ -2424,6 +2409,48 @@
|
|
|
2424
2409
|
},
|
|
2425
2410
|
"notApplicableAreas": ["bemClassesExtra"]
|
|
2426
2411
|
},
|
|
2412
|
+
"select": {
|
|
2413
|
+
"_note": "네이티브 <select> 래퍼. 기본 선택 UI 는 select-box 가 표준 진입점이고(select-box._note 의 P18), select 는 예외 상황 전용이다 — (1) 스크립트 없이 마크업만 보여주는 정적 렌더(MCP canonicalExample 등): select-box 는 jsRequired 라 optionItems 를 넣어도 옵션이 렌더되지 않는다. (2) react-hook-form 의 register 를 직접 연결해야 하는 폼. 그 외에는 select-box 를 쓸 것. optionItems 배열로 항목을 정의하고 자식 컴포넌트로 만들지 않는다.",
|
|
2414
|
+
"descriptionExtra": "[중요] 네이티브 HTML select 래퍼 — 대부분의 경우 select-box 를 우선 사용한다. size: xs(기본)/sm/md, type: default/simple. optionItems=[{id, label}] 배열로 항목 정의. ⚠️ 사이즈 modifier(ncua-select--xs/--sm/--md)는 SCSS 의 @each 루프로 동적 생성되어 pnpm extract 가 자동 추출하지 못하므로 bemClassesExtra 에 명시 등록했다 — 미등록 시 validate_html 이 invalid_modifier 로 거부하고 fixed_html 이 사이즈 클래스를 제거해 기본 크기로 되돌린다. ⚠️ 정적 렌더가 아닌 실제 화면에서는 select-box 사용을 우선 검토할 것.",
|
|
2415
|
+
"aliasesExtra": [
|
|
2416
|
+
"네이티브 select",
|
|
2417
|
+
"정렬 선택",
|
|
2418
|
+
"페이지 크기 선택",
|
|
2419
|
+
"sort select",
|
|
2420
|
+
"page size select",
|
|
2421
|
+
"폼 select",
|
|
2422
|
+
"form select"
|
|
2423
|
+
],
|
|
2424
|
+
"_note_bemClassesExtra": "ncua-select--xs / --sm / --md 는 [_select.scss:126] 의 `@each $size, $info in $select-size` 루프로 생성되어 React Select.tsx 본체에 리터럴로 존재하지 않아 pnpm extract 가 bemClasses 로 잡지 못한다. validate_html 화이트리스트 통과를 위해 명시 등록(table/data-grid.bemClassesExtra 와 동일 관행).",
|
|
2425
|
+
"bemClassesExtra": ["ncua-select--xs", "ncua-select--sm", "ncua-select--md"],
|
|
2426
|
+
"canonicalExamples": {
|
|
2427
|
+
"_note": "AI 는 사용자 의도에 따라 하나의 키를 명시적으로 선택해 시작점으로 사용한다. 라벨/옵션만 교체하고 구조는 유지. 시나리오 사이의 부분 혼합은 금지.",
|
|
2428
|
+
"action-bar-sort": {
|
|
2429
|
+
"description": "목록 화면 action-bar 우측의 정렬/페이지크기 선택. 컴팩트한 xs 사이즈. data-grid canonicalExample 이 쓰는 형태.",
|
|
2430
|
+
"props": {
|
|
2431
|
+
"size": "xs",
|
|
2432
|
+
"optionItems": [
|
|
2433
|
+
{ "id": "recent", "label": "최근 등록순" },
|
|
2434
|
+
{ "id": "name", "label": "상품명순" },
|
|
2435
|
+
{ "id": "price", "label": "가격순" }
|
|
2436
|
+
]
|
|
2437
|
+
}
|
|
2438
|
+
},
|
|
2439
|
+
"form-field-with-hint": {
|
|
2440
|
+
"description": "폼 필드용 선택 입력. placeholder 로 미선택 상태를 안내하고 hintText 로 보조 설명을 붙인다.",
|
|
2441
|
+
"props": {
|
|
2442
|
+
"size": "sm",
|
|
2443
|
+
"placeholder": "배송 방법을 선택하세요",
|
|
2444
|
+
"hintText": "주문 후에는 변경할 수 없습니다.",
|
|
2445
|
+
"optionItems": [
|
|
2446
|
+
{ "id": "parcel", "label": "택배" },
|
|
2447
|
+
{ "id": "direct", "label": "직접 수령" },
|
|
2448
|
+
{ "id": "quick", "label": "퀵 배송" }
|
|
2449
|
+
]
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
},
|
|
2427
2454
|
"switch": {
|
|
2428
2455
|
"_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 하지 말 것.",
|
|
2429
2456
|
"descriptionExtra": "[중요] 두 선택지 토글 컴포넌트 (좌/우 영역 선택). left/right props (각각 { value, label }) + value(선택된 value) + size(xxs/xs/sm/md) + disabled. ⚠️ Switch HTML 은 반드시 render_to_html('switch', props) 로만 생성 — 수동 HTML 작성 시 ncua-switch__radio 클래스 누락으로 native radio 버튼이 그대로 노출됨. 페이지 SCSS 에서 .ncua-switch__option--active 등 override CSS 작성 금지 — CDN CSS 가 완비. 발명 modifier(--toggled / --selected) 사용 금지.",
|