@alibarbar/common 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +338 -0
- package/dist/algorithm.d.mts +66 -0
- package/dist/algorithm.d.ts +66 -0
- package/dist/algorithm.js +44 -0
- package/dist/algorithm.js.map +1 -0
- package/dist/algorithm.mjs +3 -0
- package/dist/algorithm.mjs.map +1 -0
- package/dist/array.d.mts +139 -0
- package/dist/array.d.ts +139 -0
- package/dist/array.js +84 -0
- package/dist/array.js.map +1 -0
- package/dist/array.mjs +3 -0
- package/dist/array.mjs.map +1 -0
- package/dist/chunk-27UDDVLZ.js +259 -0
- package/dist/chunk-27UDDVLZ.js.map +1 -0
- package/dist/chunk-2FFSQ573.mjs +138 -0
- package/dist/chunk-2FFSQ573.mjs.map +1 -0
- package/dist/chunk-4RGXV4SJ.js +106 -0
- package/dist/chunk-4RGXV4SJ.js.map +1 -0
- package/dist/chunk-56W6YECK.js +374 -0
- package/dist/chunk-56W6YECK.js.map +1 -0
- package/dist/chunk-5BGSUGTI.mjs +128 -0
- package/dist/chunk-5BGSUGTI.mjs.map +1 -0
- package/dist/chunk-7E6GELHJ.mjs +302 -0
- package/dist/chunk-7E6GELHJ.mjs.map +1 -0
- package/dist/chunk-7V5UQXIO.js +89 -0
- package/dist/chunk-7V5UQXIO.js.map +1 -0
- package/dist/chunk-A4SWQXX7.mjs +484 -0
- package/dist/chunk-A4SWQXX7.mjs.map +1 -0
- package/dist/chunk-ALDC6LRJ.mjs +85 -0
- package/dist/chunk-ALDC6LRJ.mjs.map +1 -0
- package/dist/chunk-BHCRFURU.js +491 -0
- package/dist/chunk-BHCRFURU.js.map +1 -0
- package/dist/chunk-D7CS5EKF.js +110 -0
- package/dist/chunk-D7CS5EKF.js.map +1 -0
- package/dist/chunk-DYBSRI7V.js +189 -0
- package/dist/chunk-DYBSRI7V.js.map +1 -0
- package/dist/chunk-F3LAGHPG.js +332 -0
- package/dist/chunk-F3LAGHPG.js.map +1 -0
- package/dist/chunk-HLDFI7R2.mjs +175 -0
- package/dist/chunk-HLDFI7R2.mjs.map +1 -0
- package/dist/chunk-HME2N3VY.mjs +354 -0
- package/dist/chunk-HME2N3VY.mjs.map +1 -0
- package/dist/chunk-I3L42475.js +145 -0
- package/dist/chunk-I3L42475.js.map +1 -0
- package/dist/chunk-JBLX27WD.mjs +240 -0
- package/dist/chunk-JBLX27WD.mjs.map +1 -0
- package/dist/chunk-JHZ7M2MR.mjs +133 -0
- package/dist/chunk-JHZ7M2MR.mjs.map +1 -0
- package/dist/chunk-JK2SE3I2.js +100 -0
- package/dist/chunk-JK2SE3I2.js.map +1 -0
- package/dist/chunk-JQZBPAPO.js +157 -0
- package/dist/chunk-JQZBPAPO.js.map +1 -0
- package/dist/chunk-JXYGC2C5.mjs +100 -0
- package/dist/chunk-JXYGC2C5.mjs.map +1 -0
- package/dist/chunk-KGFTD255.js +104 -0
- package/dist/chunk-KGFTD255.js.map +1 -0
- package/dist/chunk-LBHBNPNJ.mjs +148 -0
- package/dist/chunk-LBHBNPNJ.mjs.map +1 -0
- package/dist/chunk-LCXGZISK.js +158 -0
- package/dist/chunk-LCXGZISK.js.map +1 -0
- package/dist/chunk-LF4CILQS.mjs +87 -0
- package/dist/chunk-LF4CILQS.mjs.map +1 -0
- package/dist/chunk-MMR6XQNX.js +98 -0
- package/dist/chunk-MMR6XQNX.js.map +1 -0
- package/dist/chunk-NSSDYX2U.mjs +80 -0
- package/dist/chunk-NSSDYX2U.mjs.map +1 -0
- package/dist/chunk-O3O67R4I.js +143 -0
- package/dist/chunk-O3O67R4I.js.map +1 -0
- package/dist/chunk-OX5PLOWB.js +90 -0
- package/dist/chunk-OX5PLOWB.js.map +1 -0
- package/dist/chunk-PJ7UCTX4.mjs +362 -0
- package/dist/chunk-PJ7UCTX4.mjs.map +1 -0
- package/dist/chunk-QIBE7GVN.mjs +81 -0
- package/dist/chunk-QIBE7GVN.mjs.map +1 -0
- package/dist/chunk-QIOC54LQ.mjs +130 -0
- package/dist/chunk-QIOC54LQ.mjs.map +1 -0
- package/dist/chunk-QV6MIQ7H.mjs +328 -0
- package/dist/chunk-QV6MIQ7H.mjs.map +1 -0
- package/dist/chunk-TQN37HIN.js +94 -0
- package/dist/chunk-TQN37HIN.js.map +1 -0
- package/dist/chunk-XJTZDXSR.mjs +94 -0
- package/dist/chunk-XJTZDXSR.mjs.map +1 -0
- package/dist/chunk-XVUE53T3.js +361 -0
- package/dist/chunk-XVUE53T3.js.map +1 -0
- package/dist/chunk-Y364QIQH.js +139 -0
- package/dist/chunk-Y364QIQH.js.map +1 -0
- package/dist/chunk-YXM6Q4JS.mjs +94 -0
- package/dist/chunk-YXM6Q4JS.mjs.map +1 -0
- package/dist/chunk-ZDMFMUDR.js +309 -0
- package/dist/chunk-ZDMFMUDR.js.map +1 -0
- package/dist/chunk-ZVJ6NQUM.mjs +82 -0
- package/dist/chunk-ZVJ6NQUM.mjs.map +1 -0
- package/dist/color.d.mts +74 -0
- package/dist/color.d.ts +74 -0
- package/dist/color.js +40 -0
- package/dist/color.js.map +1 -0
- package/dist/color.mjs +3 -0
- package/dist/color.mjs.map +1 -0
- package/dist/crypto.d.mts +92 -0
- package/dist/crypto.d.ts +92 -0
- package/dist/crypto.js +60 -0
- package/dist/crypto.js.map +1 -0
- package/dist/crypto.mjs +3 -0
- package/dist/crypto.mjs.map +1 -0
- package/dist/data-structure.d.mts +213 -0
- package/dist/data-structure.d.ts +213 -0
- package/dist/data-structure.js +32 -0
- package/dist/data-structure.js.map +1 -0
- package/dist/data-structure.mjs +3 -0
- package/dist/data-structure.mjs.map +1 -0
- package/dist/date.d.mts +108 -0
- package/dist/date.d.ts +108 -0
- package/dist/date.js +72 -0
- package/dist/date.js.map +1 -0
- package/dist/date.mjs +3 -0
- package/dist/date.mjs.map +1 -0
- package/dist/dom.d.mts +92 -0
- package/dist/dom.d.ts +92 -0
- package/dist/dom.js +56 -0
- package/dist/dom.js.map +1 -0
- package/dist/dom.mjs +3 -0
- package/dist/dom.mjs.map +1 -0
- package/dist/file.d.mts +44 -0
- package/dist/file.d.ts +44 -0
- package/dist/file.js +32 -0
- package/dist/file.js.map +1 -0
- package/dist/file.mjs +3 -0
- package/dist/file.mjs.map +1 -0
- package/dist/i18n.d.mts +77 -0
- package/dist/i18n.d.ts +77 -0
- package/dist/i18n.js +40 -0
- package/dist/i18n.js.map +1 -0
- package/dist/i18n.mjs +3 -0
- package/dist/i18n.mjs.map +1 -0
- package/dist/index.d.mts +155 -0
- package/dist/index.d.ts +155 -0
- package/dist/index.js +839 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +22 -0
- package/dist/index.mjs.map +1 -0
- package/dist/network.d.mts +47 -0
- package/dist/network.d.ts +47 -0
- package/dist/network.js +28 -0
- package/dist/network.js.map +1 -0
- package/dist/network.mjs +3 -0
- package/dist/network.mjs.map +1 -0
- package/dist/number.d.mts +100 -0
- package/dist/number.d.ts +100 -0
- package/dist/number.js +56 -0
- package/dist/number.js.map +1 -0
- package/dist/number.mjs +3 -0
- package/dist/number.mjs.map +1 -0
- package/dist/object.d.mts +132 -0
- package/dist/object.d.ts +132 -0
- package/dist/object.js +80 -0
- package/dist/object.js.map +1 -0
- package/dist/object.mjs +3 -0
- package/dist/object.mjs.map +1 -0
- package/dist/performance.d.mts +85 -0
- package/dist/performance.d.ts +85 -0
- package/dist/performance.js +40 -0
- package/dist/performance.js.map +1 -0
- package/dist/performance.mjs +3 -0
- package/dist/performance.mjs.map +1 -0
- package/dist/storage.d.mts +176 -0
- package/dist/storage.d.ts +176 -0
- package/dist/storage.js +33 -0
- package/dist/storage.js.map +1 -0
- package/dist/storage.mjs +4 -0
- package/dist/storage.mjs.map +1 -0
- package/dist/string.d.mts +105 -0
- package/dist/string.d.ts +105 -0
- package/dist/string.js +68 -0
- package/dist/string.js.map +1 -0
- package/dist/string.mjs +3 -0
- package/dist/string.mjs.map +1 -0
- package/dist/tracking.d.mts +182 -0
- package/dist/tracking.d.ts +182 -0
- package/dist/tracking.js +52 -0
- package/dist/tracking.js.map +1 -0
- package/dist/tracking.mjs +3 -0
- package/dist/tracking.mjs.map +1 -0
- package/dist/transform.d.mts +53 -0
- package/dist/transform.d.ts +53 -0
- package/dist/transform.js +32 -0
- package/dist/transform.js.map +1 -0
- package/dist/transform.mjs +3 -0
- package/dist/transform.mjs.map +1 -0
- package/dist/upload-DzlQtUBc.d.mts +202 -0
- package/dist/upload-DzlQtUBc.d.ts +202 -0
- package/dist/upload.d.mts +1 -0
- package/dist/upload.d.ts +1 -0
- package/dist/upload.js +17 -0
- package/dist/upload.js.map +1 -0
- package/dist/upload.mjs +4 -0
- package/dist/upload.mjs.map +1 -0
- package/dist/url.d.mts +82 -0
- package/dist/url.d.ts +82 -0
- package/dist/url.js +44 -0
- package/dist/url.js.map +1 -0
- package/dist/url.mjs +3 -0
- package/dist/url.mjs.map +1 -0
- package/dist/validation.d.mts +83 -0
- package/dist/validation.d.ts +83 -0
- package/dist/validation.js +60 -0
- package/dist/validation.js.map +1 -0
- package/dist/validation.mjs +3 -0
- package/dist/validation.mjs.map +1 -0
- package/package.json +170 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// src/helper/performance.ts
|
|
2
|
+
function debounce(fn, delay) {
|
|
3
|
+
let timeoutId = null;
|
|
4
|
+
return function(...args) {
|
|
5
|
+
if (timeoutId) {
|
|
6
|
+
clearTimeout(timeoutId);
|
|
7
|
+
}
|
|
8
|
+
timeoutId = setTimeout(() => {
|
|
9
|
+
fn.apply(this, args);
|
|
10
|
+
timeoutId = null;
|
|
11
|
+
}, delay);
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function throttle(fn, delay) {
|
|
15
|
+
let lastCall = 0;
|
|
16
|
+
let timeoutId = null;
|
|
17
|
+
return function(...args) {
|
|
18
|
+
const now = Date.now();
|
|
19
|
+
const timeSinceLastCall = now - lastCall;
|
|
20
|
+
if (timeSinceLastCall >= delay) {
|
|
21
|
+
lastCall = now;
|
|
22
|
+
fn.apply(this, args);
|
|
23
|
+
} else {
|
|
24
|
+
if (timeoutId) {
|
|
25
|
+
clearTimeout(timeoutId);
|
|
26
|
+
}
|
|
27
|
+
timeoutId = setTimeout(() => {
|
|
28
|
+
lastCall = Date.now();
|
|
29
|
+
fn.apply(this, args);
|
|
30
|
+
timeoutId = null;
|
|
31
|
+
}, delay - timeSinceLastCall);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function memoize(fn, keyFn) {
|
|
36
|
+
const cache = /* @__PURE__ */ new Map();
|
|
37
|
+
return ((...args) => {
|
|
38
|
+
const key = keyFn ? keyFn(...args) : JSON.stringify(args);
|
|
39
|
+
if (cache.has(key)) {
|
|
40
|
+
return cache.get(key);
|
|
41
|
+
}
|
|
42
|
+
const result = fn(...args);
|
|
43
|
+
cache.set(key, result);
|
|
44
|
+
return result;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function once(fn) {
|
|
48
|
+
let called = false;
|
|
49
|
+
let result;
|
|
50
|
+
return ((...args) => {
|
|
51
|
+
if (!called) {
|
|
52
|
+
called = true;
|
|
53
|
+
result = fn(...args);
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async function retry(fn, retryCount = 3, retryDelay = 1e3) {
|
|
59
|
+
let lastError = null;
|
|
60
|
+
for (let i = 0; i <= retryCount; i++) {
|
|
61
|
+
try {
|
|
62
|
+
return await fn();
|
|
63
|
+
} catch (error) {
|
|
64
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
65
|
+
if (i < retryCount) {
|
|
66
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
throw lastError || new Error("Retry failed");
|
|
71
|
+
}
|
|
72
|
+
async function timeout(fn, timeout2) {
|
|
73
|
+
return Promise.race([
|
|
74
|
+
fn(),
|
|
75
|
+
new Promise((_, reject) => {
|
|
76
|
+
setTimeout(() => reject(new Error(`Operation timeout after ${timeout2}ms`)), timeout2);
|
|
77
|
+
})
|
|
78
|
+
]);
|
|
79
|
+
}
|
|
80
|
+
async function batch(items, fn, batchSize = 10) {
|
|
81
|
+
const results = [];
|
|
82
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
83
|
+
const batch2 = items.slice(i, i + batchSize);
|
|
84
|
+
const batchResults = await Promise.all(batch2.map(fn));
|
|
85
|
+
results.push(...batchResults);
|
|
86
|
+
}
|
|
87
|
+
return results;
|
|
88
|
+
}
|
|
89
|
+
var Queue = class {
|
|
90
|
+
constructor() {
|
|
91
|
+
this.items = [];
|
|
92
|
+
this.processing = false;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 添加项到队列
|
|
96
|
+
* @param item - 要添加的项
|
|
97
|
+
*/
|
|
98
|
+
enqueue(item) {
|
|
99
|
+
this.items.push(item);
|
|
100
|
+
if (!this.processing && this.processor) {
|
|
101
|
+
this.processItems();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* 设置处理函数并开始处理
|
|
106
|
+
* @param processor - 处理函数
|
|
107
|
+
*/
|
|
108
|
+
async start(processor) {
|
|
109
|
+
this.processor = processor;
|
|
110
|
+
if (!this.processing) {
|
|
111
|
+
await this.processItems();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* 处理队列
|
|
116
|
+
*/
|
|
117
|
+
async processItems() {
|
|
118
|
+
if (!this.processor || this.processing) return;
|
|
119
|
+
this.processing = true;
|
|
120
|
+
while (this.items.length > 0) {
|
|
121
|
+
const item = this.items.shift();
|
|
122
|
+
if (item && this.processor) {
|
|
123
|
+
try {
|
|
124
|
+
await this.processor(item);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error("Queue processing error:", error);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
this.processing = false;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* 清空队列
|
|
134
|
+
*/
|
|
135
|
+
clear() {
|
|
136
|
+
this.items = [];
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* 获取队列长度
|
|
140
|
+
*/
|
|
141
|
+
get length() {
|
|
142
|
+
return this.items.length;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
export { Queue, batch, debounce, memoize, once, retry, throttle, timeout };
|
|
147
|
+
//# sourceMappingURL=chunk-LBHBNPNJ.mjs.map
|
|
148
|
+
//# sourceMappingURL=chunk-LBHBNPNJ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/helper/performance.ts"],"names":["timeout","batch"],"mappings":"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","file":"chunk-LBHBNPNJ.mjs","sourcesContent":["/**\n * 性能工具函数\n */\n\n/**\n * 防抖函数\n * @param fn - 要防抖的函数\n * @param delay - 延迟时间(毫秒)\n * @returns 防抖后的函数\n */\nexport function debounce<T extends (...args: unknown[]) => unknown>(\n fn: T,\n delay: number\n): (...args: Parameters<T>) => void {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n return function (this: unknown, ...args: Parameters<T>) {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(() => {\n fn.apply(this, args);\n timeoutId = null;\n }, delay);\n };\n}\n\n/**\n * 节流函数\n * @param fn - 要节流的函数\n * @param delay - 延迟时间(毫秒)\n * @returns 节流后的函数\n */\nexport function throttle<T extends (...args: unknown[]) => unknown>(\n fn: T,\n delay: number\n): (...args: Parameters<T>) => void {\n let lastCall = 0;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n return function (this: unknown, ...args: Parameters<T>) {\n const now = Date.now();\n const timeSinceLastCall = now - lastCall;\n\n if (timeSinceLastCall >= delay) {\n lastCall = now;\n fn.apply(this, args);\n } else {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(() => {\n lastCall = Date.now();\n fn.apply(this, args);\n timeoutId = null;\n }, delay - timeSinceLastCall);\n }\n };\n}\n\n/**\n * 函数记忆化\n * @param fn - 要记忆化的函数\n * @param keyFn - 缓存键生成函数,可选\n * @returns 记忆化后的函数\n */\nexport function memoize<T extends (...args: unknown[]) => unknown>(\n fn: T,\n keyFn?: (...args: Parameters<T>) => string\n): T {\n const cache = new Map<string, ReturnType<T>>();\n\n return ((...args: Parameters<T>): ReturnType<T> => {\n const key = keyFn ? keyFn(...args) : JSON.stringify(args);\n if (cache.has(key)) {\n return cache.get(key)!;\n }\n const result = fn(...args) as ReturnType<T>;\n cache.set(key, result);\n return result;\n }) as T;\n}\n\n/**\n * 只执行一次的函数\n * @param fn - 要执行的函数\n * @returns 包装后的函数\n */\nexport function once<T extends (...args: unknown[]) => unknown>(fn: T): T {\n let called = false;\n let result: ReturnType<T>;\n\n return ((...args: Parameters<T>): ReturnType<T> => {\n if (!called) {\n called = true;\n result = fn(...args) as ReturnType<T>;\n }\n return result;\n }) as T;\n}\n\n/**\n * 重试机制\n * @param fn - 要重试的函数\n * @param retryCount - 重试次数,默认为 3\n * @param retryDelay - 重试延迟(毫秒),默认为 1000\n * @returns Promise<T>\n */\nexport async function retry<T>(\n fn: () => Promise<T>,\n retryCount = 3,\n retryDelay = 1000\n): Promise<T> {\n let lastError: Error | null = null;\n\n for (let i = 0; i <= retryCount; i++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n if (i < retryCount) {\n await new Promise(resolve => setTimeout(resolve, retryDelay));\n }\n }\n }\n\n throw lastError || new Error('Retry failed');\n}\n\n/**\n * 超时控制\n * @param fn - 要执行的函数\n * @param timeout - 超时时间(毫秒)\n * @returns Promise<T>\n */\nexport async function timeout<T>(fn: () => Promise<T>, timeout: number): Promise<T> {\n return Promise.race([\n fn(),\n new Promise<T>((_, reject) => {\n setTimeout(() => reject(new Error(`Operation timeout after ${timeout}ms`)), timeout);\n }),\n ]);\n}\n\n/**\n * 批量处理\n * @param items - 要处理的项数组\n * @param fn - 处理函数\n * @param batchSize - 每批大小,默认为 10\n * @returns Promise<T[]>\n */\nexport async function batch<T, R>(\n items: T[],\n fn: (item: T) => Promise<R>,\n batchSize = 10\n): Promise<R[]> {\n const results: R[] = [];\n\n for (let i = 0; i < items.length; i += batchSize) {\n const batch = items.slice(i, i + batchSize);\n const batchResults = await Promise.all(batch.map(fn));\n results.push(...batchResults);\n }\n\n return results;\n}\n\n/**\n * 队列处理\n */\nexport class Queue<T> {\n private items: T[] = [];\n private processing = false;\n private processor?: (item: T) => Promise<void>;\n\n /**\n * 添加项到队列\n * @param item - 要添加的项\n */\n enqueue(item: T): void {\n this.items.push(item);\n if (!this.processing && this.processor) {\n this.processItems();\n }\n }\n\n /**\n * 设置处理函数并开始处理\n * @param processor - 处理函数\n */\n async start(processor: (item: T) => Promise<void>): Promise<void> {\n this.processor = processor;\n if (!this.processing) {\n await this.processItems();\n }\n }\n\n /**\n * 处理队列\n */\n private async processItems(): Promise<void> {\n if (!this.processor || this.processing) return;\n\n this.processing = true;\n\n while (this.items.length > 0) {\n const item = this.items.shift();\n if (item && this.processor) {\n try {\n await this.processor(item);\n } catch (error) {\n console.error('Queue processing error:', error);\n }\n }\n }\n\n this.processing = false;\n }\n\n /**\n * 清空队列\n */\n clear(): void {\n this.items = [];\n }\n\n /**\n * 获取队列长度\n */\n get length(): number {\n return this.items.length;\n }\n}\n"]}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/core/array.ts
|
|
4
|
+
function unique(arr) {
|
|
5
|
+
return Array.from(new Set(arr));
|
|
6
|
+
}
|
|
7
|
+
function groupBy(arr, keyFn) {
|
|
8
|
+
const getKey = typeof keyFn === "string" ? (item) => item[keyFn] : keyFn;
|
|
9
|
+
return arr.reduce(
|
|
10
|
+
(acc, item) => {
|
|
11
|
+
const key = getKey(item);
|
|
12
|
+
if (!acc[key]) {
|
|
13
|
+
acc[key] = [];
|
|
14
|
+
}
|
|
15
|
+
acc[key].push(item);
|
|
16
|
+
return acc;
|
|
17
|
+
},
|
|
18
|
+
{}
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
function chunk(arr, size) {
|
|
22
|
+
const chunks = [];
|
|
23
|
+
for (let i = 0; i < arr.length; i += size) {
|
|
24
|
+
chunks.push(arr.slice(i, i + size));
|
|
25
|
+
}
|
|
26
|
+
return chunks;
|
|
27
|
+
}
|
|
28
|
+
function flatten(arr, depth = 1) {
|
|
29
|
+
return depth > 0 ? arr.reduce(
|
|
30
|
+
(acc, val) => acc.concat(Array.isArray(val) ? flatten(val, depth - 1) : val),
|
|
31
|
+
[]
|
|
32
|
+
) : arr;
|
|
33
|
+
}
|
|
34
|
+
function shuffle(arr) {
|
|
35
|
+
const result = [...arr];
|
|
36
|
+
for (let i = result.length - 1; i > 0; i--) {
|
|
37
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
38
|
+
[result[i], result[j]] = [result[j], result[i]];
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
function sample(arr, count = 1) {
|
|
43
|
+
if (arr.length === 0) {
|
|
44
|
+
throw new Error("Cannot sample from empty array");
|
|
45
|
+
}
|
|
46
|
+
if (count === 1) {
|
|
47
|
+
const shuffled2 = shuffle(arr);
|
|
48
|
+
return shuffled2[0];
|
|
49
|
+
}
|
|
50
|
+
if (count >= arr.length) return [...arr];
|
|
51
|
+
const shuffled = shuffle(arr);
|
|
52
|
+
return shuffled.slice(0, count);
|
|
53
|
+
}
|
|
54
|
+
function difference(arr1, arr2) {
|
|
55
|
+
const set2 = new Set(arr2);
|
|
56
|
+
return arr1.filter((item) => !set2.has(item));
|
|
57
|
+
}
|
|
58
|
+
function intersection(arr1, arr2) {
|
|
59
|
+
const set2 = new Set(arr2);
|
|
60
|
+
return arr1.filter((item) => set2.has(item));
|
|
61
|
+
}
|
|
62
|
+
function union(arr1, arr2) {
|
|
63
|
+
return unique([...arr1, ...arr2]);
|
|
64
|
+
}
|
|
65
|
+
function sortBy(arr, keyFn, order = "asc") {
|
|
66
|
+
const getKey = typeof keyFn === "string" ? (item) => item[keyFn] : keyFn;
|
|
67
|
+
const result = [...arr];
|
|
68
|
+
result.sort((a, b) => {
|
|
69
|
+
const keyA = getKey(a);
|
|
70
|
+
const keyB = getKey(b);
|
|
71
|
+
if (keyA < keyB) return order === "asc" ? -1 : 1;
|
|
72
|
+
if (keyA > keyB) return order === "asc" ? 1 : -1;
|
|
73
|
+
return 0;
|
|
74
|
+
});
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
function findIndexBy(arr, predicate) {
|
|
78
|
+
return arr.findIndex(predicate);
|
|
79
|
+
}
|
|
80
|
+
function partition(arr, predicate) {
|
|
81
|
+
const truthy = [];
|
|
82
|
+
const falsy = [];
|
|
83
|
+
arr.forEach((item) => {
|
|
84
|
+
if (predicate(item)) {
|
|
85
|
+
truthy.push(item);
|
|
86
|
+
} else {
|
|
87
|
+
falsy.push(item);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
return [truthy, falsy];
|
|
91
|
+
}
|
|
92
|
+
function zip(...arrays) {
|
|
93
|
+
const maxLength = Math.max(...arrays.map((arr) => arr.length));
|
|
94
|
+
const result = [];
|
|
95
|
+
for (let i = 0; i < maxLength; i++) {
|
|
96
|
+
result.push(
|
|
97
|
+
arrays.map((arr) => arr[i])
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
function unzip(array) {
|
|
103
|
+
if (array.length === 0) return [];
|
|
104
|
+
const length = array[0].length;
|
|
105
|
+
const result = Array.from({ length }, () => []);
|
|
106
|
+
array.forEach((item) => {
|
|
107
|
+
item.forEach((val, index) => {
|
|
108
|
+
result[index].push(val);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
function compact(arr) {
|
|
114
|
+
return arr.filter((item) => Boolean(item));
|
|
115
|
+
}
|
|
116
|
+
function take(arr, n) {
|
|
117
|
+
return arr.slice(0, n);
|
|
118
|
+
}
|
|
119
|
+
function drop(arr, n) {
|
|
120
|
+
return arr.slice(n);
|
|
121
|
+
}
|
|
122
|
+
function takeWhile(arr, predicate) {
|
|
123
|
+
const result = [];
|
|
124
|
+
for (const item of arr) {
|
|
125
|
+
if (!predicate(item)) break;
|
|
126
|
+
result.push(item);
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
function dropWhile(arr, predicate) {
|
|
131
|
+
let index = 0;
|
|
132
|
+
while (index < arr.length && predicate(arr[index])) {
|
|
133
|
+
index++;
|
|
134
|
+
}
|
|
135
|
+
return arr.slice(index);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
exports.chunk = chunk;
|
|
139
|
+
exports.compact = compact;
|
|
140
|
+
exports.difference = difference;
|
|
141
|
+
exports.drop = drop;
|
|
142
|
+
exports.dropWhile = dropWhile;
|
|
143
|
+
exports.findIndexBy = findIndexBy;
|
|
144
|
+
exports.flatten = flatten;
|
|
145
|
+
exports.groupBy = groupBy;
|
|
146
|
+
exports.intersection = intersection;
|
|
147
|
+
exports.partition = partition;
|
|
148
|
+
exports.sample = sample;
|
|
149
|
+
exports.shuffle = shuffle;
|
|
150
|
+
exports.sortBy = sortBy;
|
|
151
|
+
exports.take = take;
|
|
152
|
+
exports.takeWhile = takeWhile;
|
|
153
|
+
exports.union = union;
|
|
154
|
+
exports.unique = unique;
|
|
155
|
+
exports.unzip = unzip;
|
|
156
|
+
exports.zip = zip;
|
|
157
|
+
//# sourceMappingURL=chunk-LCXGZISK.js.map
|
|
158
|
+
//# sourceMappingURL=chunk-LCXGZISK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/array.ts"],"names":["shuffled"],"mappings":"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","file":"chunk-LCXGZISK.js","sourcesContent":["/**\n * 数组工具函数\n */\n\n/**\n * 数组去重\n * @param arr - 输入数组\n * @returns 去重后的数组\n */\nexport function unique<T>(arr: T[]): T[] {\n return Array.from(new Set(arr));\n}\n\n/**\n * 数组分组\n * @param arr - 输入数组\n * @param keyFn - 分组键函数或属性名\n * @returns 分组后的对象\n */\nexport function groupBy<T, K extends string | number>(\n arr: T[],\n keyFn: ((item: T) => K) | string\n): Record<K, T[]> {\n const getKey = typeof keyFn === 'string' \n ? (item: T) => (item as Record<string, K>)[keyFn] as K\n : keyFn;\n \n return arr.reduce(\n (acc, item) => {\n const key = getKey(item);\n if (!acc[key]) {\n acc[key] = [];\n }\n acc[key].push(item);\n return acc;\n },\n {} as Record<K, T[]>\n );\n}\n\n/**\n * 数组分块\n * @param arr - 输入数组\n * @param size - 每块大小\n * @returns 分块后的二维数组\n */\nexport function chunk<T>(arr: T[], size: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size));\n }\n return chunks;\n}\n\n/**\n * 数组扁平化\n * @param arr - 输入数组\n * @param depth - 扁平化深度,默认为 1\n * @returns 扁平化后的数组\n */\nexport function flatten<T>(arr: (T | T[])[], depth = 1): T[] {\n return depth > 0\n ? arr.reduce<T[]>(\n (acc, val) => acc.concat(Array.isArray(val) ? flatten(val, depth - 1) : val),\n []\n )\n : (arr as T[]);\n}\n\n/**\n * 数组随机打乱(Fisher-Yates算法)\n * @param arr - 输入数组\n * @returns 打乱后的新数组\n */\nexport function shuffle<T>(arr: T[]): T[] {\n const result = [...arr];\n for (let i = result.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [result[i], result[j]] = [result[j], result[i]];\n }\n return result;\n}\n\n/**\n * 随机取样\n * @param arr - 输入数组\n * @param count - 取样数量,默认为 1。当 count=1 时返回单个元素,否则返回数组\n * @returns 随机取样的数组或单个元素\n */\nexport function sample<T>(arr: T[]): T;\nexport function sample<T>(arr: T[], count: number): T | T[];\nexport function sample<T>(arr: T[], count = 1): T | T[] {\n if (arr.length === 0) {\n throw new Error('Cannot sample from empty array');\n }\n \n if (count === 1) {\n const shuffled = shuffle(arr);\n return shuffled[0];\n }\n \n if (count >= arr.length) return [...arr];\n const shuffled = shuffle(arr);\n return shuffled.slice(0, count);\n}\n\n/**\n * 数组差集(在arr1中但不在arr2中的元素)\n * @param arr1 - 第一个数组\n * @param arr2 - 第二个数组\n * @returns 差集数组\n */\nexport function difference<T>(arr1: T[], arr2: T[]): T[] {\n const set2 = new Set(arr2);\n return arr1.filter(item => !set2.has(item));\n}\n\n/**\n * 数组交集\n * @param arr1 - 第一个数组\n * @param arr2 - 第二个数组\n * @returns 交集数组\n */\nexport function intersection<T>(arr1: T[], arr2: T[]): T[] {\n const set2 = new Set(arr2);\n return arr1.filter(item => set2.has(item));\n}\n\n/**\n * 数组并集\n * @param arr1 - 第一个数组\n * @param arr2 - 第二个数组\n * @returns 并集数组\n */\nexport function union<T>(arr1: T[], arr2: T[]): T[] {\n return unique([...arr1, ...arr2]);\n}\n\n/**\n * 按属性排序\n * @param arr - 输入数组\n * @param keyFn - 获取排序键的函数或属性名\n * @param order - 排序顺序,'asc' 或 'desc',默认为 'asc'\n * @returns 排序后的新数组\n */\nexport function sortBy<T, K extends string | number>(\n arr: T[],\n keyFn: ((item: T) => K) | string,\n order: 'asc' | 'desc' = 'asc'\n): T[] {\n const getKey = typeof keyFn === 'string'\n ? (item: T) => (item as Record<string, K>)[keyFn] as K\n : keyFn;\n \n const result = [...arr];\n result.sort((a, b) => {\n const keyA = getKey(a);\n const keyB = getKey(b);\n if (keyA < keyB) return order === 'asc' ? -1 : 1;\n if (keyA > keyB) return order === 'asc' ? 1 : -1;\n return 0;\n });\n return result;\n}\n\n/**\n * 按条件查找索引\n * @param arr - 输入数组\n * @param predicate - 条件函数\n * @returns 找到的索引,未找到返回 -1\n */\nexport function findIndexBy<T>(arr: T[], predicate: (item: T) => boolean): number {\n return arr.findIndex(predicate);\n}\n\n/**\n * 数组分割(满足条件/不满足条件)\n * @param arr - 输入数组\n * @param predicate - 条件函数\n * @returns 包含两个数组的元组:[满足条件的数组, 不满足条件的数组]\n */\nexport function partition<T>(arr: T[], predicate: (item: T) => boolean): [T[], T[]] {\n const truthy: T[] = [];\n const falsy: T[] = [];\n arr.forEach(item => {\n if (predicate(item)) {\n truthy.push(item);\n } else {\n falsy.push(item);\n }\n });\n return [truthy, falsy];\n}\n\n/**\n * 数组压缩(将多个数组合并成元组数组)\n * @param arrays - 要压缩的数组\n * @returns 压缩后的元组数组\n */\nexport function zip<T extends readonly unknown[]>(\n ...arrays: T\n): Array<{ [K in keyof T]: T[K] extends readonly (infer U)[] ? U : never }> {\n const maxLength = Math.max(...arrays.map(arr => (arr as unknown[]).length));\n const result: Array<{ [K in keyof T]: T[K] extends readonly (infer U)[] ? U : never }> = [];\n for (let i = 0; i < maxLength; i++) {\n result.push(\n arrays.map(arr => (arr as unknown[])[i]) as {\n [K in keyof T]: T[K] extends readonly (infer U)[] ? U : never;\n }\n );\n }\n return result;\n}\n\n/**\n * 数组解压(将元组数组拆分成多个数组)\n * @param array - 要解压的数组\n * @returns 解压后的数组元组\n */\nexport function unzip<T extends readonly unknown[]>(\n array: Array<{ [K in keyof T]: T[number] extends readonly (infer U)[] ? U : never }>\n): T {\n if (array.length === 0) return [] as unknown as T;\n const length = (array[0] as unknown[]).length;\n const result = Array.from({ length }, () => []) as unknown as unknown[][];\n array.forEach(item => {\n (item as unknown[]).forEach((val, index) => {\n result[index].push(val);\n });\n });\n return result as unknown as T;\n}\n\n/**\n * 移除假值(null, undefined, false, 0, '')\n * @param arr - 输入数组\n * @returns 移除假值后的数组\n */\nexport function compact<T>(arr: (T | null | undefined | false | 0 | '')[]): T[] {\n return arr.filter((item): item is T => Boolean(item));\n}\n\n/**\n * 取前N个元素\n * @param arr - 输入数组\n * @param n - 要取的元素数量\n * @returns 前N个元素的数组\n */\nexport function take<T>(arr: T[], n: number): T[] {\n return arr.slice(0, n);\n}\n\n/**\n * 跳过前N个元素\n * @param arr - 输入数组\n * @param n - 要跳过的元素数量\n * @returns 跳过后的数组\n */\nexport function drop<T>(arr: T[], n: number): T[] {\n return arr.slice(n);\n}\n\n/**\n * 条件取元素(直到条件不满足)\n * @param arr - 输入数组\n * @param predicate - 条件函数\n * @returns 满足条件的连续元素数组\n */\nexport function takeWhile<T>(arr: T[], predicate: (item: T) => boolean): T[] {\n const result: T[] = [];\n for (const item of arr) {\n if (!predicate(item)) break;\n result.push(item);\n }\n return result;\n}\n\n/**\n * 条件跳过元素(直到条件不满足)\n * @param arr - 输入数组\n * @param predicate - 条件函数\n * @returns 跳过后的数组\n */\nexport function dropWhile<T>(arr: T[], predicate: (item: T) => boolean): T[] {\n let index = 0;\n while (index < arr.length && predicate(arr[index])) {\n index++;\n }\n return arr.slice(index);\n}\n"]}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// src/browser/dom.ts
|
|
2
|
+
function $(selector, context = document) {
|
|
3
|
+
return context.querySelector(selector);
|
|
4
|
+
}
|
|
5
|
+
function $$(selector, context = document) {
|
|
6
|
+
return Array.from(context.querySelectorAll(selector));
|
|
7
|
+
}
|
|
8
|
+
function addClass(element, className) {
|
|
9
|
+
element.classList.add(className);
|
|
10
|
+
}
|
|
11
|
+
function removeClass(element, className) {
|
|
12
|
+
element.classList.remove(className);
|
|
13
|
+
}
|
|
14
|
+
function toggleClass(element, className) {
|
|
15
|
+
return element.classList.toggle(className);
|
|
16
|
+
}
|
|
17
|
+
function getStyle(element, property) {
|
|
18
|
+
return window.getComputedStyle(element).getPropertyValue(property);
|
|
19
|
+
}
|
|
20
|
+
function setStyle(element, property, value) {
|
|
21
|
+
if (typeof property === "string" && value !== void 0) {
|
|
22
|
+
element.style.setProperty(property, value);
|
|
23
|
+
} else if (typeof property === "object") {
|
|
24
|
+
Object.keys(property).forEach((key) => {
|
|
25
|
+
element.style.setProperty(key, property[key]);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function scrollTo(target, options = {}) {
|
|
30
|
+
if (typeof window === "undefined") return;
|
|
31
|
+
const { behavior = "smooth", block = "start", inline = "nearest" } = options;
|
|
32
|
+
if (typeof target === "number") {
|
|
33
|
+
window.scrollTo({ top: target, behavior });
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const element = typeof target === "string" ? $(target) : target;
|
|
37
|
+
if (element) {
|
|
38
|
+
element.scrollIntoView({ behavior, block, inline });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function getScrollPosition() {
|
|
42
|
+
if (typeof window === "undefined") return { x: 0, y: 0 };
|
|
43
|
+
return {
|
|
44
|
+
x: window.pageXOffset || document.documentElement.scrollLeft || 0,
|
|
45
|
+
y: window.pageYOffset || document.documentElement.scrollTop || 0
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function isInViewport(element, threshold = 0) {
|
|
49
|
+
if (typeof window === "undefined") return false;
|
|
50
|
+
const rect = element.getBoundingClientRect();
|
|
51
|
+
const windowHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
52
|
+
const windowWidth = window.innerWidth || document.documentElement.clientWidth;
|
|
53
|
+
return rect.top >= -threshold * rect.height && rect.left >= -threshold * rect.width && rect.bottom <= windowHeight + threshold * rect.height && rect.right <= windowWidth + threshold * rect.width;
|
|
54
|
+
}
|
|
55
|
+
function getElementOffset(element) {
|
|
56
|
+
const rect = element.getBoundingClientRect();
|
|
57
|
+
return {
|
|
58
|
+
top: rect.top + (window.pageYOffset || document.documentElement.scrollTop),
|
|
59
|
+
left: rect.left + (window.pageXOffset || document.documentElement.scrollLeft)
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async function copyToClipboard(text) {
|
|
63
|
+
if (typeof navigator === "undefined" || !navigator.clipboard) {
|
|
64
|
+
const textArea = document.createElement("textarea");
|
|
65
|
+
textArea.value = text;
|
|
66
|
+
textArea.style.position = "fixed";
|
|
67
|
+
textArea.style.opacity = "0";
|
|
68
|
+
document.body.appendChild(textArea);
|
|
69
|
+
textArea.select();
|
|
70
|
+
try {
|
|
71
|
+
document.execCommand("copy");
|
|
72
|
+
} catch (error) {
|
|
73
|
+
throw new Error("Failed to copy text");
|
|
74
|
+
}
|
|
75
|
+
document.body.removeChild(textArea);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
await navigator.clipboard.writeText(text);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
throw new Error("Failed to copy text");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { $, $$, addClass, copyToClipboard, getElementOffset, getScrollPosition, getStyle, isInViewport, removeClass, scrollTo, setStyle, toggleClass };
|
|
86
|
+
//# sourceMappingURL=chunk-LF4CILQS.mjs.map
|
|
87
|
+
//# sourceMappingURL=chunk-LF4CILQS.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/browser/dom.ts"],"names":[],"mappings":"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","file":"chunk-LF4CILQS.mjs","sourcesContent":["/**\n * DOM工具函数\n */\n\n/**\n * 选择器封装\n * @param selector - CSS选择器\n * @param context - 上下文元素,默认为 document\n * @returns 匹配的元素或元素数组\n */\nexport function $<T extends Element = Element>(\n selector: string,\n context: Document | Element = document\n): T | null {\n return context.querySelector<T>(selector);\n}\n\n/**\n * 选择器封装(返回所有匹配元素)\n * @param selector - CSS选择器\n * @param context - 上下文元素,默认为 document\n * @returns 匹配的元素数组\n */\nexport function $$<T extends Element = Element>(\n selector: string,\n context: Document | Element = document\n): T[] {\n return Array.from(context.querySelectorAll<T>(selector));\n}\n\n/**\n * 添加类名\n * @param element - DOM元素\n * @param className - 类名\n */\nexport function addClass(element: Element, className: string): void {\n element.classList.add(className);\n}\n\n/**\n * 移除类名\n * @param element - DOM元素\n * @param className - 类名\n */\nexport function removeClass(element: Element, className: string): void {\n element.classList.remove(className);\n}\n\n/**\n * 切换类名\n * @param element - DOM元素\n * @param className - 类名\n * @returns 是否包含该类名\n */\nexport function toggleClass(element: Element, className: string): boolean {\n return element.classList.toggle(className);\n}\n\n/**\n * 获取样式\n * @param element - DOM元素\n * @param property - CSS属性名\n * @returns 样式值\n */\nexport function getStyle(element: HTMLElement, property: string): string {\n return window.getComputedStyle(element).getPropertyValue(property);\n}\n\n/**\n * 设置样式\n * @param element - DOM元素\n * @param property - CSS属性名或样式对象\n * @param value - 样式值(当property为字符串时)\n */\nexport function setStyle(\n element: HTMLElement,\n property: string | Record<string, string>,\n value?: string\n): void {\n if (typeof property === 'string' && value !== undefined) {\n element.style.setProperty(property, value);\n } else if (typeof property === 'object') {\n Object.keys(property).forEach(key => {\n element.style.setProperty(key, property[key]);\n });\n }\n}\n\n/**\n * 平滑滚动\n * @param target - 目标位置(元素、选择器或数字)\n * @param options - 滚动选项\n */\nexport function scrollTo(\n target: Element | string | number,\n options: {\n behavior?: ScrollBehavior;\n block?: ScrollLogicalPosition;\n inline?: ScrollLogicalPosition;\n } = {}\n): void {\n if (typeof window === 'undefined') return;\n\n const { behavior = 'smooth', block = 'start', inline = 'nearest' } = options;\n\n if (typeof target === 'number') {\n window.scrollTo({ top: target, behavior });\n return;\n }\n\n const element = typeof target === 'string' ? $(target) : target;\n if (element) {\n element.scrollIntoView({ behavior, block, inline });\n }\n}\n\n/**\n * 获取滚动位置\n * @returns 滚动位置对象\n */\nexport function getScrollPosition(): { x: number; y: number } {\n if (typeof window === 'undefined') return { x: 0, y: 0 };\n return {\n x: window.pageXOffset || document.documentElement.scrollLeft || 0,\n y: window.pageYOffset || document.documentElement.scrollTop || 0,\n };\n}\n\n/**\n * 判断元素是否在视口内\n * @param element - DOM元素\n * @param threshold - 阈值(0-1),默认为 0\n * @returns 是否在视口内\n */\nexport function isInViewport(element: Element, threshold = 0): boolean {\n if (typeof window === 'undefined') return false;\n\n const rect = element.getBoundingClientRect();\n const windowHeight = window.innerHeight || document.documentElement.clientHeight;\n const windowWidth = window.innerWidth || document.documentElement.clientWidth;\n\n return (\n rect.top >= -threshold * rect.height &&\n rect.left >= -threshold * rect.width &&\n rect.bottom <= windowHeight + threshold * rect.height &&\n rect.right <= windowWidth + threshold * rect.width\n );\n}\n\n/**\n * 获取元素偏移量\n * @param element - DOM元素\n * @returns 偏移量对象\n */\nexport function getElementOffset(element: Element): { top: number; left: number } {\n const rect = element.getBoundingClientRect();\n return {\n top: rect.top + (window.pageYOffset || document.documentElement.scrollTop),\n left: rect.left + (window.pageXOffset || document.documentElement.scrollLeft),\n };\n}\n\n/**\n * 复制到剪贴板\n * @param text - 要复制的文本\n * @returns Promise<void>\n */\nexport async function copyToClipboard(text: string): Promise<void> {\n if (typeof navigator === 'undefined' || !navigator.clipboard) {\n // 降级方案\n const textArea = document.createElement('textarea');\n textArea.value = text;\n textArea.style.position = 'fixed';\n textArea.style.opacity = '0';\n document.body.appendChild(textArea);\n textArea.select();\n try {\n document.execCommand('copy');\n } catch (error) {\n throw new Error('Failed to copy text');\n }\n document.body.removeChild(textArea);\n return;\n }\n\n try {\n await navigator.clipboard.writeText(text);\n } catch (error) {\n throw new Error('Failed to copy text');\n }\n}\n"]}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/format/number.ts
|
|
4
|
+
function formatNumber(num, options = {}) {
|
|
5
|
+
const {
|
|
6
|
+
decimals,
|
|
7
|
+
separator = ",",
|
|
8
|
+
decimalPoint = ".",
|
|
9
|
+
minimumFractionDigits
|
|
10
|
+
} = options;
|
|
11
|
+
let numStr;
|
|
12
|
+
if (decimals !== void 0) {
|
|
13
|
+
numStr = num.toFixed(decimals);
|
|
14
|
+
} else if (minimumFractionDigits !== void 0) {
|
|
15
|
+
numStr = num.toFixed(minimumFractionDigits);
|
|
16
|
+
} else {
|
|
17
|
+
const str = num.toString();
|
|
18
|
+
if (str.includes(".")) {
|
|
19
|
+
numStr = str;
|
|
20
|
+
} else {
|
|
21
|
+
numStr = num.toFixed(0);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const parts = numStr.split(".");
|
|
25
|
+
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, separator);
|
|
26
|
+
return parts.join(decimalPoint);
|
|
27
|
+
}
|
|
28
|
+
function random(min, max, integer = false) {
|
|
29
|
+
const value = Math.random() * (max - min) + min;
|
|
30
|
+
return integer ? Math.floor(value) : value;
|
|
31
|
+
}
|
|
32
|
+
function clamp(num, min, max) {
|
|
33
|
+
return Math.min(Math.max(num, min), max);
|
|
34
|
+
}
|
|
35
|
+
function round(num, decimals = 0) {
|
|
36
|
+
const factor = Math.pow(10, decimals);
|
|
37
|
+
return Math.round(num * factor) / factor;
|
|
38
|
+
}
|
|
39
|
+
function floor(num, decimals = 0) {
|
|
40
|
+
const factor = Math.pow(10, decimals);
|
|
41
|
+
return Math.floor(num * factor) / factor;
|
|
42
|
+
}
|
|
43
|
+
function ceil(num, decimals = 0) {
|
|
44
|
+
const factor = Math.pow(10, decimals);
|
|
45
|
+
return Math.ceil(num * factor) / factor;
|
|
46
|
+
}
|
|
47
|
+
function toFixed(num, decimals) {
|
|
48
|
+
return num.toFixed(decimals);
|
|
49
|
+
}
|
|
50
|
+
function parseNumber(str, defaultValue = 0) {
|
|
51
|
+
const num = Number(str);
|
|
52
|
+
return isNaN(num) ? defaultValue : num;
|
|
53
|
+
}
|
|
54
|
+
function isBetween(num, min, max, inclusive = true) {
|
|
55
|
+
if (inclusive) {
|
|
56
|
+
return num >= min && num <= max;
|
|
57
|
+
}
|
|
58
|
+
return num > min && num < max;
|
|
59
|
+
}
|
|
60
|
+
function percent(value, decimalsOrTotal, decimals) {
|
|
61
|
+
if (value >= 0 && value <= 1 && (decimalsOrTotal === void 0 || decimalsOrTotal < 10)) {
|
|
62
|
+
const dec2 = decimalsOrTotal ?? 0;
|
|
63
|
+
return Number((value * 100).toFixed(dec2));
|
|
64
|
+
}
|
|
65
|
+
if (decimalsOrTotal !== void 0 && decimalsOrTotal >= 10) {
|
|
66
|
+
const total = decimalsOrTotal;
|
|
67
|
+
const dec2 = decimals ?? 2;
|
|
68
|
+
if (total === 0) return "0%";
|
|
69
|
+
return `${(value / total * 100).toFixed(dec2)}%`;
|
|
70
|
+
}
|
|
71
|
+
const dec = decimalsOrTotal ?? 0;
|
|
72
|
+
return Number((value * 100).toFixed(dec));
|
|
73
|
+
}
|
|
74
|
+
function formatCurrency(num, currency = "\xA5", decimals = 2) {
|
|
75
|
+
return `${currency}${formatNumber(num, { decimals, separator: "," })}`;
|
|
76
|
+
}
|
|
77
|
+
function formatBytes(bytes, decimals = 2) {
|
|
78
|
+
if (bytes === 0) return "0 Bytes";
|
|
79
|
+
const k = 1024;
|
|
80
|
+
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB"];
|
|
81
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
82
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(decimals))} ${sizes[i]}`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
exports.ceil = ceil;
|
|
86
|
+
exports.clamp = clamp;
|
|
87
|
+
exports.floor = floor;
|
|
88
|
+
exports.formatBytes = formatBytes;
|
|
89
|
+
exports.formatCurrency = formatCurrency;
|
|
90
|
+
exports.formatNumber = formatNumber;
|
|
91
|
+
exports.isBetween = isBetween;
|
|
92
|
+
exports.parseNumber = parseNumber;
|
|
93
|
+
exports.percent = percent;
|
|
94
|
+
exports.random = random;
|
|
95
|
+
exports.round = round;
|
|
96
|
+
exports.toFixed = toFixed;
|
|
97
|
+
//# sourceMappingURL=chunk-MMR6XQNX.js.map
|
|
98
|
+
//# sourceMappingURL=chunk-MMR6XQNX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/format/number.ts"],"names":["dec"],"mappings":"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","file":"chunk-MMR6XQNX.js","sourcesContent":["/**\n * 数字工具函数\n */\n\n/**\n * 数字格式化(千分位)\n * @param num - 数字\n * @param options - 格式化选项\n * @returns 格式化后的字符串\n */\nexport function formatNumber(\n num: number,\n options: {\n decimals?: number;\n separator?: string;\n decimalPoint?: string;\n minimumFractionDigits?: number;\n } = {}\n): string {\n const {\n decimals,\n separator = ',',\n decimalPoint = '.',\n minimumFractionDigits,\n } = options;\n \n // 如果没有指定 decimals,自动检测小数位\n let numStr: string;\n if (decimals !== undefined) {\n numStr = num.toFixed(decimals);\n } else if (minimumFractionDigits !== undefined) {\n numStr = num.toFixed(minimumFractionDigits);\n } else {\n // 自动检测小数位\n const str = num.toString();\n if (str.includes('.')) {\n numStr = str;\n } else {\n numStr = num.toFixed(0);\n }\n }\n \n const parts = numStr.split('.');\n parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, separator);\n return parts.join(decimalPoint);\n}\n\n/**\n * 生成随机数\n * @param min - 最小值\n * @param max - 最大值\n * @param integer - 是否为整数,默认为 false\n * @returns 随机数\n */\nexport function random(min: number, max: number, integer = false): number {\n const value = Math.random() * (max - min) + min;\n return integer ? Math.floor(value) : value;\n}\n\n/**\n * 限制数值范围\n * @param num - 数字\n * @param min - 最小值\n * @param max - 最大值\n * @returns 限制后的数字\n */\nexport function clamp(num: number, min: number, max: number): number {\n return Math.min(Math.max(num, min), max);\n}\n\n/**\n * 增强版四舍五入\n * @param num - 数字\n * @param decimals - 小数位数,默认为 0\n * @returns 四舍五入后的数字\n */\nexport function round(num: number, decimals = 0): number {\n const factor = Math.pow(10, decimals);\n return Math.round(num * factor) / factor;\n}\n\n/**\n * 增强版向下取整\n * @param num - 数字\n * @param decimals - 小数位数,默认为 0\n * @returns 向下取整后的数字\n */\nexport function floor(num: number, decimals = 0): number {\n const factor = Math.pow(10, decimals);\n return Math.floor(num * factor) / factor;\n}\n\n/**\n * 增强版向上取整\n * @param num - 数字\n * @param decimals - 小数位数,默认为 0\n * @returns 向上取整后的数字\n */\nexport function ceil(num: number, decimals = 0): number {\n const factor = Math.pow(10, decimals);\n return Math.ceil(num * factor) / factor;\n}\n\n/**\n * 保留小数位(增强版)\n * @param num - 数字\n * @param decimals - 小数位数\n * @returns 格式化后的字符串\n */\nexport function toFixed(num: number, decimals: number): string {\n return num.toFixed(decimals);\n}\n\n/**\n * 解析数字字符串\n * @param str - 数字字符串\n * @param defaultValue - 默认值,解析失败时返回\n * @returns 解析后的数字\n */\nexport function parseNumber(str: string, defaultValue = 0): number {\n const num = Number(str);\n return isNaN(num) ? defaultValue : num;\n}\n\n/**\n * 判断是否在范围内\n * @param num - 数字\n * @param min - 最小值\n * @param max - 最大值\n * @param inclusive - 是否包含边界,默认为 true\n * @returns 是否在范围内\n */\nexport function isBetween(num: number, min: number, max: number, inclusive = true): boolean {\n if (inclusive) {\n return num >= min && num <= max;\n }\n return num > min && num < max;\n}\n\n/**\n * 百分比计算\n * @param value - 当前值(0-1之间的小数)或当前值(当提供total时)\n * @param decimals - 小数位数,默认为 0(当value是0-1之间的小数时)或总值(当value是实际值时)\n * @returns 百分比数字(当value是0-1之间的小数时)或百分比字符串(当提供total时)\n */\nexport function percent(value: number, decimals?: number): number;\nexport function percent(value: number, total: number, decimals: number): string;\nexport function percent(\n value: number,\n decimalsOrTotal?: number,\n decimals?: number\n): number | string {\n // 如果 value 是 0-1 之间的小数,且只传了一个参数或第二个参数是小数位数\n if (value >= 0 && value <= 1 && (decimalsOrTotal === undefined || decimalsOrTotal < 10)) {\n const dec = decimalsOrTotal ?? 0;\n return Number((value * 100).toFixed(dec));\n }\n \n // 如果提供了 total(第二个参数大于等于10,认为是total)\n if (decimalsOrTotal !== undefined && decimalsOrTotal >= 10) {\n const total = decimalsOrTotal;\n const dec = decimals ?? 2;\n if (total === 0) return '0%';\n return `${((value / total) * 100).toFixed(dec)}%`;\n }\n \n // 默认情况:value 是 0-1 之间的小数\n const dec = decimalsOrTotal ?? 0;\n return Number((value * 100).toFixed(dec));\n}\n\n/**\n * 货币格式化\n * @param num - 数字\n * @param currency - 货币符号,默认为 '¥'\n * @param decimals - 小数位数,默认为 2\n * @returns 格式化后的货币字符串\n */\nexport function formatCurrency(num: number, currency = '¥', decimals = 2): string {\n return `${currency}${formatNumber(num, { decimals, separator: ',' })}`;\n}\n\n/**\n * 字节格式化\n * @param bytes - 字节数\n * @param decimals - 小数位数,默认为 2\n * @returns 格式化后的字节字符串\n */\nexport function formatBytes(bytes: number, decimals = 2): string {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(decimals))} ${sizes[i]}`;\n}\n"]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// src/core/validation.ts
|
|
2
|
+
function isValidEmail(email) {
|
|
3
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
4
|
+
return emailRegex.test(email);
|
|
5
|
+
}
|
|
6
|
+
function isValidPhone(phone) {
|
|
7
|
+
const phoneRegex = /^1[3-9]\d{9}$/;
|
|
8
|
+
return phoneRegex.test(phone);
|
|
9
|
+
}
|
|
10
|
+
function isValidUrl(url) {
|
|
11
|
+
try {
|
|
12
|
+
new URL(url);
|
|
13
|
+
return true;
|
|
14
|
+
} catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function isValidIdCard(idCard) {
|
|
19
|
+
const idCardRegex = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
|
|
20
|
+
return idCardRegex.test(idCard);
|
|
21
|
+
}
|
|
22
|
+
function isEmpty(value) {
|
|
23
|
+
if (value === null || value === void 0) return true;
|
|
24
|
+
if (typeof value === "string") return value.trim().length === 0;
|
|
25
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
26
|
+
if (typeof value === "object") return Object.keys(value).length === 0;
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
function isValidUUID(uuid) {
|
|
30
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
31
|
+
return uuidRegex.test(uuid);
|
|
32
|
+
}
|
|
33
|
+
function isValidIP(ip) {
|
|
34
|
+
const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
|
35
|
+
return ipRegex.test(ip);
|
|
36
|
+
}
|
|
37
|
+
function isValidDomain(domain) {
|
|
38
|
+
const domainRegex = /^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i;
|
|
39
|
+
return domainRegex.test(domain);
|
|
40
|
+
}
|
|
41
|
+
function isValidHexColor(color) {
|
|
42
|
+
const hexColorRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
|
|
43
|
+
return hexColorRegex.test(color);
|
|
44
|
+
}
|
|
45
|
+
function isValidJSON(json) {
|
|
46
|
+
try {
|
|
47
|
+
JSON.parse(json);
|
|
48
|
+
return true;
|
|
49
|
+
} catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function isNumeric(value) {
|
|
54
|
+
if (typeof value === "number") return !isNaN(value) && isFinite(value);
|
|
55
|
+
if (typeof value === "string") {
|
|
56
|
+
return value.trim() !== "" && !isNaN(Number(value)) && isFinite(Number(value));
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
function isInteger(value) {
|
|
61
|
+
if (typeof value === "number") return Number.isInteger(value);
|
|
62
|
+
if (typeof value === "string") {
|
|
63
|
+
const num = Number(value);
|
|
64
|
+
return !isNaN(num) && Number.isInteger(num);
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
function isFloat(value) {
|
|
69
|
+
if (typeof value === "number")
|
|
70
|
+
return !isNaN(value) && isFinite(value) && !Number.isInteger(value);
|
|
71
|
+
if (typeof value === "string") {
|
|
72
|
+
const num = Number(value);
|
|
73
|
+
return !isNaN(num) && isFinite(num) && !Number.isInteger(num);
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export { isEmpty, isFloat, isInteger, isNumeric, isValidDomain, isValidEmail, isValidHexColor, isValidIP, isValidIdCard, isValidJSON, isValidPhone, isValidUUID, isValidUrl };
|
|
79
|
+
//# sourceMappingURL=chunk-NSSDYX2U.mjs.map
|
|
80
|
+
//# sourceMappingURL=chunk-NSSDYX2U.mjs.map
|