@oscarpalmer/atoms 0.13.0 → 0.15.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.
@@ -0,0 +1,111 @@
1
+ // src/js/number.ts
2
+ function getNumber(value) {
3
+ if (typeof value === "number") {
4
+ return value;
5
+ }
6
+ if (typeof value === "symbol") {
7
+ return NaN;
8
+ }
9
+ let parsed = value?.valueOf?.() ?? value;
10
+ if (typeof parsed === "object") {
11
+ parsed = parsed?.toString() ?? parsed;
12
+ }
13
+ if (typeof parsed !== "string") {
14
+ return parsed == null ? NaN : typeof parsed === "number" ? parsed : +parsed;
15
+ }
16
+ if (/^\s*0+\s*$/.test(parsed)) {
17
+ return 0;
18
+ }
19
+ const trimmed = parsed.trim();
20
+ if (trimmed.length === 0) {
21
+ return NaN;
22
+ }
23
+ const isBinary = /^0b[01]+$/i.test(trimmed);
24
+ if (isBinary || /^0o[0-7]+$/i.test(trimmed)) {
25
+ return parseInt(trimmed.slice(2), isBinary ? 2 : 8);
26
+ }
27
+ return +(/^0x[0-9a-f]+$/i.test(trimmed) ? trimmed : trimmed.replace(/_/g, ""));
28
+ }
29
+
30
+ // src/js/array.ts
31
+ var _getCallback = function(value) {
32
+ if (typeof value === "function") {
33
+ return value;
34
+ }
35
+ const isString = typeof value === "string";
36
+ if (!isString && typeof value !== "number") {
37
+ return;
38
+ }
39
+ return isString && value.includes(".") ? undefined : (item) => item[value];
40
+ };
41
+ function chunk(array, size) {
42
+ const chunks = [];
43
+ const chunkSize = getNumber(size);
44
+ let remaining = Number(array.length);
45
+ while (remaining > 0) {
46
+ chunks.push(array.splice(0, chunkSize));
47
+ remaining -= chunkSize;
48
+ }
49
+ return chunks;
50
+ }
51
+ function exists(array, value, key) {
52
+ const callback = _getCallback(key);
53
+ if (callback === undefined) {
54
+ return array.indexOf(value) > -1;
55
+ }
56
+ const needle = typeof value === "object" && value !== null ? callback(value) : value;
57
+ const { length } = array;
58
+ let index = 0;
59
+ for (;index < length; index += 1) {
60
+ if (callback(array[index]) === needle) {
61
+ return true;
62
+ }
63
+ }
64
+ return false;
65
+ }
66
+ function groupBy(array, key) {
67
+ const keyCallback = _getCallback(key);
68
+ if (keyCallback === undefined) {
69
+ return {};
70
+ }
71
+ const grouped = {};
72
+ const { length } = array;
73
+ let index = 0;
74
+ for (;index < length; index += 1) {
75
+ const item = array[index];
76
+ const value = keyCallback(item);
77
+ if (value in grouped) {
78
+ grouped[value].push(item);
79
+ } else {
80
+ grouped[value] = [item];
81
+ }
82
+ }
83
+ return grouped;
84
+ }
85
+ function unique(array, key) {
86
+ const keyCallback = _getCallback(key);
87
+ const { length } = array;
88
+ if (keyCallback === undefined && length >= 100) {
89
+ return Array.from(new Set(array));
90
+ }
91
+ const result = [];
92
+ const values = keyCallback === undefined ? result : [];
93
+ let index = 0;
94
+ for (;index < length; index += 1) {
95
+ const item = array[index];
96
+ const value = keyCallback?.(item) ?? item;
97
+ if (values.indexOf(value) === -1) {
98
+ if (values !== result) {
99
+ values.push(value);
100
+ }
101
+ result.push(item);
102
+ }
103
+ }
104
+ return result;
105
+ }
106
+ export {
107
+ unique,
108
+ groupBy,
109
+ exists,
110
+ chunk
111
+ };
@@ -0,0 +1,83 @@
1
+ // src/js/array.ts
2
+ import {getNumber} from "./number";
3
+ var _getCallback = function(value) {
4
+ if (typeof value === "function") {
5
+ return value;
6
+ }
7
+ const isString = typeof value === "string";
8
+ if (!isString && typeof value !== "number") {
9
+ return;
10
+ }
11
+ return isString && value.includes(".") ? undefined : (item) => item[value];
12
+ };
13
+ function chunk(array, size) {
14
+ const chunks = [];
15
+ const chunkSize = getNumber(size);
16
+ let remaining = Number(array.length);
17
+ while (remaining > 0) {
18
+ chunks.push(array.splice(0, chunkSize));
19
+ remaining -= chunkSize;
20
+ }
21
+ return chunks;
22
+ }
23
+ function exists(array, value, key) {
24
+ const callback = _getCallback(key);
25
+ if (callback === undefined) {
26
+ return array.indexOf(value) > -1;
27
+ }
28
+ const needle = typeof value === "object" && value !== null ? callback(value) : value;
29
+ const { length } = array;
30
+ let index = 0;
31
+ for (;index < length; index += 1) {
32
+ if (callback(array[index]) === needle) {
33
+ return true;
34
+ }
35
+ }
36
+ return false;
37
+ }
38
+ function groupBy(array, key) {
39
+ const keyCallback = _getCallback(key);
40
+ if (keyCallback === undefined) {
41
+ return {};
42
+ }
43
+ const grouped = {};
44
+ const { length } = array;
45
+ let index = 0;
46
+ for (;index < length; index += 1) {
47
+ const item = array[index];
48
+ const value = keyCallback(item);
49
+ if (value in grouped) {
50
+ grouped[value].push(item);
51
+ } else {
52
+ grouped[value] = [item];
53
+ }
54
+ }
55
+ return grouped;
56
+ }
57
+ function unique(array, key) {
58
+ const keyCallback = _getCallback(key);
59
+ const { length } = array;
60
+ if (keyCallback === undefined && length >= 100) {
61
+ return Array.from(new Set(array));
62
+ }
63
+ const result = [];
64
+ const values = keyCallback === undefined ? result : [];
65
+ let index = 0;
66
+ for (;index < length; index += 1) {
67
+ const item = array[index];
68
+ const value = keyCallback?.(item) ?? item;
69
+ if (values.indexOf(value) === -1) {
70
+ if (values !== result) {
71
+ values.push(value);
72
+ }
73
+ result.push(item);
74
+ }
75
+ }
76
+ return result;
77
+ }
78
+ export {
79
+ unique,
80
+ groupBy,
81
+ exists,
82
+ chunk
83
+ };
@@ -18,7 +18,10 @@ var _getValidElements = function(type, parent, filters) {
18
18
  }
