import { IChangedArgs } from '@jupyterlab/coreutils'; import { IObservableList } from '@jupyterlab/observables'; import { IDisposable } from '@lumino/disposable'; import { Message } from '@lumino/messaging'; import { ISignal, Signal } from '@lumino/signaling'; import { PanelLayout, Widget } from '@lumino/widgets'; /** * Windowed list abstract model. */ export declare abstract class WindowedListModel implements WindowedList.IModel { /** * Constructor * * @param options Constructor options */ constructor(options?: WindowedList.IModelOptions); /** * Provide a best guess for the widget size at position index * * #### Notes * * This function should be very light to compute especially when * returning the default size. * The default value should be constant (i.e. two calls with `null` should * return the same value). But it can change for a given `index`. * * @param index Widget position * @returns Estimated widget size */ abstract estimateWidgetSize: (index: number) => number; /** * Widget factory for the list items. * * Caching the resulting widgets should be done by the callee. * * @param index List index * @returns The widget at the given position */ abstract widgetRenderer: (index: number) => Widget; /** * The overlap threshold used to decide whether to scroll down to an item * below the viewport (smart mode). If the item overlap with the viewport * is greater or equal this threshold the item is considered sufficiently * visible and will not be scrolled to. The value is the number of pixels * in overlap if greater than one, or otherwise a fraction of item height. * By default the item is scrolled to if not full visible in the viewport. */ readonly scrollDownThreshold: number; /** * The underlap threshold used to decide whether to scroll up to an item * above the viewport (smart mode). If the item part outside the viewport * (underlap) is greater than this threshold then the item is considered * not sufficiently visible and will be scrolled to. * The value is the number of pixels in underlap if greater than one, or * otherwise a fraction of the item height. * By default the item is scrolled to if not full visible in the viewport. */ readonly scrollUpThreshold: number; /** * Top padding of the the outer window node. */ paddingTop: number; /** * List widget height */ get height(): number; set height(h: number); /** * Test whether the model is disposed. */ get isDisposed(): boolean; /** * Items list to be rendered */ get itemsList(): ISimpleObservableList | null; set itemsList(v: ISimpleObservableList | null); /** * Number of widgets to render in addition to those * visible in the viewport. */ get overscanCount(): number; set overscanCount(newValue: number); /** * Viewport scroll offset. */ get scrollOffset(): number; set scrollOffset(offset: number); /** * Total number of widgets in the list */ get widgetCount(): number; set widgetCount(newValue: number); /** * Whether windowing is active or not. * * This is true by default. */ get windowingActive(): boolean; set windowingActive(newValue: boolean); /** * A signal emitted when any model state changes. */ get stateChanged(): ISignal>; /** * Dispose the model. */ dispose(): void; /** * Get the total list size. * * @returns Total estimated size */ getEstimatedTotalSize(): number; /** * Get the scroll offset to display an item in the viewport. * * By default, the list will scroll as little as possible to ensure the item is fully visible (`auto`). * You can control the alignment of the item though by specifying a second alignment parameter. * Acceptable values are: * * auto - Automatically align with the top or bottom minimising the amount scrolled, * If `alignPreference` is given, follow such preferred alignment. * If item is smaller than the viewport and fully visible, do not scroll at all. * smart - If the item is significantly visible, don't scroll at all (regardless of whether it fits in the viewport). * If the item is less than one viewport away, scroll so that it becomes fully visible (following the `auto` heuristics). * If the item is more than one viewport away, scroll so that it is centered within the viewport (`center` if smaller than viewport, `top-center` otherwise). * center - Align the middle of the item with the middle of the viewport (it only works well for items smaller than the viewport). * top-center - Align the top of the item with the middle of the viewport (works well for items larger than the viewport). * end - Align the bottom of the item to the bottom of the list. * start - Align the top of item to the top of the list. * * An item is considered significantly visible if: * - it overlaps with the viewport by the amount specified by `scrollDownThreshold` when below the viewport * - it exceeds the viewport by the amount less than specified by `scrollUpThreshold` when above the viewport. * * @param index Item index * @param align Where to align the item in the viewport * @param margin The proportion of viewport to add when aligning with the top/bottom of the list. * @param precomputed Precomputed values to use when windowing is disabled. * @param alignPreference Allows to override the alignment of item when the `auto` heuristic decides that the item needs to be scrolled into view. * @returns The needed scroll offset */ getOffsetForIndexAndAlignment(index: number, align?: WindowedList.ScrollToAlign, margin?: number, precomputed?: { totalSize: number; itemMetadata: WindowedList.ItemMetadata; currentOffset: number; }, alignPreference?: WindowedList.BaseScrollToAlignment): number; /** * Compute the items range to display. * * It returns ``null`` if the range does not need to be updated. * * @returns The current items range to display */ getRangeToRender(): WindowedList.WindowIndex | null; /** * Return the viewport top position and height for range spanning from * ``startIndex`` to ``stopIndex``. * * @param startIndex First item in viewport index * @param stopIndex Last item in viewport index * @returns The viewport top position and its height */ getSpan(startIndex: number, stopIndex: number): [number, number]; /** * WindowedListModel caches offsets and measurements for each index for performance purposes. * This method clears that cached data for all items after (and including) the specified index. * * The list will automatically re-render after the index is reset. * * @param index */ resetAfterIndex(index: number): void; /** * Update item sizes. * * This should be called when the real item sizes has been * measured. * * @param sizes New sizes per item index * @returns Whether some sizes changed or not */ setWidgetSize(sizes: { index: number; size: number; }[]): boolean; /** * Callback on list changes * * @param list List items * @param changes List change */ protected onListChanged(list: IObservableList, changes: IObservableList.IChangedArgs): void; private _getItemMetadata; private _findNearestItem; private _findNearestItemBinarySearch; private _findNearestItemExponentialSearch; private _getRangeToRender; private _getStartIndexForOffset; private _getStopIndexForStartIndex; /** * Default widget size estimation * * @deprecated we always use {@link estimateWidgetSize} */ protected _estimatedWidgetSize: number; protected _stateChanged: Signal>; private _currentWindow; private _height; private _isDisposed; private _itemsList; private _lastMeasuredIndex; private _overscanCount; private _scrollOffset; private _widgetCount; private _widgetSizers; private _windowingActive; } /** * Windowed list widget */ export declare class WindowedList extends Widget { /** * Default widget size */ static readonly DEFAULT_WIDGET_SIZE = 50; /** * Constructor * * @param options Constructor options */ constructor(options: WindowedList.IOptions); /** * Whether the parent is hidden or not. * * This should be set externally if a container is hidden to * stop updating the widget size when hidden. */ get isParentHidden(): boolean; set isParentHidden(v: boolean); /** * Widget layout */ get layout(): WindowedLayout; /** * The outer container of the windowed list. */ get outerNode(): HTMLElement; /** * Viewport */ get viewportNode(): HTMLElement; /** * Flag to enable virtual scrollbar. */ get scrollbar(): boolean; set scrollbar(enabled: boolean); /** * The renderer for this windowed list. Set at instantiation. */ protected renderer: WindowedList.IRenderer; /** * Windowed list view model */ protected get viewModel(): T; /** * Dispose the windowed list. */ dispose(): void; /** * Callback on event. * * @param event Event */ handleEvent(event: Event): void; /** * Scroll to the specified offset `scrollTop`. * * @param scrollOffset Offset to scroll * * @deprecated since v4 This is an internal helper. Prefer calling `scrollToItem`. */ scrollTo(scrollOffset: number): void; /** * Scroll to the specified item. * * By default, the list will scroll as little as possible to ensure the item is fully visible (`auto`). * You can control the alignment of the item though by specifying a second alignment parameter. * Acceptable values are: * * auto - Automatically align with the top or bottom minimising the amount scrolled, * If `alignPreference` is given, follow such preferred alignment. * If item is smaller than the viewport and fully visible, do not scroll at all. * smart - If the item is significantly visible, don't scroll at all (regardless of whether it fits in the viewport). * If the item is less than one viewport away, scroll so that it becomes fully visible (following the `auto` heuristics). * If the item is more than one viewport away, scroll so that it is centered within the viewport (`center` if smaller than viewport, `top-center` otherwise). * center - Align the middle of the item with the middle of the viewport (it only works well for items smaller than the viewport). * top-center - Align the top of the item with the middle of the viewport (works well for items larger than the viewport). * end - Align the bottom of the item to the bottom of the list. * start - Align the top of item to the top of the list. * * @param index Item index to scroll to * @param align Type of alignment * @param margin In 'smart' mode the viewport proportion to add * @param alignPreference Allows to override the alignment of item when the `auto` heuristic decides that the item needs to be scrolled into view. */ scrollToItem(index: number, align?: WindowedList.ScrollToAlign, margin?: number, alignPreference?: WindowedList.BaseScrollToAlignment): Promise; /** * A message handler invoked on an `'after-attach'` message. */ protected onAfterAttach(msg: Message): void; /** * A message handler invoked on an `'before-detach'` message. */ protected onBeforeDetach(msg: Message): void; /** * Callback on scroll event * * @param event Scroll event */ protected onScroll(event: Event): void; /** * A message handler invoked on an `'resize-request'` message. */ protected onResize(msg: Widget.ResizeMessage): void; /** * Callback on view model change * * @param model Windowed list model * @param changes Change */ protected onStateChanged(model: WindowedList.IModel, changes: IChangedArgs): void; /** * A message handler invoked on an `'update-request'` message. * * #### Notes * The default implementation of this handler is a no-op. */ protected onUpdateRequest(msg: Message): void; /** * A signal that emits the index when the virtual scrollbar jumps to an item. */ protected jumped: Signal; private _adjustDimensionsForScrollbar; /** * Add listeners for viewport, contents and the virtual scrollbar. */ private _addListeners; /** * Turn off windowing related styles in the viewport. */ private _applyNoWindowingStyles; /** * Turn on windowing related styles in the viewport. */ private _applyWindowingStyles; /** * Remove listeners for viewport and contents (but not the virtual scrollbar). */ private _removeListeners; /** * Update viewport and DOM state. */ private _update; /** * Handle viewport area resize. */ private _onAreaResize; /** * Handle viewport content (i.e. items) resize. */ private _onItemResize; /** * Scroll to the item which was most recently requested. * * This method ensures that the app scrolls to the item even if a resize event * occurs shortly after the scroll. Consider the following sequence of events: * * 1. User is at the nth cell, presses Shift+Enter (run current cell and * advance to next) * 2. App scrolls to the next (n+1) cell * 3. The nth cell finishes running and renders the output, pushing the * (n+1) cell down out of view * 4. This triggers the resize observer, which calls this method and scrolls * the (n+1) cell back into view * * On implementation level, this is ensured by scrolling to `this._scrollToItem` * which is cleared after a short timeout once the scrolling settles * (see `this._resetScrollToItem()`). */ private _scrollBackToItemOnResize; /** * Clear any outstanding timeout and enqueue scrolling to a new item. */ private _resetScrollToItem; /** * Render virtual scrollbar. */ private _renderScrollbar; /** * Handle `pointerdown` events on the virtual scrollbar. */ private _evtPointerDown; /** * Update the total size */ private _updateTotalSize; protected _viewModel: T; private _viewportPaddingTop; private _viewportPaddingBottom; private _innerElement; private _isParentHidden; private _isScrolling; private _needsUpdate; private _outerElement; private _resetScrollToItemTimeout; private _areaResizeObserver; private _itemsResizeObserver; private _scrollbarElement; private _scrollbarResizeObserver; private _scrollRepaint; private _scrollToItem; private _scrollUpdateWasRequested; private _updater; private _viewport; } /** * Customized layout for windowed list container. */ export declare class WindowedLayout extends PanelLayout { /** * Constructor */ constructor(); /** * Specialized parent type definition */ get parent(): WindowedList | null; set parent(value: WindowedList | null); /** * Attach a widget to the parent's DOM node. * * @param index - The current index of the widget in the layout. * * @param widget - The widget to attach to the parent. * * #### Notes * This method is called automatically by the panel layout at the * appropriate time. It should not be called directly by user code. * * The default implementation adds the widgets's node to the parent's * node at the proper location, and sends the appropriate attach * messages to the widget if the parent is attached to the DOM. * * Subclasses may reimplement this method to control how the widget's * node is added to the parent's node. */ protected attachWidget(index: number, widget: Widget): void; /** * Detach a widget from the parent's DOM node. * * @param index - The previous index of the widget in the layout. * * @param widget - The widget to detach from the parent. * * #### Notes * This method is called automatically by the panel layout at the * appropriate time. It should not be called directly by user code. * * The default implementation removes the widget's node from the * parent's node, and sends the appropriate detach messages to the * widget if the parent is attached to the DOM. * * Subclasses may reimplement this method to control how the widget's * node is removed from the parent's node. */ protected detachWidget(index: number, widget: Widget): void; /** * Move a widget in the parent's DOM node. * * @param fromIndex - The previous index of the widget in the layout. * * @param toIndex - The current index of the widget in the layout. * * @param widget - The widget to move in the parent. * * #### Notes * This method is called automatically by the panel layout at the * appropriate time. It should not be called directly by user code. * * The default implementation moves the widget's node to the proper * location in the parent's node and sends the appropriate attach and * detach messages to the widget if the parent is attached to the DOM. * * Subclasses may reimplement this method to control how the widget's * node is moved in the parent's node. */ protected moveWidget(fromIndex: number, toIndex: number, widget: Widget): void; /** * A message handler invoked on an `'update-request'` message. * * #### Notes * This is a reimplementation of the base class method, * and is a no-op. */ protected onUpdateRequest(msg: Message): void; } /** * Windowed list model interface */ export interface ISimpleObservableList { get?: (index: number) => T; length: number; changed: ISignal>; } /** * A namespace for windowed list */ export declare namespace WindowedList { /** * The default renderer class for windowed lists. */ class Renderer implements IRenderer { /** * Create the outer, root element of the windowed list. */ createOuter(): HTMLElement; /** * Create the virtual scrollbar element. */ createScrollbar(): HTMLOListElement; /** * Create an individual item rendered in the scrollbar. */ createScrollbarItem(_: WindowedList, index: number): HTMLLIElement; /** * Create the viewport element into which virtualized children are added. */ createViewport(): HTMLElement; } /** * The default renderer for windowed lists. */ const defaultRenderer: Renderer; /** * Windowed list model interface */ interface IModel extends IDisposable { /** * Provide a best guess for the widget size at position index * * #### Notes * * This function should be very light to compute especially when * returning the default size. * The default value should be constant (i.e. two calls with `null` should * return the same value). But it can change for a given `index`. * * @param index Widget position * @returns Estimated widget size */ estimateWidgetSize: (index: number) => number; /** * Get the total list size. * * @returns Total estimated size */ getEstimatedTotalSize(): number; /** * Get the scroll offset to display an item in the viewport. * * By default, the list will scroll as little as possible to ensure the item is fully visible (`auto`). * You can control the alignment of the item though by specifying a second alignment parameter. * Acceptable values are: * * auto - Automatically align with the top or bottom minimising the amount scrolled, * If `alignPreference` is given, follow such preferred alignment. * If item is smaller than the viewport and fully visible, do not scroll at all. * smart - If the item is significantly visible, don't scroll at all (regardless of whether it fits in the viewport). * If the item is less than one viewport away, scroll so that it becomes fully visible (following the `auto` heuristics). * If the item is more than one viewport away, scroll so that it is centered within the viewport (`center` if smaller than viewport, `top-center` otherwise). * center - Align the middle of the item with the middle of the viewport (it only works well for items smaller than the viewport). * top-center - Align the top of the item with the middle of the viewport (works well for items larger than the viewport). * end - Align the bottom of the item to the bottom of the list. * start - Align the top of item to the top of the list. * * @param index Item index * @param align Where to align the item in the viewport * @param margin In 'smart' mode the viewport proportion to add * @param precomputed Precomputed values to use when windowing is disabled. * @param alignPreference Allows to override the alignment of item when the `auto` heuristic decides that the item needs to be scrolled into view. * @returns The needed scroll offset */ getOffsetForIndexAndAlignment(index: number, align?: ScrollToAlign, margin?: number, precomputed?: { totalSize: number; itemMetadata: WindowedList.ItemMetadata; currentOffset: number; }, alignPreference?: WindowedList.BaseScrollToAlignment): number; /** * Compute the items range to display. * * It returns ``null`` if the range does not need to be updated. * * @returns The current items range to display */ getRangeToRender(): WindowIndex | null; /** * Return the viewport top position and height for range spanning from * ``startIndex`` to ``stopIndex``. * * @param start First item in viewport index * @param stop Last item in viewport index * @returns The viewport top position and its height */ getSpan(start: number, stop: number): [number, number]; /** * List widget height */ height: number; /** * Top padding of the the outer window node. */ paddingTop?: number; /** * Items list to be rendered */ itemsList: ISimpleObservableList | null; /** * Number of widgets to render in addition to those * visible in the viewport. */ overscanCount: number; /** * WindowedListModel caches offsets and measurements for each index for performance purposes. * This method clears that cached data for all items after (and including) the specified index. * * The list will automatically re-render after the index is reset. * * @param index */ resetAfterIndex(index: number): void; /** * Viewport scroll offset. */ scrollOffset: number; /** * Update item sizes. * * This should be called when the real item sizes has been * measured. * * @param sizes New sizes per item index * @returns Whether some sizes changed or not */ setWidgetSize(sizes: { index: number; size: number; }[]): boolean; /** * A signal emitted when any model state changes. */ readonly stateChanged: ISignal>; /** * Total number of widgets in the list */ widgetCount: number; /** * Whether windowing is active or not. */ windowingActive: boolean; /** * Widget factory for the list items. * * Caching the resulting widgets should be done by the callee. * * @param index List index * @returns The widget at the given position */ widgetRenderer: (index: number) => Widget; } /** * Windowed list model constructor options */ interface IModelOptions { /** * Total number of widgets in the list. * * #### Notes * If an observable list is provided this will be ignored. */ count?: number; /** * Dynamic list of items */ itemsList?: IObservableList; /** * Number of widgets to render in addition to those * visible in the viewport. */ overscanCount?: number; /** * Whether windowing is active or not. * * This is true by default. */ windowingActive?: boolean; } /** * Windowed list view constructor options */ interface IOptions { /** * Windowed list model to display */ model: T; /** * Windowed list layout */ layout?: WindowedLayout; /** * A renderer for the elements of the windowed list. */ renderer?: IRenderer; /** * Whether the windowed list should display a scrollbar UI. */ scrollbar?: boolean; } /** * A windowed list element renderer. */ interface IRenderer { /** * Create the outer, root element of the windowed list. */ createOuter(): HTMLElement; /** * Create the virtual scrollbar element. */ createScrollbar(): HTMLElement; /** * Create an individual item rendered in the scrollbar. */ createScrollbarItem(list: WindowedList, index: number, item: T | undefined): HTMLElement; /** * Create the viewport element into which virtualized children are added. */ createViewport(): HTMLElement; } /** * Item list metadata */ type ItemMetadata = { /** * Item vertical offset in the container */ offset: number; /** * Item height */ size: number; /** * Whether the size is an estimation or a measurement. */ measured?: boolean; }; /** * Basic type of scroll alignment */ type BaseScrollToAlignment = 'center' | 'top-center' | 'start' | 'end'; /** * Type of scroll alignment including `auto` and `smart` */ type ScrollToAlign = 'auto' | 'smart' | BaseScrollToAlignment; /** * Widget range in view port */ type WindowIndex = [number, number, number, number]; }