@aegisjsproject/callback-registry 1.0.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/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/README.md +55 -0
- package/callbackRegistry.cjs +528 -0
- package/callbackRegistry.js +2 -0
- package/callbackRegistry.mjs +509 -0
- package/callbacks.cjs +254 -0
- package/callbacks.js +239 -0
- package/events.js +269 -0
- package/package.json +83 -0
package/callbacks.cjs
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
let _isRegistrationOpen = true;
|
|
4
|
+
|
|
5
|
+
const $$ = (selector, base = document) => base.querySelectorAll(selector);
|
|
6
|
+
|
|
7
|
+
const $ = (selector, base = document) => base.querySelector(selector);
|
|
8
|
+
|
|
9
|
+
const FUNCS = {
|
|
10
|
+
debug: {
|
|
11
|
+
log: 'aegis:debug:log',
|
|
12
|
+
info: 'aegis:debug:info',
|
|
13
|
+
warn: 'aegis:debug:warn',
|
|
14
|
+
error: 'aegis:debug:error',
|
|
15
|
+
},
|
|
16
|
+
navigate: {
|
|
17
|
+
back: 'aegis:navigate:back',
|
|
18
|
+
forward: 'aegis:navigate:forward',
|
|
19
|
+
reload: 'aegis:navigate:reload',
|
|
20
|
+
link: 'aegis:navigate:go',
|
|
21
|
+
popup: 'aegis:navigate:popup',
|
|
22
|
+
},
|
|
23
|
+
ui: {
|
|
24
|
+
print: 'aegis:ui:print',
|
|
25
|
+
remove: 'aegis:ui:remove',
|
|
26
|
+
hide: 'aegis:ui:hide',
|
|
27
|
+
unhide: 'aegis:ui:unhide',
|
|
28
|
+
showModal: 'aegis:ui:showModal',
|
|
29
|
+
closeModal: 'aegis:ui:closeModal',
|
|
30
|
+
showPopover: 'aegis:ui:showPopover',
|
|
31
|
+
hidePopover: 'aegis:ui:hidePopover',
|
|
32
|
+
togglePopover: 'aegis:ui:togglePopover',
|
|
33
|
+
enable: 'aegis:ui:enable',
|
|
34
|
+
disable: 'aegis:ui:disable',
|
|
35
|
+
scrollTo: 'aegis:ui:scrollTo',
|
|
36
|
+
prevent: 'aegis:ui:prevent',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const registry = new Map([
|
|
41
|
+
[FUNCS.debug.log, console.log],
|
|
42
|
+
[FUNCS.debug.warn, console.warn],
|
|
43
|
+
[FUNCS.debug.error, console.error],
|
|
44
|
+
[FUNCS.debug.info, console.info],
|
|
45
|
+
[FUNCS.navigate.back, history.back],
|
|
46
|
+
[FUNCS.navigate.forward, history.forward],
|
|
47
|
+
[FUNCS.navigate.reload, () => history.go(0)],
|
|
48
|
+
[FUNCS.navigate.link, event => {
|
|
49
|
+
if (event.isTrusted) {
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
location.href = event.currentTarget.dataset.url;
|
|
52
|
+
}
|
|
53
|
+
}],
|
|
54
|
+
[FUNCS.navigate.popup, event => {
|
|
55
|
+
if (event.isTrusted) {
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
globalThis.open(event.currentTarget.dataset.url);
|
|
58
|
+
}
|
|
59
|
+
}],
|
|
60
|
+
[FUNCS.ui.hide, ({ currentTarget }) => {
|
|
61
|
+
$$(currentTarget.dataset.hideSelector).forEach(el => el.hidden = true);
|
|
62
|
+
}],
|
|
63
|
+
[FUNCS.ui.unhide, ({ currentTarget }) => {
|
|
64
|
+
$$(currentTarget.dataset.unhideSelector).forEach(el => el.hidden = false);
|
|
65
|
+
}],
|
|
66
|
+
[FUNCS.ui.disable, ({ currentTarget }) => {
|
|
67
|
+
$$(currentTarget.dataset.disableSelector).forEach(el => el.disabled = true);
|
|
68
|
+
}],
|
|
69
|
+
[FUNCS.ui.enable, ({ currentTarget }) => {
|
|
70
|
+
$$(currentTarget.dataset.enableSelector).forEach(el => el.disabled = false);
|
|
71
|
+
}],
|
|
72
|
+
[FUNCS.ui.remove, ({ currentTarget }) => {
|
|
73
|
+
$$(currentTarget.dataset.removeSelector).forEach(el => el.remove());
|
|
74
|
+
}],
|
|
75
|
+
[FUNCS.ui.scrollTo, ({ currentTarget }) => {
|
|
76
|
+
const target = $(currentTarget.dataset.scrollToSelector);
|
|
77
|
+
|
|
78
|
+
if (target instanceof Element) {
|
|
79
|
+
target.scrollIntoView({
|
|
80
|
+
behavior: matchMedia('(prefers-reduced-motion: reduce)').matches
|
|
81
|
+
? 'instant'
|
|
82
|
+
: 'smooth',
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}],
|
|
86
|
+
[FUNCS.ui.showModal, ({ currentTarget }) => {
|
|
87
|
+
const target = $(currentTarget.dataset.showModalSelector);
|
|
88
|
+
|
|
89
|
+
if (target instanceof HTMLDialogElement) {
|
|
90
|
+
target.showModal();
|
|
91
|
+
}
|
|
92
|
+
}],
|
|
93
|
+
[FUNCS.ui.closeModal, ({ currentTarget }) => {
|
|
94
|
+
const target = $(currentTarget.dataset.closeModalSelector);
|
|
95
|
+
|
|
96
|
+
if (target instanceof HTMLDialogElement) {
|
|
97
|
+
target.close();
|
|
98
|
+
}
|
|
99
|
+
}],
|
|
100
|
+
[FUNCS.ui.showPopover, ({ currentTarget }) => {
|
|
101
|
+
const target = $(currentTarget.dataset.showPopoverSelector);
|
|
102
|
+
|
|
103
|
+
if (target instanceof HTMLElement) {
|
|
104
|
+
target.showPopover();
|
|
105
|
+
}
|
|
106
|
+
}],
|
|
107
|
+
[FUNCS.ui.hidePopover, ({ currentTarget }) => {
|
|
108
|
+
const target = $(currentTarget.dataset.hidePopoverSelector);
|
|
109
|
+
|
|
110
|
+
if (target instanceof HTMLElement) {
|
|
111
|
+
target.hidePopover();
|
|
112
|
+
}
|
|
113
|
+
}],
|
|
114
|
+
[FUNCS.ui.togglePopover, ({ currentTarget }) => {
|
|
115
|
+
const target = $(currentTarget.dataset.togglePopoverSelector);
|
|
116
|
+
|
|
117
|
+
if (target instanceof HTMLElement) {
|
|
118
|
+
target.togglePopover();
|
|
119
|
+
}
|
|
120
|
+
}],
|
|
121
|
+
[FUNCS.ui.print, () => globalThis.print()],
|
|
122
|
+
[FUNCS.ui.prevent, event => event.preventDefault()],
|
|
123
|
+
]);
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Check if callback registry is open
|
|
127
|
+
*
|
|
128
|
+
* @returns {boolean} Whether or not callback registry is open
|
|
129
|
+
*/
|
|
130
|
+
const isRegistrationOpen = () => _isRegistrationOpen;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Close callback registry
|
|
134
|
+
*
|
|
135
|
+
* @returns {boolean} Whether or not the callback was succesfully removed
|
|
136
|
+
*/
|
|
137
|
+
const closeRegistration = () => _isRegistrationOpen = false;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Get an array of registered callbacks
|
|
141
|
+
*
|
|
142
|
+
* @returns {Array} A frozen array listing keys to all registered callbacks
|
|
143
|
+
*/
|
|
144
|
+
const listCallbacks = () => Object.freeze(Array.from(registry.keys()));
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Check if a callback is registered
|
|
148
|
+
*
|
|
149
|
+
* @param {string} name The name/key to check for in callback registry
|
|
150
|
+
* @returns {boolean} Whether or not a callback is registered
|
|
151
|
+
*/
|
|
152
|
+
const hasCallback = name => registry.has(name);
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Get a callback from the registry by name/key
|
|
156
|
+
*
|
|
157
|
+
* @param {string} name The name/key of the callback to get
|
|
158
|
+
* @returns {Function|undefined} The corresponding function registered under that name/key
|
|
159
|
+
*/
|
|
160
|
+
const getCallback = name => registry.get(name);
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Remove a callback from the registry
|
|
164
|
+
*
|
|
165
|
+
* @param {string} name The name/key of the callback to get
|
|
166
|
+
* @returns {boolean} Whether or not the callback was successfully unregisterd
|
|
167
|
+
*/
|
|
168
|
+
const unregisterCallback = name => _isRegistrationOpen && registry.delete(name);
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Remove all callbacks from the registry
|
|
172
|
+
*
|
|
173
|
+
* @returns {undefined}
|
|
174
|
+
*/
|
|
175
|
+
const clearRegistry = () => registry.clear();
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Create a registered callback with a randomly generated name
|
|
179
|
+
*
|
|
180
|
+
* @param {Function} callback Callback function to register
|
|
181
|
+
* @returns {string} The automatically generated key/name of the registered callback
|
|
182
|
+
*/
|
|
183
|
+
const createCallback = (callback) => registerCallback('aegis:callback:' + crypto.randomUUID(), callback);
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Call a callback fromt the registry by name/key
|
|
187
|
+
*
|
|
188
|
+
* @param {string} name The name/key of the registered function
|
|
189
|
+
* @param {...any} args Any arguments to pass along to the function
|
|
190
|
+
* @returns {any} Whatever the return value of the function is
|
|
191
|
+
* @throws {Error} Throws if callback is not found or any error resulting from calling the function
|
|
192
|
+
*/
|
|
193
|
+
function callCallback(name, ...args) {
|
|
194
|
+
if (registry.has(name)) {
|
|
195
|
+
return registry.get(name).apply(this || globalThis, args);
|
|
196
|
+
} else {
|
|
197
|
+
throw new Error(`No ${name} function registered.`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Register a named callback in registry
|
|
203
|
+
*
|
|
204
|
+
* @param {string} name The name/key to register the callback under
|
|
205
|
+
* @param {Function} callback The callback value to register
|
|
206
|
+
* @returns {string} The registered name/key
|
|
207
|
+
*/
|
|
208
|
+
function registerCallback(name, callback) {
|
|
209
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
210
|
+
throw new TypeError('Callback name must be a string.');
|
|
211
|
+
} if (! (callback instanceof Function)) {
|
|
212
|
+
throw new TypeError('Callback must be a function.');
|
|
213
|
+
} else if (! _isRegistrationOpen) {
|
|
214
|
+
throw new TypeError('Cannot register new callbacks because registry is closed.');
|
|
215
|
+
} else if (registry.has(name)) {
|
|
216
|
+
throw new Error(`Handler "${name}" is already registered.`);
|
|
217
|
+
} else {
|
|
218
|
+
registry.set(name, callback);
|
|
219
|
+
return name;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Get the host/root node of a given thing.
|
|
225
|
+
*
|
|
226
|
+
* @param {Event|Document|Element|ShadowRoot} target Source thing to search for host of
|
|
227
|
+
* @returns {Document|Element|null} The host/root node, or null
|
|
228
|
+
*/
|
|
229
|
+
function getHost(target) {
|
|
230
|
+
if (target instanceof Event) {
|
|
231
|
+
return getHost(target.currentTarget);
|
|
232
|
+
} else if (target instanceof Document) {
|
|
233
|
+
return target;
|
|
234
|
+
} else if (target instanceof Element) {
|
|
235
|
+
return getHost(target.getRootNode());
|
|
236
|
+
} else if (target instanceof ShadowRoot) {
|
|
237
|
+
return target.host;
|
|
238
|
+
} else {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
exports.FUNCS = FUNCS;
|
|
244
|
+
exports.callCallback = callCallback;
|
|
245
|
+
exports.clearRegistry = clearRegistry;
|
|
246
|
+
exports.closeRegistration = closeRegistration;
|
|
247
|
+
exports.createCallback = createCallback;
|
|
248
|
+
exports.getCallback = getCallback;
|
|
249
|
+
exports.getHost = getHost;
|
|
250
|
+
exports.hasCallback = hasCallback;
|
|
251
|
+
exports.isRegistrationOpen = isRegistrationOpen;
|
|
252
|
+
exports.listCallbacks = listCallbacks;
|
|
253
|
+
exports.registerCallback = registerCallback;
|
|
254
|
+
exports.unregisterCallback = unregisterCallback;
|
package/callbacks.js
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
let _isRegistrationOpen = true;
|
|
2
|
+
|
|
3
|
+
const $$ = (selector, base = document) => base.querySelectorAll(selector);
|
|
4
|
+
|
|
5
|
+
const $ = (selector, base = document) => base.querySelector(selector);
|
|
6
|
+
|
|
7
|
+
export const FUNCS = {
|
|
8
|
+
debug: {
|
|
9
|
+
log: 'aegis:debug:log',
|
|
10
|
+
info: 'aegis:debug:info',
|
|
11
|
+
warn: 'aegis:debug:warn',
|
|
12
|
+
error: 'aegis:debug:error',
|
|
13
|
+
},
|
|
14
|
+
navigate: {
|
|
15
|
+
back: 'aegis:navigate:back',
|
|
16
|
+
forward: 'aegis:navigate:forward',
|
|
17
|
+
reload: 'aegis:navigate:reload',
|
|
18
|
+
link: 'aegis:navigate:go',
|
|
19
|
+
popup: 'aegis:navigate:popup',
|
|
20
|
+
},
|
|
21
|
+
ui: {
|
|
22
|
+
print: 'aegis:ui:print',
|
|
23
|
+
remove: 'aegis:ui:remove',
|
|
24
|
+
hide: 'aegis:ui:hide',
|
|
25
|
+
unhide: 'aegis:ui:unhide',
|
|
26
|
+
showModal: 'aegis:ui:showModal',
|
|
27
|
+
closeModal: 'aegis:ui:closeModal',
|
|
28
|
+
showPopover: 'aegis:ui:showPopover',
|
|
29
|
+
hidePopover: 'aegis:ui:hidePopover',
|
|
30
|
+
togglePopover: 'aegis:ui:togglePopover',
|
|
31
|
+
enable: 'aegis:ui:enable',
|
|
32
|
+
disable: 'aegis:ui:disable',
|
|
33
|
+
scrollTo: 'aegis:ui:scrollTo',
|
|
34
|
+
prevent: 'aegis:ui:prevent',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const registry = new Map([
|
|
39
|
+
[FUNCS.debug.log, console.log],
|
|
40
|
+
[FUNCS.debug.warn, console.warn],
|
|
41
|
+
[FUNCS.debug.error, console.error],
|
|
42
|
+
[FUNCS.debug.info, console.info],
|
|
43
|
+
[FUNCS.navigate.back, history.back],
|
|
44
|
+
[FUNCS.navigate.forward, history.forward],
|
|
45
|
+
[FUNCS.navigate.reload, () => history.go(0)],
|
|
46
|
+
[FUNCS.navigate.link, event => {
|
|
47
|
+
if (event.isTrusted) {
|
|
48
|
+
event.preventDefault();
|
|
49
|
+
location.href = event.currentTarget.dataset.url;
|
|
50
|
+
}
|
|
51
|
+
}],
|
|
52
|
+
[FUNCS.navigate.popup, event => {
|
|
53
|
+
if (event.isTrusted) {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
globalThis.open(event.currentTarget.dataset.url);
|
|
56
|
+
}
|
|
57
|
+
}],
|
|
58
|
+
[FUNCS.ui.hide, ({ currentTarget }) => {
|
|
59
|
+
$$(currentTarget.dataset.hideSelector).forEach(el => el.hidden = true);
|
|
60
|
+
}],
|
|
61
|
+
[FUNCS.ui.unhide, ({ currentTarget }) => {
|
|
62
|
+
$$(currentTarget.dataset.unhideSelector).forEach(el => el.hidden = false);
|
|
63
|
+
}],
|
|
64
|
+
[FUNCS.ui.disable, ({ currentTarget }) => {
|
|
65
|
+
$$(currentTarget.dataset.disableSelector).forEach(el => el.disabled = true);
|
|
66
|
+
}],
|
|
67
|
+
[FUNCS.ui.enable, ({ currentTarget }) => {
|
|
68
|
+
$$(currentTarget.dataset.enableSelector).forEach(el => el.disabled = false);
|
|
69
|
+
}],
|
|
70
|
+
[FUNCS.ui.remove, ({ currentTarget }) => {
|
|
71
|
+
$$(currentTarget.dataset.removeSelector).forEach(el => el.remove());
|
|
72
|
+
}],
|
|
73
|
+
[FUNCS.ui.scrollTo, ({ currentTarget }) => {
|
|
74
|
+
const target = $(currentTarget.dataset.scrollToSelector);
|
|
75
|
+
|
|
76
|
+
if (target instanceof Element) {
|
|
77
|
+
target.scrollIntoView({
|
|
78
|
+
behavior: matchMedia('(prefers-reduced-motion: reduce)').matches
|
|
79
|
+
? 'instant'
|
|
80
|
+
: 'smooth',
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}],
|
|
84
|
+
[FUNCS.ui.showModal, ({ currentTarget }) => {
|
|
85
|
+
const target = $(currentTarget.dataset.showModalSelector);
|
|
86
|
+
|
|
87
|
+
if (target instanceof HTMLDialogElement) {
|
|
88
|
+
target.showModal();
|
|
89
|
+
}
|
|
90
|
+
}],
|
|
91
|
+
[FUNCS.ui.closeModal, ({ currentTarget }) => {
|
|
92
|
+
const target = $(currentTarget.dataset.closeModalSelector);
|
|
93
|
+
|
|
94
|
+
if (target instanceof HTMLDialogElement) {
|
|
95
|
+
target.close();
|
|
96
|
+
}
|
|
97
|
+
}],
|
|
98
|
+
[FUNCS.ui.showPopover, ({ currentTarget }) => {
|
|
99
|
+
const target = $(currentTarget.dataset.showPopoverSelector);
|
|
100
|
+
|
|
101
|
+
if (target instanceof HTMLElement) {
|
|
102
|
+
target.showPopover();
|
|
103
|
+
}
|
|
104
|
+
}],
|
|
105
|
+
[FUNCS.ui.hidePopover, ({ currentTarget }) => {
|
|
106
|
+
const target = $(currentTarget.dataset.hidePopoverSelector);
|
|
107
|
+
|
|
108
|
+
if (target instanceof HTMLElement) {
|
|
109
|
+
target.hidePopover();
|
|
110
|
+
}
|
|
111
|
+
}],
|
|
112
|
+
[FUNCS.ui.togglePopover, ({ currentTarget }) => {
|
|
113
|
+
const target = $(currentTarget.dataset.togglePopoverSelector);
|
|
114
|
+
|
|
115
|
+
if (target instanceof HTMLElement) {
|
|
116
|
+
target.togglePopover();
|
|
117
|
+
}
|
|
118
|
+
}],
|
|
119
|
+
[FUNCS.ui.print, () => globalThis.print()],
|
|
120
|
+
[FUNCS.ui.prevent, event => event.preventDefault()],
|
|
121
|
+
]);
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Check if callback registry is open
|
|
125
|
+
*
|
|
126
|
+
* @returns {boolean} Whether or not callback registry is open
|
|
127
|
+
*/
|
|
128
|
+
export const isRegistrationOpen = () => _isRegistrationOpen;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Close callback registry
|
|
132
|
+
*
|
|
133
|
+
* @returns {boolean} Whether or not the callback was succesfully removed
|
|
134
|
+
*/
|
|
135
|
+
export const closeRegistration = () => _isRegistrationOpen = false;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Get an array of registered callbacks
|
|
139
|
+
*
|
|
140
|
+
* @returns {Array} A frozen array listing keys to all registered callbacks
|
|
141
|
+
*/
|
|
142
|
+
export const listCallbacks = () => Object.freeze(Array.from(registry.keys()));
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Check if a callback is registered
|
|
146
|
+
*
|
|
147
|
+
* @param {string} name The name/key to check for in callback registry
|
|
148
|
+
* @returns {boolean} Whether or not a callback is registered
|
|
149
|
+
*/
|
|
150
|
+
export const hasCallback = name => registry.has(name);
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Get a callback from the registry by name/key
|
|
154
|
+
*
|
|
155
|
+
* @param {string} name The name/key of the callback to get
|
|
156
|
+
* @returns {Function|undefined} The corresponding function registered under that name/key
|
|
157
|
+
*/
|
|
158
|
+
export const getCallback = name => registry.get(name);
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Remove a callback from the registry
|
|
162
|
+
*
|
|
163
|
+
* @param {string} name The name/key of the callback to get
|
|
164
|
+
* @returns {boolean} Whether or not the callback was successfully unregisterd
|
|
165
|
+
*/
|
|
166
|
+
export const unregisterCallback = name => _isRegistrationOpen && registry.delete(name);
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Remove all callbacks from the registry
|
|
170
|
+
*
|
|
171
|
+
* @returns {undefined}
|
|
172
|
+
*/
|
|
173
|
+
export const clearRegistry = () => registry.clear();
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Create a registered callback with a randomly generated name
|
|
177
|
+
*
|
|
178
|
+
* @param {Function} callback Callback function to register
|
|
179
|
+
* @returns {string} The automatically generated key/name of the registered callback
|
|
180
|
+
*/
|
|
181
|
+
export const createCallback = (callback) => registerCallback('aegis:callback:' + crypto.randomUUID(), callback);
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Call a callback fromt the registry by name/key
|
|
185
|
+
*
|
|
186
|
+
* @param {string} name The name/key of the registered function
|
|
187
|
+
* @param {...any} args Any arguments to pass along to the function
|
|
188
|
+
* @returns {any} Whatever the return value of the function is
|
|
189
|
+
* @throws {Error} Throws if callback is not found or any error resulting from calling the function
|
|
190
|
+
*/
|
|
191
|
+
export function callCallback(name, ...args) {
|
|
192
|
+
if (registry.has(name)) {
|
|
193
|
+
return registry.get(name).apply(this || globalThis, args);
|
|
194
|
+
} else {
|
|
195
|
+
throw new Error(`No ${name} function registered.`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Register a named callback in registry
|
|
201
|
+
*
|
|
202
|
+
* @param {string} name The name/key to register the callback under
|
|
203
|
+
* @param {Function} callback The callback value to register
|
|
204
|
+
* @returns {string} The registered name/key
|
|
205
|
+
*/
|
|
206
|
+
export function registerCallback(name, callback) {
|
|
207
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
208
|
+
throw new TypeError('Callback name must be a string.');
|
|
209
|
+
} if (! (callback instanceof Function)) {
|
|
210
|
+
throw new TypeError('Callback must be a function.');
|
|
211
|
+
} else if (! _isRegistrationOpen) {
|
|
212
|
+
throw new TypeError('Cannot register new callbacks because registry is closed.');
|
|
213
|
+
} else if (registry.has(name)) {
|
|
214
|
+
throw new Error(`Handler "${name}" is already registered.`);
|
|
215
|
+
} else {
|
|
216
|
+
registry.set(name, callback);
|
|
217
|
+
return name;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get the host/root node of a given thing.
|
|
223
|
+
*
|
|
224
|
+
* @param {Event|Document|Element|ShadowRoot} target Source thing to search for host of
|
|
225
|
+
* @returns {Document|Element|null} The host/root node, or null
|
|
226
|
+
*/
|
|
227
|
+
export function getHost(target) {
|
|
228
|
+
if (target instanceof Event) {
|
|
229
|
+
return getHost(target.currentTarget);
|
|
230
|
+
} else if (target instanceof Document) {
|
|
231
|
+
return target;
|
|
232
|
+
} else if (target instanceof Element) {
|
|
233
|
+
return getHost(target.getRootNode());
|
|
234
|
+
} else if (target instanceof ShadowRoot) {
|
|
235
|
+
return target.host;
|
|
236
|
+
} else {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
}
|