mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-19 01:46:19 +08:00
Expand lazy creation of editor and JS Views to the proximity of the viewport (#2445)
This commit is contained in:
parent
22cd0c233a
commit
e038ff790b
3 changed files with 47 additions and 16 deletions
|
@ -65,7 +65,10 @@ const CellEditor = {
|
|||
})
|
||||
);
|
||||
|
||||
this.visibility = waitUntilInViewport(this.el);
|
||||
this.visibility = waitUntilInViewport(this.el, {
|
||||
root: document.querySelector("[data-el-notebook]"),
|
||||
proximity: 2000,
|
||||
});
|
||||
|
||||
// We mount the editor lazily once it enters the viewport
|
||||
this.visibility.promise.then(() => {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { parseHookProps } from "../lib/attribute";
|
||||
import {
|
||||
isElementHidden,
|
||||
isElementVisibleInViewport,
|
||||
randomId,
|
||||
randomToken,
|
||||
waitUntilInViewport,
|
||||
|
@ -258,7 +257,10 @@ const JSView = {
|
|||
// We detect when the placeholder enters viewport and becomes visible,
|
||||
// based on that we can load the iframe contents lazily
|
||||
|
||||
const visibility = waitUntilInViewport(this.iframePlaceholder);
|
||||
const visibility = waitUntilInViewport(this.iframePlaceholder, {
|
||||
root: notebookEl,
|
||||
proximity: 2000,
|
||||
});
|
||||
|
||||
// Reflect focus based on whether there is a focused parent, this
|
||||
// is later synced on "element_focused" events
|
||||
|
|
|
@ -12,9 +12,9 @@ export function isEditableElement(element) {
|
|||
);
|
||||
}
|
||||
|
||||
export function isElementInViewport(element) {
|
||||
export function isElementInViewport(element, proximity = 0) {
|
||||
const box = element.getBoundingClientRect();
|
||||
return box.bottom >= 0 && box.top <= window.innerHeight;
|
||||
return box.bottom >= -proximity && box.top <= window.innerHeight + proximity;
|
||||
}
|
||||
|
||||
export function isElementHidden(element) {
|
||||
|
@ -39,20 +39,46 @@ export function waitUntilVisible(element) {
|
|||
});
|
||||
}
|
||||
|
||||
export function waitUntilInViewport(element) {
|
||||
/**
|
||||
* Returns a promise that resolves when the element enters the viewport.
|
||||
*
|
||||
* ## Options
|
||||
*
|
||||
* * `root` - a scrollable ancestor that should be used for observing
|
||||
* the intersection, instead of the viewport
|
||||
*
|
||||
* * `proximity` - the number of pixels around `root` used to expand
|
||||
* the intersection box, which effectively resolves the promise when
|
||||
* `element` is in certain proximity of the viewport. Note that if
|
||||
* the element is inside a scrollable ancestor, the ancestor must
|
||||
* be set as `root`.
|
||||
*
|
||||
* > NOTE: rootMargin only applies to the intersection root itself.
|
||||
* > If a target Element is clipped by an ancestor other than the
|
||||
* > intersection root, that clipping is unaffected by rootMargin.
|
||||
* > ~ https://w3c.github.io/IntersectionObserver
|
||||
*
|
||||
*/
|
||||
export function waitUntilInViewport(
|
||||
element,
|
||||
{ root = null, proximity = 0 } = {}
|
||||
) {
|
||||
let observer = null;
|
||||
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
if (isElementVisibleInViewport(element)) {
|
||||
if (isElementVisibleInViewport(element, proximity)) {
|
||||
resolve();
|
||||
} else {
|
||||
observer = new IntersectionObserver((entries) => {
|
||||
if (isElementVisibleInViewport(element)) {
|
||||
observer.disconnect();
|
||||
observer = null;
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
if (entries[0].isIntersecting) {
|
||||
observer.disconnect();
|
||||
observer = null;
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
{ root, rootMargin: `${proximity}px` }
|
||||
);
|
||||
observer.observe(element);
|
||||
}
|
||||
});
|
||||
|
@ -64,8 +90,8 @@ export function waitUntilInViewport(element) {
|
|||
return { promise, cancel };
|
||||
}
|
||||
|
||||
export function isElementVisibleInViewport(element) {
|
||||
return !isElementHidden(element) && isElementInViewport(element);
|
||||
export function isElementVisibleInViewport(element, proximity = 0) {
|
||||
return !isElementHidden(element) && isElementInViewport(element, proximity);
|
||||
}
|
||||
|
||||
export function clamp(n, x, y) {
|
||||
|
|
Loading…
Add table
Reference in a new issue