@splendidlabz/utils 1.7.0 → 1.8.2

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.
Files changed (52) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cjs/dom/font-size.cjs +1 -1
  3. package/dist/cjs/dom/index.cjs +91 -1
  4. package/dist/cjs/dom/observers/index.cjs +92 -2
  5. package/dist/cjs/dom/observers/scroll-observer.cjs +170 -0
  6. package/dist/cjs/lib/date/index.cjs +3 -1
  7. package/dist/cjs/lib/date/time.cjs +3 -1
  8. package/dist/cjs/lib/functions/functional.cjs +20 -0
  9. package/dist/cjs/lib/functions/index.cjs +20 -0
  10. package/dist/cjs/lib/index.cjs +27 -2
  11. package/dist/cjs/lib/numbers/index.cjs +1 -1
  12. package/dist/cjs/lib/objects/extend.cjs +2 -1
  13. package/dist/cjs/lib/objects/index.cjs +4 -1
  14. package/dist/cjs/lib/objects/mix/mix.cjs +4 -1
  15. package/dist/cjs/node/file-cache.cjs +3 -3
  16. package/dist/cjs/node/index.cjs +3 -3
  17. package/dist/esm/dom/font-size.js +1 -1
  18. package/dist/esm/dom/index.js +90 -1
  19. package/dist/esm/dom/observers/index.js +90 -1
  20. package/dist/esm/dom/observers/scroll-observer.js +144 -0
  21. package/dist/esm/lib/date/index.js +3 -1
  22. package/dist/esm/lib/date/time.js +3 -1
  23. package/dist/esm/lib/functions/functional.js +18 -0
  24. package/dist/esm/lib/functions/index.js +18 -0
  25. package/dist/esm/lib/index.js +24 -2
  26. package/dist/esm/lib/numbers/index.js +1 -1
  27. package/dist/esm/lib/objects/extend.js +2 -1
  28. package/dist/esm/lib/objects/index.js +3 -1
  29. package/dist/esm/lib/objects/mix/mix.js +3 -1
  30. package/dist/esm/node/file-cache.js +1 -1
  31. package/dist/esm/node/index.js +1 -1
  32. package/dist/types/dom/index.d.cts +1 -0
  33. package/dist/types/dom/observers/index.d.cts +1 -0
  34. package/dist/types/dom/observers/scroll-observer.d.cts +27 -0
  35. package/dist/types/lib/functions/functional.d.cts +71 -5
  36. package/dist/types/lib/functions/index.d.cts +1 -1
  37. package/dist/types/lib/index.d.cts +2 -2
  38. package/dist/types/lib/objects/extend.d.cts +1 -1
  39. package/dist/types/lib/objects/index.d.cts +1 -1
  40. package/dist/types/lib/objects/mix/mix.d.cts +43 -3
  41. package/package.json +2 -3
  42. package/src/dom/observers/index.js +1 -0
  43. package/src/dom/observers/resize-observer.js +5 -5
  44. package/src/dom/observers/scroll-observer.js +132 -0
  45. package/src/lib/date/time.js +2 -0
  46. package/src/lib/functions/functional.js +82 -0
  47. package/src/lib/functions/functional.test.js +196 -0
  48. package/src/lib/numbers/index.js +1 -1
  49. package/src/lib/numbers/split-unit.test.js +45 -0
  50. package/src/lib/objects/mix/mix.js +74 -4
  51. package/src/lib/objects/mix/mix.test.js +51 -2
  52. package/src/node/file-cache.js +1 -1
@@ -49,8 +49,9 @@ function curry(fn) {
49
49
  }
50
50
 
51
51
  // src/lib/objects/mix/mix.js
52
- var DEFAULT_OPTIONS = { array: "concat" };
52
+ var DEFAULT_OPTIONS = { array: "replace" };
53
53
  var mix = createMix();
