import { Unsubscribe } from 'nanoevents'; import { AnyFunction, EditorState, EditorViewProps, Except, StateUpdateLifecycleProps } from '@remirror/core'; import type { HoverEventHandlerState, MouseEventHandlerState } from '@remirror/extension-events'; /** * The events that can trigger a positioner update. */ export type PositionerUpdateEvent = 'scroll' | 'state' | 'hover' | 'contextmenu'; export interface Rect { /** * Pixel distance from left of the reference frame. * Alias of `left`. */ x: number; /** * Pixel distance from top of the reference frame. * Alias of `top` for css. */ y: number; /** * The height of the captured position. */ height: number; /** * The width of the captured position. */ width: number; } /** * The absolutely positioned coordinates relative to the editor element. With * these coordinates you can perfectly simulate a position within the text * editor and render it as you decide. */ export interface PositionerPosition extends Rect { /** * The position relative to the document viewport. This can be used with * `position: fixed` when that is a better fit for your application. */ rect: DOMRect; /** * True when any part of the captured position is visible within the dom view. */ visible: boolean; } export interface GetPositionProps extends EditorViewProps, BasePositionerProps { /** * The data that can be transformed into a position. */ data: Data; /** * The reference element being used by the positioner to determine * positioning. */ element: HTMLElement; } export interface GetActiveProps extends EditorViewProps, BasePositionerProps { } export interface BasePositioner { /** * Determines whether anything has changed and whether to continue with a * recalculation. By default this is only true when the document has or * selection has changed. * * @remarks * * Sometimes it is useful to recalculate the positioner on every state update. * In this case you can set this method to always return true. * * ```ts * const positioner: Positioner = { * hasStateChanged: () => true * }; * ``` */ hasChanged: (props: BasePositionerProps) => boolean; /** * Get a unique id for the data returned from `getActive`. * * If left undefined, it defaults to use the index. */ getID?: (data: Data, index: number) => string; /** * Get the active items that will be passed into the `getPosition` method. */ getActive: (props: GetActiveProps) => Data[]; /** * Calculate and return an array of `VirtualPosition`'s which represent the * virtual element the positioner represents. */ getPosition: (props: GetPositionProps) => PositionerPosition; /** * An array of update listeners to determines when the positioner will update it's position. * * - `state` - updates when the prosemirror state is updated - default. * - `scroll` - updates when the editor is scrolled (debounced) * * @defaultValue ['state'] */ events?: PositionerUpdateEvent[]; } export interface SetActiveElement { /** * Set the html element for the active position. */ setElement: (element: HTMLElement) => void; /** * The unique ide for the active element. */ id: string; data: Data; } export interface BasePositionerProps extends Omit { helpers: Record; previousState: undefined | EditorState; /** * The event that triggered this update. */ event: PositionerUpdateEvent; /** * The scroll event information. */ scroll?: { scrollTop: number; }; /** * The hover event information. This is only present when the update was * triggered by a hover event. */ hover?: Except; /** * The contextmenu event information. This is only present when the update was * triggered by a contextmenu event. */ contextmenu?: Except; } export interface ElementsAddedProps { position: PositionerPosition; element: HTMLElement; id: string; } interface PositionerEvents { /** * Called when the dom elements have all been received. In some frameworks * like `React` this may be called asynchronously. */ done: (props: ElementsAddedProps[]) => void; /** * Called when the active values have been updated. */ update: (elementSetters: Array>) => void; } /** * This is the positioner. It exists to report the position of things in the * editor. Typically you will use it to get the position of the cursor. * * But you can be more ambitious and get the position all the active nodes of a * certain type. Or all visible nodes of a certain type in the editor, updated * as it scrolls. * * The positions returned have a rect which is the viewport position. * * There are also the `top`, `left`, `right`, `bottom` which represent the * absolute positioned rectangle of the position in questions. For a cursor * position `left` and `right` are probably the same. */ export declare class Positioner { #private; /** * An empty return value for the positioner. */ static EMPTY: never[]; /** * Create a positioner. */ static create(props: BasePositioner): Positioner; /** * Create a positioner from an existing positioner. * * This is useful when you want to modify parts of the positioner. */ static fromPositioner(positioner: Positioner, base: Partial>): Positioner; readonly events: PositionerUpdateEvent[]; /** * Store the props for the most recent update. This is used by `React` to * reapply the most recent props to the new positioner when the positioner is * recreated within a component. */ recentUpdate?: GetActiveProps; readonly hasChanged: (props: BasePositionerProps) => boolean; get basePositioner(): BasePositioner; private constructor(); /** * Get the active element setters. */ onActiveChanged(props: GetActiveProps): void; /** * Get the id for the active data. Defaults to the index of the data item. */ getID(data: Data, index: number): string; /** * Add a listener to the positioner events. */ readonly addListener: >(event: Key, cb: PositionerEvents[Key]) => Unsubscribe; private addProps; /** * Create a new Positioner with the provided props. */ clone(props?: PositionerCloneProps): Positioner; /** * Clones the positioner while updating the `active` value. This is designed * for usage in frameworks like `react`. */ active(isActive: boolean | ((data: Data) => boolean)): Positioner; } type PositionerCloneProps = Partial> | ((original: BasePositioner) => Partial>); export {};