-
Notifications
You must be signed in to change notification settings - Fork 0
/
waitForSelector.ts
55 lines (49 loc) · 1.64 KB
/
waitForSelector.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* Options for {@link waitForSelector}
*/
interface WaitForOptions {
/** Maximum time to wait in milliseconds, default is 30000 (30s) */
timeoutMillisecond?: number
/**
* Instructs the user agent to observe a given target (a node)
* @default document.body
*/
target?: Node
}
/**
* waits for an element to appear in the DOM
* @param {string} selector - The CSS selector to wait for.
* @param {WaitForOptions} [options]
* @returns A promise that resolves to an element that matches the selector.
* @linkcode https://github.com/GreatAuk/utopia-utils/blob/main/packages/dom/src/waitForSelector.ts
*/
export function waitForSelector<T extends Element>(selector: string, options?: WaitForOptions): Promise<T | null> {
return new Promise((resolve) => {
if (typeof window.MutationObserver === 'undefined')
throw new Error('MutationObserver is not supported in this browser')
const { timeoutMillisecond = 30000, target = document.body } = options || {}
const timeoutId = setTimeout(onTimeoutDone, timeoutMillisecond)
const observer = new MutationObserver((mutations) => {
if (mutations.some(mutation => Array.from(mutation.addedNodes).some(node => node instanceof Element && node.matches(selector)))) {
clearTimeout(timeoutId)
checkDom()
}
})
observer.observe(target, {
childList: true,
subtree: true,
})
checkDom()
function checkDom() {
const dom = document.querySelector(selector)
if (dom) {
observer.disconnect()
resolve(dom as T)
}
}
function onTimeoutDone() {
observer.disconnect()
resolve(null)
}
})
}