@sunyard-szyy-ui/utils 0.2.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 +3 -0
- package/dist/index.cjs +170 -0
- package/dist/index.d.cts +188 -0
- package/dist/index.d.ts +188 -0
- package/dist/index.js +138 -0
- package/package.json +31 -0
package/README.md
ADDED
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
SunyardSzyyUIResolver: () => SunyardSzyyUIResolver,
|
|
24
|
+
debounce: () => debounce,
|
|
25
|
+
deepClone: () => deepClone,
|
|
26
|
+
formatDate: () => formatDate,
|
|
27
|
+
throttle: () => throttle,
|
|
28
|
+
withInstall: () => withInstall
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(index_exports);
|
|
31
|
+
|
|
32
|
+
// src/resolver.ts
|
|
33
|
+
function pascalToKebab(str, prefix = "Sy") {
|
|
34
|
+
return str.slice(prefix.length).replace(/([A-Z])/g, "-$1").toLowerCase().slice(1);
|
|
35
|
+
}
|
|
36
|
+
function SunyardSzyyUIResolver(options = {}) {
|
|
37
|
+
const {
|
|
38
|
+
prefix = "Sy",
|
|
39
|
+
importStyle = true,
|
|
40
|
+
libraryName = "sunyard-szyy-ui",
|
|
41
|
+
styleLibraryName = "@sunyard-szyy-ui/theme-chalk",
|
|
42
|
+
componentsLibraryName = "@sunyard-szyy-ui/components",
|
|
43
|
+
devMode = false,
|
|
44
|
+
importMetaUrl,
|
|
45
|
+
fileURLToPath,
|
|
46
|
+
dirResolver
|
|
47
|
+
} = options;
|
|
48
|
+
if (devMode && !dirResolver) {
|
|
49
|
+
if (!importMetaUrl || !fileURLToPath) {
|
|
50
|
+
throw new Error(
|
|
51
|
+
"[SunyardSzyyUIResolver] devMode \u542F\u7528\u65F6\u5FC5\u987B\u63D0\u4F9B importMetaUrl \u548C fileURLToPath \u53C2\u6570\n\u793A\u4F8B\uFF1A\nimport { fileURLToPath } from 'node:url';\nSunyardSzyyUIResolver({ devMode: true, importMetaUrl: import.meta.url, fileURLToPath })"
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
let actualDirResolver = dirResolver;
|
|
56
|
+
if (devMode && importMetaUrl && fileURLToPath && !dirResolver) {
|
|
57
|
+
actualDirResolver = (name) => {
|
|
58
|
+
const styleFile = importStyle === "scss" ? "index.ts" : "css.ts";
|
|
59
|
+
return {
|
|
60
|
+
componentPath: fileURLToPath(new URL(`../packages/components/src/${name}/index.ts`, importMetaUrl)),
|
|
61
|
+
stylePath: fileURLToPath(new URL(`../packages/components/src/${name}/style/${styleFile}`, importMetaUrl))
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
type: "component",
|
|
67
|
+
resolve: (name) => {
|
|
68
|
+
if (name.startsWith(prefix)) {
|
|
69
|
+
const componentName = pascalToKebab(name, prefix);
|
|
70
|
+
if (actualDirResolver) {
|
|
71
|
+
const paths = actualDirResolver(componentName);
|
|
72
|
+
if (paths.componentPath) {
|
|
73
|
+
return {
|
|
74
|
+
name,
|
|
75
|
+
from: paths.componentPath,
|
|
76
|
+
sideEffects: importStyle && paths.stylePath ? paths.stylePath : void 0
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const result = {
|
|
81
|
+
name,
|
|
82
|
+
from: libraryName
|
|
83
|
+
};
|
|
84
|
+
if (importStyle) {
|
|
85
|
+
if (importStyle === "css") {
|
|
86
|
+
result.sideEffects = `${styleLibraryName}/${componentName}.css`;
|
|
87
|
+
} else if (importStyle === "scss") {
|
|
88
|
+
result.sideEffects = `${styleLibraryName}/src/${componentName}.scss`;
|
|
89
|
+
} else if (importStyle === true) {
|
|
90
|
+
result.sideEffects = `${styleLibraryName}/${componentName}.css`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/index.ts
|
|
100
|
+
function withInstall(component) {
|
|
101
|
+
const c = component;
|
|
102
|
+
c.install = (app) => {
|
|
103
|
+
const name = component.name;
|
|
104
|
+
if (!name) return;
|
|
105
|
+
app.component(name, component);
|
|
106
|
+
};
|
|
107
|
+
return c;
|
|
108
|
+
}
|
|
109
|
+
function debounce(fn, delay = 300) {
|
|
110
|
+
let timer = null;
|
|
111
|
+
return function(...args) {
|
|
112
|
+
if (timer) {
|
|
113
|
+
clearTimeout(timer);
|
|
114
|
+
}
|
|
115
|
+
timer = setTimeout(() => {
|
|
116
|
+
fn.apply(this, args);
|
|
117
|
+
timer = null;
|
|
118
|
+
}, delay);
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function throttle(fn, delay = 300) {
|
|
122
|
+
let lastTime = 0;
|
|
123
|
+
return function(...args) {
|
|
124
|
+
const now = Date.now();
|
|
125
|
+
if (now - lastTime >= delay) {
|
|
126
|
+
fn.apply(this, args);
|
|
127
|
+
lastTime = now;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function formatDate(date, format = "YYYY-MM-DD HH:mm:ss") {
|
|
132
|
+
const d = typeof date === "number" ? new Date(date) : date;
|
|
133
|
+
const year = d.getFullYear();
|
|
134
|
+
const month = String(d.getMonth() + 1).padStart(2, "0");
|
|
135
|
+
const day = String(d.getDate()).padStart(2, "0");
|
|
136
|
+
const hours = String(d.getHours()).padStart(2, "0");
|
|
137
|
+
const minutes = String(d.getMinutes()).padStart(2, "0");
|
|
138
|
+
const seconds = String(d.getSeconds()).padStart(2, "0");
|
|
139
|
+
return format.replace("YYYY", String(year)).replace("MM", month).replace("DD", day).replace("HH", hours).replace("mm", minutes).replace("ss", seconds);
|
|
140
|
+
}
|
|
141
|
+
function deepClone(obj) {
|
|
142
|
+
if (obj === null || typeof obj !== "object") {
|
|
143
|
+
return obj;
|
|
144
|
+
}
|
|
145
|
+
if (obj instanceof Date) {
|
|
146
|
+
return new Date(obj.getTime());
|
|
147
|
+
}
|
|
148
|
+
if (obj instanceof Array) {
|
|
149
|
+
return obj.map((item) => deepClone(item));
|
|
150
|
+
}
|
|
151
|
+
if (typeof obj === "object") {
|
|
152
|
+
const clonedObj = {};
|
|
153
|
+
for (const key in obj) {
|
|
154
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
155
|
+
clonedObj[key] = deepClone(obj[key]);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return clonedObj;
|
|
159
|
+
}
|
|
160
|
+
return obj;
|
|
161
|
+
}
|
|
162
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
163
|
+
0 && (module.exports = {
|
|
164
|
+
SunyardSzyyUIResolver,
|
|
165
|
+
debounce,
|
|
166
|
+
deepClone,
|
|
167
|
+
formatDate,
|
|
168
|
+
throttle,
|
|
169
|
+
withInstall
|
|
170
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import * as vue from 'vue';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 组件解析器类型(兼容 unplugin-vue-components)
|
|
5
|
+
*/
|
|
6
|
+
interface ComponentResolver {
|
|
7
|
+
type: 'component' | 'directive';
|
|
8
|
+
resolve: (name: string) => ComponentResolveResult | void | null | undefined;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 组件解析结果
|
|
12
|
+
*/
|
|
13
|
+
interface ComponentResolveResult {
|
|
14
|
+
name?: string;
|
|
15
|
+
from: string;
|
|
16
|
+
sideEffects?: string | string[];
|
|
17
|
+
[key: string]: any;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolver 配置选项
|
|
21
|
+
*/
|
|
22
|
+
interface SunyardSzyyUIResolverOptions {
|
|
23
|
+
/**
|
|
24
|
+
* 组件前缀
|
|
25
|
+
* @default 'Sy'
|
|
26
|
+
*/
|
|
27
|
+
prefix?: string;
|
|
28
|
+
/**
|
|
29
|
+
* 是否导入样式
|
|
30
|
+
* @default true
|
|
31
|
+
*/
|
|
32
|
+
importStyle?: boolean | 'css' | 'scss';
|
|
33
|
+
/**
|
|
34
|
+
* 组件库名称
|
|
35
|
+
* @default 'sunyard-szyy-ui'
|
|
36
|
+
*/
|
|
37
|
+
libraryName?: string;
|
|
38
|
+
/**
|
|
39
|
+
* 样式包名称
|
|
40
|
+
* @default '@sunyard-szyy-ui/theme-chalk'
|
|
41
|
+
*/
|
|
42
|
+
styleLibraryName?: string;
|
|
43
|
+
/**
|
|
44
|
+
* 组件目录名称
|
|
45
|
+
* @default '@sunyard-szyy-ui/components'
|
|
46
|
+
*/
|
|
47
|
+
componentsLibraryName?: string;
|
|
48
|
+
/**
|
|
49
|
+
* 是否为源码开发模式(monorepo 内部开发)
|
|
50
|
+
*
|
|
51
|
+
* 启用后会自动使用 monorepo 源码路径,无需手动配置 dirResolver
|
|
52
|
+
*
|
|
53
|
+
* @default false
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* // 在 monorepo 开发环境中使用
|
|
57
|
+
* import { fileURLToPath } from 'node:url';
|
|
58
|
+
*
|
|
59
|
+
* SunyardSzyyUIResolver({
|
|
60
|
+
* devMode: true,
|
|
61
|
+
* importMetaUrl: import.meta.url,
|
|
62
|
+
* fileURLToPath: fileURLToPath
|
|
63
|
+
* })
|
|
64
|
+
*/
|
|
65
|
+
devMode?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* import.meta.url(devMode 启用时必须提供)
|
|
68
|
+
*
|
|
69
|
+
* 用于解析 monorepo 源码的绝对路径
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* import.meta.url
|
|
73
|
+
*/
|
|
74
|
+
importMetaUrl?: string;
|
|
75
|
+
/**
|
|
76
|
+
* fileURLToPath 函数(devMode 启用时必须提供)
|
|
77
|
+
*
|
|
78
|
+
* 用于将 URL 转换为文件系统路径
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* import { fileURLToPath } from 'node:url';
|
|
82
|
+
* // 然后传入: fileURLToPath: fileURLToPath
|
|
83
|
+
*/
|
|
84
|
+
fileURLToPath?: (url: string | URL) => string;
|
|
85
|
+
/**
|
|
86
|
+
* 自定义目录解析器(高级用法,一般不需要)
|
|
87
|
+
*
|
|
88
|
+
* 如果提供了此选项,会覆盖 devMode 的默认行为
|
|
89
|
+
*
|
|
90
|
+
* @deprecated 推荐使用 devMode + importMetaUrl 替代
|
|
91
|
+
*/
|
|
92
|
+
dirResolver?: (name: string) => {
|
|
93
|
+
/**
|
|
94
|
+
* 组件源码路径(开发模式使用)
|
|
95
|
+
*/
|
|
96
|
+
componentPath?: string;
|
|
97
|
+
/**
|
|
98
|
+
* 样式源码路径(开发模式使用)
|
|
99
|
+
*/
|
|
100
|
+
stylePath?: string;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* sunyard-szyy-ui 组件自动导入 resolver
|
|
105
|
+
*
|
|
106
|
+
* 支持组件和样式的按需自动导入,适用于:
|
|
107
|
+
* - ✅ 外部项目使用(npm 包方式)
|
|
108
|
+
* - ✅ Monorepo 内部开发(源码方式)
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* // 外部项目使用(默认配置)
|
|
112
|
+
* import { SunyardSzyyUIResolver } from '@sunyard-szyy-ui/utils';
|
|
113
|
+
*
|
|
114
|
+
* Components({
|
|
115
|
+
* resolvers: [SunyardSzyyUIResolver()]
|
|
116
|
+
* })
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* // Monorepo 内部开发(推荐方式 - 简化配置)
|
|
120
|
+
* import { SunyardSzyyUIResolver } from '@sunyard-szyy-ui/utils';
|
|
121
|
+
*
|
|
122
|
+
* Components({
|
|
123
|
+
* resolvers: [
|
|
124
|
+
* SunyardSzyyUIResolver({
|
|
125
|
+
* devMode: true,
|
|
126
|
+
* importMetaUrl: import.meta.url
|
|
127
|
+
* })
|
|
128
|
+
* ]
|
|
129
|
+
* })
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* // Monorepo 内部开发(高级用法 - 自定义路径)
|
|
133
|
+
* import { SunyardSzyyUIResolver } from '@sunyard-szyy-ui/utils';
|
|
134
|
+
* import { fileURLToPath, URL } from 'node:url';
|
|
135
|
+
*
|
|
136
|
+
* Components({
|
|
137
|
+
* resolvers: [
|
|
138
|
+
* SunyardSzyyUIResolver({
|
|
139
|
+
* dirResolver: (name) => ({
|
|
140
|
+
* componentPath: fileURLToPath(
|
|
141
|
+
* new URL(`./packages/components/src/${name}/index.ts`, import.meta.url)
|
|
142
|
+
* ),
|
|
143
|
+
* stylePath: fileURLToPath(
|
|
144
|
+
* new URL(`./packages/components/src/${name}/style/css.ts`, import.meta.url)
|
|
145
|
+
* )
|
|
146
|
+
* })
|
|
147
|
+
* })
|
|
148
|
+
* ]
|
|
149
|
+
* })
|
|
150
|
+
*/
|
|
151
|
+
declare function SunyardSzyyUIResolver(options?: SunyardSzyyUIResolverOptions): ComponentResolver;
|
|
152
|
+
|
|
153
|
+
type SFCWithInstall<T> = T & {
|
|
154
|
+
install(app: vue.App): void;
|
|
155
|
+
};
|
|
156
|
+
declare function withInstall<T>(component: T & {
|
|
157
|
+
name?: string;
|
|
158
|
+
}): SFCWithInstall<T>;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 防抖函数
|
|
162
|
+
* @param fn 要防抖的函数
|
|
163
|
+
* @param delay 延迟时间(毫秒)
|
|
164
|
+
* @returns 防抖后的函数
|
|
165
|
+
*/
|
|
166
|
+
declare function debounce<T extends (...args: any[]) => any>(fn: T, delay?: number): (...args: Parameters<T>) => void;
|
|
167
|
+
/**
|
|
168
|
+
* 节流函数
|
|
169
|
+
* @param fn 要节流的函数
|
|
170
|
+
* @param delay 延迟时间(毫秒)
|
|
171
|
+
* @returns 节流后的函数
|
|
172
|
+
*/
|
|
173
|
+
declare function throttle<T extends (...args: any[]) => any>(fn: T, delay?: number): (...args: Parameters<T>) => void;
|
|
174
|
+
/**
|
|
175
|
+
* 格式化日期
|
|
176
|
+
* @param date 日期对象或时间戳
|
|
177
|
+
* @param format 格式化字符串,默认 'YYYY-MM-DD HH:mm:ss'
|
|
178
|
+
* @returns 格式化后的日期字符串
|
|
179
|
+
*/
|
|
180
|
+
declare function formatDate(date: Date | number, format?: string): string;
|
|
181
|
+
/**
|
|
182
|
+
* 深拷贝
|
|
183
|
+
* @param obj 要拷贝的对象
|
|
184
|
+
* @returns 拷贝后的对象
|
|
185
|
+
*/
|
|
186
|
+
declare function deepClone<T>(obj: T): T;
|
|
187
|
+
|
|
188
|
+
export { type ComponentResolveResult, type ComponentResolver, type SFCWithInstall, SunyardSzyyUIResolver, type SunyardSzyyUIResolverOptions, debounce, deepClone, formatDate, throttle, withInstall };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import * as vue from 'vue';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 组件解析器类型(兼容 unplugin-vue-components)
|
|
5
|
+
*/
|
|
6
|
+
interface ComponentResolver {
|
|
7
|
+
type: 'component' | 'directive';
|
|
8
|
+
resolve: (name: string) => ComponentResolveResult | void | null | undefined;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 组件解析结果
|
|
12
|
+
*/
|
|
13
|
+
interface ComponentResolveResult {
|
|
14
|
+
name?: string;
|
|
15
|
+
from: string;
|
|
16
|
+
sideEffects?: string | string[];
|
|
17
|
+
[key: string]: any;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolver 配置选项
|
|
21
|
+
*/
|
|
22
|
+
interface SunyardSzyyUIResolverOptions {
|
|
23
|
+
/**
|
|
24
|
+
* 组件前缀
|
|
25
|
+
* @default 'Sy'
|
|
26
|
+
*/
|
|
27
|
+
prefix?: string;
|
|
28
|
+
/**
|
|
29
|
+
* 是否导入样式
|
|
30
|
+
* @default true
|
|
31
|
+
*/
|
|
32
|
+
importStyle?: boolean | 'css' | 'scss';
|
|
33
|
+
/**
|
|
34
|
+
* 组件库名称
|
|
35
|
+
* @default 'sunyard-szyy-ui'
|
|
36
|
+
*/
|
|
37
|
+
libraryName?: string;
|
|
38
|
+
/**
|
|
39
|
+
* 样式包名称
|
|
40
|
+
* @default '@sunyard-szyy-ui/theme-chalk'
|
|
41
|
+
*/
|
|
42
|
+
styleLibraryName?: string;
|
|
43
|
+
/**
|
|
44
|
+
* 组件目录名称
|
|
45
|
+
* @default '@sunyard-szyy-ui/components'
|
|
46
|
+
*/
|
|
47
|
+
componentsLibraryName?: string;
|
|
48
|
+
/**
|
|
49
|
+
* 是否为源码开发模式(monorepo 内部开发)
|
|
50
|
+
*
|
|
51
|
+
* 启用后会自动使用 monorepo 源码路径,无需手动配置 dirResolver
|
|
52
|
+
*
|
|
53
|
+
* @default false
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* // 在 monorepo 开发环境中使用
|
|
57
|
+
* import { fileURLToPath } from 'node:url';
|
|
58
|
+
*
|
|
59
|
+
* SunyardSzyyUIResolver({
|
|
60
|
+
* devMode: true,
|
|
61
|
+
* importMetaUrl: import.meta.url,
|
|
62
|
+
* fileURLToPath: fileURLToPath
|
|
63
|
+
* })
|
|
64
|
+
*/
|
|
65
|
+
devMode?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* import.meta.url(devMode 启用时必须提供)
|
|
68
|
+
*
|
|
69
|
+
* 用于解析 monorepo 源码的绝对路径
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* import.meta.url
|
|
73
|
+
*/
|
|
74
|
+
importMetaUrl?: string;
|
|
75
|
+
/**
|
|
76
|
+
* fileURLToPath 函数(devMode 启用时必须提供)
|
|
77
|
+
*
|
|
78
|
+
* 用于将 URL 转换为文件系统路径
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* import { fileURLToPath } from 'node:url';
|
|
82
|
+
* // 然后传入: fileURLToPath: fileURLToPath
|
|
83
|
+
*/
|
|
84
|
+
fileURLToPath?: (url: string | URL) => string;
|
|
85
|
+
/**
|
|
86
|
+
* 自定义目录解析器(高级用法,一般不需要)
|
|
87
|
+
*
|
|
88
|
+
* 如果提供了此选项,会覆盖 devMode 的默认行为
|
|
89
|
+
*
|
|
90
|
+
* @deprecated 推荐使用 devMode + importMetaUrl 替代
|
|
91
|
+
*/
|
|
92
|
+
dirResolver?: (name: string) => {
|
|
93
|
+
/**
|
|
94
|
+
* 组件源码路径(开发模式使用)
|
|
95
|
+
*/
|
|
96
|
+
componentPath?: string;
|
|
97
|
+
/**
|
|
98
|
+
* 样式源码路径(开发模式使用)
|
|
99
|
+
*/
|
|
100
|
+
stylePath?: string;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* sunyard-szyy-ui 组件自动导入 resolver
|
|
105
|
+
*
|
|
106
|
+
* 支持组件和样式的按需自动导入,适用于:
|
|
107
|
+
* - ✅ 外部项目使用(npm 包方式)
|
|
108
|
+
* - ✅ Monorepo 内部开发(源码方式)
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* // 外部项目使用(默认配置)
|
|
112
|
+
* import { SunyardSzyyUIResolver } from '@sunyard-szyy-ui/utils';
|
|
113
|
+
*
|
|
114
|
+
* Components({
|
|
115
|
+
* resolvers: [SunyardSzyyUIResolver()]
|
|
116
|
+
* })
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* // Monorepo 内部开发(推荐方式 - 简化配置)
|
|
120
|
+
* import { SunyardSzyyUIResolver } from '@sunyard-szyy-ui/utils';
|
|
121
|
+
*
|
|
122
|
+
* Components({
|
|
123
|
+
* resolvers: [
|
|
124
|
+
* SunyardSzyyUIResolver({
|
|
125
|
+
* devMode: true,
|
|
126
|
+
* importMetaUrl: import.meta.url
|
|
127
|
+
* })
|
|
128
|
+
* ]
|
|
129
|
+
* })
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* // Monorepo 内部开发(高级用法 - 自定义路径)
|
|
133
|
+
* import { SunyardSzyyUIResolver } from '@sunyard-szyy-ui/utils';
|
|
134
|
+
* import { fileURLToPath, URL } from 'node:url';
|
|
135
|
+
*
|
|
136
|
+
* Components({
|
|
137
|
+
* resolvers: [
|
|
138
|
+
* SunyardSzyyUIResolver({
|
|
139
|
+
* dirResolver: (name) => ({
|
|
140
|
+
* componentPath: fileURLToPath(
|
|
141
|
+
* new URL(`./packages/components/src/${name}/index.ts`, import.meta.url)
|
|
142
|
+
* ),
|
|
143
|
+
* stylePath: fileURLToPath(
|
|
144
|
+
* new URL(`./packages/components/src/${name}/style/css.ts`, import.meta.url)
|
|
145
|
+
* )
|
|
146
|
+
* })
|
|
147
|
+
* })
|
|
148
|
+
* ]
|
|
149
|
+
* })
|
|
150
|
+
*/
|
|
151
|
+
declare function SunyardSzyyUIResolver(options?: SunyardSzyyUIResolverOptions): ComponentResolver;
|
|
152
|
+
|
|
153
|
+
type SFCWithInstall<T> = T & {
|
|
154
|
+
install(app: vue.App): void;
|
|
155
|
+
};
|
|
156
|
+
declare function withInstall<T>(component: T & {
|
|
157
|
+
name?: string;
|
|
158
|
+
}): SFCWithInstall<T>;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 防抖函数
|
|
162
|
+
* @param fn 要防抖的函数
|
|
163
|
+
* @param delay 延迟时间(毫秒)
|
|
164
|
+
* @returns 防抖后的函数
|
|
165
|
+
*/
|
|
166
|
+
declare function debounce<T extends (...args: any[]) => any>(fn: T, delay?: number): (...args: Parameters<T>) => void;
|
|
167
|
+
/**
|
|
168
|
+
* 节流函数
|
|
169
|
+
* @param fn 要节流的函数
|
|
170
|
+
* @param delay 延迟时间(毫秒)
|
|
171
|
+
* @returns 节流后的函数
|
|
172
|
+
*/
|
|
173
|
+
declare function throttle<T extends (...args: any[]) => any>(fn: T, delay?: number): (...args: Parameters<T>) => void;
|
|
174
|
+
/**
|
|
175
|
+
* 格式化日期
|
|
176
|
+
* @param date 日期对象或时间戳
|
|
177
|
+
* @param format 格式化字符串,默认 'YYYY-MM-DD HH:mm:ss'
|
|
178
|
+
* @returns 格式化后的日期字符串
|
|
179
|
+
*/
|
|
180
|
+
declare function formatDate(date: Date | number, format?: string): string;
|
|
181
|
+
/**
|
|
182
|
+
* 深拷贝
|
|
183
|
+
* @param obj 要拷贝的对象
|
|
184
|
+
* @returns 拷贝后的对象
|
|
185
|
+
*/
|
|
186
|
+
declare function deepClone<T>(obj: T): T;
|
|
187
|
+
|
|
188
|
+
export { type ComponentResolveResult, type ComponentResolver, type SFCWithInstall, SunyardSzyyUIResolver, type SunyardSzyyUIResolverOptions, debounce, deepClone, formatDate, throttle, withInstall };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// src/resolver.ts
|
|
2
|
+
function pascalToKebab(str, prefix = "Sy") {
|
|
3
|
+
return str.slice(prefix.length).replace(/([A-Z])/g, "-$1").toLowerCase().slice(1);
|
|
4
|
+
}
|
|
5
|
+
function SunyardSzyyUIResolver(options = {}) {
|
|
6
|
+
const {
|
|
7
|
+
prefix = "Sy",
|
|
8
|
+
importStyle = true,
|
|
9
|
+
libraryName = "sunyard-szyy-ui",
|
|
10
|
+
styleLibraryName = "@sunyard-szyy-ui/theme-chalk",
|
|
11
|
+
componentsLibraryName = "@sunyard-szyy-ui/components",
|
|
12
|
+
devMode = false,
|
|
13
|
+
importMetaUrl,
|
|
14
|
+
fileURLToPath,
|
|
15
|
+
dirResolver
|
|
16
|
+
} = options;
|
|
17
|
+
if (devMode && !dirResolver) {
|
|
18
|
+
if (!importMetaUrl || !fileURLToPath) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
"[SunyardSzyyUIResolver] devMode \u542F\u7528\u65F6\u5FC5\u987B\u63D0\u4F9B importMetaUrl \u548C fileURLToPath \u53C2\u6570\n\u793A\u4F8B\uFF1A\nimport { fileURLToPath } from 'node:url';\nSunyardSzyyUIResolver({ devMode: true, importMetaUrl: import.meta.url, fileURLToPath })"
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
let actualDirResolver = dirResolver;
|
|
25
|
+
if (devMode && importMetaUrl && fileURLToPath && !dirResolver) {
|
|
26
|
+
actualDirResolver = (name) => {
|
|
27
|
+
const styleFile = importStyle === "scss" ? "index.ts" : "css.ts";
|
|
28
|
+
return {
|
|
29
|
+
componentPath: fileURLToPath(new URL(`../packages/components/src/${name}/index.ts`, importMetaUrl)),
|
|
30
|
+
stylePath: fileURLToPath(new URL(`../packages/components/src/${name}/style/${styleFile}`, importMetaUrl))
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
type: "component",
|
|
36
|
+
resolve: (name) => {
|
|
37
|
+
if (name.startsWith(prefix)) {
|
|
38
|
+
const componentName = pascalToKebab(name, prefix);
|
|
39
|
+
if (actualDirResolver) {
|
|
40
|
+
const paths = actualDirResolver(componentName);
|
|
41
|
+
if (paths.componentPath) {
|
|
42
|
+
return {
|
|
43
|
+
name,
|
|
44
|
+
from: paths.componentPath,
|
|
45
|
+
sideEffects: importStyle && paths.stylePath ? paths.stylePath : void 0
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const result = {
|
|
50
|
+
name,
|
|
51
|
+
from: libraryName
|
|
52
|
+
};
|
|
53
|
+
if (importStyle) {
|
|
54
|
+
if (importStyle === "css") {
|
|
55
|
+
result.sideEffects = `${styleLibraryName}/${componentName}.css`;
|
|
56
|
+
} else if (importStyle === "scss") {
|
|
57
|
+
result.sideEffects = `${styleLibraryName}/src/${componentName}.scss`;
|
|
58
|
+
} else if (importStyle === true) {
|
|
59
|
+
result.sideEffects = `${styleLibraryName}/${componentName}.css`;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/index.ts
|
|
69
|
+
function withInstall(component) {
|
|
70
|
+
const c = component;
|
|
71
|
+
c.install = (app) => {
|
|
72
|
+
const name = component.name;
|
|
73
|
+
if (!name) return;
|
|
74
|
+
app.component(name, component);
|
|
75
|
+
};
|
|
76
|
+
return c;
|
|
77
|
+
}
|
|
78
|
+
function debounce(fn, delay = 300) {
|
|
79
|
+
let timer = null;
|
|
80
|
+
return function(...args) {
|
|
81
|
+
if (timer) {
|
|
82
|
+
clearTimeout(timer);
|
|
83
|
+
}
|
|
84
|
+
timer = setTimeout(() => {
|
|
85
|
+
fn.apply(this, args);
|
|
86
|
+
timer = null;
|
|
87
|
+
}, delay);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function throttle(fn, delay = 300) {
|
|
91
|
+
let lastTime = 0;
|
|
92
|
+
return function(...args) {
|
|
93
|
+
const now = Date.now();
|
|
94
|
+
if (now - lastTime >= delay) {
|
|
95
|
+
fn.apply(this, args);
|
|
96
|
+
lastTime = now;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function formatDate(date, format = "YYYY-MM-DD HH:mm:ss") {
|
|
101
|
+
const d = typeof date === "number" ? new Date(date) : date;
|
|
102
|
+
const year = d.getFullYear();
|
|
103
|
+
const month = String(d.getMonth() + 1).padStart(2, "0");
|
|
104
|
+
const day = String(d.getDate()).padStart(2, "0");
|
|
105
|
+
const hours = String(d.getHours()).padStart(2, "0");
|
|
106
|
+
const minutes = String(d.getMinutes()).padStart(2, "0");
|
|
107
|
+
const seconds = String(d.getSeconds()).padStart(2, "0");
|
|
108
|
+
return format.replace("YYYY", String(year)).replace("MM", month).replace("DD", day).replace("HH", hours).replace("mm", minutes).replace("ss", seconds);
|
|
109
|
+
}
|
|
110
|
+
function deepClone(obj) {
|
|
111
|
+
if (obj === null || typeof obj !== "object") {
|
|
112
|
+
return obj;
|
|
113
|
+
}
|
|
114
|
+
if (obj instanceof Date) {
|
|
115
|
+
return new Date(obj.getTime());
|
|
116
|
+
}
|
|
117
|
+
if (obj instanceof Array) {
|
|
118
|
+
return obj.map((item) => deepClone(item));
|
|
119
|
+
}
|
|
120
|
+
if (typeof obj === "object") {
|
|
121
|
+
const clonedObj = {};
|
|
122
|
+
for (const key in obj) {
|
|
123
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
124
|
+
clonedObj[key] = deepClone(obj[key]);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return clonedObj;
|
|
128
|
+
}
|
|
129
|
+
return obj;
|
|
130
|
+
}
|
|
131
|
+
export {
|
|
132
|
+
SunyardSzyyUIResolver,
|
|
133
|
+
debounce,
|
|
134
|
+
deepClone,
|
|
135
|
+
formatDate,
|
|
136
|
+
throttle,
|
|
137
|
+
withInstall
|
|
138
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sunyard-szyy-ui/utils",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.cjs",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"peerDependencies": {
|
|
12
|
+
"vue": "^3.0.0"
|
|
13
|
+
},
|
|
14
|
+
"peerDependenciesMeta": {
|
|
15
|
+
"unplugin-vue-components": {
|
|
16
|
+
"optional": true
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"unplugin-vue-components": "^31.0.0"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"scripts": {
|
|
27
|
+
"clean": "rimraf dist",
|
|
28
|
+
"build": "pnpm clean && tsup src/index.ts --format esm,cjs --dts --out-dir dist --tsconfig tsconfig.build.json",
|
|
29
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
30
|
+
}
|
|
31
|
+
}
|