UNPKG

@kui-shell/plugin-electron-components

Version:

Kui plugin that houses electron-specific React components

245 lines (244 loc) 8.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireDefault(require("react")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* * Copyright 2021 The Kubernetes Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var __awaiter = void 0 && (void 0).__awaiter || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; const SearchInput = _react.default.lazy(() => Promise.resolve().then(() => require('@patternfly/react-core/dist/esm/components/SearchInput')).then(_ => ({ default: _.SearchInput }))); class Search extends _react.default.Component { constructor(props) { super(props); this.onKeydown = evt => { if (!evt.defaultPrevented && evt.code === 'KeyF' && (evt.ctrlKey && process.platform !== 'darwin' || evt.metaKey)) { if (this.state.isActive && document.activeElement !== this._input) { this.doFocus(); } else { this.findInPage(); // allows for search to be reinitiated when the search bar is reopened const isActive = !this.state.isActive; if (!isActive) { this.stopFindInPage(); } this.setState(() => ({ isActive, result: undefined })); } } }; this._onChange = this.onChange.bind(this); this._onClear = this.onClear.bind(this); this._onNext = this.onNext.bind(this); this._onPrevious = this.onPrevious.bind(this); this._onRef = c => { if (c) { this._input = c; } }; this.state = { isActive: false, result: undefined, currentMatchIdx: 1 }; } /** stop findInPage, and clear selections in page */ stopFindInPage() { return __awaiter(this, void 0, void 0, function* () { const { ipcRenderer } = yield Promise.resolve().then(() => require('electron')); // note: with 'clearSelection', the focus of the input is very // odd; it is focused, but typing text does nothing until some // global refresh occurs. maybe this is just a bug in electron 6? ipcRenderer.send('synchronous-message', JSON.stringify({ operation: 'stop-find-in-page' })); }); } componentDidMount() { // this.stopFindInPage() // <-- failsafe, in case of bugs; electron seems to persist this document.body.addEventListener('keydown', this.onKeydown); } componentWillUnmount() { document.body.removeEventListener('keydown', this.onKeydown); } componentDidUpdate() { if (this.state.isActive) { setTimeout(() => this.doFocus()); } } onChange() { return __awaiter(this, void 0, void 0, function* () { if (this._input) { if (this._input.value.length === 0) { yield this.stopFindInPage(); this.setState({ result: undefined }); } else { this.findInPage(); } } }); } findInPage(options) { return __awaiter(this, void 0, void 0, function* () { if (!this._input || !this._input.value) { // protect against: "Error: Could not call remote method // 'findInPage'. Check that the method signature is // correct. Underlying error: Error: Must provide a non-empty // search contentUnderlying stack: Error: Must provide a // non-empty search content" return; } const { ipcRenderer } = yield Promise.resolve().then(() => require('electron')); // Registering a callback handler ipcRenderer.once('found-in-page-result', (event, result) => __awaiter(this, void 0, void 0, function* () { if (this.state.isActive) { // we only need hack if we're doing a find as the user is typing and the options is defined for the converse if (!options) { this.hack(); } } this.setState(() => ({ result })); })); // this is where we call the electron API to initiate a new find ipcRenderer.send('synchronous-message', JSON.stringify({ operation: 'find-in-page', value: this._input.value, options })); }); } /** findInPage api seems to result in a loss of focus */ hack() { const v = this._input.value; this._input.value = ''; this._input.value = v; this._input.focus(); } doFocus() { if (this.state.isActive && this._input) { this._input.focus(); } } onClear() { return __awaiter(this, void 0, void 0, function* () { yield this.stopFindInPage(); if (this._input) { this._input.value = ''; } this.setState({ result: undefined, isActive: false, currentMatchIdx: 1 }); }); } onNext() { return __awaiter(this, void 0, void 0, function* () { // if statement blocks user from pressing next arrow if already on last result if (this.state.currentMatchIdx < this.state.result.matches) { yield this.findInPage({ forward: true, findNext: false }); this.setState(prevState => { const newCurrentResult = prevState.currentMatchIdx + 1; return { currentMatchIdx: newCurrentResult <= prevState.result.matches ? newCurrentResult : prevState.result.matches }; }); } }); } onPrevious() { return __awaiter(this, void 0, void 0, function* () { // if statement blocks user from pressing previous arrow if already on first result if (this.state.currentMatchIdx > this.state.result.matches - this.state.result.matches + 1) { yield this.findInPage({ forward: false, findNext: false }); this.setState(prevState => { const newCurrentResult = prevState.currentMatchIdx - 1; return { currentMatchIdx: newCurrentResult > 0 ? newCurrentResult : 1 }; }); } }); } resultsRender() { if (this.state.currentMatchIdx && this.state.result) { const curResultDisplay = this.state.currentMatchIdx.toString(); const totalResult = this.state.result.matches.toString(); return curResultDisplay + '/' + totalResult; } } render() { return _react.default.createElement(SearchInput, { id: "search-bar", className: 'kui--search ' + (!this.state.isActive ? 'hide' : ''), placeholder: "Find by name", value: this._input && this._input.value, "aria-label": "Search", onChange: this._onChange, onClear: this._onClear, spellCheck: false, resultsCount: this.resultsRender(), onNextClick: this._onNext, onPreviousClick: this._onPrevious, ref: this._onRef }); } } exports.default = Search;