UNPKG

@phosphor/widgets

Version:
1,041 lines (1,040 loc) 38.2 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); } return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); /*----------------------------------------------------------------------------- | Copyright (c) 2014-2017, PhosphorJS Contributors | | Distributed under the terms of the BSD 3-Clause License. | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ var algorithm_1 = require("@phosphor/algorithm"); var coreutils_1 = require("@phosphor/coreutils"); var commands_1 = require("@phosphor/commands"); var domutils_1 = require("@phosphor/domutils"); var virtualdom_1 = require("@phosphor/virtualdom"); var widget_1 = require("./widget"); /** * A widget which displays command items as a searchable palette. */ var CommandPalette = /** @class */ (function (_super) { __extends(CommandPalette, _super); /** * Construct a new command palette. * * @param options - The options for initializing the palette. */ function CommandPalette(options) { var _this = _super.call(this, { node: Private.createNode() }) || this; _this._activeIndex = -1; _this._items = []; _this._results = null; _this.addClass('p-CommandPalette'); _this.setFlag(widget_1.Widget.Flag.DisallowLayout); _this.commands = options.commands; _this.renderer = options.renderer || CommandPalette.defaultRenderer; _this.commands.commandChanged.connect(_this._onGenericChange, _this); _this.commands.keyBindingChanged.connect(_this._onGenericChange, _this); return _this; } /** * Dispose of the resources held by the widget. */ CommandPalette.prototype.dispose = function () { this._items.length = 0; this._results = null; _super.prototype.dispose.call(this); }; Object.defineProperty(CommandPalette.prototype, "searchNode", { /** * The command palette search node. * * #### Notes * This is the node which contains the search-related elements. */ get: function () { return this.node.getElementsByClassName('p-CommandPalette-search')[0]; }, enumerable: true, configurable: true }); Object.defineProperty(CommandPalette.prototype, "inputNode", { /** * The command palette input node. * * #### Notes * This is the actual input node for the search area. */ get: function () { return this.node.getElementsByClassName('p-CommandPalette-input')[0]; }, enumerable: true, configurable: true }); Object.defineProperty(CommandPalette.prototype, "contentNode", { /** * The command palette content node. * * #### Notes * This is the node which holds the command item nodes. * * Modifying this node directly can lead to undefined behavior. */ get: function () { return this.node.getElementsByClassName('p-CommandPalette-content')[0]; }, enumerable: true, configurable: true }); Object.defineProperty(CommandPalette.prototype, "items", { /** * A read-only array of the command items in the palette. */ get: function () { return this._items; }, enumerable: true, configurable: true }); /** * Add a command item to the command palette. * * @param options - The options for creating the command item. * * @returns The command item added to the palette. */ CommandPalette.prototype.addItem = function (options) { // Create a new command item for the options. var item = Private.createItem(this.commands, options); // Add the item to the array. this._items.push(item); // Refresh the search results. this.refresh(); // Return the item added to the palette. return item; }; /** * Remove an item from the command palette. * * @param item - The item to remove from the palette. * * #### Notes * This is a no-op if the item is not in the palette. */ CommandPalette.prototype.removeItem = function (item) { this.removeItemAt(this._items.indexOf(item)); }; /** * Remove the item at a given index from the command palette. * * @param index - The index of the item to remove. * * #### Notes * This is a no-op if the index is out of range. */ CommandPalette.prototype.removeItemAt = function (index) { // Remove the item from the array. var item = algorithm_1.ArrayExt.removeAt(this._items, index); // Bail if the index is out of range. if (!item) { return; } // Refresh the search results. this.refresh(); }; /** * Remove all items from the command palette. */ CommandPalette.prototype.clearItems = function () { // Bail if there is nothing to remove. if (this._items.length === 0) { return; } // Clear the array of items. this._items.length = 0; // Refresh the search results. this.refresh(); }; /** * Clear the search results and schedule an update. * * #### Notes * This should be called whenever the search results of the palette * should be updated. * * This is typically called automatically by the palette as needed, * but can be called manually if the input text is programatically * changed. * * The rendered results are updated asynchronously. */ CommandPalette.prototype.refresh = function () { this._results = null; this.update(); }; /** * Handle the DOM events for the command palette. * * @param event - The DOM event sent to the command palette. * * #### Notes * This method implements the DOM `EventListener` interface and is * called in response to events on the command palette's DOM node. * It should not be called directly by user code. */ CommandPalette.prototype.handleEvent = function (event) { switch (event.type) { case 'click': this._evtClick(event); break; case 'keydown': this._evtKeyDown(event); break; case 'input': this.refresh(); break; case 'focus': case 'blur': this._toggleFocused(); break; } }; /** * A message handler invoked on a `'before-attach'` message. */ CommandPalette.prototype.onBeforeAttach = function (msg) { this.node.addEventListener('click', this); this.node.addEventListener('keydown', this); this.node.addEventListener('input', this); this.node.addEventListener('focus', this, true); this.node.addEventListener('blur', this, true); }; /** * A message handler invoked on an `'after-detach'` message. */ CommandPalette.prototype.onAfterDetach = function (msg) { this.node.removeEventListener('click', this); this.node.removeEventListener('keydown', this); this.node.removeEventListener('input', this); this.node.removeEventListener('focus', this, true); this.node.removeEventListener('blur', this, true); }; /** * A message handler invoked on an `'activate-request'` message. */ CommandPalette.prototype.onActivateRequest = function (msg) { if (this.isAttached) { var input = this.inputNode; input.focus(); input.select(); } }; /** * A message handler invoked on an `'update-request'` message. */ CommandPalette.prototype.onUpdateRequest = function (msg) { // Fetch the current query text and content node. var query = this.inputNode.value; var contentNode = this.contentNode; // Ensure the search results are generated. var results = this._results; if (!results) { // Generate and store the new search results. results = this._results = Private.search(this._items, query); // Reset the active index. this._activeIndex = (query ? algorithm_1.ArrayExt.findFirstIndex(results, Private.canActivate) : -1); } // If there is no query and no results, clear the content. if (!query && results.length === 0) { virtualdom_1.VirtualDOM.render(null, contentNode); return; } // If the is a query but no results, render the empty message. if (query && results.length === 0) { var content_1 = this.renderer.renderEmptyMessage({ query: query }); virtualdom_1.VirtualDOM.render(content_1, contentNode); return; } // Create the render content for the search results. var renderer = this.renderer; var activeIndex = this._activeIndex; var content = new Array(results.length); for (var i = 0, n = results.length; i < n; ++i) { var result = results[i]; if (result.type === 'header') { var indices = result.indices; var category = result.category; content[i] = renderer.renderHeader({ category: category, indices: indices }); } else { var item = result.item; var indices = result.indices; var active = i === activeIndex; content[i] = renderer.renderItem({ item: item, indices: indices, active: active }); } } // Render the search result content. virtualdom_1.VirtualDOM.render(content, contentNode); // Adjust the scroll position as needed. if (activeIndex < 0 || activeIndex >= results.length) { contentNode.scrollTop = 0; } else { var element = contentNode.children[activeIndex]; domutils_1.ElementExt.scrollIntoViewIfNeeded(contentNode, element); } }; /** * Handle the `'click'` event for the command palette. */ CommandPalette.prototype._evtClick = function (event) { // Bail if the click is not the left button. if (event.button !== 0) { return; } // Find the index of the item which was clicked. var index = algorithm_1.ArrayExt.findFirstIndex(this.contentNode.children, function (node) { return node.contains(event.target); }); // Bail if the click was not on an item. if (index === -1) { return; } // Kill the event when a content item is clicked. event.preventDefault(); event.stopPropagation(); // Execute the item if possible. this._execute(index); }; /** * Handle the `'keydown'` event for the command palette. */ CommandPalette.prototype._evtKeyDown = function (event) { if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { return; } switch (event.keyCode) { case 13: // Enter event.preventDefault(); event.stopPropagation(); this._execute(this._activeIndex); break; case 38: // Up Arrow event.preventDefault(); event.stopPropagation(); this._activatePreviousItem(); break; case 40: // Down Arrow event.preventDefault(); event.stopPropagation(); this._activateNextItem(); break; } }; /** * Activate the next enabled command item. */ CommandPalette.prototype._activateNextItem = function () { // Bail if there are no search results. if (!this._results || this._results.length === 0) { return; } // Find the next enabled item index. var ai = this._activeIndex; var n = this._results.length; var start = ai < n - 1 ? ai + 1 : 0; var stop = start === 0 ? n - 1 : start - 1; this._activeIndex = algorithm_1.ArrayExt.findFirstIndex(this._results, Private.canActivate, start, stop); // Schedule an update of the items. this.update(); }; /** * Activate the previous enabled command item. */ CommandPalette.prototype._activatePreviousItem = function () { // Bail if there are no search results. if (!this._results || this._results.length === 0) { return; } // Find the previous enabled item index. var ai = this._activeIndex; var n = this._results.length; var start = ai <= 0 ? n - 1 : ai - 1; var stop = start === n - 1 ? 0 : start + 1; this._activeIndex = algorithm_1.ArrayExt.findLastIndex(this._results, Private.canActivate, start, stop); // Schedule an update of the items. this.update(); }; /** * Execute the command item at the given index, if possible. */ CommandPalette.prototype._execute = function (index) { // Bail if there are no search results. if (!this._results) { return; } // Bail if the index is out of range. var part = this._results[index]; if (!part) { return; } // Update the search text if the item is a header. if (part.type === 'header') { var input = this.inputNode; input.value = part.category.toLowerCase() + " "; input.focus(); this.refresh(); return; } // Bail if item is not enabled. if (!part.item.isEnabled) { return; } // Execute the item. this.commands.execute(part.item.command, part.item.args); // Clear the query text. this.inputNode.value = ''; // Refresh the search results. this.refresh(); }; /** * Toggle the focused modifier based on the input node focus state. */ CommandPalette.prototype._toggleFocused = function () { var focused = document.activeElement === this.inputNode; this.toggleClass('p-mod-focused', focused); }; /** * A signal handler for generic command changes. */ CommandPalette.prototype._onGenericChange = function () { this.refresh(); }; return CommandPalette; }(widget_1.Widget)); exports.CommandPalette = CommandPalette; /** * The namespace for the `CommandPalette` class statics. */ (function (CommandPalette) { /** * The default implementation of `IRenderer`. */ var Renderer = /** @class */ (function () { function Renderer() { } /** * Render the virtual element for a command palette header. * * @param data - The data to use for rendering the header. * * @returns A virtual element representing the header. */ Renderer.prototype.renderHeader = function (data) { var content = this.formatHeader(data); return virtualdom_1.h.li({ className: 'p-CommandPalette-header' }, content); }; /** * Render the virtual element for a command palette item. * * @param data - The data to use for rendering the item. * * @returns A virtual element representing the item. */ Renderer.prototype.renderItem = function (data) { var className = this.createItemClass(data); var dataset = this.createItemDataset(data); return (virtualdom_1.h.li({ className: className, dataset: dataset }, this.renderItemIcon(data), this.renderItemContent(data), this.renderItemShortcut(data))); }; /** * Render the empty results message for a command palette. * * @param data - The data to use for rendering the message. * * @returns A virtual element representing the message. */ Renderer.prototype.renderEmptyMessage = function (data) { var content = this.formatEmptyMessage(data); return virtualdom_1.h.li({ className: 'p-CommandPalette-emptyMessage' }, content); }; /** * Render the icon for a command palette item. * * @param data - The data to use for rendering the icon. * * @returns A virtual element representing the icon. */ Renderer.prototype.renderItemIcon = function (data) { var className = this.createIconClass(data); return virtualdom_1.h.div({ className: className }, data.item.iconLabel); }; /** * Render the content for a command palette item. * * @param data - The data to use for rendering the content. * * @returns A virtual element representing the content. */ Renderer.prototype.renderItemContent = function (data) { return (virtualdom_1.h.div({ className: 'p-CommandPalette-itemContent' }, this.renderItemLabel(data), this.renderItemCaption(data))); }; /** * Render the label for a command palette item. * * @param data - The data to use for rendering the label. * * @returns A virtual element representing the label. */ Renderer.prototype.renderItemLabel = function (data) { var content = this.formatItemLabel(data); return virtualdom_1.h.div({ className: 'p-CommandPalette-itemLabel' }, content); }; /** * Render the caption for a command palette item. * * @param data - The data to use for rendering the caption. * * @returns A virtual element representing the caption. */ Renderer.prototype.renderItemCaption = function (data) { var content = this.formatItemCaption(data); return virtualdom_1.h.div({ className: 'p-CommandPalette-itemCaption' }, content); }; /** * Render the shortcut for a command palette item. * * @param data - The data to use for rendering the shortcut. * * @returns A virtual element representing the shortcut. */ Renderer.prototype.renderItemShortcut = function (data) { var content = this.formatItemShortcut(data); return virtualdom_1.h.div({ className: 'p-CommandPalette-itemShortcut' }, content); }; /** * Create the class name for the command palette item. * * @param data - The data to use for the class name. * * @returns The full class name for the command palette item. */ Renderer.prototype.createItemClass = function (data) { // Set up the initial class name. var name = 'p-CommandPalette-item'; // Add the boolean state classes. if (!data.item.isEnabled) { name += ' p-mod-disabled'; } if (data.item.isToggled) { name += ' p-mod-toggled'; } if (data.active) { name += ' p-mod-active'; } // Add the extra class. var extra = data.item.className; if (extra) { name += " " + extra; } // Return the complete class name. return name; }; /** * Create the dataset for the command palette item. * * @param data - The data to use for creating the dataset. * * @returns The dataset for the command palette item. */ Renderer.prototype.createItemDataset = function (data) { return __assign({}, data.item.dataset, { command: data.item.command }); }; /** * Create the class name for the command item icon. * * @param data - The data to use for the class name. * * @returns The full class name for the item icon. */ Renderer.prototype.createIconClass = function (data) { var name = 'p-CommandPalette-itemIcon'; var extra = data.item.iconClass; return extra ? name + " " + extra : name; }; /** * Create the render content for the header node. * * @param data - The data to use for the header content. * * @returns The content to add to the header node. */ Renderer.prototype.formatHeader = function (data) { if (!data.indices || data.indices.length === 0) { return data.category; } return algorithm_1.StringExt.highlight(data.category, data.indices, virtualdom_1.h.mark); }; /** * Create the render content for the empty message node. * * @param data - The data to use for the empty message content. * * @returns The content to add to the empty message node. */ Renderer.prototype.formatEmptyMessage = function (data) { return "No commands found that match '" + data.query + "'"; }; /** * Create the render content for the item shortcut node. * * @param data - The data to use for the shortcut content. * * @returns The content to add to the shortcut node. */ Renderer.prototype.formatItemShortcut = function (data) { var kb = data.item.keyBinding; return kb ? kb.keys.map(commands_1.CommandRegistry.formatKeystroke).join(', ') : null; }; /** * Create the render content for the item label node. * * @param data - The data to use for the label content. * * @returns The content to add to the label node. */ Renderer.prototype.formatItemLabel = function (data) { if (!data.indices || data.indices.length === 0) { return data.item.label; } return algorithm_1.StringExt.highlight(data.item.label, data.indices, virtualdom_1.h.mark); }; /** * Create the render content for the item caption node. * * @param data - The data to use for the caption content. * * @returns The content to add to the caption node. */ Renderer.prototype.formatItemCaption = function (data) { return data.item.caption; }; return Renderer; }()); CommandPalette.Renderer = Renderer; /** * The default `Renderer` instance. */ CommandPalette.defaultRenderer = new Renderer(); })(CommandPalette = exports.CommandPalette || (exports.CommandPalette = {})); exports.CommandPalette = CommandPalette; /** * The namespace for the module implementation details. */ var Private; (function (Private) { /** * Create the DOM node for a command palette. */ function createNode() { var node = document.createElement('div'); var search = document.createElement('div'); var wrapper = document.createElement('div'); var input = document.createElement('input'); var content = document.createElement('ul'); search.className = 'p-CommandPalette-search'; wrapper.className = 'p-CommandPalette-wrapper'; input.className = 'p-CommandPalette-input'; content.className = 'p-CommandPalette-content'; input.spellcheck = false; wrapper.appendChild(input); search.appendChild(wrapper); node.appendChild(search); node.appendChild(content); return node; } Private.createNode = createNode; /** * Create a new command item from a command registry and options. */ function createItem(commands, options) { return new CommandItem(commands, options); } Private.createItem = createItem; /** * Search an array of command items for fuzzy matches. */ function search(items, query) { // Fuzzy match the items for the query. var scores = matchItems(items, query); // Sort the items based on their score. scores.sort(scoreCmp); // Create the results for the search. return createResults(scores); } Private.search = search; /** * Test whether a result item can be activated. */ function canActivate(result) { return result.type === 'item' && result.item.isEnabled; } Private.canActivate = canActivate; /** * Normalize a category for a command item. */ function normalizeCategory(category) { return category.trim().replace(/\s+/g, ' '); } /** * Normalize the query text for a fuzzy search. */ function normalizeQuery(text) { return text.replace(/\s+/g, '').toLowerCase(); } /** * Perform a fuzzy match on an array of command items. */ function matchItems(items, query) { // Normalize the query text to lower case with no whitespace. query = normalizeQuery(query); // Create the array to hold the scores. var scores = []; // Iterate over the items and match against the query. for (var i = 0, n = items.length; i < n; ++i) { // Ignore items which are not visible. var item = items[i]; if (!item.isVisible) { continue; } // If the query is empty, all items are matched by default. if (!query) { scores.push({ matchType: 3 /* Default */, categoryIndices: null, labelIndices: null, score: 0, item: item }); continue; } // Run the fuzzy search for the item and query. var score = fuzzySearch(item, query); // Ignore the item if it is not a match. if (!score) { continue; } // Penalize disabled items. // TODO - push disabled items all the way down in sort cmp? if (!item.isEnabled) { score.score += 1000; } // Add the score to the results. scores.push(score); } // Return the final array of scores. return scores; } /** * Perform a fuzzy search on a single command item. */ function fuzzySearch(item, query) { // Create the source text to be searched. var category = item.category.toLowerCase(); var label = item.label.toLowerCase(); var source = category + " " + label; // Set up the match score and indices array. var score = Infinity; var indices = null; // The regex for search word boundaries var rgx = /\b\w/g; // Search the source by word boundary. while (true) { // Find the next word boundary in the source. var rgxMatch = rgx.exec(source); // Break if there is no more source context. if (!rgxMatch) { break; } // Run the string match on the relevant substring. var match = algorithm_1.StringExt.matchSumOfDeltas(source, query, rgxMatch.index); // Break if there is no match. if (!match) { break; } // Update the match if the score is better. if (match && match.score <= score) { score = match.score; indices = match.indices; } } // Bail if there was no match. if (!indices || score === Infinity) { return null; } // Compute the pivot index between category and label text. var pivot = category.length + 1; // Find the slice index to separate matched indices. var j = algorithm_1.ArrayExt.lowerBound(indices, pivot, function (a, b) { return a - b; }); // Extract the matched category and label indices. var categoryIndices = indices.slice(0, j); var labelIndices = indices.slice(j); // Adjust the label indices for the pivot offset. for (var i = 0, n = labelIndices.length; i < n; ++i) { labelIndices[i] -= pivot; } // Handle a pure label match. if (categoryIndices.length === 0) { return { matchType: 0 /* Label */, categoryIndices: null, labelIndices: labelIndices, score: score, item: item }; } // Handle a pure category match. if (labelIndices.length === 0) { return { matchType: 1 /* Category */, categoryIndices: categoryIndices, labelIndices: null, score: score, item: item }; } // Handle a split match. return { matchType: 2 /* Split */, categoryIndices: categoryIndices, labelIndices: labelIndices, score: score, item: item }; } /** * A sort comparison function for a match score. */ function scoreCmp(a, b) { // First compare based on the match type var m1 = a.matchType - b.matchType; if (m1 !== 0) { return m1; } // Otherwise, compare based on the match score. var d1 = a.score - b.score; if (d1 !== 0) { return d1; } // Find the match index based on the match type. var i1 = 0; var i2 = 0; switch (a.matchType) { case 0 /* Label */: i1 = a.labelIndices[0]; i2 = b.labelIndices[0]; break; case 1 /* Category */: case 2 /* Split */: i1 = a.categoryIndices[0]; i2 = b.categoryIndices[0]; break; } // Compare based on the match index. if (i1 !== i2) { return i1 - i2; } // Otherwise, compare by category. var d2 = a.item.category.localeCompare(b.item.category); if (d2 !== 0) { return d2; } // Otherwise, compare by rank. var r1 = a.item.rank; var r2 = b.item.rank; if (r1 !== r2) { return r1 < r2 ? -1 : 1; // Infinity safe } // Finally, compare by label. return a.item.label.localeCompare(b.item.label); } /** * Create the results from an array of sorted scores. */ function createResults(scores) { // Set up an array to track which scores have been visited. var visited = new Array(scores.length); algorithm_1.ArrayExt.fill(visited, false); // Set up the search results array. var results = []; // Iterate over each score in the array. for (var i = 0, n = scores.length; i < n; ++i) { // Ignore a score which has already been processed. if (visited[i]) { continue; } // Extract the current item and indices. var _a = scores[i], item = _a.item, categoryIndices = _a.categoryIndices; // Extract the category for the current item. var category = item.category; // Add the header result for the category. results.push({ type: 'header', category: category, indices: categoryIndices }); // Find the rest of the scores with the same category. for (var j = i; j < n; ++j) { // Ignore a score which has already been processed. if (visited[j]) { continue; } // Extract the data for the current score. var _b = scores[j], item_1 = _b.item, labelIndices = _b.labelIndices; // Ignore an item with a different category. if (item_1.category !== category) { continue; } // Create the item result for the score. results.push({ type: 'item', item: item_1, indices: labelIndices }); // Mark the score as processed. visited[j] = true; } } // Return the final results. return results; } /** * A concrete implementation of `CommandPalette.IItem`. */ var CommandItem = /** @class */ (function () { /** * Construct a new command item. */ function CommandItem(commands, options) { this._commands = commands; this.category = normalizeCategory(options.category); this.command = options.command; this.args = options.args || coreutils_1.JSONExt.emptyObject; this.rank = options.rank !== undefined ? options.rank : Infinity; } Object.defineProperty(CommandItem.prototype, "label", { /** * The display label for the command item. */ get: function () { return this._commands.label(this.command, this.args); }, enumerable: true, configurable: true }); Object.defineProperty(CommandItem.prototype, "iconClass", { /** * The icon class for the command item. */ get: function () { return this._commands.iconClass(this.command, this.args); }, enumerable: true, configurable: true }); Object.defineProperty(CommandItem.prototype, "iconLabel", { /** * The icon label for the command item. */ get: function () { return this._commands.iconLabel(this.command, this.args); }, enumerable: true, configurable: true }); Object.defineProperty(CommandItem.prototype, "caption", { /** * The display caption for the command item. */ get: function () { return this._commands.caption(this.command, this.args); }, enumerable: true, configurable: true }); Object.defineProperty(CommandItem.prototype, "className", { /** * The extra class name for the command item. */ get: function () { return this._commands.className(this.command, this.args); }, enumerable: true, configurable: true }); Object.defineProperty(CommandItem.prototype, "dataset", { /** * The dataset for the command item. */ get: function () { return this._commands.dataset(this.command, this.args); }, enumerable: true, configurable: true }); Object.defineProperty(CommandItem.prototype, "isEnabled", { /** * Whether the command item is enabled. */ get: function () { return this._commands.isEnabled(this.command, this.args); }, enumerable: true, configurable: true }); Object.defineProperty(CommandItem.prototype, "isToggled", { /** * Whether the command item is toggled. */ get: function () { return this._commands.isToggled(this.command, this.args); }, enumerable: true, configurable: true }); Object.defineProperty(CommandItem.prototype, "isVisible", { /** * Whether the command item is visible. */ get: function () { return this._commands.isVisible(this.command, this.args); }, enumerable: true, configurable: true }); Object.defineProperty(CommandItem.prototype, "keyBinding", { /** * The key binding for the command item. */ get: function () { var _a = this, command = _a.command, args = _a.args; return algorithm_1.ArrayExt.findLastValue(this._commands.keyBindings, function (kb) { return kb.command === command && coreutils_1.JSONExt.deepEqual(kb.args, args); }) || null; }, enumerable: true, configurable: true }); return CommandItem; }()); })(Private || (Private = {}));