19
19
  const indiced = [];
20
20
  const zeroed = [];
21
- for (const item of items) {
21
+ const { length } = items;
22
+ let index = 0;
23
+ for (;index < length; index += 1) {
24
+ const item = items[index];
22
25
  if (item.tabIndex === 0) {
23
26
  zeroed.push(item.element);
24
27
  } else {
@@ -44,7 +47,10 @@ var _isDisabledFromFieldset = function(element) {
44
47
  while (parent !== null) {
45
48
  if (parent instanceof HTMLFieldSetElement && parent.disabled) {
46
49
  const children = Array.from(parent.children);
47
- for (const child of children) {
50
+ const { length } = children;
51
+ let index = 0;
52
+ for (;index < length; index += 1) {
53
+ const child = children[index];
48
54
  if (child instanceof HTMLLegendElement) {
49
55
  return parent.matches("fieldset[disabled] *") ? true : !child.contains(element);
50
56
  }
@@ -18,7 +18,10 @@ var _getValidElements = function(type, parent, filters) {
18
18
  }
19
19
  const indiced = [];
20
20
  const zeroed = [];
21
- for (const item of items) {
21
+ const { length } = items;
22
+ let index = 0;
23
+ for (;index < length; index += 1) {
24
+ const item = items[index];
22
25
  if (item.tabIndex === 0) {
23
26
  zeroed.push(item.element);
24
27
  } else {
@@ -44,7 +47,10 @@ var _isDisabledFromFieldset = function(element) {
44
47
  while (parent !== null) {
45
48
  if (parent instanceof HTMLFieldSetElement && parent.disabled) {
46
49
  const children = Array.from(parent.children);
47
- for (const child of children) {
50
+ const { length } = children;
51
+ let index = 0;
52
+ for (;index < length; index += 1) {
53
+ const child = children[index];
48
54
  if (child instanceof HTMLLegendElement) {
49
55
  return parent.matches("fieldset[disabled] *") ? true : !child.contains(element);
50
56
  }
@@ -1,15 +1,23 @@
1
1
  // src/js/element/index.ts
2
+ function findElement(selector, context) {
3
+ return findElements(selector, context)[0];
4
+ }
2
5
  function findElements(selector, context) {
3
6
  const contexts = context === undefined ? [document] : findElements(context);
4
7
  const elements = [];
5
8
  if (typeof selector === "string") {
6
- for (const context2 of contexts) {
7
- elements.push(...Array.from(context2.querySelectorAll(selector) ?? []));
9
+ const { length: length2 } = contexts;
10
+ let index2 = 0;
11
+ for (;index2 < length2; index2 += 1) {
12
+ elements.push(...Array.from(contexts[index2].querySelectorAll(selector) ?? []));
8
13
  }
9
14
  return elements;
10
15
  }
11
16
  const nodes = Array.isArray(selector) || selector instanceof NodeList ? selector : [selector];
12
- for (const node of nodes) {
17
+ const { length } = nodes;
18
+ let index = 0;
19
+ for (;index < length; index += 1) {
20
+ const node = nodes[index];
13
21
  if (node instanceof Element && contexts.some((context2) => context2.contains(node))) {
14
22
  elements.push(node);
15
23
  }
@@ -56,5 +64,8 @@ export {
56
64
  getTextDirection,
57
65
  getElementUnderPointer,
58
66
  findParentElement,
59
- findElements
67
+ findElements,
68
+ findElement,
69
+ findElements as $$,
70
+ findElement as $
60
71
  };
@@ -1,15 +1,23 @@
1
1
  // src/js/element/index.ts
2
+ function findElement(selector, context) {
3
+ return findElements(selector, context)[0];
4
+ }
2
5
  function findElements(selector, context) {
3
6
  const contexts = context === undefined ? [document] : findElements(context);
4
7
  const elements = [];
5
8
  if (typeof selector === "string") {
6
- for (const context2 of contexts) {
7
- elements.push(...Array.from(context2.querySelectorAll(selector) ?? []));
9
+ const { length: length2 } = contexts;
10
+ let index2 = 0;
11
+ for (;index2 < length2; index2 += 1) {
12
+ elements.push(...Array.from(contexts[index2].querySelectorAll(selector) ?? []));
8
13
  }
9
14
  return elements;
10
15
  }
11
16
  const nodes = Array.isArray(selector) || selector instanceof NodeList ? selector : [selector];
12
- for (const node of nodes) {
17
+ const { length } = nodes;
18
+ let index = 0;
19
+ for (;index < length; index += 1) {
20
+ const node = nodes[index];
13
21
  if (node instanceof Element && contexts.some((context2) => context2.contains(node))) {
14
22
  elements.push(node);
15
23
  }
@@ -52,9 +60,13 @@ function getTextDirection(element) {
52
60
  }
53
61
  return getComputedStyle?.(element)?.direction === "rtl" ? "rtl" : "ltr";
54
62
  }
63
+ import {findElement as findElement2, findElements as findElements2} from ".";
55
64
  export {
56
65
  getTextDirection,
57
66
  getElementUnderPointer,
58
67
  findParentElement,
59
- findElements
68
+ findElements,
69
+ findElement,
70
+ findElements2 as $$,
71
+ findElement2 as $
60
72
  };
package/dist/js/event.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/js/event.ts
2
- function getEventPosition(event) {
2
+ function getPosition(event) {
3
3
  let x;
4
4
  let y;
5
5
  if (event instanceof MouseEvent) {
@@ -12,5 +12,5 @@ function getEventPosition(event) {
12
12
  return typeof x === "number" && typeof y === "number" ? { x, y } : undefined;
13
13
  }
14
14
  export {
15
- getEventPosition
15
+ getPosition
16
16
  };
package/dist/js/event.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/js/event.ts
2
- function getEventPosition(event) {
2
+ function getPosition(event) {
3
3
  let x;
4
4
  let y;
5
5
  if (event instanceof MouseEvent) {
@@ -12,5 +12,5 @@ function getEventPosition(event) {
12
12
  return typeof x === "number" && typeof y === "number" ? { x, y } : undefined;
13
13
  }
14
14
  export {
15
- getEventPosition
15
+ getPosition
16
16
  };
package/dist/js/index.js CHANGED
@@ -1,15 +1,138 @@
1
+ // src/js/number.ts
2
+ function clamp(value, min, max, loop) {
3
+ const maxNumber = getNumber(max);
4
+ const minNumber = getNumber(min);
5
+ const valueNumber = getNumber(value);
6
+ const shouldLoop = loop === true;
7
+ if (valueNumber < minNumber) {
8
+ return shouldLoop ? maxNumber : minNumber;
9
+ }
10
+ return valueNumber > maxNumber ? shouldLoop ? minNumber : maxNumber : valueNumber;
11
+ }
12
+ function getNumber(value) {
13
+ if (typeof value === "number") {
14
+ return value;
15
+ }
16
+ if (typeof value === "symbol") {
17
+ return NaN;
18
+ }
19
+ let parsed = value?.valueOf?.() ?? value;
20
+ if (typeof parsed === "object") {
21
+ parsed = parsed?.toString() ?? parsed;
22
+ }
23
+ if (typeof parsed !== "string") {
24
+ return parsed == null ? NaN : typeof parsed === "number" ? parsed : +parsed;
25
+ }
26
+ if (/^\s*0+\s*$/.test(parsed)) {
27
+ return 0;
28
+ }
29
+ const trimmed = parsed.trim();
30
+ if (trimmed.length === 0) {
31
+ return NaN;
32
+ }
33
+ const isBinary = /^0b[01]+$/i.test(trimmed);
34
+ if (isBinary || /^0o[0-7]+$/i.test(trimmed)) {
35
+ return parseInt(trimmed.slice(2), isBinary ? 2 : 8);
36
+ }
37
+ return +(/^0x[0-9a-f]+$/i.test(trimmed) ? trimmed : trimmed.replace(/_/g, ""));
38
+ }
39
+
40
+ // src/js/array.ts
41
+ var _getCallback = function(value) {
42
+ if (typeof value === "function") {
43
+ return value;
44
+ }
45
+ const isString = typeof value === "string";
46
+ if (!isString && typeof value !== "number") {
47
+ return;
48
+ }
49
+ return isString && value.includes(".") ? undefined : (item) => item[value];
50
+ };
51
+ function chunk(array, size) {
52
+ const chunks = [];
53
+ const chunkSize = getNumber(size);
54
+ let remaining = Number(array.length);
55
+ while (remaining > 0) {
56
+ chunks.push(array.splice(0, chunkSize));
57
+ remaining -= chunkSize;
58
+ }
59
+ return chunks;
60
+ }
61
+ function exists(array, value, key) {
62
+ const callback = _getCallback(key);
63
+ if (callback === undefined) {
64
+ return array.indexOf(value) > -1;
65
+ }
66
+ const needle = typeof value === "object" && value !== null ? callback(value) : value;
67
+ const { length } = array;
68
+ let index = 0;
69
+ for (;index < length; index += 1) {
70
+ if (callback(array[index]) === needle) {
71
+ return true;
72
+ }
73
+ }
74
+ return false;
75
+ }
76
+ function groupBy(array, key) {
77
+ const keyCallback = _getCallback(key);
78
+ if (keyCallback === undefined) {
79
+ return {};
80
+ }
81
+ const grouped = {};
82
+ const { length } = array;
83
+ let index = 0;
84
+ for (;index < length; index += 1) {
85
+ const item = array[index];
86
+ const value = keyCallback(item);
87
+ if (value in grouped) {
88
+ grouped[value].push(item);
89
+ } else {
90
+ grouped[value] = [item];
91
+ }
92
+ }
93
+ return grouped;
94
+ }
95
+ function unique(array, key) {
96
+ const keyCallback = _getCallback(key);
97
+ const { length } = array;
98
+ if (keyCallback === undefined && length >= 100) {
99
+ return Array.from(new Set(array));
100
+ }
101
+ const result = [];
102
+ const values = keyCallback === undefined ? result : [];
103
+ let index = 0;
104
+ for (;index < length; index += 1) {
105
+ const item = array[index];
106
+ const value = keyCallback?.(item) ?? item;
107
+ if (values.indexOf(value) === -1) {
108
+ if (values !== result) {
109
+ values.push(value);
110
+ }
111
+ result.push(item);
112
+ }
113
+ }
114
+ return result;
115
+ }
1
116
  // src/js/element/index.ts
117
+ function findElement(selector, context) {
118
+ return findElements(selector, context)[0];
119
+ }
2
120
  function findElements(selector, context) {
3
121
  const contexts = context === undefined ? [document] : findElements(context);
4
122
  const elements = [];
5
123
  if (typeof selector === "string") {
6
- for (const context2 of contexts) {
7
- elements.push(...Array.from(context2.querySelectorAll(selector) ?? []));
124
+ const { length: length2 } = contexts;
125
+ let index2 = 0;
126
+ for (;index2 < length2; index2 += 1) {
127
+ elements.push(...Array.from(contexts[index2].querySelectorAll(selector) ?? []));
8
128
  }
9
129
  return elements;
10
130
  }
11
131
  const nodes = Array.isArray(selector) || selector instanceof NodeList ? selector : [selector];
12
- for (const node of nodes) {
132
+ const { length } = nodes;
133
+ let index = 0;
134
+ for (;index < length; index += 1) {
135
+ const node = nodes[index];
13
136
  if (node instanceof Element && contexts.some((context2) => context2.contains(node))) {
14
137
  elements.push(node);
15
138
  }
@@ -53,7 +176,7 @@ function getTextDirection(element) {
53
176
  return getComputedStyle?.(element)?.direction === "rtl" ? "rtl" : "ltr";
54
177
  }
55
178
  // src/js/event.ts
56
- function getEventPosition(event) {
179
+ function getPosition(event) {
57
180
  let x;
58
181
  let y;
59
182
  if (event instanceof MouseEvent) {
@@ -65,37 +188,6 @@ function getEventPosition(event) {
65
188
  }
66
189
  return typeof x === "number" && typeof y === "number" ? { x, y } : undefined;
67
190
  }
68
- // src/js/number.ts
69
- function clampNumber(value, min, max) {
70
- return Math.min(Math.max(getNumber(value), getNumber(min)), getNumber(max));
71
- }
72
- function getNumber(value) {
73
- if (typeof value === "number") {
74
- return value;
75
- }
76
- if (typeof value === "symbol") {
77
- return NaN;
78
- }
79
- let parsed = value?.valueOf?.() ?? value;
80
- if (typeof parsed === "object") {
81
- parsed = parsed?.toString() ?? parsed;
82
- }
83
- if (typeof parsed !== "string") {
84
- return parsed == null ? NaN : typeof parsed === "number" ? parsed : +parsed;
85
- }
86
- if (/^\s*0+\s*$/.test(parsed)) {
87
- return 0;
88
- }
89
- const trimmed = parsed.trim();
90
- if (trimmed.length === 0) {
91
- return NaN;
92
- }
93
- const isBinary = /^0b[01]+$/i.test(trimmed);
94
- if (isBinary || /^0o[0-7]+$/i.test(trimmed)) {
95
- return parseInt(trimmed.slice(2), isBinary ? 2 : 8);
96
- }
97
- return +(/^0x[0-9a-f]+$/i.test(trimmed) ? trimmed : trimmed.replace(/_/g, ""));
98
- }
99
191
  // src/js/string.ts
100
192
  function createUuid() {
101
193
  return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (substring) => (substring ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> substring / 4).toString(16));
@@ -194,10 +286,7 @@ var _getValue = function(data, key) {
194
286
  if (typeof data !== "object" || data === null || /^(__proto__|constructor|prototype)$/i.test(key)) {
195
287
  return;
196
288
  }
197
- if (data instanceof Map) {
198
- return data.get(key);
199
- }
200
- return data[key];
289
+ return data instanceof Map ? data.get(key) : data[key];
201
290
  };
202
291
  var _setValue = function(data, key, value) {
203
292
  if (typeof data !== "object" || data === null || /^(__proto__|constructor|prototype)$/i.test(key)) {
@@ -214,9 +303,11 @@ function getValue(data, key) {
214
303
  return;
215
304
  }
216
305
  const parts = getString(key).split(".");
306
+ const { length } = parts;
307
+ let index = 0;
217
308
  let value = data;
218
- for (const part of parts) {
219
- value = _getValue(value, part);
309
+ for (;index < length; index += 1) {
310
+ value = _getValue(value, parts[index]);
220
311
  if (value == null) {
221
312
  break;
222
313
  }
@@ -237,8 +328,11 @@ function setValue(data, key, value) {
237
328
  return data;
238
329
  }
239
330
  const parts = getString(key).split(".");
331
+ const { length } = parts;
332
+ let index = 0;
240
333
  let target = data;
241
- for (const part of parts) {
334
+ for (;index < length; index += 1) {
335
+ const part = parts[index];
242
336
  if (parts.indexOf(part) === parts.length - 1) {
243
337
  _setValue(target, part, value);
244
338
  break;
@@ -254,21 +348,28 @@ function setValue(data, key, value) {
254
348
  }
255
349
  export {
256
350
  wait,
351
+ unique,
257
352
  setValue,
258
353
  repeat,
259
354
  isObject,
260
355
  isNullableOrWhitespace,
261
356
  isNullable,
262
357
  isArrayOrObject,
358
+ groupBy,
263
359
  getValue,
264
360
  getTextDirection,
265
361
  getString,
362
+ getPosition,
266
363
  getNumber,
267
- getEventPosition,
268
364
  getElementUnderPointer,
269
365
  findParentElement,
270
366
  findElements,
367
+ findElement,
368
+ exists,
271
369
  createUuid,
272
- clampNumber,
273
- Timer
370
+ clamp,
371
+ chunk,
372
+ Timer,
373
+ findElements as $$,
374
+ findElement as $
274
375
  };
package/dist/js/index.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/js/index.ts
2
+ export * from "./array";
2
3
  export * from "./element";
3
4
  export * from "./event";
4
5
  export * from "./number";
package/dist/js/number.js CHANGED
@@ -1,6 +1,13 @@
1
1
  // src/js/number.ts
2
- function clampNumber(value, min, max) {
3
- return Math.min(Math.max(getNumber(value), getNumber(min)), getNumber(max));
2
+ function clamp(value, min, max, loop) {
3
+ const maxNumber = getNumber(max);
4
+ const minNumber = getNumber(min);
5
+ const valueNumber = getNumber(value);
6
+ const shouldLoop = loop === true;
7
+ if (valueNumber < minNumber) {
8
+ return shouldLoop ? maxNumber : minNumber;
9
+ }
10
+ return valueNumber > maxNumber ? shouldLoop ? minNumber : maxNumber : valueNumber;
4
11
  }
5
12
  function getNumber(value) {
6
13
  if (typeof value === "number") {
@@ -31,5 +38,5 @@ function getNumber(value) {
31
38
  }
32
39
  export {
33
40
  getNumber,
34
- clampNumber
41
+ clamp
35
42
  };
@@ -1,6 +1,13 @@
1
1
  // src/js/number.ts
2
- function clampNumber(value, min, max) {
3
- return Math.min(Math.max(getNumber(value), getNumber(min)), getNumber(max));
2
+ function clamp(value, min, max, loop) {
3
+ const maxNumber = getNumber(max);
4
+ const minNumber = getNumber(min);
5
+ const valueNumber = getNumber(value);
6
+ const shouldLoop = loop === true;
7
+ if (valueNumber < minNumber) {
8
+ return shouldLoop ? maxNumber : minNumber;
9
+ }
10
+ return valueNumber > maxNumber ? shouldLoop ? minNumber : maxNumber : valueNumber;
4
11
  }
5
12
  function getNumber(value) {
6
13
  if (typeof value === "number") {
@@ -31,5 +38,5 @@ function getNumber(value) {
31
38
  }
32
39
  export {
33
40
  getNumber,
34
- clampNumber
41
+ clamp
35
42
  };
package/dist/js/value.js CHANGED
@@ -11,10 +11,7 @@ var _getValue = function(data, key) {
11
11
  if (typeof data !== "object" || data === null || /^(__proto__|constructor|prototype)$/i.test(key)) {
12
12
  return;
13
13
  }
14
- if (data instanceof Map) {
15
- return data.get(key);
16
- }
17
- return data[key];
14
+ return data instanceof Map ? data.get(key) : data[key];
18
15
  };
19
16
  var _setValue = function(data, key, value) {
20
17
  if (typeof data !== "object" || data === null || /^(__proto__|constructor|prototype)$/i.test(key)) {
@@ -31,9 +28,11 @@ function getValue(data, key) {
31
28
  return;
32
29
  }
33
30
  const parts = getString(key).split(".");
31
+ const { length } = parts;
32
+ let index = 0;
34
33
  let value = data;
35
- for (const part of parts) {
36
- value = _getValue(value, part);
34
+ for (;index < length; index += 1) {
35
+ value = _getValue(value, parts[index]);
37
36
  if (value == null) {
38
37
  break;
39
38
  }
@@ -54,8 +53,11 @@ function setValue(data, key, value) {
54
53
  return data;
55
54
  }
56
55
  const parts = getString(key).split(".");
56
+ const { length } = parts;
57
+ let index = 0;
57
58
  let target = data;
58
- for (const part of parts) {
59
+ for (;index < length; index += 1) {
60
+ const part = parts[index];
59
61
  if (parts.indexOf(part) === parts.length - 1) {
60
62
  _setValue(target, part, value);
61
63
  break;
package/dist/js/value.mjs CHANGED
@@ -4,10 +4,7 @@ var _getValue = function(data, key) {
4
4
  if (typeof data !== "object" || data === null || /^(__proto__|constructor|prototype)$/i.test(key)) {
5
5
  return;
6
6
  }
7
- if (data instanceof Map) {
8
- return data.get(key);
9
- }
10
- return data[key];
7
+ return data instanceof Map ? data.get(key) : data[key];
11
8
  };
12
9
  var _setValue = function(data, key, value) {
13
10
  if (typeof data !== "object" || data === null || /^(__proto__|constructor|prototype)$/i.test(key)) {
@@ -24,9 +21,11 @@ function getValue(data, key) {
24
21
  return;
25
22
  }
26
23
  const parts = getString(key).split(".");
24
+ const { length } = parts;
25
+ let index = 0;
27
26
  let value = data;
28
- for (const part of parts) {
29
- value = _getValue(value, part);
27
+ for (;index < length; index += 1) {
28
+ value = _getValue(value, parts[index]);
30
29
  if (value == null) {
31
30
  break;
32
31
  }
@@ -47,8 +46,11 @@ function setValue(data, key, value) {
47
46
  return data;
48
47
  }
49
48
  const parts = getString(key).split(".");
49
+ const { length } = parts;
50
+ let index = 0;
50
51
  let target = data;
51
- for (const part of parts) {
52
+ for (;index < length; index += 1) {
53
+ const part = parts[index];
52
54
  if (parts.indexOf(part) === parts.length - 1) {
53
55
  _setValue(target, part, value);
54
56
  break;
package/package.json CHANGED
@@ -18,6 +18,12 @@
18
18
  "require": "./dist/js/index.js",
19
19
  "types": "./types/index.d.ts"
20
20
  },
21
+ "./array": {
22
+ "bun": "./src/js/array.ts",
23
+ "import": "./dist/js/array.mjs",
24
+ "require": "./dist/js/array.js",
25
+ "types": "./types/array.d.ts"
26
+ },
21
27
  "./element": {
22
28
  "bun": "./src/js/element/index.ts",
23
29
  "import": "./dist/js/element/index.mjs",
@@ -93,5 +99,5 @@
93
99
  },
94
100
  "type": "module",
95
101
  "types": "./types/index.d.ts",
96
- "version": "0.13.0"
102
+ "version": "0.15.0"
97
103
  }
@@ -0,0 +1,144 @@
1
+ import {getNumber} from './number';
2
+ import {Key} from './value';
3
+
4
+ type KeyCallback<T> = (item: T) => Key;
5
+
6
+ function _getCallback<T>(
7
+ value: Key | KeyCallback<T> | undefined,
8
+ ): KeyCallback<T> | undefined {
9
+ if (typeof value === 'function') {
10
+ return value;
11
+ }
12
+
13
+ const isString = typeof value === 'string';
14
+
15
+ if (!isString && typeof value !== 'number') {
16
+ return undefined;
17
+ }
18
+
19
+ return isString && value.includes('.')
20
+ ? undefined
21
+ : (item: T): Key => item[value as never];
22
+ }
23
+
24
+ /**
25
+ * Chunks an array into smaller arrays of a specified size
26
+ */
27
+ export function chunk<T>(array: T[], size: number): T[][] {
28
+ const chunks: T[][] = [];
29
+ const chunkSize = getNumber(size);
30
+
31
+ let remaining = Number(array.length);
32
+
33
+ while (remaining > 0) {
34
+ chunks.push(array.splice(0, chunkSize));
35
+
36
+ remaining -= chunkSize;
37
+ }
38
+
39
+ return chunks;
40
+ }
41
+
42
+ /**
43
+ * Does the value exist in the array?
44
+ * - `key` is optional and can be used to specify a key or callback for finding a key for comparisons
45
+ * - If `key` is not provided, the item itself is used for comparisons
46
+ */
47
+ export function exists<T1, T2 = T1>(
48
+ array: T1[],
49
+ value: T2,
50
+ key?: Key | KeyCallback<T1>,
51
+ ): boolean {
52
+ const callback = _getCallback(key);
53
+
54
+ if (callback === undefined) {
55
+ return array.indexOf(value as never) > -1;
56
+ }
57
+
58
+ const needle =
59
+ typeof value === 'object' && value !== null
60
+ ? callback(value as never)
61
+ : value;
62
+
63
+ const {length} = array;
64
+
65
+ let index = 0;
66
+
67
+ for (; index < length; index += 1) {
68
+ if (callback(array[index]) === needle) {
69
+ return true;
70
+ }
71
+ }
72
+
73
+ return false;
74
+ }
75
+
76
+ /**
77
+ * Groups an array of items using a key or callback
78
+ */
79
+ export function groupBy<T>(
80
+ array: T[],
81
+ key: Key | ((item: T) => Key),
82
+ ): Record<Key, T[]> {
83
+ const keyCallback = _getCallback(key) as KeyCallback<T>;
84
+
85
+ if (keyCallback === undefined) {
86
+ return {};
87
+ }
88
+
89
+ const grouped: Record<Key, T[]> = {};
90
+
91
+ const {length} = array;
92
+
93
+ let index = 0;
94
+
95
+ for (; index < length; index += 1) {
96
+ const item = array[index];
97
+ const value = keyCallback(item);
98
+
99
+ if (value in grouped) {
100
+ grouped[value].push(item);
101
+ } else {
102
+ grouped[value] = [item];
103
+ }
104
+ }
105
+
106
+ return grouped;
107
+ }
108
+
109
+ /**
110
+ * - Returns a new array with unique items
111
+ * - `key` is optional and can be used to specify a key or callback for finding a key for uniqueness
112
+ * - If `key` is not provided, the item itself is used for comparisons
113
+ * - Inspired by Lodash :-)
114
+ */
115
+ export function unique<T>(array: T[], key?: Key | ((item: T) => Key)): T[] {
116
+ const keyCallback = _getCallback(key);
117
+
118
+ const {length} = array;
119
+
120
+ if (keyCallback === undefined && length >= 100) {
121
+ return Array.from(new Set(array));
122
+ }
123
+
124
+ const result: T[] = [];
125
+
126
+ const values: unknown[] = keyCallback === undefined ? result : [];
127
+
128
+ let index = 0;
129
+
130
+ for (; index < length; index += 1) {
131
+ const item = array[index];
132
+ const value = keyCallback?.(item) ?? item;
133
+
134
+ if (values.indexOf(value) === -1) {
135
+ if (values !== result) {
136
+ values.push(value);
137
+ }
138
+
139
+ result.push(item);
140
+ }
141
+ }
142
+
143
+ return result;
144
+ }
@@ -87,7 +87,13 @@ function _getValidElements(
87
87
  const indiced: Array<Array<FocusableElement>> = [];
88
88
  const zeroed: Array<FocusableElement> = [];
89
89
 
90
- for (const item of items) {
90
+ const {length} = items;
91
+
92
+ let index = 0;
93
+
94
+ for (; index < length; index += 1) {
95
+ const item = items[index];
96
+
91
97
  if (item.tabIndex === 0) {
92
98
  zeroed.push(item.element);
93
99
  } else {
@@ -128,7 +134,13 @@ function _isDisabledFromFieldset(element: FocusableElement): boolean {
128
134
  if (parent instanceof HTMLFieldSetElement && parent.disabled) {
129
135
  const children = Array.from(parent.children);
130
136
 
131
- for (const child of children) {
137
+ const {length} = children;
138
+
139
+ let index = 0;
140
+
141
+ for (; index < length; index += 1) {
142
+ const child = children[index];
143
+
132
144
  if (child instanceof HTMLLegendElement) {
133
145
  return parent.matches('fieldset[disabled] *')
134
146
  ? true
@@ -2,6 +2,17 @@ type Selector = string | Element | Element[] | NodeList;
2
2
 
3
3
  type TextDirection = 'ltr' | 'rtl';
4
4
 
5
+ /**
6
+ * - Find the first element that matches the selector
7
+ * - `context` is optional and defaults to `document`
8
+ */
9
+ export function findElement(
10
+ selector: Selector,
11
+ context?: Selector,
12
+ ): Element | undefined {
13
+ return findElements(selector, context)[0];
14
+ }
15
+
5
16
  /**
6
17
  * - Find elements that match the selector
7
18
  * - `context` is optional and defaults to `document`
@@ -15,9 +26,13 @@ export function findElements(
15
26
  const elements: Element[] = [];
16
27
 
17
28
  if (typeof selector === 'string') {
18
- for (const context of contexts) {
29
+ const {length} = contexts;
30
+
31
+ let index = 0;
32
+
33
+ for (; index < length; index += 1) {
19
34
  elements.push(
20
- ...Array.from((context as Element).querySelectorAll(selector) ?? []),
35
+ ...Array.from((contexts[index] as Element).querySelectorAll(selector) ?? []),
21
36
  );
22
37
  }
23
38
 
@@ -29,7 +44,13 @@ export function findElements(
29
44
  ? selector
30
45
  : [selector];
31
46
 
32
- for (const node of nodes) {
47
+ const {length} = nodes;
48
+
49
+ let index = 0;
50
+
51
+ for (; index < length; index += 1) {
52
+ const node = nodes[index];
53
+
33
54
  if (
34
55
  node instanceof Element &&
35
56
  contexts.some(context => context.contains(node))
@@ -119,3 +140,5 @@ export function getTextDirection(element: Element): TextDirection {
119
140
  getComputedStyle?.(element)?.direction === 'rtl' ? 'rtl' : 'ltr'
120
141
  ) as TextDirection;
121
142
  }
143
+
144
+ export {findElement as $, findElements as $$} from '.';
package/src/js/event.ts CHANGED
@@ -6,7 +6,7 @@ type Position = {
6
6
  /**
7
7
  * Get the X- and Y-coordinates from a pointer event
8
8
  */
9
- export function getEventPosition(
9
+ export function getPosition(
10
10
  event: MouseEvent | TouchEvent,
11
11
  ): Position | undefined {
12
12
  let x: number | undefined;
package/src/js/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './array';
1
2
  export * from './element';
2
3
  export * from './event';
3
4
  export * from './number';
package/src/js/number.ts CHANGED
@@ -1,9 +1,27 @@
1
-
2
1
  /**
3
- * Clamps a number between a minimum and maximum value
2
+ * - Clamps a number between a minimum and maximum value
3
+ * - If `loop` is `true`, when the value is less than the minimum, it will be clamped as the maximum, and vice versa
4
4
  */
5
- export function clampNumber(value: number, min: number, max: number): number {
6
- return Math.min(Math.max(getNumber(value), getNumber(min)), getNumber(max));
5
+ export function clamp(
6
+ value: number,
7
+ min: number,
8
+ max: number,
9
+ loop?: boolean,
10
+ ): number {
11
+ const maxNumber = getNumber(max);
12
+ const minNumber = getNumber(min);
13
+ const valueNumber = getNumber(value);
14
+ const shouldLoop = loop === true;
15
+
16
+ if (valueNumber < minNumber) {
17
+ return shouldLoop ? maxNumber : minNumber;
18
+ }
19
+
20
+ return valueNumber > maxNumber
21
+ ? shouldLoop
22
+ ? minNumber
23
+ : maxNumber
24
+ : valueNumber;
7
25
  }
8
26
 
9
27
  /**
package/src/js/value.ts CHANGED
@@ -17,11 +17,7 @@ function _getValue(data: ValueObject, key: string): unknown {
17
17
  return undefined;
18
18
  }
19
19
 
20
- if (data instanceof Map) {
21
- return data.get(key as never);
22
- }
23
-
24
- return data[key as never];
20
+ return data instanceof Map ? data.get(key as never) : data[key as never];
25
21
  }
26
22
 
27
23
  /**
@@ -59,10 +55,13 @@ export function getValue(data: ValueObject, key: Key): unknown {
59
55
 
60
56
  const parts = getString(key).split('.');
61
57
 
58
+ const {length} = parts;
59
+
60
+ let index = 0;
62
61
  let value = data;
63
62
 
64
- for (const part of parts) {
65
- value = _getValue(value, part) as ValueObject;
63
+ for (; index < length; index += 1) {
64
+ value = _getValue(value, parts[index]) as ValueObject;
66
65
 
67
66
  if (value == null) {
68
67
  break;
@@ -99,11 +98,11 @@ export function isObject(value: unknown): value is GenericObject {
99
98
  * - If a part of the path does not exist, it will be created, either as an array or a generic object, depending on the key
100
99
  * - Returns the original object
101
100
  */
102
- export function setValue<Model extends ValueObject>(
103
- data: Model,
101
+ export function setValue<T extends ValueObject>(
102
+ data: T,
104
103
  key: Key,
105
104
  value: unknown,
106
- ): Model {
105
+ ): T {
107
106
  if (
108
107
  typeof data !== 'object' ||
109
108
  data === null ||
@@ -114,9 +113,14 @@ export function setValue<Model extends ValueObject>(
114
113
 
115
114
  const parts = getString(key).split('.');
116
115
 
116
+ const {length} = parts;
117
+
118
+ let index = 0;
117
119
  let target: ValueObject = data;
118
120
 
119
- for (const part of parts) {
121
+ for (; index < length; index += 1) {
122
+ const part = parts[index];
123
+
120
124
  if (parts.indexOf(part) === parts.length - 1) {
121
125
  _setValue(target, part, value);
122
126
 
@@ -0,0 +1,24 @@
1
+ import { Key } from './value';
2
+ type KeyCallback<T> = (item: T) => Key;
3
+ /**
4
+ * Chunks an array into smaller arrays of a specified size
5
+ */
6
+ export declare function chunk<T>(array: T[], size: number): T[][];
7
+ /**
8
+ * Does the value exist in the array?
9
+ * - `key` is optional and can be used to specify a key or callback for finding a key for comparisons
10
+ * - If `key` is not provided, the item itself is used for comparisons
11
+ */
12
+ export declare function exists<T1, T2 = T1>(array: T1[], value: T2, key?: Key | KeyCallback<T1>): boolean;
13
+ /**
14
+ * Groups an array of items using a key or callback
15
+ */
16
+ export declare function groupBy<T>(array: T[], key: Key | ((item: T) => Key)): Record<Key, T[]>;
17
+ /**
18
+ * - Returns a new array with unique items
19
+ * - `key` is optional and can be used to specify a key or callback for finding a key for uniqueness
20
+ * - If `key` is not provided, the item itself is used for comparisons
21
+ * - Inspired by Lodash :-)
22
+ */
23
+ export declare function unique<T>(array: T[], key?: Key | ((item: T) => Key)): T[];
24
+ export {};
@@ -1,5 +1,10 @@
1
1
  type Selector = string | Element | Element[] | NodeList;
2
2
  type TextDirection = 'ltr' | 'rtl';
3
+ /**
4
+ * - Find the first element that matches the selector
5
+ * - `context` is optional and defaults to `document`
6
+ */
7
+ export declare function findElement(selector: Selector, context?: Selector): Element | undefined;
3
8
  /**
4
9
  * - Find elements that match the selector
5
10
  * - `context` is optional and defaults to `document`
@@ -21,4 +26,4 @@ export declare function getElementUnderPointer(skipIgnore?: boolean): Element |
21
26
  * Get the text direction of an element
22
27
  */
23
28
  export declare function getTextDirection(element: Element): TextDirection;
24
- export {};
29
+ export { findElement as $, findElements as $$ } from '.';
package/types/event.d.ts CHANGED
@@ -5,5 +5,5 @@ type Position = {
5
5
  /**
6
6
  * Get the X- and Y-coordinates from a pointer event
7
7
  */
8
- export declare function getEventPosition(event: MouseEvent | TouchEvent): Position | undefined;
8
+ export declare function getPosition(event: MouseEvent | TouchEvent): Position | undefined;
9
9
  export {};
package/types/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './array';
1
2
  export * from './element';
2
3
  export * from './event';
3
4
  export * from './number';
package/types/number.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  /**
2
- * Clamps a number between a minimum and maximum value
2
+ * - Clamps a number between a minimum and maximum value
3
+ * - If `loop` is `true`, when the value is less than the minimum, it will be clamped as the maximum, and vice versa
3
4
  */
4
- export declare function clampNumber(value: number, min: number, max: number): number;
5
+ export declare function clamp(value: number, min: number, max: number, loop?: boolean): number;
5
6
  /**
6
7
  * - Gets the number value from an unknown value
7
8
  * - Returns `NaN` if the value is `undefined`, `null`, or cannot be parsed
package/types/value.d.ts CHANGED
@@ -26,4 +26,4 @@ export declare function isObject(value: unknown): value is GenericObject;
26
26
  * - If a part of the path does not exist, it will be created, either as an array or a generic object, depending on the key
27
27
  * - Returns the original object
28
28
  */
29
- export declare function setValue<Model extends ValueObject>(data: Model, key: Key, value: unknown): Model;
29
+ export declare function setValue<T extends ValueObject>(data: T, key: Key, value: unknown): T;