-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
init.js
76 lines (68 loc) · 1.97 KB
/
init.js
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/**
* External dependencies
*/
import { hydrate } from 'preact';
/**
* Internal dependencies
*/
import { toVdom, hydratedIslands } from './vdom';
import { createRootFragment } from './utils';
import { directivePrefix } from './constants';
// Keep the same root fragment for each interactive region node.
const regionRootFragments = new WeakMap();
export const getRegionRootFragment = ( region ) => {
if ( ! regionRootFragments.has( region ) ) {
regionRootFragments.set(
region,
createRootFragment( region.parentElement, region )
);
}
return regionRootFragments.get( region );
};
function yieldToMain() {
return new Promise( ( resolve ) => {
// TODO: Use scheduler.yield() when available.
setTimeout( resolve, 0 );
} );
}
// Initialize the router with the initial DOM.
export const init = async () => {
const pendingNodes = new Set();
const intersectionObserver = new window.IntersectionObserver(
async ( entries ) => {
for ( const entry of entries ) {
if ( ! entry.isIntersecting ) {
continue;
}
const node = entry.target;
intersectionObserver.unobserve( node );
pendingNodes.delete( node );
if ( pendingNodes.size === 0 ) {
intersectionObserver.disconnect();
}
if ( ! hydratedIslands.has( node ) ) {
while ( window.navigator.scheduling?.isInputPending() ) {
await yieldToMain();
}
const fragment = getRegionRootFragment( node );
const vdom = toVdom( node );
await yieldToMain();
hydrate( vdom, fragment );
await yieldToMain();
}
}
},
{
root: null, // To watch for intersection relative to the device's viewport.
rootMargin: '100% 0% 100% 0%', // Intersect when within 1 viewport approaching from top or bottom.
threshold: 0.0, // As soon as even one pixel is visible.
}
);
const nodes = document.querySelectorAll(
`[data-${ directivePrefix }-interactive]`
);
for ( const node of nodes ) {
pendingNodes.add( node );
intersectionObserver.observe( node );
}
};