@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
95 lines (94 loc) • 4.86 kB
TypeScript
/**
* Shared utilities for scrolling to block elements with expand node support.
* Used by both Confluence's useScrollOnUrlChange and platform renderer's useScrollToBlock.
*/
import type { DocNode } from '@atlaskit/adf-schema';
/**
* Timing constants for expand animation and DOM update delays.
* These values are tuned for the expand component's behavior and React's update cycle.
*/
export declare const SCROLL_TO_BLOCK_TIMING: {
/** Minimal delay for DOM/React updates after expanding (no animation in expand component). */
readonly DOM_UPDATE_DELAY: 50;
/** Delay when expand operation fails and needs retry. */
readonly RETRY_DELAY: 100;
/** Maximum number of retry attempts before giving up and scrolling anyway. */
readonly MAX_ATTEMPTS: 5;
/** Maximum depth of nested expands to search (prevents infinite loops). */
readonly MAX_EXPAND_DEPTH: 2;
};
export type NodeWithExpandParents = {
/** Array of expand parent localIds (empty if no expand parents, ordered from outermost to innermost). */
expandParentLocalIds: string[];
};
/**
* Find a node by its localId in an ADF document and determine if it has expand or nestedExpand parents.
* This is used to identify nodes that may be hidden inside collapsed expands.
*
* @param adfDoc - The ADF document to search
* @param targetLocalId - The localId to search for
* @returns NodeWithExpandParents if found, undefined otherwise
*/
export declare function findNodeWithExpandParents(adfDoc: DocNode, targetLocalId: string): NodeWithExpandParents | undefined;
/**
* Find all parent expand elements that contain the target element.
* Searches up the DOM tree to find expand or nestedExpand containers.
*
* This function limits the search depth to prevent infinite loops and performance issues.
* The default maxDepth of 2 is chosen because:
* - Most use cases have 0-2 levels of nesting
* - Searching deeper can impact performance
* - Users rarely nest expands more than 2 levels deep
*
* @param element - The target element to find parents for.
* @param maxDepth - Maximum depth to search (default: 2). This is the maximum number of
* expand ancestors to find, starting from the target element.
* @returns Array of expand containers ordered from outermost to innermost.
* For example, if element is inside expand B which is inside expand A,
* this returns [expandA, expandB].
*/
export declare const findParentExpands: (element: HTMLElement, maxDepth?: number) => HTMLElement[];
/**
* Check if an expand node is currently collapsed.
*
* Uses two methods to determine collapse state:
* 1. First checks aria-expanded attribute on the toggle button (most reliable).
* 2. Falls back to checking content div visibility via computed styles.
*
* @param expandContainer - The expand container element.
* @returns True if the expand is collapsed, false if expanded or state cannot be determined.
*/
export declare const isExpandCollapsed: (expandContainer: HTMLElement) => boolean;
/**
* Expand a collapsed expand node by clicking its toggle button.
*
* This function finds the toggle button with aria-expanded="false" and programmatically
* clicks it to expand the node. It does not wait for the expansion to complete.
*
* @param expandContainer - The expand container element.
* @returns True if the toggle button was found and clicked, false otherwise.
*/
export declare const expandElement: (expandContainer: HTMLElement) => boolean;
/**
* Expand all parent expands then scroll to the element.
*
* This is the main entry point for scrolling to elements that may be hidden inside collapsed expands.
* It handles nested expands by expanding them one at a time from outermost to innermost,
* waiting for DOM updates between each expansion.
*
* The function uses a recursive approach with retry logic to handle:
* - Nested expands that need sequential expansion
* - DOM updates that may take time to reflect
* - Failed expand operations (e.g., if toggle button is temporarily unavailable)
* - Disconnected elements (removed from DOM)
*
* After all parent expands are open (or max attempts reached), scrolls the element into view
* with smooth behavior and centered in the viewport.
*
* @param element - The target element to scroll to.
* @param attempt - Current attempt number (used internally for retry logic, starts at 0).
* @returns A cleanup function that cancels any pending timeouts. Call this when the operation
* should be aborted (e.g., component unmount, navigation, or new scroll request).
*/
export declare const expandAllParentsThenScroll: (element: HTMLElement, attempt?: number, scrollFn?: (element: HTMLElement) => void) => (() => void);
export declare const getLocalIdSelector: (localId: string, container: HTMLElement) => HTMLElement | null;