UNPKG

@jupyterlab/apputils

Version:
143 lines 4.57 kB
/* ----------------------------------------------------------------------------- | Copyright (c) Jupyter Development Team. | Distributed under the terms of the Modified BSD License. |----------------------------------------------------------------------------*/ import { searchIcon } from '@jupyterlab/ui-components'; import { Panel, Widget } from '@lumino/widgets'; /** * Class name identifying the input group with search icon. */ const SEARCH_ICON_GROUP_CLASS = 'jp-SearchIconGroup'; /** * Wrap the command palette in a modal to make it more usable. */ export class ModalCommandPalette extends Panel { constructor(options) { super(); this.addClass('jp-ModalCommandPalette'); this.addClass('jp-ThemedContainer'); this.id = 'modal-command-palette'; this.palette = options.commandPalette; this._commandPalette.commands.commandExecuted.connect(() => { if (this.isAttached && this.isVisible) { this.hideAndReset(); } }); // required to properly receive blur and focus events; // selection of items with mouse may not work without this. this.node.tabIndex = 0; } get palette() { return this._commandPalette; } set palette(value) { this._commandPalette = value; if (!this.searchIconGroup) { this._commandPalette.inputNode.insertAdjacentElement('afterend', this.createSearchIconGroup()); } this.addWidget(value); this.hideAndReset(); } attach() { Widget.attach(this, document.body); } detach() { Widget.detach(this); } /** * Hide the modal command palette and reset its search. */ hideAndReset() { this.hide(); this._commandPalette.inputNode.value = ''; this._commandPalette.refresh(); } /** * Handle incoming events. */ handleEvent(event) { switch (event.type) { case 'keydown': this._evtKeydown(event); break; case 'blur': { // if the focus shifted outside of this DOM element, hide and reset. if ( // focus went away from child element this.node.contains(event.target) && // and it did NOT go to another child element but someplace else !this.node.contains(event.relatedTarget)) { event.stopPropagation(); this.hideAndReset(); } break; } case 'contextmenu': event.preventDefault(); event.stopPropagation(); break; default: break; } } /** * Find the element with search icon group. */ get searchIconGroup() { return this._commandPalette.node.getElementsByClassName(SEARCH_ICON_GROUP_CLASS)[0]; } /** * Create element with search icon group. */ createSearchIconGroup() { const inputGroup = document.createElement('div'); inputGroup.classList.add(SEARCH_ICON_GROUP_CLASS); searchIcon.render(inputGroup); return inputGroup; } /** * A message handler invoked on an `'after-attach'` message. */ onAfterAttach(msg) { this.node.addEventListener('keydown', this, true); this.node.addEventListener('contextmenu', this, true); } /** * A message handler invoked on an `'after-detach'` message. */ onAfterDetach(msg) { this.node.removeEventListener('keydown', this, true); this.node.removeEventListener('contextmenu', this, true); } onBeforeHide(msg) { document.removeEventListener('blur', this, true); } onAfterShow(msg) { document.addEventListener('blur', this, true); } /** * A message handler invoked on an `'activate-request'` message. */ onActivateRequest(msg) { if (this.isAttached) { this.show(); this._commandPalette.activate(); } } /** * Handle the `'keydown'` event for the widget. */ _evtKeydown(event) { // Check for escape key switch (event.keyCode) { case 27: // Escape. event.stopPropagation(); event.preventDefault(); this.hideAndReset(); break; default: break; } } } //# sourceMappingURL=commandpalette.js.map