@jupyterlab/ui-components
Version:
JupyterLab - UI components written in React
816 lines (815 loc) • 29.5 kB
TypeScript
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<WindowedListModel, IChangedArgs<any, any, 'count' | 'estimatedWidgetSize' | 'index' | 'list' | 'overscanCount' | 'windowingActive' | string>>;
/**
* 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<Widget>, changes: IObservableList.IChangedArgs<Widget>): 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<WindowedListModel, IChangedArgs<any, any, string>>;
private _currentWindow;
private _height;
private _isDisposed;
private _itemsList;
private _measuredAllUntilIndex;
private _overscanCount;
private _scrollOffset;
private _widgetCount;
private _widgetSizers;
private _windowingActive;
}
/**
* Windowed list widget
*/
export declare class WindowedList<T extends WindowedList.IModel = WindowedList.IModel, U = any> extends Widget {
/**
* Default widget size
*/
static readonly DEFAULT_WIDGET_SIZE = 50;
/**
* Constructor
*
* @param options Constructor options
*/
constructor(options: WindowedList.IOptions<T, U>);
private _viewportIndicator;
/**
* 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<U>;
/**
* 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<void>;
/**
* 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<number | boolean, number | boolean, string>): 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<this, number>;
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;
private _scrollbarItems;
/**
* Handle `pointerdown` events on the virtual scrollbar.
*/
private _evtPointerDown;
/**
* Handle `scrollend` events on the scroller.
*/
private _onScrollEnd;
/**
* 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 _requiresTotalSizeUpdate;
private _areaResizeObserver;
private _itemsResizeObserver;
private _timerToClearScrollStatus;
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<T = any> {
get?: (index: number) => T;
length: number;
changed: ISignal<any, IObservableList.IChangedArgs<any>>;
}
/**
* A namespace for windowed list
*/
export declare namespace WindowedList {
/**
* The default renderer class for windowed lists.
*/
class Renderer<T = any> implements IRenderer<T> {
/**
* Create the outer, root element of the windowed list.
*/
createOuter(): HTMLElement;
/**
* Create the virtual scrollbar element.
*/
createScrollbar(): HTMLOListElement;
/**
* Create the virtual scrollbar viewport indicator.
*/
createScrollbarViewportIndicator(): HTMLElement;
/**
* 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<any>;
/**
* Windowed list model interface
*/
interface IModel<T = any> 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<T> | 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<IModel, IChangedArgs<any, any, 'count' | 'index' | 'list' | 'overscanCount' | 'windowingActive' | string>>;
/**
* 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<any>;
/**
* 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<T extends WindowedList.IModel = WindowedList.IModel, U = any> {
/**
* Windowed list model to display
*/
model: T;
/**
* Windowed list layout
*/
layout?: WindowedLayout;
/**
* A renderer for the elements of the windowed list.
*/
renderer?: IRenderer<U>;
/**
* Whether the windowed list should display a scrollbar UI.
*/
scrollbar?: boolean;
}
/**
* A windowed list element renderer.
*/
interface IRenderer<T = any> {
/**
* Create the outer, root element of the windowed list.
*/
createOuter(): HTMLElement;
/**
* Create the virtual scrollbar element.
*/
createScrollbar(): HTMLElement;
/**
* Create the virtual scrollbar viewport indicator.
*/
createScrollbarViewportIndicator?(): HTMLElement;
/**
* Create an individual item rendered in the scrollbar.
*/
createScrollbarItem(list: WindowedList, index: number, item: T | undefined): HTMLElement | IRenderer.IScrollbarItem;
/**
* Create the viewport element into which virtualized children are added.
*/
createViewport(): HTMLElement;
}
/**
* Renderer statics.
*/
namespace IRenderer {
/**
* Scrollbar item.
*/
interface IScrollbarItem extends IDisposable {
/**
* Render the scrollbar item as an HTML element.
*/
render: (props: {
index: number;
}) => HTMLElement;
/**
* Unique item key used for caching.
*/
key: string;
}
}
/**
* 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];
}