54
+ var concatMix = createMix({ array: "concat" });
54
55
  function createMix(userOptions = {}) {
55
56
  const options = { ...DEFAULT_OPTIONS, ...userOptions };
56
57
  function _mix(...sources) {
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  var objects_exports = {};
31
31
  __export(objects_exports, {
32
32
  camelCaseKeys: () => camelCaseKeys,
33
+ concatMix: () => concatMix,
33
34
  createMix: () => createMix,
34
35
  extendObject: () => extendObject,
35
36
  flattenObject: () => flattenObject,
@@ -147,8 +148,9 @@ function pipe(...fns) {
147
148
  }
148
149
 
149
150
  // src/lib/objects/mix/mix.js
150
- var DEFAULT_OPTIONS = { array: "concat" };
151
+ var DEFAULT_OPTIONS = { array: "replace" };
151
152
  var mix = createMix();
153
+ var concatMix = createMix({ array: "concat" });
152
154
  function createMix(userOptions = {}) {
153
155
  const options = { ...DEFAULT_OPTIONS, ...userOptions };
154
156
  function _mix(...sources) {
@@ -354,6 +356,7 @@ function splitObject(obj, keys) {
354
356
  // Annotate the CommonJS export names for ESM import in node:
355
357
  0 && (module.exports = {
356
358
  camelCaseKeys,
359
+ concatMix,
357
360
  createMix,
358
361
  extendObject,
359
362
  flattenObject,
@@ -19,12 +19,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  // src/lib/objects/mix/mix.js
20
20
  var mix_exports = {};
21
21
  __export(mix_exports, {
22
+ concatMix: () => concatMix,
22
23
  createMix: () => createMix,
23
24
  mix: () => mix
24
25
  });
25
26
  module.exports = __toCommonJS(mix_exports);
26
- var DEFAULT_OPTIONS = { array: "concat" };
27
+ var DEFAULT_OPTIONS = { array: "replace" };
27
28
  var mix = createMix();
29
+ var concatMix = createMix({ array: "concat" });
28
30
  function createMix(userOptions = {}) {
29
31
  const options = { ...DEFAULT_OPTIONS, ...userOptions };
30
32
  function _mix(...sources) {
@@ -107,6 +109,7 @@ function objectType(value) {
107
109
  }
108
110
  // Annotate the CommonJS export names for ESM import in node:
109
111
  0 && (module.exports = {
112
+ concatMix,
110
113
  createMix,
111
114
  mix
112
115
  });
@@ -37,7 +37,7 @@ __export(file_cache_exports, {
37
37
  });
38
38
  module.exports = __toCommonJS(file_cache_exports);
39
39
  var import_promises = __toESM(require("fs/promises"), 1);
40
- var import_glob_promise = __toESM(require("glob-promise"), 1);
40
+ var import_glob = require("glob");
41
41
  var import_node_path = __toESM(require("path"), 1);
42
42
 
43
43
  // src/lib/objects/nested-property.js
@@ -164,11 +164,11 @@ async function fileCache({ dir, file }) {
164
164
  async function getLastModifiedTime(globPath) {
165
165
  let files;
166
166
  if (typeof globPath === "string") {
167
- files = await (0, import_glob_promise.default)(removeFirstSlash(globPath));
167
+ files = await (0, import_glob.glob)(removeFirstSlash(globPath));
168
168
  }
169
169
  if (Array.isArray(globPath)) {
170
170
  const a = await Promise.all(
171
- globPath.map((path2) => (0, import_glob_promise.default)(removeFirstSlash(path2)))
171
+ globPath.map((path2) => (0, import_glob.glob)(removeFirstSlash(path2)))
172
172
  );
173
173
  files = a.flat();
174
174
  }
@@ -63,7 +63,7 @@ function dirname(url) {
63
63
 
64
64
  // src/node/file-cache.js
65
65
  var import_promises = __toESM(require("fs/promises"), 1);
66
- var import_glob_promise = __toESM(require("glob-promise"), 1);
66
+ var import_glob = require("glob");
67
67
  var import_node_path2 = __toESM(require("path"), 1);
68
68
 
69
69
  // src/lib/objects/nested-property.js
@@ -190,11 +190,11 @@ async function fileCache({ dir, file }) {
190
190
  async function getLastModifiedTime(globPath) {
191
191
  let files;
192
192
  if (typeof globPath === "string") {
193
- files = await (0, import_glob_promise.default)(removeFirstSlash(globPath));
193
+ files = await (0, import_glob.glob)(removeFirstSlash(globPath));
194
194
  }
195
195
  if (Array.isArray(globPath)) {
196
196
  const a = await Promise.all(
197
- globPath.map((path3) => (0, import_glob_promise.default)(removeFirstSlash(path3)))
197
+ globPath.map((path3) => (0, import_glob.glob)(removeFirstSlash(path3)))
198
198
  );
199
199
  files = a.flat();
200
200
  }
@@ -1,7 +1,7 @@
1
1
  // src/lib/numbers/index.js
2
2
  function splitUnit(string) {
3
3
  if (typeof string === "number") return [string, null];
4
- const regex = /(-?\d*\.?\d+)([a-z]+)/i;
4
+ const regex = /(-?\d*\.?\d+)\s*([a-z]+)/i;
5
5
  const match = string.match(regex);
6
6
  if (match) return [parseFloat(match[1]), match[2]];
7
7
  return [parseFloat(string), null];
@@ -242,7 +242,7 @@ function nativeMasonrySupport(node) {
242
242
  // src/lib/numbers/index.js
243
243
  function splitUnit(string) {
244
244
  if (typeof string === "number") return [string, null];
245
- const regex = /(-?\d*\.?\d+)([a-z]+)/i;
245
+ const regex = /(-?\d*\.?\d+)\s*([a-z]+)/i;
246
246
  const match = string.match(regex);
247
247
  if (match) return [parseFloat(match[1]), match[2]];
248
248
  return [parseFloat(string), null];
@@ -847,6 +847,94 @@ function mutationObserver(target, options) {
847
847
  };
848
848
  }
849
849
 
850
+ // src/dom/observers/scroll-observer.js
851
+ var defaultOptions2 = {
852
+ threshold: 0,
853
+ // Float between 0 to 1.
854
+ tolerance: 0.1,
855
+ // Float between 0 to 1. Tolerance for event firing
856
+ throttle: 16,
857
+ // Throttle interval in ms (default: ~60fps)
858
+ once: false
859
+ // Only fire threshold callback once
860
+ };
861
+ function scrollObserver(node, options = {}) {
862
+ const { callback, onScrollDown, onScrollUp, onEnterThreshold, ...userOpts } = options;
863
+ const opts = { ...defaultOptions2, ...userOpts };
864
+ const { threshold, tolerance, throttle, once } = opts;
865
+ const prevScrollDirection = null;
866
+ let prevScrollTop = 0;
867
+ let prevScrollPercent = 0;
868
+ let lastThrottleTime = 0;
869
+ let thresholdFired = false;
870
+ let rafId = null;
871
+ const isDocumentScroll = node === document || node === window;
872
+ const scrollElement = isDocumentScroll ? document.documentElement : node;
873
+ let cachedScrollHeight = 0;
874
+ let cachedClientHeight = 0;
875
+ updateCache();
876
+ const cacheObserver = resizeObserver(scrollElement, {
877
+ callback: updateCache
878
+ });
879
+ node.addEventListener("scroll", throttledObserve, { passive: true });
880
+ function updateCache() {
881
+ cachedScrollHeight = scrollElement.scrollHeight;
882
+ cachedClientHeight = scrollElement.clientHeight;
883
+ }
884
+ function throttledObserve() {
885
+ const now = Date.now();
886
+ if (now - lastThrottleTime < throttle) return;
887
+ lastThrottleTime = now;
888
+ rafId = requestAnimationFrame(observe);
889
+ }
890
+ function observe() {
891
+ const scrollTop = scrollElement.scrollTop;
892
+ if (Math.abs(scrollTop - prevScrollTop) < 1) return;
893
+ const scrollDirection = scrollTop > prevScrollTop ? "down" : "up";
894
+ const maxScroll = Math.max(1, cachedScrollHeight - cachedClientHeight);
895
+ const scrollPercent = Math.min(1, Math.max(0, scrollTop / maxScroll));
896
+ const thresholdMin = threshold - tolerance / 2;
897
+ const thresholdMax = threshold + tolerance / 2;
898
+ const wasInThreshold = prevScrollPercent >= thresholdMin && prevScrollPercent <= thresholdMax;
899
+ const isInThreshold = scrollPercent >= thresholdMin && scrollPercent <= thresholdMax;
900
+ const hasEnteredThreshold = !wasInThreshold && isInThreshold && (!once || !thresholdFired);
901
+ if (hasEnteredThreshold && once) {
902
+ thresholdFired = true;
903
+ }
904
+ const callbackData = {
905
+ scrollTop,
906
+ scrollDirection,
907
+ scrollPercent,
908
+ directionChanged: scrollDirection !== prevScrollDirection,
909
+ hasEnteredThreshold,
910
+ isInThreshold
911
+ };
912
+ if (typeof callback === "function") {
913
+ callback(callbackData);
914
+ }
915
+ if (scrollDirection !== prevScrollDirection) {
916
+ if (scrollDirection === "down" && typeof onScrollDown === "function") {
917
+ onScrollDown(callbackData);
918
+ }
919
+ if (scrollDirection === "up" && typeof onScrollUp === "function") {
920
+ onScrollUp(callbackData);
921
+ }
922
+ }
923
+ if (hasEnteredThreshold && typeof onEnterThreshold === "function") {
924
+ onEnterThreshold(callbackData);
925
+ }
926
+ prevScrollTop = scrollTop;
927
+ prevScrollPercent = scrollPercent;
928
+ }
929
+ return {
930
+ destroy() {
931
+ node.removeEventListener("scroll", throttledObserve);
932
+ if (rafId) cancelAnimationFrame(rafId);
933
+ cacheObserver.destroy();
934
+ }
935
+ };
936
+ }
937
+
850
938
  // src/dom/random-string.js
851
939
  function randomString(length = 10) {
852
940
  const firstLetter = String.fromCharCode(65 + Math.floor(Math.random() * 26));
@@ -1085,6 +1173,7 @@ export {
1085
1173
  removeListeners,
1086
1174
  resizeObserver,
1087
1175
  sanitize2 as sanitize,
1176
+ scrollObserver,
1088
1177
  scrollToElement,
1089
1178
  sessionStore,
1090
1179
  setCSSValue,
@@ -121,8 +121,97 @@ function resizeObserver(target, options) {
121
121
  destroy: (_) => observer.disconnect()
122
122
  };
123
123
  }
124
+
125
+ // src/dom/observers/scroll-observer.js
126
+ var defaultOptions2 = {
127
+ threshold: 0,
128
+ // Float between 0 to 1.
129
+ tolerance: 0.1,
130
+ // Float between 0 to 1. Tolerance for event firing
131
+ throttle: 16,
132
+ // Throttle interval in ms (default: ~60fps)
133
+ once: false
134
+ // Only fire threshold callback once
135
+ };
136
+ function scrollObserver(node, options = {}) {
137
+ const { callback, onScrollDown, onScrollUp, onEnterThreshold, ...userOpts } = options;
138
+ const opts = { ...defaultOptions2, ...userOpts };
139
+ const { threshold, tolerance, throttle, once } = opts;
140
+ const prevScrollDirection = null;
141
+ let prevScrollTop = 0;
142
+ let prevScrollPercent = 0;
143
+ let lastThrottleTime = 0;
144
+ let thresholdFired = false;
145
+ let rafId = null;
146
+ const isDocumentScroll = node === document || node === window;
147
+ const scrollElement = isDocumentScroll ? document.documentElement : node;
148
+ let cachedScrollHeight = 0;
149
+ let cachedClientHeight = 0;
150
+ updateCache();
151
+ const cacheObserver = resizeObserver(scrollElement, {
152
+ callback: updateCache
153
+ });
154
+ node.addEventListener("scroll", throttledObserve, { passive: true });
155
+ function updateCache() {
156
+ cachedScrollHeight = scrollElement.scrollHeight;
157
+ cachedClientHeight = scrollElement.clientHeight;
158
+ }
159
+ function throttledObserve() {
160
+ const now = Date.now();
161
+ if (now - lastThrottleTime < throttle) return;
162
+ lastThrottleTime = now;
163
+ rafId = requestAnimationFrame(observe);
164
+ }
165
+ function observe() {
166
+ const scrollTop = scrollElement.scrollTop;
167
+ if (Math.abs(scrollTop - prevScrollTop) < 1) return;
168
+ const scrollDirection = scrollTop > prevScrollTop ? "down" : "up";
169
+ const maxScroll = Math.max(1, cachedScrollHeight - cachedClientHeight);
170
+ const scrollPercent = Math.min(1, Math.max(0, scrollTop / maxScroll));
171
+ const thresholdMin = threshold - tolerance / 2;
172
+ const thresholdMax = threshold + tolerance / 2;
173
+ const wasInThreshold = prevScrollPercent >= thresholdMin && prevScrollPercent <= thresholdMax;
174
+ const isInThreshold = scrollPercent >= thresholdMin && scrollPercent <= thresholdMax;
175
+ const hasEnteredThreshold = !wasInThreshold && isInThreshold && (!once || !thresholdFired);
176
+ if (hasEnteredThreshold && once) {
177
+ thresholdFired = true;
178
+ }
179
+ const callbackData = {
180
+ scrollTop,
181
+ scrollDirection,
182
+ scrollPercent,
183
+ directionChanged: scrollDirection !== prevScrollDirection,
184
+ hasEnteredThreshold,
185
+ isInThreshold
186
+ };
187
+ if (typeof callback === "function") {
188
+ callback(callbackData);
189
+ }
190
+ if (scrollDirection !== prevScrollDirection) {
191
+ if (scrollDirection === "down" && typeof onScrollDown === "function") {
192
+ onScrollDown(callbackData);
193
+ }
194
+ if (scrollDirection === "up" && typeof onScrollUp === "function") {
195
+ onScrollUp(callbackData);
196
+ }
197
+ }
198
+ if (hasEnteredThreshold && typeof onEnterThreshold === "function") {
199
+ onEnterThreshold(callbackData);
200
+ }
201
+ prevScrollTop = scrollTop;
202
+ prevScrollPercent = scrollPercent;
203
+ }
204
+ return {
205
+ destroy() {
206
+ node.removeEventListener("scroll", throttledObserve);
207
+ if (rafId) cancelAnimationFrame(rafId);
208
+ cacheObserver.destroy();
209
+ }
210
+ };
211
+ }
124
212
  export {
125
213
  intersectionObserver,
126
214
  mutationObserver,
127
- resizeObserver
215
+ resizeObserver,
216
+ scrollObserver
128
217
  };
@@ -0,0 +1,144 @@
1
+ // src/dom/events.js
2
+ function dispatchEvent(node, eventName, detail, options = {}) {
3
+ node.dispatchEvent(
4
+ new CustomEvent(eventName, {
5
+ ...options,
6
+ detail
7
+ })
8
+ );
9
+ }
10
+
11
+ // src/dom/get-element.js
12
+ function getNodeType(node) {
13
+ if (node instanceof Element) return "element";
14
+ if (node instanceof NodeList) return "nodelist";
15
+ if (Array.isArray(node)) return "array";
16
+ }
17
+
18
+ // src/dom/observers/observer.js
19
+ function useObserverMethodOnTarget(target, observer, method = "observe", options = void 0) {
20
+ const targetType = getNodeType(target);
21
+ if (targetType === "element") observer[method](target, options);
22
+ if (targetType === "nodelist") {
23
+ const elements = Array.from(target);
24
+ elements.forEach((element) => observer[method](element, options));
25
+ }
26
+ if (targetType === "array") {
27
+ target.forEach((element) => observer[method](element, options));
28
+ }
29
+ }
30
+
31
+ // src/dom/observers/resize-observer.js
32
+ function resizeObserver(target, options) {
33
+ const { callback, ...opts } = options;
34
+ const observer = new ResizeObserver(observerFn);
35
+ if (target === window) target = document.body;
36
+ useObserverMethodOnTarget(target, observer, "observe", opts);
37
+ function observerFn(entries) {
38
+ for (const entry of entries) {
39
+ if (callback) callback({ entry, entries, observer });
40
+ else dispatchEvent(target, "resize-obs", { entry, entries, observer });
41
+ }
42
+ }
43
+ return {
44
+ observe(target2) {
45
+ useObserverMethodOnTarget(target2, observer, "observe", options);
46
+ },
47
+ unobserve(target2) {
48
+ useObserverMethodOnTarget(target2, observer, "unobserve");
49
+ },
50
+ disconnect: (_) => observer.disconnect(),
51
+ destroy: (_) => observer.disconnect()
52
+ };
53
+ }
54
+
55
+ // src/dom/observers/scroll-observer.js
56
+ var defaultOptions = {
57
+ threshold: 0,
58
+ // Float between 0 to 1.
59
+ tolerance: 0.1,
60
+ // Float between 0 to 1. Tolerance for event firing
61
+ throttle: 16,
62
+ // Throttle interval in ms (default: ~60fps)
63
+ once: false
64
+ // Only fire threshold callback once
65
+ };
66
+ function scrollObserver(node, options = {}) {
67
+ const { callback, onScrollDown, onScrollUp, onEnterThreshold, ...userOpts } = options;
68
+ const opts = { ...defaultOptions, ...userOpts };
69
+ const { threshold, tolerance, throttle, once } = opts;
70
+ const prevScrollDirection = null;
71
+ let prevScrollTop = 0;
72
+ let prevScrollPercent = 0;
73
+ let lastThrottleTime = 0;
74
+ let thresholdFired = false;
75
+ let rafId = null;
76
+ const isDocumentScroll = node === document || node === window;
77
+ const scrollElement = isDocumentScroll ? document.documentElement : node;
78
+ let cachedScrollHeight = 0;
79
+ let cachedClientHeight = 0;
80
+ updateCache();
81
+ const cacheObserver = resizeObserver(scrollElement, {
82
+ callback: updateCache
83
+ });
84
+ node.addEventListener("scroll", throttledObserve, { passive: true });
85
+ function updateCache() {
86
+ cachedScrollHeight = scrollElement.scrollHeight;
87
+ cachedClientHeight = scrollElement.clientHeight;
88
+ }
89
+ function throttledObserve() {
90
+ const now = Date.now();
91
+ if (now - lastThrottleTime < throttle) return;
92
+ lastThrottleTime = now;
93
+ rafId = requestAnimationFrame(observe);
94
+ }
95
+ function observe() {
96
+ const scrollTop = scrollElement.scrollTop;
97
+ if (Math.abs(scrollTop - prevScrollTop) < 1) return;
98
+ const scrollDirection = scrollTop > prevScrollTop ? "down" : "up";
99
+ const maxScroll = Math.max(1, cachedScrollHeight - cachedClientHeight);
100
+ const scrollPercent = Math.min(1, Math.max(0, scrollTop / maxScroll));
101
+ const thresholdMin = threshold - tolerance / 2;
102
+ const thresholdMax = threshold + tolerance / 2;
103
+ const wasInThreshold = prevScrollPercent >= thresholdMin && prevScrollPercent <= thresholdMax;
104
+ const isInThreshold = scrollPercent >= thresholdMin && scrollPercent <= thresholdMax;
105
+ const hasEnteredThreshold = !wasInThreshold && isInThreshold && (!once || !thresholdFired);
106
+ if (hasEnteredThreshold && once) {
107
+ thresholdFired = true;
108
+ }
109
+ const callbackData = {
110
+ scrollTop,
111
+ scrollDirection,
112
+ scrollPercent,
113
+ directionChanged: scrollDirection !== prevScrollDirection,
114
+ hasEnteredThreshold,
115
+ isInThreshold
116
+ };
117
+ if (typeof callback === "function") {
118
+ callback(callbackData);
119
+ }
120
+ if (scrollDirection !== prevScrollDirection) {
121
+ if (scrollDirection === "down" && typeof onScrollDown === "function") {
122
+ onScrollDown(callbackData);
123
+ }
124
+ if (scrollDirection === "up" && typeof onScrollUp === "function") {
125
+ onScrollUp(callbackData);
126
+ }
127
+ }
128
+ if (hasEnteredThreshold && typeof onEnterThreshold === "function") {
129
+ onEnterThreshold(callbackData);
130
+ }
131
+ prevScrollTop = scrollTop;
132
+ prevScrollPercent = scrollPercent;
133
+ }
134
+ return {
135
+ destroy() {
136
+ node.removeEventListener("scroll", throttledObserve);
137
+ if (rafId) cancelAnimationFrame(rafId);
138
+ cacheObserver.destroy();
139
+ }
140
+ };
141
+ }
142
+ export {
143
+ scrollObserver
144
+ };
@@ -88,7 +88,7 @@ var MONTHS = [
88
88
  // src/lib/numbers/index.js
89
89
  function splitUnit(string) {
90
90
  if (typeof string === "number") return [string, null];
91
- const regex = /(-?\d*\.?\d+)([a-z]+)/i;
91
+ const regex = /(-?\d*\.?\d+)\s*([a-z]+)/i;
92
92
  const match = string.match(regex);
93
93
  if (match) return [parseFloat(match[1]), match[2]];
94
94
  return [parseFloat(string), null];
@@ -106,10 +106,12 @@ function ms(arg) {
106
106
  if (unit === "hours") return getTimeInMs(value, "hours");
107
107
  if (unit === "m") return getTimeInMs(value, "minutes");
108
108
  if (unit === "min") return getTimeInMs(value, "minutes");
109
+ if (unit === "mins") return getTimeInMs(value, "minutes");
109
110
  if (unit === "minute") return getTimeInMs(value, "minutes");
110
111
  if (unit === "minutes") return getTimeInMs(value, "minutes");
111
112
  if (unit === "s") return getTimeInMs(value, "seconds");
112
113
  if (unit === "sec") return getTimeInMs(value, "seconds");
114
+ if (unit === "secs") return getTimeInMs(value, "seconds");
113
115
  if (unit === "second") return getTimeInMs(value, "seconds");
114
116
  if (unit === "seconds") return getTimeInMs(value, "seconds");
115
117
  return value;
@@ -1,7 +1,7 @@
1
1
  // src/lib/numbers/index.js
2
2
  function splitUnit(string) {
3
3
  if (typeof string === "number") return [string, null];
4
- const regex = /(-?\d*\.?\d+)([a-z]+)/i;
4
+ const regex = /(-?\d*\.?\d+)\s*([a-z]+)/i;
5
5
  const match = string.match(regex);
6
6
  if (match) return [parseFloat(match[1]), match[2]];
7
7
  return [parseFloat(string), null];
@@ -19,10 +19,12 @@ function ms(arg) {
19
19
  if (unit === "hours") return getTimeInMs(value, "hours");
20
20
  if (unit === "m") return getTimeInMs(value, "minutes");
21
21
  if (unit === "min") return getTimeInMs(value, "minutes");
22
+ if (unit === "mins") return getTimeInMs(value, "minutes");
22
23
  if (unit === "minute") return getTimeInMs(value, "minutes");
23
24
  if (unit === "minutes") return getTimeInMs(value, "minutes");
24
25
  if (unit === "s") return getTimeInMs(value, "seconds");
25
26
  if (unit === "sec") return getTimeInMs(value, "seconds");
27
+ if (unit === "secs") return getTimeInMs(value, "seconds");
26
28
  if (unit === "second") return getTimeInMs(value, "seconds");
27
29
  if (unit === "seconds") return getTimeInMs(value, "seconds");
28
30
  return value;
@@ -15,11 +15,27 @@ function compose(...fns) {
15
15
  return fns.reduceRight((acc, fn) => fn(acc), value);
16
16
  };
17
17
  }
18
+ function composeAsync(...fns) {
19
+ return async function(value) {
20
+ return fns.reduceRight(async (acc, fn) => {
21
+ const result = await acc;
22
+ return await fn(result);
23
+ }, value);
24
+ };
25
+ }
18
26
  function pipe(...fns) {
19
27
  return function(value) {
20
28
  return fns.reduce((acc, fn) => fn(acc), value);
21
29
  };
22
30
  }
31
+ function pipeAsync(...fns) {
32
+ return async function(value) {
33
+ return fns.reduce(async (acc, fn) => {
34
+ const result = await acc;
35
+ return await fn(result);
36
+ }, value);
37
+ };
38
+ }
23
39
  function times(fn, n) {
24
40
  const result = [];
25
41
  for (let i = 0; i < n; i++) {
@@ -29,7 +45,9 @@ function times(fn, n) {
29
45
  }
30
46
  export {
31
47
  compose,
48
+ composeAsync,
32
49
  curry,
33
50
  pipe,
51
+ pipeAsync,
34
52
  times
35
53
  };
@@ -38,11 +38,27 @@ function compose(...fns) {
38
38
  return fns.reduceRight((acc, fn) => fn(acc), value);
39
39
  };
40
40
  }
41
+ function composeAsync(...fns) {
42
+ return async function(value) {
43
+ return fns.reduceRight(async (acc, fn) => {
44
+ const result = await acc;
45
+ return await fn(result);
46
+ }, value);
47
+ };
48
+ }
41
49
  function pipe(...fns) {
42
50
  return function(value) {
43
51
  return fns.reduce((acc, fn) => fn(acc), value);
44
52
  };
45
53
  }
54
+ function pipeAsync(...fns) {
55
+ return async function(value) {
56
+ return fns.reduce(async (acc, fn) => {
57
+ const result = await acc;
58
+ return await fn(result);
59
+ }, value);
60
+ };
61
+ }
46
62
  function times(fn, n) {
47
63
  const result = [];
48
64
  for (let i = 0; i < n; i++) {
@@ -75,11 +91,13 @@ function wait(ms) {
75
91
  }
76
92
  export {
77
93
  compose,
94
+ composeAsync,
78
95
  curry,
79
96
  debounce,
80
97
  delay,
81
98
  getEnv,
82
99
  pipe,
100
+ pipeAsync,
83
101
  throttle,
84
102
  timeout,
85
103
  times,
@@ -252,7 +252,7 @@ function toRadians(angle) {
252
252
  // src/lib/numbers/index.js
253
253
  function splitUnit(string) {
254
254
  if (typeof string === "number") return [string, null];
255
- const regex = /(-?\d*\.?\d+)([a-z]+)/i;
255
+ const regex = /(-?\d*\.?\d+)\s*([a-z]+)/i;
256
256
  const match = string.match(regex);
257
257
  if (match) return [parseFloat(match[1]), match[2]];
258
258
  return [parseFloat(string), null];
@@ -270,10 +270,12 @@ function ms(arg) {
270
270
  if (unit === "hours") return getTimeInMs(value, "hours");
271
271
  if (unit === "m") return getTimeInMs(value, "minutes");
272
272
  if (unit === "min") return getTimeInMs(value, "minutes");
273
+ if (unit === "mins") return getTimeInMs(value, "minutes");
273
274
  if (unit === "minute") return getTimeInMs(value, "minutes");
274
275
  if (unit === "minutes") return getTimeInMs(value, "minutes");
275
276
  if (unit === "s") return getTimeInMs(value, "seconds");
276
277
  if (unit === "sec") return getTimeInMs(value, "seconds");
278
+ if (unit === "secs") return getTimeInMs(value, "seconds");
277
279
  if (unit === "second") return getTimeInMs(value, "seconds");
278
280
  if (unit === "seconds") return getTimeInMs(value, "seconds");
279
281
  return value;
@@ -448,11 +450,27 @@ function compose(...fns) {
448
450
  return fns.reduceRight((acc, fn) => fn(acc), value);
449
451
  };
450
452
  }
453
+ function composeAsync(...fns) {
454
+ return async function(value) {
455
+ return fns.reduceRight(async (acc, fn) => {
456
+ const result = await acc;
457
+ return await fn(result);
458
+ }, value);
459
+ };
460
+ }
451
461
  function pipe(...fns) {
452
462
  return function(value) {
453
463
  return fns.reduce((acc, fn) => fn(acc), value);
454
464
  };
455
465
  }
466
+ function pipeAsync(...fns) {
467
+ return async function(value) {
468
+ return fns.reduce(async (acc, fn) => {
469
+ const result = await acc;
470
+ return await fn(result);
471
+ }, value);
472
+ };
473
+ }
456
474
  function times(fn, n) {
457
475
  const result = [];
458
476
  for (let i = 0; i < n; i++) {
@@ -603,8 +621,9 @@ function notEqual(a, b) {
603
621
  }
604
622
 
605
623
  // src/lib/objects/mix/mix.js
606
- var DEFAULT_OPTIONS = { array: "concat" };
624
+ var DEFAULT_OPTIONS = { array: "replace" };
607
625
  var mix = createMix();
626
+ var concatMix = createMix({ array: "concat" });
608
627
  function createMix(userOptions = {}) {
609
628
  const options = { ...DEFAULT_OPTIONS, ...userOptions };
610
629
  function _mix(...sources) {
@@ -943,6 +962,8 @@ export {
943
962
  RouteManager,
944
963
  camelCaseKeys,
945
964
  compose,
965
+ composeAsync,
966
+ concatMix,
946
967
  createMix,
947
968
  createSSE,
948
969
  curry,
@@ -983,6 +1004,7 @@ export {
983
1004
  parseJSON,
984
1005
  parseSSE,
985
1006
  pipe,
1007
+ pipeAsync,
986
1008
  plural,
987
1009
  pluralize,
988
1010
  reject,
@@ -9,7 +9,7 @@ function toRadians(angle) {
9
9
  // src/lib/numbers/index.js
10
10
  function splitUnit(string) {
11
11
  if (typeof string === "number") return [string, null];
12
- const regex = /(-?\d*\.?\d+)([a-z]+)/i;
12
+ const regex = /(-?\d*\.?\d+)\s*([a-z]+)/i;
13
13
  const match = string.match(regex);
14
14
  if (match) return [parseFloat(match[1]), match[2]];
15
15
  return [parseFloat(string), null];