rattail 0.0.3 → 0.0.5

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 CHANGED
@@ -8,6 +8,13 @@
8
8
  <a href="https://rattail.pages.dev">Documentation</a> |
9
9
  <a href="https://github.com/varletjs/rattail/blob/main/README.zh-CN.md">中文介绍</a>
10
10
  </p>
11
+ <p>
12
+ <img src="https://img.shields.io/npm/v/rattail?style=flat-square" alt="version">
13
+ <img src="https://img.shields.io/github/stars/varletjs/rattail" alt="stars">
14
+ <img src="https://img.shields.io/npm/l/rattail.svg" alt="license">
15
+ <img src="https://img.shields.io/codecov/c/github/varletjs/rattail" alt="coverage">
16
+ <img src="https://github.com/varletjs/varlet/workflows/CI/badge.svg" alt="ci">
17
+ </p>
11
18
  </div>
12
19
 
13
20
  ---
@@ -17,6 +24,7 @@
17
24
  - 🛠️ &nbsp; Provide utilities frequently used in daily development
18
25
  - 🛠️ &nbsp; Utilities implementation is very lightweight
19
26
  - 🛠️ &nbsp; Written based on ts, providing complete ts types
27
+ - 💪 &nbsp; Make sure more than 90% unit test coverage, providing stability assurance
20
28
 
21
29
  ### Installation
22
30
 
package/README.zh-CN.md CHANGED
@@ -8,6 +8,13 @@
8
8
  <a href="https://rattail.pages.dev/zh">文档</a> |
9
9
  <a href="https://github.com/varletjs/rattail/blob/main/README.md">ENGLISH README</a>
10
10
  </p>
11
+ <p>
12
+ <img src="https://img.shields.io/npm/v/rattail?style=flat-square" alt="version">
13
+ <img src="https://img.shields.io/github/stars/varletjs/rattail" alt="stars">
14
+ <img src="https://img.shields.io/npm/l/rattail.svg" alt="license">
15
+ <img src="https://img.shields.io/codecov/c/github/varletjs/rattail" alt="coverage">
16
+ <img src="https://github.com/varletjs/varlet/workflows/CI/badge.svg" alt="ci">
17
+ </p>
11
18
  </div>
12
19
 
13
20
  ---
@@ -17,6 +24,7 @@
17
24
  - 🛠️ &nbsp; 提供日常开发中经常使用的实用工具
18
25
  - 🛠️ &nbsp; 工具实现非常轻量
19
26
  - 🛠️ &nbsp; 使用 ts 编写,提供完善的类型支持
27
+ - 💪 &nbsp; 确保 90% 以上单元测试覆盖率,提供稳定性保证
20
28
 
21
29
  ### 安装
22
30
 
