neo-register 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # neo-register
2
+ > neo 组件注册器(支持 react 和 vue2.0 技术栈);
3
+ - 提供注册 neo自定义组件 和 neo-editor自定义组件模型 的方法;
4
+ - 目前支持的技术栈:vue2.0、react。
5
+
6
+ ### 提供的方法
7
+ - registerNeoCmp: 根据 cmpType 注册 neo自定义组件
8
+ - registerNeoEditorModel: 注册 neo-editor 自定义组件模型
9
+
10
+ ## 快速使用
11
+
12
+ ```
13
+ npm install --save neo-register
14
+ ```
15
+
16
+ ## 注册 neo 自定义组件
17
+ ```tsx
18
+ import { registerNeoCmp } from 'neo-register';
19
+
20
+ class MyReactSelect extends React.PureComponent {
21
+ constructor() {
22
+ super();
23
+ this.handleChange = this.handleChange.bind(this);
24
+ }
25
+
26
+ handleChange(event) {
27
+ // 调用neo onToggle 方法,变更选择器表单项值
28
+ const {onToggle, options} = this.props;
29
+ const option = options.find(o => o.value === event.target.value);
30
+ if (onToggle) {
31
+ onToggle(option);
32
+ }
33
+ }
34
+
35
+ render() {
36
+ // 获取表单项 value 和 options 属性
37
+ const {label, options, title} = this.props;
38
+
39
+ return (
40
+ <div className="react-select">
41
+ <span>
42
+ {label}:
43
+ </span>
44
+ <select onChange={this.handleChange} title={title}>
45
+ {options.map(option => (
46
+ <option key={option.value} value={option.value}>
47
+ {option.label}
48
+ </option>
49
+ ))}
50
+ </select>
51
+ </div>
52
+ );
53
+ }
54
+ }
55
+
56
+ // 注册 neo 自定义组件
57
+ registerNeoCmp(MyReactSelect, 'react-select');
58
+
59
+ export default MyReactSelect;
60
+ ```
61
+
62
+ ## 注册 neo-editor 自定义组件模型
63
+ ```tsx
64
+ import { registerNeoEditorModel } from 'neo-register';
65
+
66
+ class ReactSelectPlugin {
67
+ cmpType = 'react-select'; // 自定义组件名称,用于标识组件的唯一性
68
+ label = 'select 自定义组件'; // 组件名称,用于设置在编辑器左侧组件面板中展示的名称
69
+ description = 'react-select 自定义组件'; // 组件描述,用于设置在编辑器左侧组件面板中展示的描述
70
+ tags = ['自定义组件']; // 自定义组件分类
71
+ iconSrc = 'https://neo-widgets.bj.bcebos.com/custom-widget.svg'; // 组件图标,用于设置在编辑器左侧组件面板中展示的图标
72
+ defaultComProps = { // 初次插入页面的默认属性数据
73
+ label: 'select 自定义组件',
74
+ name: 'customSelect',
75
+ options: [
76
+ {
77
+ label: 'A',
78
+ value: 'a'
79
+ },
80
+ {
81
+ label: 'B',
82
+ value: 'b'
83
+ },
84
+ {
85
+ label: 'C',
86
+ value: 'c'
87
+ }
88
+ ]
89
+ };
90
+ previewComProps = { // 设计器端预览时展示的默认数据
91
+ label: 'select 自定义组件',
92
+ options: [
93
+ {
94
+ label: 'A',
95
+ value: 'a'
96
+ },
97
+ {
98
+ label: 'B',
99
+ value: 'b'
100
+ },
101
+ {
102
+ label: 'C',
103
+ value: 'c'
104
+ }
105
+ ]
106
+ };
107
+ propsSchema = [ // 组件面板配置,用于生成编辑器右侧属性配置面板内容
108
+ {
109
+ type: 'text',
110
+ name: 'label',
111
+ label: 'label',
112
+ value: 'react-select'
113
+ },
114
+ {
115
+ type: 'textarea',
116
+ name: 'title',
117
+ label: 'hover title',
118
+ value: '点击下拉选择数值'
119
+ }
120
+ ];
121
+ }
122
+ // 注册一个 neo-editor 自定义组件模型(仅页面设计器需要,会在组件面板中展示)
123
+ registerNeoEditorModel(ReactSelectPlugin);
124
+
125
+ export default ReactSelectPlugin;
126
+ ```
127
+
128
+ ## 自定义组件配置项设置说明
129
+ - propsSchema 中可用的配置项类型 请见 [当前可用表单项](./docs/FormItemType.md)。
@@ -0,0 +1,39 @@
1
+ /**
2
+ * neo-editor 自定义组件模型配置项
3
+ */
4
+ export interface NeoRendererOption {
5
+ /**
6
+ * 渲染器名称
7
+ * 备注:渲染过程中用于查找对应的渲染器
8
+ */
9
+ cmpType: string;
10
+ /**
11
+ * 要注册的neo渲染器类型
12
+ * neo普通渲染器、neo表单渲染器、neo表单控件渲染器
13
+ * 备注:默认为neo普通渲染器
14
+ */
15
+ usage?: string;
16
+ /**
17
+ * 自定义组件权重
18
+ * 备注:值越低越优先命中
19
+ */
20
+ weight?: number;
21
+ /**
22
+ * 自定义组件技术栈类型
23
+ * 备注:默认为react
24
+ */
25
+ framework?: string;
26
+ }
27
+ /**
28
+ * registerNeoCmp: 根据type类型注册 neo 自定义组件
29
+ *【方法参数说明】
30
+ * newRenderer: 自定义组件,
31
+ * rendererOption: {
32
+ * cmpType: 自定义组件的type类型,比如:input、text-area、select-user等
33
+ * usage?: neo普通渲染器、neo表单渲染器,默认值为 neo普通渲染器
34
+ * weight?: 自定义组件权重
35
+ * framework?: 技术栈类型,默认为 react 技术栈,可选技术栈:vue2、react
36
+ * }
37
+ * 备注:暂不支持 vue3.0 技术栈
38
+ */
39
+ export declare function registerNeoCmp(newRenderer: any, rendererOption: string | NeoRendererOption): void;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * 自定义组件模型 配置项
3
+ */
4
+ export interface PluginOption {
5
+ /**
6
+ * 关联的渲染器
7
+ * 备注:可以关联当前的自定义组件,也可以关联平台预置组件和其他自定义组件
8
+ */
9
+ cmpType: string;
10
+ /**
11
+ * 自定义组件名称
12
+ * 在「页面设计器」物料面板中显示
13
+ */
14
+ label: string;
15
+ /**
16
+ * 自定义组件描述
17
+ * hover 自定义组件时展示
18
+ */
19
+ description?: string;
20
+ /**
21
+ * 自定义组件分类
22
+ * 指定当前自定义组件模型在「页面设计器」自定义组件面板中哪个分类下展示
23
+ */
24
+ tags: string | Array<string>;
25
+ /**
26
+ * 自定义组件icon
27
+ */
28
+ iconSrc?: string;
29
+ /**
30
+ * 自定义组件排序
31
+ * 指定当前自定义组件模型在「页面设计器」自定义组件面板中的展示次序
32
+ */
33
+ order?: number;
34
+ /**
35
+ * 自定义组件显隐
36
+ * 备注:设置为false时则不展示
37
+ */
38
+ exposedToDesigner?: boolean;
39
+ /**
40
+ * 初次插入页面的默认属性数据
41
+ */
42
+ defaultComProps?: boolean;
43
+ /**
44
+ * 组件面板配置,用于生成编辑器右侧属性配置面板内容
45
+ */
46
+ propsSchema?: boolean;
47
+ }
48
+ /**
49
+ * registerNeoEditorModel: 注册 neo-editor 自定义组件模型
50
+ */
51
+ export declare function registerNeoEditorModel(curEditorModel: any, cmpType?: string): void;
@@ -0,0 +1,424 @@
1
+ import React from 'react';
2
+ import Vue from 'vue';
3
+
4
+ // 方便取值的时候能够把上层的取到,但是获取的时候不会全部把所有的数据获取到。
5
+ function cloneObject(target, persistOwnProps = true) {
6
+ const obj = target && target.__super
7
+ ? Object.create(target.__super, {
8
+ __super: {
9
+ value: target.__super,
10
+ writable: false,
11
+ enumerable: false,
12
+ },
13
+ })
14
+ : Object.create(Object.prototype);
15
+ persistOwnProps &&
16
+ target &&
17
+ Object.keys(target).forEach((key) => (obj[key] = target[key]));
18
+ return obj;
19
+ }
20
+ function extendObject(target, src, persistOwnProps = true) {
21
+ const obj = cloneObject(target, persistOwnProps);
22
+ src && Object.keys(src).forEach((key) => (obj[key] = src[key]));
23
+ return obj;
24
+ }
25
+
26
+ const consoleTag = '[neo-register]'; // 输出标记
27
+ /**
28
+ * 获取技术栈标识
29
+ * 目的:兼容用户非标准写法
30
+ */
31
+ function getFramework(_framework) {
32
+ let defaultFramework = Framework.react;
33
+ if (!_framework) {
34
+ return defaultFramework;
35
+ }
36
+ let curFramework = _framework.toLowerCase().trim();
37
+ switch (curFramework) {
38
+ case 'jquery':
39
+ case 'jq':
40
+ curFramework = Framework.jquery;
41
+ break;
42
+ case 'vue2':
43
+ case 'vue 2':
44
+ case 'vue2.0':
45
+ case 'vue 2.0':
46
+ curFramework = Framework.vue2;
47
+ break;
48
+ case 'vue':
49
+ case 'vue3':
50
+ case 'vue 3':
51
+ case 'vue3.0':
52
+ case 'vue 3.0':
53
+ curFramework = Framework.vue3;
54
+ console.error(`${consoleTag} 暂不支持 vue3.0 技术栈。`);
55
+ break;
56
+ default:
57
+ curFramework = Framework.react;
58
+ }
59
+ return curFramework;
60
+ }
61
+ /**
62
+ * 识别自定义组件技术栈类型
63
+ * react 编译后是 一个函数组件
64
+ * vue 编译后是 一个类对象: { render: ƒ, __file: 'xx/xx.vue', __compiled: true, ... }
65
+ */
66
+ function getFrameworkByCmp(component) {
67
+ if (isVueComponent(component)) {
68
+ return 'vue2';
69
+ }
70
+ return 'react';
71
+ }
72
+ function isVueComponent(component) {
73
+ return (typeof component === 'object' &&
74
+ ((component._compiled && component.components) ||
75
+ (component.__file && component.__file.endsWith('.vue'))));
76
+ }
77
+ var Usage;
78
+ (function (Usage) {
79
+ Usage["renderer"] = "renderer";
80
+ Usage["formitem"] = "formitem";
81
+ })(Usage || (Usage = {}));
82
+ /**
83
+ * 获取neo渲染器类型标识
84
+ * 目的:兼容用户非标准写法
85
+ */
86
+ function getUsage(_usage) {
87
+ let defaultUsage = Usage.renderer;
88
+ if (!_usage) {
89
+ return defaultUsage;
90
+ }
91
+ let curUsage = _usage.toLowerCase().trim();
92
+ switch (curUsage) {
93
+ case 'renderer':
94
+ case 'renderers':
95
+ curUsage = Usage.renderer;
96
+ break;
97
+ case 'formitem':
98
+ case 'form-item':
99
+ case 'form item':
100
+ curUsage = Usage.formitem;
101
+ break;
102
+ default:
103
+ curUsage = Usage.renderer;
104
+ }
105
+ return curUsage;
106
+ }
107
+ /**
108
+ * 当前 neo-register 支持的技术栈
109
+ * 备注:vue2 和 vue3 不能同时存在
110
+ */
111
+ var Framework;
112
+ (function (Framework) {
113
+ Framework["react"] = "react";
114
+ Framework["vue2"] = "vue2";
115
+ Framework["vue3"] = "vue3";
116
+ Framework["jquery"] = "jquery";
117
+ })(Framework || (Framework = {}));
118
+ // 判断是否缺失 editor 自定义组件模型关键字段
119
+ function isEditorModel(EditorModelClass) {
120
+ let _isEditorModel = false;
121
+ if (!EditorModelClass) {
122
+ return false;
123
+ }
124
+ const _editorPluginObj = new EditorModelClass();
125
+ if (!_editorPluginObj.cmpType) {
126
+ console.error(`${consoleTag} / registerNeoEditorModel: 自定义组件注册失败,cmpType 不能为空。`);
127
+ }
128
+ else if (!_editorPluginObj.label) {
129
+ console.error(`${consoleTag} / registerNeoEditorModel: 自定义组件注册失败,名称(label)不能为空。`);
130
+ }
131
+ else if (!_editorPluginObj.tags) {
132
+ console.error(`${consoleTag} / registerNeoEditorModel: 自定义组件注册失败,组件分类(tags)不能为空。`);
133
+ }
134
+ else if (!Array.isArray(_editorPluginObj.tags)) {
135
+ console.error(`${consoleTag} / registerNeoEditorModel: 自定义组件注册失败,组件分类(tags)格式异常。`);
136
+ }
137
+ else {
138
+ // 1.设置一个默认 icon
139
+ if (!_editorPluginObj.icon) {
140
+ Object.assign(EditorModelClass.prototype, {
141
+ icon: 'https://neo-widgets.bj.bcebos.com/custom-widget.svg',
142
+ });
143
+ }
144
+ _isEditorModel = true;
145
+ }
146
+ return _isEditorModel;
147
+ }
148
+ // 判断是否是字符串类型
149
+ function isString(str) {
150
+ return Object.prototype.toString.call(str).slice(8, -1) === 'String';
151
+ }
152
+ function isProxy(obj) {
153
+ if (!obj) {
154
+ return false;
155
+ }
156
+ const hasMSTProperties = !!(obj.$treenode ||
157
+ obj.$mstObservable ||
158
+ obj.$modelType ||
159
+ obj.$modelId);
160
+ return (hasMSTProperties || Object.prototype.toString.call(obj) === '[object Proxy]');
161
+ }
162
+
163
+ /**
164
+ * registerNeoEditorModel: 注册 neo-editor 自定义组件模型
165
+ */
166
+ function registerNeoEditorModel(curEditorModel, cmpType) {
167
+ if (curEditorModel && isEditorModel(curEditorModel)) {
168
+ const curCmpType = cmpType || new curEditorModel().cmpType;
169
+ const curEditorModelObj = new curEditorModel();
170
+ Object.assign(curEditorModel.prototype, {
171
+ custom: true,
172
+ exposedToDesigner: curEditorModelObj.exposedToDesigner ?? true,
173
+ namespace: curEditorModelObj.namespace ?? 'neo-cmp-cli',
174
+ cmpType: curCmpType,
175
+ });
176
+ // registerEditorModel(curEditorModel); // 不直接注册为 neo-editor 插件
177
+ // 通过 postMessage 告知 neo-editor 注册一个新的插件
178
+ if (window && window.postMessage) {
179
+ const newComponentType = AddCustomEditorModel(curCmpType, curEditorModel);
180
+ if (newComponentType) {
181
+ console.info(`${consoleTag}触发注册自定义组件模型(${curCmpType})事件`);
182
+ window.postMessage({
183
+ type: 'neo-model-register-event',
184
+ eventMsg: `${consoleTag}注册一个 neo-editor 自定义组件模型`,
185
+ cmpType: curCmpType,
186
+ }, '*');
187
+ }
188
+ }
189
+ }
190
+ }
191
+ function AddCustomEditorModel(cmpType, model) {
192
+ if (window && !window.NEOEditorCustomModels) {
193
+ window.NEOEditorCustomModels = {};
194
+ }
195
+ if (!window.NEOEditorCustomModels[cmpType]) {
196
+ window.NEOEditorCustomModels[cmpType] = model;
197
+ return cmpType;
198
+ }
199
+ else {
200
+ console.error(`${consoleTag}注册自定义组件模型失败,已存在重名插件(${cmpType})。`);
201
+ }
202
+ return null;
203
+ }
204
+
205
+ /**
206
+ * 将 vue2.0 自定义组件包裹成一个 react组件
207
+ */
208
+ function createVue2Component(vueObj) {
209
+ if (!vueObj || (typeof vueObj !== 'function' && typeof vueObj !== 'object')) {
210
+ return;
211
+ }
212
+ class VueFactory extends React.Component {
213
+ domRef;
214
+ vm;
215
+ isUnmount;
216
+ // 指定 contextType 读取当前的 scope context。
217
+ // React 会往上找到最近的 scope Provider,然后使用它的值。
218
+ // static contextType = ScopedContext; // 待支持
219
+ constructor(props, context) {
220
+ super(props);
221
+ this.domRef = React.createRef();
222
+ this.isUnmount = false;
223
+ /*
224
+ // 待支持(自定义组件支持事件动作)
225
+ const scoped = context;
226
+ scoped.registerComponent(this);
227
+ */
228
+ this.resolveNeoProps = this.resolveNeoProps.bind(this);
229
+ }
230
+ componentDidMount() {
231
+ const { neoData, neoMSTData, neoFunc } = this.resolveNeoProps();
232
+ const { data, ...rest } = (vueObj =
233
+ typeof vueObj === 'function' ? new vueObj() : vueObj);
234
+ const vueData = typeof data === 'function' ? data() : data;
235
+ const curVueData = extendObject(vueData, neoData);
236
+ // 传入的Vue属性
237
+ this.vm = new Vue({
238
+ ...rest,
239
+ data: () => curVueData,
240
+ props: extendObject(neoFunc, {
241
+ ...(rest.props || {}),
242
+ ...neoMSTData,
243
+ }),
244
+ });
245
+ Object.keys(neoFunc).forEach((key) => {
246
+ this.vm.$props[key] = neoFunc[key];
247
+ });
248
+ if (this.domRef.current) {
249
+ this.domRef.current.appendChild(this.vm.$mount().$el);
250
+ }
251
+ }
252
+ componentDidUpdate() {
253
+ if (!this.isUnmount) {
254
+ const { neoData } = this.resolveNeoProps();
255
+ if (this.vm) {
256
+ Object.keys(neoData).forEach((key) => {
257
+ this.vm[key] = neoData[key];
258
+ });
259
+ this.vm.$forceUpdate();
260
+ }
261
+ }
262
+ }
263
+ componentWillUnmount() {
264
+ this.isUnmount = true;
265
+ /*
266
+ // 待支持
267
+ const scoped = this.context;
268
+ scoped.unRegisterComponent(this);
269
+ */
270
+ if (this.vm) {
271
+ this.vm.$destroy();
272
+ }
273
+ }
274
+ resolveNeoProps() {
275
+ let neoFunc = {};
276
+ let neoData = {};
277
+ let neoMSTData = {};
278
+ Object.keys(this.props).forEach((key) => {
279
+ const value = this.props[key];
280
+ if (typeof value === 'function') {
281
+ neoFunc[key] = value;
282
+ }
283
+ else if (isProxy(value)) {
284
+ neoMSTData[key] = value;
285
+ }
286
+ else {
287
+ neoData[key] = value;
288
+ }
289
+ });
290
+ return { neoData, neoMSTData, neoFunc };
291
+ }
292
+ /**
293
+ * reload动作处理
294
+ */
295
+ reload() {
296
+ if (this.vm && this.vm.reload) {
297
+ this.vm.reload();
298
+ }
299
+ else {
300
+ console.warn('自定义组件暂不支持reload动作。');
301
+ }
302
+ }
303
+ /**
304
+ * 事件动作处理:
305
+ * 在这里设置自定义组件对外暴露的动作,其他组件可以通过组件动作触发自定义组件的对应动作
306
+ */
307
+ doAction(action, args) {
308
+ if (this.vm && this.vm.doAction) {
309
+ this.vm.doAction(action, args);
310
+ }
311
+ else {
312
+ console.warn('自定义组件中不存在 doAction。');
313
+ }
314
+ }
315
+ render() {
316
+ return React.createElement("div", { ref: this.domRef });
317
+ }
318
+ }
319
+ return VueFactory;
320
+ }
321
+
322
+ /**
323
+ * registerNeoCmp: 根据type类型注册 neo 自定义组件
324
+ *【方法参数说明】
325
+ * newRenderer: 自定义组件,
326
+ * rendererOption: {
327
+ * cmpType: 自定义组件的type类型,比如:input、text-area、select-user等
328
+ * usage?: neo普通渲染器、neo表单渲染器,默认值为 neo普通渲染器
329
+ * weight?: 自定义组件权重
330
+ * framework?: 技术栈类型,默认为 react 技术栈,可选技术栈:vue2、react
331
+ * }
332
+ * 备注:暂不支持 vue3.0 技术栈
333
+ */
334
+ function registerNeoCmp(newRenderer, rendererOption) {
335
+ if (!newRenderer) {
336
+ return;
337
+ }
338
+ // 1.默认注册配置参数
339
+ const curRendererOption = {
340
+ cmpType: '',
341
+ usage: Usage.renderer,
342
+ weight: 0,
343
+ // framework: Framework.react, // 默认为 react 技术栈
344
+ };
345
+ // 2.获取相关配置参数
346
+ if (rendererOption && isString(rendererOption)) {
347
+ // rendererOption为字符串则将其设置为type
348
+ Object.assign(curRendererOption, {
349
+ cmpType: rendererOption,
350
+ });
351
+ }
352
+ else {
353
+ Object.assign(curRendererOption, rendererOption);
354
+ }
355
+ if (curRendererOption && !curRendererOption.cmpType) {
356
+ console.error(`${consoleTag} / registerNeoCmp: 自定义组件注册失败,cmpType 不能为空。`);
357
+ }
358
+ else {
359
+ // 根据组件结构自动识别组件技术栈
360
+ curRendererOption.framework = curRendererOption.framework
361
+ ? getFramework(curRendererOption.framework)
362
+ : getFrameworkByCmp(newRenderer);
363
+ // 修正usage数值
364
+ curRendererOption.usage = getUsage(curRendererOption.usage);
365
+ // 当前支持注册的渲染器类型
366
+ const registerMap = {
367
+ renderer: () => { },
368
+ formitem: () => { }, // FormItem
369
+ };
370
+ // 当前支持的技术栈类型
371
+ const resolverMap = {
372
+ react: (i) => i,
373
+ vue2: createVue2Component,
374
+ vue3: createVue2Component, // createVue3Component,
375
+ };
376
+ // 支持多技术栈
377
+ const curRendererComponent = resolverMap[curRendererOption.framework](newRenderer);
378
+ // 注册neo渲染器
379
+ if (!registerMap[curRendererOption.usage]) {
380
+ console.error(`${consoleTag} / registerNeoCmp: 自定义组件注册失败,暂不支持 ${curRendererOption.usage} 组件类型。`);
381
+ }
382
+ else {
383
+ // 通过 postMessage 告知 neo 注册一个新的渲染器
384
+ if (window && window.postMessage) {
385
+ const newComponentType = AddNeoCustomModel(curRendererOption.cmpType, {
386
+ cmpType: curRendererOption.cmpType,
387
+ weight: curRendererOption.weight,
388
+ usage: curRendererOption.usage,
389
+ framework: curRendererOption.framework,
390
+ component: curRendererComponent,
391
+ config: curRendererOption,
392
+ });
393
+ if (newComponentType) {
394
+ console.info(`${consoleTag}触发注册自定义组件(${newComponentType})事件`);
395
+ window.postMessage({
396
+ type: 'neo-cmp-register-event',
397
+ eventMsg: `${consoleTag}注册一个自定义组件`,
398
+ neoRenderer: {
399
+ cmpType: newComponentType,
400
+ weight: curRendererOption.weight,
401
+ usage: curRendererOption.usage,
402
+ config: curRendererOption,
403
+ },
404
+ }, '*');
405
+ }
406
+ }
407
+ }
408
+ }
409
+ }
410
+ function AddNeoCustomModel(componentType, rendererData) {
411
+ if (window && !window.NeoCustomCmps) {
412
+ window.NeoCustomCmps = {};
413
+ }
414
+ if (!window.NeoCustomCmps[componentType]) {
415
+ window.NeoCustomCmps[componentType] = rendererData;
416
+ return componentType;
417
+ }
418
+ else {
419
+ console.error(`${consoleTag} / registerNeoCmp: 自定义组件注册失败,已存在重名渲染器(${componentType})。`);
420
+ }
421
+ return null;
422
+ }
423
+
424
+ export { createVue2Component, registerNeoCmp, registerNeoEditorModel };
@@ -0,0 +1 @@
1
+ import e from"react";import o from"vue";function t(e,o,t=!0){const r=function(e,o=!0){const t=e&&e.__super?Object.create(e.__super,{__super:{value:e.__super,writable:!1,enumerable:!1}}):Object.create(Object.prototype);return o&&e&&Object.keys(e).forEach(o=>t[o]=e[o]),t}(e,t);return o&&Object.keys(o).forEach(e=>r[e]=o[e]),r}const r="[neo-register]";var s,n;function i(e,o){if(e&&function(e){let o=!1;if(!e)return!1;const t=new e;return t.cmpType?t.label?t.tags?Array.isArray(t.tags)?(t.icon||Object.assign(e.prototype,{icon:"https://neo-widgets.bj.bcebos.com/custom-widget.svg"}),o=!0):console.error(`${r} / registerNeoEditorModel: 自定义组件注册失败,组件分类(tags)格式异常。`):console.error(`${r} / registerNeoEditorModel: 自定义组件注册失败,组件分类(tags)不能为空。`):console.error(`${r} / registerNeoEditorModel: 自定义组件注册失败,名称(label)不能为空。`):console.error(`${r} / registerNeoEditorModel: 自定义组件注册失败,cmpType 不能为空。`),o}(e)){const t=o||(new e).cmpType,s=new e;if(Object.assign(e.prototype,{custom:!0,exposedToDesigner:s.exposedToDesigner??!0,namespace:s.namespace??"neo-cmp-cli",cmpType:t}),window&&window.postMessage){const o=function(e,o){window&&!window.NEOEditorCustomModels&&(window.NEOEditorCustomModels={});if(!window.NEOEditorCustomModels[e])return window.NEOEditorCustomModels[e]=o,e;console.error(`${r}注册自定义组件模型失败,已存在重名插件(${e})。`);return null}(t,e);o&&(console.info(`${r}触发注册自定义组件模型(${t})事件`),window.postMessage({type:"neo-model-register-event",eventMsg:`${r}注册一个 neo-editor 自定义组件模型`,cmpType:t},"*"))}}}function c(r){if(r&&("function"==typeof r||"object"==typeof r)){class s extends e.Component{domRef;vm;isUnmount;constructor(o,t){super(o),this.domRef=e.createRef(),this.isUnmount=!1,this.resolveNeoProps=this.resolveNeoProps.bind(this)}componentDidMount(){const{neoData:e,neoMSTData:s,neoFunc:n}=this.resolveNeoProps(),{data:i,...c}=r="function"==typeof r?new r:r,a=t("function"==typeof i?i():i,e);this.vm=new o({...c,data:()=>a,props:t(n,{...c.props||{},...s})}),Object.keys(n).forEach(e=>{this.vm.$props[e]=n[e]}),this.domRef.current&&this.domRef.current.appendChild(this.vm.$mount().$el)}componentDidUpdate(){if(!this.isUnmount){const{neoData:e}=this.resolveNeoProps();this.vm&&(Object.keys(e).forEach(o=>{this.vm[o]=e[o]}),this.vm.$forceUpdate())}}componentWillUnmount(){this.isUnmount=!0,this.vm&&this.vm.$destroy()}resolveNeoProps(){let e={},o={},t={};return Object.keys(this.props).forEach(r=>{const s=this.props[r];var n;"function"==typeof s?e[r]=s:(n=s)&&(n.$treenode||n.$mstObservable||n.$modelType||n.$modelId||"[object Proxy]"===Object.prototype.toString.call(n))?t[r]=s:o[r]=s}),{neoData:o,neoMSTData:t,neoFunc:e}}reload(){this.vm&&this.vm.reload?this.vm.reload():console.warn("自定义组件暂不支持reload动作。")}doAction(e,o){this.vm&&this.vm.doAction?this.vm.doAction(e,o):console.warn("自定义组件中不存在 doAction。")}render(){return e.createElement("div",{ref:this.domRef})}}return s}}function a(e,o){if(!e)return;const t={cmpType:"",usage:s.renderer,weight:0};var i;if(o&&(i=o,"String"===Object.prototype.toString.call(i).slice(8,-1))?Object.assign(t,{cmpType:o}):Object.assign(t,o),t&&!t.cmpType)console.error(`${r} / registerNeoCmp: 自定义组件注册失败,cmpType 不能为空。`);else{t.framework=t.framework?function(e){let o=n.react;if(!e)return o;let t=e.toLowerCase().trim();switch(t){case"jquery":case"jq":t=n.jquery;break;case"vue2":case"vue 2":case"vue2.0":case"vue 2.0":t=n.vue2;break;case"vue":case"vue3":case"vue 3":case"vue3.0":case"vue 3.0":t=n.vue3,console.error(`${r} 暂不支持 vue3.0 技术栈。`);break;default:t=n.react}return t}(t.framework):function(e){return"object"==typeof e&&(e._compiled&&e.components||e.__file&&e.__file.endsWith(".vue"))}(e)?"vue2":"react",t.usage=function(e){let o=s.renderer;if(!e)return o;let t=e.toLowerCase().trim();switch(t){case"renderer":case"renderers":default:t=s.renderer;break;case"formitem":case"form-item":case"form item":t=s.formitem}return t}(t.usage);const o={renderer:()=>{},formitem:()=>{}},i={react:e=>e,vue2:c,vue3:c}[t.framework](e);if(o[t.usage]){if(window&&window.postMessage){const e=function(e,o){window&&!window.NeoCustomCmps&&(window.NeoCustomCmps={});if(!window.NeoCustomCmps[e])return window.NeoCustomCmps[e]=o,e;console.error(`${r} / registerNeoCmp: 自定义组件注册失败,已存在重名渲染器(${e})。`);return null}(t.cmpType,{cmpType:t.cmpType,weight:t.weight,usage:t.usage,framework:t.framework,component:i,config:t});e&&(console.info(`${r}触发注册自定义组件(${e})事件`),window.postMessage({type:"neo-cmp-register-event",eventMsg:`${r}注册一个自定义组件`,neoRenderer:{cmpType:e,weight:t.weight,usage:t.usage,config:t}},"*"))}}else console.error(`${r} / registerNeoCmp: 自定义组件注册失败,暂不支持 ${t.usage} 组件类型。`)}}!function(e){e.renderer="renderer",e.formitem="formitem"}(s||(s={})),function(e){e.react="react",e.vue2="vue2",e.vue3="vue3",e.jquery="jquery"}(n||(n={}));export{c as createVue2Component,a as registerNeoCmp,i as registerNeoEditorModel};
@@ -0,0 +1,2 @@
1
+ /*! For license information please see index.umd.js.LICENSE.txt */
2
+ !function(e,o){"object"==typeof exports&&"object"==typeof module?module.exports=o():"function"==typeof define&&define.amd?define([],o):"object"==typeof exports?exports.neoRegister=o():e.neoRegister=o()}(this,function(){return function(){"use strict";var e={n:function(o){var r=o&&o.__esModule?function(){return o.default}:function(){return o};return e.d(r,{a:r}),r},d:function(o,r){for(var t in r)e.o(r,t)&&!e.o(o,t)&&Object.defineProperty(o,t,{enumerable:!0,get:r[t]})},o:function(e,o){return Object.prototype.hasOwnProperty.call(e,o)},r:function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},o={};e.r(o),e.d(o,{createVue2Component:function(){return y},registerNeoCmp:function(){return b},registerNeoEditorModel:function(){return u}});var r=require("@babel/runtime/helpers/extends"),t=e.n(r);function n(e,o,r){void 0===r&&(r=!0);var t=function(e,o){void 0===o&&(o=!0);var r=e&&e.__super?Object.create(e.__super,{__super:{value:e.__super,writable:!1,enumerable:!1}}):Object.create(Object.prototype);return o&&e&&Object.keys(e).forEach(function(o){return r[o]=e[o]}),r}(e,r);return o&&Object.keys(o).forEach(function(e){return t[e]=o[e]}),t}var i,s,c="[neo-register]";function u(e,o){if(e&&function(e){var o=!1;if(!e)return!1;var r=new e;return r.cmpType?r.label?r.tags?Array.isArray(r.tags)?(r.icon||Object.assign(e.prototype,{icon:"https://neo-widgets.bj.bcebos.com/custom-widget.svg"}),o=!0):console.error(c+" / registerNeoEditorModel: 自定义组件注册失败,组件分类(tags)格式异常。"):console.error(c+" / registerNeoEditorModel: 自定义组件注册失败,组件分类(tags)不能为空。"):console.error(c+" / registerNeoEditorModel: 自定义组件注册失败,名称(label)不能为空。"):console.error(c+" / registerNeoEditorModel: 自定义组件注册失败,cmpType 不能为空。"),o}(e)){var r,t,n=o||(new e).cmpType,i=new e;if(Object.assign(e.prototype,{custom:!0,exposedToDesigner:null==(r=i.exposedToDesigner)||r,namespace:null!=(t=i.namespace)?t:"neo-cmp-cli",cmpType:n}),window&&window.postMessage){var s=function(e,o){return window&&!window.NEOEditorCustomModels&&(window.NEOEditorCustomModels={}),window.NEOEditorCustomModels[e]?(console.error(c+"注册自定义组件模型失败,已存在重名插件("+e+")。"),null):(window.NEOEditorCustomModels[e]=o,e)}(n,e);s&&(console.info(c+"触发注册自定义组件模型("+n+")事件"),window.postMessage({type:"neo-model-register-event",eventMsg:c+"注册一个 neo-editor 自定义组件模型",cmpType:n},"*"))}}}!function(e){e.renderer="renderer",e.formitem="formitem"}(i||(i={})),function(e){e.react="react",e.vue2="vue2",e.vue3="vue3",e.jquery="jquery"}(s||(s={}));var a=require("@babel/runtime/helpers/objectWithoutPropertiesLoose"),p=e.n(a),f=require("@babel/runtime/helpers/inheritsLoose"),m=e.n(f),d=require("react"),l=e.n(d),v=require("vue"),w=e.n(v),g=["data"];function y(e){if(e&&("function"==typeof e||"object"==typeof e))return function(o){function r(e,r){var t;return(t=o.call(this,e)||this).domRef=void 0,t.vm=void 0,t.isUnmount=void 0,t.domRef=l().createRef(),t.isUnmount=!1,t.resolveNeoProps=t.resolveNeoProps.bind(t),t}m()(r,o);var i=r.prototype;return i.componentDidMount=function(){var o=this,r=this.resolveNeoProps(),i=r.neoData,s=r.neoMSTData,c=r.neoFunc,u=e="function"==typeof e?new e:e,a=u.data,f=p()(u,g),m=n("function"==typeof a?a():a,i);this.vm=new(w())(t()({},f,{data:function(){return m},props:n(c,t()({},f.props||{},s))})),Object.keys(c).forEach(function(e){o.vm.$props[e]=c[e]}),this.domRef.current&&this.domRef.current.appendChild(this.vm.$mount().$el)},i.componentDidUpdate=function(){var e=this;if(!this.isUnmount){var o=this.resolveNeoProps().neoData;this.vm&&(Object.keys(o).forEach(function(r){e.vm[r]=o[r]}),this.vm.$forceUpdate())}},i.componentWillUnmount=function(){this.isUnmount=!0,this.vm&&this.vm.$destroy()},i.resolveNeoProps=function(){var e=this,o={},r={},t={};return Object.keys(this.props).forEach(function(n){var i,s=e.props[n];"function"==typeof s?o[n]=s:(i=s)&&(i.$treenode||i.$mstObservable||i.$modelType||i.$modelId||"[object Proxy]"===Object.prototype.toString.call(i))?t[n]=s:r[n]=s}),{neoData:r,neoMSTData:t,neoFunc:o}},i.reload=function(){this.vm&&this.vm.reload?this.vm.reload():console.warn("自定义组件暂不支持reload动作。")},i.doAction=function(e,o){this.vm&&this.vm.doAction?this.vm.doAction(e,o):console.warn("自定义组件中不存在 doAction。")},i.render=function(){return l().createElement("div",{ref:this.domRef})},r}(l().Component)}function b(e,o){if(e){var r,t={cmpType:"",usage:i.renderer,weight:0};if(o&&(r=o,"String"===Object.prototype.toString.call(r).slice(8,-1))?Object.assign(t,{cmpType:o}):Object.assign(t,o),t&&!t.cmpType)console.error(c+" / registerNeoCmp: 自定义组件注册失败,cmpType 不能为空。");else{t.framework=t.framework?function(e){var o=s.react;if(!e)return o;var r=e.toLowerCase().trim();switch(r){case"jquery":case"jq":r=s.jquery;break;case"vue2":case"vue 2":case"vue2.0":case"vue 2.0":r=s.vue2;break;case"vue":case"vue3":case"vue 3":case"vue3.0":case"vue 3.0":r=s.vue3,console.error(c+" 暂不支持 vue3.0 技术栈。");break;default:r=s.react}return r}(t.framework):"object"==typeof(f=e)&&(f._compiled&&f.components||f.__file&&f.__file.endsWith(".vue"))?"vue2":"react",t.usage=function(e){var o=i.renderer;if(!e)return o;var r=e.toLowerCase().trim();switch(r){case"renderer":case"renderers":default:r=i.renderer;break;case"formitem":case"form-item":case"form item":r=i.formitem}return r}(t.usage);var n={react:function(e){return e},vue2:y,vue3:y}[t.framework](e);if({renderer:function(){},formitem:function(){}}[t.usage]){if(window&&window.postMessage){var u=(a=t.cmpType,p={cmpType:t.cmpType,weight:t.weight,usage:t.usage,framework:t.framework,component:n,config:t},window&&!window.NeoCustomCmps&&(window.NeoCustomCmps={}),window.NeoCustomCmps[a]?(console.error(c+" / registerNeoCmp: 自定义组件注册失败,已存在重名渲染器("+a+")。"),null):(window.NeoCustomCmps[a]=p,a));u&&(console.info(c+"触发注册自定义组件("+u+")事件"),window.postMessage({type:"neo-cmp-register-event",eventMsg:c+"注册一个自定义组件",neoRenderer:{cmpType:u,weight:t.weight,usage:t.usage,config:t}},"*"))}}else console.error(c+" / registerNeoCmp: 自定义组件注册失败,暂不支持 "+t.usage+" 组件类型。")}}var a,p,f}return o}()});
@@ -0,0 +1,7 @@
1
+ /*!
2
+ * neo-register v1.0.0
3
+ * author: wibetter
4
+ * build tool: AKFun
5
+ * build time: Wed Sep 10 2025 13:41:28 GMT+0800 (中国标准时间)
6
+ * build tool info: https://github.com/wibetter/akfun
7
+ */
package/dist/main.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * neo-register: 组件注册器
3
+ *
4
+ * 【提供的工具方法清单】
5
+ * registerNeoCmp: 根据 cmpType 注册 neo 自定义组件
6
+ * registerNeoEditorModel: 注册 neo-editor 自定义组件模型
7
+ */
8
+ export { registerNeoEditorModel } from './function/registerNeoEditorModel';
9
+ export { registerNeoCmp } from './function/registerNeoCmp';
10
+ export { createVue2Component } from './frameworkFactory/vueFactory';
@@ -0,0 +1,38 @@
1
+ export declare const consoleTag = "[neo-register]";
2
+ export * from './object';
3
+ /**
4
+ * 获取技术栈标识
5
+ * 目的:兼容用户非标准写法
6
+ */
7
+ export declare function getFramework(_framework?: string): string;
8
+ /**
9
+ * 识别自定义组件技术栈类型
10
+ * react 编译后是 一个函数组件
11
+ * vue 编译后是 一个类对象: { render: ƒ, __file: 'xx/xx.vue', __compiled: true, ... }
12
+ */
13
+ export declare function getFrameworkByCmp(component: any): string;
14
+ export declare function isReactComponent(component: any): boolean;
15
+ export declare function isVueComponent(component: any): boolean;
16
+ export declare enum Usage {
17
+ renderer = "renderer",
18
+ formitem = "formitem"
19
+ }
20
+ /**
21
+ * 获取neo渲染器类型标识
22
+ * 目的:兼容用户非标准写法
23
+ */
24
+ export declare function getUsage(_usage?: string): string;
25
+ /**
26
+ * 当前 neo-register 支持的技术栈
27
+ * 备注:vue2 和 vue3 不能同时存在
28
+ */
29
+ export declare enum Framework {
30
+ react = "react",
31
+ vue2 = "vue2",
32
+ vue3 = "vue3",
33
+ jquery = "jquery"
34
+ }
35
+ export declare function isEditorModel(EditorModelClass: any): boolean;
36
+ export declare function isString(str: any): boolean;
37
+ export declare function isObject(obj: any): boolean;
38
+ export declare function isProxy(obj: any): boolean;
@@ -0,0 +1,8 @@
1
+ export declare function createObject(superProps?: {
2
+ [propName: string]: any;
3
+ }, props?: {
4
+ [propName: string]: any;
5
+ }, properties?: any): object;
6
+ export declare function cloneObject(target: any, persistOwnProps?: boolean): any;
7
+ export declare function extendObject(target: any, src?: any, persistOwnProps?: boolean): any;
8
+ export declare function isObject(obj: any): any;
@@ -0,0 +1,159 @@
1
+ ## 可作为自定义配置项的表单项组件
2
+
3
+ ### 1. 基础输入类
4
+
5
+ #### 文本输入
6
+ - **text** - 文本输入框
7
+ - **password** - 密码输入框
8
+ - **email** - 邮箱输入框
9
+ - **url** - URL输入框
10
+ - **native-date** - 原生日期输入
11
+ - **native-time** - 原生时间输入
12
+ - **native-number** - 原生数字输入
13
+
14
+ #### 多行文本
15
+ - **textarea** - 多行文本输入框
16
+
17
+ #### 数字输入
18
+ - **number** - 数字输入框
19
+
20
+ #### 日期时间
21
+ - **date** - 日期选择器
22
+ - **datetime** - 日期时间选择器
23
+ - **time** - 时间选择器
24
+ - **month** - 月份选择器
25
+ - **quarter** - 季度选择器
26
+ - **year** - 年份选择器
27
+ - **date-range** - 日期范围选择器
28
+ - **datetime-range** - 日期时间范围选择器
29
+
30
+ ### 2. 选择类
31
+
32
+ #### 单选/多选
33
+ - **select** - 下拉选择框
34
+ - **multi-select** - 多选下拉框
35
+ - **radios** - 单选框组
36
+ - **checkboxes** - 复选框组
37
+ - **checkbox** - 单个复选框
38
+
39
+ #### 树形选择
40
+ - **tree-select** - 树形选择器
41
+ - **nested-select** - 嵌套选择器
42
+
43
+ #### 级联选择
44
+ - **chained-select** - 级联选择器
45
+
46
+ #### 穿梭框
47
+ - **transfer** - 穿梭框组件
48
+
49
+ #### 其他选择
50
+ - **picker** - 选择器
51
+ - **tabs-transfer** - 标签页穿梭框
52
+
53
+ ### 3. 特殊输入类
54
+
55
+ #### 开关
56
+ - **switch** - 开关组件
57
+
58
+ #### 滑块
59
+ - **range** - 范围滑块
60
+
61
+ #### 评分
62
+ - **rating** - 评分组件(待完善)
63
+
64
+ #### 颜色
65
+ - **color** - 颜色选择器
66
+
67
+ #### 图标
68
+ - **icon-picker** - 图标选择器
69
+
70
+ #### 城市
71
+ - **city** - 城市选择器
72
+
73
+ #### 位置
74
+ - **location** - 位置选择器
75
+
76
+ ### 4. 文件上传类
77
+
78
+ #### 文件上传
79
+ - **file** - 文件上传组件
80
+
81
+ #### 图片上传
82
+ - **image** - 图片上传组件
83
+
84
+ ### 5. 富文本编辑类
85
+
86
+ #### 编辑器
87
+ - **js-editor** - JavaScript 编辑器
88
+ - **ts-editor** - TypeScript 编辑器
89
+ - **rich-text** - 富文本编辑器
90
+ - **editor** - 通用编辑器
91
+ - **diff-editor** - 差异编辑器
92
+
93
+ ### 6. 布局容器类
94
+
95
+ #### 容器
96
+ - **container** - 容器组件
97
+ - **hbox** - 水平盒子布局
98
+ - **grid** - 网格布局
99
+
100
+ #### 分组
101
+ - **field-set** - 字段集
102
+ - **group** - 分组组件
103
+
104
+ #### 标签页
105
+ - **tabs** - 标签页组件
106
+
107
+ ### 7. 复合组件类
108
+
109
+ #### 组合
110
+ - **combo** - 组合组件
111
+ - **array** - 数组组件
112
+ - **repeat** - 重复组件
113
+
114
+ #### 子表单
115
+ - **form** - 子表单
116
+
117
+ #### 表格
118
+ - **table** - 表格组件
119
+
120
+ ### 8. 特殊功能类
121
+
122
+ #### 隐藏字段
123
+ - **hidden** - 隐藏字段
124
+
125
+ #### 静态显示
126
+ - **static** - 静态文本显示
127
+
128
+ #### 按钮
129
+ - **button** - 按钮组件
130
+ - **submit** - 提交按钮
131
+ - **reset** - 重置按钮
132
+ - **button-toolbar** - 按钮工具栏
133
+
134
+ #### 输入组合
135
+ - **input-group** - 输入组合组件
136
+
137
+ #### 服务
138
+ - **service** - 服务组件
139
+
140
+ #### 公式
141
+ - **formula** - 公式组件
142
+
143
+ #### 条件构建器
144
+ - **condition-builder** - 条件构建器
145
+
146
+ #### 矩阵
147
+ - **matrix** - 矩阵组件
148
+
149
+ #### UUID
150
+ - **uuid** - UUID 生成器
151
+
152
+ #### 月份范围
153
+ - **month-range** - 月份范围选择器
154
+
155
+
156
+ ## 使用说明
157
+
158
+ - 以上表单项为 amis 表单项(基于amis 1.1.5私有化版本)
159
+ - 相关表单项使用说明请见 [amis 使用文档](https://aisuda.bce.baidu.com/amis/zh-CN/components/form/index)
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "neo-register",
3
+ "version": "1.0.0",
4
+ "description": "neo自定义组件注册器(支持 react 和 vue2.0 技术栈),主要用于注册 neo 自定义组件、neo-editor 自定义组件模型。",
5
+ "keywords": [
6
+ "neo自定义组件注册器",
7
+ "neo自定义组件",
8
+ "neo-editor自定义组件模型"
9
+ ],
10
+ "author": "wibetter",
11
+ "license": "MIT",
12
+ "main": "dist/index.umd.js",
13
+ "module": "dist/index.esm.js",
14
+ "scripts": {
15
+ "linkDebug": "neo linkDebug",
16
+ "build2lib": "neo build2lib",
17
+ "build2esm": "neo build2esm",
18
+ "format": "prettier --write \"src/**/**/*.{js,jsx,ts,tsx,vue,scss,json}\""
19
+ },
20
+ "files": [
21
+ "dist/*",
22
+ "docs/*"
23
+ ],
24
+ "husky": {
25
+ "hooks": {
26
+ "pre-commit": "lint-staged",
27
+ "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
28
+ }
29
+ },
30
+ "lint-staged": {
31
+ "src/**/**/*.{js,jsx,ts,tsx,vue,scss,json}": [
32
+ "prettier --write"
33
+ ]
34
+ },
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://git@github.com:wibetter/neo-register.git"
38
+ },
39
+ "bugs": {
40
+ "url": "https://github.com/wibetter/neo-register/issues"
41
+ },
42
+ "dependencies": {
43
+ "vue": "^2.6.14"
44
+ },
45
+ "devDependencies": {
46
+ "@commitlint/cli": "^8.3.5",
47
+ "@commitlint/config-conventional": "^9.1.1",
48
+ "@types/react": "^16.14.66",
49
+ "@types/react-dom": "^16.9.25",
50
+ "@types/vue": "^1.0.31",
51
+ "husky": "^4.2.5",
52
+ "lint-staged": "^10.2.9",
53
+ "neo-cmp-cli": "^1.0.0",
54
+ "prettier": "^2.0.5",
55
+ "react": "^16.9.0",
56
+ "react-dom": "^16.9.0"
57
+ },
58
+ "engines": {
59
+ "node": ">= 10.13.0",
60
+ "npm": ">= 6.4.1"
61
+ }
62
+ }