pulsar-select-list
v1.4.1
Published
A general-purpose select list for use in Pulsar packages
Maintainers
Readme
pulsar-select-list
Fuzzy-searchable select list component. An etch component with keyboard/mouse navigation and built-in panel management.
Fork of atom-select-list.
Features
- Fuzzy filtering: Multiple algorithms including
command-tfor file paths. - Match highlighting: Built-in helpers for displaying match positions.
- Panel management: Show/hide/toggle with focus restoration.
- Lazy match indices: Match positions computed only when accessed.
- Diacritics support: Accent-insensitive matching option.
- Help mode: Toggle help content in the panel.
API
Constructor props
When creating a new instance of a select list, or when calling update on an existing one, you can supply a JavaScript object that can contain any of the following properties:
Required
elementForItem: (item: Object, options: Object) -> HTMLElement: a function that is called whenever an item needs to be displayed.options: Object:selected: Boolean: indicating whether item is selected or not.index: Number: item's index.filterKey: String|null: the text that was matched against (fromfilterKeyForItemor item itself).matchIndices: [Number]|null: lazy getter - character indices infilterKeythat matched the query. Only computed when accessed.
Optional
items: [Object]: an array containing the objects you want to show in the select list.className: String: CSS class name(s) to add to the select list element. Multiple classes can be space-separated.maxResults: Number: the number of maximum items that are shown.filter: (items: [Object], query: String) -> [Object]: a function that allows to decide which items to show whenever the query changes. By default, it uses Pulsar's built-in fuzzy matcher.filterKeyForItem: (item: Object) -> String: whenfilteris not provided, this function will be called to retrieve a string property on each item and that will be used to filter them.filterQuery: (query: String) -> String: a function that allows to apply a transformation to the user query and whose return value will be used to filter items.removeDiacritics: Boolean: whentrue, removes diacritical marks from both the query and item text before filtering, enabling accent-insensitive matching (e.g., "cafe" matches "café").filterScoreModifier: (score: Number, item: Object) -> Number: a function to modify the fuzzy match score for each item. Useful for applying custom ranking factors (e.g., boosting by recency or proximity).algorithm: String: the fuzzy matching algorithm to use. Options:'fuzzaldrin'(default),'command-t'(path-aware, better for file paths).numThreads: Number: number of threads for parallel matching. Defaults to 80% of available CPUs.maxGap: Number: maximum gap between consecutive matched characters (only for'command-t'algorithm). Lower values require tighter matches. Defaults to infinite.query: String: a string that will replace the contents of the query editor.selectQuery: Boolean: a boolean indicating whether the query text should be selected or not.order: (item1: Object, item2: Object) -> Number: a function that allows to change the order in which items are shown.emptyMessage: String: a string shown when the list is empty.errorMessage: String: a string that needs to be set when you want to notify the user that an error occurred.infoMessage: String: a string that needs to be set when you want to provide some information to the user.helpMessage: String|Array: content to display when help is toggled. Can be a string or JSX array for rich formatting.helpMarkdown: String: markdown content to display when help is toggled. Rendered using Pulsar's built-in markdown renderer.loadingMessage: String: a string that needs to be set when you are loading items in the background.loadingSpinner: Boolean: show spinner next to loading message.loadingBadge: String/Number: a string or number that needs to be set when the progress status changes.itemsClassList: [String]: an array of strings that will be added as class names to the items element.initialSelectionIndex: Number: the index of the item to initially select; defaults to0.placeholderText: String: placeholder text to display in the query editor when empty.skipCommandsRegistration: Boolean: whentrue, skips registering default keyboard commands.
Registered commands
By default, the component registers these commands on its element:
core:move-up/core:move-down: Navigate itemscore:move-to-top/core:move-to-bottom: Jump to first/last itemcore:confirm: Confirm selectioncore:cancel: Cancel selectionselect-list:help: Toggle help message visibility (requireshelpMessageorhelpMarkdown)
Callbacks
didChangeQuery: (query: String) -> Void: called when the query changes.didChangeSelection: (item: Object) -> Void: called when the selected item changes.didConfirmSelection: (item: Object) -> Void: called when the user clicks or presses Enter on an item.didConfirmEmptySelection: () -> Void: called when the user presses Enter but the list is empty.didCancelSelection: () -> Void: called when the user presses Esc or the list loses focus.willShow: () -> Void: called when transitioning from hidden to visible, useful for data preparation.
Instance properties
processedQuery: String: The cached result ofgetFilterQuery(), updated after each query change. Useful inelementForItemto avoid callinggetFilterQuery()multiple times.selectionIndex: Number|undefined: The index of the currently selected item, orundefinedif nothing is selected.refs.queryEditor: The underlying TextEditor component for the query input.
Instance methods
Panel management
show(): Shows the select list as a modal panel and focuses the query editor. CallswillShowcallback if provided.hide(): Hides the panel and restores focus to the previously focused element.toggle(): Toggles the visibility of the panel.isVisible(): Returnstrueif the panel is currently visible.isHelpMode(): Returnstrueif help is currently displayed.toggleHelp(): Toggles help message visibility. Only works ifhelpMessageis set.hideHelp(): Hides help message if currently shown.
Other methods
focus(): Focuses the query editor.reset(): Clears the query editor text.destroy(): Disposes of the component and cleans up resources.update(props): Updates the component with new props.getQuery(): Returns the current query string.getFilterKey(item): Returns the filter key string for an item (from cache,filterKeyForItem, or item itself).getMatchIndices(item, filterKey?): Returns match indices for an item, computing lazily if needed. Prefer usingoptions.matchIndicesinelementForIteminstead.getFilterQuery(): Returns the filtered query string (appliesfilterQuerytransformation).setQueryFromSelection(): Sets the query text from the active editor's selection. Returnstrueif successful,falseif no editor, no selection, or selection contains newlines.getSelectedItem(): Returns the currently selected item.selectPrevious(): Selects the previous item.selectNext(): Selects the next item.selectFirst(): Selects the first item.selectLast(): Selects the last item.selectNone(): Deselects all items.selectIndex(index): Selects the item at the given index.selectItem(item): Selects the given item.confirmSelection(): Confirms the current selection.cancelSelection(): Cancels the selection.
Static methods
SelectListView.getMatchIndices(text, query, options)
Computes fuzzy match indices for a text against a query. Useful outside of elementForItem context.
const { getMatchIndices } = require("pulsar-select-list");
const indices = getMatchIndices("MyComponent.js", "mcjs");
// => [0, 2, 11, 12] or null if no match
// With diacritics removal
const indices = getMatchIndices("café", "cafe", { removeDiacritics: true });
// => [0, 1, 2, 3]SelectListView.highlightMatches(text, matchIndices, options)
Creates a DocumentFragment with highlighted match characters.
// In elementForItem, use options.matchIndices (lazy getter):
elementForItem: (item, { filterKey, matchIndices }) => {
const li = document.createElement("li");
li.appendChild(SelectListView.highlightMatches(filterKey, matchIndices));
return li;
}SelectListView.removeDiacritics(str)
Removes diacritical marks (accents) from a string.
SelectListView.removeDiacritics("café"); // => 'cafe'SelectListView.createTwoLineItem(options)
Creates a two-line list item element with primary and optional secondary lines.
elementForItem: (item, { filterKey, matchIndices }) => {
return SelectListView.createTwoLineItem({
primary: SelectListView.highlightMatches(filterKey, matchIndices),
secondary: item.description,
icon: ["icon-file-text"],
});
}Example
const SelectListView = require("pulsar-select-list");
const fs = require("fs");
const path = require("path");
class MyFileList {
constructor() {
this.selectList = new SelectListView({
className: "my-package my-file-list",
items: [],
filterKeyForItem: (item) => item.name,
emptyMessage: "No files found",
willShow: () => {
this.loadFiles();
},
elementForItem: (item, { index, filterKey, matchIndices }) => {
const li = document.createElement("li");
li.appendChild(SelectListView.highlightMatches(filterKey, matchIndices));
return li;
},
didConfirmSelection: (item) => {
atom.workspace.open(item.path);
this.selectList.hide();
},
didCancelSelection: () => {
this.selectList.hide();
},
});
}
toggle() {
this.selectList.toggle();
}
destroy() {
this.selectList.destroy();
}
}Contributing
Got ideas to make this package better, found a bug, or want to help add new features? Just drop your thoughts on GitHub — any feedback's welcome!
