piral-hooks-utils 0.15.0-alpha.3537
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/LICENSE +21 -0
- package/README.md +57 -0
- package/esm/contexts/PiletApiProvider.d.ts +2 -0
- package/esm/contexts/PiletApiProvider.js +3 -0
- package/esm/contexts/PiletApiProvider.js.map +1 -0
- package/esm/contexts/index.d.ts +1 -0
- package/esm/contexts/index.js +2 -0
- package/esm/contexts/index.js.map +1 -0
- package/esm/hocs/index.d.ts +1 -0
- package/esm/hocs/index.js +2 -0
- package/esm/hocs/index.js.map +1 -0
- package/esm/hocs/withProvider.d.ts +15 -0
- package/esm/hocs/withProvider.js +13 -0
- package/esm/hocs/withProvider.js.map +1 -0
- package/esm/hooks/afterVisible.d.ts +8 -0
- package/esm/hooks/afterVisible.js +26 -0
- package/esm/hooks/afterVisible.js.map +1 -0
- package/esm/hooks/asyncReplace.d.ts +7 -0
- package/esm/hooks/asyncReplace.js +21 -0
- package/esm/hooks/asyncReplace.js.map +1 -0
- package/esm/hooks/index.d.ts +7 -0
- package/esm/hooks/index.js +8 -0
- package/esm/hooks/index.js.map +1 -0
- package/esm/hooks/lockBodyScroll.d.ts +6 -0
- package/esm/hooks/lockBodyScroll.js +15 -0
- package/esm/hooks/lockBodyScroll.js.map +1 -0
- package/esm/hooks/onClickOutside.d.ts +8 -0
- package/esm/hooks/onClickOutside.js +23 -0
- package/esm/hooks/onClickOutside.js.map +1 -0
- package/esm/hooks/onScreenVisible.d.ts +11 -0
- package/esm/hooks/onScreenVisible.js +24 -0
- package/esm/hooks/onScreenVisible.js.map +1 -0
- package/esm/hooks/piletApi.d.ts +7 -0
- package/esm/hooks/piletApi.js +12 -0
- package/esm/hooks/piletApi.js.map +1 -0
- package/esm/hooks/prompt.d.ts +9 -0
- package/esm/hooks/prompt.js +28 -0
- package/esm/hooks/prompt.js.map +1 -0
- package/esm/index.d.ts +3 -0
- package/esm/index.js +4 -0
- package/esm/index.js.map +1 -0
- package/lib/contexts/PiletApiProvider.d.ts +2 -0
- package/lib/contexts/PiletApiProvider.js +6 -0
- package/lib/contexts/PiletApiProvider.js.map +1 -0
- package/lib/contexts/index.d.ts +1 -0
- package/lib/contexts/index.js +14 -0
- package/lib/contexts/index.js.map +1 -0
- package/lib/hocs/index.d.ts +1 -0
- package/lib/hocs/index.js +14 -0
- package/lib/hocs/index.js.map +1 -0
- package/lib/hocs/withProvider.d.ts +15 -0
- package/lib/hocs/withProvider.js +17 -0
- package/lib/hocs/withProvider.js.map +1 -0
- package/lib/hooks/afterVisible.d.ts +8 -0
- package/lib/hooks/afterVisible.js +30 -0
- package/lib/hooks/afterVisible.js.map +1 -0
- package/lib/hooks/asyncReplace.d.ts +7 -0
- package/lib/hooks/asyncReplace.js +25 -0
- package/lib/hooks/asyncReplace.js.map +1 -0
- package/lib/hooks/index.d.ts +7 -0
- package/lib/hooks/index.js +20 -0
- package/lib/hooks/index.js.map +1 -0
- package/lib/hooks/lockBodyScroll.d.ts +6 -0
- package/lib/hooks/lockBodyScroll.js +19 -0
- package/lib/hooks/lockBodyScroll.js.map +1 -0
- package/lib/hooks/onClickOutside.d.ts +8 -0
- package/lib/hooks/onClickOutside.js +27 -0
- package/lib/hooks/onClickOutside.js.map +1 -0
- package/lib/hooks/onScreenVisible.d.ts +11 -0
- package/lib/hooks/onScreenVisible.js +28 -0
- package/lib/hooks/onScreenVisible.js.map +1 -0
- package/lib/hooks/piletApi.d.ts +7 -0
- package/lib/hooks/piletApi.js +16 -0
- package/lib/hooks/piletApi.js.map +1 -0
- package/lib/hooks/prompt.d.ts +9 -0
- package/lib/hooks/prompt.js +32 -0
- package/lib/hooks/prompt.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +16 -0
- package/lib/index.js.map +1 -0
- package/package.json +43 -0
- package/src/contexts/PiletApiProvider.ts +3 -0
- package/src/contexts/index.ts +1 -0
- package/src/hocs/index.ts +1 -0
- package/src/hocs/withProvider.tsx +23 -0
- package/src/hooks/afterVisible.ts +29 -0
- package/src/hooks/asyncReplace.ts +32 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/lockBodyScroll.test.ts +24 -0
- package/src/hooks/lockBodyScroll.ts +15 -0
- package/src/hooks/onClickOutside.test.ts +113 -0
- package/src/hooks/onClickOutside.ts +25 -0
- package/src/hooks/onScreenVisible.test.ts +68 -0
- package/src/hooks/onScreenVisible.ts +28 -0
- package/src/hooks/piletApi.ts +12 -0
- package/src/hooks/prompt.ts +35 -0
- package/src/index.ts +3 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useOnScreenVisible } from './onScreenVisible';
|
|
3
|
+
|
|
4
|
+
jest.mock('react');
|
|
5
|
+
|
|
6
|
+
(React as any).useState = (result) => [result, jest.fn()];
|
|
7
|
+
|
|
8
|
+
function mockIntersectionObserver() {
|
|
9
|
+
const instances = [];
|
|
10
|
+
(window as any).IntersectionObserver = class {
|
|
11
|
+
constructor(cb, margin) {
|
|
12
|
+
instances.push(this);
|
|
13
|
+
this.init(cb, margin);
|
|
14
|
+
}
|
|
15
|
+
init = jest.fn();
|
|
16
|
+
observe = jest.fn();
|
|
17
|
+
unobserve = jest.fn();
|
|
18
|
+
};
|
|
19
|
+
return instances;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe('OnScreenVisible Module', () => {
|
|
23
|
+
it('is not intersecting by default', () => {
|
|
24
|
+
const result = useOnScreenVisible({ current: undefined });
|
|
25
|
+
expect(result).toBeFalsy();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('creates one intersection observer with effect', () => {
|
|
29
|
+
const usedEffect = jest.fn();
|
|
30
|
+
(React as any).useEffect = usedEffect;
|
|
31
|
+
const instances = mockIntersectionObserver();
|
|
32
|
+
useOnScreenVisible({ current: undefined });
|
|
33
|
+
const cleanup = usedEffect.mock.calls[0][0]();
|
|
34
|
+
expect(instances.length).toBe(1);
|
|
35
|
+
cleanup();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('does not observe if no ref given', () => {
|
|
39
|
+
const usedEffect = jest.fn();
|
|
40
|
+
(React as any).useEffect = usedEffect;
|
|
41
|
+
const instances = mockIntersectionObserver();
|
|
42
|
+
useOnScreenVisible({ current: undefined });
|
|
43
|
+
const cleanup = usedEffect.mock.calls[0][0]();
|
|
44
|
+
expect(instances[0].observe).toHaveBeenCalledTimes(0);
|
|
45
|
+
cleanup();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('does observe if valid ref given', () => {
|
|
49
|
+
const usedEffect = jest.fn();
|
|
50
|
+
(React as any).useEffect = usedEffect;
|
|
51
|
+
const instances = mockIntersectionObserver();
|
|
52
|
+
useOnScreenVisible({ current: {} as any });
|
|
53
|
+
const cleanup = usedEffect.mock.calls[0][0]();
|
|
54
|
+
expect(instances[0].observe).toHaveBeenCalledTimes(1);
|
|
55
|
+
cleanup();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('calls setIntersecting if something changes', () => {
|
|
59
|
+
const usedEffect = jest.fn();
|
|
60
|
+
(React as any).useEffect = usedEffect;
|
|
61
|
+
const instances = mockIntersectionObserver();
|
|
62
|
+
useOnScreenVisible({ current: {} as any });
|
|
63
|
+
const cleanup = usedEffect.mock.calls[0][0]();
|
|
64
|
+
instances[0].init.mock.calls[0][0]([{ isIntersecting: true }]);
|
|
65
|
+
cleanup();
|
|
66
|
+
expect(instances[0].unobserve).toHaveBeenCalledTimes(1);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useState, useEffect, RefObject } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hook that detects if a reference element within the main document is
|
|
5
|
+
* visible.
|
|
6
|
+
* Useful for performing some animation or triggering certain actions (e.g.,
|
|
7
|
+
* loading data for infinity scrolling) when an element appears or is close
|
|
8
|
+
* to appear on screen.
|
|
9
|
+
* @param ref The reference element to be visible.
|
|
10
|
+
* @param rootMargin The tolerance level to the reference element.
|
|
11
|
+
*/
|
|
12
|
+
export function useOnScreenVisible<T extends HTMLElement>(ref: RefObject<T>, rootMargin = '0px') {
|
|
13
|
+
const [isIntersecting, setIntersecting] = useState(false);
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const observer = new IntersectionObserver(([entry]) => setIntersecting(entry.isIntersecting), {
|
|
17
|
+
rootMargin,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (ref.current) {
|
|
21
|
+
observer.observe(ref.current);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return () => observer.unobserve(ref.current);
|
|
25
|
+
}, []);
|
|
26
|
+
|
|
27
|
+
return isIntersecting;
|
|
28
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { PiletApiProvider } from '../contexts';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Retrieves the Pilet API stored in the provider.
|
|
6
|
+
* The component must be somewhat wrapped in the
|
|
7
|
+
* PiletApiProvider, e.g., via withPiletApi wrapper.
|
|
8
|
+
* @returns The Pilet API for this component.
|
|
9
|
+
*/
|
|
10
|
+
export function usePiletApi<TPiletApi = any>(): TPiletApi {
|
|
11
|
+
return useContext(PiletApiProvider);
|
|
12
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import type { History, Location } from 'history';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook to notify the user in case of potential data loss when
|
|
6
|
+
* performing a page transition (internal or external).
|
|
7
|
+
* @param active True if the prompt should be shown, otherwise false.
|
|
8
|
+
* @param history The history of the currently used router.
|
|
9
|
+
* @param message The message to display when the prompt is shown.
|
|
10
|
+
*/
|
|
11
|
+
export function usePrompt(
|
|
12
|
+
active: boolean,
|
|
13
|
+
history: History,
|
|
14
|
+
message: string,
|
|
15
|
+
onTransition?: (location: Location) => void
|
|
16
|
+
) {
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (active) {
|
|
19
|
+
const beforeUnload = (ev: BeforeUnloadEvent) => {
|
|
20
|
+
ev.returnValue = message;
|
|
21
|
+
return message;
|
|
22
|
+
};
|
|
23
|
+
const unlisten = onTransition && history.listen(onTransition);
|
|
24
|
+
const unblock = message && history.block(message);
|
|
25
|
+
window.addEventListener('beforeunload', beforeUnload);
|
|
26
|
+
return () => {
|
|
27
|
+
unlisten && unlisten();
|
|
28
|
+
unblock && unblock();
|
|
29
|
+
window.removeEventListener('beforeunload', beforeUnload);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return () => {};
|
|
34
|
+
}, [active, message]);
|
|
35
|
+
}
|
package/src/index.ts
ADDED