nhanh-pure-function 1.4.1 → 2.0.1

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 ADMINnhanh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -7,4 +7,13 @@
7
7
  您可以通过 npm 安装该库:
8
8
 
9
9
  ```bash
10
- npm install nhanh-pure-function
10
+ npm install nhanh-pure-function
11
+ ```
12
+
13
+ ## 功能介绍
14
+
15
+ `nhanh-pure-function` 库旨在提供一系列纯函数,这些函数在处理数据时不会产生副作用,确保函数的输入和输出之间的映射关系是确定的。这使得代码更易于测试、维护和复用。
16
+
17
+ ## 许可证
18
+
19
+ [MIT](https://opensource.org/licenses/MIT)
@@ -0,0 +1,82 @@
1
+ export declare const EXTENSION_TO_MIME: {
2
+ ".mp3": string;
3
+ ".mp4": string;
4
+ ".m4a": string;
5
+ ".aac": string;
6
+ ".ogg": string;
7
+ ".wav": string;
8
+ ".flac": string;
9
+ ".opus": string;
10
+ ".webm": string;
11
+ ".avi": string;
12
+ ".mov": string;
13
+ ".wmv": string;
14
+ ".png": string;
15
+ ".jpg": string;
16
+ ".jpeg": string;
17
+ ".gif": string;
18
+ ".bmp": string;
19
+ ".tiff": string;
20
+ ".ico": string;
21
+ ".svg": string;
22
+ ".webp": string;
23
+ ".heif": string;
24
+ ".heic": string;
25
+ ".json": string;
26
+ ".xml": string;
27
+ ".html": string;
28
+ ".htm": string;
29
+ ".css": string;
30
+ ".js": string;
31
+ ".ts": string;
32
+ ".csv": string;
33
+ ".tsv": string;
34
+ ".txt": string;
35
+ ".md": string;
36
+ ".rtf": string;
37
+ ".pdf": string;
38
+ ".zip": string;
39
+ ".rar": string;
40
+ ".tar": string;
41
+ ".gz": string;
42
+ ".7z": string;
43
+ ".exe": string;
44
+ ".apk": string;
45
+ ".doc": string;
46
+ ".docx": string;
47
+ ".xls": string;
48
+ ".xlsx": string;
49
+ ".ppt": string;
50
+ ".pptx": string;
51
+ ".odt": string;
52
+ ".ods": string;
53
+ ".odp": string;
54
+ ".jsonld": string;
55
+ ".yaml": string;
56
+ ".yml": string;
57
+ ".woff": string;
58
+ ".woff2": string;
59
+ ".ttf": string;
60
+ ".otf": string;
61
+ ".eot": string;
62
+ ".map": string;
63
+ };
64
+ export declare const FILE_EXTENSIONS: {
65
+ image: string[];
66
+ ppt: string[];
67
+ word: string[];
68
+ excel: string[];
69
+ pdf: string[];
70
+ text: string[];
71
+ audio: string[];
72
+ video: string[];
73
+ archive: string[];
74
+ code: string[];
75
+ font: string[];
76
+ database: string[];
77
+ markup: string[];
78
+ configuration: string[];
79
+ logs: string[];
80
+ script: string[];
81
+ };
82
+ export declare const UNIT_LABELS: string[];
@@ -0,0 +1,60 @@
1
+ import { Point } from './type';
2
+ /**
3
+ * 转为百分比字符串
4
+ * @param value 分子
5
+ * @param totalValue 分母
6
+ * @param decimalPlaces 保留小数位
7
+ * @returns 10.00%
8
+ */
9
+ export declare function _ConvertToPercentage(value: number, totalValue: number, decimalPlaces?: number): string;
10
+ /**
11
+ * 误差范围
12
+ * @param value 需要判断的数字
13
+ * @param target 目标数字
14
+ * @param errorMargin 正负误差范围
15
+ * @returns 是否在误差内
16
+ */
17
+ export declare function _IsWithinErrorMargin(value: number, target: number, errorMargin: number): boolean;
18
+ /**
19
+ * 进度
20
+ * @param {(schedule)=>void} callback callback( 进度百分比 )
21
+ * @param {Number} TIME 总时长
22
+ */
23
+ export declare function _Schedule(callback: (schedule: number) => void, TIME?: number): void;
24
+ /**
25
+ * 格式化数字,给数字加上千位分隔符。
26
+ * @param {number} number - 要格式化的数字。
27
+ * @returns {string} - 格式化后的字符串。
28
+ */
29
+ export declare function _FormatNumber(number: number): string;
30
+ /**
31
+ * 将纯数字转换为带单位的数字格式
32
+ *
33
+ * @param value - 要转换的数字或字符串形式的数字
34
+ * @param config - 配置对象
35
+ * @param config.join - 是否将数字和单位拼接成一个字符串,默认为 `false`
36
+ * @param config.suffix - 单位后缀,默认为 `万`
37
+ * @param config.decimalPlaces - 保留的小数位数,默认为 `2`
38
+ *
39
+ * @returns 返回转换后的结果:
40
+ * - 如果 `config.join` 为 `true`,返回拼接后的字符串,如 "12.34万"
41
+ * - 如果 `config.join` 为 `false`,返回一个数组,如 [ 12.34, '万' ]
42
+ */
43
+ export declare function _FormatNumberWithUnit(value: string | number, config?: {
44
+ join?: boolean;
45
+ suffix?: string;
46
+ decimalPlaces?: number;
47
+ }): string | (string | number)[];
48
+ /**
49
+ * 判断点是否在多边形内
50
+ * @param point - 待检测的点,包含 x 和 y 坐标
51
+ * @param polygon - 多边形的点集,数组形式,每个点包含 x 和 y 坐标
52
+ * @returns boolean - 点是否在多边形内
53
+ */
54
+ export declare function _IsPointInPolygon(point: Point, polygon: Point[]): boolean;
55
+ /**
56
+ * 格式化文件大小
57
+ * @param {number} size
58
+ * @returns string
59
+ */
60
+ export declare function _FormatFileSize(size: number): string;
@@ -0,0 +1,4 @@
1
+ export interface Point {
2
+ x: number;
3
+ y: number;
4
+ }
@@ -0,0 +1,67 @@
1
+ import { DragOption, LocalDragOptions, UiLibrary } from './type';
2
+ /**
3
+ * 滚动结束监听器
4
+ * @param {(trigger: "vertical" | "horizontal") => void} callback
5
+ */
6
+ export declare function _ScrollEndListener(callback: (trigger: "vertical" | "horizontal") => void): (payload: Event) => void;
7
+ /**
8
+ * 点击非指定dom(包含子级dom)时执行 callback
9
+ * @param querySelector 允许点击的 dom 顶层祖先元素选择器
10
+ * @param callback 满足条件时执行的回调
11
+ *
12
+ * @param options 其他配置
13
+ * @param options.uiLibrary 项目使用的 ui库 , 用于排除 ui库 创建的元素 , 避免点击 ui库 创建的元素时意外的执行 callback
14
+ * @param options.isClickAllowed 是否允许该点击 ( 如果不确定可以返回 undefined )
15
+ */
16
+ export declare function _CloseOnOutsideClick(querySelector: string[], callback: Function, options?: {
17
+ uiLibrary?: UiLibrary[];
18
+ isClickAllowed?: (event: MouseEvent) => boolean | undefined;
19
+ }): void;
20
+ /** 拖拽dom */
21
+ export declare class _Drag {
22
+ #private;
23
+ init(dom: HTMLElement, option?: DragOption): void;
24
+ finish(): void;
25
+ bindOrUnbindEvent(type: "bind" | "unbind"): void;
26
+ alterLocation(): void;
27
+ mousedown(event: Event): void;
28
+ mousemove(event: Event): void;
29
+ mouseup(): void;
30
+ }
31
+ /** 局部拖拽 计算位置距离/百分比 */
32
+ export declare class _LocalDrag {
33
+ #private;
34
+ init(parentDom: HTMLElement, options?: LocalDragOptions): void;
35
+ finish(): void;
36
+ bindOrUnbindEvent(type: "bind" | "unbind"): void;
37
+ updateValue(): {
38
+ top: number;
39
+ left: number;
40
+ percentage: {
41
+ top: number;
42
+ left: number;
43
+ };
44
+ };
45
+ alterLocation(): void;
46
+ mousedown(event: Event): void;
47
+ mousemove(event: Event): void;
48
+ mouseup(): void;
49
+ }
50
+ /** 进入全屏模式 */
51
+ export declare function _EnterFullscreen(content: HTMLElement): Promise<void>;
52
+ /** 退出全屏模式 */
53
+ export declare function _ExitFullscreen(): Promise<void>;
54
+ /** 判断是否处于全屏模式 */
55
+ export declare function _IsFullscreen(): HTMLElement | undefined;
56
+ /**
57
+ * 返回一个用于切换全屏模式的函数
58
+ * @param {HTMLElement} content - 需要进入全屏的元素
59
+ * 该函数通过检查不同浏览器的特定方法来实现全屏切换
60
+ */
61
+ export declare function _Fullscreen(content: HTMLElement): () => void;
62
+ /**
63
+ * 单位转换 12** -> **px
64
+ * @param {string} width
65
+ * @returns 对应的单位为px的宽
66
+ */
67
+ export declare function _GetOtherSizeInPixels(width: string, target?: HTMLElement): number;
@@ -0,0 +1,33 @@
1
+ export type UiLibrary = "naiveUI" | "ElementPlus" | "Element";
2
+ export type EventFunctionMap = Partial<Record<"mousedown" | "mousemove" | "mouseup" | "click" | "touchstart" | "touchmove" | "touchend" | "touchcancel", (event: Event) => void>>;
3
+ /** 拖拽配置 */
4
+ export type DragOption = {
5
+ /** 拖拽范围限制 */
6
+ limit?: {
7
+ max: {
8
+ top: number;
9
+ left: number;
10
+ };
11
+ min: {
12
+ top: number;
13
+ left: number;
14
+ };
15
+ };
16
+ /** 指定的拖拽元素 */
17
+ dragDom?: HTMLElement;
18
+ };
19
+ /** 更新后的位置信息 */
20
+ export type UpdateValue = {
21
+ top: number;
22
+ left: number;
23
+ percentage?: {
24
+ top: number;
25
+ left: number;
26
+ };
27
+ };
28
+ /** 局部拖拽配置 */
29
+ export type LocalDragOptions = {
30
+ limit?: DragOption["limit"];
31
+ update_move?: (value: UpdateValue) => void | undefined;
32
+ update_up?: (value: UpdateValue) => void | undefined;
33
+ };
@@ -0,0 +1,260 @@
1
+ import { FILE_EXTENSIONS } from '../Constant';
2
+ /**
3
+ * 非null | undefined判断
4
+ * @param value any
5
+ * @returns boolean
6
+ */
7
+ export declare function _NotNull(value: any): boolean;
8
+ /**
9
+ * 是正常对象吗
10
+ * @param {} value
11
+ * @returns boolean
12
+ */
13
+ export declare function _IsObject(value: any): boolean;
14
+ /**
15
+ * 寻找空闲时机执行传入方法
16
+ * @param callback 需执行的方法
17
+ */
18
+ export declare function _ExecuteWhenIdle(callback: Function): void;
19
+ /**
20
+ * 等待条件满足
21
+ * @param conditionChecker 条件检查器
22
+ * @param timeoutMillis 超时毫秒数
23
+ * @returns Promise<unknown>
24
+ */
25
+ export declare function _WaitForCondition(conditionChecker: () => boolean, timeoutMillis: number): Promise<"完成" | "超时">;
26
+ /**
27
+ * 排除子串
28
+ * @param inputString 需裁剪字符串
29
+ * @param substringToDelete 被裁减字符串
30
+ * @param delimiter 分隔符
31
+ * @returns 裁减后的字符串
32
+ */
33
+ export declare function _ExcludeSubstring(inputString: string, substringToDelete: string, delimiter?: string): string;
34
+ /**
35
+ * 首字母大写
36
+ * @param str
37
+ * @returns string
38
+ */
39
+ export declare function _CapitalizeFirstLetter(string: string): string;
40
+ /**
41
+ * 合并对象 注意: 本函数会直接操作 A
42
+ * @param {Object | Array} A
43
+ * @param {Object | Array} B
44
+ * @returns (A & B) | A | B | undefined
45
+ */
46
+ export declare function _MergeObjects<T, T1>(A: T, B: T1, visitedObjects?: [any, any][], outTime?: number): (T & T1) | T | T1 | undefined;
47
+ /**
48
+ * 时间戳转换字符串
49
+ * @param {Number | Date} time 时间戳或Date对象
50
+ * @param {String} template 完整模板 --> YYYY MM DD hh mm ss ms
51
+ * @param {Boolean} pad 补0
52
+ */
53
+ export declare function _TimeTransition(time: number | Date, template?: string, pad?: boolean): string;
54
+ /**
55
+ * 读取文件
56
+ * @param src 文件地址
57
+ * @returns 文件的字符串内容
58
+ */
59
+ export declare function _ReadFile(src: string): Promise<string>;
60
+ /**
61
+ * 从给定的href中提取名称部分
62
+ * 该函数旨在处理URL字符串,并返回URL路径的最后一部分,去除查询参数
63
+ *
64
+ * @param {string} href - 待处理的URL字符串
65
+ * @param {string} [defaultName="file"] - 默认的文件名,当无法提取时使用
66
+ * @returns {string} URL路径的最后一部分,不包括查询参数
67
+ */
68
+ export declare function _GetHrefName(href: string, defaultName?: string): string;
69
+ /**
70
+ * 下载文件
71
+ * @param {string} href - 文件路径
72
+ * @param {string} [fileName] - 导出文件名
73
+ */
74
+ export declare function _DownloadFile(href: string, fileName?: string): Promise<unknown>;
75
+ /**
76
+ * 获取帧率
77
+ * @param {(fps , frameTime)=>void} callback callback( 帧率 , 每帧时间 )
78
+ * @param {Number} referenceNode 参考节点数量
79
+ */
80
+ export declare function _GetFrameRate(callback: (fps: number, frameTime: number) => void, referenceNode?: number): void;
81
+ /**
82
+ * 驼峰命名
83
+ * @param {字符串} str
84
+ * @param {是否删除分割字符} isRemoveDelimiter
85
+ * @returns 'wq1wqw-qw2qw' -> 'wq1Wqw-Qw2Qw' / 'wqWqwQwQw'
86
+ */
87
+ export declare function _ConvertToCamelCase(str: string, isRemoveDelimiter?: boolean): string;
88
+ /**
89
+ * 创建文件并下载
90
+ * @param {BlobPart[]} content 文件内容
91
+ * @param {string} fileName 文件名称
92
+ * @param {BlobPropertyBag} options Blob 配置
93
+ */
94
+ export declare function _CreateAndDownloadFile(content: BlobPart[], fileName: string, options?: BlobPropertyBag): void;
95
+ /**
96
+ * 获取url参数
97
+ * @param {string} url
98
+ * @returns {Object}
99
+ */
100
+ export declare function _GetQueryParams(url: string): Record<string, string>;
101
+ /**
102
+ * 生成一个UUID(通用唯一标识符)字符串
103
+ * 可以选择性地在UUID前面添加前缀
104
+ *
105
+ * @param {string} prefix - 可选参数,要添加到UUID前面的前缀
106
+ * @returns {string} 一个带有可选前缀的UUID字符串
107
+ */
108
+ export declare function _GenerateUUID(prefix?: string): string;
109
+ /**
110
+ * 防抖
111
+ * @param {Function} fn
112
+ * @param {number} delay
113
+ * @returns {Function}
114
+ */
115
+ export declare function _Debounce<T extends (...args: any[]) => void>(fn: T, delay: number): (...args: Parameters<T>) => void;
116
+ /**
117
+ * 节流
118
+ * @param {Function} fn
119
+ * @param {number} delay
120
+ * @returns {Function}
121
+ */
122
+ export declare function _Throttle<T extends (...args: any[]) => void>(fn: T, delay: number): (...args: Parameters<T>) => void;
123
+ /**
124
+ * 数据类型
125
+ * @param {any} value
126
+ * @returns string
127
+ */
128
+ export declare function _DataType(value: any): "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | "array" | "null";
129
+ /**
130
+ * 复制到剪贴板
131
+ * @param {string} text
132
+ */
133
+ export declare function _CopyToClipboard(text: string): Promise<void>;
134
+ /**
135
+ * 根据路径初始化目标对象
136
+ * 如果路径中某个属性不存在,则会创建该属性及其所有父属性
137
+ * 最终返回路径的最后一个属性对应的值或undefined(如果路径不存在)
138
+ *
139
+ * @param {Object} model - 要初始化的模型对象
140
+ * @param {string} path - 属性路径,使用英文句点分隔
141
+ * @returns {any} 路径的最后一个属性对应的值或undefined
142
+ */
143
+ export declare function _InitTargetByPath(model: any, path: string): any;
144
+ /**
145
+ * 根据路径获取目标对象
146
+ * 该函数用于在给定的模型中,通过路径字符串来获取深层嵌套的目标对象如果路径中的某一部分不存在,则会创建一个新的对象(除非已经是路径的最后一部分)
147
+ *
148
+ * @param {Object} model - 包含要查询的数据的模型对象
149
+ * @param {string} path - 用点分隔的路径字符串,表示要访问的对象属性路径
150
+ * @returns {Object|undefined} - 返回目标对象,如果路径不存在则返回undefined
151
+ */
152
+ export declare function _GetTargetByPath(model: any, path: string): any;
153
+ /**
154
+ * 根据路径更新目标值
155
+ *
156
+ * 该函数通过一个点分隔的路径来更新一个对象中的嵌套属性值
157
+ * 它使用了reduce方法来遍历路径数组,并在路径的终点设置新的值
158
+ *
159
+ * @param {Object} model - 包含要更新数据的模型对象
160
+ * @param {string} path - 点分隔的字符串路径,指示如何到达目标属性
161
+ * @param {*} value - 要设置的新值
162
+ * @returns {*} - 返回更新后的模型对象中的值
163
+ */
164
+ export declare function _UpdateTargetByPath(model: any, path: string, value: any): any;
165
+ /**
166
+ * 使用 XMLHttpRequest 检查指定 URL 的连接状态
167
+ *
168
+ * 此函数通过发送一个 HEAD 请求来检查给定 URL 是否可访问 HEAD 请求仅请求文档头部信息,
169
+ * 而不是整个页面,因此比 GET 或 POST 请求更快此方法常用于检查 URL 是否有效,以及服务器的响应时间等
170
+ *
171
+ * @param {string} url - 需要检查连接的 URL 地址
172
+ * @returns {Promise} - 返回一个 Promise 对象,该对象在连接成功时解析,在连接失败时拒绝
173
+ */
174
+ export declare function _CheckConnectionWithXHR(url: string): Promise<unknown>;
175
+ /**
176
+ * 判断给定URL是否指向一个安全上下文
177
+ *
178
+ * 安全上下文是指通过一系列安全协议访问的资源,这些协议提供了数据的加密传输和身份验证
179
+ * 本函数通过检查URL的协议前缀来判断是否属于安全上下文
180
+ *
181
+ * @param {string} url - 待检查的URL字符串
182
+ * @returns {boolean} - 如果URL指向安全上下文,则返回true;否则返回false
183
+ */
184
+ export declare function _IsSecureContext(url: string): boolean;
185
+ type FileType = keyof typeof FILE_EXTENSIONS;
186
+ /**
187
+ * 文件类型检查器类
188
+ * 用于检查文件URL的类型
189
+ */
190
+ export declare class _FileTypeChecker {
191
+ static cachedEntries: [FileType, string[]][];
192
+ /**
193
+ * 检查给定URL的文件类型
194
+ * @param {string} url - 文件的URL
195
+ * @param {string} [type] - 可选参数,指定要检查的文件类型
196
+ * @returns {string} - 如果URL与指定类型或任何已知类型匹配,则返回文件类型,否则返回"unknown"
197
+ */
198
+ static check(url: string): FileType | "unknown";
199
+ static check(url: string, type: FileType): boolean;
200
+ /**
201
+ * 静态方法,用于解析地址信息
202
+ * 该方法接受一个URL字符串,将其解析为一个包含地址详情的对象数组
203
+ * 主要用于批量处理以逗号分隔的URL列表,为每个URL生成相应的名称和类型
204
+ *
205
+ * @param {string} url - 以逗号分隔的URL字符串,每个URL代表一个资源的位置
206
+ * @returns {Array} - 包含每个URL及其相关信息(名称和类型)的对象数组
207
+ */
208
+ static parseAddresses(url: string): {
209
+ url: string;
210
+ name: string;
211
+ type: "audio" | "code" | "script" | "video" | "image" | "ppt" | "word" | "excel" | "pdf" | "text" | "archive" | "font" | "database" | "markup" | "configuration" | "logs" | "unknown";
212
+ }[];
213
+ /**
214
+ * 检查 MIME 类型是否与指定的模式匹配
215
+ * @param {string} type - 要检查的 MIME 类型(如 "image/png")
216
+ * @param {string} [accept] - 可接受的 MIME 类型模式(如 "image/*, text/plain")
217
+ * @returns {boolean} - 如果类型匹配,则返回 true,否则返回 false
218
+ */
219
+ static matchesMimeType(type: string, accept?: string): boolean;
220
+ /**
221
+ * 类型标准化函数
222
+ * 该函数旨在将文件类型或MIME类型字符串转换为标准格式
223
+ * 主要处理三种情况:带扩展名的字符串、简写格式的类型以及已标准格式的类型
224
+ *
225
+ * @param {string} type - 文件类型或MIME类型字符串
226
+ * @returns {string} 标准化的MIME类型字符串,如果无法识别则返回原始输入
227
+ */
228
+ static _normalizeType(type: string): string;
229
+ /**
230
+ * 检查URL是否具有任何指定的文件扩展名
231
+ * @param {string} url - 文件的URL
232
+ * @param {string[]} validExtensions - 有效文件扩展名的数组
233
+ * @returns {boolean} - 如果URL具有任何指定的文件扩展名,则返回true,否则返回false
234
+ */
235
+ static _checkExtension(url: string, validExtensions: string[]): boolean;
236
+ /**
237
+ * 检测文件URL的类型
238
+ * @param {string} url - 文件的URL
239
+ * @returns {string} - 如果URL与任何已知类型匹配,则返回文件类型,否则返回"unknown"
240
+ */
241
+ static _detectFileType(url: string): "audio" | "code" | "script" | "video" | "image" | "ppt" | "word" | "excel" | "pdf" | "text" | "archive" | "font" | "database" | "markup" | "configuration" | "logs" | "unknown";
242
+ }
243
+ /**
244
+ * 旋转列表函数
245
+ *
246
+ * 该函数接受一个列表作为参数,并返回一个二维数组,其中每个内部数组都是原列表的一种旋转形式
247
+ * 旋转列表的原理是将原列表分割成两部分,并将这两部分重新组合,形成一个新的列表
248
+ *
249
+ * @param list T[] - 需要旋转的列表,列表元素类型为泛型T
250
+ * @returns T[][] - 返回一个二维数组,每个内部数组代表原列表的一种旋转形式
251
+ */
252
+ export declare function _RotateList<T>(list: T[]): T[][];
253
+ /**
254
+ * 克隆给定值的函数
255
+ * 该函数尝试使用window.structuredClone方法进行深克隆,如果失败则使用自定义方法
256
+ * @param {any} val - 需要克隆的值
257
+ * @returns {any} - 克隆后的值
258
+ */
259
+ export declare function _Clone<T>(val: T): T | {} | undefined;
260
+ export {};
File without changes
@@ -0,0 +1 @@
1
+ "use strict";var Z=Object.defineProperty;var A=n=>{throw TypeError(n)};var K=(n,t,e)=>t in n?Z(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var Y=(n,t,e)=>K(n,typeof t!="symbol"?t+"":t,e),$=(n,t,e)=>t.has(n)||A("Cannot "+e);var s=(n,t,e)=>($(n,t,"read from private field"),e?e.call(n):t.get(n)),d=(n,t,e)=>t.has(n)?A("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(n):t.set(n,e),l=(n,t,e,o)=>($(n,t,"write to private field"),o?o.call(n,e):t.set(n,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const J={".mp3":"audio/mpeg",".mp4":"video/mp4",".m4a":"audio/mp4",".aac":"audio/aac",".ogg":"audio/ogg",".wav":"audio/wav",".flac":"audio/flac",".opus":"audio/opus",".webm":"video/webm",".avi":"video/x-msvideo",".mov":"video/quicktime",".wmv":"video/x-ms-wmv",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".bmp":"image/bmp",".tiff":"image/tiff",".ico":"image/vnd.microsoft.icon",".svg":"image/svg+xml",".webp":"image/webp",".heif":"image/heif",".heic":"image/heic",".json":"application/json",".xml":"application/xml",".html":"text/html",".htm":"text/html",".css":"text/css",".js":"application/javascript",".ts":"application/typescript",".csv":"text/csv",".tsv":"text/tab-separated-values",".txt":"text/plain",".md":"text/markdown",".rtf":"application/rtf",".pdf":"application/pdf",".zip":"application/zip",".rar":"application/x-rar-compressed",".tar":"application/x-tar",".gz":"application/gzip",".7z":"application/x-7z-compressed",".exe":"application/x-msdownload",".apk":"application/vnd.android.package-archive",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".odt":"application/vnd.oasis.opendocument.text",".ods":"application/vnd.oasis.opendocument.spreadsheet",".odp":"application/vnd.oasis.opendocument.presentation",".jsonld":"application/ld+json",".yaml":"application/x-yaml",".yml":"application/x-yaml",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".map":"application/json"},N={image:[".jpg",".jpeg",".png",".gif",".bmp",".webp",".tiff",".svg",".heif",".heic",".ico",".raw",".jfif",".avif",".png8",".indd",".eps",".ai"],ppt:[".ppt",".pptx",".odp"],word:[".doc",".docx",".odt",".rtf"],excel:[".xls",".xlsx",".ods",".csv",".tsv"],pdf:[".pdf"],text:[".txt",".csv",".md",".json",".yaml",".yml",".log",".ini",".rtf"],audio:[".mp3",".wav",".ogg",".flac",".aac",".wma",".m4a",".alac",".ape",".opus",".amr",".ra",".mid",".midi",".aiff",".pcm",".au",".wavpack",".spx"],video:[".mp4",".avi",".mkv",".mov",".wmv",".flv",".webm",".mpg",".mpeg",".3gp",".vob",".ogv",".m4v",".ts",".rm",".rmvb",".m2ts",".divx",".xvid",".swf",".f4v"],archive:[".zip",".rar",".tar",".gz",".bz2",".xz",".7z",".tar.gz",".tar.bz2",".tar.xz",".tar.lz",".tar.lzma",".cab",".iso",".dmg",".tgz",".apk",".gz2",".tar.zst"],code:[".js",".ts",".py",".java",".cpp",".c",".html",".css",".scss",".less",".sass",".php",".rb",".go",".swift",".rs",".kt",".scala",".lua",".pl",".m",".h",".xml",".json",".yaml",".yml",".toml",".vue",".ejs",".handlebars",".jinja",".dart"],font:[".woff",".woff2",".ttf",".otf",".eot",".svg",".ttc",".fnt",".fon",".otc"],database:[".sql",".sqlite",".db",".mdb",".accdb",".jsonld",".xml",".csv"],markup:[".html",".htm",".xhtml",".xml",".json",".yaml",".yml"],configuration:[".ini",".conf",".cfg",".env",".properties",".json",".toml"],logs:[".log",".err",".trace",".out"],script:[".bash",".sh",".zsh",".bat",".ps1",".vbs",".cmd",".sed",".awk",".php"]},W=["","万","亿","兆","京","垓","秭","穰","沟","涧","正","载","极"];function ee(n){return n!=null}function te(n){return!(n===null||typeof n!="object"||Array.isArray(n))}function ne(n){if(typeof n!="function")return console.error("非函数:",n);const t=function(e){e.didTimeout||e.timeRemaining()<=0?requestIdleCallback(t):n()};requestIdleCallback(t)}function oe(n,t){const e=+new Date;return new Promise((o,i)=>{const r=()=>{if(+new Date-e>=t)return i("超时");if(n())return o("完成");requestIdleCallback(r)};r()})}function ie(n,t,e=","){const o=new RegExp(`(^|${e})${t}(${e}|$)`,"g");return n.replace(o,function(i,r,a){return r===a?e:""})}function re(n){return n.charAt(0).toUpperCase()+n.slice(1)}function z(n,t,e=[],o=+new Date){if(o<+new Date-300){console.error("_MergeObjects 合并异常:疑似死循环");return}const i=c=>Array.isArray(c)?"array":typeof c,r=i(n),a=i(t);if(r!=a)return t;if(r=="object"||r=="array"){if(e.some(([c,m])=>c==n&&m==t))return n;if(e.push([n,t]),r=="object"){for(const c in t)if(Object.prototype.hasOwnProperty.call(t,c)){const m=t[c],u=n[c],p=z(u,m,e,o);n[c]=p}return n}else if(r=="array")return t.forEach((c,m)=>{const u=c,p=n[m],f=z(p,u,e,o);n[m]=f}),n}else return t}function se(n,t="YYYY-MM-DD hh:mm:ss",e=!0){const o=new Date(n);if(isNaN(o.getTime()))return console.error("Invalid date"),"";const i={YYYY:r=>r.getFullYear(),MM:r=>r.getMonth()+1,DD:r=>r.getDate(),hh:r=>r.getHours(),mm:r=>r.getMinutes(),ss:r=>r.getSeconds(),ms:r=>r.getMilliseconds()};return t.replace(/YYYY|MM|DD|hh|mm|ss|ms/g,r=>{const a=i[r](o);return e?String(a).padStart(2,"0"):String(a)})}function ae(n){return new Promise((t,e)=>{fetch(n).then(o=>t(o.text())).catch(o=>{console.error("Error fetching :",o),e(o)})})}function O(n,t="file"){if(!n||(n=String(n).trim(),n===""))return t;const e=n.split("/");return e[e.length-1].split("?")[0]}function ce(n,t){return new Promise((e,o)=>{try{t=t||O(n,"downloaded_file"),fetch(n).then(i=>(i.ok||o(`文件下载失败,状态码: ${i.status}`),i.blob())).then(i=>{const r=URL.createObjectURL(i),a=document.createElement("a");a.href=r,a.download=decodeURIComponent(t),document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(r),e(i)}).catch(o)}catch(i){o(i)}})}function le(n,t=10){let e=0,o=t;function i(){if(o>0)o--,requestAnimationFrame(i);else{const a=(+new Date-e)/t,c=1e3/a;n(Number(c.toFixed(2)),Number(a.toFixed(2)))}}requestAnimationFrame(()=>{e=+new Date,i()})}function ue(n,t){return n=n.replace(/([^a-zA-Z][a-z])/g,e=>e.toUpperCase()),t?n.replace(/[^a-zA-Z]+/g,""):n}function me(n,t,e){if(!e){let a=t.replace(/^[^.]+./,"");a=a==t?"text/plain":"application/"+a,e={type:a}}const o=new Blob(n,e),i=URL.createObjectURL(o),r=document.createElement("a");r.href=i,r.download=t,document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(i)}function de(n){const t=n.split("?")[1]||"",e=new URLSearchParams(t),o={};return e.forEach((i,r)=>{o[r]=i}),o}function pe(n=""){return n+"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){const e=Math.random()*16|0;return(t==="x"?e:e&3|8).toString(16)})}function H(n,t){let e;return function(...o){clearTimeout(e),e=setTimeout(()=>{n(...o),e=void 0},t)}}function fe(n,t){let e=-1/0;return function(...o){const i=performance.now();if(i-e>t){e=i;try{n(...o)}catch(r){console.error("Throttled function execution failed:",r)}}}}function he(n){return Array.isArray(n)?"array":n===null?"null":typeof n}function ge(n){const t=()=>Promise.resolve(),e=c=>(console.error(c),Promise.reject(c));function o(){return navigator.clipboard.writeText(n).then(t).catch(e)}function i(){const c=document.createElement("div");c.innerText=n,document.body.appendChild(c);const m=document.createRange();m.selectNodeContents(c);const u=window.getSelection();let p=!1;return u&&(u.removeAllRanges(),u.addRange(m),p=document.execCommand("copy")),document.body.removeChild(c),p?Promise.resolve():Promise.reject()}function r(){const c=document.createElement("textarea");c.value=n,document.body.appendChild(c),c.select(),c.setSelectionRange(0,n.length);let m=!1;return document.activeElement===c&&(m=document.execCommand("Copy",!0)),document.body.removeChild(c),m?Promise.resolve():Promise.reject()}function a(){return i().then(t).catch(()=>{r().then(t).catch(()=>e("复制方式尽皆失效"))})}return navigator.clipboard?o().catch(a):a()}function xe(n,t){const e=t.split(".");return e.reduce((o,i,r)=>(i in o||(r===e.length-1?o[i]=void 0:o[i]={}),o[i]),n)}function be(n,t){const e=t.split(".");return e.reduce((o,i,r)=>o.hasOwnProperty(i)?o[i]:o[i]=r==e.length-1?void 0:{},n)}function ve(n,t,e){const o=t.split(".");return o.reduce((i,r,a)=>(a===o.length-1&&(i[r]=e),i[r]),n)}function we(n){return new Promise((t,e)=>{if(typeof n!="string"||n.trim()===""||!n.includes("://")){e(new Error("Invalid URL: Must be a non-empty string"));return}try{new XMLHttpRequest().open("HEAD",n,!0)}catch(r){e(new Error(`Invalid URL format: ${r.message}`));return}const o=new XMLHttpRequest;o.open("HEAD",n,!0);const i=r=>{e(new Error(`Request failed: ${r.type}`))};o.onreadystatechange=function(){o.readyState===XMLHttpRequest.DONE&&(o.status===0?e(new Error("Network error or CORS blocked")):o.status>=200&&o.status<300?t(!0):e(new Error(`HTTP Error: ${o.status}`)))},o.onerror=i,o.onabort=i,o.ontimeout=i;try{o.send()}catch(r){e(new Error(`Request send failed: ${r.message}`))}})}function ye(n){return["https:","wss:","ftps:","sftp:","smpts:","smtp+tls:","imap+tls:","pop3+tls:","rdp:","vpn:"].some(e=>n.startsWith(e))}const C=class C{static check(t,e){if(!t||typeof t!="string")return console.error("Invalid URL provided"),e?!1:"unknown";const o=O(t).toLowerCase();if(e){if(!N.hasOwnProperty(e))return console.error(`Unknown file type: ${e}`),"unknown";const i=N[e];return C._checkExtension(o,i)}return C._detectFileType(o)}static parseAddresses(t){return!t||typeof t!="string"?(console.error("Invalid URL provided"),[]):t.split(",").map(e=>{const o=O(e),i=this.check(e);return{url:e,name:o,type:i}})}static matchesMimeType(t,e){if(!e)return!0;if(typeof t!="string"||typeof e!="string")return!1;const o=C._normalizeType(t),i=e.split(",").map(c=>C._normalizeType(c.trim())),[r,a="*"]=o.split("/");return i.some(c=>{const[m,u="*"]=c.split("/");return(m==="*"||r==="*"||m===r)&&(u==="*"||a==="*"||u===a)})}static _normalizeType(t){return t.startsWith(".")&&!t.includes("/")?J[t.toLowerCase()]||t:t.includes("/")?t:`${t}/*`}static _checkExtension(t,e){return e.some(o=>t.endsWith(o))}static _detectFileType(t){for(const[e,o]of C.cachedEntries)if(o.some(i=>t.endsWith(i)))return e;return"unknown"}};Y(C,"cachedEntries",Object.entries(N));let q=C;function _e(n){return n.map((t,e)=>n.slice(e).concat(n.slice(0,e)))}function Ce(n){const t=window.structuredClone,e=o=>o===null||typeof o!="object"?o:z(Array.isArray(o)?[]:{},o);try{return t?t(n):e(n)}catch(o){return console.error("structuredClone error:",o),t&&e(n)}}function Ee(n){const t=H(n,100);let e=0,o=0;return function(i){const r=i.target;if(!r||!(r instanceof HTMLElement))return;const{scrollTop:a,scrollHeight:c,clientHeight:m,scrollLeft:u,scrollWidth:p,clientWidth:f}=r;function S(){if(e==a)return;const U=e>a;if(e=a,U)return;c-a-m<=1&&t("vertical")}function V(){if(o==u)return;const U=o>u;if(o=u,U)return;p-u-f<=1&&t("horizontal")}S(),V()}}function Fe(n,t,e){const{isClickAllowed:o,uiLibrary:i=["naiveUI","ElementPlus","Element"]}=e||{},r=function(m){const u=[];for(const p in m)Object.hasOwnProperty.call(m,p)&&i.includes(p)&&u.push(...m[p]);return u}({naiveUI:[".v-binder-follower-container",".n-image-preview-container",".n-modal-container"],ElementPlus:[".el-popper"],Element:[".el-popper"]});function a(){t(),document.removeEventListener("mousedown",c)}function c(m){if(o){const f=o(m);if(f)return;if(f===!1)return a()}const u=m.target;if(!(u instanceof HTMLElement)||!(u!=null&&u.closest("body")))return;n.concat(r).some(f=>!!(u!=null&&u.closest(f)))||a()}requestAnimationFrame(()=>document.addEventListener("mousedown",c))}var g,E,F,P,L,w,y,_,R;class Me{constructor(){d(this,g);d(this,E,!1);d(this,F,{});d(this,P,0);d(this,L,0);d(this,w,0);d(this,y,0);d(this,_);d(this,R)}init(t,e){l(this,g,t),l(this,_,e==null?void 0:e.limit),l(this,R,e==null?void 0:e.dragDom),l(this,F,{mousedown:this.mousedown.bind(this),mousemove:this.mousemove.bind(this),mouseup:this.mouseup.bind(this)}),this.bindOrUnbindEvent("bind")}finish(){this.bindOrUnbindEvent("unbind")}bindOrUnbindEvent(t){const e=t==="bind"?"addEventListener":"removeEventListener";if(!s(this,g))return console.error("No DOM");s(this,g)[e]("mousedown",s(this,F).mousedown),document[e]("mousemove",s(this,F).mousemove),document[e]("mouseup",s(this,F).mouseup)}alterLocation(){if(!s(this,g))return console.error("No DOM");s(this,_)&&(l(this,w,Math.min(s(this,w),s(this,_).max.top)),l(this,w,Math.max(s(this,w),s(this,_).min.top)),l(this,y,Math.min(s(this,y),s(this,_).max.left)),l(this,y,Math.max(s(this,y),s(this,_).min.left))),s(this,g).style.setProperty("--top",s(this,w)+"px"),s(this,g).style.setProperty("--left",s(this,y)+"px")}mousedown(t){if(!s(this,g))return console.error("No DOM");if(s(this,R)&&t.target!=s(this,R))return;document.body.classList.add("no-select"),l(this,E,!0);const e=s(this,g).getBoundingClientRect(),{pageX:o,pageY:i}=t;l(this,P,o),l(this,L,i),l(this,w,e.y),l(this,y,e.x)}mousemove(t){const{pageX:e,pageY:o}=t;s(this,E)&&(l(this,w,s(this,w)+(o-s(this,L))),l(this,y,s(this,y)+(e-s(this,P))),l(this,P,e),l(this,L,o),this.alterLocation())}mouseup(){s(this,E)&&(l(this,E,!1),document.body.classList.remove("no-select"))}}g=new WeakMap,E=new WeakMap,F=new WeakMap,P=new WeakMap,L=new WeakMap,w=new WeakMap,y=new WeakMap,_=new WeakMap,R=new WeakMap;var x,M,T,k,I,b,v,h,j,D;class Te{constructor(){d(this,x);d(this,M,!1);d(this,T,{});d(this,k,0);d(this,I,0);d(this,b,0);d(this,v,0);d(this,h);d(this,j);d(this,D)}init(t,e={}){l(this,x,t),l(this,h,e.limit),l(this,j,e.update_move),l(this,D,e.update_up),l(this,T,{mousedown:this.mousedown.bind(this),mousemove:this.mousemove.bind(this),mouseup:this.mouseup.bind(this)}),this.bindOrUnbindEvent("bind")}finish(){this.bindOrUnbindEvent("unbind")}bindOrUnbindEvent(t){const e=t==="bind"?"addEventListener":"removeEventListener";if(!s(this,x))return console.error("No DOM");s(this,x)[e]("mousedown",s(this,T).mousedown),document[e]("mousemove",s(this,T).mousemove),document[e]("mouseup",s(this,T).mouseup)}updateValue(){const t={top:s(this,b),left:s(this,v),percentage:{top:0,left:0}};if(s(this,h)){const e=o=>s(this,h)?(t[o]-s(this,h).min[o])/(s(this,h).max[o]-s(this,h).min[o]):0;t.percentage={top:e("top")||0,left:e("left")||0}}return t}alterLocation(){if(!s(this,x))return console.error("No DOM");s(this,h)&&(l(this,b,Math.min(s(this,b),s(this,h).max.top)),l(this,b,Math.max(s(this,b),s(this,h).min.top)),l(this,v,Math.min(s(this,v),s(this,h).max.left)),l(this,v,Math.max(s(this,v),s(this,h).min.left))),s(this,j)&&s(this,j).call(this,this.updateValue()),s(this,x).style.setProperty("--top",s(this,b)+"px"),s(this,x).style.setProperty("--left",s(this,v)+"px")}mousedown(t){if(!s(this,x))return console.error("No DOM");document.body.classList.add("no-select"),l(this,M,!0);const e=s(this,x).getBoundingClientRect();l(this,I,e.y),l(this,k,e.x);const{pageX:o,pageY:i}=t;l(this,b,i-s(this,I)),l(this,v,o-s(this,k)),this.alterLocation()}mousemove(t){const{pageX:e,pageY:o}=t;s(this,M)&&(l(this,b,o-s(this,I)),l(this,v,e-s(this,k)),this.alterLocation())}mouseup(){s(this,M)&&(l(this,M,!1),document.body.classList.remove("no-select"),s(this,D)&&s(this,D).call(this,this.updateValue()))}}x=new WeakMap,M=new WeakMap,T=new WeakMap,k=new WeakMap,I=new WeakMap,b=new WeakMap,v=new WeakMap,h=new WeakMap,j=new WeakMap,D=new WeakMap;function B(n){const t=n;if(n){if(n.requestFullscreen)return n.requestFullscreen();if(t.mozRequestFullScreen)return t.mozRequestFullScreen();if(t.webkitRequestFullscreen)return t.webkitRequestFullscreen();if(t.msRequestFullscreen)return t.msRequestFullscreen()}else return Promise.reject("No DOM");return Promise.reject("No Fullscreen API")}function X(){const n=document;return document.exitFullscreen?document.exitFullscreen():n.mozCancelFullScreen?n.mozCancelFullScreen():n.webkitExitFullscreen?n.webkitExitFullscreen():n.msExitFullscreen?n.msExitFullscreen():Promise.reject("No ExitFullscreen API")}function G(){const n=document;return document.fullscreenElement||n.webkitFullscreenElement||n.mozFullScreenElement||n.msFullscreenElement}function Pe(n){return function(){G()?X():B(n)}}function Le(n,t){if(typeof n=="number")return n;if(/px/.test(n))return Number(n.replace(/px/,""))||0;const e=document.createElement("div");e.style.width=n,t=t||document.body,t.appendChild(e);const o=e.getBoundingClientRect().width;return t.removeChild(e),o}function Re(n,t,e=2){return!Number.isFinite(n)||!Number.isFinite(t)||!Number.isFinite(e)?(console.error("所有参数必须是有限的数字"),""):t===0?(console.error("分母不能为零"),""):e<0?(console.error("小数位数不能为负数"),""):(n/t*100).toFixed(e)+"%"}function ke(n,t,e){return Math.abs(n-t)<=e}function Ie(n,t=500){let e;function o(i){e||(e=i);let r=Math.min((i-e)/t,1);n(r),i-e<t&&requestAnimationFrame(o)}requestAnimationFrame(o)}function je(n){return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}function De(n,t){const e={join:!0,suffix:"",decimalPlaces:2},{join:o,suffix:i,decimalPlaces:r}={...e,...t||{}},a=Number(n);if(isNaN(a))return o?`0${i}`:[0,i];const c=Math.abs(a),m=a>=0,u=Math.max(0,Math.floor(Math.log10(c)/4)),p=Math.pow(1e4,u),f=c/p,S=(m?1:-1)*parseFloat(f.toFixed(Math.max(0,r)));return o?`${S}${W[u]}${i}`:[S,W[u]+i]}function Se(n,t){let e=!1;const{x:o,y:i}=n,r=t.length;for(let a=0,c=r-1;a<r;c=a++){const m=t[a].x,u=t[a].y,p=t[c].x,f=t[c].y;u>i!=f>i&&o<(p-m)*(i-u)/(f-u)+m&&(e=!e)}return e}function ze(n){const t=["B","KB","MB","GB","TB","PB"];let e=0;for(;n>1024;)n/=1024,e++;return`${Math.round(n*100)/100} ${t[e]}`}exports._CapitalizeFirstLetter=re;exports._CheckConnectionWithXHR=we;exports._Clone=Ce;exports._CloseOnOutsideClick=Fe;exports._ConvertToCamelCase=ue;exports._ConvertToPercentage=Re;exports._CopyToClipboard=ge;exports._CreateAndDownloadFile=me;exports._DataType=he;exports._Debounce=H;exports._DownloadFile=ce;exports._Drag=Me;exports._EnterFullscreen=B;exports._ExcludeSubstring=ie;exports._ExecuteWhenIdle=ne;exports._ExitFullscreen=X;exports._FileTypeChecker=q;exports._FormatFileSize=ze;exports._FormatNumber=je;exports._FormatNumberWithUnit=De;exports._Fullscreen=Pe;exports._GenerateUUID=pe;exports._GetFrameRate=le;exports._GetHrefName=O;exports._GetOtherSizeInPixels=Le;exports._GetQueryParams=de;exports._GetTargetByPath=be;exports._InitTargetByPath=xe;exports._IsFullscreen=G;exports._IsObject=te;exports._IsPointInPolygon=Se;exports._IsSecureContext=ye;exports._IsWithinErrorMargin=ke;exports._LocalDrag=Te;exports._MergeObjects=z;exports._NotNull=ee;exports._ReadFile=ae;exports._RotateList=_e;exports._Schedule=Ie;exports._ScrollEndListener=Ee;exports._Throttle=fe;exports._TimeTransition=se;exports._UpdateTargetByPath=ve;exports._WaitForCondition=oe;
@@ -0,0 +1,3 @@
1
+ export * from './Utility';
2
+ export * from './User';
3
+ export * from './Math';