@nbreak/shared 0.1.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/LICENSE +34 -0
- package/README.md +3 -0
- package/dist/cjs/index.cjs +554 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/esm/index.js +522 -0
- package/dist/esm/index.js.map +1 -0
- package/package.json +26 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Data Screen License
|
|
2
|
+
===================
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 NBreak. All rights reserved.
|
|
5
|
+
|
|
6
|
+
本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。
|
|
7
|
+
This work is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License.
|
|
8
|
+
|
|
9
|
+
您可以自由地:
|
|
10
|
+
------------------
|
|
11
|
+
* **分享** — 在任何媒介以任何形式复制、发行本作品
|
|
12
|
+
* **演绎** — 修改、转换或以本作品为基础进行创作
|
|
13
|
+
|
|
14
|
+
惟须遵守下列条件:
|
|
15
|
+
------------------
|
|
16
|
+
* **署名** — 您必须给出适当的署名,提供指向本许可协议的链接,同时标明是否(对原始作品)作了修改。您可以用任何合理的方式来署名,但是不得以任何方式暗示许可人为您或您的使用背书。
|
|
17
|
+
* **非商业性使用** — 您不得将本作品用于商业目的。
|
|
18
|
+
|
|
19
|
+
**商业使用需获得商业授权。** 请参阅项目根目录下的 LICENSE-COMMERCIAL 文件了解商业授权详情。
|
|
20
|
+
|
|
21
|
+
没有附加限制 — 您不得适用法律限制或技术措施从而限制他人做本许可协议允许的事情。
|
|
22
|
+
|
|
23
|
+
完整协议文本请访问:
|
|
24
|
+
https://creativecommons.org/licenses/by-nc/4.0/legalcode
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
29
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
30
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
31
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
32
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
33
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
34
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/constants.js
|
|
3
|
+
/**
|
|
4
|
+
* @nbreak/shared - 常量定义
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* 扩展物类型枚举
|
|
8
|
+
* 对标竞品:
|
|
9
|
+
* - DataV: 主题/组件/数据源三类
|
|
10
|
+
* - Superset: 仅可视化插件
|
|
11
|
+
* - FineReport: 图表/函数/数据源/模板
|
|
12
|
+
* - Tableau: Extensions API(Dashboard 组件/连接器/数据驱动型操作)
|
|
13
|
+
* 本方案聚合为 6 类,覆盖全部竞品场景
|
|
14
|
+
*/
|
|
15
|
+
var EXTENSION_TYPES = {
|
|
16
|
+
COMPONENT: "component",
|
|
17
|
+
THEME: "theme",
|
|
18
|
+
DATASOURCE: "datasource",
|
|
19
|
+
TEMPLATE: "template",
|
|
20
|
+
ACTION: "action",
|
|
21
|
+
PROPERTY_FIELD: "property-field"
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* 扩展物类型列表(便于遍历)
|
|
25
|
+
*/
|
|
26
|
+
var ALL_EXTENSION_TYPES = Object.values(EXTENSION_TYPES);
|
|
27
|
+
/**
|
|
28
|
+
* 属性字段类型枚举(内置)
|
|
29
|
+
* 第三方可通过 property-field 扩展注册新类型
|
|
30
|
+
*/
|
|
31
|
+
var PROPERTY_FIELD_TYPES = {
|
|
32
|
+
TEXT: "text",
|
|
33
|
+
NUMBER: "number",
|
|
34
|
+
COLOR: "color",
|
|
35
|
+
SELECT: "select",
|
|
36
|
+
SWITCH: "switch",
|
|
37
|
+
SLIDER: "slider",
|
|
38
|
+
JSON: "json",
|
|
39
|
+
CODE: "code",
|
|
40
|
+
GRADIENT: "gradient",
|
|
41
|
+
IMAGE: "image",
|
|
42
|
+
DATE: "date",
|
|
43
|
+
RADIO: "radio",
|
|
44
|
+
CHECKBOX: "checkbox",
|
|
45
|
+
TEXTAREA: "textarea"
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* 内置属性字段类型列表
|
|
49
|
+
*/
|
|
50
|
+
var BUILTIN_PROPERTY_FIELD_TYPES = Object.values(PROPERTY_FIELD_TYPES);
|
|
51
|
+
/**
|
|
52
|
+
* 组件分类(与现有 componentLibrary.js 对齐)
|
|
53
|
+
*/
|
|
54
|
+
var COMPONENT_CATEGORIES = {
|
|
55
|
+
CHARTS: "charts",
|
|
56
|
+
CONTROLS: "controls",
|
|
57
|
+
DECORATIONS: "decorations",
|
|
58
|
+
TITLES: "titles",
|
|
59
|
+
TABLES: "tables",
|
|
60
|
+
LISTS: "lists",
|
|
61
|
+
TIME: "time",
|
|
62
|
+
MEDIA: "media",
|
|
63
|
+
CONTAINERS: "containers",
|
|
64
|
+
BORDERS: "borders",
|
|
65
|
+
WEATHER: "weather",
|
|
66
|
+
DATASOURCE: "datasource",
|
|
67
|
+
FORMS: "forms",
|
|
68
|
+
CONFIG: "config",
|
|
69
|
+
OTHER: "other"
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* 预定义钩子名称(与现有 pluginSystem.js HOOKS 对齐并扩展)
|
|
73
|
+
*/
|
|
74
|
+
var HOOK_NAMES = {
|
|
75
|
+
BEFORE_RENDER: "beforeRender",
|
|
76
|
+
AFTER_RENDER: "afterRender",
|
|
77
|
+
BEFORE_EXPORT: "beforeExport",
|
|
78
|
+
AFTER_EXPORT: "afterExport",
|
|
79
|
+
COMPONENT_REGISTER: "componentRegister",
|
|
80
|
+
DATA_SOURCE_REGISTER: "dataSourceRegister",
|
|
81
|
+
THEME_APPLY: "themeApply",
|
|
82
|
+
CHART_OPTIONS_MERGE: "chartOptionsMerge",
|
|
83
|
+
ANIMATION_CONFIG: "animationConfig",
|
|
84
|
+
BEFORE_EXTENSION_REGISTER: "beforeExtensionRegister",
|
|
85
|
+
AFTER_EXTENSION_REGISTER: "afterExtensionRegister",
|
|
86
|
+
BEFORE_EXTENSION_UNREGISTER: "beforeExtensionUnregister",
|
|
87
|
+
SCHEMA_RESOLVE: "schemaResolve",
|
|
88
|
+
PROPERTY_FIELD_RENDER: "propertyFieldRender"
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* 加载策略枚举
|
|
92
|
+
*/
|
|
93
|
+
var LOAD_STRATEGIES = {
|
|
94
|
+
STATIC: "static",
|
|
95
|
+
FEDERATION: "federation",
|
|
96
|
+
UMD: "umd"
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* 扩展状态
|
|
100
|
+
*/
|
|
101
|
+
var EXTENSION_STATUS = {
|
|
102
|
+
REGISTERED: "registered",
|
|
103
|
+
ENABLED: "enabled",
|
|
104
|
+
DISABLED: "disabled",
|
|
105
|
+
ERROR: "error",
|
|
106
|
+
LOADING: "loading"
|
|
107
|
+
};
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/schema.js
|
|
110
|
+
/**
|
|
111
|
+
* @nbreak/shared - Schema 规范与类型定义
|
|
112
|
+
*
|
|
113
|
+
* 统一现有三套字段定义:
|
|
114
|
+
* - src/data/componentSchemas.js(Schema 驱动)
|
|
115
|
+
* - src/components/panels/ComponentConfigPanel.vue(手写模板)
|
|
116
|
+
* - src/components/panels/ChartConfigPanel.vue(图表专属)
|
|
117
|
+
*
|
|
118
|
+
* 对标竞品:
|
|
119
|
+
* - DataV:每个组件支持样式/数据/交互三级配置面板
|
|
120
|
+
* - Power BI:capabilities.json 声明式字段
|
|
121
|
+
* - FineReport:条件格式 + 联动参数
|
|
122
|
+
*/
|
|
123
|
+
/**
|
|
124
|
+
* 属性字段描述符
|
|
125
|
+
* @typedef {Object} PropertyFieldSchema
|
|
126
|
+
* @property {string} key - 属性路径,支持点号(如 'style.color')
|
|
127
|
+
* @property {string} label - 显示标签
|
|
128
|
+
* @property {string} type - 字段类型(内置 PROPERTY_FIELD_TYPES 或扩展自定义类型)
|
|
129
|
+
* @property {string} [group] - 配置分组(如 '样式'/'数据'/'交互')
|
|
130
|
+
* @property {*} [default] - 默认值
|
|
131
|
+
* @property {number} [min] - 最小值(number/slider 用)
|
|
132
|
+
* @property {number} [max] - 最大值
|
|
133
|
+
* @property {number} [step] - 步长
|
|
134
|
+
* @property {Array<{label:string,value:*}>} [options] - 选项(select/radio 用)
|
|
135
|
+
* @property {function|boolean} [visible] - 条件显示,函数接收 (props, context) 返回 boolean
|
|
136
|
+
* @property {function} [validator] - 校验函数,返回 true 或错误信息字符串
|
|
137
|
+
* @property {function} [transform] - 输入转换函数,对值做加工后返回
|
|
138
|
+
* @property {string} [description] - 描述文本
|
|
139
|
+
* @property {string} [placeholder] - 占位符
|
|
140
|
+
* @property {boolean} [required] - 是否必填
|
|
141
|
+
* @property {Object} [props] - 透传给编辑器组件的额外 props
|
|
142
|
+
* @property {Array<PropertyFieldSchema>} [children] - 子字段(用于嵌套对象/数组)
|
|
143
|
+
*/
|
|
144
|
+
/**
|
|
145
|
+
* 创建属性字段描述符
|
|
146
|
+
* @param {PropertyFieldSchema} schema
|
|
147
|
+
* @returns {PropertyFieldSchema}
|
|
148
|
+
*/
|
|
149
|
+
function definePropertyField(schema) {
|
|
150
|
+
if (!schema || !schema.key) throw new Error("[DataScreen] 属性字段描述符必须包含 key 字段");
|
|
151
|
+
return {
|
|
152
|
+
type: "text",
|
|
153
|
+
group: "基础",
|
|
154
|
+
...schema
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* 创建属性字段组
|
|
159
|
+
* @param {string} name - 组名
|
|
160
|
+
* @param {Array<PropertyFieldSchema>} fields
|
|
161
|
+
* @returns {{name: string, fields: Array}}
|
|
162
|
+
*/
|
|
163
|
+
function definePropertyGroup(name, fields) {
|
|
164
|
+
return {
|
|
165
|
+
name,
|
|
166
|
+
fields: fields || []
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* 组件 Schema(描述一个组件的全部可配置项)
|
|
171
|
+
* @typedef {Object} ComponentSchema
|
|
172
|
+
* @property {string} type - 组件类型
|
|
173
|
+
* @property {string} name - 显示名称
|
|
174
|
+
* @property {string} category - 分类
|
|
175
|
+
* @property {Array<PropertyFieldSchema>} properties - 属性字段数组
|
|
176
|
+
* @property {Object} defaults - 默认值对象
|
|
177
|
+
* @property {Array} [dataConfig] - 数据源配置
|
|
178
|
+
* @property {Array} [interactionConfig] - 交互配置
|
|
179
|
+
*/
|
|
180
|
+
/**
|
|
181
|
+
* 数据源配置 Schema
|
|
182
|
+
* @typedef {Object} DataSourceSchema
|
|
183
|
+
* @property {string} type - 数据源类型
|
|
184
|
+
* @property {string} name - 显示名称
|
|
185
|
+
* @property {Array<PropertyFieldSchema>} configSchema - 配置字段
|
|
186
|
+
* @property {Object} defaults - 默认配置
|
|
187
|
+
*/
|
|
188
|
+
/**
|
|
189
|
+
* Schema 解析:把字段数组按 group 分组
|
|
190
|
+
* @param {Array<PropertyFieldSchema>} fields
|
|
191
|
+
* @returns {Array<{name: string, fields: Array}>}
|
|
192
|
+
*/
|
|
193
|
+
function groupFields(fields) {
|
|
194
|
+
const groups = /* @__PURE__ */ new Map();
|
|
195
|
+
for (const field of fields || []) {
|
|
196
|
+
const groupName = field.group || "基础";
|
|
197
|
+
if (!groups.has(groupName)) groups.set(groupName, []);
|
|
198
|
+
groups.get(groupName).push(field);
|
|
199
|
+
}
|
|
200
|
+
return Array.from(groups.entries()).map(([name, fields]) => ({
|
|
201
|
+
name,
|
|
202
|
+
fields
|
|
203
|
+
}));
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* 从 Schema 字段数组生成默认值对象
|
|
207
|
+
* @param {Array<PropertyFieldSchema>} fields
|
|
208
|
+
* @param {Object} [base] - 基础默认值
|
|
209
|
+
* @returns {Object}
|
|
210
|
+
*/
|
|
211
|
+
function resolveDefaults(fields, base = {}) {
|
|
212
|
+
const result = { ...base };
|
|
213
|
+
for (const field of fields || []) if (field.default !== void 0 && getNestedValue(result, field.key) === void 0) setNestedValue(result, field.key, field.default);
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* 读取嵌套值(支持点号路径)
|
|
218
|
+
* @param {Object} obj
|
|
219
|
+
* @param {string} path - 如 'style.color'
|
|
220
|
+
* @returns {*}
|
|
221
|
+
*/
|
|
222
|
+
function getNestedValue(obj, path) {
|
|
223
|
+
if (!obj || !path) return void 0;
|
|
224
|
+
const keys = path.split(".");
|
|
225
|
+
let current = obj;
|
|
226
|
+
for (const key of keys) {
|
|
227
|
+
if (current == null) return void 0;
|
|
228
|
+
current = current[key];
|
|
229
|
+
}
|
|
230
|
+
return current;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* 设置嵌套值(支持点号路径)
|
|
234
|
+
* @param {Object} obj
|
|
235
|
+
* @param {string} path
|
|
236
|
+
* @param {*} value
|
|
237
|
+
*/
|
|
238
|
+
function setNestedValue(obj, path, value) {
|
|
239
|
+
if (!obj || !path) return;
|
|
240
|
+
const keys = path.split(".");
|
|
241
|
+
let current = obj;
|
|
242
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
243
|
+
const key = keys[i];
|
|
244
|
+
if (current[key] == null || typeof current[key] !== "object") current[key] = {};
|
|
245
|
+
current = current[key];
|
|
246
|
+
}
|
|
247
|
+
current[keys[keys.length - 1]] = value;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* 字段可见性判定
|
|
251
|
+
* @param {PropertyFieldSchema} field
|
|
252
|
+
* @param {Object} props - 当前属性对象
|
|
253
|
+
* @param {Object} [context] - 额外上下文
|
|
254
|
+
* @returns {boolean}
|
|
255
|
+
*/
|
|
256
|
+
function isFieldVisible(field, props, context = {}) {
|
|
257
|
+
if (field.visible === void 0 || field.visible === null) return true;
|
|
258
|
+
if (typeof field.visible === "boolean") return field.visible;
|
|
259
|
+
if (typeof field.visible === "function") try {
|
|
260
|
+
return !!field.visible(props, context);
|
|
261
|
+
} catch (e) {
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* 字段校验
|
|
268
|
+
* @param {PropertyFieldSchema} field
|
|
269
|
+
* @param {*} value
|
|
270
|
+
* @returns {true|string} true 表示通过,字符串表示错误信息
|
|
271
|
+
*/
|
|
272
|
+
function validateField(field, value) {
|
|
273
|
+
if (field.required && (value === void 0 || value === null || value === "")) return `${field.label || field.key} 是必填项`;
|
|
274
|
+
if (field.validator && typeof field.validator === "function") try {
|
|
275
|
+
const result = field.validator(value);
|
|
276
|
+
return result === true ? true : result || "校验失败";
|
|
277
|
+
} catch (e) {
|
|
278
|
+
return e.message || "校验异常";
|
|
279
|
+
}
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
//#endregion
|
|
283
|
+
//#region src/manifest.js
|
|
284
|
+
/**
|
|
285
|
+
* @nbreak/shared - Manifest 规范与校验
|
|
286
|
+
*
|
|
287
|
+
* 每个扩展包根目录声明 datascreen.extension.json:
|
|
288
|
+
* {
|
|
289
|
+
* "name": "@nbreak/theme-dark-tech",
|
|
290
|
+
* "version": "1.0.0",
|
|
291
|
+
* "type": "theme",
|
|
292
|
+
* "entry": "./dist/index.js",
|
|
293
|
+
* "module": "./dist/index.mjs",
|
|
294
|
+
* "types": "./dist/index.d.ts",
|
|
295
|
+
* "datascreenVersion": ">=1.0.0",
|
|
296
|
+
* "dependencies": { "@nbreak/core": "^1.0.0" },
|
|
297
|
+
* "displayName": "暗黑科技主题",
|
|
298
|
+
* "description": "...",
|
|
299
|
+
* "icon": "...",
|
|
300
|
+
* "preview": "./preview.png",
|
|
301
|
+
* "schema": {}
|
|
302
|
+
* }
|
|
303
|
+
*/
|
|
304
|
+
/**
|
|
305
|
+
* Manifest 必填字段
|
|
306
|
+
*/
|
|
307
|
+
var MANIFEST_REQUIRED_FIELDS = [
|
|
308
|
+
"name",
|
|
309
|
+
"version",
|
|
310
|
+
"type",
|
|
311
|
+
"entry"
|
|
312
|
+
];
|
|
313
|
+
/**
|
|
314
|
+
* Manifest 可选字段
|
|
315
|
+
*/
|
|
316
|
+
var MANIFEST_OPTIONAL_FIELDS = [
|
|
317
|
+
"module",
|
|
318
|
+
"types",
|
|
319
|
+
"datascreenVersion",
|
|
320
|
+
"dependencies",
|
|
321
|
+
"displayName",
|
|
322
|
+
"description",
|
|
323
|
+
"icon",
|
|
324
|
+
"preview",
|
|
325
|
+
"schema",
|
|
326
|
+
"author",
|
|
327
|
+
"license",
|
|
328
|
+
"keywords"
|
|
329
|
+
];
|
|
330
|
+
/**
|
|
331
|
+
* 校验 Manifest
|
|
332
|
+
* @param {Object} manifest
|
|
333
|
+
* @returns {{valid: boolean, errors: Array<string>, warnings: Array<string>}}
|
|
334
|
+
*/
|
|
335
|
+
function validateManifest(manifest) {
|
|
336
|
+
const errors = [];
|
|
337
|
+
const warnings = [];
|
|
338
|
+
if (!manifest || typeof manifest !== "object") return {
|
|
339
|
+
valid: false,
|
|
340
|
+
errors: ["manifest 必须是对象"],
|
|
341
|
+
warnings
|
|
342
|
+
};
|
|
343
|
+
for (const field of MANIFEST_REQUIRED_FIELDS) if (!manifest[field]) errors.push(`缺少必填字段: ${field}`);
|
|
344
|
+
if (manifest.type && !ALL_EXTENSION_TYPES.includes(manifest.type)) errors.push(`无效的 type: "${manifest.type}",有效值: ${ALL_EXTENSION_TYPES.join(", ")}`);
|
|
345
|
+
if (manifest.name && !/^[a-z@][a-z0-9-._/@]*$/i.test(manifest.name)) warnings.push(`name "${manifest.name}" 不符合 npm 包名规范`);
|
|
346
|
+
if (manifest.version && !/^\d+\.\d+\.\d+/.test(manifest.version)) warnings.push(`version "${manifest.version}" 不符合 semver 规范`);
|
|
347
|
+
if (manifest.datascreenVersion && typeof manifest.datascreenVersion !== "string") warnings.push("datascreenVersion 应为字符串");
|
|
348
|
+
return {
|
|
349
|
+
valid: errors.length === 0,
|
|
350
|
+
errors,
|
|
351
|
+
warnings
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* 创建标准 Manifest
|
|
356
|
+
* @param {Object} partial
|
|
357
|
+
* @returns {Object}
|
|
358
|
+
*/
|
|
359
|
+
function createManifest(partial) {
|
|
360
|
+
const manifest = {
|
|
361
|
+
name: "",
|
|
362
|
+
version: "0.1.0",
|
|
363
|
+
type: "component",
|
|
364
|
+
entry: "./dist/index.js",
|
|
365
|
+
module: "./dist/index.mjs",
|
|
366
|
+
types: "./dist/index.d.ts",
|
|
367
|
+
datascreenVersion: ">=0.1.0",
|
|
368
|
+
dependencies: {},
|
|
369
|
+
displayName: "",
|
|
370
|
+
description: "",
|
|
371
|
+
icon: "",
|
|
372
|
+
preview: "",
|
|
373
|
+
schema: {},
|
|
374
|
+
...partial
|
|
375
|
+
};
|
|
376
|
+
if (!manifest.displayName) manifest.displayName = manifest.name;
|
|
377
|
+
return manifest;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* 版本兼容性检查
|
|
381
|
+
* @param {string} requiredVersion - 扩展要求的版本范围
|
|
382
|
+
* @param {string} currentVersion - 宿主当前版本
|
|
383
|
+
* @returns {boolean}
|
|
384
|
+
*/
|
|
385
|
+
function isVersionCompatible(requiredVersion, currentVersion) {
|
|
386
|
+
if (!requiredVersion) return true;
|
|
387
|
+
if (!currentVersion) return true;
|
|
388
|
+
const cleanRequired = requiredVersion.replace(/^[>=^~]+/, "").trim();
|
|
389
|
+
const cleanCurrent = currentVersion.replace(/^[>=^~]+/, "").trim();
|
|
390
|
+
const [reqMajor, reqMinor = 0, reqPatch = 0] = cleanRequired.split(".").map(Number);
|
|
391
|
+
const [curMajor, curMinor = 0, curPatch = 0] = cleanCurrent.split(".").map(Number);
|
|
392
|
+
if (curMajor < reqMajor) return false;
|
|
393
|
+
if (curMajor === reqMajor) {
|
|
394
|
+
if (curMinor < reqMinor) return false;
|
|
395
|
+
if (curMinor === reqMinor && curPatch < reqPatch) return false;
|
|
396
|
+
}
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
//#endregion
|
|
400
|
+
//#region src/utils.js
|
|
401
|
+
/**
|
|
402
|
+
* @nbreak/shared - 工具函数
|
|
403
|
+
*/
|
|
404
|
+
/**
|
|
405
|
+
* 生成唯一 ID
|
|
406
|
+
* @param {string} [prefix='ds-']
|
|
407
|
+
* @returns {string}
|
|
408
|
+
*/
|
|
409
|
+
function uid(prefix = "ds-") {
|
|
410
|
+
return `${prefix}${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* 深拷贝(结构化克隆优先)
|
|
414
|
+
* @param {*} obj
|
|
415
|
+
* @returns {*}
|
|
416
|
+
*/
|
|
417
|
+
function deepClone(obj) {
|
|
418
|
+
if (obj === null || typeof obj !== "object") return obj;
|
|
419
|
+
if (typeof structuredClone === "function") try {
|
|
420
|
+
return structuredClone(obj);
|
|
421
|
+
} catch (e) {}
|
|
422
|
+
return JSON.parse(JSON.stringify(obj));
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* 深合并对象(后者覆盖前者,递归)
|
|
426
|
+
* @param {Object} target
|
|
427
|
+
* @param {Object} source
|
|
428
|
+
* @returns {Object}
|
|
429
|
+
*/
|
|
430
|
+
function deepMerge(target = {}, source = {}) {
|
|
431
|
+
const result = { ...target };
|
|
432
|
+
for (const key of Object.keys(source)) {
|
|
433
|
+
const tVal = result[key];
|
|
434
|
+
const sVal = source[key];
|
|
435
|
+
if (sVal && typeof sVal === "object" && !Array.isArray(sVal) && tVal && typeof tVal === "object" && !Array.isArray(tVal)) result[key] = deepMerge(tVal, sVal);
|
|
436
|
+
else result[key] = deepClone(sVal);
|
|
437
|
+
}
|
|
438
|
+
return result;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* 防抖
|
|
442
|
+
* @param {Function} fn
|
|
443
|
+
* @param {number} delay
|
|
444
|
+
* @returns {Function}
|
|
445
|
+
*/
|
|
446
|
+
function debounce(fn, delay = 200) {
|
|
447
|
+
let timer = null;
|
|
448
|
+
return function(...args) {
|
|
449
|
+
if (timer) clearTimeout(timer);
|
|
450
|
+
timer = setTimeout(() => fn.apply(this, args), delay);
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* 节流
|
|
455
|
+
* @param {Function} fn
|
|
456
|
+
* @param {number} interval
|
|
457
|
+
* @returns {Function}
|
|
458
|
+
*/
|
|
459
|
+
function throttle(fn, interval = 200) {
|
|
460
|
+
let lastTime = 0;
|
|
461
|
+
let timer = null;
|
|
462
|
+
return function(...args) {
|
|
463
|
+
const now = Date.now();
|
|
464
|
+
const remaining = interval - (now - lastTime);
|
|
465
|
+
if (remaining <= 0) {
|
|
466
|
+
if (timer) {
|
|
467
|
+
clearTimeout(timer);
|
|
468
|
+
timer = null;
|
|
469
|
+
}
|
|
470
|
+
lastTime = now;
|
|
471
|
+
fn.apply(this, args);
|
|
472
|
+
} else if (!timer) timer = setTimeout(() => {
|
|
473
|
+
lastTime = Date.now();
|
|
474
|
+
timer = null;
|
|
475
|
+
fn.apply(this, args);
|
|
476
|
+
}, remaining);
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* 判断是否为 Promise
|
|
481
|
+
* @param {*} obj
|
|
482
|
+
* @returns {boolean}
|
|
483
|
+
*/
|
|
484
|
+
function isPromise(obj) {
|
|
485
|
+
return !!obj && (typeof obj === "object" || typeof obj === "function") && typeof obj.then === "function";
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* 安全 JSON 解析
|
|
489
|
+
* @param {string} str
|
|
490
|
+
* @param {*} [fallback]
|
|
491
|
+
* @returns {*}
|
|
492
|
+
*/
|
|
493
|
+
function safeJsonParse(str, fallback = null) {
|
|
494
|
+
try {
|
|
495
|
+
return JSON.parse(str);
|
|
496
|
+
} catch (e) {
|
|
497
|
+
return fallback;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* 类名转换:camelCase → kebab-case
|
|
502
|
+
* @param {string} str
|
|
503
|
+
* @returns {string}
|
|
504
|
+
*/
|
|
505
|
+
function toKebabCase(str) {
|
|
506
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* 类名转换:kebab-case → camelCase
|
|
510
|
+
* @param {string} str
|
|
511
|
+
* @returns {string}
|
|
512
|
+
*/
|
|
513
|
+
function toCamelCase(str) {
|
|
514
|
+
return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
515
|
+
}
|
|
516
|
+
//#endregion
|
|
517
|
+
//#region src/index.js
|
|
518
|
+
var VERSION = "0.1.0";
|
|
519
|
+
var PACKAGE_NAME = "@nbreak/shared";
|
|
520
|
+
//#endregion
|
|
521
|
+
exports.ALL_EXTENSION_TYPES = ALL_EXTENSION_TYPES;
|
|
522
|
+
exports.BUILTIN_PROPERTY_FIELD_TYPES = BUILTIN_PROPERTY_FIELD_TYPES;
|
|
523
|
+
exports.COMPONENT_CATEGORIES = COMPONENT_CATEGORIES;
|
|
524
|
+
exports.EXTENSION_STATUS = EXTENSION_STATUS;
|
|
525
|
+
exports.EXTENSION_TYPES = EXTENSION_TYPES;
|
|
526
|
+
exports.HOOK_NAMES = HOOK_NAMES;
|
|
527
|
+
exports.LOAD_STRATEGIES = LOAD_STRATEGIES;
|
|
528
|
+
exports.MANIFEST_OPTIONAL_FIELDS = MANIFEST_OPTIONAL_FIELDS;
|
|
529
|
+
exports.MANIFEST_REQUIRED_FIELDS = MANIFEST_REQUIRED_FIELDS;
|
|
530
|
+
exports.PACKAGE_NAME = PACKAGE_NAME;
|
|
531
|
+
exports.PROPERTY_FIELD_TYPES = PROPERTY_FIELD_TYPES;
|
|
532
|
+
exports.VERSION = VERSION;
|
|
533
|
+
exports.createManifest = createManifest;
|
|
534
|
+
exports.debounce = debounce;
|
|
535
|
+
exports.deepClone = deepClone;
|
|
536
|
+
exports.deepMerge = deepMerge;
|
|
537
|
+
exports.definePropertyField = definePropertyField;
|
|
538
|
+
exports.definePropertyGroup = definePropertyGroup;
|
|
539
|
+
exports.getNestedValue = getNestedValue;
|
|
540
|
+
exports.groupFields = groupFields;
|
|
541
|
+
exports.isFieldVisible = isFieldVisible;
|
|
542
|
+
exports.isPromise = isPromise;
|
|
543
|
+
exports.isVersionCompatible = isVersionCompatible;
|
|
544
|
+
exports.resolveDefaults = resolveDefaults;
|
|
545
|
+
exports.safeJsonParse = safeJsonParse;
|
|
546
|
+
exports.setNestedValue = setNestedValue;
|
|
547
|
+
exports.throttle = throttle;
|
|
548
|
+
exports.toCamelCase = toCamelCase;
|
|
549
|
+
exports.toKebabCase = toKebabCase;
|
|
550
|
+
exports.uid = uid;
|
|
551
|
+
exports.validateField = validateField;
|
|
552
|
+
exports.validateManifest = validateManifest;
|
|
553
|
+
|
|
554
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/constants.js","../../src/schema.js","../../src/manifest.js","../../src/utils.js","../../src/index.js"],"sourcesContent":["/**\n * @nbreak/shared - 常量定义\n */\n\n/**\n * 扩展物类型枚举\n * 对标竞品:\n * - DataV: 主题/组件/数据源三类\n * - Superset: 仅可视化插件\n * - FineReport: 图表/函数/数据源/模板\n * - Tableau: Extensions API(Dashboard 组件/连接器/数据驱动型操作)\n * 本方案聚合为 6 类,覆盖全部竞品场景\n */\nexport const EXTENSION_TYPES = {\n COMPONENT: 'component', // 自定义组件\n THEME: 'theme', // 主题包\n DATASOURCE: 'datasource', // 数据源适配器\n TEMPLATE: 'template', // 大屏模板\n ACTION: 'action', // 动作处理器\n PROPERTY_FIELD: 'property-field', // 属性编辑器自定义字段类型\n};\n\n/**\n * 扩展物类型列表(便于遍历)\n */\nexport const ALL_EXTENSION_TYPES = Object.values(EXTENSION_TYPES);\n\n/**\n * 属性字段类型枚举(内置)\n * 第三方可通过 property-field 扩展注册新类型\n */\nexport const PROPERTY_FIELD_TYPES = {\n TEXT: 'text',\n NUMBER: 'number',\n COLOR: 'color',\n SELECT: 'select',\n SWITCH: 'switch',\n SLIDER: 'slider',\n JSON: 'json',\n CODE: 'code',\n GRADIENT: 'gradient',\n IMAGE: 'image',\n DATE: 'date',\n RADIO: 'radio',\n CHECKBOX: 'checkbox',\n TEXTAREA: 'textarea',\n};\n\n/**\n * 内置属性字段类型列表\n */\nexport const BUILTIN_PROPERTY_FIELD_TYPES = Object.values(PROPERTY_FIELD_TYPES);\n\n/**\n * 组件分类(与现有 componentLibrary.js 对齐)\n */\nexport const COMPONENT_CATEGORIES = {\n CHARTS: 'charts',\n CONTROLS: 'controls',\n DECORATIONS: 'decorations',\n TITLES: 'titles',\n TABLES: 'tables',\n LISTS: 'lists',\n TIME: 'time',\n MEDIA: 'media',\n CONTAINERS: 'containers',\n BORDERS: 'borders',\n WEATHER: 'weather',\n DATASOURCE: 'datasource',\n FORMS: 'forms',\n CONFIG: 'config',\n OTHER: 'other',\n};\n\n/**\n * 预定义钩子名称(与现有 pluginSystem.js HOOKS 对齐并扩展)\n */\nexport const HOOK_NAMES = {\n // 渲染生命周期\n BEFORE_RENDER: 'beforeRender',\n AFTER_RENDER: 'afterRender',\n // 导出\n BEFORE_EXPORT: 'beforeExport',\n AFTER_EXPORT: 'afterExport',\n // 注册\n COMPONENT_REGISTER: 'componentRegister',\n DATA_SOURCE_REGISTER: 'dataSourceRegister',\n THEME_APPLY: 'themeApply',\n // 图表\n CHART_OPTIONS_MERGE: 'chartOptionsMerge',\n // 动画\n ANIMATION_CONFIG: 'animationConfig',\n // 扩展系统新增钩子\n BEFORE_EXTENSION_REGISTER: 'beforeExtensionRegister',\n AFTER_EXTENSION_REGISTER: 'afterExtensionRegister',\n BEFORE_EXTENSION_UNREGISTER: 'beforeExtensionUnregister',\n SCHEMA_RESOLVE: 'schemaResolve',\n PROPERTY_FIELD_RENDER: 'propertyFieldRender',\n};\n\n/**\n * 加载策略枚举\n */\nexport const LOAD_STRATEGIES = {\n STATIC: 'static', // 构建期 import\n FEDERATION: 'federation', // Module Federation\n UMD: 'umd', // UMD script\n};\n\n/**\n * 扩展状态\n */\nexport const EXTENSION_STATUS = {\n REGISTERED: 'registered',\n ENABLED: 'enabled',\n DISABLED: 'disabled',\n ERROR: 'error',\n LOADING: 'loading',\n};\n","/**\n * @nbreak/shared - Schema 规范与类型定义\n *\n * 统一现有三套字段定义:\n * - src/data/componentSchemas.js(Schema 驱动)\n * - src/components/panels/ComponentConfigPanel.vue(手写模板)\n * - src/components/panels/ChartConfigPanel.vue(图表专属)\n *\n * 对标竞品:\n * - DataV:每个组件支持样式/数据/交互三级配置面板\n * - Power BI:capabilities.json 声明式字段\n * - FineReport:条件格式 + 联动参数\n */\n\n/**\n * 属性字段描述符\n * @typedef {Object} PropertyFieldSchema\n * @property {string} key - 属性路径,支持点号(如 'style.color')\n * @property {string} label - 显示标签\n * @property {string} type - 字段类型(内置 PROPERTY_FIELD_TYPES 或扩展自定义类型)\n * @property {string} [group] - 配置分组(如 '样式'/'数据'/'交互')\n * @property {*} [default] - 默认值\n * @property {number} [min] - 最小值(number/slider 用)\n * @property {number} [max] - 最大值\n * @property {number} [step] - 步长\n * @property {Array<{label:string,value:*}>} [options] - 选项(select/radio 用)\n * @property {function|boolean} [visible] - 条件显示,函数接收 (props, context) 返回 boolean\n * @property {function} [validator] - 校验函数,返回 true 或错误信息字符串\n * @property {function} [transform] - 输入转换函数,对值做加工后返回\n * @property {string} [description] - 描述文本\n * @property {string} [placeholder] - 占位符\n * @property {boolean} [required] - 是否必填\n * @property {Object} [props] - 透传给编辑器组件的额外 props\n * @property {Array<PropertyFieldSchema>} [children] - 子字段(用于嵌套对象/数组)\n */\n\n/**\n * 创建属性字段描述符\n * @param {PropertyFieldSchema} schema\n * @returns {PropertyFieldSchema}\n */\nexport function definePropertyField(schema) {\n if (!schema || !schema.key) {\n throw new Error('[DataScreen] 属性字段描述符必须包含 key 字段');\n }\n return {\n type: 'text',\n group: '基础',\n ...schema,\n };\n}\n\n/**\n * 创建属性字段组\n * @param {string} name - 组名\n * @param {Array<PropertyFieldSchema>} fields\n * @returns {{name: string, fields: Array}}\n */\nexport function definePropertyGroup(name, fields) {\n return { name, fields: fields || [] };\n}\n\n/**\n * 组件 Schema(描述一个组件的全部可配置项)\n * @typedef {Object} ComponentSchema\n * @property {string} type - 组件类型\n * @property {string} name - 显示名称\n * @property {string} category - 分类\n * @property {Array<PropertyFieldSchema>} properties - 属性字段数组\n * @property {Object} defaults - 默认值对象\n * @property {Array} [dataConfig] - 数据源配置\n * @property {Array} [interactionConfig] - 交互配置\n */\n\n/**\n * 数据源配置 Schema\n * @typedef {Object} DataSourceSchema\n * @property {string} type - 数据源类型\n * @property {string} name - 显示名称\n * @property {Array<PropertyFieldSchema>} configSchema - 配置字段\n * @property {Object} defaults - 默认配置\n */\n\n/**\n * Schema 解析:把字段数组按 group 分组\n * @param {Array<PropertyFieldSchema>} fields\n * @returns {Array<{name: string, fields: Array}>}\n */\nexport function groupFields(fields) {\n const groups = new Map();\n for (const field of fields || []) {\n const groupName = field.group || '基础';\n if (!groups.has(groupName)) {\n groups.set(groupName, []);\n }\n groups.get(groupName).push(field);\n }\n return Array.from(groups.entries()).map(([name, fields]) => ({ name, fields }));\n}\n\n/**\n * 从 Schema 字段数组生成默认值对象\n * @param {Array<PropertyFieldSchema>} fields\n * @param {Object} [base] - 基础默认值\n * @returns {Object}\n */\nexport function resolveDefaults(fields, base = {}) {\n const result = { ...base };\n for (const field of fields || []) {\n if (field.default !== undefined && getNestedValue(result, field.key) === undefined) {\n setNestedValue(result, field.key, field.default);\n }\n }\n return result;\n}\n\n/**\n * 读取嵌套值(支持点号路径)\n * @param {Object} obj\n * @param {string} path - 如 'style.color'\n * @returns {*}\n */\nexport function getNestedValue(obj, path) {\n if (!obj || !path) return undefined;\n const keys = path.split('.');\n let current = obj;\n for (const key of keys) {\n if (current == null) return undefined;\n current = current[key];\n }\n return current;\n}\n\n/**\n * 设置嵌套值(支持点号路径)\n * @param {Object} obj\n * @param {string} path\n * @param {*} value\n */\nexport function setNestedValue(obj, path, value) {\n if (!obj || !path) return;\n const keys = path.split('.');\n let current = obj;\n for (let i = 0; i < keys.length - 1; i++) {\n const key = keys[i];\n if (current[key] == null || typeof current[key] !== 'object') {\n current[key] = {};\n }\n current = current[key];\n }\n current[keys[keys.length - 1]] = value;\n}\n\n/**\n * 字段可见性判定\n * @param {PropertyFieldSchema} field\n * @param {Object} props - 当前属性对象\n * @param {Object} [context] - 额外上下文\n * @returns {boolean}\n */\nexport function isFieldVisible(field, props, context = {}) {\n if (field.visible === undefined || field.visible === null) return true;\n if (typeof field.visible === 'boolean') return field.visible;\n if (typeof field.visible === 'function') {\n try {\n return !!field.visible(props, context);\n } catch (e) {\n return true;\n }\n }\n return true;\n}\n\n/**\n * 字段校验\n * @param {PropertyFieldSchema} field\n * @param {*} value\n * @returns {true|string} true 表示通过,字符串表示错误信息\n */\nexport function validateField(field, value) {\n if (field.required && (value === undefined || value === null || value === '')) {\n return `${field.label || field.key} 是必填项`;\n }\n if (field.validator && typeof field.validator === 'function') {\n try {\n const result = field.validator(value);\n return result === true ? true : (result || '校验失败');\n } catch (e) {\n return e.message || '校验异常';\n }\n }\n return true;\n}\n","/**\n * @nbreak/shared - Manifest 规范与校验\n *\n * 每个扩展包根目录声明 datascreen.extension.json:\n * {\n * \"name\": \"@nbreak/theme-dark-tech\",\n * \"version\": \"1.0.0\",\n * \"type\": \"theme\",\n * \"entry\": \"./dist/index.js\",\n * \"module\": \"./dist/index.mjs\",\n * \"types\": \"./dist/index.d.ts\",\n * \"datascreenVersion\": \">=1.0.0\",\n * \"dependencies\": { \"@nbreak/core\": \"^1.0.0\" },\n * \"displayName\": \"暗黑科技主题\",\n * \"description\": \"...\",\n * \"icon\": \"...\",\n * \"preview\": \"./preview.png\",\n * \"schema\": {}\n * }\n */\n\nimport { ALL_EXTENSION_TYPES } from './constants.js';\n\n/**\n * Manifest 必填字段\n */\nexport const MANIFEST_REQUIRED_FIELDS = ['name', 'version', 'type', 'entry'];\n\n/**\n * Manifest 可选字段\n */\nexport const MANIFEST_OPTIONAL_FIELDS = [\n 'module', 'types', 'datascreenVersion', 'dependencies',\n 'displayName', 'description', 'icon', 'preview', 'schema', 'author', 'license', 'keywords',\n];\n\n/**\n * 校验 Manifest\n * @param {Object} manifest\n * @returns {{valid: boolean, errors: Array<string>, warnings: Array<string>}}\n */\nexport function validateManifest(manifest) {\n const errors = [];\n const warnings = [];\n\n if (!manifest || typeof manifest !== 'object') {\n return { valid: false, errors: ['manifest 必须是对象'], warnings };\n }\n\n // 必填字段\n for (const field of MANIFEST_REQUIRED_FIELDS) {\n if (!manifest[field]) {\n errors.push(`缺少必填字段: ${field}`);\n }\n }\n\n // type 校验\n if (manifest.type && !ALL_EXTENSION_TYPES.includes(manifest.type)) {\n errors.push(\n `无效的 type: \"${manifest.type}\",有效值: ${ALL_EXTENSION_TYPES.join(', ')}`\n );\n }\n\n // name 规范校验\n if (manifest.name && !/^[a-z@][a-z0-9-._/@]*$/i.test(manifest.name)) {\n warnings.push(`name \"${manifest.name}\" 不符合 npm 包名规范`);\n }\n\n // version 语义化校验\n if (manifest.version && !/^\\d+\\.\\d+\\.\\d+/.test(manifest.version)) {\n warnings.push(`version \"${manifest.version}\" 不符合 semver 规范`);\n }\n\n // datascreenVersion 范围校验\n if (manifest.datascreenVersion && typeof manifest.datascreenVersion !== 'string') {\n warnings.push('datascreenVersion 应为字符串');\n }\n\n return { valid: errors.length === 0, errors, warnings };\n}\n\n/**\n * 创建标准 Manifest\n * @param {Object} partial\n * @returns {Object}\n */\nexport function createManifest(partial) {\n const manifest = {\n name: '',\n version: '0.1.0',\n type: 'component',\n entry: './dist/index.js',\n module: './dist/index.mjs',\n types: './dist/index.d.ts',\n datascreenVersion: '>=0.1.0',\n dependencies: {},\n displayName: '',\n description: '',\n icon: '',\n preview: '',\n schema: {},\n ...partial,\n };\n\n if (!manifest.displayName) {\n manifest.displayName = manifest.name;\n }\n\n return manifest;\n}\n\n/**\n * 版本兼容性检查\n * @param {string} requiredVersion - 扩展要求的版本范围\n * @param {string} currentVersion - 宿主当前版本\n * @returns {boolean}\n */\nexport function isVersionCompatible(requiredVersion, currentVersion) {\n if (!requiredVersion) return true;\n if (!currentVersion) return true;\n\n // 简单实现:支持 >=、^、~ 前缀\n const cleanRequired = requiredVersion.replace(/^[>=^~]+/, '').trim();\n const cleanCurrent = currentVersion.replace(/^[>=^~]+/, '').trim();\n\n const [reqMajor, reqMinor = 0, reqPatch = 0] = cleanRequired.split('.').map(Number);\n const [curMajor, curMinor = 0, curPatch = 0] = cleanCurrent.split('.').map(Number);\n\n // 主版本必须一致或更高\n if (curMajor < reqMajor) return false;\n if (curMajor === reqMajor) {\n if (curMinor < reqMinor) return false;\n if (curMinor === reqMinor && curPatch < reqPatch) return false;\n }\n return true;\n}\n","/**\n * @nbreak/shared - 工具函数\n */\n\n/**\n * 生成唯一 ID\n * @param {string} [prefix='ds-']\n * @returns {string}\n */\nexport function uid(prefix = 'ds-') {\n return `${prefix}${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;\n}\n\n/**\n * 深拷贝(结构化克隆优先)\n * @param {*} obj\n * @returns {*}\n */\nexport function deepClone(obj) {\n if (obj === null || typeof obj !== 'object') return obj;\n if (typeof structuredClone === 'function') {\n try {\n return structuredClone(obj);\n } catch (e) {\n // fallback\n }\n }\n return JSON.parse(JSON.stringify(obj));\n}\n\n/**\n * 深合并对象(后者覆盖前者,递归)\n * @param {Object} target\n * @param {Object} source\n * @returns {Object}\n */\nexport function deepMerge(target = {}, source = {}) {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n const tVal = result[key];\n const sVal = source[key];\n if (sVal && typeof sVal === 'object' && !Array.isArray(sVal) &&\n tVal && typeof tVal === 'object' && !Array.isArray(tVal)) {\n result[key] = deepMerge(tVal, sVal);\n } else {\n result[key] = deepClone(sVal);\n }\n }\n return result;\n}\n\n/**\n * 防抖\n * @param {Function} fn\n * @param {number} delay\n * @returns {Function}\n */\nexport function debounce(fn, delay = 200) {\n let timer = null;\n return function (...args) {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => fn.apply(this, args), delay);\n };\n}\n\n/**\n * 节流\n * @param {Function} fn\n * @param {number} interval\n * @returns {Function}\n */\nexport function throttle(fn, interval = 200) {\n let lastTime = 0;\n let timer = null;\n return function (...args) {\n const now = Date.now();\n const remaining = interval - (now - lastTime);\n if (remaining <= 0) {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n lastTime = now;\n fn.apply(this, args);\n } else if (!timer) {\n timer = setTimeout(() => {\n lastTime = Date.now();\n timer = null;\n fn.apply(this, args);\n }, remaining);\n }\n };\n}\n\n/**\n * 判断是否为 Promise\n * @param {*} obj\n * @returns {boolean}\n */\nexport function isPromise(obj) {\n return !!obj && (typeof obj === 'object' || typeof obj === 'function') &&\n typeof obj.then === 'function';\n}\n\n/**\n * 安全 JSON 解析\n * @param {string} str\n * @param {*} [fallback]\n * @returns {*}\n */\nexport function safeJsonParse(str, fallback = null) {\n try {\n return JSON.parse(str);\n } catch (e) {\n return fallback;\n }\n}\n\n/**\n * 类名转换:camelCase → kebab-case\n * @param {string} str\n * @returns {string}\n */\nexport function toKebabCase(str) {\n return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n}\n\n/**\n * 类名转换:kebab-case → camelCase\n * @param {string} str\n * @returns {string}\n */\nexport function toCamelCase(str) {\n return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n}\n","/**\n * @nbreak/shared - 入口\n *\n * 提供共享类型、Schema 规范、常量、工具函数\n * 无 Vue 依赖,纯 JS,可被任何环境引用\n */\n\n// 常量\nexport * from './constants.js';\n\n// Schema 规范与工具\nexport {\n definePropertyField,\n definePropertyGroup,\n groupFields,\n resolveDefaults,\n getNestedValue,\n setNestedValue,\n isFieldVisible,\n validateField,\n} from './schema.js';\n\n// Manifest 规范\nexport {\n validateManifest,\n createManifest,\n isVersionCompatible,\n MANIFEST_REQUIRED_FIELDS,\n MANIFEST_OPTIONAL_FIELDS,\n} from './manifest.js';\n\n// 工具函数\nexport {\n uid,\n deepClone,\n deepMerge,\n debounce,\n throttle,\n isPromise,\n safeJsonParse,\n toKebabCase,\n toCamelCase,\n} from './utils.js';\n\n// 版本信息\nexport const VERSION = '0.1.0';\n\n// 包信息\nexport const PACKAGE_NAME = '@nbreak/shared';\n"],"mappings":"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"}
|
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
//#region src/constants.js
|
|
2
|
+
/**
|
|
3
|
+
* @nbreak/shared - 常量定义
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 扩展物类型枚举
|
|
7
|
+
* 对标竞品:
|
|
8
|
+
* - DataV: 主题/组件/数据源三类
|
|
9
|
+
* - Superset: 仅可视化插件
|
|
10
|
+
* - FineReport: 图表/函数/数据源/模板
|
|
11
|
+
* - Tableau: Extensions API(Dashboard 组件/连接器/数据驱动型操作)
|
|
12
|
+
* 本方案聚合为 6 类,覆盖全部竞品场景
|
|
13
|
+
*/
|
|
14
|
+
var EXTENSION_TYPES = {
|
|
15
|
+
COMPONENT: "component",
|
|
16
|
+
THEME: "theme",
|
|
17
|
+
DATASOURCE: "datasource",
|
|
18
|
+
TEMPLATE: "template",
|
|
19
|
+
ACTION: "action",
|
|
20
|
+
PROPERTY_FIELD: "property-field"
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* 扩展物类型列表(便于遍历)
|
|
24
|
+
*/
|
|
25
|
+
var ALL_EXTENSION_TYPES = Object.values(EXTENSION_TYPES);
|
|
26
|
+
/**
|
|
27
|
+
* 属性字段类型枚举(内置)
|
|
28
|
+
* 第三方可通过 property-field 扩展注册新类型
|
|
29
|
+
*/
|
|
30
|
+
var PROPERTY_FIELD_TYPES = {
|
|
31
|
+
TEXT: "text",
|
|
32
|
+
NUMBER: "number",
|
|
33
|
+
COLOR: "color",
|
|
34
|
+
SELECT: "select",
|
|
35
|
+
SWITCH: "switch",
|
|
36
|
+
SLIDER: "slider",
|
|
37
|
+
JSON: "json",
|
|
38
|
+
CODE: "code",
|
|
39
|
+
GRADIENT: "gradient",
|
|
40
|
+
IMAGE: "image",
|
|
41
|
+
DATE: "date",
|
|
42
|
+
RADIO: "radio",
|
|
43
|
+
CHECKBOX: "checkbox",
|
|
44
|
+
TEXTAREA: "textarea"
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* 内置属性字段类型列表
|
|
48
|
+
*/
|
|
49
|
+
var BUILTIN_PROPERTY_FIELD_TYPES = Object.values(PROPERTY_FIELD_TYPES);
|
|
50
|
+
/**
|
|
51
|
+
* 组件分类(与现有 componentLibrary.js 对齐)
|
|
52
|
+
*/
|
|
53
|
+
var COMPONENT_CATEGORIES = {
|
|
54
|
+
CHARTS: "charts",
|
|
55
|
+
CONTROLS: "controls",
|
|
56
|
+
DECORATIONS: "decorations",
|
|
57
|
+
TITLES: "titles",
|
|
58
|
+
TABLES: "tables",
|
|
59
|
+
LISTS: "lists",
|
|
60
|
+
TIME: "time",
|
|
61
|
+
MEDIA: "media",
|
|
62
|
+
CONTAINERS: "containers",
|
|
63
|
+
BORDERS: "borders",
|
|
64
|
+
WEATHER: "weather",
|
|
65
|
+
DATASOURCE: "datasource",
|
|
66
|
+
FORMS: "forms",
|
|
67
|
+
CONFIG: "config",
|
|
68
|
+
OTHER: "other"
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* 预定义钩子名称(与现有 pluginSystem.js HOOKS 对齐并扩展)
|
|
72
|
+
*/
|
|
73
|
+
var HOOK_NAMES = {
|
|
74
|
+
BEFORE_RENDER: "beforeRender",
|
|
75
|
+
AFTER_RENDER: "afterRender",
|
|
76
|
+
BEFORE_EXPORT: "beforeExport",
|
|
77
|
+
AFTER_EXPORT: "afterExport",
|
|
78
|
+
COMPONENT_REGISTER: "componentRegister",
|
|
79
|
+
DATA_SOURCE_REGISTER: "dataSourceRegister",
|
|
80
|
+
THEME_APPLY: "themeApply",
|
|
81
|
+
CHART_OPTIONS_MERGE: "chartOptionsMerge",
|
|
82
|
+
ANIMATION_CONFIG: "animationConfig",
|
|
83
|
+
BEFORE_EXTENSION_REGISTER: "beforeExtensionRegister",
|
|
84
|
+
AFTER_EXTENSION_REGISTER: "afterExtensionRegister",
|
|
85
|
+
BEFORE_EXTENSION_UNREGISTER: "beforeExtensionUnregister",
|
|
86
|
+
SCHEMA_RESOLVE: "schemaResolve",
|
|
87
|
+
PROPERTY_FIELD_RENDER: "propertyFieldRender"
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* 加载策略枚举
|
|
91
|
+
*/
|
|
92
|
+
var LOAD_STRATEGIES = {
|
|
93
|
+
STATIC: "static",
|
|
94
|
+
FEDERATION: "federation",
|
|
95
|
+
UMD: "umd"
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* 扩展状态
|
|
99
|
+
*/
|
|
100
|
+
var EXTENSION_STATUS = {
|
|
101
|
+
REGISTERED: "registered",
|
|
102
|
+
ENABLED: "enabled",
|
|
103
|
+
DISABLED: "disabled",
|
|
104
|
+
ERROR: "error",
|
|
105
|
+
LOADING: "loading"
|
|
106
|
+
};
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/schema.js
|
|
109
|
+
/**
|
|
110
|
+
* @nbreak/shared - Schema 规范与类型定义
|
|
111
|
+
*
|
|
112
|
+
* 统一现有三套字段定义:
|
|
113
|
+
* - src/data/componentSchemas.js(Schema 驱动)
|
|
114
|
+
* - src/components/panels/ComponentConfigPanel.vue(手写模板)
|
|
115
|
+
* - src/components/panels/ChartConfigPanel.vue(图表专属)
|
|
116
|
+
*
|
|
117
|
+
* 对标竞品:
|
|
118
|
+
* - DataV:每个组件支持样式/数据/交互三级配置面板
|
|
119
|
+
* - Power BI:capabilities.json 声明式字段
|
|
120
|
+
* - FineReport:条件格式 + 联动参数
|
|
121
|
+
*/
|
|
122
|
+
/**
|
|
123
|
+
* 属性字段描述符
|
|
124
|
+
* @typedef {Object} PropertyFieldSchema
|
|
125
|
+
* @property {string} key - 属性路径,支持点号(如 'style.color')
|
|
126
|
+
* @property {string} label - 显示标签
|
|
127
|
+
* @property {string} type - 字段类型(内置 PROPERTY_FIELD_TYPES 或扩展自定义类型)
|
|
128
|
+
* @property {string} [group] - 配置分组(如 '样式'/'数据'/'交互')
|
|
129
|
+
* @property {*} [default] - 默认值
|
|
130
|
+
* @property {number} [min] - 最小值(number/slider 用)
|
|
131
|
+
* @property {number} [max] - 最大值
|
|
132
|
+
* @property {number} [step] - 步长
|
|
133
|
+
* @property {Array<{label:string,value:*}>} [options] - 选项(select/radio 用)
|
|
134
|
+
* @property {function|boolean} [visible] - 条件显示,函数接收 (props, context) 返回 boolean
|
|
135
|
+
* @property {function} [validator] - 校验函数,返回 true 或错误信息字符串
|
|
136
|
+
* @property {function} [transform] - 输入转换函数,对值做加工后返回
|
|
137
|
+
* @property {string} [description] - 描述文本
|
|
138
|
+
* @property {string} [placeholder] - 占位符
|
|
139
|
+
* @property {boolean} [required] - 是否必填
|
|
140
|
+
* @property {Object} [props] - 透传给编辑器组件的额外 props
|
|
141
|
+
* @property {Array<PropertyFieldSchema>} [children] - 子字段(用于嵌套对象/数组)
|
|
142
|
+
*/
|
|
143
|
+
/**
|
|
144
|
+
* 创建属性字段描述符
|
|
145
|
+
* @param {PropertyFieldSchema} schema
|
|
146
|
+
* @returns {PropertyFieldSchema}
|
|
147
|
+
*/
|
|
148
|
+
function definePropertyField(schema) {
|
|
149
|
+
if (!schema || !schema.key) throw new Error("[DataScreen] 属性字段描述符必须包含 key 字段");
|
|
150
|
+
return {
|
|
151
|
+
type: "text",
|
|
152
|
+
group: "基础",
|
|
153
|
+
...schema
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* 创建属性字段组
|
|
158
|
+
* @param {string} name - 组名
|
|
159
|
+
* @param {Array<PropertyFieldSchema>} fields
|
|
160
|
+
* @returns {{name: string, fields: Array}}
|
|
161
|
+
*/
|
|
162
|
+
function definePropertyGroup(name, fields) {
|
|
163
|
+
return {
|
|
164
|
+
name,
|
|
165
|
+
fields: fields || []
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* 组件 Schema(描述一个组件的全部可配置项)
|
|
170
|
+
* @typedef {Object} ComponentSchema
|
|
171
|
+
* @property {string} type - 组件类型
|
|
172
|
+
* @property {string} name - 显示名称
|
|
173
|
+
* @property {string} category - 分类
|
|
174
|
+
* @property {Array<PropertyFieldSchema>} properties - 属性字段数组
|
|
175
|
+
* @property {Object} defaults - 默认值对象
|
|
176
|
+
* @property {Array} [dataConfig] - 数据源配置
|
|
177
|
+
* @property {Array} [interactionConfig] - 交互配置
|
|
178
|
+
*/
|
|
179
|
+
/**
|
|
180
|
+
* 数据源配置 Schema
|
|
181
|
+
* @typedef {Object} DataSourceSchema
|
|
182
|
+
* @property {string} type - 数据源类型
|
|
183
|
+
* @property {string} name - 显示名称
|
|
184
|
+
* @property {Array<PropertyFieldSchema>} configSchema - 配置字段
|
|
185
|
+
* @property {Object} defaults - 默认配置
|
|
186
|
+
*/
|
|
187
|
+
/**
|
|
188
|
+
* Schema 解析:把字段数组按 group 分组
|
|
189
|
+
* @param {Array<PropertyFieldSchema>} fields
|
|
190
|
+
* @returns {Array<{name: string, fields: Array}>}
|
|
191
|
+
*/
|
|
192
|
+
function groupFields(fields) {
|
|
193
|
+
const groups = /* @__PURE__ */ new Map();
|
|
194
|
+
for (const field of fields || []) {
|
|
195
|
+
const groupName = field.group || "基础";
|
|
196
|
+
if (!groups.has(groupName)) groups.set(groupName, []);
|
|
197
|
+
groups.get(groupName).push(field);
|
|
198
|
+
}
|
|
199
|
+
return Array.from(groups.entries()).map(([name, fields]) => ({
|
|
200
|
+
name,
|
|
201
|
+
fields
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* 从 Schema 字段数组生成默认值对象
|
|
206
|
+
* @param {Array<PropertyFieldSchema>} fields
|
|
207
|
+
* @param {Object} [base] - 基础默认值
|
|
208
|
+
* @returns {Object}
|
|
209
|
+
*/
|
|
210
|
+
function resolveDefaults(fields, base = {}) {
|
|
211
|
+
const result = { ...base };
|
|
212
|
+
for (const field of fields || []) if (field.default !== void 0 && getNestedValue(result, field.key) === void 0) setNestedValue(result, field.key, field.default);
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* 读取嵌套值(支持点号路径)
|
|
217
|
+
* @param {Object} obj
|
|
218
|
+
* @param {string} path - 如 'style.color'
|
|
219
|
+
* @returns {*}
|
|
220
|
+
*/
|
|
221
|
+
function getNestedValue(obj, path) {
|
|
222
|
+
if (!obj || !path) return void 0;
|
|
223
|
+
const keys = path.split(".");
|
|
224
|
+
let current = obj;
|
|
225
|
+
for (const key of keys) {
|
|
226
|
+
if (current == null) return void 0;
|
|
227
|
+
current = current[key];
|
|
228
|
+
}
|
|
229
|
+
return current;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* 设置嵌套值(支持点号路径)
|
|
233
|
+
* @param {Object} obj
|
|
234
|
+
* @param {string} path
|
|
235
|
+
* @param {*} value
|
|
236
|
+
*/
|
|
237
|
+
function setNestedValue(obj, path, value) {
|
|
238
|
+
if (!obj || !path) return;
|
|
239
|
+
const keys = path.split(".");
|
|
240
|
+
let current = obj;
|
|
241
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
242
|
+
const key = keys[i];
|
|
243
|
+
if (current[key] == null || typeof current[key] !== "object") current[key] = {};
|
|
244
|
+
current = current[key];
|
|
245
|
+
}
|
|
246
|
+
current[keys[keys.length - 1]] = value;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* 字段可见性判定
|
|
250
|
+
* @param {PropertyFieldSchema} field
|
|
251
|
+
* @param {Object} props - 当前属性对象
|
|
252
|
+
* @param {Object} [context] - 额外上下文
|
|
253
|
+
* @returns {boolean}
|
|
254
|
+
*/
|
|
255
|
+
function isFieldVisible(field, props, context = {}) {
|
|
256
|
+
if (field.visible === void 0 || field.visible === null) return true;
|
|
257
|
+
if (typeof field.visible === "boolean") return field.visible;
|
|
258
|
+
if (typeof field.visible === "function") try {
|
|
259
|
+
return !!field.visible(props, context);
|
|
260
|
+
} catch (e) {
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* 字段校验
|
|
267
|
+
* @param {PropertyFieldSchema} field
|
|
268
|
+
* @param {*} value
|
|
269
|
+
* @returns {true|string} true 表示通过,字符串表示错误信息
|
|
270
|
+
*/
|
|
271
|
+
function validateField(field, value) {
|
|
272
|
+
if (field.required && (value === void 0 || value === null || value === "")) return `${field.label || field.key} 是必填项`;
|
|
273
|
+
if (field.validator && typeof field.validator === "function") try {
|
|
274
|
+
const result = field.validator(value);
|
|
275
|
+
return result === true ? true : result || "校验失败";
|
|
276
|
+
} catch (e) {
|
|
277
|
+
return e.message || "校验异常";
|
|
278
|
+
}
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
//#endregion
|
|
282
|
+
//#region src/manifest.js
|
|
283
|
+
/**
|
|
284
|
+
* @nbreak/shared - Manifest 规范与校验
|
|
285
|
+
*
|
|
286
|
+
* 每个扩展包根目录声明 datascreen.extension.json:
|
|
287
|
+
* {
|
|
288
|
+
* "name": "@nbreak/theme-dark-tech",
|
|
289
|
+
* "version": "1.0.0",
|
|
290
|
+
* "type": "theme",
|
|
291
|
+
* "entry": "./dist/index.js",
|
|
292
|
+
* "module": "./dist/index.mjs",
|
|
293
|
+
* "types": "./dist/index.d.ts",
|
|
294
|
+
* "datascreenVersion": ">=1.0.0",
|
|
295
|
+
* "dependencies": { "@nbreak/core": "^1.0.0" },
|
|
296
|
+
* "displayName": "暗黑科技主题",
|
|
297
|
+
* "description": "...",
|
|
298
|
+
* "icon": "...",
|
|
299
|
+
* "preview": "./preview.png",
|
|
300
|
+
* "schema": {}
|
|
301
|
+
* }
|
|
302
|
+
*/
|
|
303
|
+
/**
|
|
304
|
+
* Manifest 必填字段
|
|
305
|
+
*/
|
|
306
|
+
var MANIFEST_REQUIRED_FIELDS = [
|
|
307
|
+
"name",
|
|
308
|
+
"version",
|
|
309
|
+
"type",
|
|
310
|
+
"entry"
|
|
311
|
+
];
|
|
312
|
+
/**
|
|
313
|
+
* Manifest 可选字段
|
|
314
|
+
*/
|
|
315
|
+
var MANIFEST_OPTIONAL_FIELDS = [
|
|
316
|
+
"module",
|
|
317
|
+
"types",
|
|
318
|
+
"datascreenVersion",
|
|
319
|
+
"dependencies",
|
|
320
|
+
"displayName",
|
|
321
|
+
"description",
|
|
322
|
+
"icon",
|
|
323
|
+
"preview",
|
|
324
|
+
"schema",
|
|
325
|
+
"author",
|
|
326
|
+
"license",
|
|
327
|
+
"keywords"
|
|
328
|
+
];
|
|
329
|
+
/**
|
|
330
|
+
* 校验 Manifest
|
|
331
|
+
* @param {Object} manifest
|
|
332
|
+
* @returns {{valid: boolean, errors: Array<string>, warnings: Array<string>}}
|
|
333
|
+
*/
|
|
334
|
+
function validateManifest(manifest) {
|
|
335
|
+
const errors = [];
|
|
336
|
+
const warnings = [];
|
|
337
|
+
if (!manifest || typeof manifest !== "object") return {
|
|
338
|
+
valid: false,
|
|
339
|
+
errors: ["manifest 必须是对象"],
|
|
340
|
+
warnings
|
|
341
|
+
};
|
|
342
|
+
for (const field of MANIFEST_REQUIRED_FIELDS) if (!manifest[field]) errors.push(`缺少必填字段: ${field}`);
|
|
343
|
+
if (manifest.type && !ALL_EXTENSION_TYPES.includes(manifest.type)) errors.push(`无效的 type: "${manifest.type}",有效值: ${ALL_EXTENSION_TYPES.join(", ")}`);
|
|
344
|
+
if (manifest.name && !/^[a-z@][a-z0-9-._/@]*$/i.test(manifest.name)) warnings.push(`name "${manifest.name}" 不符合 npm 包名规范`);
|
|
345
|
+
if (manifest.version && !/^\d+\.\d+\.\d+/.test(manifest.version)) warnings.push(`version "${manifest.version}" 不符合 semver 规范`);
|
|
346
|
+
if (manifest.datascreenVersion && typeof manifest.datascreenVersion !== "string") warnings.push("datascreenVersion 应为字符串");
|
|
347
|
+
return {
|
|
348
|
+
valid: errors.length === 0,
|
|
349
|
+
errors,
|
|
350
|
+
warnings
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* 创建标准 Manifest
|
|
355
|
+
* @param {Object} partial
|
|
356
|
+
* @returns {Object}
|
|
357
|
+
*/
|
|
358
|
+
function createManifest(partial) {
|
|
359
|
+
const manifest = {
|
|
360
|
+
name: "",
|
|
361
|
+
version: "0.1.0",
|
|
362
|
+
type: "component",
|
|
363
|
+
entry: "./dist/index.js",
|
|
364
|
+
module: "./dist/index.mjs",
|
|
365
|
+
types: "./dist/index.d.ts",
|
|
366
|
+
datascreenVersion: ">=0.1.0",
|
|
367
|
+
dependencies: {},
|
|
368
|
+
displayName: "",
|
|
369
|
+
description: "",
|
|
370
|
+
icon: "",
|
|
371
|
+
preview: "",
|
|
372
|
+
schema: {},
|
|
373
|
+
...partial
|
|
374
|
+
};
|
|
375
|
+
if (!manifest.displayName) manifest.displayName = manifest.name;
|
|
376
|
+
return manifest;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* 版本兼容性检查
|
|
380
|
+
* @param {string} requiredVersion - 扩展要求的版本范围
|
|
381
|
+
* @param {string} currentVersion - 宿主当前版本
|
|
382
|
+
* @returns {boolean}
|
|
383
|
+
*/
|
|
384
|
+
function isVersionCompatible(requiredVersion, currentVersion) {
|
|
385
|
+
if (!requiredVersion) return true;
|
|
386
|
+
if (!currentVersion) return true;
|
|
387
|
+
const cleanRequired = requiredVersion.replace(/^[>=^~]+/, "").trim();
|
|
388
|
+
const cleanCurrent = currentVersion.replace(/^[>=^~]+/, "").trim();
|
|
389
|
+
const [reqMajor, reqMinor = 0, reqPatch = 0] = cleanRequired.split(".").map(Number);
|
|
390
|
+
const [curMajor, curMinor = 0, curPatch = 0] = cleanCurrent.split(".").map(Number);
|
|
391
|
+
if (curMajor < reqMajor) return false;
|
|
392
|
+
if (curMajor === reqMajor) {
|
|
393
|
+
if (curMinor < reqMinor) return false;
|
|
394
|
+
if (curMinor === reqMinor && curPatch < reqPatch) return false;
|
|
395
|
+
}
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
//#endregion
|
|
399
|
+
//#region src/utils.js
|
|
400
|
+
/**
|
|
401
|
+
* @nbreak/shared - 工具函数
|
|
402
|
+
*/
|
|
403
|
+
/**
|
|
404
|
+
* 生成唯一 ID
|
|
405
|
+
* @param {string} [prefix='ds-']
|
|
406
|
+
* @returns {string}
|
|
407
|
+
*/
|
|
408
|
+
function uid(prefix = "ds-") {
|
|
409
|
+
return `${prefix}${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* 深拷贝(结构化克隆优先)
|
|
413
|
+
* @param {*} obj
|
|
414
|
+
* @returns {*}
|
|
415
|
+
*/
|
|
416
|
+
function deepClone(obj) {
|
|
417
|
+
if (obj === null || typeof obj !== "object") return obj;
|
|
418
|
+
if (typeof structuredClone === "function") try {
|
|
419
|
+
return structuredClone(obj);
|
|
420
|
+
} catch (e) {}
|
|
421
|
+
return JSON.parse(JSON.stringify(obj));
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* 深合并对象(后者覆盖前者,递归)
|
|
425
|
+
* @param {Object} target
|
|
426
|
+
* @param {Object} source
|
|
427
|
+
* @returns {Object}
|
|
428
|
+
*/
|
|
429
|
+
function deepMerge(target = {}, source = {}) {
|
|
430
|
+
const result = { ...target };
|
|
431
|
+
for (const key of Object.keys(source)) {
|
|
432
|
+
const tVal = result[key];
|
|
433
|
+
const sVal = source[key];
|
|
434
|
+
if (sVal && typeof sVal === "object" && !Array.isArray(sVal) && tVal && typeof tVal === "object" && !Array.isArray(tVal)) result[key] = deepMerge(tVal, sVal);
|
|
435
|
+
else result[key] = deepClone(sVal);
|
|
436
|
+
}
|
|
437
|
+
return result;
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* 防抖
|
|
441
|
+
* @param {Function} fn
|
|
442
|
+
* @param {number} delay
|
|
443
|
+
* @returns {Function}
|
|
444
|
+
*/
|
|
445
|
+
function debounce(fn, delay = 200) {
|
|
446
|
+
let timer = null;
|
|
447
|
+
return function(...args) {
|
|
448
|
+
if (timer) clearTimeout(timer);
|
|
449
|
+
timer = setTimeout(() => fn.apply(this, args), delay);
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* 节流
|
|
454
|
+
* @param {Function} fn
|
|
455
|
+
* @param {number} interval
|
|
456
|
+
* @returns {Function}
|
|
457
|
+
*/
|
|
458
|
+
function throttle(fn, interval = 200) {
|
|
459
|
+
let lastTime = 0;
|
|
460
|
+
let timer = null;
|
|
461
|
+
return function(...args) {
|
|
462
|
+
const now = Date.now();
|
|
463
|
+
const remaining = interval - (now - lastTime);
|
|
464
|
+
if (remaining <= 0) {
|
|
465
|
+
if (timer) {
|
|
466
|
+
clearTimeout(timer);
|
|
467
|
+
timer = null;
|
|
468
|
+
}
|
|
469
|
+
lastTime = now;
|
|
470
|
+
fn.apply(this, args);
|
|
471
|
+
} else if (!timer) timer = setTimeout(() => {
|
|
472
|
+
lastTime = Date.now();
|
|
473
|
+
timer = null;
|
|
474
|
+
fn.apply(this, args);
|
|
475
|
+
}, remaining);
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* 判断是否为 Promise
|
|
480
|
+
* @param {*} obj
|
|
481
|
+
* @returns {boolean}
|
|
482
|
+
*/
|
|
483
|
+
function isPromise(obj) {
|
|
484
|
+
return !!obj && (typeof obj === "object" || typeof obj === "function") && typeof obj.then === "function";
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* 安全 JSON 解析
|
|
488
|
+
* @param {string} str
|
|
489
|
+
* @param {*} [fallback]
|
|
490
|
+
* @returns {*}
|
|
491
|
+
*/
|
|
492
|
+
function safeJsonParse(str, fallback = null) {
|
|
493
|
+
try {
|
|
494
|
+
return JSON.parse(str);
|
|
495
|
+
} catch (e) {
|
|
496
|
+
return fallback;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* 类名转换:camelCase → kebab-case
|
|
501
|
+
* @param {string} str
|
|
502
|
+
* @returns {string}
|
|
503
|
+
*/
|
|
504
|
+
function toKebabCase(str) {
|
|
505
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* 类名转换:kebab-case → camelCase
|
|
509
|
+
* @param {string} str
|
|
510
|
+
* @returns {string}
|
|
511
|
+
*/
|
|
512
|
+
function toCamelCase(str) {
|
|
513
|
+
return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
514
|
+
}
|
|
515
|
+
//#endregion
|
|
516
|
+
//#region src/index.js
|
|
517
|
+
var VERSION = "0.1.0";
|
|
518
|
+
var PACKAGE_NAME = "@nbreak/shared";
|
|
519
|
+
//#endregion
|
|
520
|
+
export { ALL_EXTENSION_TYPES, BUILTIN_PROPERTY_FIELD_TYPES, COMPONENT_CATEGORIES, EXTENSION_STATUS, EXTENSION_TYPES, HOOK_NAMES, LOAD_STRATEGIES, MANIFEST_OPTIONAL_FIELDS, MANIFEST_REQUIRED_FIELDS, PACKAGE_NAME, PROPERTY_FIELD_TYPES, VERSION, createManifest, debounce, deepClone, deepMerge, definePropertyField, definePropertyGroup, getNestedValue, groupFields, isFieldVisible, isPromise, isVersionCompatible, resolveDefaults, safeJsonParse, setNestedValue, throttle, toCamelCase, toKebabCase, uid, validateField, validateManifest };
|
|
521
|
+
|
|
522
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/constants.js","../../src/schema.js","../../src/manifest.js","../../src/utils.js","../../src/index.js"],"sourcesContent":["/**\n * @nbreak/shared - 常量定义\n */\n\n/**\n * 扩展物类型枚举\n * 对标竞品:\n * - DataV: 主题/组件/数据源三类\n * - Superset: 仅可视化插件\n * - FineReport: 图表/函数/数据源/模板\n * - Tableau: Extensions API(Dashboard 组件/连接器/数据驱动型操作)\n * 本方案聚合为 6 类,覆盖全部竞品场景\n */\nexport const EXTENSION_TYPES = {\n COMPONENT: 'component', // 自定义组件\n THEME: 'theme', // 主题包\n DATASOURCE: 'datasource', // 数据源适配器\n TEMPLATE: 'template', // 大屏模板\n ACTION: 'action', // 动作处理器\n PROPERTY_FIELD: 'property-field', // 属性编辑器自定义字段类型\n};\n\n/**\n * 扩展物类型列表(便于遍历)\n */\nexport const ALL_EXTENSION_TYPES = Object.values(EXTENSION_TYPES);\n\n/**\n * 属性字段类型枚举(内置)\n * 第三方可通过 property-field 扩展注册新类型\n */\nexport const PROPERTY_FIELD_TYPES = {\n TEXT: 'text',\n NUMBER: 'number',\n COLOR: 'color',\n SELECT: 'select',\n SWITCH: 'switch',\n SLIDER: 'slider',\n JSON: 'json',\n CODE: 'code',\n GRADIENT: 'gradient',\n IMAGE: 'image',\n DATE: 'date',\n RADIO: 'radio',\n CHECKBOX: 'checkbox',\n TEXTAREA: 'textarea',\n};\n\n/**\n * 内置属性字段类型列表\n */\nexport const BUILTIN_PROPERTY_FIELD_TYPES = Object.values(PROPERTY_FIELD_TYPES);\n\n/**\n * 组件分类(与现有 componentLibrary.js 对齐)\n */\nexport const COMPONENT_CATEGORIES = {\n CHARTS: 'charts',\n CONTROLS: 'controls',\n DECORATIONS: 'decorations',\n TITLES: 'titles',\n TABLES: 'tables',\n LISTS: 'lists',\n TIME: 'time',\n MEDIA: 'media',\n CONTAINERS: 'containers',\n BORDERS: 'borders',\n WEATHER: 'weather',\n DATASOURCE: 'datasource',\n FORMS: 'forms',\n CONFIG: 'config',\n OTHER: 'other',\n};\n\n/**\n * 预定义钩子名称(与现有 pluginSystem.js HOOKS 对齐并扩展)\n */\nexport const HOOK_NAMES = {\n // 渲染生命周期\n BEFORE_RENDER: 'beforeRender',\n AFTER_RENDER: 'afterRender',\n // 导出\n BEFORE_EXPORT: 'beforeExport',\n AFTER_EXPORT: 'afterExport',\n // 注册\n COMPONENT_REGISTER: 'componentRegister',\n DATA_SOURCE_REGISTER: 'dataSourceRegister',\n THEME_APPLY: 'themeApply',\n // 图表\n CHART_OPTIONS_MERGE: 'chartOptionsMerge',\n // 动画\n ANIMATION_CONFIG: 'animationConfig',\n // 扩展系统新增钩子\n BEFORE_EXTENSION_REGISTER: 'beforeExtensionRegister',\n AFTER_EXTENSION_REGISTER: 'afterExtensionRegister',\n BEFORE_EXTENSION_UNREGISTER: 'beforeExtensionUnregister',\n SCHEMA_RESOLVE: 'schemaResolve',\n PROPERTY_FIELD_RENDER: 'propertyFieldRender',\n};\n\n/**\n * 加载策略枚举\n */\nexport const LOAD_STRATEGIES = {\n STATIC: 'static', // 构建期 import\n FEDERATION: 'federation', // Module Federation\n UMD: 'umd', // UMD script\n};\n\n/**\n * 扩展状态\n */\nexport const EXTENSION_STATUS = {\n REGISTERED: 'registered',\n ENABLED: 'enabled',\n DISABLED: 'disabled',\n ERROR: 'error',\n LOADING: 'loading',\n};\n","/**\n * @nbreak/shared - Schema 规范与类型定义\n *\n * 统一现有三套字段定义:\n * - src/data/componentSchemas.js(Schema 驱动)\n * - src/components/panels/ComponentConfigPanel.vue(手写模板)\n * - src/components/panels/ChartConfigPanel.vue(图表专属)\n *\n * 对标竞品:\n * - DataV:每个组件支持样式/数据/交互三级配置面板\n * - Power BI:capabilities.json 声明式字段\n * - FineReport:条件格式 + 联动参数\n */\n\n/**\n * 属性字段描述符\n * @typedef {Object} PropertyFieldSchema\n * @property {string} key - 属性路径,支持点号(如 'style.color')\n * @property {string} label - 显示标签\n * @property {string} type - 字段类型(内置 PROPERTY_FIELD_TYPES 或扩展自定义类型)\n * @property {string} [group] - 配置分组(如 '样式'/'数据'/'交互')\n * @property {*} [default] - 默认值\n * @property {number} [min] - 最小值(number/slider 用)\n * @property {number} [max] - 最大值\n * @property {number} [step] - 步长\n * @property {Array<{label:string,value:*}>} [options] - 选项(select/radio 用)\n * @property {function|boolean} [visible] - 条件显示,函数接收 (props, context) 返回 boolean\n * @property {function} [validator] - 校验函数,返回 true 或错误信息字符串\n * @property {function} [transform] - 输入转换函数,对值做加工后返回\n * @property {string} [description] - 描述文本\n * @property {string} [placeholder] - 占位符\n * @property {boolean} [required] - 是否必填\n * @property {Object} [props] - 透传给编辑器组件的额外 props\n * @property {Array<PropertyFieldSchema>} [children] - 子字段(用于嵌套对象/数组)\n */\n\n/**\n * 创建属性字段描述符\n * @param {PropertyFieldSchema} schema\n * @returns {PropertyFieldSchema}\n */\nexport function definePropertyField(schema) {\n if (!schema || !schema.key) {\n throw new Error('[DataScreen] 属性字段描述符必须包含 key 字段');\n }\n return {\n type: 'text',\n group: '基础',\n ...schema,\n };\n}\n\n/**\n * 创建属性字段组\n * @param {string} name - 组名\n * @param {Array<PropertyFieldSchema>} fields\n * @returns {{name: string, fields: Array}}\n */\nexport function definePropertyGroup(name, fields) {\n return { name, fields: fields || [] };\n}\n\n/**\n * 组件 Schema(描述一个组件的全部可配置项)\n * @typedef {Object} ComponentSchema\n * @property {string} type - 组件类型\n * @property {string} name - 显示名称\n * @property {string} category - 分类\n * @property {Array<PropertyFieldSchema>} properties - 属性字段数组\n * @property {Object} defaults - 默认值对象\n * @property {Array} [dataConfig] - 数据源配置\n * @property {Array} [interactionConfig] - 交互配置\n */\n\n/**\n * 数据源配置 Schema\n * @typedef {Object} DataSourceSchema\n * @property {string} type - 数据源类型\n * @property {string} name - 显示名称\n * @property {Array<PropertyFieldSchema>} configSchema - 配置字段\n * @property {Object} defaults - 默认配置\n */\n\n/**\n * Schema 解析:把字段数组按 group 分组\n * @param {Array<PropertyFieldSchema>} fields\n * @returns {Array<{name: string, fields: Array}>}\n */\nexport function groupFields(fields) {\n const groups = new Map();\n for (const field of fields || []) {\n const groupName = field.group || '基础';\n if (!groups.has(groupName)) {\n groups.set(groupName, []);\n }\n groups.get(groupName).push(field);\n }\n return Array.from(groups.entries()).map(([name, fields]) => ({ name, fields }));\n}\n\n/**\n * 从 Schema 字段数组生成默认值对象\n * @param {Array<PropertyFieldSchema>} fields\n * @param {Object} [base] - 基础默认值\n * @returns {Object}\n */\nexport function resolveDefaults(fields, base = {}) {\n const result = { ...base };\n for (const field of fields || []) {\n if (field.default !== undefined && getNestedValue(result, field.key) === undefined) {\n setNestedValue(result, field.key, field.default);\n }\n }\n return result;\n}\n\n/**\n * 读取嵌套值(支持点号路径)\n * @param {Object} obj\n * @param {string} path - 如 'style.color'\n * @returns {*}\n */\nexport function getNestedValue(obj, path) {\n if (!obj || !path) return undefined;\n const keys = path.split('.');\n let current = obj;\n for (const key of keys) {\n if (current == null) return undefined;\n current = current[key];\n }\n return current;\n}\n\n/**\n * 设置嵌套值(支持点号路径)\n * @param {Object} obj\n * @param {string} path\n * @param {*} value\n */\nexport function setNestedValue(obj, path, value) {\n if (!obj || !path) return;\n const keys = path.split('.');\n let current = obj;\n for (let i = 0; i < keys.length - 1; i++) {\n const key = keys[i];\n if (current[key] == null || typeof current[key] !== 'object') {\n current[key] = {};\n }\n current = current[key];\n }\n current[keys[keys.length - 1]] = value;\n}\n\n/**\n * 字段可见性判定\n * @param {PropertyFieldSchema} field\n * @param {Object} props - 当前属性对象\n * @param {Object} [context] - 额外上下文\n * @returns {boolean}\n */\nexport function isFieldVisible(field, props, context = {}) {\n if (field.visible === undefined || field.visible === null) return true;\n if (typeof field.visible === 'boolean') return field.visible;\n if (typeof field.visible === 'function') {\n try {\n return !!field.visible(props, context);\n } catch (e) {\n return true;\n }\n }\n return true;\n}\n\n/**\n * 字段校验\n * @param {PropertyFieldSchema} field\n * @param {*} value\n * @returns {true|string} true 表示通过,字符串表示错误信息\n */\nexport function validateField(field, value) {\n if (field.required && (value === undefined || value === null || value === '')) {\n return `${field.label || field.key} 是必填项`;\n }\n if (field.validator && typeof field.validator === 'function') {\n try {\n const result = field.validator(value);\n return result === true ? true : (result || '校验失败');\n } catch (e) {\n return e.message || '校验异常';\n }\n }\n return true;\n}\n","/**\n * @nbreak/shared - Manifest 规范与校验\n *\n * 每个扩展包根目录声明 datascreen.extension.json:\n * {\n * \"name\": \"@nbreak/theme-dark-tech\",\n * \"version\": \"1.0.0\",\n * \"type\": \"theme\",\n * \"entry\": \"./dist/index.js\",\n * \"module\": \"./dist/index.mjs\",\n * \"types\": \"./dist/index.d.ts\",\n * \"datascreenVersion\": \">=1.0.0\",\n * \"dependencies\": { \"@nbreak/core\": \"^1.0.0\" },\n * \"displayName\": \"暗黑科技主题\",\n * \"description\": \"...\",\n * \"icon\": \"...\",\n * \"preview\": \"./preview.png\",\n * \"schema\": {}\n * }\n */\n\nimport { ALL_EXTENSION_TYPES } from './constants.js';\n\n/**\n * Manifest 必填字段\n */\nexport const MANIFEST_REQUIRED_FIELDS = ['name', 'version', 'type', 'entry'];\n\n/**\n * Manifest 可选字段\n */\nexport const MANIFEST_OPTIONAL_FIELDS = [\n 'module', 'types', 'datascreenVersion', 'dependencies',\n 'displayName', 'description', 'icon', 'preview', 'schema', 'author', 'license', 'keywords',\n];\n\n/**\n * 校验 Manifest\n * @param {Object} manifest\n * @returns {{valid: boolean, errors: Array<string>, warnings: Array<string>}}\n */\nexport function validateManifest(manifest) {\n const errors = [];\n const warnings = [];\n\n if (!manifest || typeof manifest !== 'object') {\n return { valid: false, errors: ['manifest 必须是对象'], warnings };\n }\n\n // 必填字段\n for (const field of MANIFEST_REQUIRED_FIELDS) {\n if (!manifest[field]) {\n errors.push(`缺少必填字段: ${field}`);\n }\n }\n\n // type 校验\n if (manifest.type && !ALL_EXTENSION_TYPES.includes(manifest.type)) {\n errors.push(\n `无效的 type: \"${manifest.type}\",有效值: ${ALL_EXTENSION_TYPES.join(', ')}`\n );\n }\n\n // name 规范校验\n if (manifest.name && !/^[a-z@][a-z0-9-._/@]*$/i.test(manifest.name)) {\n warnings.push(`name \"${manifest.name}\" 不符合 npm 包名规范`);\n }\n\n // version 语义化校验\n if (manifest.version && !/^\\d+\\.\\d+\\.\\d+/.test(manifest.version)) {\n warnings.push(`version \"${manifest.version}\" 不符合 semver 规范`);\n }\n\n // datascreenVersion 范围校验\n if (manifest.datascreenVersion && typeof manifest.datascreenVersion !== 'string') {\n warnings.push('datascreenVersion 应为字符串');\n }\n\n return { valid: errors.length === 0, errors, warnings };\n}\n\n/**\n * 创建标准 Manifest\n * @param {Object} partial\n * @returns {Object}\n */\nexport function createManifest(partial) {\n const manifest = {\n name: '',\n version: '0.1.0',\n type: 'component',\n entry: './dist/index.js',\n module: './dist/index.mjs',\n types: './dist/index.d.ts',\n datascreenVersion: '>=0.1.0',\n dependencies: {},\n displayName: '',\n description: '',\n icon: '',\n preview: '',\n schema: {},\n ...partial,\n };\n\n if (!manifest.displayName) {\n manifest.displayName = manifest.name;\n }\n\n return manifest;\n}\n\n/**\n * 版本兼容性检查\n * @param {string} requiredVersion - 扩展要求的版本范围\n * @param {string} currentVersion - 宿主当前版本\n * @returns {boolean}\n */\nexport function isVersionCompatible(requiredVersion, currentVersion) {\n if (!requiredVersion) return true;\n if (!currentVersion) return true;\n\n // 简单实现:支持 >=、^、~ 前缀\n const cleanRequired = requiredVersion.replace(/^[>=^~]+/, '').trim();\n const cleanCurrent = currentVersion.replace(/^[>=^~]+/, '').trim();\n\n const [reqMajor, reqMinor = 0, reqPatch = 0] = cleanRequired.split('.').map(Number);\n const [curMajor, curMinor = 0, curPatch = 0] = cleanCurrent.split('.').map(Number);\n\n // 主版本必须一致或更高\n if (curMajor < reqMajor) return false;\n if (curMajor === reqMajor) {\n if (curMinor < reqMinor) return false;\n if (curMinor === reqMinor && curPatch < reqPatch) return false;\n }\n return true;\n}\n","/**\n * @nbreak/shared - 工具函数\n */\n\n/**\n * 生成唯一 ID\n * @param {string} [prefix='ds-']\n * @returns {string}\n */\nexport function uid(prefix = 'ds-') {\n return `${prefix}${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;\n}\n\n/**\n * 深拷贝(结构化克隆优先)\n * @param {*} obj\n * @returns {*}\n */\nexport function deepClone(obj) {\n if (obj === null || typeof obj !== 'object') return obj;\n if (typeof structuredClone === 'function') {\n try {\n return structuredClone(obj);\n } catch (e) {\n // fallback\n }\n }\n return JSON.parse(JSON.stringify(obj));\n}\n\n/**\n * 深合并对象(后者覆盖前者,递归)\n * @param {Object} target\n * @param {Object} source\n * @returns {Object}\n */\nexport function deepMerge(target = {}, source = {}) {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n const tVal = result[key];\n const sVal = source[key];\n if (sVal && typeof sVal === 'object' && !Array.isArray(sVal) &&\n tVal && typeof tVal === 'object' && !Array.isArray(tVal)) {\n result[key] = deepMerge(tVal, sVal);\n } else {\n result[key] = deepClone(sVal);\n }\n }\n return result;\n}\n\n/**\n * 防抖\n * @param {Function} fn\n * @param {number} delay\n * @returns {Function}\n */\nexport function debounce(fn, delay = 200) {\n let timer = null;\n return function (...args) {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => fn.apply(this, args), delay);\n };\n}\n\n/**\n * 节流\n * @param {Function} fn\n * @param {number} interval\n * @returns {Function}\n */\nexport function throttle(fn, interval = 200) {\n let lastTime = 0;\n let timer = null;\n return function (...args) {\n const now = Date.now();\n const remaining = interval - (now - lastTime);\n if (remaining <= 0) {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n lastTime = now;\n fn.apply(this, args);\n } else if (!timer) {\n timer = setTimeout(() => {\n lastTime = Date.now();\n timer = null;\n fn.apply(this, args);\n }, remaining);\n }\n };\n}\n\n/**\n * 判断是否为 Promise\n * @param {*} obj\n * @returns {boolean}\n */\nexport function isPromise(obj) {\n return !!obj && (typeof obj === 'object' || typeof obj === 'function') &&\n typeof obj.then === 'function';\n}\n\n/**\n * 安全 JSON 解析\n * @param {string} str\n * @param {*} [fallback]\n * @returns {*}\n */\nexport function safeJsonParse(str, fallback = null) {\n try {\n return JSON.parse(str);\n } catch (e) {\n return fallback;\n }\n}\n\n/**\n * 类名转换:camelCase → kebab-case\n * @param {string} str\n * @returns {string}\n */\nexport function toKebabCase(str) {\n return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n}\n\n/**\n * 类名转换:kebab-case → camelCase\n * @param {string} str\n * @returns {string}\n */\nexport function toCamelCase(str) {\n return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n}\n","/**\n * @nbreak/shared - 入口\n *\n * 提供共享类型、Schema 规范、常量、工具函数\n * 无 Vue 依赖,纯 JS,可被任何环境引用\n */\n\n// 常量\nexport * from './constants.js';\n\n// Schema 规范与工具\nexport {\n definePropertyField,\n definePropertyGroup,\n groupFields,\n resolveDefaults,\n getNestedValue,\n setNestedValue,\n isFieldVisible,\n validateField,\n} from './schema.js';\n\n// Manifest 规范\nexport {\n validateManifest,\n createManifest,\n isVersionCompatible,\n MANIFEST_REQUIRED_FIELDS,\n MANIFEST_OPTIONAL_FIELDS,\n} from './manifest.js';\n\n// 工具函数\nexport {\n uid,\n deepClone,\n deepMerge,\n debounce,\n throttle,\n isPromise,\n safeJsonParse,\n toKebabCase,\n toCamelCase,\n} from './utils.js';\n\n// 版本信息\nexport const VERSION = '0.1.0';\n\n// 包信息\nexport const PACKAGE_NAME = '@nbreak/shared';\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nbreak/shared",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "DataScreen 共享类型、Schema 规范与常量",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/cjs/index.cjs",
|
|
7
|
+
"module": "./dist/esm/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/esm/index.js",
|
|
11
|
+
"require": "./dist/cjs/index.cjs"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "rm -rf dist && BUILD_FORMAT=es vite build && BUILD_FORMAT=cjs vite build",
|
|
24
|
+
"dev": "vite build --watch"
|
|
25
|
+
}
|
|
26
|
+
}
|