import { AssistedSearchOptions, DropdownOption, Facet, GetDropdown, InitialValues, Nullable, OptionTemplate, SearchEntry, Value } from '../types'; import { Dropdown, Entry, Input } from './ComponentStores'; import { AssistedSearchType } from './AssistedSearchType'; /** * Represents the state of the search bar */ export default class AssistedSearchStore { /** * The default options when initializing the store. */ static DEFAULT_OPTIONS: AssistedSearchOptions; /** Configures the behavior for this store */ options: AssistedSearchOptions; /** Represents the state of the "main" input */ input: Input; /** Represents the state of the dropdown component */ dropdown: Dropdown; /** * The selected entries in the input. * When in single mode, it only ever has length of 1, and used in the UI if the the value has a label */ entries: Entry[]; /** Indicates which input is currently focused */ activeElement: Input | null; /** Tracking current dropdown lookup to ignore previous promises */ private _currentLookup; private _lastValue; /** Internal use for async tracking of a pending blur event */ _pendingBlur: boolean; private _changeSet; /** * @param {AssistedSearchOptions} options * @param {InitialValues} initialValues? */ constructor(options?: AssistedSearchOptions, initialValues?: InitialValues); /** * Set the value of an input (the main input if no second argument passed) * @param value * @param entry */ setInput(value: string, entry?: Entry | number): void; /** * Focus the input of an entry (or just the main input if is nothing passed). * @param entry * @param clearSelections if true, clear the selectionStart/End * @param start set the selectionStart value * @param end set the selectionEnd value * @param updateDropdown if false, ignore this focus event */ focus(entry?: Nullable, clearSelections?: boolean, start?: number, end?: number, updateDropdown?: boolean): AssistedSearchStore; /** convenience to get an Entry by its value or array index */ private _entry; /** Returns either the input of the entry, or the main input if null or undefinde */ private _input; /** * Bring focus to the main input or an input in one of the entries * @param input * @param clearSelections * @param start * @param end * @param updateDropdown if false, ignore this focus event */ focusInput: (input: Input, clearSelections?: boolean, start?: number | undefined, end?: number | undefined, updateDropdown?: boolean | undefined) => void; blur: () => void; /** Returns true if the component is focused */ isFocused(): boolean; /** * Returns true if the given entry (or the main input if not present) is focused * @param entry the entry to check, if null/undefined is passed, will return true if the main input is active */ isActiveEntry(entry?: Entry | number): boolean; setInputSelection(start: number | null, end: number | null, input?: Nullable): void; /** * A convenience to set the input selection based on a DOM input element. * * @param el * @param entry */ setInputSelectionFor(el: HTMLInputElement, entry?: Entry): void; /** * Handles the state change for the expected behavior of the "home" key * * NOTE: Assumes the input is focused */ moveToHome(): true | void; /** * Handles the state change for the expected behavior of the "end" key * * NOTE: Assumes the input is focused */ moveToEnd(): true | void; /** * React to the text cursor moving left or right. The selectionStart/End of the active input MUST be updated first. * Returns true if an action precludes the default browser behaviour * * NOTE: Assumes the input is focused */ moveLeft(): true | void; private hasItems; /** * React to the text cursor moving right. The selectionStart/End of the focused input must be updated first. * @returns true if the state behavior precludes the default browser behavior * * NOTE: Assumes the input is focused */ moveRight(): true | void; /** Maintains the event listeners */ private _handlers; private _dispatch; /** * Add a listener to the store for an event. * @param {string} evt * @param {Function} handler */ addListener(evt: string, handler: Function): void; /** * Remove a function from the event listeners * @param {string} evt * @param {Function} handler */ removeListener(evt: string, handler: Function): void; /** isUpdating lock */ private _u; /** isUpdatingDropdown lock */ private _ud; /** Is true if we're suppressing change events */ private _c?; /** True if next update should trigger a submit event */ private _s; private _b; /** Dispatch the update event to any listeners. Note that additional changes will trigger a secondary update event */ private _update; /** * Returns the option template from the config options, if there is one. * @returns {OptionTemplate | null} * TODO: rename OptionTemplate */ getOptionTemplate(): OptionTemplate | null; /** Returns the custom for the current state of the store, if there is one */ getCustomDropdown(): GetDropdown | null; /** Returns the currently focused entry, if there is one */ getActiveEntry(): Entry | undefined; /** Returns the active entry index, or -1 if none are active/focused */ getActiveEntryIdx(): number; /** Returns the facet of the active entry, if there is one */ getActiveFacet(): Facet | null; /** Returns activeFacet().value, if there is one (faceted mode only) */ getActiveFacetName(): string | null; /** * Returns the current placeholder text. This could be a string, react element, null (if there is input), or anything * really. * * @returns {any} */ placeholder(): any; /** Returns the entries */ getEntries(): SearchEntry[]; /** Returns the current input value */ getActiveInput(): string | null; /** Reset selection states after blur */ resetSelections(): void; /** * Returns true if we're auto selecting the first value. * @returns {boolean} * @private */ private _autoSelect; /** Setting the items in dropdown for either facet or value */ private setDropdownItems; private _setDropdownContent; /** * Returns true if the item at itemIndex is a selected item in the dropdown * @param {number} item * @returns {boolean} */ isSelectedItem(item: DropdownOption | number): boolean; clearSelectedItems(): void; /** * Returns true if the given entry index is currently selected. * @param {number} entry * @returns {boolean} */ isSelectedEntry(entry: Entry | number): boolean; /** * Set the selected items in the dropdown by their index position * @param {number[]} items */ setSelectedItems(items: number[]): void; /** * Set the selected items in the dropdown by their index position * @param {DropdownOption} item * @param submit * @param closeDropdown */ setSelectedItem(item: number, submit?: boolean, closeDropdown?: boolean): void; /** * Select the next item in the dropdown, wrapping to the top if necessary. */ selectNextItem(offset?: number): void; /** * Select dropdown items (or a single dropdown item) by their exact position, useful for programmatic use. * @param {number[]} items * @param closeDropdown if true, always closes the dropdown after the action completes * @param submit if true, fires a submit event */ selectExact(items: number[] | number, closeDropdown?: boolean, submit?: boolean): void; /** * Select the previous (above) item in the dropdown, wrapping to the bottom if necessary. */ selectPrevItem(offset?: number): void; /** * Select the given entries * @param {number[]} entries */ selectEntries(entries: Entry[]): void; deselectEntries(): void; /** * Returns true if items are selected in the dropdown * @returns {boolean} */ hasSelectedItems(): boolean; /** * Returns the minimum length of the input before the dropdown activates. * @returns {number} */ private minLength; /** * Perform a delete of entries, or the active facet for the main input, if needed. selectionStart/End must be updated * before calling. (handles action for backspace key in UI) * * NOTE: assumes component is focused */ deleteBehind(): true | void; /** * Perform a delete of entries in front of the cursor. selectionStart/End must be updated before calling. * (handles action for delete key in UI) * * NOTE: assumes component is focused */ deleteAhead(): true | void; deleteEntries(entries: Array): void; getSelectedEntries(): Entry[]; clearCurrentFacet(): void; /** Removes the entries that are currently selected */ deleteSelectedEntries(): void; private _deleteSelectedEntries; /** Returns the single value represented by the assisted search component. */ getSingleValue(): Value; /** Returns true if we're currently displaying the dropdown */ showingDropdown(): boolean; /** * Change the value of an existing entry. * @param entry * @param value */ setEntryValue(entry: Entry | number, value: string | Value): void; /** * Returns the value appropriate for this search type. * @returns {Value | Value[] | SearchEntry[]} */ getValueForType(): Value | Value[] | SearchEntry[]; /** * Set the value for the single-value component * @param value */ setValue(value: string | Value | null): void; /** * Set the input (and entry) using the input. Works a little differently than multi/faceted since the input takes the * place of the entry. * * @param value */ setSingleValue(value: string): void; /** Make changes without triggering a change event */ noChange(fn: Function): void; /** Change the value of the main input */ setEntries(entries?: SearchEntry[]): void; /** * Returns the values for this multivalue component * @returns {Value[]} */ getValues(): Value[]; /** * Remove an entry from the list, by its actual value. * * @param {SearchEntry} entry * @param {boolean} [deleteForward] if set to true, and this is the active entry, focus will move to the next entry * instead of the previous one. */ removeEntry: (entry: Entry, deleteForward?: boolean | undefined) => void; clearDropdown(): void; /** * Add the facet value, either from the selection or from the input, if applicable, or sets the * standalone value determined by isFacet | options.isStandaloneValue() * @returns true if an entry was added as a result (implies we need to submit). If a string, that is the facet candidate set, which * implies we NEVER submit * @private */ private _setCandidateFacet; /** * Update the dropdown state based on input, currentFacet, etc * @param force set to true to run regardless of if another updateDropdown call is pending * @private */ updateDropdown(force?: boolean): void; /** * Add either the selected value(s) or the value in the input based on the context. * Only applicable in faceted or multiple mode * @private */ private _addValues; private _getRewrittenValue; private _getRewrittenFacet; private _addEntry; /** Cancel the current facet, if there is one */ removeCurrentFacet(): void; /** Delete the previous entry from we are currently at */ deletePrevEntry(): void; /** * Enter a value into the active input and select it, this is the "manual" version of setSelection, (which works with dropdown values) * @param value * @param closeDropdown * @param submit */ selectValue(value: string | Value, closeDropdown?: boolean, submit?: boolean): void; /** * Enter the current selection of the dropdown into a value, or the new current facet, if appropriate. * @param closeDropdown * @param submit */ setSelection(closeDropdown?: boolean, submit?: boolean): void; /** * Enter the current selection of the dropdown into a value, or the new current facet, if appropriate. * @param selected * @param closeDropdown * @param submit */ private _select; /** Fire a submission event after the current transaction terminates */ submit(): void; private _removeEntries; setValueAndEntries(value: Nullable, entries: Nullable>, silent?: boolean): void; private _setValue; /** * Clears the selected text state of the currently focused input * @param input */ clearSelection(input: Input): void; /** * Run a series of changes to the store, then commit the result as an update to the component. Will not trigger a * double update if the upper layer is also inside of an action. * @param fn * @param updateDropdown */ runInAction(fn: (...args: any[]) => T, updateDropdown?: boolean): T; /** * Returns true if the given facet supports custom values. If nothing is passed, * returns the option passed in (or the default). * * @param facet */ customValues(facet: Nullable): boolean; type(): AssistedSearchType; isSingle(): boolean; isMultiple(): boolean; isFaceted(): boolean; private _setLoading; /** * Returns true if the dropdown is currently waiting on results from getValues() or getFacets() */ isDropdownLoading(): boolean; _loadingDropdownTo?: number; setLoadingDropdown(value: string, isFacet: boolean): void; _setDropdownError(error: any): void; }