UNPKG

@theia/core

Version:

Theia is a cloud & desktop IDE framework implemented in TypeScript.

266 lines • 9.58 kB
"use strict"; // ***************************************************************************** // Copyright (C) 2018 TypeFox and others. // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License v. 2.0 which is available at // http://www.eclipse.org/legal/epl-2.0. // // This Source Code may also be made available under the following Secondary // Licenses when the conditions for such availability set forth in the Eclipse // Public License v. 2.0 are satisfied: GNU General Public License, version 2 // with the GNU Classpath Exception which is available at // https://www.gnu.org/software/classpath/license.html. // // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 // ***************************************************************************** Object.defineProperty(exports, "__esModule", { value: true }); exports.SearchBoxFactory = exports.SearchBox = exports.SearchBoxProps = void 0; const search_box_debounce_1 = require("../tree/search-box-debounce"); const widget_1 = require("../widgets/widget"); const event_1 = require("../../common/event"); const keys_1 = require("../keyboard/keys"); const nls_1 = require("../../common/nls"); var SearchBoxProps; (function (SearchBoxProps) { /** * The default search box widget option. */ SearchBoxProps.DEFAULT = search_box_debounce_1.SearchBoxDebounceOptions.DEFAULT; })(SearchBoxProps = exports.SearchBoxProps || (exports.SearchBoxProps = {})); /** * The search box widget. */ class SearchBox extends widget_1.BaseWidget { constructor(props, debounce) { super(); this.props = props; this.debounce = debounce; this.nextEmitter = new event_1.Emitter(); this.previousEmitter = new event_1.Emitter(); this.closeEmitter = new event_1.Emitter(); this.textChangeEmitter = new event_1.Emitter(); this.filterToggleEmitter = new event_1.Emitter(); this._isFiltering = false; this.toDispose.pushAll([ this.nextEmitter, this.previousEmitter, this.closeEmitter, this.textChangeEmitter, this.filterToggleEmitter, this.debounce, this.debounce.onChanged(data => this.fireTextChange(data)) ]); this.hide(); this.update(); const { input, filter } = this.createContent(); this.input = input; this.filter = filter; } get onPrevious() { return this.previousEmitter.event; } get onNext() { return this.nextEmitter.event; } get onClose() { return this.closeEmitter.event; } get onTextChange() { return this.textChangeEmitter.event; } get onFilterToggled() { return this.filterToggleEmitter.event; } get isFiltering() { return this._isFiltering; } get keyCodePredicate() { return this.canHandle.bind(this); } firePrevious() { this.previousEmitter.fire(undefined); } fireNext() { this.nextEmitter.fire(undefined); } fireClose() { this.closeEmitter.fire(undefined); } fireTextChange(input) { this.textChangeEmitter.fire(input); } fireFilterToggle() { this.doFireFilterToggle(); } doFireFilterToggle(toggleTo = !this._isFiltering) { if (this.filter) { if (toggleTo) { this.filter.classList.add(SearchBox.Styles.FILTER_ON); } else { this.filter.classList.remove(SearchBox.Styles.FILTER_ON); } this._isFiltering = toggleTo; this.filterToggleEmitter.fire(toggleTo); this.update(); } } handle(event) { event.preventDefault(); const keyCode = keys_1.KeyCode.createKeyCode(event); if (this.canHandle(keyCode)) { if (keys_1.Key.equals(keys_1.Key.ESCAPE, keyCode) || this.isCtrlBackspace(keyCode)) { this.hide(); } else { this.show(); this.handleKey(keyCode); } } } handleArrowUp() { this.firePrevious(); } handleArrowDown() { this.fireNext(); } onBeforeHide() { this.removeClass(SearchBox.Styles.NO_MATCH); this.doFireFilterToggle(false); this.debounce.append(undefined); this.fireClose(); } handleKey(keyCode) { const character = keys_1.Key.equals(keys_1.Key.BACKSPACE, keyCode) ? '\b' : keyCode.character; const data = this.debounce.append(character); if (data) { this.input.textContent = this.getTrimmedContent(data); this.update(); } else { this.hide(); } } getTrimmedContent(data) { if (data.length > SearchBox.MAX_CONTENT_LENGTH) { return '...' + data.substring(data.length - SearchBox.MAX_CONTENT_LENGTH); } return data; } canHandle(keyCode) { if (keyCode === undefined) { return false; } const { ctrl, alt, meta } = keyCode; if (this.isCtrlBackspace(keyCode)) { return true; } if (ctrl || alt || meta || keyCode.key === keys_1.Key.SPACE) { return false; } if (keyCode.character || (this.isVisible && SearchBox.SPECIAL_KEYS.some(key => keys_1.Key.equals(key, keyCode)))) { return true; } return false; } isCtrlBackspace(keyCode) { if (keyCode.ctrl && keys_1.Key.equals(keys_1.Key.BACKSPACE, keyCode)) { return true; } return false; } updateHighlightInfo(info) { if (info.filterText && info.filterText.length > 0) { if (info.matched === 0) { this.addClass(SearchBox.Styles.NO_MATCH); } else { this.removeClass(SearchBox.Styles.NO_MATCH); } } } createContent() { this.node.setAttribute('tabIndex', '0'); this.addClass(SearchBox.Styles.SEARCH_BOX); const input = document.createElement('span'); input.classList.add(SearchBox.Styles.SEARCH_INPUT); this.node.appendChild(input); const buttons = document.createElement('div'); buttons.classList.add(SearchBox.Styles.SEARCH_BUTTONS_WRAPPER); this.node.appendChild(buttons); let filter; if (this.props.showFilter) { filter = document.createElement('div'); filter.classList.add(SearchBox.Styles.BUTTON, ...SearchBox.Styles.FILTER); filter.title = nls_1.nls.localizeByDefault('Enable Filter on Type'); buttons.appendChild(filter); filter.onclick = this.fireFilterToggle.bind(this); } let previous; let next; let close; if (!!this.props.showButtons) { previous = document.createElement('div'); previous.classList.add(SearchBox.Styles.BUTTON, SearchBox.Styles.BUTTON_PREVIOUS); previous.title = nls_1.nls.localize('theia/core/searchbox/previous', 'Previous (Up)'); buttons.appendChild(previous); previous.onclick = () => this.firePrevious.bind(this)(); next = document.createElement('div'); next.classList.add(SearchBox.Styles.BUTTON, SearchBox.Styles.BUTTON_NEXT); next.title = nls_1.nls.localize('theia/core/searchbox/next', 'Next (Down)'); buttons.appendChild(next); next.onclick = () => this.fireNext.bind(this)(); } if (this.props.showButtons || this.props.showFilter) { close = document.createElement('div'); close.classList.add(SearchBox.Styles.BUTTON, SearchBox.Styles.BUTTON_CLOSE); close.title = nls_1.nls.localize('theia/core/searchbox/close', 'Close (Escape)'); buttons.appendChild(close); close.onclick = () => this.hide.bind(this)(); } return { container: this.node, input, filter, previous, next, close }; } onAfterAttach(msg) { super.onAfterAttach(msg); // eslint-disable-next-line @typescript-eslint/no-explicit-any this.addEventListener(this.input, 'selectstart', () => false); } } exports.SearchBox = SearchBox; SearchBox.SPECIAL_KEYS = [ keys_1.Key.ESCAPE, keys_1.Key.BACKSPACE ]; SearchBox.MAX_CONTENT_LENGTH = 15; (function (SearchBox) { /** * CSS classes for the search box widget. */ let Styles; (function (Styles) { Styles.SEARCH_BOX = 'theia-search-box'; Styles.SEARCH_INPUT = 'theia-search-input'; Styles.SEARCH_BUTTONS_WRAPPER = 'theia-search-buttons-wrapper'; Styles.BUTTON = 'theia-search-button'; Styles.FILTER = ['codicon', 'codicon-filter']; Styles.FILTER_ON = 'filter-active'; Styles.BUTTON_PREVIOUS = 'theia-search-button-previous'; Styles.BUTTON_NEXT = 'theia-search-button-next'; Styles.BUTTON_CLOSE = 'theia-search-button-close'; Styles.NON_SELECTABLE = 'theia-non-selectable'; Styles.NO_MATCH = 'no-match'; })(Styles = SearchBox.Styles || (SearchBox.Styles = {})); })(SearchBox = exports.SearchBox || (exports.SearchBox = {})); /** * Search box factory. */ exports.SearchBoxFactory = Symbol('SearchBoxFactory'); //# sourceMappingURL=search-box.js.map