@pexip-engage-public/utils 0.1.46
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/CHANGELOG.md +549 -0
- package/README.md +5 -0
- package/dist/array.d.ts +8 -0
- package/dist/array.d.ts.map +1 -0
- package/dist/array.js +22 -0
- package/dist/array.js.map +1 -0
- package/dist/copyToClipBoard.d.ts +7 -0
- package/dist/copyToClipBoard.d.ts.map +1 -0
- package/dist/copyToClipBoard.js +22 -0
- package/dist/copyToClipBoard.js.map +1 -0
- package/dist/get-current-position.d.ts +14 -0
- package/dist/get-current-position.d.ts.map +1 -0
- package/dist/get-current-position.js +23 -0
- package/dist/get-current-position.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/invariant.d.ts +3 -0
- package/dist/invariant.d.ts.map +1 -0
- package/dist/invariant.js +6 -0
- package/dist/invariant.js.map +1 -0
- package/dist/object.d.ts +17 -0
- package/dist/object.d.ts.map +1 -0
- package/dist/object.js +21 -0
- package/dist/object.js.map +1 -0
- package/dist/safe-json-parse.d.ts +4 -0
- package/dist/safe-json-parse.d.ts.map +1 -0
- package/dist/safe-json-parse.js +11 -0
- package/dist/safe-json-parse.js.map +1 -0
- package/dist/type-guard.d.ts +5 -0
- package/dist/type-guard.d.ts.map +1 -0
- package/dist/type-guard.js +10 -0
- package/dist/type-guard.js.map +1 -0
- package/dist/useDebouncedState.d.ts +6 -0
- package/dist/useDebouncedState.d.ts.map +1 -0
- package/dist/useDebouncedState.js +14 -0
- package/dist/useDebouncedState.js.map +1 -0
- package/dist/useEffectEvent.d.ts +6 -0
- package/dist/useEffectEvent.d.ts.map +1 -0
- package/dist/useEffectEvent.js +13 -0
- package/dist/useEffectEvent.js.map +1 -0
- package/dist/useElementSize.d.ts +10 -0
- package/dist/useElementSize.d.ts.map +1 -0
- package/dist/useElementSize.js +22 -0
- package/dist/useElementSize.js.map +1 -0
- package/dist/useEventListener.d.ts +5 -0
- package/dist/useEventListener.d.ts.map +1 -0
- package/dist/useEventListener.js +17 -0
- package/dist/useEventListener.js.map +1 -0
- package/dist/useIsomorphicLayoutEffect.d.ts +8 -0
- package/dist/useIsomorphicLayoutEffect.d.ts.map +1 -0
- package/dist/useIsomorphicLayoutEffect.js +8 -0
- package/dist/useIsomorphicLayoutEffect.js.map +1 -0
- package/package.json +58 -0
- package/src/array.ts +29 -0
- package/src/copyToClipBoard.tsx +30 -0
- package/src/get-current-position.ts +36 -0
- package/src/index.tsx +13 -0
- package/src/invariant.ts +7 -0
- package/src/object.ts +36 -0
- package/src/safe-json-parse.ts +10 -0
- package/src/type-guard.ts +10 -0
- package/src/useDebouncedState.ts +17 -0
- package/src/useEffectEvent.ts +17 -0
- package/src/useElementSize.ts +35 -0
- package/src/useEventListener.ts +30 -0
- package/src/useIsomorphicLayoutEffect.ts +9 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * as array from "./array.js";
|
|
2
|
+
export * from "./copyToClipBoard.js";
|
|
3
|
+
export * from "./invariant.js";
|
|
4
|
+
export * as obj from "./object.js";
|
|
5
|
+
export * from "./safe-json-parse.js";
|
|
6
|
+
export * from "./useDebouncedState.js";
|
|
7
|
+
export * from "./useEffectEvent.js";
|
|
8
|
+
export * from "./useElementSize.js";
|
|
9
|
+
export * from "./useEventListener.js";
|
|
10
|
+
export * from "./useIsomorphicLayoutEffect.js";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invariant.d.ts","sourceRoot":"","sources":["../src/invariant.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;AAC3E,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invariant.js","sourceRoot":"","sources":["../src/invariant.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,SAAS,CAAC,KAAc,EAAE,OAAgB;IACxD,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;IACzF,CAAC;AACH,CAAC"}
|
package/dist/object.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare function keys<T extends {}>(object: T): [keyof T, ...(keyof T)[]];
|
|
2
|
+
type ReplaceStringWithNull<T extends {
|
|
3
|
+
[key: string]: unknown;
|
|
4
|
+
}> = {
|
|
5
|
+
[K in keyof T]: T[K] extends string | undefined ? T[K] | null : T[K] extends {
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
} ? ReplaceStringWithNull<T[K]> : T[K];
|
|
8
|
+
};
|
|
9
|
+
export declare const replaceEmptyString: <T extends {
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}>(obj: T) => ReplaceStringWithNull<T>;
|
|
12
|
+
type ValueOf<T> = T[keyof T];
|
|
13
|
+
type Entries<T> = [keyof T, ValueOf<T>][];
|
|
14
|
+
export declare function entries<T extends object>(obj: T): Entries<T>;
|
|
15
|
+
export declare function values<T extends object>(obj: T): ValueOf<T>[];
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=object.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":"AAAA,wBAAgB,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAEvE;AAED,KAAK,qBAAqB,CAAC,CAAC,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,IAAI;KAChE,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,GAC3C,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GACX,CAAC,CAAC,CAAC,CAAC,SAAS;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,GACrC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAC3B,CAAC,CAAC,CAAC,CAAC;CACX,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,CAAC,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,EACrE,KAAK,CAAC,KACL,qBAAqB,CAAC,CAAC,CAUzB,CAAC;AAEF,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7B,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAE1C,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAE5D;AAED,wBAAgB,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAE7D"}
|
package/dist/object.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function keys(object) {
|
|
2
|
+
return Object.keys(object);
|
|
3
|
+
}
|
|
4
|
+
export const replaceEmptyString = (obj) => {
|
|
5
|
+
for (const key in obj) {
|
|
6
|
+
if (obj[key] === "") {
|
|
7
|
+
obj[key] = null;
|
|
8
|
+
}
|
|
9
|
+
else if (typeof obj[key] === "object") {
|
|
10
|
+
replaceEmptyString(obj[key]);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return obj;
|
|
14
|
+
};
|
|
15
|
+
export function entries(obj) {
|
|
16
|
+
return Object.entries(obj);
|
|
17
|
+
}
|
|
18
|
+
export function values(obj) {
|
|
19
|
+
return Object.values(obj);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=object.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object.js","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,IAAI,CAAe,MAAS;IAC1C,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAA8B,CAAC;AAC1D,CAAC;AAUD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,GAAM,EACoB,EAAE;IAC5B,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC;YACpB,GAAG,CAAC,GAAG,CAAC,GAAG,IAAqB,CAAC;QACnC,CAAC;aAAM,IAAI,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ,EAAE,CAAC;YACxC,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAQ,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAKF,MAAM,UAAU,OAAO,CAAmB,GAAM;IAC9C,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAe,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,MAAM,CAAmB,GAAM;IAC7C,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAiB,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-json-parse.d.ts","sourceRoot":"","sources":["../src/safe-json-parse.ts"],"names":[],"mappings":"AAAA,KAAK,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;AAEhE,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAOrE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-json-parse.js","sourceRoot":"","sources":["../src/safe-json-parse.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,aAAa,CAAC,KAAqB;IACjD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAS,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-guard.d.ts","sourceRoot":"","sources":["../src/type-guard.ts"],"names":[],"mappings":"AAEA,wBAAgB,eAAe,CAAC,UAAU,SAAS,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;wBAEzD,OAAO,KAAG,KAAK,IAAI,UAAU;;EAKpE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-guard.js","sourceRoot":"","sources":["../src/type-guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC,MAAM,UAAU,eAAe,CAA4B,GAAsC;IAC/F,OAAO;QACL,SAAS,EAAE,SAAS,OAAO,CAAC,KAAe;YACzC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,GAAG,CAAC;QACnD,CAAC;QACD,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC;KAClB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDebouncedState.d.ts","sourceRoot":"","sources":["../src/useDebouncedState.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,SAAM,KAUxD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* @param {T} value - Value to debounce
|
|
4
|
+
* @param {number} [delay=300] - how long to wait before updating the value
|
|
5
|
+
*/
|
|
6
|
+
export function useDebounceState(value, delay = 300) {
|
|
7
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const timeoutId = setTimeout(() => setDebouncedValue(value), delay);
|
|
10
|
+
return () => clearTimeout(timeoutId);
|
|
11
|
+
}, [value, delay]);
|
|
12
|
+
return debouncedValue;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=useDebouncedState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDebouncedState.js","sourceRoot":"","sources":["../src/useDebouncedState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAI,KAAQ,EAAE,KAAK,GAAG,GAAG;IACvD,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5D,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;QAEpE,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAEnB,OAAO,cAAc,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polyfill until actual `useEffectEvent` lands:
|
|
3
|
+
* https://beta.reactjs.org/learn/separating-events-from-effects#declaring-an-effect-event
|
|
4
|
+
*/
|
|
5
|
+
export declare function useEffectEvent<Args extends unknown[], ReturnType>(fn: (...args: Args) => ReturnType): (...args: Args) => ReturnType;
|
|
6
|
+
//# sourceMappingURL=useEffectEvent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEffectEvent.d.ts","sourceRoot":"","sources":["../src/useEffectEvent.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,SAAS,OAAO,EAAE,EAAE,UAAU,EAC/D,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,UAAU,aAQJ,IAAI,gBAClC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Polyfill until actual `useEffectEvent` lands:
|
|
4
|
+
* https://beta.reactjs.org/learn/separating-events-from-effects#declaring-an-effect-event
|
|
5
|
+
*/
|
|
6
|
+
export function useEffectEvent(fn) {
|
|
7
|
+
const ref = useRef(fn);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
ref.current = fn;
|
|
10
|
+
});
|
|
11
|
+
return useCallback((...args) => ref.current(...args), []);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=useEffectEvent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEffectEvent.js","sourceRoot":"","sources":["../src/useEffectEvent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAEvD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,EAAiC;IAEjC,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IAEvB,SAAS,CAAC,GAAG,EAAE;QACb,GAAG,CAAC,OAAO,GAAG,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,OAAO,WAAW,CAAC,CAAC,GAAG,IAAU,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;AAClE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useElementSize.d.ts","sourceRoot":"","sources":["../src/useElementSize.ts"],"names":[],"mappings":"AAKA,UAAU,IAAI;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,WAAW,GAAG,cAAc,KAAK;IACxE,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI;IACxB,IAAI;CACL,CAqBA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
import { useEventListener } from "./useEventListener.js";
|
|
3
|
+
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
4
|
+
export function useElementSize() {
|
|
5
|
+
const [ref, setRef] = useState(null);
|
|
6
|
+
const [size, setSize] = useState({
|
|
7
|
+
height: 0,
|
|
8
|
+
width: 0,
|
|
9
|
+
});
|
|
10
|
+
const handleSize = useCallback(() => {
|
|
11
|
+
setSize({
|
|
12
|
+
height: ref?.offsetHeight ?? 0,
|
|
13
|
+
width: ref?.offsetWidth ?? 0,
|
|
14
|
+
});
|
|
15
|
+
}, [ref?.offsetHeight, ref?.offsetWidth]);
|
|
16
|
+
useEventListener("resize", handleSize, window);
|
|
17
|
+
useIsomorphicLayoutEffect(() => {
|
|
18
|
+
handleSize();
|
|
19
|
+
}, [ref?.offsetHeight, ref?.offsetWidth, handleSize]);
|
|
20
|
+
return [setRef, size];
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=useElementSize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useElementSize.js","sourceRoot":"","sources":["../src/useElementSize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAO3E,MAAM,UAAU,cAAc;IAI5B,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAW,IAAI,CAAC,CAAC;IAC/C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAO;QACrC,MAAM,EAAE,CAAC;QACT,KAAK,EAAE,CAAC;KACT,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;QAClC,OAAO,CAAC;YACN,MAAM,EAAE,GAAG,EAAE,YAAY,IAAI,CAAC;YAC9B,KAAK,EAAE,GAAG,EAAE,WAAW,IAAI,CAAC;SAC7B,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC;IAE1C,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAE/C,yBAAyB,CAAC,GAAG,EAAE;QAC7B,UAAU,EAAE,CAAC;IACf,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;IAEtD,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
type Options = Pick<AddEventListenerOptions, "capture" | "passive" | "once">;
|
|
2
|
+
type EventMap = HTMLElementEventMap & DocumentEventMap & WindowEventMap;
|
|
3
|
+
export declare function useEventListener<K extends keyof EventMap>(eventName: K, handler: (event: EventMap[K]) => void, element?: HTMLElement | Document | Window, options?: Options): void;
|
|
4
|
+
export {};
|
|
5
|
+
//# sourceMappingURL=useEventListener.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEventListener.d.ts","sourceRoot":"","sources":["../src/useEventListener.ts"],"names":[],"mappings":"AAEA,KAAK,OAAO,GAAG,IAAI,CAAC,uBAAuB,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC,CAAC;AAE7E,KAAK,QAAQ,GAAG,mBAAmB,GAAG,gBAAgB,GAAG,cAAc,CAAC;AAExE,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,QAAQ,EACvD,SAAS,EAAE,CAAC,EACZ,OAAO,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,EACrC,OAAO,GAAE,WAAW,GAAG,QAAQ,GAAG,MAAiB,EACnD,OAAO,GAAE,OAAY,QAmBtB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
export function useEventListener(eventName, handler, element = document, options = {}) {
|
|
3
|
+
const savedHandler = useRef(null);
|
|
4
|
+
const { capture, once, passive } = options;
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
savedHandler.current = handler;
|
|
7
|
+
}, [handler]);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const eventListener = (event) => savedHandler.current?.(event);
|
|
10
|
+
const opts = { capture, once, passive };
|
|
11
|
+
element.addEventListener(eventName, eventListener, opts);
|
|
12
|
+
return () => {
|
|
13
|
+
element.removeEventListener(eventName, eventListener, opts);
|
|
14
|
+
};
|
|
15
|
+
}, [eventName, element, capture, passive, once]);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=useEventListener.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEventListener.js","sourceRoot":"","sources":["../src/useEventListener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAM1C,MAAM,UAAU,gBAAgB,CAC9B,SAAY,EACZ,OAAqC,EACrC,UAA2C,QAAQ,EACnD,UAAmB,EAAE;IAErB,MAAM,YAAY,GAAG,MAAM,CAA+B,IAAI,CAAC,CAAC;IAChE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAE3C,SAAS,CAAC,GAAG,EAAE;QACb,YAAY,CAAC,OAAO,GAAG,OAAO,CAAC;IACjC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,aAAa,GAAG,CAAC,KAAU,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QAEpE,MAAM,IAAI,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QACxC,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;QAEzD,OAAO,GAAG,EAAE;YACV,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;QAC9D,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { useLayoutEffect } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* During SSR, React emits a warning when calling useLayoutEffect.
|
|
4
|
+
* Since neither useLayoutEffect nor useEffect run on the server,
|
|
5
|
+
* we can suppress this by replace it with a noop on the server.
|
|
6
|
+
*/
|
|
7
|
+
export declare const useIsomorphicLayoutEffect: typeof useLayoutEffect;
|
|
8
|
+
//# sourceMappingURL=useIsomorphicLayoutEffect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIsomorphicLayoutEffect.d.ts","sourceRoot":"","sources":["../src/useIsomorphicLayoutEffect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAExC;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,wBACwB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { useLayoutEffect } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* During SSR, React emits a warning when calling useLayoutEffect.
|
|
4
|
+
* Since neither useLayoutEffect nor useEffect run on the server,
|
|
5
|
+
* we can suppress this by replace it with a noop on the server.
|
|
6
|
+
*/
|
|
7
|
+
export const useIsomorphicLayoutEffect = typeof document !== "undefined" ? useLayoutEffect : () => { };
|
|
8
|
+
//# sourceMappingURL=useIsomorphicLayoutEffect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIsomorphicLayoutEffect.js","sourceRoot":"","sources":["../src/useIsomorphicLayoutEffect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAExC;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GACpC,OAAO,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pexip-engage-public/utils",
|
|
3
|
+
"version": "0.1.46",
|
|
4
|
+
"description": "Shared utils for Pexip Engage",
|
|
5
|
+
"homepage": "https://github.com/skedify/frontend-mono/tree/develop/packages/utils#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/skedify/frontend-mono/issues"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/skedify/frontend-mono.git",
|
|
12
|
+
"directory": "packages/utils"
|
|
13
|
+
},
|
|
14
|
+
"license": "UNLICENSED",
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "Pexip Engage",
|
|
17
|
+
"email": "info@pexip.com",
|
|
18
|
+
"url": "https://engage.pexip.com"
|
|
19
|
+
},
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"type": "module",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": "./dist/index.js",
|
|
24
|
+
"./array": "./dist/array.js",
|
|
25
|
+
"./get-current-position": "./dist/get-current-position.js",
|
|
26
|
+
"./invariant": "./dist/invariant.js",
|
|
27
|
+
"./safe-json-parse": "./dist/safe-json-parse.js",
|
|
28
|
+
"./type-guard": "./dist/type-guard.js",
|
|
29
|
+
"./use-effect-event": "./dist/useEffectEvent.js"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"CHANGELOG.md",
|
|
34
|
+
"src"
|
|
35
|
+
],
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"react": "^19.1.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"vitest": "^3.2.4",
|
|
41
|
+
"@pexip-engage/tsconfig": "0.1.1",
|
|
42
|
+
"eslint-config-pexip-engage": "1.1.24"
|
|
43
|
+
},
|
|
44
|
+
"volta": {
|
|
45
|
+
"extends": "../../package.json"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public",
|
|
49
|
+
"registry": "https://registry.npmjs.org"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsc",
|
|
53
|
+
"clean": "rm -rf .turbo node_modules dist tsconfig.tsbuildinfo",
|
|
54
|
+
"lint": "cross-env TIMING=1 eslint --max-warnings=0 .",
|
|
55
|
+
"lint:fix": "pnpm lint --fix",
|
|
56
|
+
"test": "vitest run --passWithNoTests"
|
|
57
|
+
}
|
|
58
|
+
}
|
package/src/array.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { invariant } from "./invariant.js";
|
|
2
|
+
|
|
3
|
+
export function filterBoolean<T>(x: T | false | undefined | null | "" | 0): x is T {
|
|
4
|
+
return !!x;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function times(n: number): number[] {
|
|
8
|
+
return Array.from(new Array(n).keys());
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function keys<T extends {}>(object: T): Array<keyof T> {
|
|
12
|
+
return Object.keys(object) as Array<keyof T>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function toMap<T extends { id: string }>(arr: T[]): Record<string, T> {
|
|
16
|
+
return arr.reduce<Record<string, T>>((acc, current) => {
|
|
17
|
+
acc[current.id] = current;
|
|
18
|
+
|
|
19
|
+
return acc;
|
|
20
|
+
}, {});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getRandomItem<T>(array: T[] | ReadonlyArray<T>): T {
|
|
24
|
+
const item = array[Math.floor(Math.random() * array.length)];
|
|
25
|
+
|
|
26
|
+
invariant(item, "Passed empty array to getRandomItem");
|
|
27
|
+
|
|
28
|
+
return item;
|
|
29
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
export enum CopyStatusEnum {
|
|
4
|
+
SUCCESS = 0,
|
|
5
|
+
INACTIVE = 1,
|
|
6
|
+
FAILED = 2,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function useCopyToClipboard(notifyTimeout = 2500) {
|
|
10
|
+
const [status, setCopyStatus] = useState<CopyStatusEnum>(CopyStatusEnum.INACTIVE);
|
|
11
|
+
|
|
12
|
+
const copyToClipboard = useCallback((text: string) => {
|
|
13
|
+
navigator.clipboard.writeText(text).then(
|
|
14
|
+
() => setCopyStatus(CopyStatusEnum.SUCCESS),
|
|
15
|
+
() => setCopyStatus(CopyStatusEnum.FAILED),
|
|
16
|
+
);
|
|
17
|
+
}, []);
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (status === CopyStatusEnum.INACTIVE) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const timeoutId = setTimeout(() => setCopyStatus(CopyStatusEnum.INACTIVE), notifyTimeout);
|
|
25
|
+
|
|
26
|
+
return () => clearTimeout(timeoutId);
|
|
27
|
+
}, [status, notifyTimeout]);
|
|
28
|
+
|
|
29
|
+
return [status, copyToClipboard] as const;
|
|
30
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface GeoPosition {
|
|
2
|
+
timestamp: number;
|
|
3
|
+
coords: {
|
|
4
|
+
latitude: number;
|
|
5
|
+
longitude: number;
|
|
6
|
+
accuracy: number;
|
|
7
|
+
altitude: number | null;
|
|
8
|
+
altitudeAccuracy: number | null;
|
|
9
|
+
heading: number | null;
|
|
10
|
+
speed: number | null;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function getCurrentPosition() {
|
|
15
|
+
return new Promise<GeoPosition>((res, rej) => {
|
|
16
|
+
if (window.navigator && "geolocation" in navigator) {
|
|
17
|
+
return navigator.geolocation.getCurrentPosition((result) => {
|
|
18
|
+
// result is destructered for compatibility with iframe message serialization.
|
|
19
|
+
res({
|
|
20
|
+
coords: {
|
|
21
|
+
accuracy: result.coords.accuracy,
|
|
22
|
+
altitude: result.coords.altitude,
|
|
23
|
+
altitudeAccuracy: result.coords.altitudeAccuracy,
|
|
24
|
+
heading: result.coords.heading,
|
|
25
|
+
latitude: result.coords.latitude,
|
|
26
|
+
longitude: result.coords.longitude,
|
|
27
|
+
speed: result.coords.speed,
|
|
28
|
+
},
|
|
29
|
+
timestamp: result.timestamp,
|
|
30
|
+
});
|
|
31
|
+
}, rej);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
rej("User location not available");
|
|
35
|
+
});
|
|
36
|
+
}
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * as array from "./array.js";
|
|
2
|
+
export * from "./copyToClipBoard.js";
|
|
3
|
+
export * from "./invariant.js";
|
|
4
|
+
export * as obj from "./object.js";
|
|
5
|
+
export * from "./safe-json-parse.js";
|
|
6
|
+
export * from "./useDebouncedState.js";
|
|
7
|
+
export * from "./useEffectEvent.js";
|
|
8
|
+
export * from "./useElementSize.js";
|
|
9
|
+
export * from "./useEventListener.js";
|
|
10
|
+
export * from "./useIsomorphicLayoutEffect.js";
|
|
11
|
+
|
|
12
|
+
export type ValueOf<T> = T[keyof T];
|
|
13
|
+
export type Prettify<T> = { [K in keyof T]: T[K] } & {};
|
package/src/invariant.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function invariant(value: boolean, message?: string): asserts value;
|
|
2
|
+
export function invariant<T>(value: T | null | undefined, message?: string): asserts value is T;
|
|
3
|
+
export function invariant(value: unknown, message?: string): void {
|
|
4
|
+
if (value === false || value == null) {
|
|
5
|
+
throw new Error(message != null ? `Assertion failed: ${message}` : "Assertion failed");
|
|
6
|
+
}
|
|
7
|
+
}
|
package/src/object.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export function keys<T extends {}>(object: T): [keyof T, ...(keyof T)[]] {
|
|
2
|
+
return Object.keys(object) as [keyof T, ...(keyof T)[]];
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
type ReplaceStringWithNull<T extends { [key: string]: unknown }> = {
|
|
6
|
+
[K in keyof T]: T[K] extends string | undefined
|
|
7
|
+
? T[K] | null
|
|
8
|
+
: T[K] extends { [key: string]: unknown }
|
|
9
|
+
? ReplaceStringWithNull<T[K]>
|
|
10
|
+
: T[K];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const replaceEmptyString = <T extends { [key: string]: unknown }>(
|
|
14
|
+
obj: T,
|
|
15
|
+
): ReplaceStringWithNull<T> => {
|
|
16
|
+
for (const key in obj) {
|
|
17
|
+
if (obj[key] === "") {
|
|
18
|
+
obj[key] = null as T[typeof key];
|
|
19
|
+
} else if (typeof obj[key] === "object") {
|
|
20
|
+
replaceEmptyString(obj[key] as any);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return obj;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
type ValueOf<T> = T[keyof T];
|
|
28
|
+
type Entries<T> = [keyof T, ValueOf<T>][];
|
|
29
|
+
|
|
30
|
+
export function entries<T extends object>(obj: T): Entries<T> {
|
|
31
|
+
return Object.entries(obj) as Entries<T>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function values<T extends object>(obj: T): ValueOf<T>[] {
|
|
35
|
+
return Object.values(obj) as ValueOf<T>[];
|
|
36
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { keys } from "./object.js";
|
|
2
|
+
|
|
3
|
+
export function createTypeGuard<Constraint extends string>(map: Record<Constraint, string | true>) {
|
|
4
|
+
return {
|
|
5
|
+
typeguard: function isValue(value?: unknown): value is Constraint {
|
|
6
|
+
return typeof value === "string" && value in map;
|
|
7
|
+
},
|
|
8
|
+
values: keys(map),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {T} value - Value to debounce
|
|
5
|
+
* @param {number} [delay=300] - how long to wait before updating the value
|
|
6
|
+
*/
|
|
7
|
+
export function useDebounceState<T>(value: T, delay = 300) {
|
|
8
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const timeoutId = setTimeout(() => setDebouncedValue(value), delay);
|
|
12
|
+
|
|
13
|
+
return () => clearTimeout(timeoutId);
|
|
14
|
+
}, [value, delay]);
|
|
15
|
+
|
|
16
|
+
return debouncedValue;
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Polyfill until actual `useEffectEvent` lands:
|
|
5
|
+
* https://beta.reactjs.org/learn/separating-events-from-effects#declaring-an-effect-event
|
|
6
|
+
*/
|
|
7
|
+
export function useEffectEvent<Args extends unknown[], ReturnType>(
|
|
8
|
+
fn: (...args: Args) => ReturnType,
|
|
9
|
+
) {
|
|
10
|
+
const ref = useRef(fn);
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
ref.current = fn;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
return useCallback((...args: Args) => ref.current(...args), []);
|
|
17
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { useEventListener } from "./useEventListener.js";
|
|
4
|
+
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
5
|
+
|
|
6
|
+
interface Size {
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function useElementSize<T extends HTMLElement = HTMLDivElement>(): [
|
|
12
|
+
(node: T | null) => void,
|
|
13
|
+
Size,
|
|
14
|
+
] {
|
|
15
|
+
const [ref, setRef] = useState<T | null>(null);
|
|
16
|
+
const [size, setSize] = useState<Size>({
|
|
17
|
+
height: 0,
|
|
18
|
+
width: 0,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const handleSize = useCallback(() => {
|
|
22
|
+
setSize({
|
|
23
|
+
height: ref?.offsetHeight ?? 0,
|
|
24
|
+
width: ref?.offsetWidth ?? 0,
|
|
25
|
+
});
|
|
26
|
+
}, [ref?.offsetHeight, ref?.offsetWidth]);
|
|
27
|
+
|
|
28
|
+
useEventListener("resize", handleSize, window);
|
|
29
|
+
|
|
30
|
+
useIsomorphicLayoutEffect(() => {
|
|
31
|
+
handleSize();
|
|
32
|
+
}, [ref?.offsetHeight, ref?.offsetWidth, handleSize]);
|
|
33
|
+
|
|
34
|
+
return [setRef, size];
|
|
35
|
+
}
|