package/lib/index.cjs CHANGED
@@ -42,13 +42,15 @@ __export(src_exports, {
42
42
  call: () => call,
43
43
  camelize: () => camelize,
44
44
  cancelAnimationFrame: () => cancelAnimationFrame,
45
- capitalizeFirstLetter: () => capitalizeFirstLetter,
46
45
  clamp: () => clamp,
47
46
  clampArrayRange: () => clampArrayRange,
48
47
  classes: () => classes,
48
+ cloneDeep: () => cloneDeep,
49
+ cloneDeepWith: () => cloneDeepWith,
49
50
  createNamespaceFn: () => createNamespaceFn,
50
51
  createStorage: () => createStorage,
51
52
  debounce: () => debounce,
53
+ delay: () => delay,
52
54
  doubleRaf: () => doubleRaf,
53
55
  find: () => find,
54
56
  genNumberKey: () => genNumberKey,
@@ -65,7 +67,9 @@ __export(src_exports, {
65
67
  inMobile: () => inMobile,
66
68
  inViewport: () => inViewport,
67
69
  isArray: () => isArray,
70
+ isArrayBuffer: () => isArrayBuffer,
68
71
  isBoolean: () => isBoolean,
72
+ isDataView: () => isDataView,
69
73
  isDate: () => isDate,
70
74
  isEmpty: () => isEmpty,
71
75
  isFunction: () => isFunction,
@@ -82,10 +86,19 @@ __export(src_exports, {
82
86
  isString: () => isString,
83
87
  isSymbol: () => isSymbol,
84
88
  isTruthy: () => isTruthy,
89
+ isTypedArray: () => isTypedArray,
90
+ isWeakMap: () => isWeakMap,
91
+ isWeakSet: () => isWeakSet,
85
92
  isWindow: () => isWindow,
86
93
  kebabCase: () => kebabCase,
87
94
  localStorage: () => localStorage,
95
+ lowerFirst: () => lowerFirst,
96
+ maxBy: () => maxBy,
97
+ mean: () => mean,
98
+ meanBy: () => meanBy,
99
+ merge: () => merge,
88
100
  mergeWith: () => mergeWith,
101
+ minBy: () => minBy,
89
102
  normalizeToArray: () => normalizeToArray,
90
103
  objectToString: () => objectToString,
91
104
  pascalCase: () => pascalCase,
@@ -97,6 +110,7 @@ __export(src_exports, {
97
110
  removeArrayEmpty: () => removeArrayEmpty,
98
111
  removeItem: () => removeItem,
99
112
  requestAnimationFrame: () => requestAnimationFrame,
113
+ sample: () => sample,
100
114
  sessionStorage: () => sessionStorage,
101
115
  shuffle: () => shuffle,
102
116
  slash: () => slash,
@@ -104,6 +118,7 @@ __export(src_exports, {
104
118
  sumBy: () => sumBy,
105
119
  supportTouch: () => supportTouch,
106
120
  throttle: () => throttle,
121
+ times: () => times,
107
122
  toArrayBuffer: () => toArrayBuffer,
108
123
  toDataURL: () => toDataURL,
109
124
  toNumber: () => toNumber,
@@ -113,7 +128,8 @@ __export(src_exports, {
113
128
  toggleItem: () => toggleItem,
114
129
  tryParseJSON: () => tryParseJSON,
115
130
  uniq: () => uniq,
116
- uniqBy: () => uniqBy
131
+ uniqBy: () => uniqBy,
132
+ upperFirst: () => upperFirst
117
133
  });
118
134
  module.exports = __toCommonJS(src_exports);
119
135
 
@@ -147,16 +163,43 @@ function isPromise(val) {
147
163
  return isObject(val) && isFunction(val.then) && isFunction(val.catch);
148
164
  }
149
165
  function isMap(val) {
150
- return toTypeString(val) === "[object Map]";
166
+ return toRawType(val) === "Map";
151
167
  }
152
168
  function isSet(val) {
153
- return toTypeString(val) === "[object Set]";
169
+ return toRawType(val) === "Set";
154
170
  }
155
171
  function isDate(val) {
156
- return toTypeString(val) === "[object Date]";
172
+ return toRawType(val) === "Date";
157
173
  }
158
174
  function isRegExp(val) {
159
- return toTypeString(val) === "[object RegExp]";
175
+ return toRawType(val) === "RegExp";
176
+ }
177
+ function isWeakMap(val) {
178
+ return toRawType(val) === "WeakMap";
179
+ }
180
+ function isWeakSet(val) {
181
+ return toRawType(val) === "WeakSet";
182
+ }
183
+ function isArrayBuffer(val) {
184
+ return toRawType(val) === "ArrayBuffer";
185
+ }
186
+ function isTypedArray(val) {
187
+ return [
188
+ "Int8Array",
189
+ "Uint8Array",
190
+ "Uint8ClampedArray",
191
+ "Int16Array",
192
+ "Uint16Array",
193
+ "Int32Array",
194
+ "Uint32Array",
195
+ "Float32Array",
196
+ "Float64Array",
197
+ "BigInt64Array",
198
+ "BigUint64Array"
199
+ ].includes(toRawType(val));
200
+ }
201
+ function isDataView(val) {
202
+ return toRawType(val) === "DataView";
160
203
  }
161
204
  function toRawType(value) {
162
205
  return toTypeString(value).slice(8, -1);
@@ -264,12 +307,6 @@ function shuffle(arr) {
264
307
  }
265
308
  return arr;
266
309
  }
267
- function sum(arr) {
268
- return arr.reduce((ret, val) => ret + val, 0);
269
- }
270
- function sumBy(arr, fn) {
271
- return arr.reduce((ret, val) => ret + fn(val), 0);
272
- }
273
310
 
274
311
  // src/string.ts
275
312
  function pascalCase(s) {
@@ -294,9 +331,12 @@ var key = 0;
294
331
  function genStringKey() {
295
332
  return `generated-key-${key++}`;
296
333
  }
297
- function capitalizeFirstLetter(s) {
334
+ function upperFirst(s) {
298
335
  return s.charAt(0).toUpperCase() + s.slice(1);
299
336
  }
337
+ function lowerFirst(s) {
338
+ return s.charAt(0).toLowerCase() + s.slice(1);
339
+ }
300
340
 
301
341
  // src/element.ts
302
342
  function requestAnimationFrame(fn) {
@@ -422,7 +462,7 @@ function createNamespaceFn(namespace) {
422
462
  // src/function.ts
423
463
  function NOOP() {
424
464
  }
425
- function debounce(fn, delay = 0) {
465
+ function debounce(fn, delay2 = 0) {
426
466
  let timer;
427
467
  return function(...args) {
428
468
  if (timer) {
@@ -430,14 +470,14 @@ function debounce(fn, delay = 0) {
430
470
  }
431
471
  timer = setTimeout(() => {
432
472
  fn.apply(this, args);
433
- }, delay);
473
+ }, delay2);
434
474
  };
435
475
  }
436
- function throttle(fn, delay = 200) {
476
+ function throttle(fn, delay2 = 200) {
437
477
  let timer;
438
478
  let start = 0;
439
479
  return function loop(...args) {
440
- const now = Date.now();
480
+ const now = performance.now();
441
481
  const elapsed = now - start;
442
482
  if (!start) {
443
483
  start = now;
@@ -445,13 +485,13 @@ function throttle(fn, delay = 200) {
445
485
  if (timer) {
446
486
  clearTimeout(timer);
447
487
  }
448
- if (elapsed >= delay) {
488
+ if (elapsed >= delay2) {
449
489
  fn.apply(this, args);
450
490
  start = now;
451
491
  } else {
452
492
  timer = setTimeout(() => {
453
493
  loop.apply(this, args);
454
- }, delay - elapsed);
494
+ }, delay2 - elapsed);
455
495
  }
456
496
  };
457
497
  }
@@ -492,15 +532,24 @@ function genNumberKey() {
492
532
  function randomNumber(min = 0, max = 100) {
493
533
  return Math.floor(Math.random() * (max - min + 1)) + min;
494
534
  }
535
+ function times(num, fn) {
536
+ return Array.from({ length: num }, (_, index) => fn(index));
537
+ }
538
+ function delay(time) {
539
+ return new Promise((resolve) => {
540
+ setTimeout(resolve, time);
541
+ });
542
+ }
495
543
 
496
544
  // src/collection.ts
497
- function mergeWith(object, source, callback) {
545
+ var import_types = require("util/types");
546
+ function mergeWith(object, source, fn) {
498
547
  function baseMerge(target, src) {
499
548
  for (const key3 in src) {
500
549
  if (hasOwn(src, key3)) {
501
550
  const srcValue = src[key3];
502
551
  const targetValue = target[key3];
503
- const customResult = callback == null ? void 0 : callback(targetValue, srcValue, key3, object, source);
552
+ const customResult = fn(targetValue, srcValue, key3, object, source);
504
553
  if (customResult !== void 0) {
505
554
  target[key3] = customResult;
506
555
  } else if (isObject(srcValue)) {
@@ -518,6 +567,92 @@ function mergeWith(object, source, callback) {
518
567
  }
519
568
  return baseMerge(object, source);
520
569
  }
570
+ function merge(object, source) {
571
+ return mergeWith(object, source, () => void 0);
572
+ }
573
+ function cloneDeep(value) {
574
+ return cloneDeepWith(value, () => void 0);
575
+ }
576
+ function cloneDeepWith(value, fn) {
577
+ const cache = /* @__PURE__ */ new WeakMap();
578
+ function baseCloneDeep(value2, cache2) {
579
+ const customResult = fn(value2);
580
+ if (customResult !== void 0) {
581
+ return customResult;
582
+ }
583
+ if (!isObject(value2)) {
584
+ return value2;
585
+ }
586
+ if (cache2.has(value2)) {
587
+ return cache2.get(value2);
588
+ }
589
+ if (isDate(value2)) {
590
+ return new Date(value2);
591
+ }
592
+ if ((0, import_types.isRegExp)(value2)) {
593
+ return new RegExp(value2);
594
+ }
595
+ if (isMap(value2)) {
596
+ const result = /* @__PURE__ */ new Map();
597
+ cache2.set(value2, result);
598
+ value2.forEach((val, key3) => {
599
+ result.set(baseCloneDeep(key3, cache2), baseCloneDeep(val, cache2));
600
+ });
601
+ return result;
602
+ }
603
+ if (isSet(value2)) {
604
+ const result = /* @__PURE__ */ new Set();
605
+ cache2.set(value2, result);
606
+ value2.forEach((val) => {
607
+ result.add(baseCloneDeep(val, cache2));
608
+ });
609
+ return result;
610
+ }
611
+ if (toRawType(value2) === "String" || toRawType(value2) === "Number" || toRawType(value2) === "Boolean") {
612
+ return newConstructor(value2, value2.valueOf());
613
+ }
614
+ if ((0, import_types.isWeakMap)(value2) || isWeakSet(value2)) {
615
+ return {};
616
+ }
617
+ if ((0, import_types.isTypedArray)(value2)) {
618
+ return newConstructor(value2, baseCloneArrayBuffer(value2.buffer), value2.byteOffset, value2.length);
619
+ }
620
+ if ((0, import_types.isDataView)(value2)) {
621
+ return newConstructor(value2, baseCloneArrayBuffer(value2.buffer), value2.byteOffset, value2.byteLength);
622
+ }
623
+ if ((0, import_types.isArrayBuffer)(value2)) {
624
+ return baseCloneArrayBuffer(value2);
625
+ }
626
+ if (isArray(value2)) {
627
+ const result = [];
628
+ cache2.set(value2, result);
629
+ value2.forEach((value3, index) => {
630
+ result[index] = baseCloneDeep(value3, cache2);
631
+ });
632
+ return result;
633
+ }
634
+ if (isPlainObject(value2)) {
635
+ const result = Object.create(Reflect.getPrototypeOf(value2));
636
+ cache2.set(value2, result);
637
+ for (const key3 in value2) {
638
+ if (hasOwn(value2, key3)) {
639
+ result[key3] = baseCloneDeep(value2[key3], cache2);
640
+ }
641
+ }
642
+ return result;
643
+ }
644
+ return value2;
645
+ }
646
+ function baseCloneArrayBuffer(value2) {
647
+ const result = new ArrayBuffer(value2.byteLength);
648
+ new Uint8Array(result).set(new Uint8Array(value2));
649
+ return result;
650
+ }
651
+ function newConstructor(value2, ...args) {
652
+ return new value2.constructor(...args);
653
+ }
654
+ return baseCloneDeep(value, cache);
655
+ }
521
656
 
522
657
  // src/json.ts
523
658
  function tryParseJSON(json) {
@@ -587,6 +722,38 @@ function createStorage(storage) {
587
722
  }
588
723
  var sessionStorage = createStorage(globalThis.sessionStorage);
589
724
  var localStorage = createStorage(globalThis.localStorage);
725
+
726
+ // src/math.ts
727
+ function sum(arr) {
728
+ return arr.reduce((ret, val) => ret + val, 0);
729
+ }
730
+ function sumBy(arr, fn) {
731
+ return arr.reduce((ret, val) => ret + fn(val), 0);
732
+ }
733
+ function minBy(arr, fn) {
734
+ if (!arr.length) {
735
+ return;
736
+ }
737
+ return arr.reduce((result, item) => fn(result) < fn(item) ? result : item, arr[0]);
738
+ }
739
+ function maxBy(arr, fn) {
740
+ if (!arr.length) {
741
+ return;
742
+ }
743
+ return arr.reduce((result, item) => fn(result) > fn(item) ? result : item, arr[0]);
744
+ }
745
+ function mean(arr) {
746
+ return sum(arr) / arr.length;
747
+ }
748
+ function meanBy(arr, fn) {
749
+ return sumBy(arr, fn) / arr.length;
750
+ }
751
+ function sample(arr) {
752
+ if (!arr.length) {
753
+ return;
754
+ }
755
+ return arr[randomNumber(0, arr.length - 1)];
756
+ }
590
757
  // Annotate the CommonJS export names for ESM import in node:
591
758
  0 && (module.exports = {
592
759
  NOOP,
@@ -594,13 +761,15 @@ var localStorage = createStorage(globalThis.localStorage);
594
761
  call,
595
762
  camelize,
596
763
  cancelAnimationFrame,
597
- capitalizeFirstLetter,
598
764
  clamp,
599
765
  clampArrayRange,
600
766
  classes,
767
+ cloneDeep,
768
+ cloneDeepWith,
601
769
  createNamespaceFn,
602
770
  createStorage,
603
771
  debounce,
772
+ delay,
604
773
  doubleRaf,
605
774
  find,
606
775
  genNumberKey,
@@ -617,7 +786,9 @@ var localStorage = createStorage(globalThis.localStorage);
617
786
  inMobile,
618
787
  inViewport,
619
788
  isArray,
789
+ isArrayBuffer,
620
790
  isBoolean,
791
+ isDataView,
621
792
  isDate,
622
793
  isEmpty,
623
794
  isFunction,
@@ -634,10 +805,19 @@ var localStorage = createStorage(globalThis.localStorage);
634
805
  isString,
635
806
  isSymbol,
636
807
  isTruthy,
808
+ isTypedArray,
809
+ isWeakMap,
810
+ isWeakSet,
637
811
  isWindow,
638
812
  kebabCase,
639
813
  localStorage,
814
+ lowerFirst,
815
+ maxBy,
816
+ mean,
817
+ meanBy,
818
+ merge,
640
819
  mergeWith,
820
+ minBy,
641
821
  normalizeToArray,
642
822
  objectToString,
643
823
  pascalCase,
@@ -649,6 +829,7 @@ var localStorage = createStorage(globalThis.localStorage);
649
829
  removeArrayEmpty,
650
830
  removeItem,
651
831
  requestAnimationFrame,
832
+ sample,
652
833
  sessionStorage,
653
834
  shuffle,
654
835
  slash,
@@ -656,6 +837,7 @@ var localStorage = createStorage(globalThis.localStorage);
656
837
  sumBy,
657
838
  supportTouch,
658
839
  throttle,
840
+ times,
659
841
  toArrayBuffer,
660
842
  toDataURL,
661
843
  toNumber,
@@ -665,5 +847,6 @@ var localStorage = createStorage(globalThis.localStorage);
665
847
  toggleItem,
666
848
  tryParseJSON,
667
849
  uniq,
668
- uniqBy
850
+ uniqBy,
851
+ upperFirst
669
852
  });
package/lib/index.d.cts CHANGED
@@ -8,8 +8,6 @@ declare const removeArrayEmpty: <T>(arr: Array<T | null | undefined | "">) => T[
8
8
  declare function find<T>(arr: Array<T>, fn: (item: T, index: number, array: Array<T>) => any, from?: 'start' | 'end'): [T, number] | [null, -1];
9
9
  declare function at<T>(arr: T[], index: number): T | undefined;
10
10
  declare function shuffle<T>(arr: T[]): T[];
11
- declare function sum(arr: number[]): number;
12
- declare function sumBy<T>(arr: T[], fn: (val: T) => number): number;
13
11
 
14
12
  declare function requestAnimationFrame(fn: FrameRequestCallback): number;
15
13
  declare function cancelAnimationFrame(handle: number): void;
@@ -34,8 +32,8 @@ declare function createNamespaceFn<N extends string>(namespace: N): <C extends s
34
32
  };
35
33
 
36
34
  declare function NOOP(): void;
37
- declare function debounce(fn: any, delay?: number): (this: unknown, ...args: any[]) => void;
38
- declare function throttle(fn: any, delay?: number): () => void;
35
+ declare function debounce<F extends (...args: any[]) => any>(fn: F, delay?: number): (this: unknown, ...args: Parameters<F>) => void;
36
+ declare function throttle<F extends (...args: any[]) => any>(fn: F, delay?: number): (this: unknown, ...args: Parameters<F>) => void;
39
37
  declare function call<P extends any[], R>(fn?: ((...arg: P) => R) | ((...arg: P) => R)[] | null, ...args: P): R | R[] | undefined;
40
38
 
41
39
  declare const objectToString: typeof Object.prototype.toString;
@@ -52,6 +50,11 @@ declare function isMap(val: unknown): val is Map<any, any>;
52
50
  declare function isSet(val: unknown): val is Set<any>;
53
51
  declare function isDate(val: unknown): val is Date;
54
52
  declare function isRegExp(val: unknown): val is RegExp;
53
+ declare function isWeakMap(val: unknown): val is WeakMap<any, any>;
54
+ declare function isWeakSet(val: unknown): val is WeakSet<any>;
55
+ declare function isArrayBuffer(val: unknown): val is ArrayBuffer;
56
+ declare function isTypedArray(val: unknown): boolean;
57
+ declare function isDataView(val: unknown): val is DataView;
55
58
  declare function toRawType(value: unknown): string;
56
59
  declare function isFunction(val: unknown): val is Function;
57
60
  declare function isArray(val: unknown): val is Array<any>;
@@ -71,15 +74,21 @@ declare function clamp(num: number, min: number, max: number): number;
71
74
  declare function clampArrayRange(index: number, arr: Array<unknown>): number;
72
75
  declare function genNumberKey(): number;
73
76
  declare function randomNumber(min?: number, max?: number): number;
77
+ declare function times<T>(num: number, fn: (index: number) => T): T[];
78
+ declare function delay(time: number): Promise<void>;
74
79
 
75
80
  declare function pascalCase(s: string): string;
76
81
  declare function camelize(s: string): string;
77
82
  declare function kebabCase(s: string): string;
78
83
  declare function slash(path: string): string;
79
84
  declare function genStringKey(): string;
80
- declare function capitalizeFirstLetter(s: string): string;
85
+ declare function upperFirst(s: string): string;
86
+ declare function lowerFirst(s: string): string;
81
87
 
82
- declare function mergeWith<TObject extends Record<string, any>, TSource extends Record<string, any>>(object: TObject, source: TSource, callback?: (objValue: any, srcValue: any, key: string | number | symbol, object?: TObject, source?: TSource) => any | void): TObject & TSource;
88
+ declare function mergeWith<TObject extends Record<string, any>, TSource extends Record<string, any>>(object: TObject, source: TSource, fn: (objValue: any, srcValue: any, key: string | number | symbol, object?: TObject, source?: TSource) => any): TObject & TSource;
89
+ declare function merge<TObject extends Record<string, any>, TSource extends Record<string, any>>(object: TObject, source: TSource): TObject & TSource;
90
+ declare function cloneDeep<T>(value: T): T;
91
+ declare function cloneDeepWith<T>(value: T, fn: (value: any) => any): T;
83
92
 
84
93
  declare function tryParseJSON<T>(json: string): T | undefined;
85
94
  declare function prettyJSONObject(jsonObject: Record<string, any>): string;
@@ -97,4 +106,12 @@ declare function createStorage(storage: globalThis.Storage): Storage;
97
106
  declare const sessionStorage: Storage;
98
107
  declare const localStorage: Storage;
99
108
 
100
- export { type BEM, type ClassName, type Classes, NOOP, type Storage, at, call, camelize, cancelAnimationFrame, capitalizeFirstLetter, clamp, clampArrayRange, classes, createNamespaceFn, createStorage, debounce, doubleRaf, find, genNumberKey, genStringKey, getAllParentScroller, getGlobalThis, getParentScroller, getRect, getScrollLeft, getScrollTop, getStyle, hasOwn, inBrowser, inMobile, inViewport, isArray, isBoolean, isDate, isEmpty, isFunction, isMap, isNonEmptyArray, isNullish, isNumber, isNumeric, isObject, isPlainObject, isPromise, isRegExp, isSet, isString, isSymbol, isTruthy, isWindow, kebabCase, localStorage, mergeWith, normalizeToArray, objectToString, pascalCase, prettyJSONObject, preventDefault, raf, randomNumber, removeArrayBlank, removeArrayEmpty, removeItem, requestAnimationFrame, sessionStorage, shuffle, slash, sum, sumBy, supportTouch, throttle, toArrayBuffer, toDataURL, toNumber, toRawType, toText, toTypeString, toggleItem, tryParseJSON, uniq, uniqBy };
109
+ declare function sum(arr: number[]): number;
110
+ declare function sumBy<T>(arr: T[], fn: (val: T) => number): number;
111
+ declare function minBy<T>(arr: T[], fn: (val: T) => number): T | undefined;
112
+ declare function maxBy<T>(arr: T[], fn: (val: T) => number): T | undefined;
113
+ declare function mean(arr: number[]): number;
114
+ declare function meanBy<T>(arr: T[], fn: (val: T) => number): number;
115
+ declare function sample<T>(arr: T[]): T | undefined;
116
+
117
+ export { type BEM, type ClassName, type Classes, NOOP, type Storage, at, call, camelize, cancelAnimationFrame, clamp, clampArrayRange, classes, cloneDeep, cloneDeepWith, createNamespaceFn, createStorage, debounce, delay, doubleRaf, find, genNumberKey, genStringKey, getAllParentScroller, getGlobalThis, getParentScroller, getRect, getScrollLeft, getScrollTop, getStyle, hasOwn, inBrowser, inMobile, inViewport, isArray, isArrayBuffer, isBoolean, isDataView, isDate, isEmpty, isFunction, isMap, isNonEmptyArray, isNullish, isNumber, isNumeric, isObject, isPlainObject, isPromise, isRegExp, isSet, isString, isSymbol, isTruthy, isTypedArray, isWeakMap, isWeakSet, isWindow, kebabCase, localStorage, lowerFirst, maxBy, mean, meanBy, merge, mergeWith, minBy, normalizeToArray, objectToString, pascalCase, prettyJSONObject, preventDefault, raf, randomNumber, removeArrayBlank, removeArrayEmpty, removeItem, requestAnimationFrame, sample, sessionStorage, shuffle, slash, sum, sumBy, supportTouch, throttle, times, toArrayBuffer, toDataURL, toNumber, toRawType, toText, toTypeString, toggleItem, tryParseJSON, uniq, uniqBy, upperFirst };
package/lib/index.d.ts CHANGED
@@ -8,8 +8,6 @@ declare const removeArrayEmpty: <T>(arr: Array<T | null | undefined | "">) => T[
8
8
  declare function find<T>(arr: Array<T>, fn: (item: T, index: number, array: Array<T>) => any, from?: 'start' | 'end'): [T, number] | [null, -1];
9
9
  declare function at<T>(arr: T[], index: number): T | undefined;
10
10
  declare function shuffle<T>(arr: T[]): T[];
11
- declare function sum(arr: number[]): number;
12
- declare function sumBy<T>(arr: T[], fn: (val: T) => number): number;
13
11
 
14
12
  declare function requestAnimationFrame(fn: FrameRequestCallback): number;
15
13
  declare function cancelAnimationFrame(handle: number): void;
@@ -34,8 +32,8 @@ declare function createNamespaceFn<N extends string>(namespace: N): <C extends s
34
32
  };
35
33
 
36
34
  declare function NOOP(): void;
37
- declare function debounce(fn: any, delay?: number): (this: unknown, ...args: any[]) => void;
38
- declare function throttle(fn: any, delay?: number): () => void;
35
+ declare function debounce<F extends (...args: any[]) => any>(fn: F, delay?: number): (this: unknown, ...args: Parameters<F>) => void;
36
+ declare function throttle<F extends (...args: any[]) => any>(fn: F, delay?: number): (this: unknown, ...args: Parameters<F>) => void;
39
37
  declare function call<P extends any[], R>(fn?: ((...arg: P) => R) | ((...arg: P) => R)[] | null, ...args: P): R | R[] | undefined;
40
38
 
41
39
  declare const objectToString: typeof Object.prototype.toString;
@@ -52,6 +50,11 @@ declare function isMap(val: unknown): val is Map<any, any>;
52
50
  declare function isSet(val: unknown): val is Set<any>;
53
51
  declare function isDate(val: unknown): val is Date;
54
52
  declare function isRegExp(val: unknown): val is RegExp;
53
+ declare function isWeakMap(val: unknown): val is WeakMap<any, any>;
54
+ declare function isWeakSet(val: unknown): val is WeakSet<any>;
55
+ declare function isArrayBuffer(val: unknown): val is ArrayBuffer;
56
+ declare function isTypedArray(val: unknown): boolean;
57
+ declare function isDataView(val: unknown): val is DataView;
55
58
  declare function toRawType(value: unknown): string;
56
59
  declare function isFunction(val: unknown): val is Function;
57
60
  declare function isArray(val: unknown): val is Array<any>;
@@ -71,15 +74,21 @@ declare function clamp(num: number, min: number, max: number): number;
71
74
  declare function clampArrayRange(index: number, arr: Array<unknown>): number;
72
75
  declare function genNumberKey(): number;
73
76
  declare function randomNumber(min?: number, max?: number): number;
77
+ declare function times<T>(num: number, fn: (index: number) => T): T[];
78
+ declare function delay(time: number): Promise<void>;
74
79
 
75
80
  declare function pascalCase(s: string): string;
76
81
  declare function camelize(s: string): string;
77
82
  declare function kebabCase(s: string): string;
78
83
  declare function slash(path: string): string;
79
84
  declare function genStringKey(): string;
80
- declare function capitalizeFirstLetter(s: string): string;
85
+ declare function upperFirst(s: string): string;
86
+ declare function lowerFirst(s: string): string;
81
87
 
82
- declare function mergeWith<TObject extends Record<string, any>, TSource extends Record<string, any>>(object: TObject, source: TSource, callback?: (objValue: any, srcValue: any, key: string | number | symbol, object?: TObject, source?: TSource) => any | void): TObject & TSource;
88
+ declare function mergeWith<TObject extends Record<string, any>, TSource extends Record<string, any>>(object: TObject, source: TSource, fn: (objValue: any, srcValue: any, key: string | number | symbol, object?: TObject, source?: TSource) => any): TObject & TSource;
89
+ declare function merge<TObject extends Record<string, any>, TSource extends Record<string, any>>(object: TObject, source: TSource): TObject & TSource;
90
+ declare function cloneDeep<T>(value: T): T;
91
+ declare function cloneDeepWith<T>(value: T, fn: (value: any) => any): T;
83
92
 
84
93
  declare function tryParseJSON<T>(json: string): T | undefined;
85
94
  declare function prettyJSONObject(jsonObject: Record<string, any>): string;
@@ -97,4 +106,12 @@ declare function createStorage(storage: globalThis.Storage): Storage;
97
106
  declare const sessionStorage: Storage;
98
107
  declare const localStorage: Storage;
99
108
 
100
- export { type BEM, type ClassName, type Classes, NOOP, type Storage, at, call, camelize, cancelAnimationFrame, capitalizeFirstLetter, clamp, clampArrayRange, classes, createNamespaceFn, createStorage, debounce, doubleRaf, find, genNumberKey, genStringKey, getAllParentScroller, getGlobalThis, getParentScroller, getRect, getScrollLeft, getScrollTop, getStyle, hasOwn, inBrowser, inMobile, inViewport, isArray, isBoolean, isDate, isEmpty, isFunction, isMap, isNonEmptyArray, isNullish, isNumber, isNumeric, isObject, isPlainObject, isPromise, isRegExp, isSet, isString, isSymbol, isTruthy, isWindow, kebabCase, localStorage, mergeWith, normalizeToArray, objectToString, pascalCase, prettyJSONObject, preventDefault, raf, randomNumber, removeArrayBlank, removeArrayEmpty, removeItem, requestAnimationFrame, sessionStorage, shuffle, slash, sum, sumBy, supportTouch, throttle, toArrayBuffer, toDataURL, toNumber, toRawType, toText, toTypeString, toggleItem, tryParseJSON, uniq, uniqBy };
109
+ declare function sum(arr: number[]): number;
110
+ declare function sumBy<T>(arr: T[], fn: (val: T) => number): number;
111
+ declare function minBy<T>(arr: T[], fn: (val: T) => number): T | undefined;
112
+ declare function maxBy<T>(arr: T[], fn: (val: T) => number): T | undefined;
113
+ declare function mean(arr: number[]): number;
114
+ declare function meanBy<T>(arr: T[], fn: (val: T) => number): number;
115
+ declare function sample<T>(arr: T[]): T | undefined;
116
+
117
+ export { type BEM, type ClassName, type Classes, NOOP, type Storage, at, call, camelize, cancelAnimationFrame, clamp, clampArrayRange, classes, cloneDeep, cloneDeepWith, createNamespaceFn, createStorage, debounce, delay, doubleRaf, find, genNumberKey, genStringKey, getAllParentScroller, getGlobalThis, getParentScroller, getRect, getScrollLeft, getScrollTop, getStyle, hasOwn, inBrowser, inMobile, inViewport, isArray, isArrayBuffer, isBoolean, isDataView, isDate, isEmpty, isFunction, isMap, isNonEmptyArray, isNullish, isNumber, isNumeric, isObject, isPlainObject, isPromise, isRegExp, isSet, isString, isSymbol, isTruthy, isTypedArray, isWeakMap, isWeakSet, isWindow, kebabCase, localStorage, lowerFirst, maxBy, mean, meanBy, merge, mergeWith, minBy, normalizeToArray, objectToString, pascalCase, prettyJSONObject, preventDefault, raf, randomNumber, removeArrayBlank, removeArrayEmpty, removeItem, requestAnimationFrame, sample, sessionStorage, shuffle, slash, sum, sumBy, supportTouch, throttle, times, toArrayBuffer, toDataURL, toNumber, toRawType, toText, toTypeString, toggleItem, tryParseJSON, uniq, uniqBy, upperFirst };
package/lib/index.js CHANGED
@@ -48,16 +48,43 @@ function isPromise(val) {
48
48
  return isObject(val) && isFunction(val.then) && isFunction(val.catch);
49
49
  }
50
50
  function isMap(val) {
51
- return toTypeString(val) === "[object Map]";
51
+ return toRawType(val) === "Map";
52
52
  }
53
53
  function isSet(val) {
54
- return toTypeString(val) === "[object Set]";
54
+ return toRawType(val) === "Set";
55
55
  }
56
56
  function isDate(val) {
57
- return toTypeString(val) === "[object Date]";
57
+ return toRawType(val) === "Date";
58
58
  }
59
59
  function isRegExp(val) {
60
- return toTypeString(val) === "[object RegExp]";
60
+ return toRawType(val) === "RegExp";
61
+ }
62
+ function isWeakMap(val) {
63
+ return toRawType(val) === "WeakMap";
64
+ }
65
+ function isWeakSet(val) {
66
+ return toRawType(val) === "WeakSet";
67
+ }
68
+ function isArrayBuffer(val) {
69
+ return toRawType(val) === "ArrayBuffer";
70
+ }
71
+ function isTypedArray(val) {
72
+ return [
73
+ "Int8Array",
74
+ "Uint8Array",
75
+ "Uint8ClampedArray",
76
+ "Int16Array",
77
+ "Uint16Array",
78
+ "Int32Array",
79
+ "Uint32Array",
80
+ "Float32Array",
81
+ "Float64Array",
82
+ "BigInt64Array",
83
+ "BigUint64Array"
84
+ ].includes(toRawType(val));
85
+ }
86
+ function isDataView(val) {
87
+ return toRawType(val) === "DataView";
61
88
  }
62
89
  function toRawType(value) {
63
90
  return toTypeString(value).slice(8, -1);
@@ -165,12 +192,6 @@ function shuffle(arr) {
165
192
  }
166
193
  return arr;
167
194
  }
168
- function sum(arr) {
169
- return arr.reduce((ret, val) => ret + val, 0);
170
- }
171
- function sumBy(arr, fn) {
172
- return arr.reduce((ret, val) => ret + fn(val), 0);
173
- }
174
195
 
175
196
  // src/string.ts
176
197
  function pascalCase(s) {
@@ -195,9 +216,12 @@ var key = 0;
195
216
  function genStringKey() {
196
217
  return `generated-key-${key++}`;
197
218
  }
198
- function capitalizeFirstLetter(s) {
219
+ function upperFirst(s) {
199
220
  return s.charAt(0).toUpperCase() + s.slice(1);
200
221
  }
222
+ function lowerFirst(s) {
223
+ return s.charAt(0).toLowerCase() + s.slice(1);
224
+ }
201
225
 
202
226
  // src/element.ts
203
227
  function requestAnimationFrame(fn) {
@@ -323,7 +347,7 @@ function createNamespaceFn(namespace) {
323
347
  // src/function.ts
324
348
  function NOOP() {
325
349
  }
326
- function debounce(fn, delay = 0) {
350
+ function debounce(fn, delay2 = 0) {
327
351
  let timer;
328
352
  return function(...args) {
329
353
  if (timer) {
@@ -331,14 +355,14 @@ function debounce(fn, delay = 0) {
331
355
  }
332
356
  timer = setTimeout(() => {
333
357
  fn.apply(this, args);
334
- }, delay);
358
+ }, delay2);
335
359
  };
336
360
  }
337
- function throttle(fn, delay = 200) {
361
+ function throttle(fn, delay2 = 200) {
338
362
  let timer;
339
363
  let start = 0;
340
364
  return function loop(...args) {
341
- const now = Date.now();
365
+ const now = performance.now();
342
366
  const elapsed = now - start;
343
367
  if (!start) {
344
368
  start = now;
@@ -346,13 +370,13 @@ function throttle(fn, delay = 200) {
346
370
  if (timer) {
347
371
  clearTimeout(timer);
348
372
  }
349
- if (elapsed >= delay) {
373
+ if (elapsed >= delay2) {
350
374
  fn.apply(this, args);
351
375
  start = now;
352
376
  } else {
353
377
  timer = setTimeout(() => {
354
378
  loop.apply(this, args);
355
- }, delay - elapsed);
379
+ }, delay2 - elapsed);
356
380
  }
357
381
  };
358
382
  }
@@ -393,15 +417,24 @@ function genNumberKey() {
393
417
  function randomNumber(min = 0, max = 100) {
394
418
  return Math.floor(Math.random() * (max - min + 1)) + min;
395
419
  }
420
+ function times(num, fn) {
421
+ return Array.from({ length: num }, (_, index) => fn(index));
422
+ }
423
+ function delay(time) {
424
+ return new Promise((resolve) => {
425
+ setTimeout(resolve, time);
426
+ });
427
+ }
396
428
 
397
429
  // src/collection.ts
398
- function mergeWith(object, source, callback) {
430
+ import { isArrayBuffer as isArrayBuffer2, isDataView as isDataView2, isRegExp as isRegExp2, isTypedArray as isTypedArray2, isWeakMap as isWeakMap2 } from "util/types";
431
+ function mergeWith(object, source, fn) {
399
432
  function baseMerge(target, src) {
400
433
  for (const key3 in src) {
401
434
  if (hasOwn(src, key3)) {
402
435
  const srcValue = src[key3];
403
436
  const targetValue = target[key3];
404
- const customResult = callback == null ? void 0 : callback(targetValue, srcValue, key3, object, source);
437
+ const customResult = fn(targetValue, srcValue, key3, object, source);
405
438
  if (customResult !== void 0) {
406
439
  target[key3] = customResult;
407
440
  } else if (isObject(srcValue)) {
@@ -419,6 +452,92 @@ function mergeWith(object, source, callback) {
419
452
  }
420
453
  return baseMerge(object, source);
421
454
  }
455
+ function merge(object, source) {
456
+ return mergeWith(object, source, () => void 0);
457
+ }
458
+ function cloneDeep(value) {
459
+ return cloneDeepWith(value, () => void 0);
460
+ }
461
+ function cloneDeepWith(value, fn) {
462
+ const cache = /* @__PURE__ */ new WeakMap();
463
+ function baseCloneDeep(value2, cache2) {
464
+ const customResult = fn(value2);
465
+ if (customResult !== void 0) {
466
+ return customResult;
467
+ }
468
+ if (!isObject(value2)) {
469
+ return value2;
470
+ }
471
+ if (cache2.has(value2)) {
472
+ return cache2.get(value2);
473
+ }
474
+ if (isDate(value2)) {
475
+ return new Date(value2);
476
+ }
477
+ if (isRegExp2(value2)) {
478
+ return new RegExp(value2);
479
+ }
480
+ if (isMap(value2)) {
481
+ const result = /* @__PURE__ */ new Map();
482
+ cache2.set(value2, result);
483
+ value2.forEach((val, key3) => {
484
+ result.set(baseCloneDeep(key3, cache2), baseCloneDeep(val, cache2));
485
+ });
486
+ return result;
487
+ }
488
+ if (isSet(value2)) {
489
+ const result = /* @__PURE__ */ new Set();
490
+ cache2.set(value2, result);
491
+ value2.forEach((val) => {
492
+ result.add(baseCloneDeep(val, cache2));
493
+ });
494
+ return result;
495
+ }
496
+ if (toRawType(value2) === "String" || toRawType(value2) === "Number" || toRawType(value2) === "Boolean") {
497
+ return newConstructor(value2, value2.valueOf());
498
+ }
499
+ if (isWeakMap2(value2) || isWeakSet(value2)) {
500
+ return {};
501
+ }
502
+ if (isTypedArray2(value2)) {
503
+ return newConstructor(value2, baseCloneArrayBuffer(value2.buffer), value2.byteOffset, value2.length);
504
+ }
505
+ if (isDataView2(value2)) {
506
+ return newConstructor(value2, baseCloneArrayBuffer(value2.buffer), value2.byteOffset, value2.byteLength);
507
+ }
508
+ if (isArrayBuffer2(value2)) {
509
+ return baseCloneArrayBuffer(value2);
510
+ }
511
+ if (isArray(value2)) {
512
+ const result = [];
513
+ cache2.set(value2, result);
514
+ value2.forEach((value3, index) => {
515
+ result[index] = baseCloneDeep(value3, cache2);
516
+ });
517
+ return result;
518
+ }
519
+ if (isPlainObject(value2)) {
520
+ const result = Object.create(Reflect.getPrototypeOf(value2));
521
+ cache2.set(value2, result);
522
+ for (const key3 in value2) {
523
+ if (hasOwn(value2, key3)) {
524
+ result[key3] = baseCloneDeep(value2[key3], cache2);
525
+ }
526
+ }
527
+ return result;
528
+ }
529
+ return value2;
530
+ }
531
+ function baseCloneArrayBuffer(value2) {
532
+ const result = new ArrayBuffer(value2.byteLength);
533
+ new Uint8Array(result).set(new Uint8Array(value2));
534
+ return result;
535
+ }
536
+ function newConstructor(value2, ...args) {
537
+ return new value2.constructor(...args);
538
+ }
539
+ return baseCloneDeep(value, cache);
540
+ }
422
541
 
423
542
  // src/json.ts
424
543
  function tryParseJSON(json) {
@@ -488,19 +607,53 @@ function createStorage(storage) {
488
607
  }
489
608
  var sessionStorage = createStorage(globalThis.sessionStorage);
490
609
  var localStorage = createStorage(globalThis.localStorage);
610
+
611
+ // src/math.ts
612
+ function sum(arr) {
613
+ return arr.reduce((ret, val) => ret + val, 0);
614
+ }
615
+ function sumBy(arr, fn) {
616
+ return arr.reduce((ret, val) => ret + fn(val), 0);
617
+ }
618
+ function minBy(arr, fn) {
619
+ if (!arr.length) {
620
+ return;
621
+ }
622
+ return arr.reduce((result, item) => fn(result) < fn(item) ? result : item, arr[0]);
623
+ }
624
+ function maxBy(arr, fn) {
625
+ if (!arr.length) {
626
+ return;
627
+ }
628
+ return arr.reduce((result, item) => fn(result) > fn(item) ? result : item, arr[0]);
629
+ }
630
+ function mean(arr) {
631
+ return sum(arr) / arr.length;
632
+ }
633
+ function meanBy(arr, fn) {
634
+ return sumBy(arr, fn) / arr.length;
635
+ }
636
+ function sample(arr) {
637
+ if (!arr.length) {
638
+ return;
639
+ }
640
+ return arr[randomNumber(0, arr.length - 1)];
641
+ }
491
642
  export {
492
643
  NOOP,
493
644
  at,
494
645
  call,
495
646
  camelize,
496
647
  cancelAnimationFrame,
497
- capitalizeFirstLetter,
498
648
  clamp,
499
649
  clampArrayRange,
500
650
  classes,
651
+ cloneDeep,
652
+ cloneDeepWith,
501
653
  createNamespaceFn,
502
654
  createStorage,
503
655
  debounce,
656
+ delay,
504
657
  doubleRaf,
505
658
  find,
506
659
  genNumberKey,
@@ -517,7 +670,9 @@ export {
517
670
  inMobile,
518
671
  inViewport,
519
672
  isArray,
673
+ isArrayBuffer,
520
674
  isBoolean,
675
+ isDataView,
521
676
  isDate,
522
677
  isEmpty,
523
678
  isFunction,
@@ -534,10 +689,19 @@ export {
534
689
  isString,
535
690
  isSymbol,
536
691
  isTruthy,
692
+ isTypedArray,
693
+ isWeakMap,
694
+ isWeakSet,
537
695
  isWindow,
538
696
  kebabCase,
539
697
  localStorage,
698
+ lowerFirst,
699
+ maxBy,
700
+ mean,
701
+ meanBy,
702
+ merge,
540
703
  mergeWith,
704
+ minBy,
541
705
  normalizeToArray,
542
706
  objectToString,
543
707
  pascalCase,
@@ -549,6 +713,7 @@ export {
549
713
  removeArrayEmpty,
550
714
  removeItem,
551
715
  requestAnimationFrame,
716
+ sample,
552
717
  sessionStorage,
553
718
  shuffle,
554
719
  slash,
@@ -556,6 +721,7 @@ export {
556
721
  sumBy,
557
722
  supportTouch,
558
723
  throttle,
724
+ times,
559
725
  toArrayBuffer,
560
726
  toDataURL,
561
727
  toNumber,
@@ -565,5 +731,6 @@ export {
565
731
  toggleItem,
566
732
  tryParseJSON,
567
733
  uniq,
568
- uniqBy
734
+ uniqBy,
735
+ upperFirst
569
736
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rattail",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "type": "module",
5
5
  "main": "lib/index.cjs",
6
6
  "module": "lib/index.js",
@@ -51,7 +51,7 @@
51
51
  "scripts": {
52
52
  "dev": "tsup src/index.ts --format esm --out-dir=lib --watch --dts",
53
53
  "build": "tsup src/index.ts --format esm,cjs --out-dir=lib --dts --clean",
54
- "lint": "eslint --ext .ts,.js",
54
+ "lint": "eslint . --fix --ext .ts,.js",
55
55
  "format": "prettier --write .",
56
56
  "clean": "rimraf node_modules lib",
57
57
  "test:watch": "vitest --coverage",