@ncds/ui-admin-mcp 1.0.0-alpha.14 → 1.0.0-alpha.15
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 +1 -1
- package/bin/definitions/external/editor.d.ts +50 -0
- package/bin/definitions/external/editor.js +53 -0
- package/bin/definitions/js-api.json +68 -15
- package/bin/tools/renderToHtml.d.ts +15 -0
- package/bin/tools/renderToHtml.js +16 -7
- package/data/badge-group.json +1 -1
- package/data/badge.json +1 -1
- package/data/bread-crumb.json +1 -1
- package/data/carousel-arrow.json +1 -1
- package/data/carousel-number-group.json +1 -1
- package/data/checkbox.json +1 -1
- package/data/combo-box.json +1 -1
- package/data/date-picker.json +1 -1
- package/data/divider.json +1 -1
- package/data/dot.json +1 -1
- package/data/dropdown.json +38 -18
- package/data/editor.json +85 -0
- package/data/empty-state.json +2 -2
- package/data/featured-icon.json +1 -1
- package/data/file-input.json +1 -1
- package/data/horizontal-tab.json +1 -1
- package/data/image-file-input.json +1 -1
- package/data/input-base.json +1 -1
- package/data/modal.json +2 -2
- package/data/notification.json +2 -2
- package/data/number-input.json +1 -1
- package/data/password-input.json +1 -1
- package/data/progress-bar.json +2 -2
- package/data/progress-circle.json +1 -1
- package/data/radio.json +1 -1
- package/data/range-date-picker-with-buttons.json +3 -3
- package/data/range-date-picker.json +3 -3
- package/data/select-box.json +1 -1
- package/data/select.json +1 -1
- package/data/slider.json +1 -1
- package/data/spinner.json +1 -1
- package/data/switch.json +1 -1
- package/data/tag.json +1 -1
- package/data/textarea.json +1 -1
- package/data/toggle.json +1 -1
- package/data/tooltip.json +1 -1
- package/data/vertical-tab.json +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story 5.10: editor 외부 분기 정의
|
|
3
|
+
*
|
|
4
|
+
* froala 기반 에디터(`@ncds/editor-html`)의 응답 메타·CDN URL·props·cdnDefaults·methods.
|
|
5
|
+
* `tools/external/editor.ts` 의 `buildEditorResponse` 가 본 정의를 읽어 응답 조립.
|
|
6
|
+
* (json 대신 ts — tsconfig `module: Node16` 환경에서 import 단순화. 빌드 시 자동 포함.)
|
|
7
|
+
*/
|
|
8
|
+
export declare const editorDefinition: {
|
|
9
|
+
readonly name: "editor";
|
|
10
|
+
readonly className: "NcdsEditor";
|
|
11
|
+
readonly category: "form";
|
|
12
|
+
readonly description: "froala 기반 WYSIWYG 에디터. textarea 를 in-place 변환.";
|
|
13
|
+
readonly cdn: {
|
|
14
|
+
readonly version: "0.0";
|
|
15
|
+
readonly css: "https://fe-sdk.cdn-nhncommerce.com/@ncds/editor/0.0/ncds-editor.css";
|
|
16
|
+
readonly js: "https://fe-sdk.cdn-nhncommerce.com/@ncds/editor/0.0/ncds-editor.js";
|
|
17
|
+
};
|
|
18
|
+
readonly props: readonly [{
|
|
19
|
+
readonly name: "heightMin";
|
|
20
|
+
readonly type: "number";
|
|
21
|
+
readonly default: 300;
|
|
22
|
+
readonly description: "최소 높이 (px)";
|
|
23
|
+
}, {
|
|
24
|
+
readonly name: "heightMax";
|
|
25
|
+
readonly type: "number";
|
|
26
|
+
readonly default: 600;
|
|
27
|
+
readonly description: "최대 높이 (px)";
|
|
28
|
+
}, {
|
|
29
|
+
readonly name: "heightResize";
|
|
30
|
+
readonly type: "boolean";
|
|
31
|
+
readonly default: false;
|
|
32
|
+
readonly description: "높이 조정 가능 여부";
|
|
33
|
+
}, {
|
|
34
|
+
readonly name: "placeholderText";
|
|
35
|
+
readonly type: "string";
|
|
36
|
+
readonly default: "내용을 입력하세요.";
|
|
37
|
+
readonly description: "플레이스홀더 텍스트";
|
|
38
|
+
}, {
|
|
39
|
+
readonly name: "imageUploadCallback";
|
|
40
|
+
readonly type: "function";
|
|
41
|
+
readonly description: "이미지 업로드 콜백 함수명 (전역 함수). 외부 분기에서 stripFunctionProps 로 자동 제외 — data-* 직렬화 대상 아님";
|
|
42
|
+
}];
|
|
43
|
+
readonly cdnDefaults: {
|
|
44
|
+
heightMin: number;
|
|
45
|
+
heightMax: number;
|
|
46
|
+
heightResize: boolean;
|
|
47
|
+
placeholderText: string;
|
|
48
|
+
};
|
|
49
|
+
readonly methods: readonly ["getHTML()", "setHTML(html)", "getText()", "focus()", "blur()", "enable()", "disable()", "destroy()", "insertImage(src, alt, link)", "insertLink(href, text)", "insertTable(rows, cols)", "on(event, handler)", "off(event)"];
|
|
50
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Story 5.10: editor 외부 분기 정의
|
|
4
|
+
*
|
|
5
|
+
* froala 기반 에디터(`@ncds/editor-html`)의 응답 메타·CDN URL·props·cdnDefaults·methods.
|
|
6
|
+
* `tools/external/editor.ts` 의 `buildEditorResponse` 가 본 정의를 읽어 응답 조립.
|
|
7
|
+
* (json 대신 ts — tsconfig `module: Node16` 환경에서 import 단순화. 빌드 시 자동 포함.)
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.editorDefinition = void 0;
|
|
11
|
+
exports.editorDefinition = {
|
|
12
|
+
name: 'editor',
|
|
13
|
+
className: 'NcdsEditor',
|
|
14
|
+
category: 'form',
|
|
15
|
+
description: 'froala 기반 WYSIWYG 에디터. textarea 를 in-place 변환.',
|
|
16
|
+
cdn: {
|
|
17
|
+
version: '0.0',
|
|
18
|
+
css: 'https://fe-sdk.cdn-nhncommerce.com/@ncds/editor/0.0/ncds-editor.css',
|
|
19
|
+
js: 'https://fe-sdk.cdn-nhncommerce.com/@ncds/editor/0.0/ncds-editor.js',
|
|
20
|
+
},
|
|
21
|
+
props: [
|
|
22
|
+
{ name: 'heightMin', type: 'number', default: 300, description: '최소 높이 (px)' },
|
|
23
|
+
{ name: 'heightMax', type: 'number', default: 600, description: '최대 높이 (px)' },
|
|
24
|
+
{ name: 'heightResize', type: 'boolean', default: false, description: '높이 조정 가능 여부' },
|
|
25
|
+
{ name: 'placeholderText', type: 'string', default: '내용을 입력하세요.', description: '플레이스홀더 텍스트' },
|
|
26
|
+
{
|
|
27
|
+
name: 'imageUploadCallback',
|
|
28
|
+
type: 'function',
|
|
29
|
+
description: '이미지 업로드 콜백 함수명 (전역 함수). 외부 분기에서 stripFunctionProps 로 자동 제외 — data-* 직렬화 대상 아님',
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
cdnDefaults: {
|
|
33
|
+
heightMin: 300,
|
|
34
|
+
heightMax: 600,
|
|
35
|
+
heightResize: false,
|
|
36
|
+
placeholderText: '내용을 입력하세요.',
|
|
37
|
+
},
|
|
38
|
+
methods: [
|
|
39
|
+
'getHTML()',
|
|
40
|
+
'setHTML(html)',
|
|
41
|
+
'getText()',
|
|
42
|
+
'focus()',
|
|
43
|
+
'blur()',
|
|
44
|
+
'enable()',
|
|
45
|
+
'disable()',
|
|
46
|
+
'destroy()',
|
|
47
|
+
'insertImage(src, alt, link)',
|
|
48
|
+
'insertLink(href, text)',
|
|
49
|
+
'insertTable(rows, cols)',
|
|
50
|
+
'on(event, handler)',
|
|
51
|
+
'off(event)',
|
|
52
|
+
],
|
|
53
|
+
};
|
|
@@ -60,10 +60,10 @@
|
|
|
60
60
|
"constructorParams": {
|
|
61
61
|
"wrapper": "HTMLElement — container element",
|
|
62
62
|
"options.size": "'xs' | 'sm'",
|
|
63
|
-
"options.
|
|
64
|
-
"options.
|
|
65
|
-
"options.
|
|
66
|
-
"options.
|
|
63
|
+
"options.datePickerOptions": "Array<{ element: string, attrName?: string, placeholder?: string, options: FlatpickrOptions }>",
|
|
64
|
+
"options.buttons": "Array<{ text: string, period: number, unit: 'days'|'weeks'|'months'|'years', isCurrent: boolean }>",
|
|
65
|
+
"options.onValidationError": "(error: ValidationError) => void",
|
|
66
|
+
"options.autoComplete": "'on' | 'off'"
|
|
67
67
|
},
|
|
68
68
|
"methods": ["getDates()", "setDate(dates: string[])", "setMultipleDates(dates: string[])"],
|
|
69
69
|
"example": "const dp = new window.ncua.DatePicker(document.getElementById('my-dp'), {\n size: 'xs',\n datePickerOptions: [{ element: 'date-input', placeholder: 'Select date', options: { dateFormat: 'Y-m-d' } }]\n});",
|
|
@@ -94,7 +94,8 @@
|
|
|
94
94
|
"options.step": "number (default: 1)",
|
|
95
95
|
"options.value": "number | [number, number]",
|
|
96
96
|
"options.onChange": "(value) => void",
|
|
97
|
-
"options.disabled": "boolean"
|
|
97
|
+
"options.disabled": "boolean",
|
|
98
|
+
"options.labelPosition": "'bottom' | 'top-floating'"
|
|
98
99
|
},
|
|
99
100
|
"methods": ["getValue()", "setValue(value)", "enable()", "disable()", "destroy()"],
|
|
100
101
|
"example": "const slider = new window.ncua.Slider(document.getElementById('my-slider'), {\n min: 0, max: 100, value: 50,\n onChange: (v) => console.log(v)\n});",
|
|
@@ -121,7 +122,15 @@
|
|
|
121
122
|
"constructorParams": {
|
|
122
123
|
"title": "string",
|
|
123
124
|
"content": "string (HTML supported)",
|
|
124
|
-
"options.position": "'top' | 'bottom' | 'left' | 'right' (default: '
|
|
125
|
+
"options.position": "'top' | 'bottom' | 'left' | 'right' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'auto' (default: 'auto')",
|
|
126
|
+
"options.type": "'long' | 'short'",
|
|
127
|
+
"options.tooltipType": "'white' | 'black'",
|
|
128
|
+
"options.iconType": "'stroke' | 'fill'",
|
|
129
|
+
"options.size": "'sm' | 'md'",
|
|
130
|
+
"options.hideArrow": "boolean",
|
|
131
|
+
"options.zIndex": "number",
|
|
132
|
+
"options.useShadowDOM": "boolean",
|
|
133
|
+
"options.className": "string"
|
|
125
134
|
},
|
|
126
135
|
"methods": ["getElement()", "showTooltip()", "hideTooltip()", "destroy()"],
|
|
127
136
|
"example": "const tip = window.ncua.Tooltip.createShort('Help', 'Tooltip content');\ndocument.getElementById('container').appendChild(tip.getElement());",
|
|
@@ -129,7 +138,6 @@
|
|
|
129
138
|
"type": "short",
|
|
130
139
|
"tooltipType": "black",
|
|
131
140
|
"iconType": "stroke",
|
|
132
|
-
"iconStyle": "help-circle",
|
|
133
141
|
"position": "auto",
|
|
134
142
|
"size": "sm"
|
|
135
143
|
}
|
|
@@ -146,7 +154,14 @@
|
|
|
146
154
|
"constructorParams": {
|
|
147
155
|
"title": "string",
|
|
148
156
|
"supportingText": "string",
|
|
149
|
-
"options.autoClose": "number (ms, 0 = no auto-close)"
|
|
157
|
+
"options.autoClose": "number (ms, 0 = no auto-close)",
|
|
158
|
+
"options.type": "'floating' | 'message' | 'full-width'",
|
|
159
|
+
"options.color": "'neutral' | 'success' | 'error' | 'warning' | 'info'",
|
|
160
|
+
"options.actions": "Array<NotificationAction>",
|
|
161
|
+
"options.onClose": "() => void",
|
|
162
|
+
"options.className": "string",
|
|
163
|
+
"options.supportTextLink": "string — full-width 전용 supportingText 링크 URL",
|
|
164
|
+
"options.onHidePermanently": "() => void — full-width/message 다시보지 않기 핸들러"
|
|
150
165
|
},
|
|
151
166
|
"methods": ["show(parent?)", "remove()", "destroy()"],
|
|
152
167
|
"staticMethods": ["success()", "error()", "warning()", "info()", "neutral()"],
|
|
@@ -158,7 +173,10 @@
|
|
|
158
173
|
"constructor": "new window.ncua.ProgressBar(options?)",
|
|
159
174
|
"constructorParams": {
|
|
160
175
|
"options.value": "number (0-100)",
|
|
161
|
-
"options.label": "'right' | 'bottom' | 'top-float' | 'bottom-float'"
|
|
176
|
+
"options.label": "'right' | 'bottom' | 'top-float' | 'bottom-float'",
|
|
177
|
+
"options.segments": "ProgressSegment[] — 멀티 세그먼트 진행률",
|
|
178
|
+
"options.showZeroLabel": "boolean — 0% 라벨 표시 여부",
|
|
179
|
+
"options.valueToPercent": "boolean — value 를 % 환산 표시"
|
|
162
180
|
},
|
|
163
181
|
"methods": ["getElement()", "updateOptions(newOptions)", "toHTML()"],
|
|
164
182
|
"example": "const bar = new window.ncua.ProgressBar({ value: 65, label: 'right' });\ndocument.getElementById('container').appendChild(bar.getElement());",
|
|
@@ -174,7 +192,10 @@
|
|
|
174
192
|
"options.text": "string",
|
|
175
193
|
"options.size": "'sm' | 'md' (default: 'sm')",
|
|
176
194
|
"options.close": "boolean — show close button",
|
|
177
|
-
"options.onButtonClick": "() => void — close handler"
|
|
195
|
+
"options.onButtonClick": "(event: MouseEvent) => void — close handler",
|
|
196
|
+
"options.count": "string — 카운트 표시",
|
|
197
|
+
"options.icon": "SideSlotType — 좌측 아이콘 슬롯",
|
|
198
|
+
"options.maxLength": "number — 최대 텍스트 길이 (default: 20)"
|
|
178
199
|
},
|
|
179
200
|
"methods": ["getElement()", "setText(text)", "setCount(count)", "destroy()"],
|
|
180
201
|
"example": "const tag = new window.ncua.Tag({ text: 'Label', close: true, onButtonClick: () => tag.destroy() });\ndocument.getElementById('container').appendChild(tag.getElement());",
|
|
@@ -190,7 +211,21 @@
|
|
|
190
211
|
"options.container": "HTMLElement | string — auto-append target",
|
|
191
212
|
"options.onChange": "(files: File[]) => void",
|
|
192
213
|
"options.onFail": "(invalidFiles: File[]) => void",
|
|
193
|
-
"options.disabled": "boolean"
|
|
214
|
+
"options.disabled": "boolean",
|
|
215
|
+
"options.size": "'xs' | 'sm'",
|
|
216
|
+
"options.accept": "string — e.g. '.jpg,.png' or 'image/*'",
|
|
217
|
+
"options.multiple": "boolean",
|
|
218
|
+
"options.maxFileCount": "number",
|
|
219
|
+
"options.maxFileSize": "number — bytes",
|
|
220
|
+
"options.buttonLabel": "string",
|
|
221
|
+
"options.label": "string",
|
|
222
|
+
"options.hintItems": "string[]",
|
|
223
|
+
"options.isRequired": "boolean",
|
|
224
|
+
"options.showHelpIcon": "boolean",
|
|
225
|
+
"options.hintText": "string",
|
|
226
|
+
"options.validation": "boolean",
|
|
227
|
+
"options.destructive": "boolean",
|
|
228
|
+
"options.className": "string"
|
|
194
229
|
},
|
|
195
230
|
"methods": ["getElement()", "setDisabled(boolean)", "destroy()"],
|
|
196
231
|
"example": "const fi = new window.ncua.FileInput({\n container: 'file-container',\n onChange: (files) => console.log(files)\n});",
|
|
@@ -204,10 +239,27 @@
|
|
|
204
239
|
"constructor": "new window.ncua.ImageFileInput(options)",
|
|
205
240
|
"constructorParams": {
|
|
206
241
|
"options.container": "HTMLElement | string — auto-append target",
|
|
207
|
-
"options.onChange": "(files: File[]) => void",
|
|
242
|
+
"options.onChange": "(files: File[]) => void — controlled mode",
|
|
243
|
+
"options.onFileSelect": "(files: File[]) => void — uncontrolled mode",
|
|
244
|
+
"options.onFail": "(files: InvalidFile[]) => void",
|
|
245
|
+
"options.value": "File[] — initial files (controlled mode)",
|
|
246
|
+
"options.disabled": "boolean",
|
|
247
|
+
"options.size": "'xs' | 'sm'",
|
|
248
|
+
"options.accept": "string — e.g. '.jpg,.png' or 'image/*'",
|
|
249
|
+
"options.multiple": "boolean",
|
|
208
250
|
"options.maxFileCount": "number",
|
|
209
|
-
"options.
|
|
210
|
-
"options.
|
|
251
|
+
"options.maxFileSize": "number — bytes",
|
|
252
|
+
"options.buttonLabel": "string",
|
|
253
|
+
"options.imagePreviewTooltipLabel": "string",
|
|
254
|
+
"options.label": "string",
|
|
255
|
+
"options.hintItems": "string[]",
|
|
256
|
+
"options.isRequired": "boolean",
|
|
257
|
+
"options.showHelpIcon": "boolean",
|
|
258
|
+
"options.hintText": "string",
|
|
259
|
+
"options.validation": "boolean",
|
|
260
|
+
"options.destructive": "boolean",
|
|
261
|
+
"options.fileInputName": "string — name attr (PHP form 제출용)",
|
|
262
|
+
"options.className": "string"
|
|
211
263
|
},
|
|
212
264
|
"cdnDefaults": {
|
|
213
265
|
"buttonLabel": "파일 찾기"
|
|
@@ -222,7 +274,8 @@
|
|
|
222
274
|
"options.svgString": "string — SVG content",
|
|
223
275
|
"options.theme": "'light-circle' | 'dark-circle' | 'outline-circle' | 'square-outline'",
|
|
224
276
|
"options.color": "'neutral' | 'error' | 'warning' | 'success'",
|
|
225
|
-
"options.size": "'sm' | 'md' | 'lg' | 'xl'"
|
|
277
|
+
"options.size": "'sm' | 'md' | 'lg' | 'xl'",
|
|
278
|
+
"options.className": "string"
|
|
226
279
|
},
|
|
227
280
|
"methods": ["getElement()", "updateColor(color)", "updateSize(size)", "destroy()"],
|
|
228
281
|
"example": "const icon = new window.ncua.FeaturedIcon({ svgString: '<svg>...</svg>', color: 'success', size: 'md' });\ndocument.getElementById('container').appendChild(icon.getElement());"
|
|
@@ -19,5 +19,20 @@ export interface RenderToHtmlParams {
|
|
|
19
19
|
*/
|
|
20
20
|
instanceId: string;
|
|
21
21
|
}
|
|
22
|
+
/** Story 5.9: 사용자 props 에서 함수 prop 재귀 제거 (JSON 직렬화·deep merge 안전).
|
|
23
|
+
* cdnDefaults 는 JSON 이라 함수 없음 → 사용자 props 만 정리.
|
|
24
|
+
* Story 5.10: 외부 분기 모듈(`tools/external/editor.ts`)에서도 재사용 → export. */
|
|
25
|
+
export declare const stripFunctionProps: (obj: unknown) => unknown;
|
|
26
|
+
/** Story 5.9: cdnDefaults 와 사용자 props 를 deep merge.
|
|
27
|
+
* - 사용자 값 우선 (lodash merge 의 두 번째 인자가 우선)
|
|
28
|
+
* - 함수 prop 은 사용자 props 에서 stripFunctionProps 로 사전 제거
|
|
29
|
+
* - DatePicker `datePickerOptions` 배열 한정: 각 항목의 `options` 에 cdnDefaults 의 첫 항목 options 를 per-element 부분 merge
|
|
30
|
+
* - 다른 배열(`buttons` 등) 은 사용자 값 그대로
|
|
31
|
+
* 반환: { merged, defaultsApplied } — defaultsApplied 는 cdnDefaults 에 있고 사용자 props 에 없는 top-level 키 (defaultsUsed 응답용)
|
|
32
|
+
* Story 5.10: 외부 분기 모듈(`tools/external/editor.ts`)에서도 재사용 → export. */
|
|
33
|
+
export declare const mergeCdnDefaults: (componentName: string, cdnDefaults: Record<string, unknown> | undefined, userProps: Record<string, unknown>) => {
|
|
34
|
+
merged: Record<string, unknown>;
|
|
35
|
+
defaultsApplied: string[];
|
|
36
|
+
};
|
|
22
37
|
/** render_to_html tool — props로 React 컴포넌트를 렌더링하여 HTML + React 매핑 반환 */
|
|
23
38
|
export declare const renderToHtml: (params: RenderToHtmlParams) => McpToolResponse;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.renderToHtml = void 0;
|
|
3
|
+
exports.renderToHtml = exports.mergeCdnDefaults = exports.stripFunctionProps = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* render_to_html tool — 컴포넌트 속성을 전달하면 정확한 HTML + React 매핑을 반환 (순수 함수)
|
|
6
6
|
*
|
|
@@ -14,6 +14,7 @@ exports.renderToHtml = void 0;
|
|
|
14
14
|
// biome-ignore-all lint/style/useTemplate: 기존 attrsPrefix 문자열 결합 (Story 5.8 scope 외)
|
|
15
15
|
const lodash_1 = require("lodash");
|
|
16
16
|
const response_js_1 = require("../utils/response.js");
|
|
17
|
+
const editor_js_1 = require("./external/editor.js");
|
|
17
18
|
// ── 상수 ──────────────────────────────────────────────────────────
|
|
18
19
|
/** React 특수 props 차단 — injection 방지 */
|
|
19
20
|
const BLOCKED_PROPS = new Set(['dangerouslySetInnerHTML', 'ref', '__self', '__source']);
|
|
@@ -444,30 +445,33 @@ const normalizeCdnInputProps = (componentName, cdnConfig) => {
|
|
|
444
445
|
return { normalized: { ...cdnConfig, options: normalizedOptions }, warnings };
|
|
445
446
|
};
|
|
446
447
|
/** Story 5.9: 사용자 props 에서 함수 prop 재귀 제거 (JSON 직렬화·deep merge 안전).
|
|
447
|
-
* cdnDefaults 는 JSON 이라 함수 없음 → 사용자 props 만
|
|
448
|
+
* cdnDefaults 는 JSON 이라 함수 없음 → 사용자 props 만 정리.
|
|
449
|
+
* Story 5.10: 외부 분기 모듈(`tools/external/editor.ts`)에서도 재사용 → export. */
|
|
448
450
|
const stripFunctionProps = (obj) => {
|
|
449
451
|
if (typeof obj === 'function')
|
|
450
452
|
return undefined;
|
|
451
453
|
if (Array.isArray(obj)) {
|
|
452
|
-
return obj.map((item) => stripFunctionProps(item)).filter((item) => item !== undefined);
|
|
454
|
+
return obj.map((item) => (0, exports.stripFunctionProps)(item)).filter((item) => item !== undefined);
|
|
453
455
|
}
|
|
454
456
|
if (typeof obj === 'object' && obj !== null) {
|
|
455
457
|
return Object.fromEntries(Object.entries(obj)
|
|
456
458
|
.filter(([, value]) => typeof value !== 'function')
|
|
457
|
-
.map(([key, value]) => [key, stripFunctionProps(value)]));
|
|
459
|
+
.map(([key, value]) => [key, (0, exports.stripFunctionProps)(value)]));
|
|
458
460
|
}
|
|
459
461
|
return obj;
|
|
460
462
|
};
|
|
463
|
+
exports.stripFunctionProps = stripFunctionProps;
|
|
461
464
|
/** Story 5.9: cdnDefaults 와 사용자 props 를 deep merge.
|
|
462
465
|
* - 사용자 값 우선 (lodash merge 의 두 번째 인자가 우선)
|
|
463
466
|
* - 함수 prop 은 사용자 props 에서 stripFunctionProps 로 사전 제거
|
|
464
467
|
* - DatePicker `datePickerOptions` 배열 한정: 각 항목의 `options` 에 cdnDefaults 의 첫 항목 options 를 per-element 부분 merge
|
|
465
468
|
* - 다른 배열(`buttons` 등) 은 사용자 값 그대로
|
|
466
|
-
* 반환: { merged, defaultsApplied } — defaultsApplied 는 cdnDefaults 에 있고 사용자 props 에 없는 top-level 키 (defaultsUsed 응답용)
|
|
469
|
+
* 반환: { merged, defaultsApplied } — defaultsApplied 는 cdnDefaults 에 있고 사용자 props 에 없는 top-level 키 (defaultsUsed 응답용)
|
|
470
|
+
* Story 5.10: 외부 분기 모듈(`tools/external/editor.ts`)에서도 재사용 → export. */
|
|
467
471
|
const mergeCdnDefaults = (componentName, cdnDefaults, userProps) => {
|
|
468
472
|
if (!cdnDefaults)
|
|
469
473
|
return { merged: userProps, defaultsApplied: [] };
|
|
470
|
-
const userPropsClean = stripFunctionProps(userProps);
|
|
474
|
+
const userPropsClean = (0, exports.stripFunctionProps)(userProps);
|
|
471
475
|
const baseMerged = (0, lodash_1.merge)((0, lodash_1.cloneDeep)(cdnDefaults), userPropsClean);
|
|
472
476
|
const merged = componentName === 'date-picker' && Array.isArray(userPropsClean.datePickerOptions)
|
|
473
477
|
? {
|
|
@@ -484,6 +488,7 @@ const mergeCdnDefaults = (componentName, cdnDefaults, userProps) => {
|
|
|
484
488
|
const defaultsApplied = Object.keys(cdnDefaults).filter((key) => !(key in userPropsClean));
|
|
485
489
|
return { merged, defaultsApplied };
|
|
486
490
|
};
|
|
491
|
+
exports.mergeCdnDefaults = mergeCdnDefaults;
|
|
487
492
|
/** CDN config(에이전트 입력) → React props (buildReactOutput 입력) 번역.
|
|
488
493
|
* 단순 컴포넌트는 identity, 차이가 있는 컴포넌트는 별도 룰. */
|
|
489
494
|
const translateCdnToReactProps = (componentName, cdnConfig) => {
|
|
@@ -648,6 +653,10 @@ const buildJsField = (componentData, jsApiMap) => {
|
|
|
648
653
|
const renderToHtml = (params) => {
|
|
649
654
|
const { componentMap, bundle, iconBundle, cdnMeta, iconMeta, reactRuntime, jsApiMap, name, props, instanceId } = params;
|
|
650
655
|
const normalized = (0, response_js_1.normalizeName)(name);
|
|
656
|
+
// Story 5.10: editor alias 검출 시 ui-admin 흐름 우회 — 외부 분기에서 응답 직접 조립
|
|
657
|
+
if ((0, editor_js_1.isEditorAlias)(normalized)) {
|
|
658
|
+
return (0, editor_js_1.buildEditorResponse)(props ?? {}, instanceId);
|
|
659
|
+
}
|
|
651
660
|
const componentData = componentMap.get(normalized);
|
|
652
661
|
if (!componentData)
|
|
653
662
|
return (0, response_js_1.componentNotFoundResponse)(normalized);
|
|
@@ -670,7 +679,7 @@ const renderToHtml = (params) => {
|
|
|
670
679
|
const normalizedCdnProps = cdnNormalization.normalized;
|
|
671
680
|
// Story 5.9: cdnDefaults 와 deep merge (사용자 props 우선, 함수 prop skip, datePickerOptions per-element 부분 merge)
|
|
672
681
|
const cdnMergeResult = isCdnInput && jsApi
|
|
673
|
-
? mergeCdnDefaults(normalized, jsApi.cdnDefaults, normalizedCdnProps)
|
|
682
|
+
? (0, exports.mergeCdnDefaults)(normalized, jsApi.cdnDefaults, normalizedCdnProps)
|
|
674
683
|
: { merged: normalizedCdnProps, defaultsApplied: [] };
|
|
675
684
|
const mergedCdnProps = cdnMergeResult.merged;
|
|
676
685
|
const reactInput = isCdnInput ? translateCdnToReactProps(normalized, mergedCdnProps) : mergedCdnProps;
|
package/data/badge-group.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"exportName": "BadgeGroup",
|
|
4
4
|
"importPath": "@ncds/ui-admin",
|
|
5
5
|
"jsRequired": false,
|
|
6
|
-
"category": "feedback",
|
|
6
|
+
"category": "feedback-and-status",
|
|
7
7
|
"description": "BadgeGroup은 Badge 컴포넌트를 그룹화하여 표시하는 컴포넌트입니다. 주로 Badge와 함께 추가적인 라벨과 아이콘을 표시하여 액션유도할 수 있는 아이템으로 활용할 수 있습니다.",
|
|
8
8
|
"aliases": [
|
|
9
9
|
"BadgeGroup",
|
package/data/badge.json
CHANGED
package/data/bread-crumb.json
CHANGED
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"items": {
|
|
58
58
|
"type": "object",
|
|
59
59
|
"required": true,
|
|
60
|
-
"rawType": "import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/bread-crumb/BreadCrumb\").BreadcrumbItemProps[]",
|
|
60
|
+
"rawType": "import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/navigation/bread-crumb/BreadCrumb\").BreadcrumbItemProps[]",
|
|
61
61
|
"properties": {
|
|
62
62
|
"href": {
|
|
63
63
|
"type": "string",
|
package/data/carousel-arrow.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"exportName": "CarouselNumberGroup",
|
|
4
4
|
"importPath": "@ncds/ui-admin",
|
|
5
5
|
"jsRequired": false,
|
|
6
|
-
"category": "feedback",
|
|
6
|
+
"category": "feedback-and-status",
|
|
7
7
|
"description": "CarouselNumberGroup은 캐러셀의 현재 페이지와 전체 페이지 수를 표시하는 컴포넌트입니다.",
|
|
8
8
|
"aliases": [
|
|
9
9
|
"CarouselNumberGroup",
|
package/data/checkbox.json
CHANGED
package/data/combo-box.json
CHANGED
package/data/date-picker.json
CHANGED
package/data/divider.json
CHANGED
package/data/dot.json
CHANGED
package/data/dropdown.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"exportName": "Dropdown",
|
|
4
4
|
"importPath": "@ncds/ui-admin",
|
|
5
5
|
"jsRequired": false,
|
|
6
|
-
"category": "
|
|
6
|
+
"category": "overlays",
|
|
7
7
|
"description": "Dropdown(메뉴형)은 버튼, 아이콘, 아바타 등 트리거 요소를 통해 숨겨진 메뉴 또는 작업(Action) 목록을 레이어 형태로 노출하는 컴포넌트입니다.",
|
|
8
8
|
"aliases": [
|
|
9
9
|
"Dropdown",
|
|
@@ -97,32 +97,25 @@
|
|
|
97
97
|
"values": [
|
|
98
98
|
"left",
|
|
99
99
|
"right"
|
|
100
|
-
]
|
|
101
|
-
"default": "left"
|
|
100
|
+
]
|
|
102
101
|
},
|
|
103
102
|
"className": {
|
|
104
103
|
"type": "string",
|
|
105
104
|
"required": false
|
|
106
105
|
},
|
|
107
|
-
"closeOnClickItem": {
|
|
108
|
-
"type": "boolean",
|
|
109
|
-
"required": false,
|
|
110
|
-
"default": true
|
|
111
|
-
},
|
|
112
106
|
"closeOnClickOutside": {
|
|
113
107
|
"type": "boolean",
|
|
114
|
-
"required": false
|
|
115
|
-
"default": true
|
|
108
|
+
"required": false
|
|
116
109
|
},
|
|
117
110
|
"groups": {
|
|
118
111
|
"type": "object",
|
|
119
112
|
"required": true,
|
|
120
|
-
"rawType": "import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/dropdown/Dropdown\").DropdownGroup[]",
|
|
113
|
+
"rawType": "import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/overlays/dropdown/Dropdown\").DropdownGroup[]",
|
|
121
114
|
"properties": {
|
|
122
115
|
"items": {
|
|
123
116
|
"type": "object",
|
|
124
117
|
"required": true,
|
|
125
|
-
"rawType": "import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/dropdown/Dropdown\").DropdownItemType[]",
|
|
118
|
+
"rawType": "import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/overlays/dropdown/Dropdown\").DropdownItemType[]",
|
|
126
119
|
"properties": {
|
|
127
120
|
"id": {
|
|
128
121
|
"type": "string",
|
|
@@ -160,15 +153,27 @@
|
|
|
160
153
|
"className": {
|
|
161
154
|
"type": "string",
|
|
162
155
|
"required": false
|
|
156
|
+
},
|
|
157
|
+
"visible": {
|
|
158
|
+
"type": "boolean",
|
|
159
|
+
"required": false
|
|
160
|
+
},
|
|
161
|
+
"required": {
|
|
162
|
+
"type": "boolean",
|
|
163
|
+
"required": false
|
|
163
164
|
}
|
|
164
165
|
}
|
|
166
|
+
},
|
|
167
|
+
"sortable": {
|
|
168
|
+
"type": "boolean",
|
|
169
|
+
"required": false
|
|
165
170
|
}
|
|
166
171
|
}
|
|
167
172
|
},
|
|
168
173
|
"header": {
|
|
169
174
|
"type": "object",
|
|
170
175
|
"required": false,
|
|
171
|
-
"rawType": "import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/dropdown/Dropdown\").DropdownHeaderType | undefined",
|
|
176
|
+
"rawType": "import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/overlays/dropdown/Dropdown\").DropdownHeaderType | undefined",
|
|
172
177
|
"properties": {
|
|
173
178
|
"type": {
|
|
174
179
|
"type": "string",
|
|
@@ -191,13 +196,12 @@
|
|
|
191
196
|
},
|
|
192
197
|
"opened": {
|
|
193
198
|
"type": "boolean",
|
|
194
|
-
"required": false
|
|
195
|
-
"default": false
|
|
199
|
+
"required": false
|
|
196
200
|
},
|
|
197
201
|
"trigger": {
|
|
198
202
|
"type": "object",
|
|
199
203
|
"required": true,
|
|
200
|
-
"rawType": "import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/dropdown/Dropdown\").AvatarTrigger | import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/dropdown/Dropdown\").ButtonTrigger | import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/dropdown/Dropdown\").IconTrigger | import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/dropdown/Dropdown\").CustomTrigger",
|
|
204
|
+
"rawType": "import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/overlays/dropdown/Dropdown\").AvatarTrigger | import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/overlays/dropdown/Dropdown\").ButtonTrigger | import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/overlays/dropdown/Dropdown\").IconTrigger | import(\"/Users/nhncommerce/Desktop/project/ncds/packages/ui-admin/src/components/overlays/dropdown/Dropdown\").CustomTrigger",
|
|
201
205
|
"properties": {
|
|
202
206
|
"type": {
|
|
203
207
|
"type": "string",
|
|
@@ -222,13 +226,23 @@
|
|
|
222
226
|
"required": false
|
|
223
227
|
}
|
|
224
228
|
}
|
|
229
|
+
},
|
|
230
|
+
"variant": {
|
|
231
|
+
"type": "enum",
|
|
232
|
+
"required": false,
|
|
233
|
+
"values": [
|
|
234
|
+
"action",
|
|
235
|
+
"config"
|
|
236
|
+
]
|
|
225
237
|
}
|
|
226
238
|
},
|
|
227
239
|
"html": {},
|
|
228
240
|
"bemClasses": [
|
|
229
241
|
"ncua-dropdown",
|
|
242
|
+
"ncua-dropdown-",
|
|
230
243
|
"ncua-dropdown--right",
|
|
231
244
|
"ncua-dropdown__avatar",
|
|
245
|
+
"ncua-dropdown__footer",
|
|
232
246
|
"ncua-dropdown__group",
|
|
233
247
|
"ncua-dropdown__header",
|
|
234
248
|
"ncua-dropdown__header-avatar-group",
|
|
@@ -236,12 +250,16 @@
|
|
|
236
250
|
"ncua-dropdown__header-text",
|
|
237
251
|
"ncua-dropdown__header-title",
|
|
238
252
|
"ncua-dropdown__item",
|
|
239
|
-
"ncua-dropdown__item
|
|
253
|
+
"ncua-dropdown__item--config",
|
|
254
|
+
"ncua-dropdown__item--drag-preview",
|
|
240
255
|
"ncua-dropdown__item-content",
|
|
256
|
+
"ncua-dropdown__item-drag-handle",
|
|
257
|
+
"ncua-dropdown__item-drop-indicator",
|
|
241
258
|
"ncua-dropdown__item-icon",
|
|
242
259
|
"ncua-dropdown__item-shortcut",
|
|
243
260
|
"ncua-dropdown__item-text",
|
|
244
261
|
"ncua-dropdown__item-text-group",
|
|
262
|
+
"ncua-dropdown__item-visibility",
|
|
245
263
|
"ncua-dropdown__menu",
|
|
246
264
|
"ncua-dropdown__menu-items",
|
|
247
265
|
"ncua-dropdown__trigger",
|
|
@@ -254,7 +272,9 @@
|
|
|
254
272
|
"react": {
|
|
255
273
|
"default": "<Dropdown groups=\"\" trigger=\"\" />",
|
|
256
274
|
"align:left": "<Dropdown align=\"left\" groups=\"\" trigger=\"\" />",
|
|
257
|
-
"align:right": "<Dropdown align=\"right\" groups=\"\" trigger=\"\" />"
|
|
275
|
+
"align:right": "<Dropdown align=\"right\" groups=\"\" trigger=\"\" />",
|
|
276
|
+
"variant:action": "<Dropdown variant=\"action\" groups=\"\" trigger=\"\" />",
|
|
277
|
+
"variant:config": "<Dropdown variant=\"config\" groups=\"\" trigger=\"\" />"
|
|
258
278
|
}
|
|
259
279
|
}
|
|
260
280
|
}
|