UNPKG

@lexical/utils

Version:

This package contains misc utilities for Lexical.

55 lines (52 loc) 1.88 kB
/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ import {getParentElement} from 'lexical'; // Got from https://stackoverflow.com/a/42543908/2013580 /** * Walks up from `element` and returns the nearest scrollable ancestor (or * `ownerDocument.body` if none is found), used to keep the active typeahead * option scrolled into view. Set `includeHidden` to also treat * `overflow: hidden` ancestors as scroll parents. * * The walk crosses ShadowRoot→host (via `getParentElement`) so a * shadow-mounted editor's scroll parent is found in the enclosing light-DOM * ancestor chain, and the styles / body are resolved through the element's * own realm so an iframe-mounted editor stays inside its document. */ export function getScrollParent( element: HTMLElement, includeHidden: boolean, ): HTMLElement | HTMLBodyElement { // Resolve through the element's own realm so an iframe-mounted editor's // scroll parent and computed styles come from its document, not the top one. const ownerDocument = element.ownerDocument; const win = ownerDocument.defaultView || window; let style = win.getComputedStyle(element); const excludeStaticParent = style.position === 'absolute'; const overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/; if (style.position === 'fixed') { return ownerDocument.body; } for ( let parent: HTMLElement | null = element; (parent = getParentElement(parent)); ) { style = win.getComputedStyle(parent); if (excludeStaticParent && style.position === 'static') { continue; } if ( overflowRegex.test(style.overflow + style.overflowY + style.overflowX) ) { return parent; } } return ownerDocument.body; }