@wordpress/interactivity
Version:
Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.
52 lines (48 loc) • 1.93 kB
JavaScript
/**
* External dependencies
*/
import { hydrate } from 'preact';
/**
* Internal dependencies
*/
import { toVdom, hydratedIslands } from './vdom';
import { createRootFragment, splitTask } 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 (!region.parentElement) {
throw Error('The passed region should be an element with a parent.');
}
if (!regionRootFragments.has(region)) {
regionRootFragments.set(region, createRootFragment(region.parentElement, region));
}
return regionRootFragments.get(region);
};
// Initial vDOM regions associated with its DOM element.
export const initialVdom = new WeakMap();
// Initialize the router with the initial DOM.
export const init = async () => {
const nodes = document.querySelectorAll(`[data-${directivePrefix}-interactive]`);
/*
* This `await` with setTimeout is required to apparently ensure that the interactive blocks have their stores
* fully initialized prior to hydrating the blocks. If this is not present, then an error occurs, for example:
* > view.js:46 Uncaught (in promise) ReferenceError: Cannot access 'state' before initialization
* This occurs when splitTask() is implemented with scheduler.yield() as opposed to setTimeout(), as with the former
* split tasks are added to the front of the task queue whereas with the latter they are added to the end of the queue.
*/
await new Promise(resolve => {
setTimeout(resolve, 0);
});
for (const node of nodes) {
if (!hydratedIslands.has(node)) {
await splitTask();
const fragment = getRegionRootFragment(node);
const vdom = toVdom(node);
initialVdom.set(node, vdom);
await splitTask();
hydrate(vdom, fragment);
}
}
};
//# sourceMappingURL=init.js.map