@nativerent/js-utils 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/jest.config.mjs +4 -0
- package/jest.setup.ts +4 -0
- package/package.json +1 -1
- package/src/index.ts +187 -198
- package/src/types.d.ts +0 -2
- package/tests/tests.ts +1728 -0
package/jest.config.mjs
CHANGED
package/jest.setup.ts
ADDED
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Primitive, SimpleObject } from "./types";
|
|
2
2
|
|
|
3
3
|
export function debounce(fn: Function, delay: number): () => void {
|
|
4
4
|
let timeout: ReturnType<typeof setTimeout>;
|
|
@@ -42,7 +42,7 @@ export function isString(value: any): value is string {
|
|
|
42
42
|
* Check if the given argument is a string which is not empty
|
|
43
43
|
*/
|
|
44
44
|
export function isNotEmptyString(value: any) {
|
|
45
|
-
return isString(value) && value.length;
|
|
45
|
+
return isString(value) && value.length > 0;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
export function isHTMLElement(value: any): value is HTMLElement {
|
|
@@ -88,16 +88,18 @@ export function arrayIntersect(
|
|
|
88
88
|
array1: Array<Primitive | null | undefined>,
|
|
89
89
|
array2: Array<Primitive | null | undefined>,
|
|
90
90
|
) {
|
|
91
|
-
|
|
91
|
+
const set = new Set(array2);
|
|
92
|
+
return array1.filter((value) => set.has(value));
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
export function deepCloneObject<Type>(object: Type): Type {
|
|
95
96
|
return JSON.parse(JSON.stringify(object));
|
|
96
97
|
}
|
|
97
98
|
|
|
99
|
+
// todo: non-px values
|
|
98
100
|
export function getNumericStyleProp(prop: string, el: Element) {
|
|
99
101
|
const styles: { [key: string]: any } = window.getComputedStyle(el);
|
|
100
|
-
return !isNullOrUndef(styles[prop]) ?
|
|
102
|
+
return !isNullOrUndef(styles[prop]) ? parseFloat(styles[prop] || 0) : 0;
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
export function objectHasProp(
|
|
@@ -150,58 +152,39 @@ export function objectToQueryString(object: {
|
|
|
150
152
|
.join("&");
|
|
151
153
|
}
|
|
152
154
|
|
|
153
|
-
export function countObjectInnerLength(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
return 0;
|
|
161
|
-
} else if (len === 1) {
|
|
162
|
-
return obj[0].length;
|
|
163
|
-
} else {
|
|
164
|
-
return obj.reduce((acc: any, cur) => {
|
|
165
|
-
if (Array.isArray(acc)) {
|
|
166
|
-
acc = acc.length;
|
|
167
|
-
}
|
|
168
|
-
if (cur) {
|
|
169
|
-
acc += cur.length;
|
|
170
|
-
}
|
|
171
|
-
return acc;
|
|
172
|
-
});
|
|
173
|
-
}
|
|
155
|
+
export function countObjectInnerLength(
|
|
156
|
+
object: Record<string | number, any[] | null | undefined>,
|
|
157
|
+
) {
|
|
158
|
+
return Object.values(object).reduce(
|
|
159
|
+
(sum, arr) => sum + (arr?.length ?? 0),
|
|
160
|
+
0,
|
|
161
|
+
);
|
|
174
162
|
}
|
|
175
163
|
|
|
176
164
|
/**
|
|
177
165
|
* Check if the element is in viewport
|
|
178
166
|
*/
|
|
179
|
-
export function isElementVisible(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
167
|
+
export function isElementVisible(
|
|
168
|
+
element: HTMLElement,
|
|
169
|
+
minVisiblePercent = 50,
|
|
170
|
+
): boolean {
|
|
171
|
+
const { top, bottom, height } = element.getBoundingClientRect();
|
|
172
|
+
if (!height) return false;
|
|
186
173
|
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
const viewPortHeight = window.innerHeight;
|
|
174
|
+
const viewportTop = 0;
|
|
175
|
+
const viewportBottom = window.innerHeight;
|
|
190
176
|
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
viewPortHeight - elementTop
|
|
195
|
-
: // the element is still in or above viewport
|
|
196
|
-
elementBottom;
|
|
177
|
+
const visibleTop = Math.max(top, viewportTop);
|
|
178
|
+
const visibleBottom = Math.min(bottom, viewportBottom);
|
|
179
|
+
const visibleHeight = Math.max(0, visibleBottom - visibleTop);
|
|
197
180
|
|
|
198
|
-
return (
|
|
181
|
+
return (visibleHeight / height) * 100 >= minVisiblePercent;
|
|
199
182
|
}
|
|
200
183
|
|
|
201
184
|
export function decodeSafeURL(url: string): string {
|
|
202
185
|
try {
|
|
203
186
|
return decodeURI(url);
|
|
204
|
-
} catch
|
|
187
|
+
} catch {
|
|
205
188
|
return url;
|
|
206
189
|
}
|
|
207
190
|
}
|
|
@@ -240,12 +223,14 @@ export function injectStyleLink(filename: string): void {
|
|
|
240
223
|
document.head.appendChild(link);
|
|
241
224
|
}
|
|
242
225
|
|
|
243
|
-
export function toBinaryStr(str: string) {
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
226
|
+
export function toBinaryStr(str: string): string {
|
|
227
|
+
const CHUNK = 0x8000; // String.fromCharCode(...charCodes) can overflow the call stack with large strings
|
|
228
|
+
const bytes = new TextEncoder().encode(str);
|
|
229
|
+
let result = "";
|
|
230
|
+
for (let i = 0; i < bytes.length; i += CHUNK) {
|
|
231
|
+
result += String.fromCharCode(...bytes.subarray(i, i + CHUNK));
|
|
232
|
+
}
|
|
233
|
+
return result;
|
|
249
234
|
}
|
|
250
235
|
|
|
251
236
|
/**
|
|
@@ -269,18 +254,11 @@ export function stringToHtmlElements(html: string): NodeListOf<ChildNode> {
|
|
|
269
254
|
*/
|
|
270
255
|
export function createHtmlElement(
|
|
271
256
|
type: string,
|
|
272
|
-
attributes:
|
|
257
|
+
attributes: Record<string, string> = {},
|
|
273
258
|
): HTMLElement {
|
|
274
|
-
const
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
if (attrs.length) {
|
|
278
|
-
attrs.forEach((name) => {
|
|
279
|
-
element.setAttribute(name, attributes[name]);
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
return element;
|
|
259
|
+
const el = document.createElement(type);
|
|
260
|
+
for (const [k, v] of Object.entries(attributes)) el.setAttribute(k, v);
|
|
261
|
+
return el as HTMLElement;
|
|
284
262
|
}
|
|
285
263
|
|
|
286
264
|
/**
|
|
@@ -288,67 +266,69 @@ export function createHtmlElement(
|
|
|
288
266
|
*/
|
|
289
267
|
export function insertHtmlElements(
|
|
290
268
|
nodes: NodeListOf<Node>,
|
|
291
|
-
appendTo
|
|
269
|
+
appendTo: Element | ShadowRoot = document.body,
|
|
292
270
|
) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const fragment = new DocumentFragment();
|
|
271
|
+
const fragment = document.createDocumentFragment();
|
|
296
272
|
|
|
297
273
|
for (let i = 0; i < nodes.length; i++) {
|
|
298
|
-
|
|
299
|
-
|
|
274
|
+
const node = nodes[i];
|
|
275
|
+
|
|
276
|
+
// Allow elements + text nodes only
|
|
277
|
+
if (!isHTMLElement(node) && node.nodeType !== Node.TEXT_NODE) {
|
|
300
278
|
continue;
|
|
301
279
|
}
|
|
302
280
|
|
|
303
|
-
|
|
304
|
-
let newNode;
|
|
281
|
+
let newNode: Node;
|
|
305
282
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
283
|
+
// Text node
|
|
284
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
285
|
+
newNode = document.createTextNode(node.textContent ?? "");
|
|
286
|
+
fragment.appendChild(newNode);
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
309
289
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
290
|
+
// Element node from here on
|
|
291
|
+
const el = node as Element;
|
|
292
|
+
const tag = el.tagName.toLowerCase();
|
|
293
|
+
|
|
294
|
+
switch (tag) {
|
|
295
|
+
case "script": {
|
|
296
|
+
const src = el.getAttribute("src");
|
|
297
|
+
newNode =
|
|
298
|
+
!isNullOrUndef(src) && src.length > 0
|
|
299
|
+
? createScriptElement(src, false, flatHtmlAttributes(el.attributes))
|
|
300
|
+
: createScriptElement(
|
|
301
|
+
el.textContent ?? "",
|
|
302
|
+
true,
|
|
303
|
+
flatHtmlAttributes(el.attributes),
|
|
304
|
+
);
|
|
323
305
|
break;
|
|
306
|
+
}
|
|
324
307
|
|
|
325
308
|
case "style":
|
|
326
|
-
newNode = createStyleElement(
|
|
309
|
+
newNode = createStyleElement(el.textContent);
|
|
327
310
|
break;
|
|
328
311
|
|
|
329
312
|
case "svg":
|
|
330
313
|
newNode = createSvgElement(
|
|
331
|
-
|
|
332
|
-
flatHtmlAttributes(
|
|
314
|
+
el.innerHTML,
|
|
315
|
+
flatHtmlAttributes(el.attributes),
|
|
333
316
|
);
|
|
334
317
|
break;
|
|
335
318
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
default:
|
|
341
|
-
newNode = createHtmlElement(
|
|
342
|
-
node.tagName,
|
|
343
|
-
flatHtmlAttributes(node.attributes),
|
|
319
|
+
default: {
|
|
320
|
+
const created = createHtmlElement(
|
|
321
|
+
el.tagName,
|
|
322
|
+
flatHtmlAttributes(el.attributes),
|
|
344
323
|
);
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
insertHtmlElements(node.childNodes, newNode);
|
|
324
|
+
// Recurse for children (handles mixed element/text)
|
|
325
|
+
if (el.childNodes.length) {
|
|
326
|
+
insertHtmlElements(el.childNodes, created);
|
|
349
327
|
} else {
|
|
350
|
-
|
|
328
|
+
created.textContent = el.textContent ?? "";
|
|
351
329
|
}
|
|
330
|
+
newNode = created;
|
|
331
|
+
}
|
|
352
332
|
}
|
|
353
333
|
|
|
354
334
|
fragment.appendChild(newNode);
|
|
@@ -360,20 +340,21 @@ export function insertHtmlElements(
|
|
|
360
340
|
/**
|
|
361
341
|
* Make a simple object which contains only attribute name and value
|
|
362
342
|
*/
|
|
363
|
-
export function flatHtmlAttributes(
|
|
364
|
-
|
|
343
|
+
export function flatHtmlAttributes(
|
|
344
|
+
attributes?: NamedNodeMap | null,
|
|
345
|
+
): Record<string, string> {
|
|
346
|
+
if (!attributes) return {};
|
|
365
347
|
|
|
366
|
-
|
|
367
|
-
for (let i = 0; i < attributes.length; i++) {
|
|
368
|
-
let attr = attributes[i];
|
|
348
|
+
const result: Record<string, string> = {};
|
|
369
349
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
350
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
351
|
+
const attr = attributes[i];
|
|
352
|
+
if (attr) {
|
|
353
|
+
result[attr.name] = attr.value;
|
|
373
354
|
}
|
|
374
355
|
}
|
|
375
356
|
|
|
376
|
-
return
|
|
357
|
+
return result;
|
|
377
358
|
}
|
|
378
359
|
|
|
379
360
|
/**
|
|
@@ -381,33 +362,30 @@ export function flatHtmlAttributes(attributes?: NamedNodeMap) {
|
|
|
381
362
|
*/
|
|
382
363
|
export function createScriptElement(
|
|
383
364
|
js: string,
|
|
384
|
-
inline
|
|
385
|
-
attributes:
|
|
386
|
-
) {
|
|
387
|
-
const
|
|
388
|
-
const element = createHtmlElement("script") as HTMLScriptElement;
|
|
365
|
+
inline = false,
|
|
366
|
+
attributes: Record<string, string> = {},
|
|
367
|
+
): HTMLScriptElement {
|
|
368
|
+
const el = document.createElement("script");
|
|
389
369
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
element.setAttribute(name, attributes[name]);
|
|
393
|
-
});
|
|
370
|
+
for (const [k, v] of Object.entries(attributes)) {
|
|
371
|
+
el.setAttribute(k, v);
|
|
394
372
|
}
|
|
395
373
|
|
|
396
374
|
if (inline) {
|
|
397
|
-
|
|
375
|
+
el.text = js;
|
|
398
376
|
} else {
|
|
399
|
-
|
|
400
|
-
|
|
377
|
+
el.async = true;
|
|
378
|
+
el.src = js;
|
|
401
379
|
}
|
|
402
380
|
|
|
403
|
-
return
|
|
381
|
+
return el;
|
|
404
382
|
}
|
|
405
383
|
|
|
406
384
|
/**
|
|
407
385
|
* Create a <style> element
|
|
408
386
|
*/
|
|
409
|
-
export function createStyleElement(css: string | null) {
|
|
410
|
-
const element = createHtmlElement("style");
|
|
387
|
+
export function createStyleElement(css: string | null): HTMLStyleElement {
|
|
388
|
+
const element = createHtmlElement("style") as HTMLStyleElement;
|
|
411
389
|
|
|
412
390
|
if (css) {
|
|
413
391
|
element.appendChild(document.createTextNode(css));
|
|
@@ -419,7 +397,7 @@ export function createStyleElement(css: string | null) {
|
|
|
419
397
|
/**
|
|
420
398
|
* Create a <link> element
|
|
421
399
|
*/
|
|
422
|
-
export function createLinkElement(href: string) {
|
|
400
|
+
export function createLinkElement(href: string): HTMLLinkElement {
|
|
423
401
|
const element = createHtmlElement("link") as HTMLLinkElement;
|
|
424
402
|
|
|
425
403
|
element.rel = "stylesheet";
|
|
@@ -433,18 +411,18 @@ export function createLinkElement(href: string) {
|
|
|
433
411
|
*/
|
|
434
412
|
export function createSvgElement(
|
|
435
413
|
content: string,
|
|
436
|
-
attributes:
|
|
437
|
-
) {
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
414
|
+
attributes: Record<string, string> = {},
|
|
415
|
+
): SVGSVGElement {
|
|
416
|
+
const element = document.createElementNS(
|
|
417
|
+
"http://www.w3.org/2000/svg",
|
|
418
|
+
"svg",
|
|
419
|
+
) as SVGSVGElement;
|
|
420
|
+
|
|
421
|
+
for (const [name, value] of Object.entries(attributes)) {
|
|
422
|
+
element.setAttribute(name, value);
|
|
445
423
|
}
|
|
446
424
|
|
|
447
|
-
element.innerHTML = content;
|
|
425
|
+
element.innerHTML = content.trim();
|
|
448
426
|
|
|
449
427
|
return element;
|
|
450
428
|
}
|
|
@@ -455,9 +433,12 @@ export function createSvgElement(
|
|
|
455
433
|
export function createPixelElement(src: string) {
|
|
456
434
|
const image = document.createElement("img");
|
|
457
435
|
|
|
436
|
+
image.alt = "";
|
|
458
437
|
image.src = src;
|
|
459
438
|
image.width = 1;
|
|
460
439
|
image.height = 1;
|
|
440
|
+
image.loading = "eager";
|
|
441
|
+
image.setAttribute("aria-hidden", "true");
|
|
461
442
|
image.style.position = "absolute";
|
|
462
443
|
image.style.left = "-99999px";
|
|
463
444
|
|
|
@@ -490,29 +471,23 @@ export function insertCss(css: string, className?: string, external = false) {
|
|
|
490
471
|
* Get screen sizes
|
|
491
472
|
*/
|
|
492
473
|
export function getScreenSize(): { width: number; height: number } {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
if (window.screen) {
|
|
496
|
-
width = screen.width;
|
|
497
|
-
height = screen.height;
|
|
498
|
-
} else {
|
|
499
|
-
width = window.innerWidth;
|
|
500
|
-
height = window.innerHeight;
|
|
501
|
-
}
|
|
474
|
+
const width = window.screen?.width ?? window.innerWidth;
|
|
475
|
+
const height = window.screen?.height ?? window.innerHeight;
|
|
502
476
|
|
|
503
|
-
return {
|
|
504
|
-
width: width,
|
|
505
|
-
height: height,
|
|
506
|
-
};
|
|
477
|
+
return { width, height };
|
|
507
478
|
}
|
|
508
479
|
|
|
509
480
|
/**
|
|
510
481
|
* Get a random integer between min and max
|
|
511
482
|
*/
|
|
512
|
-
export function getRandomInt(min = 0, max = 4294967295) {
|
|
483
|
+
export function getRandomInt(min = 0, max = 4294967295): number {
|
|
513
484
|
min = Math.ceil(min);
|
|
514
485
|
max = Math.floor(max);
|
|
515
486
|
|
|
487
|
+
if (max <= min) {
|
|
488
|
+
return min;
|
|
489
|
+
}
|
|
490
|
+
|
|
516
491
|
return Math.floor(Math.random() * (max - min)) + min;
|
|
517
492
|
}
|
|
518
493
|
|
|
@@ -535,7 +510,10 @@ export function hashCode(str: string) {
|
|
|
535
510
|
/**
|
|
536
511
|
* Executes a callback as soon as DOM is interactive
|
|
537
512
|
*/
|
|
538
|
-
export function onDOMReady
|
|
513
|
+
export function onDOMReady<T extends unknown[]>(
|
|
514
|
+
callback: (...args: T) => void,
|
|
515
|
+
...args: T
|
|
516
|
+
): void {
|
|
539
517
|
if (
|
|
540
518
|
document.readyState === "interactive" ||
|
|
541
519
|
document.readyState === "complete"
|
|
@@ -693,54 +671,55 @@ export function fireInputEvent(
|
|
|
693
671
|
export function fireEvent(
|
|
694
672
|
eventName: string,
|
|
695
673
|
element: string | Element | null,
|
|
696
|
-
delay
|
|
674
|
+
delay = 0,
|
|
697
675
|
): void {
|
|
698
676
|
setTimeout(() => {
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
element.dispatchEvent(
|
|
705
|
-
new Event(eventName, {
|
|
706
|
-
bubbles: true,
|
|
707
|
-
}),
|
|
708
|
-
);
|
|
677
|
+
const target = isString(element)
|
|
678
|
+
? document.querySelector(element)
|
|
679
|
+
: element;
|
|
680
|
+
if (target) {
|
|
681
|
+
target.dispatchEvent(new Event(eventName, { bubbles: true }));
|
|
709
682
|
}
|
|
710
683
|
}, delay);
|
|
711
684
|
}
|
|
712
685
|
|
|
713
686
|
export function hasObjectChanged(
|
|
714
|
-
|
|
715
|
-
values: any[],
|
|
687
|
+
oldObj: Record<string, any>,
|
|
688
|
+
values: [string, any][],
|
|
689
|
+
checkNewKeys = false,
|
|
716
690
|
): boolean {
|
|
717
|
-
|
|
691
|
+
const newMap = new Map(values);
|
|
718
692
|
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
let
|
|
693
|
+
// check keys from old
|
|
694
|
+
for (const key of Object.keys(oldObj)) {
|
|
695
|
+
let oldVal = oldObj[key];
|
|
696
|
+
let newVal = newMap.get(key);
|
|
722
697
|
|
|
723
698
|
if (isObject(oldVal)) {
|
|
724
|
-
if (!isObject(newVal))
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
} else if (Array.isArray(newVal) || Array.isArray(oldVal)) {
|
|
730
|
-
newVal = Array.isArray(newVal) ? newVal : [];
|
|
731
|
-
oldVal = Array.isArray(oldVal) ? oldVal : [];
|
|
699
|
+
if (!isObject(newVal)) return true;
|
|
700
|
+
if (hasObjectChanged(oldVal, Object.entries(newVal), checkNewKeys))
|
|
701
|
+
return true;
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
732
704
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
705
|
+
if (Array.isArray(oldVal) || Array.isArray(newVal)) {
|
|
706
|
+
const oldArr = Array.isArray(oldVal) ? oldVal : [];
|
|
707
|
+
const newArr = Array.isArray(newVal) ? newVal : [];
|
|
708
|
+
if (arrayDiff(newArr, oldArr).length > 0) return true;
|
|
709
|
+
continue;
|
|
736
710
|
}
|
|
737
711
|
|
|
738
|
-
if (
|
|
739
|
-
|
|
712
|
+
if (areDiff(newVal, oldVal)) return true;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// optional: check keys that exist only in new
|
|
716
|
+
if (checkNewKeys) {
|
|
717
|
+
for (const key of newMap.keys()) {
|
|
718
|
+
if (!(key in oldObj)) return true;
|
|
740
719
|
}
|
|
741
720
|
}
|
|
742
721
|
|
|
743
|
-
return
|
|
722
|
+
return false;
|
|
744
723
|
}
|
|
745
724
|
|
|
746
725
|
export function roundBigNum(number: number): number {
|
|
@@ -759,15 +738,15 @@ export function roundBigNum(number: number): number {
|
|
|
759
738
|
return roundTo ? Math.round(number / roundTo) * roundTo : number;
|
|
760
739
|
}
|
|
761
740
|
|
|
762
|
-
export function extractNumbers(value:
|
|
763
|
-
if (!
|
|
741
|
+
export function extractNumbers(value: unknown): string {
|
|
742
|
+
if (!isString(value) && !isNum(value)) {
|
|
764
743
|
return "";
|
|
765
744
|
}
|
|
766
745
|
return value.toString().replace(/[^0-9]/g, "");
|
|
767
746
|
}
|
|
768
747
|
|
|
769
|
-
export function removeSpaces(value:
|
|
770
|
-
if (!
|
|
748
|
+
export function removeSpaces(value: unknown): string {
|
|
749
|
+
if (!isString(value) && !isNum(value)) {
|
|
771
750
|
return "";
|
|
772
751
|
}
|
|
773
752
|
return value.toString().replace(/\s/g, "");
|
|
@@ -802,28 +781,38 @@ export function areDiff(
|
|
|
802
781
|
return false;
|
|
803
782
|
}
|
|
804
783
|
|
|
805
|
-
export function flattenObject(
|
|
806
|
-
|
|
807
|
-
|
|
784
|
+
export function flattenObject(
|
|
785
|
+
obj: Record<string, any>,
|
|
786
|
+
prefix = "",
|
|
787
|
+
): Record<string, any> {
|
|
788
|
+
const pre = prefix ? `${prefix}.` : "";
|
|
789
|
+
|
|
790
|
+
return Object.keys(obj).reduce<Record<string, any>>((acc, k) => {
|
|
791
|
+
const val = obj[k];
|
|
792
|
+
const key = `${pre}${k}`;
|
|
793
|
+
|
|
808
794
|
if (
|
|
809
|
-
(isObject(
|
|
795
|
+
(isObject(val) || Array.isArray(val)) &&
|
|
810
796
|
getObjectKeys(obj[k]).length > 0
|
|
811
797
|
) {
|
|
812
|
-
Object.assign(acc, flattenObject(
|
|
798
|
+
Object.assign(acc, flattenObject(val, key));
|
|
813
799
|
} else {
|
|
814
|
-
acc[
|
|
800
|
+
acc[key] = val;
|
|
815
801
|
}
|
|
816
802
|
return acc;
|
|
817
|
-
}, {}
|
|
803
|
+
}, {});
|
|
818
804
|
}
|
|
819
805
|
|
|
820
|
-
export function flattenObjectAsArray(
|
|
821
|
-
|
|
806
|
+
export function flattenObjectAsArray(
|
|
807
|
+
obj: Record<string, any>,
|
|
808
|
+
): Record<string, any> {
|
|
822
809
|
const flat = flattenObject(obj);
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
810
|
+
const result: Record<string, any> = {};
|
|
811
|
+
|
|
812
|
+
for (const key of Object.keys(flat)) {
|
|
813
|
+
const newKey = key.replace(/\.([^.]+)/g, "[$1]");
|
|
814
|
+
result[newKey] = (flat as any)[key];
|
|
815
|
+
}
|
|
827
816
|
|
|
828
817
|
return result;
|
|
829
818
|
}
|