UNPKG

3.04 kBJavaScriptView Raw
1import * as React from 'react';
2
3/**
4 * Hook to manage the event system used by the navigator to notify screens of various events.
5 */
6export default function useEventEmitter(listen) {
7 const listenRef = React.useRef(listen);
8 React.useEffect(() => {
9 listenRef.current = listen;
10 });
11 const listeners = React.useRef(Object.create(null));
12 const create = React.useCallback(target => {
13 const removeListener = (type, callback) => {
14 const callbacks = listeners.current[type] ? listeners.current[type][target] : undefined;
15
16 if (!callbacks) {
17 return;
18 }
19
20 const index = callbacks.indexOf(callback);
21
22 if (index > -1) {
23 callbacks.splice(index, 1);
24 }
25 };
26
27 const addListener = (type, callback) => {
28 listeners.current[type] = listeners.current[type] || {};
29 listeners.current[type][target] = listeners.current[type][target] || [];
30 listeners.current[type][target].push(callback);
31 let removed = false;
32 return () => {
33 // Prevent removing other listeners when unsubscribing same listener multiple times
34 if (!removed) {
35 removed = true;
36 removeListener(type, callback);
37 }
38 };
39 };
40
41 return {
42 addListener,
43 removeListener
44 };
45 }, []);
46 const emit = React.useCallback(_ref => {
47 var _items$target, _listenRef$current;
48
49 let {
50 type,
51 data,
52 target,
53 canPreventDefault
54 } = _ref;
55 const items = listeners.current[type] || {}; // Copy the current list of callbacks in case they are mutated during execution
56
57 const callbacks = target !== undefined ? (_items$target = items[target]) === null || _items$target === void 0 ? void 0 : _items$target.slice() : [].concat(...Object.keys(items).map(t => items[t])).filter((cb, i, self) => self.lastIndexOf(cb) === i);
58 const event = {
59 get type() {
60 return type;
61 }
62
63 };
64
65 if (target !== undefined) {
66 Object.defineProperty(event, 'target', {
67 enumerable: true,
68
69 get() {
70 return target;
71 }
72
73 });
74 }
75
76 if (data !== undefined) {
77 Object.defineProperty(event, 'data', {
78 enumerable: true,
79
80 get() {
81 return data;
82 }
83
84 });
85 }
86
87 if (canPreventDefault) {
88 let defaultPrevented = false;
89 Object.defineProperties(event, {
90 defaultPrevented: {
91 enumerable: true,
92
93 get() {
94 return defaultPrevented;
95 }
96
97 },
98 preventDefault: {
99 enumerable: true,
100
101 value() {
102 defaultPrevented = true;
103 }
104
105 }
106 });
107 }
108
109 (_listenRef$current = listenRef.current) === null || _listenRef$current === void 0 ? void 0 : _listenRef$current.call(listenRef, event);
110 callbacks === null || callbacks === void 0 ? void 0 : callbacks.forEach(cb => cb(event));
111 return event;
112 }, []);
113 return React.useMemo(() => ({
114 create,
115 emit
116 }), [create, emit]);
117}
118//# sourceMappingURL=useEventEmitter.js.map
\No newline at end of file