UNPKG

@atlaskit/editor-common

Version:

A package that contains common classes and components for editor and renderer

72 lines (69 loc) 2.78 kB
// Use this selector to set the intersection observer boundary for editor's inline node views // If this does not exist, it will use the IntersectionObserver's default root const INTERSECTION_OBSERVER_ROOT_SELECTOR = '[data-editor-scroll-container="true"]'; const editorObservers = new WeakMap(); const callbackMap = new WeakMap(); /** * Creates a node visibility manager * @param editorElement * @returns */ export const nodeVisibilityManager = editorElement => { // Warning! do not reference editorElement outside of internal functions. // editorElement is passed to allow support for multiple editors, const unObserveInternal = nodeElement => { var _editorObservers$get; (_editorObservers$get = editorObservers.get(editorElement)) === null || _editorObservers$get === void 0 ? void 0 : _editorObservers$get.unobserve(nodeElement); callbackMap.delete(nodeElement); }; const observe = observerConfig => { var _editorObservers$get2; callbackMap.set(observerConfig.element, observerConfig); (_editorObservers$get2 = editorObservers.get(editorElement)) === null || _editorObservers$get2 === void 0 ? void 0 : _editorObservers$get2.observe(observerConfig.element); // return clean up return () => { // consumer needs to unobserve on destroy if their element // was observed but never scrolled into view unObserveInternal(observerConfig.element); }; }; const initialiseNodeObserver = () => { if (editorObservers.has(editorElement)) { return; } const intersectionObserverOptions = { root: editorElement.closest(INTERSECTION_OBSERVER_ROOT_SELECTOR), rootMargin: '0px 0px 100px 0px', threshold: 0 }; const editorObserver = new IntersectionObserver(entries => entries.map(entry => ({ entry, callback: callbackMap.get(entry.target) })) // Invoke callbacks together to group browser rendering // Avoiding requestAnimationFrame to reduce visual flickering .forEach(({ entry, callback }) => { if (entry.isIntersecting) { callback === null || callback === void 0 ? void 0 : callback.onFirstVisible(); if (entry.target instanceof HTMLElement) { // immediately unobserve the element after it is visible unObserveInternal(entry.target); } } }), intersectionObserverOptions); editorObservers.set(editorElement, editorObserver); }; const disconnect = () => { var _editorObservers$get3; (_editorObservers$get3 = editorObservers.get(editorElement)) === null || _editorObservers$get3 === void 0 ? void 0 : _editorObservers$get3.disconnect(); editorObservers.delete(editorElement); }; return { initialiseNodeObserver, observe, disconnect }; };