diff --git a/assets/images/logo.svg b/assets/images/logo.svg index acfca7cd..271609ca 100644 --- a/assets/images/logo.svg +++ b/assets/images/logo.svg @@ -5,6 +5,6 @@ Created with Sketch. - + \ No newline at end of file diff --git a/assets/scripts/choices.js b/assets/scripts/choices.js index 8cadac64..048664d8 100644 --- a/assets/scripts/choices.js +++ b/assets/scripts/choices.js @@ -1,6925 +1,5197 @@ -/*! choices.js v10.2.0 | © 2022 Josh Johnson | https://github.com/jshjohnson/Choices#readme */ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else if(typeof exports === 'object') - exports["Choices"] = factory(); - else - root["Choices"] = factory(); -})(window, function() { -return /******/ (function() { // webpackBootstrap -/******/ "use strict"; -/******/ var __webpack_modules__ = ({ +/*! choices.js v11.0.0-rc7 | © 2024 Josh Johnson | https://github.com/jshjohnson/Choices#readme */ -/***/ 282: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Choices = factory()); +})(this, (function () { 'use strict'; + /****************************************************************************** + Copyright (c) Microsoft Corporation. + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.clearChoices = exports.activateChoices = exports.filterChoices = exports.addChoice = void 0; -var constants_1 = __webpack_require__(883); -var addChoice = function (_a) { - var value = _a.value, - label = _a.label, - id = _a.id, - groupId = _a.groupId, - disabled = _a.disabled, - elementId = _a.elementId, - customProperties = _a.customProperties, - placeholder = _a.placeholder, - keyCode = _a.keyCode; - return { - type: constants_1.ACTION_TYPES.ADD_CHOICE, - value: value, - label: label, - id: id, - groupId: groupId, - disabled: disabled, - elementId: elementId, - customProperties: customProperties, - placeholder: placeholder, - keyCode: keyCode - }; -}; -exports.addChoice = addChoice; -var filterChoices = function (results) { - return { - type: constants_1.ACTION_TYPES.FILTER_CHOICES, - results: results - }; -}; -exports.filterChoices = filterChoices; -var activateChoices = function (active) { - if (active === void 0) { - active = true; - } - return { - type: constants_1.ACTION_TYPES.ACTIVATE_CHOICES, - active: active - }; -}; -exports.activateChoices = activateChoices; -var clearChoices = function () { - return { - type: constants_1.ACTION_TYPES.CLEAR_CHOICES - }; -}; -exports.clearChoices = clearChoices; + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + ***************************************************************************** */ + /* global Reflect, Promise, SuppressedError, Symbol */ -/***/ }), - -/***/ 783: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.addGroup = void 0; -var constants_1 = __webpack_require__(883); -var addGroup = function (_a) { - var value = _a.value, - id = _a.id, - active = _a.active, - disabled = _a.disabled; - return { - type: constants_1.ACTION_TYPES.ADD_GROUP, - value: value, - id: id, - active: active, - disabled: disabled - }; -}; -exports.addGroup = addGroup; - -/***/ }), - -/***/ 464: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.highlightItem = exports.removeItem = exports.addItem = void 0; -var constants_1 = __webpack_require__(883); -var addItem = function (_a) { - var value = _a.value, - label = _a.label, - id = _a.id, - choiceId = _a.choiceId, - groupId = _a.groupId, - customProperties = _a.customProperties, - placeholder = _a.placeholder, - keyCode = _a.keyCode; - return { - type: constants_1.ACTION_TYPES.ADD_ITEM, - value: value, - label: label, - id: id, - choiceId: choiceId, - groupId: groupId, - customProperties: customProperties, - placeholder: placeholder, - keyCode: keyCode - }; -}; -exports.addItem = addItem; -var removeItem = function (id, choiceId) { - return { - type: constants_1.ACTION_TYPES.REMOVE_ITEM, - id: id, - choiceId: choiceId - }; -}; -exports.removeItem = removeItem; -var highlightItem = function (id, highlighted) { - return { - type: constants_1.ACTION_TYPES.HIGHLIGHT_ITEM, - id: id, - highlighted: highlighted - }; -}; -exports.highlightItem = highlightItem; - -/***/ }), - -/***/ 137: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.setIsLoading = exports.resetTo = exports.clearAll = void 0; -var constants_1 = __webpack_require__(883); -var clearAll = function () { - return { - type: constants_1.ACTION_TYPES.CLEAR_ALL - }; -}; -exports.clearAll = clearAll; -var resetTo = function (state) { - return { - type: constants_1.ACTION_TYPES.RESET_TO, - state: state - }; -}; -exports.resetTo = resetTo; -var setIsLoading = function (isLoading) { - return { - type: constants_1.ACTION_TYPES.SET_IS_LOADING, - isLoading: isLoading - }; -}; -exports.setIsLoading = setIsLoading; - -/***/ }), - -/***/ 373: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -var __spreadArray = this && this.__spreadArray || function (to, from, pack) { - if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); -}; -var __importDefault = this && this.__importDefault || function (mod) { - return mod && mod.__esModule ? mod : { - "default": mod - }; -}; -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -var deepmerge_1 = __importDefault(__webpack_require__(996)); -/* eslint-disable @typescript-eslint/no-explicit-any */ -var fuse_js_1 = __importDefault(__webpack_require__(221)); -var choices_1 = __webpack_require__(282); -var groups_1 = __webpack_require__(783); -var items_1 = __webpack_require__(464); -var misc_1 = __webpack_require__(137); -var components_1 = __webpack_require__(520); -var constants_1 = __webpack_require__(883); -var defaults_1 = __webpack_require__(789); -var utils_1 = __webpack_require__(799); -var reducers_1 = __webpack_require__(655); -var store_1 = __importDefault(__webpack_require__(744)); -var templates_1 = __importDefault(__webpack_require__(686)); -/** @see {@link http://browserhacks.com/#hack-acea075d0ac6954f275a70023906050c} */ -var IS_IE11 = '-ms-scroll-limit' in document.documentElement.style && '-ms-ime-align' in document.documentElement.style; -var USER_DEFAULTS = {}; -/** - * Choices - * @author Josh Johnson - */ -var Choices = /** @class */function () { - function Choices(element, userConfig) { - if (element === void 0) { - element = '[data-choice]'; - } - if (userConfig === void 0) { - userConfig = {}; - } - var _this = this; - if (userConfig.allowHTML === undefined) { - console.warn('Deprecation warning: allowHTML will default to false in a future release. To render HTML in Choices, you will need to set it to true. Setting allowHTML will suppress this message.'); - } - this.config = deepmerge_1.default.all([defaults_1.DEFAULT_CONFIG, Choices.defaults.options, userConfig], - // When merging array configs, replace with a copy of the userConfig array, - // instead of concatenating with the default array - { - arrayMerge: function (_, sourceArray) { - return __spreadArray([], sourceArray, true); - } - }); - var invalidConfigOptions = (0, utils_1.diff)(this.config, defaults_1.DEFAULT_CONFIG); - if (invalidConfigOptions.length) { - console.warn('Unknown config option(s) passed', invalidConfigOptions.join(', ')); - } - var passedElement = typeof element === 'string' ? document.querySelector(element) : element; - if (!(passedElement instanceof HTMLInputElement || passedElement instanceof HTMLSelectElement)) { - throw TypeError('Expected one of the following types text|select-one|select-multiple'); - } - this._isTextElement = passedElement.type === constants_1.TEXT_TYPE; - this._isSelectOneElement = passedElement.type === constants_1.SELECT_ONE_TYPE; - this._isSelectMultipleElement = passedElement.type === constants_1.SELECT_MULTIPLE_TYPE; - this._isSelectElement = this._isSelectOneElement || this._isSelectMultipleElement; - this.config.searchEnabled = this._isSelectMultipleElement || this.config.searchEnabled; - if (!['auto', 'always'].includes("".concat(this.config.renderSelectedChoices))) { - this.config.renderSelectedChoices = 'auto'; - } - if (userConfig.addItemFilter && typeof userConfig.addItemFilter !== 'function') { - var re = userConfig.addItemFilter instanceof RegExp ? userConfig.addItemFilter : new RegExp(userConfig.addItemFilter); - this.config.addItemFilter = re.test.bind(re); - } - if (this._isTextElement) { - this.passedElement = new components_1.WrappedInput({ - element: passedElement, - classNames: this.config.classNames, - delimiter: this.config.delimiter - }); - } else { - this.passedElement = new components_1.WrappedSelect({ - element: passedElement, - classNames: this.config.classNames, - template: function (data) { - return _this._templates.option(data); - } - }); - } - this.initialised = false; - this._store = new store_1.default(); - this._initialState = reducers_1.defaultState; - this._currentState = reducers_1.defaultState; - this._prevState = reducers_1.defaultState; - this._currentValue = ''; - this._canSearch = !!this.config.searchEnabled; - this._isScrollingOnIe = false; - this._highlightPosition = 0; - this._wasTap = true; - this._placeholderValue = this._generatePlaceholderValue(); - this._baseId = (0, utils_1.generateId)(this.passedElement.element, 'choices-'); - /** - * setting direction in cases where it's explicitly set on passedElement - * or when calculated direction is different from the document - */ - this._direction = this.passedElement.dir; - if (!this._direction) { - var elementDirection = window.getComputedStyle(this.passedElement.element).direction; - var documentDirection = window.getComputedStyle(document.documentElement).direction; - if (elementDirection !== documentDirection) { - this._direction = elementDirection; - } - } - this._idNames = { - itemChoice: 'item-choice' - }; - if (this._isSelectElement) { - // Assign preset groups from passed element - this._presetGroups = this.passedElement.optionGroups; - // Assign preset options from passed element - this._presetOptions = this.passedElement.options; - } - // Assign preset choices from passed object - this._presetChoices = this.config.choices; - // Assign preset items from passed object first - this._presetItems = this.config.items; - // Add any values passed from attribute - if (this.passedElement.value && this._isTextElement) { - var splitValues = this.passedElement.value.split(this.config.delimiter); - this._presetItems = this._presetItems.concat(splitValues); - } - // Create array of choices from option elements - if (this.passedElement.options) { - this.passedElement.options.forEach(function (option) { - _this._presetChoices.push({ - value: option.value, - label: option.innerHTML, - selected: !!option.selected, - disabled: option.disabled || option.parentNode.disabled, - placeholder: option.value === '' || option.hasAttribute('placeholder'), - customProperties: (0, utils_1.parseCustomProperties)(option.dataset.customProperties) - }); - }); - } - this._render = this._render.bind(this); - this._onFocus = this._onFocus.bind(this); - this._onBlur = this._onBlur.bind(this); - this._onKeyUp = this._onKeyUp.bind(this); - this._onKeyDown = this._onKeyDown.bind(this); - this._onClick = this._onClick.bind(this); - this._onTouchMove = this._onTouchMove.bind(this); - this._onTouchEnd = this._onTouchEnd.bind(this); - this._onMouseDown = this._onMouseDown.bind(this); - this._onMouseOver = this._onMouseOver.bind(this); - this._onFormReset = this._onFormReset.bind(this); - this._onSelectKey = this._onSelectKey.bind(this); - this._onEnterKey = this._onEnterKey.bind(this); - this._onEscapeKey = this._onEscapeKey.bind(this); - this._onDirectionKey = this._onDirectionKey.bind(this); - this._onDeleteKey = this._onDeleteKey.bind(this); - // If element has already been initialised with Choices, fail silently - if (this.passedElement.isActive) { - if (!this.config.silent) { - console.warn('Trying to initialise Choices on element already initialised', { - element: element - }); - } - this.initialised = true; - return; - } - // Let's go - this.init(); - } - Object.defineProperty(Choices, "defaults", { - get: function () { - return Object.preventExtensions({ - get options() { - return USER_DEFAULTS; - }, - get templates() { - return templates_1.default; - } - }); - }, - enumerable: false, - configurable: true - }); - Choices.prototype.init = function () { - if (this.initialised) { - return; - } - this._createTemplates(); - this._createElements(); - this._createStructure(); - this._store.subscribe(this._render); - this._render(); - this._addEventListeners(); - var shouldDisable = !this.config.addItems || this.passedElement.element.hasAttribute('disabled'); - if (shouldDisable) { - this.disable(); - } - this.initialised = true; - var callbackOnInit = this.config.callbackOnInit; - // Run callback if it is a function - if (callbackOnInit && typeof callbackOnInit === 'function') { - callbackOnInit.call(this); - } - }; - Choices.prototype.destroy = function () { - if (!this.initialised) { - return; - } - this._removeEventListeners(); - this.passedElement.reveal(); - this.containerOuter.unwrap(this.passedElement.element); - this.clearStore(); - if (this._isSelectElement) { - this.passedElement.options = this._presetOptions; - } - this._templates = templates_1.default; - this.initialised = false; - }; - Choices.prototype.enable = function () { - if (this.passedElement.isDisabled) { - this.passedElement.enable(); - } - if (this.containerOuter.isDisabled) { - this._addEventListeners(); - this.input.enable(); - this.containerOuter.enable(); - } - return this; - }; - Choices.prototype.disable = function () { - if (!this.passedElement.isDisabled) { - this.passedElement.disable(); - } - if (!this.containerOuter.isDisabled) { - this._removeEventListeners(); - this.input.disable(); - this.containerOuter.disable(); - } - return this; - }; - Choices.prototype.highlightItem = function (item, runEvent) { - if (runEvent === void 0) { - runEvent = true; - } - if (!item || !item.id) { - return this; - } - var id = item.id, - _a = item.groupId, - groupId = _a === void 0 ? -1 : _a, - _b = item.value, - value = _b === void 0 ? '' : _b, - _c = item.label, - label = _c === void 0 ? '' : _c; - var group = groupId >= 0 ? this._store.getGroupById(groupId) : null; - this._store.dispatch((0, items_1.highlightItem)(id, true)); - if (runEvent) { - this.passedElement.triggerEvent(constants_1.EVENTS.highlightItem, { - id: id, - value: value, - label: label, - groupValue: group && group.value ? group.value : null - }); - } - return this; - }; - Choices.prototype.unhighlightItem = function (item) { - if (!item || !item.id) { - return this; - } - var id = item.id, - _a = item.groupId, - groupId = _a === void 0 ? -1 : _a, - _b = item.value, - value = _b === void 0 ? '' : _b, - _c = item.label, - label = _c === void 0 ? '' : _c; - var group = groupId >= 0 ? this._store.getGroupById(groupId) : null; - this._store.dispatch((0, items_1.highlightItem)(id, false)); - this.passedElement.triggerEvent(constants_1.EVENTS.highlightItem, { - id: id, - value: value, - label: label, - groupValue: group && group.value ? group.value : null - }); - return this; - }; - Choices.prototype.highlightAll = function () { - var _this = this; - this._store.items.forEach(function (item) { - return _this.highlightItem(item); - }); - return this; - }; - Choices.prototype.unhighlightAll = function () { - var _this = this; - this._store.items.forEach(function (item) { - return _this.unhighlightItem(item); - }); - return this; - }; - Choices.prototype.removeActiveItemsByValue = function (value) { - var _this = this; - this._store.activeItems.filter(function (item) { - return item.value === value; - }).forEach(function (item) { - return _this._removeItem(item); - }); - return this; - }; - Choices.prototype.removeActiveItems = function (excludedId) { - var _this = this; - this._store.activeItems.filter(function (_a) { - var id = _a.id; - return id !== excludedId; - }).forEach(function (item) { - return _this._removeItem(item); - }); - return this; - }; - Choices.prototype.removeHighlightedItems = function (runEvent) { - var _this = this; - if (runEvent === void 0) { - runEvent = false; - } - this._store.highlightedActiveItems.forEach(function (item) { - _this._removeItem(item); - // If this action was performed by the user - // trigger the event - if (runEvent) { - _this._triggerChange(item.value); - } - }); - return this; - }; - Choices.prototype.showDropdown = function (preventInputFocus) { - var _this = this; - if (this.dropdown.isActive) { - return this; - } - requestAnimationFrame(function () { - _this.dropdown.show(); - _this.containerOuter.open(_this.dropdown.distanceFromTopWindow); - if (!preventInputFocus && _this._canSearch) { - _this.input.focus(); - } - _this.passedElement.triggerEvent(constants_1.EVENTS.showDropdown, {}); - }); - return this; - }; - Choices.prototype.hideDropdown = function (preventInputBlur) { - var _this = this; - if (!this.dropdown.isActive) { - return this; - } - requestAnimationFrame(function () { - _this.dropdown.hide(); - _this.containerOuter.close(); - if (!preventInputBlur && _this._canSearch) { - _this.input.removeActiveDescendant(); - _this.input.blur(); - } - _this.passedElement.triggerEvent(constants_1.EVENTS.hideDropdown, {}); - }); - return this; - }; - Choices.prototype.getValue = function (valueOnly) { - if (valueOnly === void 0) { - valueOnly = false; - } - var values = this._store.activeItems.reduce(function (selectedItems, item) { - var itemValue = valueOnly ? item.value : item; - selectedItems.push(itemValue); - return selectedItems; - }, []); - return this._isSelectOneElement ? values[0] : values; - }; - Choices.prototype.setValue = function (items) { - var _this = this; - if (!this.initialised) { - return this; - } - items.forEach(function (value) { - return _this._setChoiceOrItem(value); - }); - return this; - }; - Choices.prototype.setChoiceByValue = function (value) { - var _this = this; - if (!this.initialised || this._isTextElement) { - return this; - } - // If only one value has been passed, convert to array - var choiceValue = Array.isArray(value) ? value : [value]; - // Loop through each value and - choiceValue.forEach(function (val) { - return _this._findAndSelectChoiceByValue(val); - }); - return this; - }; - /** - * Set choices of select input via an array of objects (or function that returns array of object or promise of it), - * a value field name and a label field name. - * This behaves the same as passing items via the choices option but can be called after initialising Choices. - * This can also be used to add groups of choices (see example 2); Optionally pass a true `replaceChoices` value to remove any existing choices. - * Optionally pass a `customProperties` object to add additional data to your choices (useful when searching/filtering etc). - * - * **Input types affected:** select-one, select-multiple - * - * @example - * ```js - * const example = new Choices(element); - * - * example.setChoices([ - * {value: 'One', label: 'Label One', disabled: true}, - * {value: 'Two', label: 'Label Two', selected: true}, - * {value: 'Three', label: 'Label Three'}, - * ], 'value', 'label', false); - * ``` - * - * @example - * ```js - * const example = new Choices(element); - * - * example.setChoices(async () => { - * try { - * const items = await fetch('/items'); - * return items.json() - * } catch(err) { - * console.error(err) - * } - * }); - * ``` - * - * @example - * ```js - * const example = new Choices(element); - * - * example.setChoices([{ - * label: 'Group one', - * id: 1, - * disabled: false, - * choices: [ - * {value: 'Child One', label: 'Child One', selected: true}, - * {value: 'Child Two', label: 'Child Two', disabled: true}, - * {value: 'Child Three', label: 'Child Three'}, - * ] - * }, - * { - * label: 'Group two', - * id: 2, - * disabled: false, - * choices: [ - * {value: 'Child Four', label: 'Child Four', disabled: true}, - * {value: 'Child Five', label: 'Child Five'}, - * {value: 'Child Six', label: 'Child Six', customProperties: { - * description: 'Custom description about child six', - * random: 'Another random custom property' - * }}, - * ] - * }], 'value', 'label', false); - * ``` - */ - Choices.prototype.setChoices = function (choicesArrayOrFetcher, value, label, replaceChoices) { - var _this = this; - if (choicesArrayOrFetcher === void 0) { - choicesArrayOrFetcher = []; - } - if (value === void 0) { - value = 'value'; - } - if (label === void 0) { - label = 'label'; - } - if (replaceChoices === void 0) { - replaceChoices = false; - } - if (!this.initialised) { - throw new ReferenceError("setChoices was called on a non-initialized instance of Choices"); - } - if (!this._isSelectElement) { - throw new TypeError("setChoices can't be used with INPUT based Choices"); - } - if (typeof value !== 'string' || !value) { - throw new TypeError("value parameter must be a name of 'value' field in passed objects"); - } - // Clear choices if needed - if (replaceChoices) { - this.clearChoices(); - } - if (typeof choicesArrayOrFetcher === 'function') { - // it's a choices fetcher function - var fetcher_1 = choicesArrayOrFetcher(this); - if (typeof Promise === 'function' && fetcher_1 instanceof Promise) { - // that's a promise - // eslint-disable-next-line no-promise-executor-return - return new Promise(function (resolve) { - return requestAnimationFrame(resolve); - }).then(function () { - return _this._handleLoadingState(true); - }).then(function () { - return fetcher_1; - }).then(function (data) { - return _this.setChoices(data, value, label, replaceChoices); - }).catch(function (err) { - if (!_this.config.silent) { - console.error(err); - } - }).then(function () { - return _this._handleLoadingState(false); - }).then(function () { - return _this; - }); - } - // function returned something else than promise, let's check if it's an array of choices - if (!Array.isArray(fetcher_1)) { - throw new TypeError(".setChoices first argument function must return either array of choices or Promise, got: ".concat(typeof fetcher_1)); - } - // recursion with results, it's sync and choices were cleared already - return this.setChoices(fetcher_1, value, label, false); - } - if (!Array.isArray(choicesArrayOrFetcher)) { - throw new TypeError(".setChoices must be called either with array of choices with a function resulting into Promise of array of choices"); - } - this.containerOuter.removeLoadingState(); - this._startLoading(); - choicesArrayOrFetcher.forEach(function (groupOrChoice) { - if (groupOrChoice.choices) { - _this._addGroup({ - id: groupOrChoice.id ? parseInt("".concat(groupOrChoice.id), 10) : null, - group: groupOrChoice, - valueKey: value, - labelKey: label - }); - } else { - var choice = groupOrChoice; - _this._addChoice({ - value: choice[value], - label: choice[label], - isSelected: !!choice.selected, - isDisabled: !!choice.disabled, - placeholder: !!choice.placeholder, - customProperties: choice.customProperties - }); - } - }); - this._stopLoading(); - return this; - }; - Choices.prototype.clearChoices = function () { - this._store.dispatch((0, choices_1.clearChoices)()); - return this; - }; - Choices.prototype.clearStore = function () { - this._store.dispatch((0, misc_1.clearAll)()); - return this; - }; - Choices.prototype.clearInput = function () { - var shouldSetInputWidth = !this._isSelectOneElement; - this.input.clear(shouldSetInputWidth); - if (!this._isTextElement && this._canSearch) { - this._isSearching = false; - this._store.dispatch((0, choices_1.activateChoices)(true)); - } - return this; - }; - Choices.prototype._render = function () { - if (this._store.isLoading()) { - return; - } - this._currentState = this._store.state; - var stateChanged = this._currentState.choices !== this._prevState.choices || this._currentState.groups !== this._prevState.groups || this._currentState.items !== this._prevState.items; - var shouldRenderChoices = this._isSelectElement; - var shouldRenderItems = this._currentState.items !== this._prevState.items; - if (!stateChanged) { - return; - } - if (shouldRenderChoices) { - this._renderChoices(); - } - if (shouldRenderItems) { - this._renderItems(); - } - this._prevState = this._currentState; - }; - Choices.prototype._renderChoices = function () { - var _this = this; - var _a = this._store, - activeGroups = _a.activeGroups, - activeChoices = _a.activeChoices; - var choiceListFragment = document.createDocumentFragment(); - this.choiceList.clear(); - if (this.config.resetScrollPosition) { - requestAnimationFrame(function () { - return _this.choiceList.scrollToTop(); - }); - } - // If we have grouped options - if (activeGroups.length >= 1 && !this._isSearching) { - // If we have a placeholder choice along with groups - var activePlaceholders = activeChoices.filter(function (activeChoice) { - return activeChoice.placeholder === true && activeChoice.groupId === -1; - }); - if (activePlaceholders.length >= 1) { - choiceListFragment = this._createChoicesFragment(activePlaceholders, choiceListFragment); - } - choiceListFragment = this._createGroupsFragment(activeGroups, activeChoices, choiceListFragment); - } else if (activeChoices.length >= 1) { - choiceListFragment = this._createChoicesFragment(activeChoices, choiceListFragment); - } - // If we have choices to show - if (choiceListFragment.childNodes && choiceListFragment.childNodes.length > 0) { - var activeItems = this._store.activeItems; - var canAddItem = this._canAddItem(activeItems, this.input.value); - // ...and we can select them - if (canAddItem.response) { - // ...append them and highlight the first choice - this.choiceList.append(choiceListFragment); - this._highlightChoice(); - } else { - var notice = this._getTemplate('notice', canAddItem.notice); - this.choiceList.append(notice); - } - } else { - // Otherwise show a notice - var dropdownItem = void 0; - var notice = void 0; - if (this._isSearching) { - notice = typeof this.config.noResultsText === 'function' ? this.config.noResultsText() : this.config.noResultsText; - dropdownItem = this._getTemplate('notice', notice, 'no-results'); - } else { - notice = typeof this.config.noChoicesText === 'function' ? this.config.noChoicesText() : this.config.noChoicesText; - dropdownItem = this._getTemplate('notice', notice, 'no-choices'); - } - this.choiceList.append(dropdownItem); - } - }; - Choices.prototype._renderItems = function () { - var activeItems = this._store.activeItems || []; - this.itemList.clear(); - // Create a fragment to store our list items - // (so we don't have to update the DOM for each item) - var itemListFragment = this._createItemsFragment(activeItems); - // If we have items to add, append them - if (itemListFragment.childNodes) { - this.itemList.append(itemListFragment); - } - }; - Choices.prototype._createGroupsFragment = function (groups, choices, fragment) { - var _this = this; - if (fragment === void 0) { - fragment = document.createDocumentFragment(); - } - var getGroupChoices = function (group) { - return choices.filter(function (choice) { - if (_this._isSelectOneElement) { - return choice.groupId === group.id; - } - return choice.groupId === group.id && (_this.config.renderSelectedChoices === 'always' || !choice.selected); - }); - }; - // If sorting is enabled, filter groups - if (this.config.shouldSort) { - groups.sort(this.config.sorter); - } - groups.forEach(function (group) { - var groupChoices = getGroupChoices(group); - if (groupChoices.length >= 1) { - var dropdownGroup = _this._getTemplate('choiceGroup', group); - fragment.appendChild(dropdownGroup); - _this._createChoicesFragment(groupChoices, fragment, true); - } - }); - return fragment; - }; - Choices.prototype._createChoicesFragment = function (choices, fragment, withinGroup) { - var _this = this; - if (fragment === void 0) { - fragment = document.createDocumentFragment(); - } - if (withinGroup === void 0) { - withinGroup = false; - } - // Create a fragment to store our list items (so we don't have to update the DOM for each item) - var _a = this.config, - renderSelectedChoices = _a.renderSelectedChoices, - searchResultLimit = _a.searchResultLimit, - renderChoiceLimit = _a.renderChoiceLimit; - var filter = this._isSearching ? utils_1.sortByScore : this.config.sorter; - var appendChoice = function (choice) { - var shouldRender = renderSelectedChoices === 'auto' ? _this._isSelectOneElement || !choice.selected : true; - if (shouldRender) { - var dropdownItem = _this._getTemplate('choice', choice, _this.config.itemSelectText); - fragment.appendChild(dropdownItem); - } - }; - var rendererableChoices = choices; - if (renderSelectedChoices === 'auto' && !this._isSelectOneElement) { - rendererableChoices = choices.filter(function (choice) { - return !choice.selected; - }); - } - // Split array into placeholders and "normal" choices - var _b = rendererableChoices.reduce(function (acc, choice) { - if (choice.placeholder) { - acc.placeholderChoices.push(choice); - } else { - acc.normalChoices.push(choice); - } - return acc; - }, { - placeholderChoices: [], - normalChoices: [] - }), - placeholderChoices = _b.placeholderChoices, - normalChoices = _b.normalChoices; - // If sorting is enabled or the user is searching, filter choices - if (this.config.shouldSort || this._isSearching) { - normalChoices.sort(filter); - } - var choiceLimit = rendererableChoices.length; - // Prepend placeholeder - var sortedChoices = this._isSelectOneElement ? __spreadArray(__spreadArray([], placeholderChoices, true), normalChoices, true) : normalChoices; - if (this._isSearching) { - choiceLimit = searchResultLimit; - } else if (renderChoiceLimit && renderChoiceLimit > 0 && !withinGroup) { - choiceLimit = renderChoiceLimit; - } - // Add each choice to dropdown within range - for (var i = 0; i < choiceLimit; i += 1) { - if (sortedChoices[i]) { - appendChoice(sortedChoices[i]); - } - } - return fragment; - }; - Choices.prototype._createItemsFragment = function (items, fragment) { - var _this = this; - if (fragment === void 0) { - fragment = document.createDocumentFragment(); - } - // Create fragment to add elements to - var _a = this.config, - shouldSortItems = _a.shouldSortItems, - sorter = _a.sorter, - removeItemButton = _a.removeItemButton; - // If sorting is enabled, filter items - if (shouldSortItems && !this._isSelectOneElement) { - items.sort(sorter); - } - if (this._isTextElement) { - // Update the value of the hidden input - this.passedElement.value = items.map(function (_a) { - var value = _a.value; - return value; - }).join(this.config.delimiter); - } else { - // Update the options of the hidden input - this.passedElement.options = items; - } - var addItemToFragment = function (item) { - // Create new list element - var listItem = _this._getTemplate('item', item, removeItemButton); - // Append it to list - fragment.appendChild(listItem); - }; - // Add each list item to list - items.forEach(addItemToFragment); - return fragment; - }; - Choices.prototype._triggerChange = function (value) { - if (value === undefined || value === null) { - return; - } - this.passedElement.triggerEvent(constants_1.EVENTS.change, { - value: value - }); - }; - Choices.prototype._selectPlaceholderChoice = function (placeholderChoice) { - this._addItem({ - value: placeholderChoice.value, - label: placeholderChoice.label, - choiceId: placeholderChoice.id, - groupId: placeholderChoice.groupId, - placeholder: placeholderChoice.placeholder - }); - this._triggerChange(placeholderChoice.value); - }; - Choices.prototype._handleButtonAction = function (activeItems, element) { - if (!activeItems || !element || !this.config.removeItems || !this.config.removeItemButton) { - return; - } - var itemId = element.parentNode && element.parentNode.dataset.id; - var itemToRemove = itemId && activeItems.find(function (item) { - return item.id === parseInt(itemId, 10); - }); - if (!itemToRemove) { - return; - } - // Remove item associated with button - this._removeItem(itemToRemove); - this._triggerChange(itemToRemove.value); - if (this._isSelectOneElement && this._store.placeholderChoice) { - this._selectPlaceholderChoice(this._store.placeholderChoice); - } - }; - Choices.prototype._handleItemAction = function (activeItems, element, hasShiftKey) { - var _this = this; - if (hasShiftKey === void 0) { - hasShiftKey = false; - } - if (!activeItems || !element || !this.config.removeItems || this._isSelectOneElement) { - return; - } - var passedId = element.dataset.id; - // We only want to select one item with a click - // so we deselect any items that aren't the target - // unless shift is being pressed - activeItems.forEach(function (item) { - if (item.id === parseInt("".concat(passedId), 10) && !item.highlighted) { - _this.highlightItem(item); - } else if (!hasShiftKey && item.highlighted) { - _this.unhighlightItem(item); - } - }); - // Focus input as without focus, a user cannot do anything with a - // highlighted item - this.input.focus(); - }; - Choices.prototype._handleChoiceAction = function (activeItems, element) { - if (!activeItems || !element) { - return; - } - // If we are clicking on an option - var id = element.dataset.id; - var choice = id && this._store.getChoiceById(id); - if (!choice) { - return; - } - var passedKeyCode = activeItems[0] && activeItems[0].keyCode ? activeItems[0].keyCode : undefined; - var hasActiveDropdown = this.dropdown.isActive; - // Update choice keyCode - choice.keyCode = passedKeyCode; - this.passedElement.triggerEvent(constants_1.EVENTS.choice, { - choice: choice - }); - if (!choice.selected && !choice.disabled) { - var canAddItem = this._canAddItem(activeItems, choice.value); - if (canAddItem.response) { - this._addItem({ - value: choice.value, - label: choice.label, - choiceId: choice.id, - groupId: choice.groupId, - customProperties: choice.customProperties, - placeholder: choice.placeholder, - keyCode: choice.keyCode - }); - this._triggerChange(choice.value); - } - } - this.clearInput(); - // We want to close the dropdown if we are dealing with a single select box - if (hasActiveDropdown && this._isSelectOneElement) { - this.hideDropdown(true); - this.containerOuter.focus(); - } - }; - Choices.prototype._handleBackspace = function (activeItems) { - if (!this.config.removeItems || !activeItems) { - return; - } - var lastItem = activeItems[activeItems.length - 1]; - var hasHighlightedItems = activeItems.some(function (item) { - return item.highlighted; - }); - // If editing the last item is allowed and there are not other selected items, - // we can edit the item value. Otherwise if we can remove items, remove all selected items - if (this.config.editItems && !hasHighlightedItems && lastItem) { - this.input.value = lastItem.value; - this.input.setWidth(); - this._removeItem(lastItem); - this._triggerChange(lastItem.value); - } else { - if (!hasHighlightedItems) { - // Highlight last item if none already highlighted - this.highlightItem(lastItem, false); - } - this.removeHighlightedItems(true); - } - }; - Choices.prototype._startLoading = function () { - this._store.dispatch((0, misc_1.setIsLoading)(true)); - }; - Choices.prototype._stopLoading = function () { - this._store.dispatch((0, misc_1.setIsLoading)(false)); - }; - Choices.prototype._handleLoadingState = function (setLoading) { - if (setLoading === void 0) { - setLoading = true; - } - var placeholderItem = this.itemList.getChild(".".concat(this.config.classNames.placeholder)); - if (setLoading) { - this.disable(); - this.containerOuter.addLoadingState(); - if (this._isSelectOneElement) { - if (!placeholderItem) { - placeholderItem = this._getTemplate('placeholder', this.config.loadingText); - if (placeholderItem) { - this.itemList.append(placeholderItem); - } - } else { - placeholderItem.innerHTML = this.config.loadingText; - } - } else { - this.input.placeholder = this.config.loadingText; - } - } else { - this.enable(); - this.containerOuter.removeLoadingState(); - if (this._isSelectOneElement) { - if (placeholderItem) { - placeholderItem.innerHTML = this._placeholderValue || ''; - } - } else { - this.input.placeholder = this._placeholderValue || ''; - } - } - }; - Choices.prototype._handleSearch = function (value) { - if (!this.input.isFocussed) { - return; - } - var choices = this._store.choices; - var _a = this.config, - searchFloor = _a.searchFloor, - searchChoices = _a.searchChoices; - var hasUnactiveChoices = choices.some(function (option) { - return !option.active; - }); - // Check that we have a value to search and the input was an alphanumeric character - if (value !== null && typeof value !== 'undefined' && value.length >= searchFloor) { - var resultCount = searchChoices ? this._searchChoices(value) : 0; - // Trigger search event - this.passedElement.triggerEvent(constants_1.EVENTS.search, { - value: value, - resultCount: resultCount - }); - } else if (hasUnactiveChoices) { - // Otherwise reset choices to active - this._isSearching = false; - this._store.dispatch((0, choices_1.activateChoices)(true)); - } - }; - Choices.prototype._canAddItem = function (activeItems, value) { - var canAddItem = true; - var notice = typeof this.config.addItemText === 'function' ? this.config.addItemText(value) : this.config.addItemText; - if (!this._isSelectOneElement) { - var isDuplicateValue = (0, utils_1.existsInArray)(activeItems, value); - if (this.config.maxItemCount > 0 && this.config.maxItemCount <= activeItems.length) { - // If there is a max entry limit and we have reached that limit - // don't update - canAddItem = false; - notice = typeof this.config.maxItemText === 'function' ? this.config.maxItemText(this.config.maxItemCount) : this.config.maxItemText; - } - if (!this.config.duplicateItemsAllowed && isDuplicateValue && canAddItem) { - canAddItem = false; - notice = typeof this.config.uniqueItemText === 'function' ? this.config.uniqueItemText(value) : this.config.uniqueItemText; - } - if (this._isTextElement && this.config.addItems && canAddItem && typeof this.config.addItemFilter === 'function' && !this.config.addItemFilter(value)) { - canAddItem = false; - notice = typeof this.config.customAddItemText === 'function' ? this.config.customAddItemText(value) : this.config.customAddItemText; - } - } - return { - response: canAddItem, - notice: notice - }; - }; - Choices.prototype._searchChoices = function (value) { - var newValue = typeof value === 'string' ? value.trim() : value; - var currentValue = typeof this._currentValue === 'string' ? this._currentValue.trim() : this._currentValue; - if (newValue.length < 1 && newValue === "".concat(currentValue, " ")) { - return 0; - } - // If new value matches the desired length and is not the same as the current value with a space - var haystack = this._store.searchableChoices; - var needle = newValue; - var options = Object.assign(this.config.fuseOptions, { - keys: __spreadArray([], this.config.searchFields, true), - includeMatches: true - }); - var fuse = new fuse_js_1.default(haystack, options); - var results = fuse.search(needle); // see https://github.com/krisk/Fuse/issues/303 - this._currentValue = newValue; - this._highlightPosition = 0; - this._isSearching = true; - this._store.dispatch((0, choices_1.filterChoices)(results)); - return results.length; - }; - Choices.prototype._addEventListeners = function () { - var documentElement = document.documentElement; - // capture events - can cancel event processing or propagation - documentElement.addEventListener('touchend', this._onTouchEnd, true); - this.containerOuter.element.addEventListener('keydown', this._onKeyDown, true); - this.containerOuter.element.addEventListener('mousedown', this._onMouseDown, true); - // passive events - doesn't call `preventDefault` or `stopPropagation` - documentElement.addEventListener('click', this._onClick, { - passive: true - }); - documentElement.addEventListener('touchmove', this._onTouchMove, { - passive: true - }); - this.dropdown.element.addEventListener('mouseover', this._onMouseOver, { - passive: true - }); - if (this._isSelectOneElement) { - this.containerOuter.element.addEventListener('focus', this._onFocus, { - passive: true - }); - this.containerOuter.element.addEventListener('blur', this._onBlur, { - passive: true - }); - } - this.input.element.addEventListener('keyup', this._onKeyUp, { - passive: true - }); - this.input.element.addEventListener('focus', this._onFocus, { - passive: true - }); - this.input.element.addEventListener('blur', this._onBlur, { - passive: true - }); - if (this.input.element.form) { - this.input.element.form.addEventListener('reset', this._onFormReset, { - passive: true - }); - } - this.input.addEventListeners(); - }; - Choices.prototype._removeEventListeners = function () { - var documentElement = document.documentElement; - documentElement.removeEventListener('touchend', this._onTouchEnd, true); - this.containerOuter.element.removeEventListener('keydown', this._onKeyDown, true); - this.containerOuter.element.removeEventListener('mousedown', this._onMouseDown, true); - documentElement.removeEventListener('click', this._onClick); - documentElement.removeEventListener('touchmove', this._onTouchMove); - this.dropdown.element.removeEventListener('mouseover', this._onMouseOver); - if (this._isSelectOneElement) { - this.containerOuter.element.removeEventListener('focus', this._onFocus); - this.containerOuter.element.removeEventListener('blur', this._onBlur); - } - this.input.element.removeEventListener('keyup', this._onKeyUp); - this.input.element.removeEventListener('focus', this._onFocus); - this.input.element.removeEventListener('blur', this._onBlur); - if (this.input.element.form) { - this.input.element.form.removeEventListener('reset', this._onFormReset); - } - this.input.removeEventListeners(); - }; - Choices.prototype._onKeyDown = function (event) { - var keyCode = event.keyCode; - var activeItems = this._store.activeItems; - var hasFocusedInput = this.input.isFocussed; - var hasActiveDropdown = this.dropdown.isActive; - var hasItems = this.itemList.hasChildren(); - var keyString = String.fromCharCode(keyCode); - // eslint-disable-next-line no-control-regex - var wasPrintableChar = /[^\x00-\x1F]/.test(keyString); - var BACK_KEY = constants_1.KEY_CODES.BACK_KEY, - DELETE_KEY = constants_1.KEY_CODES.DELETE_KEY, - ENTER_KEY = constants_1.KEY_CODES.ENTER_KEY, - A_KEY = constants_1.KEY_CODES.A_KEY, - ESC_KEY = constants_1.KEY_CODES.ESC_KEY, - UP_KEY = constants_1.KEY_CODES.UP_KEY, - DOWN_KEY = constants_1.KEY_CODES.DOWN_KEY, - PAGE_UP_KEY = constants_1.KEY_CODES.PAGE_UP_KEY, - PAGE_DOWN_KEY = constants_1.KEY_CODES.PAGE_DOWN_KEY; - if (!this._isTextElement && !hasActiveDropdown && wasPrintableChar) { - this.showDropdown(); - if (!this.input.isFocussed) { - /* - We update the input value with the pressed key as - the input was not focussed at the time of key press - therefore does not have the value of the key. - */ - this.input.value += event.key.toLowerCase(); - } - } - switch (keyCode) { - case A_KEY: - return this._onSelectKey(event, hasItems); - case ENTER_KEY: - return this._onEnterKey(event, activeItems, hasActiveDropdown); - case ESC_KEY: - return this._onEscapeKey(hasActiveDropdown); - case UP_KEY: - case PAGE_UP_KEY: - case DOWN_KEY: - case PAGE_DOWN_KEY: - return this._onDirectionKey(event, hasActiveDropdown); - case DELETE_KEY: - case BACK_KEY: - return this._onDeleteKey(event, activeItems, hasFocusedInput); - default: - } - }; - Choices.prototype._onKeyUp = function (_a) { - var target = _a.target, - keyCode = _a.keyCode; - var value = this.input.value; - var activeItems = this._store.activeItems; - var canAddItem = this._canAddItem(activeItems, value); - var backKey = constants_1.KEY_CODES.BACK_KEY, - deleteKey = constants_1.KEY_CODES.DELETE_KEY; - // We are typing into a text input and have a value, we want to show a dropdown - // notice. Otherwise hide the dropdown - if (this._isTextElement) { - var canShowDropdownNotice = canAddItem.notice && value; - if (canShowDropdownNotice) { - var dropdownItem = this._getTemplate('notice', canAddItem.notice); - this.dropdown.element.innerHTML = dropdownItem.outerHTML; - this.showDropdown(true); - } else { - this.hideDropdown(true); - } - } else { - var wasRemovalKeyCode = keyCode === backKey || keyCode === deleteKey; - var userHasRemovedValue = wasRemovalKeyCode && target && !target.value; - var canReactivateChoices = !this._isTextElement && this._isSearching; - var canSearch = this._canSearch && canAddItem.response; - if (userHasRemovedValue && canReactivateChoices) { - this._isSearching = false; - this._store.dispatch((0, choices_1.activateChoices)(true)); - } else if (canSearch) { - this._handleSearch(this.input.rawValue); - } - } - this._canSearch = this.config.searchEnabled; - }; - Choices.prototype._onSelectKey = function (event, hasItems) { - var ctrlKey = event.ctrlKey, - metaKey = event.metaKey; - var hasCtrlDownKeyPressed = ctrlKey || metaKey; - // If CTRL + A or CMD + A have been pressed and there are items to select - if (hasCtrlDownKeyPressed && hasItems) { - this._canSearch = false; - var shouldHightlightAll = this.config.removeItems && !this.input.value && this.input.element === document.activeElement; - if (shouldHightlightAll) { - this.highlightAll(); - } - } - }; - Choices.prototype._onEnterKey = function (event, activeItems, hasActiveDropdown) { - var target = event.target; - var enterKey = constants_1.KEY_CODES.ENTER_KEY; - var targetWasButton = target && target.hasAttribute('data-button'); - if (this._isTextElement && target && target.value) { - var value = this.input.value; - var canAddItem = this._canAddItem(activeItems, value); - if (canAddItem.response) { - this.hideDropdown(true); - this._addItem({ - value: value - }); - this._triggerChange(value); - this.clearInput(); - } - } - if (targetWasButton) { - this._handleButtonAction(activeItems, target); - event.preventDefault(); - } - if (hasActiveDropdown) { - var highlightedChoice = this.dropdown.getChild(".".concat(this.config.classNames.highlightedState)); - if (highlightedChoice) { - // add enter keyCode value - if (activeItems[0]) { - activeItems[0].keyCode = enterKey; // eslint-disable-line no-param-reassign - } - - this._handleChoiceAction(activeItems, highlightedChoice); - } - event.preventDefault(); - } else if (this._isSelectOneElement) { - this.showDropdown(); - event.preventDefault(); - } - }; - Choices.prototype._onEscapeKey = function (hasActiveDropdown) { - if (hasActiveDropdown) { - this.hideDropdown(true); - this.containerOuter.focus(); - } - }; - Choices.prototype._onDirectionKey = function (event, hasActiveDropdown) { - var keyCode = event.keyCode, - metaKey = event.metaKey; - var downKey = constants_1.KEY_CODES.DOWN_KEY, - pageUpKey = constants_1.KEY_CODES.PAGE_UP_KEY, - pageDownKey = constants_1.KEY_CODES.PAGE_DOWN_KEY; - // If up or down key is pressed, traverse through options - if (hasActiveDropdown || this._isSelectOneElement) { - this.showDropdown(); - this._canSearch = false; - var directionInt = keyCode === downKey || keyCode === pageDownKey ? 1 : -1; - var skipKey = metaKey || keyCode === pageDownKey || keyCode === pageUpKey; - var selectableChoiceIdentifier = '[data-choice-selectable]'; - var nextEl = void 0; - if (skipKey) { - if (directionInt > 0) { - nextEl = this.dropdown.element.querySelector("".concat(selectableChoiceIdentifier, ":last-of-type")); - } else { - nextEl = this.dropdown.element.querySelector(selectableChoiceIdentifier); - } - } else { - var currentEl = this.dropdown.element.querySelector(".".concat(this.config.classNames.highlightedState)); - if (currentEl) { - nextEl = (0, utils_1.getAdjacentEl)(currentEl, selectableChoiceIdentifier, directionInt); - } else { - nextEl = this.dropdown.element.querySelector(selectableChoiceIdentifier); - } - } - if (nextEl) { - // We prevent default to stop the cursor moving - // when pressing the arrow - if (!(0, utils_1.isScrolledIntoView)(nextEl, this.choiceList.element, directionInt)) { - this.choiceList.scrollToChildElement(nextEl, directionInt); - } - this._highlightChoice(nextEl); - } - // Prevent default to maintain cursor position whilst - // traversing dropdown options - event.preventDefault(); - } - }; - Choices.prototype._onDeleteKey = function (event, activeItems, hasFocusedInput) { - var target = event.target; - // If backspace or delete key is pressed and the input has no value - if (!this._isSelectOneElement && !target.value && hasFocusedInput) { - this._handleBackspace(activeItems); - event.preventDefault(); - } - }; - Choices.prototype._onTouchMove = function () { - if (this._wasTap) { - this._wasTap = false; - } - }; - Choices.prototype._onTouchEnd = function (event) { - var target = (event || event.touches[0]).target; - var touchWasWithinContainer = this._wasTap && this.containerOuter.element.contains(target); - if (touchWasWithinContainer) { - var containerWasExactTarget = target === this.containerOuter.element || target === this.containerInner.element; - if (containerWasExactTarget) { - if (this._isTextElement) { - this.input.focus(); - } else if (this._isSelectMultipleElement) { - this.showDropdown(); - } - } - // Prevents focus event firing - event.stopPropagation(); - } - this._wasTap = true; - }; - /** - * Handles mousedown event in capture mode for containetOuter.element - */ - Choices.prototype._onMouseDown = function (event) { - var target = event.target; - if (!(target instanceof HTMLElement)) { - return; - } - // If we have our mouse down on the scrollbar and are on IE11... - if (IS_IE11 && this.choiceList.element.contains(target)) { - // check if click was on a scrollbar area - var firstChoice = this.choiceList.element.firstElementChild; - var isOnScrollbar = this._direction === 'ltr' ? event.offsetX >= firstChoice.offsetWidth : event.offsetX < firstChoice.offsetLeft; - this._isScrollingOnIe = isOnScrollbar; - } - if (target === this.input.element) { - return; - } - var item = target.closest('[data-button],[data-item],[data-choice]'); - if (item instanceof HTMLElement) { - var hasShiftKey = event.shiftKey; - var activeItems = this._store.activeItems; - var dataset = item.dataset; - if ('button' in dataset) { - this._handleButtonAction(activeItems, item); - } else if ('item' in dataset) { - this._handleItemAction(activeItems, item, hasShiftKey); - } else if ('choice' in dataset) { - this._handleChoiceAction(activeItems, item); - } - } - event.preventDefault(); - }; - /** - * Handles mouseover event over this.dropdown - * @param {MouseEvent} event - */ - Choices.prototype._onMouseOver = function (_a) { - var target = _a.target; - if (target instanceof HTMLElement && 'choice' in target.dataset) { - this._highlightChoice(target); - } - }; - Choices.prototype._onClick = function (_a) { - var target = _a.target; - var clickWasWithinContainer = this.containerOuter.element.contains(target); - if (clickWasWithinContainer) { - if (!this.dropdown.isActive && !this.containerOuter.isDisabled) { - if (this._isTextElement) { - if (document.activeElement !== this.input.element) { - this.input.focus(); - } - } else { - this.showDropdown(); - this.containerOuter.focus(); - } - } else if (this._isSelectOneElement && target !== this.input.element && !this.dropdown.element.contains(target)) { - this.hideDropdown(); - } - } else { - var hasHighlightedItems = this._store.highlightedActiveItems.length > 0; - if (hasHighlightedItems) { - this.unhighlightAll(); - } - this.containerOuter.removeFocusState(); - this.hideDropdown(true); - } - }; - Choices.prototype._onFocus = function (_a) { - var _b; - var _this = this; - var target = _a.target; - var focusWasWithinContainer = target && this.containerOuter.element.contains(target); - if (!focusWasWithinContainer) { - return; - } - var focusActions = (_b = {}, _b[constants_1.TEXT_TYPE] = function () { - if (target === _this.input.element) { - _this.containerOuter.addFocusState(); - } - }, _b[constants_1.SELECT_ONE_TYPE] = function () { - _this.containerOuter.addFocusState(); - if (target === _this.input.element) { - _this.showDropdown(true); - } - }, _b[constants_1.SELECT_MULTIPLE_TYPE] = function () { - if (target === _this.input.element) { - _this.showDropdown(true); - // If element is a select box, the focused element is the container and the dropdown - // isn't already open, focus and show dropdown - _this.containerOuter.addFocusState(); - } - }, _b); - focusActions[this.passedElement.element.type](); - }; - Choices.prototype._onBlur = function (_a) { - var _b; - var _this = this; - var target = _a.target; - var blurWasWithinContainer = target && this.containerOuter.element.contains(target); - if (blurWasWithinContainer && !this._isScrollingOnIe) { - var activeItems = this._store.activeItems; - var hasHighlightedItems_1 = activeItems.some(function (item) { - return item.highlighted; - }); - var blurActions = (_b = {}, _b[constants_1.TEXT_TYPE] = function () { - if (target === _this.input.element) { - _this.containerOuter.removeFocusState(); - if (hasHighlightedItems_1) { - _this.unhighlightAll(); - } - _this.hideDropdown(true); - } - }, _b[constants_1.SELECT_ONE_TYPE] = function () { - _this.containerOuter.removeFocusState(); - if (target === _this.input.element || target === _this.containerOuter.element && !_this._canSearch) { - _this.hideDropdown(true); - } - }, _b[constants_1.SELECT_MULTIPLE_TYPE] = function () { - if (target === _this.input.element) { - _this.containerOuter.removeFocusState(); - _this.hideDropdown(true); - if (hasHighlightedItems_1) { - _this.unhighlightAll(); - } - } - }, _b); - blurActions[this.passedElement.element.type](); - } else { - // On IE11, clicking the scollbar blurs our input and thus - // closes the dropdown. To stop this, we refocus our input - // if we know we are on IE *and* are scrolling. - this._isScrollingOnIe = false; - this.input.element.focus(); - } - }; - Choices.prototype._onFormReset = function () { - this._store.dispatch((0, misc_1.resetTo)(this._initialState)); - }; - Choices.prototype._highlightChoice = function (el) { - var _this = this; - if (el === void 0) { - el = null; - } - var choices = Array.from(this.dropdown.element.querySelectorAll('[data-choice-selectable]')); - if (!choices.length) { - return; - } - var passedEl = el; - var highlightedChoices = Array.from(this.dropdown.element.querySelectorAll(".".concat(this.config.classNames.highlightedState))); - // Remove any highlighted choices - highlightedChoices.forEach(function (choice) { - choice.classList.remove(_this.config.classNames.highlightedState); - choice.setAttribute('aria-selected', 'false'); - }); - if (passedEl) { - this._highlightPosition = choices.indexOf(passedEl); - } else { - // Highlight choice based on last known highlight location - if (choices.length > this._highlightPosition) { - // If we have an option to highlight - passedEl = choices[this._highlightPosition]; - } else { - // Otherwise highlight the option before - passedEl = choices[choices.length - 1]; - } - if (!passedEl) { - passedEl = choices[0]; - } - } - passedEl.classList.add(this.config.classNames.highlightedState); - passedEl.setAttribute('aria-selected', 'true'); - this.passedElement.triggerEvent(constants_1.EVENTS.highlightChoice, { - el: passedEl - }); - if (this.dropdown.isActive) { - // IE11 ignores aria-label and blocks virtual keyboard - // if aria-activedescendant is set without a dropdown - this.input.setActiveDescendant(passedEl.id); - this.containerOuter.setActiveDescendant(passedEl.id); - } - }; - Choices.prototype._addItem = function (_a) { - var value = _a.value, - _b = _a.label, - label = _b === void 0 ? null : _b, - _c = _a.choiceId, - choiceId = _c === void 0 ? -1 : _c, - _d = _a.groupId, - groupId = _d === void 0 ? -1 : _d, - _e = _a.customProperties, - customProperties = _e === void 0 ? {} : _e, - _f = _a.placeholder, - placeholder = _f === void 0 ? false : _f, - _g = _a.keyCode, - keyCode = _g === void 0 ? -1 : _g; - var passedValue = typeof value === 'string' ? value.trim() : value; - var items = this._store.items; - var passedLabel = label || passedValue; - var passedOptionId = choiceId || -1; - var group = groupId >= 0 ? this._store.getGroupById(groupId) : null; - var id = items ? items.length + 1 : 1; - // If a prepended value has been passed, prepend it - if (this.config.prependValue) { - passedValue = this.config.prependValue + passedValue.toString(); - } - // If an appended value has been passed, append it - if (this.config.appendValue) { - passedValue += this.config.appendValue.toString(); - } - this._store.dispatch((0, items_1.addItem)({ - value: passedValue, - label: passedLabel, - id: id, - choiceId: passedOptionId, - groupId: groupId, - customProperties: customProperties, - placeholder: placeholder, - keyCode: keyCode - })); - if (this._isSelectOneElement) { - this.removeActiveItems(id); - } - // Trigger change event - this.passedElement.triggerEvent(constants_1.EVENTS.addItem, { - id: id, - value: passedValue, - label: passedLabel, - customProperties: customProperties, - groupValue: group && group.value ? group.value : null, - keyCode: keyCode - }); - }; - Choices.prototype._removeItem = function (item) { - var id = item.id, - value = item.value, - label = item.label, - customProperties = item.customProperties, - choiceId = item.choiceId, - groupId = item.groupId; - var group = groupId && groupId >= 0 ? this._store.getGroupById(groupId) : null; - if (!id || !choiceId) { - return; - } - this._store.dispatch((0, items_1.removeItem)(id, choiceId)); - this.passedElement.triggerEvent(constants_1.EVENTS.removeItem, { - id: id, - value: value, - label: label, - customProperties: customProperties, - groupValue: group && group.value ? group.value : null - }); - }; - Choices.prototype._addChoice = function (_a) { - var value = _a.value, - _b = _a.label, - label = _b === void 0 ? null : _b, - _c = _a.isSelected, - isSelected = _c === void 0 ? false : _c, - _d = _a.isDisabled, - isDisabled = _d === void 0 ? false : _d, - _e = _a.groupId, - groupId = _e === void 0 ? -1 : _e, - _f = _a.customProperties, - customProperties = _f === void 0 ? {} : _f, - _g = _a.placeholder, - placeholder = _g === void 0 ? false : _g, - _h = _a.keyCode, - keyCode = _h === void 0 ? -1 : _h; - if (typeof value === 'undefined' || value === null) { - return; - } - // Generate unique id - var choices = this._store.choices; - var choiceLabel = label || value; - var choiceId = choices ? choices.length + 1 : 1; - var choiceElementId = "".concat(this._baseId, "-").concat(this._idNames.itemChoice, "-").concat(choiceId); - this._store.dispatch((0, choices_1.addChoice)({ - id: choiceId, - groupId: groupId, - elementId: choiceElementId, - value: value, - label: choiceLabel, - disabled: isDisabled, - customProperties: customProperties, - placeholder: placeholder, - keyCode: keyCode - })); - if (isSelected) { - this._addItem({ - value: value, - label: choiceLabel, - choiceId: choiceId, - customProperties: customProperties, - placeholder: placeholder, - keyCode: keyCode - }); - } - }; - Choices.prototype._addGroup = function (_a) { - var _this = this; - var group = _a.group, - id = _a.id, - _b = _a.valueKey, - valueKey = _b === void 0 ? 'value' : _b, - _c = _a.labelKey, - labelKey = _c === void 0 ? 'label' : _c; - var groupChoices = (0, utils_1.isType)('Object', group) ? group.choices : Array.from(group.getElementsByTagName('OPTION')); - var groupId = id || Math.floor(new Date().valueOf() * Math.random()); - var isDisabled = group.disabled ? group.disabled : false; - if (groupChoices) { - this._store.dispatch((0, groups_1.addGroup)({ - value: group.label, - id: groupId, - active: true, - disabled: isDisabled - })); - var addGroupChoices = function (choice) { - var isOptDisabled = choice.disabled || choice.parentNode && choice.parentNode.disabled; - _this._addChoice({ - value: choice[valueKey], - label: (0, utils_1.isType)('Object', choice) ? choice[labelKey] : choice.innerHTML, - isSelected: choice.selected, - isDisabled: isOptDisabled, - groupId: groupId, - customProperties: choice.customProperties, - placeholder: choice.placeholder - }); + 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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - groupChoices.forEach(addGroupChoices); - } else { - this._store.dispatch((0, groups_1.addGroup)({ - value: group.label, - id: group.id, - active: false, - disabled: group.disabled - })); - } - }; - Choices.prototype._getTemplate = function (template) { - var _a; - var args = []; - for (var _i = 1; _i < arguments.length; _i++) { - args[_i - 1] = arguments[_i]; - } - return (_a = this._templates[template]).call.apply(_a, __spreadArray([this, this.config], args, false)); - }; - Choices.prototype._createTemplates = function () { - var callbackOnCreateTemplates = this.config.callbackOnCreateTemplates; - var userTemplates = {}; - if (callbackOnCreateTemplates && typeof callbackOnCreateTemplates === 'function') { - userTemplates = callbackOnCreateTemplates.call(this, utils_1.strToEl); - } - this._templates = (0, deepmerge_1.default)(templates_1.default, userTemplates); - }; - Choices.prototype._createElements = function () { - this.containerOuter = new components_1.Container({ - element: this._getTemplate('containerOuter', this._direction, this._isSelectElement, this._isSelectOneElement, this.config.searchEnabled, this.passedElement.element.type, this.config.labelId), - classNames: this.config.classNames, - type: this.passedElement.element.type, - position: this.config.position - }); - this.containerInner = new components_1.Container({ - element: this._getTemplate('containerInner'), - classNames: this.config.classNames, - type: this.passedElement.element.type, - position: this.config.position - }); - this.input = new components_1.Input({ - element: this._getTemplate('input', this._placeholderValue), - classNames: this.config.classNames, - type: this.passedElement.element.type, - preventPaste: !this.config.paste - }); - this.choiceList = new components_1.List({ - element: this._getTemplate('choiceList', this._isSelectOneElement) - }); - this.itemList = new components_1.List({ - element: this._getTemplate('itemList', this._isSelectOneElement) - }); - this.dropdown = new components_1.Dropdown({ - element: this._getTemplate('dropdown'), - classNames: this.config.classNames, - type: this.passedElement.element.type - }); - }; - Choices.prototype._createStructure = function () { - // Hide original element - this.passedElement.conceal(); - // Wrap input in container preserving DOM ordering - this.containerInner.wrap(this.passedElement.element); - // Wrapper inner container with outer container - this.containerOuter.wrap(this.containerInner.element); - if (this._isSelectOneElement) { - this.input.placeholder = this.config.searchPlaceholderValue || ''; - } else if (this._placeholderValue) { - this.input.placeholder = this._placeholderValue; - this.input.setWidth(); - } - this.containerOuter.element.appendChild(this.containerInner.element); - this.containerOuter.element.appendChild(this.dropdown.element); - this.containerInner.element.appendChild(this.itemList.element); - if (!this._isTextElement) { - this.dropdown.element.appendChild(this.choiceList.element); - } - if (!this._isSelectOneElement) { - this.containerInner.element.appendChild(this.input.element); - } else if (this.config.searchEnabled) { - this.dropdown.element.insertBefore(this.input.element, this.dropdown.element.firstChild); - } - if (this._isSelectElement) { - this._highlightPosition = 0; - this._isSearching = false; - this._startLoading(); - if (this._presetGroups.length) { - this._addPredefinedGroups(this._presetGroups); - } else { - this._addPredefinedChoices(this._presetChoices); + return extendStatics(d, b); + }; + function __extends(d, b) { + if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { + this.constructor = d; } - this._stopLoading(); + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } - if (this._isTextElement) { - this._addPredefinedItems(this._presetItems); - } - }; - Choices.prototype._addPredefinedGroups = function (groups) { - var _this = this; - // If we have a placeholder option - var placeholderChoice = this.passedElement.placeholderOption; - if (placeholderChoice && placeholderChoice.parentNode && placeholderChoice.parentNode.tagName === 'SELECT') { - this._addChoice({ - value: placeholderChoice.value, - label: placeholderChoice.innerHTML, - isSelected: placeholderChoice.selected, - isDisabled: placeholderChoice.disabled, - placeholder: true - }); - } - groups.forEach(function (group) { - return _this._addGroup({ - group: group, - id: group.id || null - }); - }); - }; - Choices.prototype._addPredefinedChoices = function (choices) { - var _this = this; - // If sorting is enabled or the user is searching, filter choices - if (this.config.shouldSort) { - choices.sort(this.config.sorter); - } - var hasSelectedChoice = choices.some(function (choice) { - return choice.selected; - }); - var firstEnabledChoiceIndex = choices.findIndex(function (choice) { - return choice.disabled === undefined || !choice.disabled; - }); - choices.forEach(function (choice, index) { - var _a = choice.value, - value = _a === void 0 ? '' : _a, - label = choice.label, - customProperties = choice.customProperties, - placeholder = choice.placeholder; - if (_this._isSelectElement) { - // If the choice is actually a group - if (choice.choices) { - _this._addGroup({ - group: choice, - id: choice.id || null - }); - } else { - /** - * If there is a selected choice already or the choice is not the first in - * the array, add each choice normally. - * - * Otherwise we pre-select the first enabled choice in the array ("select-one" only) - */ - var shouldPreselect = _this._isSelectOneElement && !hasSelectedChoice && index === firstEnabledChoiceIndex; - var isSelected = shouldPreselect ? true : choice.selected; - var isDisabled = choice.disabled; - _this._addChoice({ - value: value, - label: label, - isSelected: !!isSelected, - isDisabled: !!isDisabled, - placeholder: !!placeholder, - customProperties: customProperties - }); + var __assign = function () { + __assign = Object.assign || function __assign(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); + }; + function __spreadArray(to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); + } + typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; + }; + + var ActionType = { + ADD_CHOICE: 'ADD_CHOICE', + REMOVE_CHOICE: 'REMOVE_CHOICE', + FILTER_CHOICES: 'FILTER_CHOICES', + ACTIVATE_CHOICES: 'ACTIVATE_CHOICES', + CLEAR_CHOICES: 'CLEAR_CHOICES', + ADD_GROUP: 'ADD_GROUP', + ADD_ITEM: 'ADD_ITEM', + REMOVE_ITEM: 'REMOVE_ITEM', + HIGHLIGHT_ITEM: 'HIGHLIGHT_ITEM', + }; + + var ObjectsInConfig = ['fuseOptions', 'classNames']; + + var addChoice = function (choice) { return ({ + type: ActionType.ADD_CHOICE, + choice: choice, + }); }; + var removeChoice = function (choice) { return ({ + type: ActionType.REMOVE_CHOICE, + choice: choice, + }); }; + var filterChoices = function (results) { return ({ + type: ActionType.FILTER_CHOICES, + results: results, + }); }; + var activateChoices = function (active) { + return ({ + type: ActionType.ACTIVATE_CHOICES, + active: active, + }); + }; + var clearChoices = function () { return ({ + type: ActionType.CLEAR_CHOICES, + }); }; + + var addGroup = function (group) { return ({ + type: ActionType.ADD_GROUP, + group: group, + }); }; + + var addItem = function (item) { return ({ + type: ActionType.ADD_ITEM, + item: item, + }); }; + var removeItem = function (item) { return ({ + type: ActionType.REMOVE_ITEM, + item: item, + }); }; + var highlightItem = function (item, highlighted) { return ({ + type: ActionType.HIGHLIGHT_ITEM, + item: item, + highlighted: highlighted, + }); }; + + /* eslint-disable @typescript-eslint/no-explicit-any */ + var getRandomNumber = function (min, max) { return Math.floor(Math.random() * (max - min) + min); }; + var generateChars = function (length) { + return Array.from({ length: length }, function () { return getRandomNumber(0, 36).toString(36); }).join(''); + }; + var generateId = function (element, prefix) { + var id = element.id || (element.name && "".concat(element.name, "-").concat(generateChars(2))) || generateChars(4); + id = id.replace(/(:|\.|\[|\]|,)/g, ''); + id = "".concat(prefix, "-").concat(id); + return id; + }; + var getAdjacentEl = function (startEl, selector, direction) { + if (direction === void 0) { direction = 1; } + var prop = "".concat(direction > 0 ? 'next' : 'previous', "ElementSibling"); + var sibling = startEl[prop]; + while (sibling) { + if (sibling.matches(selector)) { + return sibling; + } + sibling = sibling[prop]; + } + return null; + }; + var isScrolledIntoView = function (element, parent, direction) { + if (direction === void 0) { direction = 1; } + var isVisible; + if (direction > 0) { + // In view from bottom + isVisible = parent.scrollTop + parent.offsetHeight >= element.offsetTop + element.offsetHeight; + } + else { + // In view from top + isVisible = element.offsetTop >= parent.scrollTop; + } + return isVisible; + }; + var sanitise = function (value) { + if (typeof value !== 'string') { + if (value === null || value === undefined) { + return ''; + } + if (typeof value === 'object') { + if ('raw' in value) { + return sanitise(value.raw); + } + if ('trusted' in value) { + return value.trusted; + } + } + return value; + } + return value + .replace(/&/g, '&') + .replace(/>/g, '>') + .replace(/ 0 ? this.element.scrollTop + elementPos - listScrollPosition : element.offsetTop; + requestAnimationFrame(function () { + _this._animateScroll(destination, direction); + }); + }; + List.prototype._scrollDown = function (scrollPos, strength, destination) { + var easing = (destination - scrollPos) / strength; + var distance = easing > 1 ? easing : 1; + this.element.scrollTop = scrollPos + distance; + }; + List.prototype._scrollUp = function (scrollPos, strength, destination) { + var easing = (scrollPos - destination) / strength; + var distance = easing > 1 ? easing : 1; + this.element.scrollTop = scrollPos - distance; + }; + List.prototype._animateScroll = function (destination, direction) { + var _this = this; + var strength = SCROLLING_SPEED; + var choiceListScrollTop = this.element.scrollTop; + var continueAnimation = false; + if (direction > 0) { + this._scrollDown(choiceListScrollTop, strength, destination); + if (choiceListScrollTop < destination) { + continueAnimation = true; + } + } + else { + this._scrollUp(choiceListScrollTop, strength, destination); + if (choiceListScrollTop > destination) { + continueAnimation = true; + } + } + if (continueAnimation) { + requestAnimationFrame(function () { + _this._animateScroll(destination, direction); + }); + } + }; + return List; + }()); + + var WrappedElement = /** @class */ (function () { + function WrappedElement(_a) { + var element = _a.element, classNames = _a.classNames; + this.element = element; + this.classNames = classNames; + this.isDisabled = false; + } + Object.defineProperty(WrappedElement.prototype, "isActive", { + get: function () { + return this.element.dataset.choice === 'active'; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(WrappedElement.prototype, "dir", { + get: function () { + return this.element.dir; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(WrappedElement.prototype, "value", { + get: function () { + return this.element.value; + }, + set: function (value) { + this.element.setAttribute('value', value); + this.element.value = value; + }, + enumerable: false, + configurable: true + }); + WrappedElement.prototype.conceal = function () { + var _a; + var el = this.element; + // Hide passed input + (_a = el.classList).add.apply(_a, getClassNames(this.classNames.input)); + el.hidden = true; + // Remove element from tab index + el.tabIndex = -1; + // Backup original styles if any + var origStyle = el.getAttribute('style'); + if (origStyle) { + el.setAttribute('data-choice-orig-style', origStyle); + } + el.setAttribute('data-choice', 'active'); + }; + WrappedElement.prototype.reveal = function () { + var _a; + var el = this.element; + // Reinstate passed element + (_a = el.classList).remove.apply(_a, getClassNames(this.classNames.input)); + el.hidden = false; + el.removeAttribute('tabindex'); + // Recover original styles if any + var origStyle = el.getAttribute('data-choice-orig-style'); + if (origStyle) { + el.removeAttribute('data-choice-orig-style'); + el.setAttribute('style', origStyle); + } + else { + el.removeAttribute('style'); + } + el.removeAttribute('data-choice'); + }; + WrappedElement.prototype.enable = function () { + var element = this.element; + element.removeAttribute('disabled'); + element.disabled = false; + this.isDisabled = false; + }; + WrappedElement.prototype.disable = function () { + var element = this.element; + element.setAttribute('disabled', ''); + element.disabled = true; + this.isDisabled = true; + }; + WrappedElement.prototype.triggerEvent = function (eventType, data) { + dispatchEvent(this.element, eventType, data || {}); + }; + return WrappedElement; + }()); + + var WrappedInput = /** @class */ (function (_super) { + __extends(WrappedInput, _super); + function WrappedInput() { + return _super !== null && _super.apply(this, arguments) || this; + } + return WrappedInput; + }(WrappedElement)); + + var coerceBool = function (arg, defaultValue) { + if (defaultValue === void 0) { defaultValue = true; } + return typeof arg === 'undefined' ? defaultValue : !!arg; + }; + var stringToHtmlClass = function (input) { + if (typeof input === 'string') { + // eslint-disable-next-line no-param-reassign + input = input.split(' ').filter(function (s) { return s.length; }); + } + if (Array.isArray(input) && input.length) { + return input; + } + return undefined; + }; + var mapInputToChoice = function (value, allowGroup) { + if (typeof value === 'string') { + var result_1 = mapInputToChoice({ + value: value, + label: value, + }, false); + return result_1; + } + var groupOrChoice = value; + if ('choices' in groupOrChoice) { + if (!allowGroup) { + // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup + throw new TypeError("optGroup is not allowed"); + } + var group = groupOrChoice; + var choices = group.choices.map(function (e) { return mapInputToChoice(e, false); }); + var result_2 = { + id: 0, // actual ID will be assigned during _addGroup + label: unwrapStringForRaw(group.label) || group.value, + active: !!choices.length, + disabled: !!group.disabled, + choices: choices, + }; + return result_2; + } + var choice = groupOrChoice; + var result = { + id: 0, // actual ID will be assigned during _addChoice + groupId: 0, // actual ID will be assigned during _addGroup but before _addChoice + score: 0, // used in search + rank: 0, // used in search, stable sort order + value: choice.value, + label: choice.label || choice.value, + active: coerceBool(choice.active), + selected: coerceBool(choice.selected, false), + disabled: coerceBool(choice.disabled, false), + placeholder: coerceBool(choice.placeholder, false), + highlighted: false, + labelClass: stringToHtmlClass(choice.labelClass), + labelDescription: choice.labelDescription, + customProperties: choice.customProperties, + }; + return result; + }; + + var isHtmlInputElement = function (e) { return e.tagName === 'INPUT'; }; + var isHtmlSelectElement = function (e) { return e.tagName === 'SELECT'; }; + var isHtmlOption = function (e) { return e.tagName === 'OPTION'; }; + var isHtmlOptgroup = function (e) { return e.tagName === 'OPTGROUP'; }; + + var WrappedSelect = /** @class */ (function (_super) { + __extends(WrappedSelect, _super); + function WrappedSelect(_a) { + var element = _a.element, classNames = _a.classNames, template = _a.template, extractPlaceholder = _a.extractPlaceholder; + var _this = _super.call(this, { element: element, classNames: classNames }) || this; + _this.template = template; + _this.extractPlaceholder = extractPlaceholder; + return _this; + } + Object.defineProperty(WrappedSelect.prototype, "placeholderOption", { + get: function () { + return (this.element.querySelector('option[value=""]') || + // Backward compatibility layer for the non-standard placeholder attribute supported in older versions. + this.element.querySelector('option[placeholder]')); + }, + enumerable: false, + configurable: true + }); + WrappedSelect.prototype.addOptions = function (choices) { + var _this = this; + var fragment = document.createDocumentFragment(); + choices.forEach(function (obj) { + var choice = obj; + if (choice.element) { + return; + } + var option = _this.template(choice); + fragment.appendChild(option); + choice.element = option; + }); + this.element.appendChild(fragment); + }; + WrappedSelect.prototype.optionsAsChoices = function () { + var _this = this; + var choices = []; + this.element.querySelectorAll(':scope > option, :scope > optgroup').forEach(function (e) { + if (isHtmlOption(e)) { + choices.push(_this._optionToChoice(e)); + } + else if (isHtmlOptgroup(e)) { + choices.push(_this._optgroupToChoice(e)); + } + // todo: hr as empty optgroup, requires displaying empty opt-groups to be useful + }); + return choices; + }; + // eslint-disable-next-line class-methods-use-this + WrappedSelect.prototype._optionToChoice = function (option) { + // option.value returns the label if there is no value attribute, which can break legacy placeholder attribute support + if (!option.hasAttribute('value') && option.hasAttribute('placeholder')) { + option.setAttribute('value', ''); + option.value = ''; + } + var dataset = option.dataset; + return { + id: 0, + groupId: 0, + score: 0, + rank: 0, + value: option.value, + label: option.innerHTML, + element: option, + active: true, + // this returns true if nothing is selected on initial load, which will break placeholder support + selected: this.extractPlaceholder ? option.selected : option.hasAttribute('selected'), + disabled: option.disabled, + highlighted: false, + placeholder: this.extractPlaceholder && (!option.value || option.hasAttribute('placeholder')), + labelClass: typeof dataset.labelClass !== 'undefined' ? stringToHtmlClass(dataset.labelClass) : undefined, + labelDescription: typeof dataset.labelDescription !== 'undefined' ? dataset.labelDescription : undefined, + customProperties: parseCustomProperties(dataset.customProperties), + }; + }; + WrappedSelect.prototype._optgroupToChoice = function (optgroup) { + var _this = this; + var options = optgroup.querySelectorAll('option'); + var choices = Array.from(options).map(function (option) { return _this._optionToChoice(option); }); + return { + id: 0, + label: optgroup.label || '', + element: optgroup, + active: !!choices.length, + disabled: optgroup.disabled, + choices: choices, + }; + }; + return WrappedSelect; + }(WrappedElement)); + + var DEFAULT_CLASSNAMES = { + containerOuter: ['choices'], + containerInner: ['choices__inner'], + input: ['choices__input'], + inputCloned: ['choices__input--cloned'], + list: ['choices__list'], + listItems: ['choices__list--multiple'], + listSingle: ['choices__list--single'], + listDropdown: ['choices__list--dropdown'], + item: ['choices__item'], + itemSelectable: ['choices__item--selectable'], + itemDisabled: ['choices__item--disabled'], + itemChoice: ['choices__item--choice'], + description: ['choices__description'], + placeholder: ['choices__placeholder'], + group: ['choices__group'], + groupHeading: ['choices__heading'], + button: ['choices__button'], + activeState: ['is-active'], + focusState: ['is-focused'], + openState: ['is-open'], + disabledState: ['is-disabled'], + highlightedState: ['is-highlighted'], + selectedState: ['is-selected'], + flippedState: ['is-flipped'], + loadingState: ['is-loading'], + notice: ['choices__notice'], + addChoice: ['choices__item--selectable', 'add-choice'], + noResults: ['has-no-results'], + noChoices: ['has-no-choices'], + }; + var DEFAULT_CONFIG = { + items: [], + choices: [], + silent: false, + renderChoiceLimit: -1, + maxItemCount: -1, + closeDropdownOnSelect: 'auto', + singleModeForMultiSelect: false, + addChoices: false, + addItems: true, + addItemFilter: function (value) { return !!value && value !== ''; }, + removeItems: true, + removeItemButton: false, + removeItemButtonAlignLeft: false, + editItems: false, + allowHTML: false, + allowHtmlUserInput: false, + duplicateItemsAllowed: true, + delimiter: ',', + paste: true, + searchEnabled: true, + searchChoices: true, + searchFloor: 1, + searchResultLimit: 4, + searchFields: ['label', 'value'], + position: 'auto', + resetScrollPosition: true, + shouldSort: true, + shouldSortItems: false, + sorter: sortByAlpha, + shadowRoot: null, + placeholder: true, + placeholderValue: null, + searchPlaceholderValue: null, + prependValue: null, + appendValue: null, + renderSelectedChoices: 'auto', + loadingText: 'Loading...', + noResultsText: 'No results found', + noChoicesText: 'No choices to choose from', + itemSelectText: 'Press to select', + uniqueItemText: 'Only unique values can be added', + customAddItemText: 'Only values matching specific conditions can be added', + addItemText: function (value) { return "Press Enter to add \"".concat(value, "\""); }, + removeItemIconText: function () { return "Remove item"; }, + removeItemLabelText: function (value) { return "Remove item: ".concat(value); }, + maxItemText: function (maxItemCount) { return "Only ".concat(maxItemCount, " values can be added"); }, + valueComparer: function (value1, value2) { return value1 === value2; }, + fuseOptions: { + includeScore: true, + }, + labelId: '', + callbackOnInit: null, + callbackOnCreateTemplates: null, + classNames: DEFAULT_CLASSNAMES, + appendGroupInSearch: false, + }; + + function items(s, action) { + var state = s; + var update = true; + switch (action.type) { + case ActionType.ADD_ITEM: { + var item = action.item; + item.selected = true; + var el = item.element; + if (el) { + el.selected = true; + el.setAttribute('selected', ''); + } + state.push(item); + state.forEach(function (choice) { + choice.highlighted = false; + }); + break; + } + case ActionType.REMOVE_ITEM: { + var item_1 = action.item; + item_1.selected = false; + var el = item_1.element; + if (el) { + el.selected = false; + el.removeAttribute('selected'); + // For a select-one, if all options are deselected, the first item is selected. To set a black value, select.value needs to be set + var select = el.parentElement; + if (select && isHtmlSelectElement(select) && select.type === SELECT_ONE_TYPE) { + select.value = ''; + } + } + state = state.filter(function (choice) { return choice.id !== item_1.id; }); + break; + } + case ActionType.REMOVE_CHOICE: { + state = state.filter(function (item) { return item.id !== action.choice.id; }); + break; + } + case ActionType.HIGHLIGHT_ITEM: { + var highlightItemAction_1 = action; + state.forEach(function (choice) { + if (choice.id === highlightItemAction_1.item.id) { + choice.highlighted = highlightItemAction_1.highlighted; + } + }); + break; + } + default: { + update = false; + break; + } + } + return { state: state, update: update }; + } + + function groups(s, action) { + var state = s; + var update = true; + switch (action.type) { + case ActionType.ADD_GROUP: { + state.push(action.group); + break; + } + case ActionType.CLEAR_CHOICES: { + state = []; + break; + } + default: { + update = false; + break; + } + } + return { state: state, update: update }; + } + + /* eslint-disable */ + function choices(s, action) { + var state = s; + var update = true; + switch (action.type) { + case ActionType.ADD_CHOICE: { + /* + A disabled choice appears in the choice dropdown but cannot be selected + A selected choice has been added to the passed input's value (added as an item) + An active choice appears within the choice dropdown + */ + state.push(action.choice); + break; + } + case ActionType.REMOVE_CHOICE: { + state = state.filter(function (obj) { return obj.id !== action.choice.id; }); + break; + } + case ActionType.ADD_ITEM: + case ActionType.REMOVE_ITEM: { + break; + } + case ActionType.FILTER_CHOICES: { + // avoid O(n^2) algorithm complexity when searching/filtering choices + var scoreLookup_1 = []; + action.results.forEach(function (result) { + scoreLookup_1[result.item.id] = result; + }); + state.forEach(function (choice) { + var result = scoreLookup_1[choice.id]; + if (result !== undefined) { + choice.score = result.score; + choice.rank = result.rank; + choice.active = true; + } + else { + choice.score = 0; + choice.rank = 0; + choice.active = false; + } + }); + break; + } + case ActionType.ACTIVATE_CHOICES: { + state.forEach(function (choice) { + choice.active = action.active; + }); + break; + } + case ActionType.CLEAR_CHOICES: { + state = []; + break; + } + default: { + update = false; + break; + } + } + return { state: state, update: update }; + } + + var reducers = { + groups: groups, + items: items, + choices: choices, + }; + var Store = /** @class */ (function () { + function Store() { + this._state = this.defaultState; + this._listeners = []; + this._txn = 0; + } + Object.defineProperty(Store.prototype, "defaultState", { + // eslint-disable-next-line class-methods-use-this + get: function () { + return { + groups: [], + items: [], + choices: [], + }; + }, + enumerable: false, + configurable: true + }); + // eslint-disable-next-line class-methods-use-this + Store.prototype.changeSet = function (init) { + return { + groups: init, + items: init, + choices: init, + }; + }; + Store.prototype.reset = function () { + this._state = this.defaultState; + var changes = this.changeSet(true); + if (this._txn) { + this._changeSet = changes; + } + else { + this._listeners.forEach(function (l) { return l(changes); }); + } + }; + Store.prototype.subscribe = function (onChange) { + this._listeners.push(onChange); + }; + Store.prototype.dispatch = function (action) { + var state = this._state; + var hasChanges = false; + var changes = this._changeSet || this.changeSet(false); + Object.keys(reducers).forEach(function (key) { + var stateUpdate = reducers[key](state[key], action); + if (stateUpdate.update) { + hasChanges = true; + changes[key] = true; + state[key] = stateUpdate.state; + } + }); + if (hasChanges) { + if (this._txn) { + this._changeSet = changes; + } + else { + this._listeners.forEach(function (l) { return l(changes); }); + } + } + }; + Store.prototype.withTxn = function (func) { + this._txn++; + try { + func(); + } + finally { + this._txn = Math.max(0, this._txn - 1); + if (!this._txn) { + var changeSet_1 = this._changeSet; + if (changeSet_1) { + this._changeSet = undefined; + this._listeners.forEach(function (l) { return l(changeSet_1); }); + } + } + } + }; + Object.defineProperty(Store.prototype, "state", { + /** + * Get store object + */ + get: function () { + return this._state; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "items", { + /** + * Get items from store + */ + get: function () { + return this.state.items; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "highlightedActiveItems", { + /** + * Get highlighted items from store + */ + get: function () { + return this.items.filter(function (item) { return !item.disabled && item.active && item.highlighted; }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "choices", { + /** + * Get choices from store + */ + get: function () { + return this.state.choices; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "activeChoices", { + /** + * Get active choices from store + */ + get: function () { + return this.choices.filter(function (choice) { return choice.active; }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "searchableChoices", { + /** + * Get choices that can be searched (excluding placeholders) + */ + get: function () { + return this.choices.filter(function (choice) { return !choice.disabled && !choice.placeholder; }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "groups", { + /** + * Get groups from store + */ + get: function () { + return this.state.groups; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "activeGroups", { + /** + * Get active groups from store + */ + get: function () { + var _this = this; + return this.state.groups.filter(function (group) { + var isActive = group.active && !group.disabled; + var hasActiveOptions = _this.state.choices.some(function (choice) { return choice.active && !choice.disabled; }); + return isActive && hasActiveOptions; + }, []); + }, + enumerable: false, + configurable: true + }); + Store.prototype.inTxn = function () { + return this._txn > 0; + }; + /** + * Get single choice by it's ID + */ + Store.prototype.getChoiceById = function (id) { + return this.activeChoices.find(function (choice) { return choice.id === id; }); + }; + /** + * Get group by group id + */ + Store.prototype.getGroupById = function (id) { + return this.groups.find(function (group) { return group.id === id; }); + }; + return Store; + }()); + + var NoticeTypes = { + noChoices: 'no-choices', + noResults: 'no-results', + addChoice: 'add-choice', + generic: '', + }; + + function _defineProperty(e, r, t) { + return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { + value: t, + enumerable: !0, + configurable: !0, + writable: !0 + }) : e[r] = t, e; + } + function ownKeys(e, r) { + var t = Object.keys(e); + if (Object.getOwnPropertySymbols) { + var o = Object.getOwnPropertySymbols(e); + r && (o = o.filter(function (r) { + return Object.getOwnPropertyDescriptor(e, r).enumerable; + })), t.push.apply(t, o); + } + return t; + } + function _objectSpread2(e) { + for (var r = 1; r < arguments.length; r++) { + var t = null != arguments[r] ? arguments[r] : {}; + r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { + _defineProperty(e, r, t[r]); + }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { + Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); + }); + } + return e; + } + function _toPrimitive(t, r) { + if ("object" != typeof t || !t) return t; + var e = t[Symbol.toPrimitive]; + if (void 0 !== e) { + var i = e.call(t, r || "default"); + if ("object" != typeof i) return i; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return ("string" === r ? String : Number)(t); + } + function _toPropertyKey(t) { + var i = _toPrimitive(t, "string"); + return "symbol" == typeof i ? i : i + ""; + } + + /** + * Fuse.js v7.0.0 - Lightweight fuzzy-search (http://fusejs.io) + * + * Copyright (c) 2023 Kiro Risk (http://kiro.me) + * All Rights Reserved. Apache Software License 2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + function isArray(value) { + return !Array.isArray ? getTag(value) === '[object Array]' : Array.isArray(value); + } + + // Adapted from: https://github.com/lodash/lodash/blob/master/.internal/baseToString.js + const INFINITY = 1 / 0; + function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + let result = value + ''; + return result == '0' && 1 / value == -INFINITY ? '-0' : result; + } + function toString(value) { + return value == null ? '' : baseToString(value); + } + function isString(value) { + return typeof value === 'string'; + } + function isNumber(value) { + return typeof value === 'number'; + } + + // Adapted from: https://github.com/lodash/lodash/blob/master/isBoolean.js + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && getTag(value) == '[object Boolean]'; + } + function isObject(value) { + return typeof value === 'object'; + } + + // Checks if `value` is object-like. + function isObjectLike(value) { + return isObject(value) && value !== null; + } + function isDefined(value) { + return value !== undefined && value !== null; + } + function isBlank(value) { + return !value.trim().length; + } + + // Gets the `toStringTag` of `value`. + // Adapted from: https://github.com/lodash/lodash/blob/master/.internal/getTag.js + function getTag(value) { + return value == null ? value === undefined ? '[object Undefined]' : '[object Null]' : Object.prototype.toString.call(value); + } + const EXTENDED_SEARCH_UNAVAILABLE = 'Extended search is not available'; + const INCORRECT_INDEX_TYPE = "Incorrect 'index' type"; + const LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY = key => `Invalid value for key ${key}`; + const PATTERN_LENGTH_TOO_LARGE = max => `Pattern length exceeds max of ${max}.`; + const MISSING_KEY_PROPERTY = name => `Missing ${name} property in key`; + const INVALID_KEY_WEIGHT_VALUE = key => `Property 'weight' in key '${key}' must be a positive integer`; + const hasOwn = Object.prototype.hasOwnProperty; + class KeyStore { + constructor(keys) { + this._keys = []; + this._keyMap = {}; + let totalWeight = 0; + keys.forEach(key => { + let obj = createKey(key); + this._keys.push(obj); + this._keyMap[obj.id] = obj; + totalWeight += obj.weight; + }); + + // Normalize weights so that their sum is equal to 1 + this._keys.forEach(key => { + key.weight /= totalWeight; + }); + } + get(keyId) { + return this._keyMap[keyId]; + } + keys() { + return this._keys; + } + toJSON() { + return JSON.stringify(this._keys); + } + } + function createKey(key) { + let path = null; + let id = null; + let src = null; + let weight = 1; + let getFn = null; + if (isString(key) || isArray(key)) { + src = key; + path = createKeyPath(key); + id = createKeyId(key); } else { - _this._addChoice({ - value: value, - label: label, - isSelected: !!choice.selected, - isDisabled: !!choice.disabled, - placeholder: !!choice.placeholder, - customProperties: customProperties - }); + if (!hasOwn.call(key, 'name')) { + throw new Error(MISSING_KEY_PROPERTY('name')); + } + const name = key.name; + src = name; + if (hasOwn.call(key, 'weight')) { + weight = key.weight; + if (weight <= 0) { + throw new Error(INVALID_KEY_WEIGHT_VALUE(name)); + } + } + path = createKeyPath(name); + id = createKeyId(name); + getFn = key.getFn; } - }); - }; - Choices.prototype._addPredefinedItems = function (items) { - var _this = this; - items.forEach(function (item) { - if (typeof item === 'object' && item.value) { - _this._addItem({ - value: item.value, - label: item.label, - choiceId: item.id, - customProperties: item.customProperties, - placeholder: item.placeholder - }); - } - if (typeof item === 'string') { - _this._addItem({ - value: item - }); - } - }); - }; - Choices.prototype._setChoiceOrItem = function (item) { - var _this = this; - var itemType = (0, utils_1.getType)(item).toLowerCase(); - var handleType = { - object: function () { - if (!item.value) { + return { + path, + id, + weight, + src, + getFn + }; + } + function createKeyPath(key) { + return isArray(key) ? key : key.split('.'); + } + function createKeyId(key) { + return isArray(key) ? key.join('.') : key; + } + function get(obj, path) { + let list = []; + let arr = false; + const deepGet = (obj, path, index) => { + if (!isDefined(obj)) { return; } - // If we are dealing with a select input, we need to create an option first - // that is then selected. For text inputs we can just add items normally. - if (!_this._isTextElement) { - _this._addChoice({ - value: item.value, - label: item.label, - isSelected: true, - isDisabled: false, - customProperties: item.customProperties, - placeholder: item.placeholder - }); + if (!path[index]) { + // If there's no path left, we've arrived at the object we care about. + list.push(obj); } else { - _this._addItem({ - value: item.value, - label: item.label, - choiceId: item.id, - customProperties: item.customProperties, - placeholder: item.placeholder - }); - } - }, - string: function () { - if (!_this._isTextElement) { - _this._addChoice({ - value: item, - label: item, - isSelected: true, - isDisabled: false - }); - } else { - _this._addItem({ - value: item - }); - } - } - }; - handleType[itemType](); - }; - Choices.prototype._findAndSelectChoiceByValue = function (value) { - var _this = this; - var choices = this._store.choices; - // Check 'value' property exists and the choice isn't already selected - var foundChoice = choices.find(function (choice) { - return _this.config.valueComparer(choice.value, value); - }); - if (foundChoice && !foundChoice.selected) { - this._addItem({ - value: foundChoice.value, - label: foundChoice.label, - choiceId: foundChoice.id, - groupId: foundChoice.groupId, - customProperties: foundChoice.customProperties, - placeholder: foundChoice.placeholder, - keyCode: foundChoice.keyCode - }); - } - }; - Choices.prototype._generatePlaceholderValue = function () { - if (this._isSelectElement && this.passedElement.placeholderOption) { - var placeholderOption = this.passedElement.placeholderOption; - return placeholderOption ? placeholderOption.text : null; - } - var _a = this.config, - placeholder = _a.placeholder, - placeholderValue = _a.placeholderValue; - var dataset = this.passedElement.element.dataset; - if (placeholder) { - if (placeholderValue) { - return placeholderValue; - } - if (dataset.placeholder) { - return dataset.placeholder; - } - } - return null; - }; - return Choices; -}(); -exports["default"] = Choices; - -/***/ }), - -/***/ 613: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -var utils_1 = __webpack_require__(799); -var constants_1 = __webpack_require__(883); -var Container = /** @class */function () { - function Container(_a) { - var element = _a.element, - type = _a.type, - classNames = _a.classNames, - position = _a.position; - this.element = element; - this.classNames = classNames; - this.type = type; - this.position = position; - this.isOpen = false; - this.isFlipped = false; - this.isFocussed = false; - this.isDisabled = false; - this.isLoading = false; - this._onFocus = this._onFocus.bind(this); - this._onBlur = this._onBlur.bind(this); - } - Container.prototype.addEventListeners = function () { - this.element.addEventListener('focus', this._onFocus); - this.element.addEventListener('blur', this._onBlur); - }; - Container.prototype.removeEventListeners = function () { - this.element.removeEventListener('focus', this._onFocus); - this.element.removeEventListener('blur', this._onBlur); - }; - /** - * Determine whether container should be flipped based on passed - * dropdown position - */ - Container.prototype.shouldFlip = function (dropdownPos) { - if (typeof dropdownPos !== 'number') { - return false; - } - // If flip is enabled and the dropdown bottom position is - // greater than the window height flip the dropdown. - var shouldFlip = false; - if (this.position === 'auto') { - shouldFlip = !window.matchMedia("(min-height: ".concat(dropdownPos + 1, "px)")).matches; - } else if (this.position === 'top') { - shouldFlip = true; - } - return shouldFlip; - }; - Container.prototype.setActiveDescendant = function (activeDescendantID) { - this.element.setAttribute('aria-activedescendant', activeDescendantID); - }; - Container.prototype.removeActiveDescendant = function () { - this.element.removeAttribute('aria-activedescendant'); - }; - Container.prototype.open = function (dropdownPos) { - this.element.classList.add(this.classNames.openState); - this.element.setAttribute('aria-expanded', 'true'); - this.isOpen = true; - if (this.shouldFlip(dropdownPos)) { - this.element.classList.add(this.classNames.flippedState); - this.isFlipped = true; - } - }; - Container.prototype.close = function () { - this.element.classList.remove(this.classNames.openState); - this.element.setAttribute('aria-expanded', 'false'); - this.removeActiveDescendant(); - this.isOpen = false; - // A dropdown flips if it does not have space within the page - if (this.isFlipped) { - this.element.classList.remove(this.classNames.flippedState); - this.isFlipped = false; - } - }; - Container.prototype.focus = function () { - if (!this.isFocussed) { - this.element.focus(); - } - }; - Container.prototype.addFocusState = function () { - this.element.classList.add(this.classNames.focusState); - }; - Container.prototype.removeFocusState = function () { - this.element.classList.remove(this.classNames.focusState); - }; - Container.prototype.enable = function () { - this.element.classList.remove(this.classNames.disabledState); - this.element.removeAttribute('aria-disabled'); - if (this.type === constants_1.SELECT_ONE_TYPE) { - this.element.setAttribute('tabindex', '0'); - } - this.isDisabled = false; - }; - Container.prototype.disable = function () { - this.element.classList.add(this.classNames.disabledState); - this.element.setAttribute('aria-disabled', 'true'); - if (this.type === constants_1.SELECT_ONE_TYPE) { - this.element.setAttribute('tabindex', '-1'); - } - this.isDisabled = true; - }; - Container.prototype.wrap = function (element) { - (0, utils_1.wrap)(element, this.element); - }; - Container.prototype.unwrap = function (element) { - if (this.element.parentNode) { - // Move passed element outside this element - this.element.parentNode.insertBefore(element, this.element); - // Remove this element - this.element.parentNode.removeChild(this.element); - } - }; - Container.prototype.addLoadingState = function () { - this.element.classList.add(this.classNames.loadingState); - this.element.setAttribute('aria-busy', 'true'); - this.isLoading = true; - }; - Container.prototype.removeLoadingState = function () { - this.element.classList.remove(this.classNames.loadingState); - this.element.removeAttribute('aria-busy'); - this.isLoading = false; - }; - Container.prototype._onFocus = function () { - this.isFocussed = true; - }; - Container.prototype._onBlur = function () { - this.isFocussed = false; - }; - return Container; -}(); -exports["default"] = Container; - -/***/ }), - -/***/ 217: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -var Dropdown = /** @class */function () { - function Dropdown(_a) { - var element = _a.element, - type = _a.type, - classNames = _a.classNames; - this.element = element; - this.classNames = classNames; - this.type = type; - this.isActive = false; - } - Object.defineProperty(Dropdown.prototype, "distanceFromTopWindow", { - /** - * Bottom position of dropdown in viewport coordinates - */ - get: function () { - return this.element.getBoundingClientRect().bottom; - }, - enumerable: false, - configurable: true - }); - Dropdown.prototype.getChild = function (selector) { - return this.element.querySelector(selector); - }; - /** - * Show dropdown to user by adding active state class - */ - Dropdown.prototype.show = function () { - this.element.classList.add(this.classNames.activeState); - this.element.setAttribute('aria-expanded', 'true'); - this.isActive = true; - return this; - }; - /** - * Hide dropdown from user - */ - Dropdown.prototype.hide = function () { - this.element.classList.remove(this.classNames.activeState); - this.element.setAttribute('aria-expanded', 'false'); - this.isActive = false; - return this; - }; - return Dropdown; -}(); -exports["default"] = Dropdown; - -/***/ }), - -/***/ 520: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -var __importDefault = this && this.__importDefault || function (mod) { - return mod && mod.__esModule ? mod : { - "default": mod - }; -}; -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.WrappedSelect = exports.WrappedInput = exports.List = exports.Input = exports.Container = exports.Dropdown = void 0; -var dropdown_1 = __importDefault(__webpack_require__(217)); -exports.Dropdown = dropdown_1.default; -var container_1 = __importDefault(__webpack_require__(613)); -exports.Container = container_1.default; -var input_1 = __importDefault(__webpack_require__(11)); -exports.Input = input_1.default; -var list_1 = __importDefault(__webpack_require__(624)); -exports.List = list_1.default; -var wrapped_input_1 = __importDefault(__webpack_require__(541)); -exports.WrappedInput = wrapped_input_1.default; -var wrapped_select_1 = __importDefault(__webpack_require__(982)); -exports.WrappedSelect = wrapped_select_1.default; - -/***/ }), - -/***/ 11: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -var utils_1 = __webpack_require__(799); -var constants_1 = __webpack_require__(883); -var Input = /** @class */function () { - function Input(_a) { - var element = _a.element, - type = _a.type, - classNames = _a.classNames, - preventPaste = _a.preventPaste; - this.element = element; - this.type = type; - this.classNames = classNames; - this.preventPaste = preventPaste; - this.isFocussed = this.element.isEqualNode(document.activeElement); - this.isDisabled = element.disabled; - this._onPaste = this._onPaste.bind(this); - this._onInput = this._onInput.bind(this); - this._onFocus = this._onFocus.bind(this); - this._onBlur = this._onBlur.bind(this); - } - Object.defineProperty(Input.prototype, "placeholder", { - set: function (placeholder) { - this.element.placeholder = placeholder; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Input.prototype, "value", { - get: function () { - return (0, utils_1.sanitise)(this.element.value); - }, - set: function (value) { - this.element.value = value; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Input.prototype, "rawValue", { - get: function () { - return this.element.value; - }, - enumerable: false, - configurable: true - }); - Input.prototype.addEventListeners = function () { - this.element.addEventListener('paste', this._onPaste); - this.element.addEventListener('input', this._onInput, { - passive: true - }); - this.element.addEventListener('focus', this._onFocus, { - passive: true - }); - this.element.addEventListener('blur', this._onBlur, { - passive: true - }); - }; - Input.prototype.removeEventListeners = function () { - this.element.removeEventListener('input', this._onInput); - this.element.removeEventListener('paste', this._onPaste); - this.element.removeEventListener('focus', this._onFocus); - this.element.removeEventListener('blur', this._onBlur); - }; - Input.prototype.enable = function () { - this.element.removeAttribute('disabled'); - this.isDisabled = false; - }; - Input.prototype.disable = function () { - this.element.setAttribute('disabled', ''); - this.isDisabled = true; - }; - Input.prototype.focus = function () { - if (!this.isFocussed) { - this.element.focus(); - } - }; - Input.prototype.blur = function () { - if (this.isFocussed) { - this.element.blur(); - } - }; - Input.prototype.clear = function (setWidth) { - if (setWidth === void 0) { - setWidth = true; - } - if (this.element.value) { - this.element.value = ''; - } - if (setWidth) { - this.setWidth(); - } - return this; - }; - /** - * Set the correct input width based on placeholder - * value or input value - */ - Input.prototype.setWidth = function () { - // Resize input to contents or placeholder - var _a = this.element, - style = _a.style, - value = _a.value, - placeholder = _a.placeholder; - style.minWidth = "".concat(placeholder.length + 1, "ch"); - style.width = "".concat(value.length + 1, "ch"); - }; - Input.prototype.setActiveDescendant = function (activeDescendantID) { - this.element.setAttribute('aria-activedescendant', activeDescendantID); - }; - Input.prototype.removeActiveDescendant = function () { - this.element.removeAttribute('aria-activedescendant'); - }; - Input.prototype._onInput = function () { - if (this.type !== constants_1.SELECT_ONE_TYPE) { - this.setWidth(); - } - }; - Input.prototype._onPaste = function (event) { - if (this.preventPaste) { - event.preventDefault(); - } - }; - Input.prototype._onFocus = function () { - this.isFocussed = true; - }; - Input.prototype._onBlur = function () { - this.isFocussed = false; - }; - return Input; -}(); -exports["default"] = Input; - -/***/ }), - -/***/ 624: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -var constants_1 = __webpack_require__(883); -var List = /** @class */function () { - function List(_a) { - var element = _a.element; - this.element = element; - this.scrollPos = this.element.scrollTop; - this.height = this.element.offsetHeight; - } - List.prototype.clear = function () { - this.element.innerHTML = ''; - }; - List.prototype.append = function (node) { - this.element.appendChild(node); - }; - List.prototype.getChild = function (selector) { - return this.element.querySelector(selector); - }; - List.prototype.hasChildren = function () { - return this.element.hasChildNodes(); - }; - List.prototype.scrollToTop = function () { - this.element.scrollTop = 0; - }; - List.prototype.scrollToChildElement = function (element, direction) { - var _this = this; - if (!element) { - return; - } - var listHeight = this.element.offsetHeight; - // Scroll position of dropdown - var listScrollPosition = this.element.scrollTop + listHeight; - var elementHeight = element.offsetHeight; - // Distance from bottom of element to top of parent - var elementPos = element.offsetTop + elementHeight; - // Difference between the element and scroll position - var destination = direction > 0 ? this.element.scrollTop + elementPos - listScrollPosition : element.offsetTop; - requestAnimationFrame(function () { - _this._animateScroll(destination, direction); - }); - }; - List.prototype._scrollDown = function (scrollPos, strength, destination) { - var easing = (destination - scrollPos) / strength; - var distance = easing > 1 ? easing : 1; - this.element.scrollTop = scrollPos + distance; - }; - List.prototype._scrollUp = function (scrollPos, strength, destination) { - var easing = (scrollPos - destination) / strength; - var distance = easing > 1 ? easing : 1; - this.element.scrollTop = scrollPos - distance; - }; - List.prototype._animateScroll = function (destination, direction) { - var _this = this; - var strength = constants_1.SCROLLING_SPEED; - var choiceListScrollTop = this.element.scrollTop; - var continueAnimation = false; - if (direction > 0) { - this._scrollDown(choiceListScrollTop, strength, destination); - if (choiceListScrollTop < destination) { - continueAnimation = true; - } - } else { - this._scrollUp(choiceListScrollTop, strength, destination); - if (choiceListScrollTop > destination) { - continueAnimation = true; - } - } - if (continueAnimation) { - requestAnimationFrame(function () { - _this._animateScroll(destination, direction); - }); - } - }; - return List; -}(); -exports["default"] = List; - -/***/ }), - -/***/ 730: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -var utils_1 = __webpack_require__(799); -var WrappedElement = /** @class */function () { - function WrappedElement(_a) { - var element = _a.element, - classNames = _a.classNames; - this.element = element; - this.classNames = classNames; - if (!(element instanceof HTMLInputElement) && !(element instanceof HTMLSelectElement)) { - throw new TypeError('Invalid element passed'); - } - this.isDisabled = false; - } - Object.defineProperty(WrappedElement.prototype, "isActive", { - get: function () { - return this.element.dataset.choice === 'active'; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(WrappedElement.prototype, "dir", { - get: function () { - return this.element.dir; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(WrappedElement.prototype, "value", { - get: function () { - return this.element.value; - }, - set: function (value) { - // you must define setter here otherwise it will be readonly property - this.element.value = value; - }, - enumerable: false, - configurable: true - }); - WrappedElement.prototype.conceal = function () { - // Hide passed input - this.element.classList.add(this.classNames.input); - this.element.hidden = true; - // Remove element from tab index - this.element.tabIndex = -1; - // Backup original styles if any - var origStyle = this.element.getAttribute('style'); - if (origStyle) { - this.element.setAttribute('data-choice-orig-style', origStyle); - } - this.element.setAttribute('data-choice', 'active'); - }; - WrappedElement.prototype.reveal = function () { - // Reinstate passed element - this.element.classList.remove(this.classNames.input); - this.element.hidden = false; - this.element.removeAttribute('tabindex'); - // Recover original styles if any - var origStyle = this.element.getAttribute('data-choice-orig-style'); - if (origStyle) { - this.element.removeAttribute('data-choice-orig-style'); - this.element.setAttribute('style', origStyle); - } else { - this.element.removeAttribute('style'); - } - this.element.removeAttribute('data-choice'); - // Re-assign values - this is weird, I know - // @todo Figure out why we need to do this - this.element.value = this.element.value; // eslint-disable-line no-self-assign - }; - - WrappedElement.prototype.enable = function () { - this.element.removeAttribute('disabled'); - this.element.disabled = false; - this.isDisabled = false; - }; - WrappedElement.prototype.disable = function () { - this.element.setAttribute('disabled', ''); - this.element.disabled = true; - this.isDisabled = true; - }; - WrappedElement.prototype.triggerEvent = function (eventType, data) { - (0, utils_1.dispatchEvent)(this.element, eventType, data); - }; - return WrappedElement; -}(); -exports["default"] = WrappedElement; - -/***/ }), - -/***/ 541: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; - }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); -var __importDefault = this && this.__importDefault || function (mod) { - return mod && mod.__esModule ? mod : { - "default": mod - }; -}; -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -var wrapped_element_1 = __importDefault(__webpack_require__(730)); -var WrappedInput = /** @class */function (_super) { - __extends(WrappedInput, _super); - function WrappedInput(_a) { - var element = _a.element, - classNames = _a.classNames, - delimiter = _a.delimiter; - var _this = _super.call(this, { - element: element, - classNames: classNames - }) || this; - _this.delimiter = delimiter; - return _this; - } - Object.defineProperty(WrappedInput.prototype, "value", { - get: function () { - return this.element.value; - }, - set: function (value) { - this.element.setAttribute('value', value); - this.element.value = value; - }, - enumerable: false, - configurable: true - }); - return WrappedInput; -}(wrapped_element_1.default); -exports["default"] = WrappedInput; - -/***/ }), - -/***/ 982: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; - }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); -var __importDefault = this && this.__importDefault || function (mod) { - return mod && mod.__esModule ? mod : { - "default": mod - }; -}; -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -var wrapped_element_1 = __importDefault(__webpack_require__(730)); -var WrappedSelect = /** @class */function (_super) { - __extends(WrappedSelect, _super); - function WrappedSelect(_a) { - var element = _a.element, - classNames = _a.classNames, - template = _a.template; - var _this = _super.call(this, { - element: element, - classNames: classNames - }) || this; - _this.template = template; - return _this; - } - Object.defineProperty(WrappedSelect.prototype, "placeholderOption", { - get: function () { - return this.element.querySelector('option[value=""]') || - // Backward compatibility layer for the non-standard placeholder attribute supported in older versions. - this.element.querySelector('option[placeholder]'); - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(WrappedSelect.prototype, "optionGroups", { - get: function () { - return Array.from(this.element.getElementsByTagName('OPTGROUP')); - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(WrappedSelect.prototype, "options", { - get: function () { - return Array.from(this.element.options); - }, - set: function (options) { - var _this = this; - var fragment = document.createDocumentFragment(); - var addOptionToFragment = function (data) { - // Create a standard select option - var option = _this.template(data); - // Append it to fragment - fragment.appendChild(option); - }; - // Add each list item to list - options.forEach(function (optionData) { - return addOptionToFragment(optionData); - }); - this.appendDocFragment(fragment); - }, - enumerable: false, - configurable: true - }); - WrappedSelect.prototype.appendDocFragment = function (fragment) { - this.element.innerHTML = ''; - this.element.appendChild(fragment); - }; - return WrappedSelect; -}(wrapped_element_1.default); -exports["default"] = WrappedSelect; - -/***/ }), - -/***/ 883: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.SCROLLING_SPEED = exports.SELECT_MULTIPLE_TYPE = exports.SELECT_ONE_TYPE = exports.TEXT_TYPE = exports.KEY_CODES = exports.ACTION_TYPES = exports.EVENTS = void 0; -exports.EVENTS = { - showDropdown: 'showDropdown', - hideDropdown: 'hideDropdown', - change: 'change', - choice: 'choice', - search: 'search', - addItem: 'addItem', - removeItem: 'removeItem', - highlightItem: 'highlightItem', - highlightChoice: 'highlightChoice', - unhighlightItem: 'unhighlightItem' -}; -exports.ACTION_TYPES = { - ADD_CHOICE: 'ADD_CHOICE', - FILTER_CHOICES: 'FILTER_CHOICES', - ACTIVATE_CHOICES: 'ACTIVATE_CHOICES', - CLEAR_CHOICES: 'CLEAR_CHOICES', - ADD_GROUP: 'ADD_GROUP', - ADD_ITEM: 'ADD_ITEM', - REMOVE_ITEM: 'REMOVE_ITEM', - HIGHLIGHT_ITEM: 'HIGHLIGHT_ITEM', - CLEAR_ALL: 'CLEAR_ALL', - RESET_TO: 'RESET_TO', - SET_IS_LOADING: 'SET_IS_LOADING' -}; -exports.KEY_CODES = { - BACK_KEY: 46, - DELETE_KEY: 8, - ENTER_KEY: 13, - A_KEY: 65, - ESC_KEY: 27, - UP_KEY: 38, - DOWN_KEY: 40, - PAGE_UP_KEY: 33, - PAGE_DOWN_KEY: 34 -}; -exports.TEXT_TYPE = 'text'; -exports.SELECT_ONE_TYPE = 'select-one'; -exports.SELECT_MULTIPLE_TYPE = 'select-multiple'; -exports.SCROLLING_SPEED = 4; - -/***/ }), - -/***/ 789: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.DEFAULT_CONFIG = exports.DEFAULT_CLASSNAMES = void 0; -var utils_1 = __webpack_require__(799); -exports.DEFAULT_CLASSNAMES = { - containerOuter: 'choices', - containerInner: 'choices__inner', - input: 'choices__input', - inputCloned: 'choices__input--cloned', - list: 'choices__list', - listItems: 'choices__list--multiple', - listSingle: 'choices__list--single', - listDropdown: 'choices__list--dropdown', - item: 'choices__item', - itemSelectable: 'choices__item--selectable', - itemDisabled: 'choices__item--disabled', - itemChoice: 'choices__item--choice', - placeholder: 'choices__placeholder', - group: 'choices__group', - groupHeading: 'choices__heading', - button: 'choices__button', - activeState: 'is-active', - focusState: 'is-focused', - openState: 'is-open', - disabledState: 'is-disabled', - highlightedState: 'is-highlighted', - selectedState: 'is-selected', - flippedState: 'is-flipped', - loadingState: 'is-loading', - noResults: 'has-no-results', - noChoices: 'has-no-choices' -}; -exports.DEFAULT_CONFIG = { - items: [], - choices: [], - silent: false, - renderChoiceLimit: -1, - maxItemCount: -1, - addItems: true, - addItemFilter: null, - removeItems: true, - removeItemButton: false, - editItems: false, - allowHTML: true, - duplicateItemsAllowed: true, - delimiter: ',', - paste: true, - searchEnabled: true, - searchChoices: true, - searchFloor: 1, - searchResultLimit: 4, - searchFields: ['label', 'value'], - position: 'auto', - resetScrollPosition: true, - shouldSort: true, - shouldSortItems: false, - sorter: utils_1.sortByAlpha, - placeholder: true, - placeholderValue: null, - searchPlaceholderValue: null, - prependValue: null, - appendValue: null, - renderSelectedChoices: 'auto', - loadingText: 'Loading...', - noResultsText: 'No results found', - noChoicesText: 'No choices to choose from', - itemSelectText: 'Press to select', - uniqueItemText: 'Only unique values can be added', - customAddItemText: 'Only values matching specific conditions can be added', - addItemText: function (value) { - return "Press Enter to add \"".concat((0, utils_1.sanitise)(value), "\""); - }, - maxItemText: function (maxItemCount) { - return "Only ".concat(maxItemCount, " values can be added"); - }, - valueComparer: function (value1, value2) { - return value1 === value2; - }, - fuseOptions: { - includeScore: true - }, - labelId: '', - callbackOnInit: null, - callbackOnCreateTemplates: null, - classNames: exports.DEFAULT_CLASSNAMES -}; - -/***/ }), - -/***/ 18: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 978: -/***/ (function(__unused_webpack_module, exports) { - - - -/* eslint-disable @typescript-eslint/no-explicit-any */ -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 948: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 359: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 285: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 533: -/***/ (function(__unused_webpack_module, exports) { - - - -/* eslint-disable @typescript-eslint/no-explicit-any */ -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 187: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -var __createBinding = this && this.__createBinding || (Object.create ? function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { - enumerable: true, - get: function () { - return m[k]; - } - }; - } - Object.defineProperty(o, k2, desc); -} : function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -}); -var __exportStar = this && this.__exportStar || function (m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -__exportStar(__webpack_require__(18), exports); -__exportStar(__webpack_require__(978), exports); -__exportStar(__webpack_require__(948), exports); -__exportStar(__webpack_require__(359), exports); -__exportStar(__webpack_require__(285), exports); -__exportStar(__webpack_require__(533), exports); -__exportStar(__webpack_require__(287), exports); -__exportStar(__webpack_require__(132), exports); -__exportStar(__webpack_require__(837), exports); -__exportStar(__webpack_require__(598), exports); -__exportStar(__webpack_require__(369), exports); -__exportStar(__webpack_require__(37), exports); -__exportStar(__webpack_require__(47), exports); -__exportStar(__webpack_require__(923), exports); -__exportStar(__webpack_require__(876), exports); - -/***/ }), - -/***/ 287: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 132: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 837: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 598: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 37: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 369: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 47: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 923: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 876: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); - -/***/ }), - -/***/ 799: -/***/ (function(__unused_webpack_module, exports) { - - - -/* eslint-disable @typescript-eslint/no-explicit-any */ -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.parseCustomProperties = exports.diff = exports.cloneObject = exports.existsInArray = exports.dispatchEvent = exports.sortByScore = exports.sortByAlpha = exports.strToEl = exports.sanitise = exports.isScrolledIntoView = exports.getAdjacentEl = exports.wrap = exports.isType = exports.getType = exports.generateId = exports.generateChars = exports.getRandomNumber = void 0; -var getRandomNumber = function (min, max) { - return Math.floor(Math.random() * (max - min) + min); -}; -exports.getRandomNumber = getRandomNumber; -var generateChars = function (length) { - return Array.from({ - length: length - }, function () { - return (0, exports.getRandomNumber)(0, 36).toString(36); - }).join(''); -}; -exports.generateChars = generateChars; -var generateId = function (element, prefix) { - var id = element.id || element.name && "".concat(element.name, "-").concat((0, exports.generateChars)(2)) || (0, exports.generateChars)(4); - id = id.replace(/(:|\.|\[|\]|,)/g, ''); - id = "".concat(prefix, "-").concat(id); - return id; -}; -exports.generateId = generateId; -var getType = function (obj) { - return Object.prototype.toString.call(obj).slice(8, -1); -}; -exports.getType = getType; -var isType = function (type, obj) { - return obj !== undefined && obj !== null && (0, exports.getType)(obj) === type; -}; -exports.isType = isType; -var wrap = function (element, wrapper) { - if (wrapper === void 0) { - wrapper = document.createElement('div'); - } - if (element.parentNode) { - if (element.nextSibling) { - element.parentNode.insertBefore(wrapper, element.nextSibling); - } else { - element.parentNode.appendChild(wrapper); - } - } - return wrapper.appendChild(element); -}; -exports.wrap = wrap; -var getAdjacentEl = function (startEl, selector, direction) { - if (direction === void 0) { - direction = 1; - } - var prop = "".concat(direction > 0 ? 'next' : 'previous', "ElementSibling"); - var sibling = startEl[prop]; - while (sibling) { - if (sibling.matches(selector)) { - return sibling; - } - sibling = sibling[prop]; - } - return sibling; -}; -exports.getAdjacentEl = getAdjacentEl; -var isScrolledIntoView = function (element, parent, direction) { - if (direction === void 0) { - direction = 1; - } - if (!element) { - return false; - } - var isVisible; - if (direction > 0) { - // In view from bottom - isVisible = parent.scrollTop + parent.offsetHeight >= element.offsetTop + element.offsetHeight; - } else { - // In view from top - isVisible = element.offsetTop >= parent.scrollTop; - } - return isVisible; -}; -exports.isScrolledIntoView = isScrolledIntoView; -var sanitise = function (value) { - if (typeof value !== 'string') { - return value; - } - return value.replace(/&/g, '&').replace(/>/g, '>').replace(/ -1) { - return state.map(function (obj) { - var choice = obj; - if (choice.id === parseInt("".concat(addItemAction_1.choiceId), 10)) { - choice.selected = true; - } - return choice; - }); - } - return state; - } - case 'REMOVE_ITEM': - { - var removeItemAction_1 = action; - // When an item is removed and it has an associated choice, - // we want to re-enable it so it can be chosen again - if (removeItemAction_1.choiceId && removeItemAction_1.choiceId > -1) { - return state.map(function (obj) { - var choice = obj; - if (choice.id === parseInt("".concat(removeItemAction_1.choiceId), 10)) { - choice.selected = false; - } - return choice; - }); - } - return state; - } - case 'FILTER_CHOICES': - { - var filterChoicesAction_1 = action; - return state.map(function (obj) { - var choice = obj; - // Set active state based on whether choice is - // within filtered results - choice.active = filterChoicesAction_1.results.some(function (_a) { - var item = _a.item, - score = _a.score; - if (item.id === choice.id) { - choice.score = score; - return true; - } - return false; - }); - return choice; - }); - } - case 'ACTIVATE_CHOICES': - { - var activateChoicesAction_1 = action; - return state.map(function (obj) { - var choice = obj; - choice.active = activateChoicesAction_1.active; - return choice; - }); - } - case 'CLEAR_CHOICES': - { - return exports.defaultState; - } - default: - { - return state; - } - } -} -exports["default"] = choices; - -/***/ }), - -/***/ 871: -/***/ (function(__unused_webpack_module, exports) { - - - -var __spreadArray = this && this.__spreadArray || function (to, from, pack) { - if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); -}; -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.defaultState = void 0; -exports.defaultState = []; -function groups(state, action) { - if (state === void 0) { - state = exports.defaultState; - } - if (action === void 0) { - action = {}; - } - switch (action.type) { - case 'ADD_GROUP': - { - var addGroupAction = action; - return __spreadArray(__spreadArray([], state, true), [{ - id: addGroupAction.id, - value: addGroupAction.value, - active: addGroupAction.active, - disabled: addGroupAction.disabled - }], false); - } - case 'CLEAR_CHOICES': - { - return []; - } - default: - { - return state; - } - } -} -exports["default"] = groups; - -/***/ }), - -/***/ 655: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -var __importDefault = this && this.__importDefault || function (mod) { - return mod && mod.__esModule ? mod : { - "default": mod - }; -}; -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.defaultState = void 0; -var redux_1 = __webpack_require__(791); -var items_1 = __importDefault(__webpack_require__(52)); -var groups_1 = __importDefault(__webpack_require__(871)); -var choices_1 = __importDefault(__webpack_require__(273)); -var loading_1 = __importDefault(__webpack_require__(502)); -var utils_1 = __webpack_require__(799); -exports.defaultState = { - groups: [], - items: [], - choices: [], - loading: false -}; -var appReducer = (0, redux_1.combineReducers)({ - items: items_1.default, - groups: groups_1.default, - choices: choices_1.default, - loading: loading_1.default -}); -var rootReducer = function (passedState, action) { - var state = passedState; - // If we are clearing all items, groups and options we reassign - // state and then pass that state to our proper reducer. This isn't - // mutating our actual state - // See: http://stackoverflow.com/a/35641992 - if (action.type === 'CLEAR_ALL') { - state = exports.defaultState; - } else if (action.type === 'RESET_TO') { - return (0, utils_1.cloneObject)(action.state); - } - return appReducer(state, action); -}; -exports["default"] = rootReducer; - -/***/ }), - -/***/ 52: -/***/ (function(__unused_webpack_module, exports) { - - - -var __spreadArray = this && this.__spreadArray || function (to, from, pack) { - if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); -}; -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.defaultState = void 0; -exports.defaultState = []; -function items(state, action) { - if (state === void 0) { - state = exports.defaultState; - } - if (action === void 0) { - action = {}; - } - switch (action.type) { - case 'ADD_ITEM': - { - var addItemAction = action; - // Add object to items array - var newState = __spreadArray(__spreadArray([], state, true), [{ - id: addItemAction.id, - choiceId: addItemAction.choiceId, - groupId: addItemAction.groupId, - value: addItemAction.value, - label: addItemAction.label, - active: true, - highlighted: false, - customProperties: addItemAction.customProperties, - placeholder: addItemAction.placeholder || false, - keyCode: null - }], false); - return newState.map(function (obj) { - var item = obj; - item.highlighted = false; - return item; - }); - } - case 'REMOVE_ITEM': - { - // Set item to inactive - return state.map(function (obj) { - var item = obj; - if (item.id === action.id) { - item.active = false; - } - return item; - }); - } - case 'HIGHLIGHT_ITEM': - { - var highlightItemAction_1 = action; - return state.map(function (obj) { - var item = obj; - if (item.id === highlightItemAction_1.id) { - item.highlighted = highlightItemAction_1.highlighted; - } - return item; - }); - } - default: - { - return state; - } - } -} -exports["default"] = items; - -/***/ }), - -/***/ 502: -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.defaultState = void 0; -exports.defaultState = false; -var general = function (state, action) { - if (state === void 0) { - state = exports.defaultState; - } - if (action === void 0) { - action = {}; - } - switch (action.type) { - case 'SET_IS_LOADING': - { - return action.isLoading; - } - default: - { - return state; - } - } -}; -exports["default"] = general; - -/***/ }), - -/***/ 744: -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -var __spreadArray = this && this.__spreadArray || function (to, from, pack) { - if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); -}; -var __importDefault = this && this.__importDefault || function (mod) { - return mod && mod.__esModule ? mod : { - "default": mod - }; -}; -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -/* eslint-disable @typescript-eslint/no-explicit-any */ -var redux_1 = __webpack_require__(791); -var index_1 = __importDefault(__webpack_require__(655)); -var Store = /** @class */function () { - function Store() { - this._store = (0, redux_1.createStore)(index_1.default, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()); - } - /** - * Subscribe store to function call (wrapped Redux method) - */ - Store.prototype.subscribe = function (onChange) { - this._store.subscribe(onChange); - }; - /** - * Dispatch event to store (wrapped Redux method) - */ - Store.prototype.dispatch = function (action) { - this._store.dispatch(action); - }; - Object.defineProperty(Store.prototype, "state", { - /** - * Get store object (wrapping Redux method) - */ - get: function () { - return this._store.getState(); - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Store.prototype, "items", { - /** - * Get items from store - */ - get: function () { - return this.state.items; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Store.prototype, "activeItems", { - /** - * Get active items from store - */ - get: function () { - return this.items.filter(function (item) { - return item.active === true; - }); - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Store.prototype, "highlightedActiveItems", { - /** - * Get highlighted items from store - */ - get: function () { - return this.items.filter(function (item) { - return item.active && item.highlighted; - }); - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Store.prototype, "choices", { - /** - * Get choices from store - */ - get: function () { - return this.state.choices; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Store.prototype, "activeChoices", { - /** - * Get active choices from store - */ - get: function () { - return this.choices.filter(function (choice) { - return choice.active === true; - }); - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Store.prototype, "selectableChoices", { - /** - * Get selectable choices from store - */ - get: function () { - return this.choices.filter(function (choice) { - return choice.disabled !== true; - }); - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Store.prototype, "searchableChoices", { - /** - * Get choices that can be searched (excluding placeholders) - */ - get: function () { - return this.selectableChoices.filter(function (choice) { - return choice.placeholder !== true; - }); - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Store.prototype, "placeholderChoice", { - /** - * Get placeholder choice from store - */ - get: function () { - return __spreadArray([], this.choices, true).reverse().find(function (choice) { - return choice.placeholder === true; - }); - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Store.prototype, "groups", { - /** - * Get groups from store - */ - get: function () { - return this.state.groups; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Store.prototype, "activeGroups", { - /** - * Get active groups from store - */ - get: function () { - var _a = this, - groups = _a.groups, - choices = _a.choices; - return groups.filter(function (group) { - var isActive = group.active === true && group.disabled === false; - var hasActiveOptions = choices.some(function (choice) { - return choice.active === true && choice.disabled === false; - }); - return isActive && hasActiveOptions; - }, []); - }, - enumerable: false, - configurable: true - }); - /** - * Get loading state from store - */ - Store.prototype.isLoading = function () { - return this.state.loading; - }; - /** - * Get single choice by it's ID - */ - Store.prototype.getChoiceById = function (id) { - return this.activeChoices.find(function (choice) { - return choice.id === parseInt(id, 10); - }); - }; - /** - * Get group by group id - */ - Store.prototype.getGroupById = function (id) { - return this.groups.find(function (group) { - return group.id === id; - }); - }; - return Store; -}(); -exports["default"] = Store; - -/***/ }), - -/***/ 686: -/***/ (function(__unused_webpack_module, exports) { - - - -/** - * Helpers to create HTML elements used by Choices - * Can be overridden by providing `callbackOnCreateTemplates` option - */ -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -var templates = { - containerOuter: function (_a, dir, isSelectElement, isSelectOneElement, searchEnabled, passedElementType, labelId) { - var containerOuter = _a.classNames.containerOuter; - var div = Object.assign(document.createElement('div'), { - className: containerOuter - }); - div.dataset.type = passedElementType; - if (dir) { - div.dir = dir; - } - if (isSelectOneElement) { - div.tabIndex = 0; - } - if (isSelectElement) { - div.setAttribute('role', searchEnabled ? 'combobox' : 'listbox'); - if (searchEnabled) { - div.setAttribute('aria-autocomplete', 'list'); - } - } - div.setAttribute('aria-haspopup', 'true'); - div.setAttribute('aria-expanded', 'false'); - if (labelId) { - div.setAttribute('aria-labelledby', labelId); - } - return div; - }, - containerInner: function (_a) { - var containerInner = _a.classNames.containerInner; - return Object.assign(document.createElement('div'), { - className: containerInner - }); - }, - itemList: function (_a, isSelectOneElement) { - var _b = _a.classNames, - list = _b.list, - listSingle = _b.listSingle, - listItems = _b.listItems; - return Object.assign(document.createElement('div'), { - className: "".concat(list, " ").concat(isSelectOneElement ? listSingle : listItems) - }); - }, - placeholder: function (_a, value) { - var _b; - var allowHTML = _a.allowHTML, - placeholder = _a.classNames.placeholder; - return Object.assign(document.createElement('div'), (_b = { - className: placeholder - }, _b[allowHTML ? 'innerHTML' : 'innerText'] = value, _b)); - }, - item: function (_a, _b, removeItemButton) { - var _c, _d; - var allowHTML = _a.allowHTML, - _e = _a.classNames, - item = _e.item, - button = _e.button, - highlightedState = _e.highlightedState, - itemSelectable = _e.itemSelectable, - placeholder = _e.placeholder; - var id = _b.id, - value = _b.value, - label = _b.label, - customProperties = _b.customProperties, - active = _b.active, - disabled = _b.disabled, - highlighted = _b.highlighted, - isPlaceholder = _b.placeholder; - var div = Object.assign(document.createElement('div'), (_c = { - className: item - }, _c[allowHTML ? 'innerHTML' : 'innerText'] = label, _c)); - Object.assign(div.dataset, { - item: '', - id: id, - value: value, - customProperties: customProperties - }); - if (active) { - div.setAttribute('aria-selected', 'true'); - } - if (disabled) { - div.setAttribute('aria-disabled', 'true'); - } - if (isPlaceholder) { - div.classList.add(placeholder); - } - div.classList.add(highlighted ? highlightedState : itemSelectable); - if (removeItemButton) { - if (disabled) { - div.classList.remove(itemSelectable); - } - div.dataset.deletable = ''; - /** @todo This MUST be localizable, not hardcoded! */ - var REMOVE_ITEM_TEXT = 'Remove item'; - var removeButton = Object.assign(document.createElement('button'), (_d = { - type: 'button', - className: button - }, _d[allowHTML ? 'innerHTML' : 'innerText'] = REMOVE_ITEM_TEXT, _d)); - removeButton.setAttribute('aria-label', "".concat(REMOVE_ITEM_TEXT, ": '").concat(value, "'")); - removeButton.dataset.button = ''; - div.appendChild(removeButton); - } - return div; - }, - choiceList: function (_a, isSelectOneElement) { - var list = _a.classNames.list; - var div = Object.assign(document.createElement('div'), { - className: list - }); - if (!isSelectOneElement) { - div.setAttribute('aria-multiselectable', 'true'); - } - div.setAttribute('role', 'listbox'); - return div; - }, - choiceGroup: function (_a, _b) { - var _c; - var allowHTML = _a.allowHTML, - _d = _a.classNames, - group = _d.group, - groupHeading = _d.groupHeading, - itemDisabled = _d.itemDisabled; - var id = _b.id, - value = _b.value, - disabled = _b.disabled; - var div = Object.assign(document.createElement('div'), { - className: "".concat(group, " ").concat(disabled ? itemDisabled : '') - }); - div.setAttribute('role', 'group'); - Object.assign(div.dataset, { - group: '', - id: id, - value: value - }); - if (disabled) { - div.setAttribute('aria-disabled', 'true'); - } - div.appendChild(Object.assign(document.createElement('div'), (_c = { - className: groupHeading - }, _c[allowHTML ? 'innerHTML' : 'innerText'] = value, _c))); - return div; - }, - choice: function (_a, _b, selectText) { - var _c; - var allowHTML = _a.allowHTML, - _d = _a.classNames, - item = _d.item, - itemChoice = _d.itemChoice, - itemSelectable = _d.itemSelectable, - selectedState = _d.selectedState, - itemDisabled = _d.itemDisabled, - placeholder = _d.placeholder; - var id = _b.id, - value = _b.value, - label = _b.label, - groupId = _b.groupId, - elementId = _b.elementId, - isDisabled = _b.disabled, - isSelected = _b.selected, - isPlaceholder = _b.placeholder; - var div = Object.assign(document.createElement('div'), (_c = { - id: elementId - }, _c[allowHTML ? 'innerHTML' : 'innerText'] = label, _c.className = "".concat(item, " ").concat(itemChoice), _c)); - if (isSelected) { - div.classList.add(selectedState); - } - if (isPlaceholder) { - div.classList.add(placeholder); - } - div.setAttribute('role', groupId && groupId > 0 ? 'treeitem' : 'option'); - Object.assign(div.dataset, { - choice: '', - id: id, - value: value, - selectText: selectText - }); - if (isDisabled) { - div.classList.add(itemDisabled); - div.dataset.choiceDisabled = ''; - div.setAttribute('aria-disabled', 'true'); - } else { - div.classList.add(itemSelectable); - div.dataset.choiceSelectable = ''; - } - return div; - }, - input: function (_a, placeholderValue) { - var _b = _a.classNames, - input = _b.input, - inputCloned = _b.inputCloned; - var inp = Object.assign(document.createElement('input'), { - type: 'search', - name: 'search_terms', - className: "".concat(input, " ").concat(inputCloned), - autocomplete: 'off', - autocapitalize: 'off', - spellcheck: false - }); - inp.setAttribute('role', 'textbox'); - inp.setAttribute('aria-autocomplete', 'list'); - inp.setAttribute('aria-label', placeholderValue); - return inp; - }, - dropdown: function (_a) { - var _b = _a.classNames, - list = _b.list, - listDropdown = _b.listDropdown; - var div = document.createElement('div'); - div.classList.add(list, listDropdown); - div.setAttribute('aria-expanded', 'false'); - return div; - }, - notice: function (_a, innerText, type) { - var _b; - var allowHTML = _a.allowHTML, - _c = _a.classNames, - item = _c.item, - itemChoice = _c.itemChoice, - noResults = _c.noResults, - noChoices = _c.noChoices; - if (type === void 0) { - type = ''; - } - var classes = [item, itemChoice]; - if (type === 'no-choices') { - classes.push(noChoices); - } else if (type === 'no-results') { - classes.push(noResults); - } - return Object.assign(document.createElement('div'), (_b = {}, _b[allowHTML ? 'innerHTML' : 'innerText'] = innerText, _b.className = classes.join(' '), _b)); - }, - option: function (_a) { - var label = _a.label, - value = _a.value, - customProperties = _a.customProperties, - active = _a.active, - disabled = _a.disabled; - var opt = new Option(label, value, false, active); - if (customProperties) { - opt.dataset.customProperties = "".concat(customProperties); - } - opt.disabled = !!disabled; - return opt; - } -}; -exports["default"] = templates; - -/***/ }), - -/***/ 996: -/***/ (function(module) { - - - -var isMergeableObject = function isMergeableObject(value) { - return isNonNullObject(value) - && !isSpecial(value) -}; - -function isNonNullObject(value) { - return !!value && typeof value === 'object' -} - -function isSpecial(value) { - var stringValue = Object.prototype.toString.call(value); - - return stringValue === '[object RegExp]' - || stringValue === '[object Date]' - || isReactElement(value) -} - -// see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25 -var canUseSymbol = typeof Symbol === 'function' && Symbol.for; -var REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7; - -function isReactElement(value) { - return value.$$typeof === REACT_ELEMENT_TYPE -} - -function emptyTarget(val) { - return Array.isArray(val) ? [] : {} -} - -function cloneUnlessOtherwiseSpecified(value, options) { - return (options.clone !== false && options.isMergeableObject(value)) - ? deepmerge(emptyTarget(value), value, options) - : value -} - -function defaultArrayMerge(target, source, options) { - return target.concat(source).map(function(element) { - return cloneUnlessOtherwiseSpecified(element, options) - }) -} - -function getMergeFunction(key, options) { - if (!options.customMerge) { - return deepmerge - } - var customMerge = options.customMerge(key); - return typeof customMerge === 'function' ? customMerge : deepmerge -} - -function getEnumerableOwnPropertySymbols(target) { - return Object.getOwnPropertySymbols - ? Object.getOwnPropertySymbols(target).filter(function(symbol) { - return target.propertyIsEnumerable(symbol) - }) - : [] -} - -function getKeys(target) { - return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target)) -} - -function propertyIsOnObject(object, property) { - try { - return property in object - } catch(_) { - return false - } -} - -// Protects from prototype poisoning and unexpected merging up the prototype chain. -function propertyIsUnsafe(target, key) { - return propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet, - && !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain, - && Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable. -} - -function mergeObject(target, source, options) { - var destination = {}; - if (options.isMergeableObject(target)) { - getKeys(target).forEach(function(key) { - destination[key] = cloneUnlessOtherwiseSpecified(target[key], options); - }); - } - getKeys(source).forEach(function(key) { - if (propertyIsUnsafe(target, key)) { - return - } - - if (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) { - destination[key] = getMergeFunction(key, options)(target[key], source[key], options); - } else { - destination[key] = cloneUnlessOtherwiseSpecified(source[key], options); - } - }); - return destination -} - -function deepmerge(target, source, options) { - options = options || {}; - options.arrayMerge = options.arrayMerge || defaultArrayMerge; - options.isMergeableObject = options.isMergeableObject || isMergeableObject; - // cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge() - // implementations can use it. The caller may not replace it. - options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified; - - var sourceIsArray = Array.isArray(source); - var targetIsArray = Array.isArray(target); - var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray; - - if (!sourceAndTargetTypesMatch) { - return cloneUnlessOtherwiseSpecified(source, options) - } else if (sourceIsArray) { - return options.arrayMerge(target, source, options) - } else { - return mergeObject(target, source, options) - } -} - -deepmerge.all = function deepmergeAll(array, options) { - if (!Array.isArray(array)) { - throw new Error('first argument should be an array') - } - - return array.reduce(function(prev, next) { - return deepmerge(prev, next, options) - }, {}) -}; - -var deepmerge_1 = deepmerge; - -module.exports = deepmerge_1; - - -/***/ }), - -/***/ 221: -/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "default": function() { return /* binding */ Fuse; } -/* harmony export */ }); -/** - * Fuse.js v6.6.2 - Lightweight fuzzy-search (http://fusejs.io) - * - * Copyright (c) 2022 Kiro Risk (http://kiro.me) - * All Rights Reserved. Apache Software License 2.0 - * - * http://www.apache.org/licenses/LICENSE-2.0 - */ - -function isArray(value) { - return !Array.isArray - ? getTag(value) === '[object Array]' - : Array.isArray(value) -} - -// Adapted from: https://github.com/lodash/lodash/blob/master/.internal/baseToString.js -const INFINITY = 1 / 0; -function baseToString(value) { - // Exit early for strings to avoid a performance hit in some environments. - if (typeof value == 'string') { - return value - } - let result = value + ''; - return result == '0' && 1 / value == -INFINITY ? '-0' : result -} - -function toString(value) { - return value == null ? '' : baseToString(value) -} - -function isString(value) { - return typeof value === 'string' -} - -function isNumber(value) { - return typeof value === 'number' -} - -// Adapted from: https://github.com/lodash/lodash/blob/master/isBoolean.js -function isBoolean(value) { - return ( - value === true || - value === false || - (isObjectLike(value) && getTag(value) == '[object Boolean]') - ) -} - -function isObject(value) { - return typeof value === 'object' -} - -// Checks if `value` is object-like. -function isObjectLike(value) { - return isObject(value) && value !== null -} - -function isDefined(value) { - return value !== undefined && value !== null -} - -function isBlank(value) { - return !value.trim().length -} - -// Gets the `toStringTag` of `value`. -// Adapted from: https://github.com/lodash/lodash/blob/master/.internal/getTag.js -function getTag(value) { - return value == null - ? value === undefined - ? '[object Undefined]' - : '[object Null]' - : Object.prototype.toString.call(value) -} - -const EXTENDED_SEARCH_UNAVAILABLE = 'Extended search is not available'; - -const INCORRECT_INDEX_TYPE = "Incorrect 'index' type"; - -const LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY = (key) => - `Invalid value for key ${key}`; - -const PATTERN_LENGTH_TOO_LARGE = (max) => - `Pattern length exceeds max of ${max}.`; - -const MISSING_KEY_PROPERTY = (name) => `Missing ${name} property in key`; - -const INVALID_KEY_WEIGHT_VALUE = (key) => - `Property 'weight' in key '${key}' must be a positive integer`; - -const hasOwn = Object.prototype.hasOwnProperty; - -class KeyStore { - constructor(keys) { - this._keys = []; - this._keyMap = {}; - - let totalWeight = 0; - - keys.forEach((key) => { - let obj = createKey(key); - - totalWeight += obj.weight; - - this._keys.push(obj); - this._keyMap[obj.id] = obj; - - totalWeight += obj.weight; - }); - - // Normalize weights so that their sum is equal to 1 - this._keys.forEach((key) => { - key.weight /= totalWeight; - }); - } - get(keyId) { - return this._keyMap[keyId] - } - keys() { - return this._keys - } - toJSON() { - return JSON.stringify(this._keys) - } -} - -function createKey(key) { - let path = null; - let id = null; - let src = null; - let weight = 1; - let getFn = null; - - if (isString(key) || isArray(key)) { - src = key; - path = createKeyPath(key); - id = createKeyId(key); - } else { - if (!hasOwn.call(key, 'name')) { - throw new Error(MISSING_KEY_PROPERTY('name')) - } - - const name = key.name; - src = name; - - if (hasOwn.call(key, 'weight')) { - weight = key.weight; - - if (weight <= 0) { - throw new Error(INVALID_KEY_WEIGHT_VALUE(name)) - } - } - - path = createKeyPath(name); - id = createKeyId(name); - getFn = key.getFn; - } - - return { path, id, weight, src, getFn } -} - -function createKeyPath(key) { - return isArray(key) ? key : key.split('.') -} - -function createKeyId(key) { - return isArray(key) ? key.join('.') : key -} - -function get(obj, path) { - let list = []; - let arr = false; - - const deepGet = (obj, path, index) => { - if (!isDefined(obj)) { - return - } - if (!path[index]) { - // If there's no path left, we've arrived at the object we care about. - list.push(obj); - } else { - let key = path[index]; - - const value = obj[key]; - - if (!isDefined(value)) { - return - } - - // If we're at the last value in the path, and if it's a string/number/bool, - // add it to the list - if ( - index === path.length - 1 && - (isString(value) || isNumber(value) || isBoolean(value)) - ) { - list.push(toString(value)); - } else if (isArray(value)) { - arr = true; - // Search each item in the array. - for (let i = 0, len = value.length; i < len; i += 1) { - deepGet(value[i], path, index + 1); - } - } else if (path.length) { - // An object. Recurse further. - deepGet(value, path, index + 1); - } - } - }; - - // Backwards compatibility (since path used to be a string) - deepGet(obj, isString(path) ? path.split('.') : path, 0); - - return arr ? list : list[0] -} - -const MatchOptions = { - // Whether the matches should be included in the result set. When `true`, each record in the result - // set will include the indices of the matched characters. - // These can consequently be used for highlighting purposes. - includeMatches: false, - // When `true`, the matching function will continue to the end of a search pattern even if - // a perfect match has already been located in the string. - findAllMatches: false, - // Minimum number of characters that must be matched before a result is considered a match - minMatchCharLength: 1 -}; - -const BasicOptions = { - // When `true`, the algorithm continues searching to the end of the input even if a perfect - // match is found before the end of the same input. - isCaseSensitive: false, - // When true, the matching function will continue to the end of a search pattern even if - includeScore: false, - // List of properties that will be searched. This also supports nested properties. - keys: [], - // Whether to sort the result list, by score - shouldSort: true, - // Default sort function: sort by ascending score, ascending index - sortFn: (a, b) => - a.score === b.score ? (a.idx < b.idx ? -1 : 1) : a.score < b.score ? -1 : 1 -}; - -const FuzzyOptions = { - // Approximately where in the text is the pattern expected to be found? - location: 0, - // At what point does the match algorithm give up. A threshold of '0.0' requires a perfect match - // (of both letters and location), a threshold of '1.0' would match anything. - threshold: 0.6, - // Determines how close the match must be to the fuzzy location (specified above). - // An exact letter match which is 'distance' characters away from the fuzzy location - // would score as a complete mismatch. A distance of '0' requires the match be at - // the exact location specified, a threshold of '1000' would require a perfect match - // to be within 800 characters of the fuzzy location to be found using a 0.8 threshold. - distance: 100 -}; - -const AdvancedOptions = { - // When `true`, it enables the use of unix-like search commands - useExtendedSearch: false, - // The get function to use when fetching an object's properties. - // The default will search nested paths *ie foo.bar.baz* - getFn: get, - // When `true`, search will ignore `location` and `distance`, so it won't matter - // where in the string the pattern appears. - // More info: https://fusejs.io/concepts/scoring-theory.html#fuzziness-score - ignoreLocation: false, - // When `true`, the calculation for the relevance score (used for sorting) will - // ignore the field-length norm. - // More info: https://fusejs.io/concepts/scoring-theory.html#field-length-norm - ignoreFieldNorm: false, - // The weight to determine how much field length norm effects scoring. - fieldNormWeight: 1 -}; - -var Config = { - ...BasicOptions, - ...MatchOptions, - ...FuzzyOptions, - ...AdvancedOptions -}; - -const SPACE = /[^ ]+/g; - -// Field-length norm: the shorter the field, the higher the weight. -// Set to 3 decimals to reduce index size. -function norm(weight = 1, mantissa = 3) { - const cache = new Map(); - const m = Math.pow(10, mantissa); - - return { - get(value) { - const numTokens = value.match(SPACE).length; - - if (cache.has(numTokens)) { - return cache.get(numTokens) - } - - // Default function is 1/sqrt(x), weight makes that variable - const norm = 1 / Math.pow(numTokens, 0.5 * weight); - - // In place of `toFixed(mantissa)`, for faster computation - const n = parseFloat(Math.round(norm * m) / m); - - cache.set(numTokens, n); - - return n - }, - clear() { - cache.clear(); - } - } -} - -class FuseIndex { - constructor({ - getFn = Config.getFn, - fieldNormWeight = Config.fieldNormWeight - } = {}) { - this.norm = norm(fieldNormWeight, 3); - this.getFn = getFn; - this.isCreated = false; - - this.setIndexRecords(); - } - setSources(docs = []) { - this.docs = docs; - } - setIndexRecords(records = []) { - this.records = records; - } - setKeys(keys = []) { - this.keys = keys; - this._keysMap = {}; - keys.forEach((key, idx) => { - this._keysMap[key.id] = idx; - }); - } - create() { - if (this.isCreated || !this.docs.length) { - return - } - - this.isCreated = true; - - // List is Array - if (isString(this.docs[0])) { - this.docs.forEach((doc, docIndex) => { - this._addString(doc, docIndex); - }); - } else { - // List is Array - this.docs.forEach((doc, docIndex) => { - this._addObject(doc, docIndex); - }); - } - - this.norm.clear(); - } - // Adds a doc to the end of the index - add(doc) { - const idx = this.size(); - - if (isString(doc)) { - this._addString(doc, idx); - } else { - this._addObject(doc, idx); - } - } - // Removes the doc at the specified index of the index - removeAt(idx) { - this.records.splice(idx, 1); - - // Change ref index of every subsquent doc - for (let i = idx, len = this.size(); i < len; i += 1) { - this.records[i].i -= 1; - } - } - getValueForItemAtKeyId(item, keyId) { - return item[this._keysMap[keyId]] - } - size() { - return this.records.length - } - _addString(doc, docIndex) { - if (!isDefined(doc) || isBlank(doc)) { - return - } - - let record = { - v: doc, - i: docIndex, - n: this.norm.get(doc) - }; - - this.records.push(record); - } - _addObject(doc, docIndex) { - let record = { i: docIndex, $: {} }; - - // Iterate over every key (i.e, path), and fetch the value at that key - this.keys.forEach((key, keyIndex) => { - let value = key.getFn ? key.getFn(doc) : this.getFn(doc, key.path); - - if (!isDefined(value)) { - return - } - - if (isArray(value)) { - let subRecords = []; - const stack = [{ nestedArrIndex: -1, value }]; - - while (stack.length) { - const { nestedArrIndex, value } = stack.pop(); - + let key = path[index]; + const value = obj[key]; if (!isDefined(value)) { - continue + return; } - if (isString(value) && !isBlank(value)) { + // If we're at the last value in the path, and if it's a string/number/bool, + // add it to the list + if (index === path.length - 1 && (isString(value) || isNumber(value) || isBoolean(value))) { + list.push(toString(value)); + } else if (isArray(value)) { + arr = true; + // Search each item in the array. + for (let i = 0, len = value.length; i < len; i += 1) { + deepGet(value[i], path, index + 1); + } + } else if (path.length) { + // An object. Recurse further. + deepGet(value, path, index + 1); + } + } + }; + + // Backwards compatibility (since path used to be a string) + deepGet(obj, isString(path) ? path.split('.') : path, 0); + return arr ? list : list[0]; + } + const MatchOptions = { + // Whether the matches should be included in the result set. When `true`, each record in the result + // set will include the indices of the matched characters. + // These can consequently be used for highlighting purposes. + includeMatches: false, + // When `true`, the matching function will continue to the end of a search pattern even if + // a perfect match has already been located in the string. + findAllMatches: false, + // Minimum number of characters that must be matched before a result is considered a match + minMatchCharLength: 1 + }; + const BasicOptions = { + // When `true`, the algorithm continues searching to the end of the input even if a perfect + // match is found before the end of the same input. + isCaseSensitive: false, + // When true, the matching function will continue to the end of a search pattern even if + includeScore: false, + // List of properties that will be searched. This also supports nested properties. + keys: [], + // Whether to sort the result list, by score + shouldSort: true, + // Default sort function: sort by ascending score, ascending index + sortFn: (a, b) => a.score === b.score ? a.idx < b.idx ? -1 : 1 : a.score < b.score ? -1 : 1 + }; + const FuzzyOptions = { + // Approximately where in the text is the pattern expected to be found? + location: 0, + // At what point does the match algorithm give up. A threshold of '0.0' requires a perfect match + // (of both letters and location), a threshold of '1.0' would match anything. + threshold: 0.6, + // Determines how close the match must be to the fuzzy location (specified above). + // An exact letter match which is 'distance' characters away from the fuzzy location + // would score as a complete mismatch. A distance of '0' requires the match be at + // the exact location specified, a threshold of '1000' would require a perfect match + // to be within 800 characters of the fuzzy location to be found using a 0.8 threshold. + distance: 100 + }; + const AdvancedOptions = { + // When `true`, it enables the use of unix-like search commands + useExtendedSearch: false, + // The get function to use when fetching an object's properties. + // The default will search nested paths *ie foo.bar.baz* + getFn: get, + // When `true`, search will ignore `location` and `distance`, so it won't matter + // where in the string the pattern appears. + // More info: https://fusejs.io/concepts/scoring-theory.html#fuzziness-score + ignoreLocation: false, + // When `true`, the calculation for the relevance score (used for sorting) will + // ignore the field-length norm. + // More info: https://fusejs.io/concepts/scoring-theory.html#field-length-norm + ignoreFieldNorm: false, + // The weight to determine how much field length norm effects scoring. + fieldNormWeight: 1 + }; + var Config = _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, BasicOptions), MatchOptions), FuzzyOptions), AdvancedOptions); + const SPACE = /[^ ]+/g; + + // Field-length norm: the shorter the field, the higher the weight. + // Set to 3 decimals to reduce index size. + function norm(weight = 1, mantissa = 3) { + const cache = new Map(); + const m = Math.pow(10, mantissa); + return { + get(value) { + const numTokens = value.match(SPACE).length; + if (cache.has(numTokens)) { + return cache.get(numTokens); + } + + // Default function is 1/sqrt(x), weight makes that variable + const norm = 1 / Math.pow(numTokens, 0.5 * weight); + + // In place of `toFixed(mantissa)`, for faster computation + const n = parseFloat(Math.round(norm * m) / m); + cache.set(numTokens, n); + return n; + }, + clear() { + cache.clear(); + } + }; + } + class FuseIndex { + constructor({ + getFn = Config.getFn, + fieldNormWeight = Config.fieldNormWeight + } = {}) { + this.norm = norm(fieldNormWeight, 3); + this.getFn = getFn; + this.isCreated = false; + this.setIndexRecords(); + } + setSources(docs = []) { + this.docs = docs; + } + setIndexRecords(records = []) { + this.records = records; + } + setKeys(keys = []) { + this.keys = keys; + this._keysMap = {}; + keys.forEach((key, idx) => { + this._keysMap[key.id] = idx; + }); + } + create() { + if (this.isCreated || !this.docs.length) { + return; + } + this.isCreated = true; + + // List is Array + if (isString(this.docs[0])) { + this.docs.forEach((doc, docIndex) => { + this._addString(doc, docIndex); + }); + } else { + // List is Array + this.docs.forEach((doc, docIndex) => { + this._addObject(doc, docIndex); + }); + } + this.norm.clear(); + } + // Adds a doc to the end of the index + add(doc) { + const idx = this.size(); + if (isString(doc)) { + this._addString(doc, idx); + } else { + this._addObject(doc, idx); + } + } + // Removes the doc at the specified index of the index + removeAt(idx) { + this.records.splice(idx, 1); + + // Change ref index of every subsquent doc + for (let i = idx, len = this.size(); i < len; i += 1) { + this.records[i].i -= 1; + } + } + getValueForItemAtKeyId(item, keyId) { + return item[this._keysMap[keyId]]; + } + size() { + return this.records.length; + } + _addString(doc, docIndex) { + if (!isDefined(doc) || isBlank(doc)) { + return; + } + let record = { + v: doc, + i: docIndex, + n: this.norm.get(doc) + }; + this.records.push(record); + } + _addObject(doc, docIndex) { + let record = { + i: docIndex, + $: {} + }; + + // Iterate over every key (i.e, path), and fetch the value at that key + this.keys.forEach((key, keyIndex) => { + let value = key.getFn ? key.getFn(doc) : this.getFn(doc, key.path); + if (!isDefined(value)) { + return; + } + if (isArray(value)) { + let subRecords = []; + const stack = [{ + nestedArrIndex: -1, + value + }]; + while (stack.length) { + const { + nestedArrIndex, + value + } = stack.pop(); + if (!isDefined(value)) { + continue; + } + if (isString(value) && !isBlank(value)) { + let subRecord = { + v: value, + i: nestedArrIndex, + n: this.norm.get(value) + }; + subRecords.push(subRecord); + } else if (isArray(value)) { + value.forEach((item, k) => { + stack.push({ + nestedArrIndex: k, + value: item + }); + }); + } else ; + } + record.$[keyIndex] = subRecords; + } else if (isString(value) && !isBlank(value)) { let subRecord = { v: value, - i: nestedArrIndex, n: this.norm.get(value) }; - - subRecords.push(subRecord); - } else if (isArray(value)) { - value.forEach((item, k) => { - stack.push({ - nestedArrIndex: k, - value: item - }); - }); - } else ; - } - record.$[keyIndex] = subRecords; - } else if (isString(value) && !isBlank(value)) { - let subRecord = { - v: value, - n: this.norm.get(value) + record.$[keyIndex] = subRecord; + } + }); + this.records.push(record); + } + toJSON() { + return { + keys: this.keys, + records: this.records }; - - record.$[keyIndex] = subRecord; - } - }); - - this.records.push(record); - } - toJSON() { - return { - keys: this.keys, - records: this.records - } - } -} - -function createIndex( - keys, - docs, - { getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {} -) { - const myIndex = new FuseIndex({ getFn, fieldNormWeight }); - myIndex.setKeys(keys.map(createKey)); - myIndex.setSources(docs); - myIndex.create(); - return myIndex -} - -function parseIndex( - data, - { getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {} -) { - const { keys, records } = data; - const myIndex = new FuseIndex({ getFn, fieldNormWeight }); - myIndex.setKeys(keys); - myIndex.setIndexRecords(records); - return myIndex -} - -function computeScore$1( - pattern, - { - errors = 0, - currentLocation = 0, - expectedLocation = 0, - distance = Config.distance, - ignoreLocation = Config.ignoreLocation - } = {} -) { - const accuracy = errors / pattern.length; - - if (ignoreLocation) { - return accuracy - } - - const proximity = Math.abs(expectedLocation - currentLocation); - - if (!distance) { - // Dodge divide by zero error. - return proximity ? 1.0 : accuracy - } - - return accuracy + proximity / distance -} - -function convertMaskToIndices( - matchmask = [], - minMatchCharLength = Config.minMatchCharLength -) { - let indices = []; - let start = -1; - let end = -1; - let i = 0; - - for (let len = matchmask.length; i < len; i += 1) { - let match = matchmask[i]; - if (match && start === -1) { - start = i; - } else if (!match && start !== -1) { - end = i - 1; - if (end - start + 1 >= minMatchCharLength) { - indices.push([start, end]); - } - start = -1; - } - } - - // (i-1 - start) + 1 => i - start - if (matchmask[i - 1] && i - start >= minMatchCharLength) { - indices.push([start, i - 1]); - } - - return indices -} - -// Machine word size -const MAX_BITS = 32; - -function search( - text, - pattern, - patternAlphabet, - { - location = Config.location, - distance = Config.distance, - threshold = Config.threshold, - findAllMatches = Config.findAllMatches, - minMatchCharLength = Config.minMatchCharLength, - includeMatches = Config.includeMatches, - ignoreLocation = Config.ignoreLocation - } = {} -) { - if (pattern.length > MAX_BITS) { - throw new Error(PATTERN_LENGTH_TOO_LARGE(MAX_BITS)) - } - - const patternLen = pattern.length; - // Set starting location at beginning text and initialize the alphabet. - const textLen = text.length; - // Handle the case when location > text.length - const expectedLocation = Math.max(0, Math.min(location, textLen)); - // Highest score beyond which we give up. - let currentThreshold = threshold; - // Is there a nearby exact match? (speedup) - let bestLocation = expectedLocation; - - // Performance: only computer matches when the minMatchCharLength > 1 - // OR if `includeMatches` is true. - const computeMatches = minMatchCharLength > 1 || includeMatches; - // A mask of the matches, used for building the indices - const matchMask = computeMatches ? Array(textLen) : []; - - let index; - - // Get all exact matches, here for speed up - while ((index = text.indexOf(pattern, bestLocation)) > -1) { - let score = computeScore$1(pattern, { - currentLocation: index, - expectedLocation, - distance, - ignoreLocation - }); - - currentThreshold = Math.min(score, currentThreshold); - bestLocation = index + patternLen; - - if (computeMatches) { - let i = 0; - while (i < patternLen) { - matchMask[index + i] = 1; - i += 1; } } - } - - // Reset the best location - bestLocation = -1; - - let lastBitArr = []; - let finalScore = 1; - let binMax = patternLen + textLen; - - const mask = 1 << (patternLen - 1); - - for (let i = 0; i < patternLen; i += 1) { - // Scan for the best match; each iteration allows for one more error. - // Run a binary search to determine how far from the match location we can stray - // at this error level. - let binMin = 0; - let binMid = binMax; - - while (binMin < binMid) { - const score = computeScore$1(pattern, { - errors: i, - currentLocation: expectedLocation + binMid, - expectedLocation, - distance, - ignoreLocation + function createIndex(keys, docs, { + getFn = Config.getFn, + fieldNormWeight = Config.fieldNormWeight + } = {}) { + const myIndex = new FuseIndex({ + getFn, + fieldNormWeight }); - - if (score <= currentThreshold) { - binMin = binMid; - } else { - binMax = binMid; + myIndex.setKeys(keys.map(createKey)); + myIndex.setSources(docs); + myIndex.create(); + return myIndex; + } + function parseIndex(data, { + getFn = Config.getFn, + fieldNormWeight = Config.fieldNormWeight + } = {}) { + const { + keys, + records + } = data; + const myIndex = new FuseIndex({ + getFn, + fieldNormWeight + }); + myIndex.setKeys(keys); + myIndex.setIndexRecords(records); + return myIndex; + } + function computeScore$1(pattern, { + errors = 0, + currentLocation = 0, + expectedLocation = 0, + distance = Config.distance, + ignoreLocation = Config.ignoreLocation + } = {}) { + const accuracy = errors / pattern.length; + if (ignoreLocation) { + return accuracy; + } + const proximity = Math.abs(expectedLocation - currentLocation); + if (!distance) { + // Dodge divide by zero error. + return proximity ? 1.0 : accuracy; + } + return accuracy + proximity / distance; + } + function convertMaskToIndices(matchmask = [], minMatchCharLength = Config.minMatchCharLength) { + let indices = []; + let start = -1; + let end = -1; + let i = 0; + for (let len = matchmask.length; i < len; i += 1) { + let match = matchmask[i]; + if (match && start === -1) { + start = i; + } else if (!match && start !== -1) { + end = i - 1; + if (end - start + 1 >= minMatchCharLength) { + indices.push([start, end]); + } + start = -1; + } } - binMid = Math.floor((binMax - binMin) / 2 + binMin); + // (i-1 - start) + 1 => i - start + if (matchmask[i - 1] && i - start >= minMatchCharLength) { + indices.push([start, i - 1]); + } + return indices; } - // Use the result from this iteration as the maximum for the next. - binMax = binMid; - - let start = Math.max(1, expectedLocation - binMid + 1); - let finish = findAllMatches - ? textLen - : Math.min(expectedLocation + binMid, textLen) + patternLen; - - // Initialize the bit array - let bitArr = Array(finish + 2); - - bitArr[finish + 1] = (1 << i) - 1; - - for (let j = finish; j >= start; j -= 1) { - let currentLocation = j - 1; - let charMatch = patternAlphabet[text.charAt(currentLocation)]; - - if (computeMatches) { - // Speed up: quick bool to int conversion (i.e, `charMatch ? 1 : 0`) - matchMask[currentLocation] = +!!charMatch; + // Machine word size + const MAX_BITS = 32; + function search(text, pattern, patternAlphabet, { + location = Config.location, + distance = Config.distance, + threshold = Config.threshold, + findAllMatches = Config.findAllMatches, + minMatchCharLength = Config.minMatchCharLength, + includeMatches = Config.includeMatches, + ignoreLocation = Config.ignoreLocation + } = {}) { + if (pattern.length > MAX_BITS) { + throw new Error(PATTERN_LENGTH_TOO_LARGE(MAX_BITS)); } + const patternLen = pattern.length; + // Set starting location at beginning text and initialize the alphabet. + const textLen = text.length; + // Handle the case when location > text.length + const expectedLocation = Math.max(0, Math.min(location, textLen)); + // Highest score beyond which we give up. + let currentThreshold = threshold; + // Is there a nearby exact match? (speedup) + let bestLocation = expectedLocation; - // First pass: exact match - bitArr[j] = ((bitArr[j + 1] << 1) | 1) & charMatch; + // Performance: only computer matches when the minMatchCharLength > 1 + // OR if `includeMatches` is true. + const computeMatches = minMatchCharLength > 1 || includeMatches; + // A mask of the matches, used for building the indices + const matchMask = computeMatches ? Array(textLen) : []; + let index; - // Subsequent passes: fuzzy match - if (i) { - bitArr[j] |= - ((lastBitArr[j + 1] | lastBitArr[j]) << 1) | 1 | lastBitArr[j + 1]; - } - - if (bitArr[j] & mask) { - finalScore = computeScore$1(pattern, { - errors: i, - currentLocation, + // Get all exact matches, here for speed up + while ((index = text.indexOf(pattern, bestLocation)) > -1) { + let score = computeScore$1(pattern, { + currentLocation: index, expectedLocation, distance, ignoreLocation }); + currentThreshold = Math.min(score, currentThreshold); + bestLocation = index + patternLen; + if (computeMatches) { + let i = 0; + while (i < patternLen) { + matchMask[index + i] = 1; + i += 1; + } + } + } - // This match will almost certainly be better than any existing match. - // But check anyway. - if (finalScore <= currentThreshold) { - // Indeed it is - currentThreshold = finalScore; - bestLocation = currentLocation; + // Reset the best location + bestLocation = -1; + let lastBitArr = []; + let finalScore = 1; + let binMax = patternLen + textLen; + const mask = 1 << patternLen - 1; + for (let i = 0; i < patternLen; i += 1) { + // Scan for the best match; each iteration allows for one more error. + // Run a binary search to determine how far from the match location we can stray + // at this error level. + let binMin = 0; + let binMid = binMax; + while (binMin < binMid) { + const score = computeScore$1(pattern, { + errors: i, + currentLocation: expectedLocation + binMid, + expectedLocation, + distance, + ignoreLocation + }); + if (score <= currentThreshold) { + binMin = binMid; + } else { + binMax = binMid; + } + binMid = Math.floor((binMax - binMin) / 2 + binMin); + } - // Already passed `loc`, downhill from here on in. - if (bestLocation <= expectedLocation) { - break + // Use the result from this iteration as the maximum for the next. + binMax = binMid; + let start = Math.max(1, expectedLocation - binMid + 1); + let finish = findAllMatches ? textLen : Math.min(expectedLocation + binMid, textLen) + patternLen; + + // Initialize the bit array + let bitArr = Array(finish + 2); + bitArr[finish + 1] = (1 << i) - 1; + for (let j = finish; j >= start; j -= 1) { + let currentLocation = j - 1; + let charMatch = patternAlphabet[text.charAt(currentLocation)]; + if (computeMatches) { + // Speed up: quick bool to int conversion (i.e, `charMatch ? 1 : 0`) + matchMask[currentLocation] = +!!charMatch; } - // When passing `bestLocation`, don't exceed our current distance from `expectedLocation`. - start = Math.max(1, 2 * expectedLocation - bestLocation); - } - } - } - - // No hope for a (better) match at greater error levels. - const score = computeScore$1(pattern, { - errors: i + 1, - currentLocation: expectedLocation, - expectedLocation, - distance, - ignoreLocation - }); - - if (score > currentThreshold) { - break - } - - lastBitArr = bitArr; - } - - const result = { - isMatch: bestLocation >= 0, - // Count exact matches (those with a score of 0) to be "almost" exact - score: Math.max(0.001, finalScore) - }; - - if (computeMatches) { - const indices = convertMaskToIndices(matchMask, minMatchCharLength); - if (!indices.length) { - result.isMatch = false; - } else if (includeMatches) { - result.indices = indices; - } - } - - return result -} - -function createPatternAlphabet(pattern) { - let mask = {}; - - for (let i = 0, len = pattern.length; i < len; i += 1) { - const char = pattern.charAt(i); - mask[char] = (mask[char] || 0) | (1 << (len - i - 1)); - } - - return mask -} - -class BitapSearch { - constructor( - pattern, - { - location = Config.location, - threshold = Config.threshold, - distance = Config.distance, - includeMatches = Config.includeMatches, - findAllMatches = Config.findAllMatches, - minMatchCharLength = Config.minMatchCharLength, - isCaseSensitive = Config.isCaseSensitive, - ignoreLocation = Config.ignoreLocation - } = {} - ) { - this.options = { - location, - threshold, - distance, - includeMatches, - findAllMatches, - minMatchCharLength, - isCaseSensitive, - ignoreLocation - }; - - this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase(); - - this.chunks = []; - - if (!this.pattern.length) { - return - } - - const addChunk = (pattern, startIndex) => { - this.chunks.push({ - pattern, - alphabet: createPatternAlphabet(pattern), - startIndex - }); - }; - - const len = this.pattern.length; - - if (len > MAX_BITS) { - let i = 0; - const remainder = len % MAX_BITS; - const end = len - remainder; - - while (i < end) { - addChunk(this.pattern.substr(i, MAX_BITS), i); - i += MAX_BITS; - } - - if (remainder) { - const startIndex = len - MAX_BITS; - addChunk(this.pattern.substr(startIndex), startIndex); - } - } else { - addChunk(this.pattern, 0); - } - } - - searchIn(text) { - const { isCaseSensitive, includeMatches } = this.options; - - if (!isCaseSensitive) { - text = text.toLowerCase(); - } - - // Exact match - if (this.pattern === text) { - let result = { - isMatch: true, - score: 0 - }; - - if (includeMatches) { - result.indices = [[0, text.length - 1]]; - } - - return result - } - - // Otherwise, use Bitap algorithm - const { - location, - distance, - threshold, - findAllMatches, - minMatchCharLength, - ignoreLocation - } = this.options; - - let allIndices = []; - let totalScore = 0; - let hasMatches = false; - - this.chunks.forEach(({ pattern, alphabet, startIndex }) => { - const { isMatch, score, indices } = search(text, pattern, alphabet, { - location: location + startIndex, - distance, - threshold, - findAllMatches, - minMatchCharLength, - includeMatches, - ignoreLocation - }); - - if (isMatch) { - hasMatches = true; - } - - totalScore += score; - - if (isMatch && indices) { - allIndices = [...allIndices, ...indices]; - } - }); - - let result = { - isMatch: hasMatches, - score: hasMatches ? totalScore / this.chunks.length : 1 - }; - - if (hasMatches && includeMatches) { - result.indices = allIndices; - } - - return result - } -} - -class BaseMatch { - constructor(pattern) { - this.pattern = pattern; - } - static isMultiMatch(pattern) { - return getMatch(pattern, this.multiRegex) - } - static isSingleMatch(pattern) { - return getMatch(pattern, this.singleRegex) - } - search(/*text*/) {} -} - -function getMatch(pattern, exp) { - const matches = pattern.match(exp); - return matches ? matches[1] : null -} - -// Token: 'file - -class ExactMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'exact' - } - static get multiRegex() { - return /^="(.*)"$/ - } - static get singleRegex() { - return /^=(.*)$/ - } - search(text) { - const isMatch = text === this.pattern; - - return { - isMatch, - score: isMatch ? 0 : 1, - indices: [0, this.pattern.length - 1] - } - } -} - -// Token: !fire - -class InverseExactMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'inverse-exact' - } - static get multiRegex() { - return /^!"(.*)"$/ - } - static get singleRegex() { - return /^!(.*)$/ - } - search(text) { - const index = text.indexOf(this.pattern); - const isMatch = index === -1; - - return { - isMatch, - score: isMatch ? 0 : 1, - indices: [0, text.length - 1] - } - } -} - -// Token: ^file - -class PrefixExactMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'prefix-exact' - } - static get multiRegex() { - return /^\^"(.*)"$/ - } - static get singleRegex() { - return /^\^(.*)$/ - } - search(text) { - const isMatch = text.startsWith(this.pattern); - - return { - isMatch, - score: isMatch ? 0 : 1, - indices: [0, this.pattern.length - 1] - } - } -} - -// Token: !^fire - -class InversePrefixExactMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'inverse-prefix-exact' - } - static get multiRegex() { - return /^!\^"(.*)"$/ - } - static get singleRegex() { - return /^!\^(.*)$/ - } - search(text) { - const isMatch = !text.startsWith(this.pattern); - - return { - isMatch, - score: isMatch ? 0 : 1, - indices: [0, text.length - 1] - } - } -} - -// Token: .file$ - -class SuffixExactMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'suffix-exact' - } - static get multiRegex() { - return /^"(.*)"\$$/ - } - static get singleRegex() { - return /^(.*)\$$/ - } - search(text) { - const isMatch = text.endsWith(this.pattern); - - return { - isMatch, - score: isMatch ? 0 : 1, - indices: [text.length - this.pattern.length, text.length - 1] - } - } -} - -// Token: !.file$ - -class InverseSuffixExactMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'inverse-suffix-exact' - } - static get multiRegex() { - return /^!"(.*)"\$$/ - } - static get singleRegex() { - return /^!(.*)\$$/ - } - search(text) { - const isMatch = !text.endsWith(this.pattern); - return { - isMatch, - score: isMatch ? 0 : 1, - indices: [0, text.length - 1] - } - } -} - -class FuzzyMatch extends BaseMatch { - constructor( - pattern, - { - location = Config.location, - threshold = Config.threshold, - distance = Config.distance, - includeMatches = Config.includeMatches, - findAllMatches = Config.findAllMatches, - minMatchCharLength = Config.minMatchCharLength, - isCaseSensitive = Config.isCaseSensitive, - ignoreLocation = Config.ignoreLocation - } = {} - ) { - super(pattern); - this._bitapSearch = new BitapSearch(pattern, { - location, - threshold, - distance, - includeMatches, - findAllMatches, - minMatchCharLength, - isCaseSensitive, - ignoreLocation - }); - } - static get type() { - return 'fuzzy' - } - static get multiRegex() { - return /^"(.*)"$/ - } - static get singleRegex() { - return /^(.*)$/ - } - search(text) { - return this._bitapSearch.searchIn(text) - } -} - -// Token: 'file - -class IncludeMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'include' - } - static get multiRegex() { - return /^'"(.*)"$/ - } - static get singleRegex() { - return /^'(.*)$/ - } - search(text) { - let location = 0; - let index; - - const indices = []; - const patternLen = this.pattern.length; - - // Get all exact matches - while ((index = text.indexOf(this.pattern, location)) > -1) { - location = index + patternLen; - indices.push([index, location - 1]); - } - - const isMatch = !!indices.length; - - return { - isMatch, - score: isMatch ? 0 : 1, - indices - } - } -} - -// ❗Order is important. DO NOT CHANGE. -const searchers = [ - ExactMatch, - IncludeMatch, - PrefixExactMatch, - InversePrefixExactMatch, - InverseSuffixExactMatch, - SuffixExactMatch, - InverseExactMatch, - FuzzyMatch -]; - -const searchersLen = searchers.length; - -// Regex to split by spaces, but keep anything in quotes together -const SPACE_RE = / +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/; -const OR_TOKEN = '|'; - -// Return a 2D array representation of the query, for simpler parsing. -// Example: -// "^core go$ | rb$ | py$ xy$" => [["^core", "go$"], ["rb$"], ["py$", "xy$"]] -function parseQuery(pattern, options = {}) { - return pattern.split(OR_TOKEN).map((item) => { - let query = item - .trim() - .split(SPACE_RE) - .filter((item) => item && !!item.trim()); - - let results = []; - for (let i = 0, len = query.length; i < len; i += 1) { - const queryItem = query[i]; - - // 1. Handle multiple query match (i.e, once that are quoted, like `"hello world"`) - let found = false; - let idx = -1; - while (!found && ++idx < searchersLen) { - const searcher = searchers[idx]; - let token = searcher.isMultiMatch(queryItem); - if (token) { - results.push(new searcher(token, options)); - found = true; - } - } - - if (found) { - continue - } - - // 2. Handle single query matches (i.e, once that are *not* quoted) - idx = -1; - while (++idx < searchersLen) { - const searcher = searchers[idx]; - let token = searcher.isSingleMatch(queryItem); - if (token) { - results.push(new searcher(token, options)); - break - } - } - } - - return results - }) -} - -// These extended matchers can return an array of matches, as opposed -// to a singl match -const MultiMatchSet = new Set([FuzzyMatch.type, IncludeMatch.type]); - -/** - * Command-like searching - * ====================== - * - * Given multiple search terms delimited by spaces.e.g. `^jscript .python$ ruby !java`, - * search in a given text. - * - * Search syntax: - * - * | Token | Match type | Description | - * | ----------- | -------------------------- | -------------------------------------- | - * | `jscript` | fuzzy-match | Items that fuzzy match `jscript` | - * | `=scheme` | exact-match | Items that are `scheme` | - * | `'python` | include-match | Items that include `python` | - * | `!ruby` | inverse-exact-match | Items that do not include `ruby` | - * | `^java` | prefix-exact-match | Items that start with `java` | - * | `!^earlang` | inverse-prefix-exact-match | Items that do not start with `earlang` | - * | `.js$` | suffix-exact-match | Items that end with `.js` | - * | `!.go$` | inverse-suffix-exact-match | Items that do not end with `.go` | - * - * A single pipe character acts as an OR operator. For example, the following - * query matches entries that start with `core` and end with either`go`, `rb`, - * or`py`. - * - * ``` - * ^core go$ | rb$ | py$ - * ``` - */ -class ExtendedSearch { - constructor( - pattern, - { - isCaseSensitive = Config.isCaseSensitive, - includeMatches = Config.includeMatches, - minMatchCharLength = Config.minMatchCharLength, - ignoreLocation = Config.ignoreLocation, - findAllMatches = Config.findAllMatches, - location = Config.location, - threshold = Config.threshold, - distance = Config.distance - } = {} - ) { - this.query = null; - this.options = { - isCaseSensitive, - includeMatches, - minMatchCharLength, - findAllMatches, - ignoreLocation, - location, - threshold, - distance - }; - - this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase(); - this.query = parseQuery(this.pattern, this.options); - } - - static condition(_, options) { - return options.useExtendedSearch - } - - searchIn(text) { - const query = this.query; - - if (!query) { - return { - isMatch: false, - score: 1 - } - } - - const { includeMatches, isCaseSensitive } = this.options; - - text = isCaseSensitive ? text : text.toLowerCase(); - - let numMatches = 0; - let allIndices = []; - let totalScore = 0; - - // ORs - for (let i = 0, qLen = query.length; i < qLen; i += 1) { - const searchers = query[i]; - - // Reset indices - allIndices.length = 0; - numMatches = 0; - - // ANDs - for (let j = 0, pLen = searchers.length; j < pLen; j += 1) { - const searcher = searchers[j]; - const { isMatch, indices, score } = searcher.search(text); - - if (isMatch) { - numMatches += 1; - totalScore += score; - if (includeMatches) { - const type = searcher.constructor.type; - if (MultiMatchSet.has(type)) { - allIndices = [...allIndices, ...indices]; - } else { - allIndices.push(indices); + // First pass: exact match + bitArr[j] = (bitArr[j + 1] << 1 | 1) & charMatch; + + // Subsequent passes: fuzzy match + if (i) { + bitArr[j] |= (lastBitArr[j + 1] | lastBitArr[j]) << 1 | 1 | lastBitArr[j + 1]; + } + if (bitArr[j] & mask) { + finalScore = computeScore$1(pattern, { + errors: i, + currentLocation, + expectedLocation, + distance, + ignoreLocation + }); + + // This match will almost certainly be better than any existing match. + // But check anyway. + if (finalScore <= currentThreshold) { + // Indeed it is + currentThreshold = finalScore; + bestLocation = currentLocation; + + // Already passed `loc`, downhill from here on in. + if (bestLocation <= expectedLocation) { + break; + } + + // When passing `bestLocation`, don't exceed our current distance from `expectedLocation`. + start = Math.max(1, 2 * expectedLocation - bestLocation); } } - } else { - totalScore = 0; - numMatches = 0; - allIndices.length = 0; - break + } + + // No hope for a (better) match at greater error levels. + const score = computeScore$1(pattern, { + errors: i + 1, + currentLocation: expectedLocation, + expectedLocation, + distance, + ignoreLocation + }); + if (score > currentThreshold) { + break; + } + lastBitArr = bitArr; + } + const result = { + isMatch: bestLocation >= 0, + // Count exact matches (those with a score of 0) to be "almost" exact + score: Math.max(0.001, finalScore) + }; + if (computeMatches) { + const indices = convertMaskToIndices(matchMask, minMatchCharLength); + if (!indices.length) { + result.isMatch = false; + } else if (includeMatches) { + result.indices = indices; } } - - // OR condition, so if TRUE, return - if (numMatches) { - let result = { - isMatch: true, - score: totalScore / numMatches + return result; + } + function createPatternAlphabet(pattern) { + let mask = {}; + for (let i = 0, len = pattern.length; i < len; i += 1) { + const char = pattern.charAt(i); + mask[char] = (mask[char] || 0) | 1 << len - i - 1; + } + return mask; + } + class BitapSearch { + constructor(pattern, { + location = Config.location, + threshold = Config.threshold, + distance = Config.distance, + includeMatches = Config.includeMatches, + findAllMatches = Config.findAllMatches, + minMatchCharLength = Config.minMatchCharLength, + isCaseSensitive = Config.isCaseSensitive, + ignoreLocation = Config.ignoreLocation + } = {}) { + this.options = { + location, + threshold, + distance, + includeMatches, + findAllMatches, + minMatchCharLength, + isCaseSensitive, + ignoreLocation }; + this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase(); + this.chunks = []; + if (!this.pattern.length) { + return; + } + const addChunk = (pattern, startIndex) => { + this.chunks.push({ + pattern, + alphabet: createPatternAlphabet(pattern), + startIndex + }); + }; + const len = this.pattern.length; + if (len > MAX_BITS) { + let i = 0; + const remainder = len % MAX_BITS; + const end = len - remainder; + while (i < end) { + addChunk(this.pattern.substr(i, MAX_BITS), i); + i += MAX_BITS; + } + if (remainder) { + const startIndex = len - MAX_BITS; + addChunk(this.pattern.substr(startIndex), startIndex); + } + } else { + addChunk(this.pattern, 0); + } + } + searchIn(text) { + const { + isCaseSensitive, + includeMatches + } = this.options; + if (!isCaseSensitive) { + text = text.toLowerCase(); + } - if (includeMatches) { + // Exact match + if (this.pattern === text) { + let result = { + isMatch: true, + score: 0 + }; + if (includeMatches) { + result.indices = [[0, text.length - 1]]; + } + return result; + } + + // Otherwise, use Bitap algorithm + const { + location, + distance, + threshold, + findAllMatches, + minMatchCharLength, + ignoreLocation + } = this.options; + let allIndices = []; + let totalScore = 0; + let hasMatches = false; + this.chunks.forEach(({ + pattern, + alphabet, + startIndex + }) => { + const { + isMatch, + score, + indices + } = search(text, pattern, alphabet, { + location: location + startIndex, + distance, + threshold, + findAllMatches, + minMatchCharLength, + includeMatches, + ignoreLocation + }); + if (isMatch) { + hasMatches = true; + } + totalScore += score; + if (isMatch && indices) { + allIndices = [...allIndices, ...indices]; + } + }); + let result = { + isMatch: hasMatches, + score: hasMatches ? totalScore / this.chunks.length : 1 + }; + if (hasMatches && includeMatches) { result.indices = allIndices; } + return result; + } + } + class BaseMatch { + constructor(pattern) { + this.pattern = pattern; + } + static isMultiMatch(pattern) { + return getMatch(pattern, this.multiRegex); + } + static isSingleMatch(pattern) { + return getMatch(pattern, this.singleRegex); + } + search( /*text*/) {} + } + function getMatch(pattern, exp) { + const matches = pattern.match(exp); + return matches ? matches[1] : null; + } - return result + // Token: 'file + + class ExactMatch extends BaseMatch { + constructor(pattern) { + super(pattern); + } + static get type() { + return 'exact'; + } + static get multiRegex() { + return /^="(.*)"$/; + } + static get singleRegex() { + return /^=(.*)$/; + } + search(text) { + const isMatch = text === this.pattern; + return { + isMatch, + score: isMatch ? 0 : 1, + indices: [0, this.pattern.length - 1] + }; } } - // Nothing was matched - return { - isMatch: false, - score: 1 - } - } -} + // Token: !fire -const registeredSearchers = []; - -function register(...args) { - registeredSearchers.push(...args); -} - -function createSearcher(pattern, options) { - for (let i = 0, len = registeredSearchers.length; i < len; i += 1) { - let searcherClass = registeredSearchers[i]; - if (searcherClass.condition(pattern, options)) { - return new searcherClass(pattern, options) - } - } - - return new BitapSearch(pattern, options) -} - -const LogicalOperator = { - AND: '$and', - OR: '$or' -}; - -const KeyType = { - PATH: '$path', - PATTERN: '$val' -}; - -const isExpression = (query) => - !!(query[LogicalOperator.AND] || query[LogicalOperator.OR]); - -const isPath = (query) => !!query[KeyType.PATH]; - -const isLeaf = (query) => - !isArray(query) && isObject(query) && !isExpression(query); - -const convertToExplicit = (query) => ({ - [LogicalOperator.AND]: Object.keys(query).map((key) => ({ - [key]: query[key] - })) -}); - -// When `auto` is `true`, the parse function will infer and initialize and add -// the appropriate `Searcher` instance -function parse(query, options, { auto = true } = {}) { - const next = (query) => { - let keys = Object.keys(query); - - const isQueryPath = isPath(query); - - if (!isQueryPath && keys.length > 1 && !isExpression(query)) { - return next(convertToExplicit(query)) - } - - if (isLeaf(query)) { - const key = isQueryPath ? query[KeyType.PATH] : keys[0]; - - const pattern = isQueryPath ? query[KeyType.PATTERN] : query[key]; - - if (!isString(pattern)) { - throw new Error(LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key)) + class InverseExactMatch extends BaseMatch { + constructor(pattern) { + super(pattern); } + static get type() { + return 'inverse-exact'; + } + static get multiRegex() { + return /^!"(.*)"$/; + } + static get singleRegex() { + return /^!(.*)$/; + } + search(text) { + const index = text.indexOf(this.pattern); + const isMatch = index === -1; + return { + isMatch, + score: isMatch ? 0 : 1, + indices: [0, text.length - 1] + }; + } + } - const obj = { - keyId: createKeyId(key), - pattern + // Token: ^file + + class PrefixExactMatch extends BaseMatch { + constructor(pattern) { + super(pattern); + } + static get type() { + return 'prefix-exact'; + } + static get multiRegex() { + return /^\^"(.*)"$/; + } + static get singleRegex() { + return /^\^(.*)$/; + } + search(text) { + const isMatch = text.startsWith(this.pattern); + return { + isMatch, + score: isMatch ? 0 : 1, + indices: [0, this.pattern.length - 1] + }; + } + } + + // Token: !^fire + + class InversePrefixExactMatch extends BaseMatch { + constructor(pattern) { + super(pattern); + } + static get type() { + return 'inverse-prefix-exact'; + } + static get multiRegex() { + return /^!\^"(.*)"$/; + } + static get singleRegex() { + return /^!\^(.*)$/; + } + search(text) { + const isMatch = !text.startsWith(this.pattern); + return { + isMatch, + score: isMatch ? 0 : 1, + indices: [0, text.length - 1] + }; + } + } + + // Token: .file$ + + class SuffixExactMatch extends BaseMatch { + constructor(pattern) { + super(pattern); + } + static get type() { + return 'suffix-exact'; + } + static get multiRegex() { + return /^"(.*)"\$$/; + } + static get singleRegex() { + return /^(.*)\$$/; + } + search(text) { + const isMatch = text.endsWith(this.pattern); + return { + isMatch, + score: isMatch ? 0 : 1, + indices: [text.length - this.pattern.length, text.length - 1] + }; + } + } + + // Token: !.file$ + + class InverseSuffixExactMatch extends BaseMatch { + constructor(pattern) { + super(pattern); + } + static get type() { + return 'inverse-suffix-exact'; + } + static get multiRegex() { + return /^!"(.*)"\$$/; + } + static get singleRegex() { + return /^!(.*)\$$/; + } + search(text) { + const isMatch = !text.endsWith(this.pattern); + return { + isMatch, + score: isMatch ? 0 : 1, + indices: [0, text.length - 1] + }; + } + } + class FuzzyMatch extends BaseMatch { + constructor(pattern, { + location = Config.location, + threshold = Config.threshold, + distance = Config.distance, + includeMatches = Config.includeMatches, + findAllMatches = Config.findAllMatches, + minMatchCharLength = Config.minMatchCharLength, + isCaseSensitive = Config.isCaseSensitive, + ignoreLocation = Config.ignoreLocation + } = {}) { + super(pattern); + this._bitapSearch = new BitapSearch(pattern, { + location, + threshold, + distance, + includeMatches, + findAllMatches, + minMatchCharLength, + isCaseSensitive, + ignoreLocation + }); + } + static get type() { + return 'fuzzy'; + } + static get multiRegex() { + return /^"(.*)"$/; + } + static get singleRegex() { + return /^(.*)$/; + } + search(text) { + return this._bitapSearch.searchIn(text); + } + } + + // Token: 'file + + class IncludeMatch extends BaseMatch { + constructor(pattern) { + super(pattern); + } + static get type() { + return 'include'; + } + static get multiRegex() { + return /^'"(.*)"$/; + } + static get singleRegex() { + return /^'(.*)$/; + } + search(text) { + let location = 0; + let index; + const indices = []; + const patternLen = this.pattern.length; + + // Get all exact matches + while ((index = text.indexOf(this.pattern, location)) > -1) { + location = index + patternLen; + indices.push([index, location - 1]); + } + const isMatch = !!indices.length; + return { + isMatch, + score: isMatch ? 0 : 1, + indices + }; + } + } + + // ❗Order is important. DO NOT CHANGE. + const searchers = [ExactMatch, IncludeMatch, PrefixExactMatch, InversePrefixExactMatch, InverseSuffixExactMatch, SuffixExactMatch, InverseExactMatch, FuzzyMatch]; + const searchersLen = searchers.length; + + // Regex to split by spaces, but keep anything in quotes together + const SPACE_RE = / +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/; + const OR_TOKEN = '|'; + + // Return a 2D array representation of the query, for simpler parsing. + // Example: + // "^core go$ | rb$ | py$ xy$" => [["^core", "go$"], ["rb$"], ["py$", "xy$"]] + function parseQuery(pattern, options = {}) { + return pattern.split(OR_TOKEN).map(item => { + let query = item.trim().split(SPACE_RE).filter(item => item && !!item.trim()); + let results = []; + for (let i = 0, len = query.length; i < len; i += 1) { + const queryItem = query[i]; + + // 1. Handle multiple query match (i.e, once that are quoted, like `"hello world"`) + let found = false; + let idx = -1; + while (!found && ++idx < searchersLen) { + const searcher = searchers[idx]; + let token = searcher.isMultiMatch(queryItem); + if (token) { + results.push(new searcher(token, options)); + found = true; + } + } + if (found) { + continue; + } + + // 2. Handle single query matches (i.e, once that are *not* quoted) + idx = -1; + while (++idx < searchersLen) { + const searcher = searchers[idx]; + let token = searcher.isSingleMatch(queryItem); + if (token) { + results.push(new searcher(token, options)); + break; + } + } + } + return results; + }); + } + + // These extended matchers can return an array of matches, as opposed + // to a singl match + const MultiMatchSet = new Set([FuzzyMatch.type, IncludeMatch.type]); + + /** + * Command-like searching + * ====================== + * + * Given multiple search terms delimited by spaces.e.g. `^jscript .python$ ruby !java`, + * search in a given text. + * + * Search syntax: + * + * | Token | Match type | Description | + * | ----------- | -------------------------- | -------------------------------------- | + * | `jscript` | fuzzy-match | Items that fuzzy match `jscript` | + * | `=scheme` | exact-match | Items that are `scheme` | + * | `'python` | include-match | Items that include `python` | + * | `!ruby` | inverse-exact-match | Items that do not include `ruby` | + * | `^java` | prefix-exact-match | Items that start with `java` | + * | `!^earlang` | inverse-prefix-exact-match | Items that do not start with `earlang` | + * | `.js$` | suffix-exact-match | Items that end with `.js` | + * | `!.go$` | inverse-suffix-exact-match | Items that do not end with `.go` | + * + * A single pipe character acts as an OR operator. For example, the following + * query matches entries that start with `core` and end with either`go`, `rb`, + * or`py`. + * + * ``` + * ^core go$ | rb$ | py$ + * ``` + */ + class ExtendedSearch { + constructor(pattern, { + isCaseSensitive = Config.isCaseSensitive, + includeMatches = Config.includeMatches, + minMatchCharLength = Config.minMatchCharLength, + ignoreLocation = Config.ignoreLocation, + findAllMatches = Config.findAllMatches, + location = Config.location, + threshold = Config.threshold, + distance = Config.distance + } = {}) { + this.query = null; + this.options = { + isCaseSensitive, + includeMatches, + minMatchCharLength, + findAllMatches, + ignoreLocation, + location, + threshold, + distance + }; + this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase(); + this.query = parseQuery(this.pattern, this.options); + } + static condition(_, options) { + return options.useExtendedSearch; + } + searchIn(text) { + const query = this.query; + if (!query) { + return { + isMatch: false, + score: 1 + }; + } + const { + includeMatches, + isCaseSensitive + } = this.options; + text = isCaseSensitive ? text : text.toLowerCase(); + let numMatches = 0; + let allIndices = []; + let totalScore = 0; + + // ORs + for (let i = 0, qLen = query.length; i < qLen; i += 1) { + const searchers = query[i]; + + // Reset indices + allIndices.length = 0; + numMatches = 0; + + // ANDs + for (let j = 0, pLen = searchers.length; j < pLen; j += 1) { + const searcher = searchers[j]; + const { + isMatch, + indices, + score + } = searcher.search(text); + if (isMatch) { + numMatches += 1; + totalScore += score; + if (includeMatches) { + const type = searcher.constructor.type; + if (MultiMatchSet.has(type)) { + allIndices = [...allIndices, ...indices]; + } else { + allIndices.push(indices); + } + } + } else { + totalScore = 0; + numMatches = 0; + allIndices.length = 0; + break; + } + } + + // OR condition, so if TRUE, return + if (numMatches) { + let result = { + isMatch: true, + score: totalScore / numMatches + }; + if (includeMatches) { + result.indices = allIndices; + } + return result; + } + } + + // Nothing was matched + return { + isMatch: false, + score: 1 + }; + } + } + const registeredSearchers = []; + function register(...args) { + registeredSearchers.push(...args); + } + function createSearcher(pattern, options) { + for (let i = 0, len = registeredSearchers.length; i < len; i += 1) { + let searcherClass = registeredSearchers[i]; + if (searcherClass.condition(pattern, options)) { + return new searcherClass(pattern, options); + } + } + return new BitapSearch(pattern, options); + } + const LogicalOperator = { + AND: '$and', + OR: '$or' + }; + const KeyType = { + PATH: '$path', + PATTERN: '$val' + }; + const isExpression = query => !!(query[LogicalOperator.AND] || query[LogicalOperator.OR]); + const isPath = query => !!query[KeyType.PATH]; + const isLeaf = query => !isArray(query) && isObject(query) && !isExpression(query); + const convertToExplicit = query => ({ + [LogicalOperator.AND]: Object.keys(query).map(key => ({ + [key]: query[key] + })) + }); + + // When `auto` is `true`, the parse function will infer and initialize and add + // the appropriate `Searcher` instance + function parse(query, options, { + auto = true + } = {}) { + const next = query => { + let keys = Object.keys(query); + const isQueryPath = isPath(query); + if (!isQueryPath && keys.length > 1 && !isExpression(query)) { + return next(convertToExplicit(query)); + } + if (isLeaf(query)) { + const key = isQueryPath ? query[KeyType.PATH] : keys[0]; + const pattern = isQueryPath ? query[KeyType.PATTERN] : query[key]; + if (!isString(pattern)) { + throw new Error(LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key)); + } + const obj = { + keyId: createKeyId(key), + pattern + }; + if (auto) { + obj.searcher = createSearcher(pattern, options); + } + return obj; + } + let node = { + children: [], + operator: keys[0] + }; + keys.forEach(key => { + const value = query[key]; + if (isArray(value)) { + value.forEach(item => { + node.children.push(next(item)); + }); + } + }); + return node; }; - - if (auto) { - obj.searcher = createSearcher(pattern, options); + if (!isExpression(query)) { + query = convertToExplicit(query); } - - return obj + return next(query); } - let node = { - children: [], - operator: keys[0] - }; - - keys.forEach((key) => { - const value = query[key]; - - if (isArray(value)) { - value.forEach((item) => { - node.children.push(next(item)); + // Practical scoring function + function computeScore(results, { + ignoreFieldNorm = Config.ignoreFieldNorm + }) { + results.forEach(result => { + let totalScore = 1; + result.matches.forEach(({ + key, + norm, + score + }) => { + const weight = key ? key.weight : null; + totalScore *= Math.pow(score === 0 && weight ? Number.EPSILON : score, (weight || 1) * (ignoreFieldNorm ? 1 : norm)); }); - } - }); - - return node - }; - - if (!isExpression(query)) { - query = convertToExplicit(query); - } - - return next(query) -} - -// Practical scoring function -function computeScore( - results, - { ignoreFieldNorm = Config.ignoreFieldNorm } -) { - results.forEach((result) => { - let totalScore = 1; - - result.matches.forEach(({ key, norm, score }) => { - const weight = key ? key.weight : null; - - totalScore *= Math.pow( - score === 0 && weight ? Number.EPSILON : score, - (weight || 1) * (ignoreFieldNorm ? 1 : norm) - ); - }); - - result.score = totalScore; - }); -} - -function transformMatches(result, data) { - const matches = result.matches; - data.matches = []; - - if (!isDefined(matches)) { - return - } - - matches.forEach((match) => { - if (!isDefined(match.indices) || !match.indices.length) { - return - } - - const { indices, value } = match; - - let obj = { - indices, - value - }; - - if (match.key) { - obj.key = match.key.src; - } - - if (match.idx > -1) { - obj.refIndex = match.idx; - } - - data.matches.push(obj); - }); -} - -function transformScore(result, data) { - data.score = result.score; -} - -function format( - results, - docs, - { - includeMatches = Config.includeMatches, - includeScore = Config.includeScore - } = {} -) { - const transformers = []; - - if (includeMatches) transformers.push(transformMatches); - if (includeScore) transformers.push(transformScore); - - return results.map((result) => { - const { idx } = result; - - const data = { - item: docs[idx], - refIndex: idx - }; - - if (transformers.length) { - transformers.forEach((transformer) => { - transformer(result, data); + result.score = totalScore; }); } - - return data - }) -} - -class Fuse { - constructor(docs, options = {}, index) { - this.options = { ...Config, ...options }; - - if ( - this.options.useExtendedSearch && - !true - ) {} - - this._keyStore = new KeyStore(this.options.keys); - - this.setCollection(docs, index); - } - - setCollection(docs, index) { - this._docs = docs; - - if (index && !(index instanceof FuseIndex)) { - throw new Error(INCORRECT_INDEX_TYPE) - } - - this._myIndex = - index || - createIndex(this.options.keys, this._docs, { - getFn: this.options.getFn, - fieldNormWeight: this.options.fieldNormWeight + function transformMatches(result, data) { + const matches = result.matches; + data.matches = []; + if (!isDefined(matches)) { + return; + } + matches.forEach(match => { + if (!isDefined(match.indices) || !match.indices.length) { + return; + } + const { + indices, + value + } = match; + let obj = { + indices, + value + }; + if (match.key) { + obj.key = match.key.src; + } + if (match.idx > -1) { + obj.refIndex = match.idx; + } + data.matches.push(obj); }); - } - - add(doc) { - if (!isDefined(doc)) { - return } - - this._docs.push(doc); - this._myIndex.add(doc); - } - - remove(predicate = (/* doc, idx */) => false) { - const results = []; - - for (let i = 0, len = this._docs.length; i < len; i += 1) { - const doc = this._docs[i]; - if (predicate(doc, i)) { - this.removeAt(i); - i -= 1; - len -= 1; - - results.push(doc); + function transformScore(result, data) { + data.score = result.score; + } + function format(results, docs, { + includeMatches = Config.includeMatches, + includeScore = Config.includeScore + } = {}) { + const transformers = []; + if (includeMatches) transformers.push(transformMatches); + if (includeScore) transformers.push(transformScore); + return results.map(result => { + const { + idx + } = result; + const data = { + item: docs[idx], + refIndex: idx + }; + if (transformers.length) { + transformers.forEach(transformer => { + transformer(result, data); + }); + } + return data; + }); + } + class Fuse { + constructor(docs, options = {}, index) { + this.options = _objectSpread2(_objectSpread2({}, Config), options); + if (this.options.useExtendedSearch && !true) { + throw new Error(EXTENDED_SEARCH_UNAVAILABLE); + } + this._keyStore = new KeyStore(this.options.keys); + this.setCollection(docs, index); } - } - - return results - } - - removeAt(idx) { - this._docs.splice(idx, 1); - this._myIndex.removeAt(idx); - } - - getIndex() { - return this._myIndex - } - - search(query, { limit = -1 } = {}) { - const { - includeMatches, - includeScore, - shouldSort, - sortFn, - ignoreFieldNorm - } = this.options; - - let results = isString(query) - ? isString(this._docs[0]) - ? this._searchStringList(query) - : this._searchObjectList(query) - : this._searchLogical(query); - - computeScore(results, { ignoreFieldNorm }); - - if (shouldSort) { - results.sort(sortFn); - } - - if (isNumber(limit) && limit > -1) { - results = results.slice(0, limit); - } - - return format(results, this._docs, { - includeMatches, - includeScore - }) - } - - _searchStringList(query) { - const searcher = createSearcher(query, this.options); - const { records } = this._myIndex; - const results = []; - - // Iterate over every string in the index - records.forEach(({ v: text, i: idx, n: norm }) => { - if (!isDefined(text)) { - return - } - - const { isMatch, score, indices } = searcher.searchIn(text); - - if (isMatch) { - results.push({ - item: text, - idx, - matches: [{ score, value: text, norm, indices }] + setCollection(docs, index) { + this._docs = docs; + if (index && !(index instanceof FuseIndex)) { + throw new Error(INCORRECT_INDEX_TYPE); + } + this._myIndex = index || createIndex(this.options.keys, this._docs, { + getFn: this.options.getFn, + fieldNormWeight: this.options.fieldNormWeight }); } - }); - - return results - } - - _searchLogical(query) { - - const expression = parse(query, this.options); - - const evaluate = (node, item, idx) => { - if (!node.children) { - const { keyId, searcher } = node; - - const matches = this._findMatches({ - key: this._keyStore.get(keyId), - value: this._myIndex.getValueForItemAtKeyId(item, keyId), - searcher + add(doc) { + if (!isDefined(doc)) { + return; + } + this._docs.push(doc); + this._myIndex.add(doc); + } + remove(predicate = ( /* doc, idx */) => false) { + const results = []; + for (let i = 0, len = this._docs.length; i < len; i += 1) { + const doc = this._docs[i]; + if (predicate(doc, i)) { + this.removeAt(i); + i -= 1; + len -= 1; + results.push(doc); + } + } + return results; + } + removeAt(idx) { + this._docs.splice(idx, 1); + this._myIndex.removeAt(idx); + } + getIndex() { + return this._myIndex; + } + search(query, { + limit = -1 + } = {}) { + const { + includeMatches, + includeScore, + shouldSort, + sortFn, + ignoreFieldNorm + } = this.options; + let results = isString(query) ? isString(this._docs[0]) ? this._searchStringList(query) : this._searchObjectList(query) : this._searchLogical(query); + computeScore(results, { + ignoreFieldNorm }); + if (shouldSort) { + results.sort(sortFn); + } + if (isNumber(limit) && limit > -1) { + results = results.slice(0, limit); + } + return format(results, this._docs, { + includeMatches, + includeScore + }); + } + _searchStringList(query) { + const searcher = createSearcher(query, this.options); + const { + records + } = this._myIndex; + const results = []; - if (matches && matches.length) { - return [ - { + // Iterate over every string in the index + records.forEach(({ + v: text, + i: idx, + n: norm + }) => { + if (!isDefined(text)) { + return; + } + const { + isMatch, + score, + indices + } = searcher.searchIn(text); + if (isMatch) { + results.push({ + item: text, + idx, + matches: [{ + score, + value: text, + norm, + indices + }] + }); + } + }); + return results; + } + _searchLogical(query) { + const expression = parse(query, this.options); + const evaluate = (node, item, idx) => { + if (!node.children) { + const { + keyId, + searcher + } = node; + const matches = this._findMatches({ + key: this._keyStore.get(keyId), + value: this._myIndex.getValueForItemAtKeyId(item, keyId), + searcher + }); + if (matches && matches.length) { + return [{ + idx, + item, + matches + }]; + } + return []; + } + const res = []; + for (let i = 0, len = node.children.length; i < len; i += 1) { + const child = node.children[i]; + const result = evaluate(child, item, idx); + if (result.length) { + res.push(...result); + } else if (node.operator === LogicalOperator.AND) { + return []; + } + } + return res; + }; + const records = this._myIndex.records; + const resultMap = {}; + const results = []; + records.forEach(({ + $: item, + i: idx + }) => { + if (isDefined(item)) { + let expResults = evaluate(expression, item, idx); + if (expResults.length) { + // Dedupe when adding + if (!resultMap[idx]) { + resultMap[idx] = { + idx, + item, + matches: [] + }; + results.push(resultMap[idx]); + } + expResults.forEach(({ + matches + }) => { + resultMap[idx].matches.push(...matches); + }); + } + } + }); + return results; + } + _searchObjectList(query) { + const searcher = createSearcher(query, this.options); + const { + keys, + records + } = this._myIndex; + const results = []; + + // List is Array + records.forEach(({ + $: item, + i: idx + }) => { + if (!isDefined(item)) { + return; + } + let matches = []; + + // Iterate over every key (i.e, path), and fetch the value at that key + keys.forEach((key, keyIndex) => { + matches.push(...this._findMatches({ + key, + value: item[keyIndex], + searcher + })); + }); + if (matches.length) { + results.push({ idx, item, matches - } - ] - } - - return [] - } - - const res = []; - for (let i = 0, len = node.children.length; i < len; i += 1) { - const child = node.children[i]; - const result = evaluate(child, item, idx); - if (result.length) { - res.push(...result); - } else if (node.operator === LogicalOperator.AND) { - return [] - } - } - return res - }; - - const records = this._myIndex.records; - const resultMap = {}; - const results = []; - - records.forEach(({ $: item, i: idx }) => { - if (isDefined(item)) { - let expResults = evaluate(expression, item, idx); - - if (expResults.length) { - // Dedupe when adding - if (!resultMap[idx]) { - resultMap[idx] = { idx, item, matches: [] }; - results.push(resultMap[idx]); + }); } - expResults.forEach(({ matches }) => { - resultMap[idx].matches.push(...matches); - }); - } - } - }); - - return results - } - - _searchObjectList(query) { - const searcher = createSearcher(query, this.options); - const { keys, records } = this._myIndex; - const results = []; - - // List is Array - records.forEach(({ $: item, i: idx }) => { - if (!isDefined(item)) { - return - } - - let matches = []; - - // Iterate over every key (i.e, path), and fetch the value at that key - keys.forEach((key, keyIndex) => { - matches.push( - ...this._findMatches({ - key, - value: item[keyIndex], - searcher - }) - ); - }); - - if (matches.length) { - results.push({ - idx, - item, - matches }); + return results; } - }); - - return results - } - _findMatches({ key, value, searcher }) { - if (!isDefined(value)) { - return [] - } - - let matches = []; - - if (isArray(value)) { - value.forEach(({ v: text, i: idx, n: norm }) => { - if (!isDefined(text)) { - return + _findMatches({ + key, + value, + searcher + }) { + if (!isDefined(value)) { + return []; } - - const { isMatch, score, indices } = searcher.searchIn(text); - - if (isMatch) { - matches.push({ - score, - key, - value: text, - idx, - norm, - indices + let matches = []; + if (isArray(value)) { + value.forEach(({ + v: text, + i: idx, + n: norm + }) => { + if (!isDefined(text)) { + return; + } + const { + isMatch, + score, + indices + } = searcher.searchIn(text); + if (isMatch) { + matches.push({ + score, + key, + value: text, + idx, + norm, + indices + }); + } }); - } - }); - } else { - const { v: text, n: norm } = value; - - const { isMatch, score, indices } = searcher.searchIn(text); - - if (isMatch) { - matches.push({ score, key, value: text, norm, indices }); - } - } - - return matches - } -} - -Fuse.version = '6.6.2'; -Fuse.createIndex = createIndex; -Fuse.parseIndex = parseIndex; -Fuse.config = Config; - -{ - Fuse.parseQuery = parse; -} - -{ - register(ExtendedSearch); -} - - - - -/***/ }), - -/***/ 791: -/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { - -// ESM COMPAT FLAG -__webpack_require__.r(__webpack_exports__); - -// EXPORTS -__webpack_require__.d(__webpack_exports__, { - "__DO_NOT_USE__ActionTypes": function() { return /* binding */ ActionTypes; }, - "applyMiddleware": function() { return /* binding */ applyMiddleware; }, - "bindActionCreators": function() { return /* binding */ bindActionCreators; }, - "combineReducers": function() { return /* binding */ combineReducers; }, - "compose": function() { return /* binding */ compose; }, - "createStore": function() { return /* binding */ createStore; }, - "legacy_createStore": function() { return /* binding */ legacy_createStore; } -}); - -;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/typeof.js -function _typeof(obj) { - "@babel/helpers - typeof"; - - return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { - return typeof obj; - } : function (obj) { - return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }, _typeof(obj); -} -;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/toPrimitive.js - -function _toPrimitive(input, hint) { - if (_typeof(input) !== "object" || input === null) return input; - var prim = input[Symbol.toPrimitive]; - if (prim !== undefined) { - var res = prim.call(input, hint || "default"); - if (_typeof(res) !== "object") return res; - throw new TypeError("@@toPrimitive must return a primitive value."); - } - return (hint === "string" ? String : Number)(input); -} -;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/toPropertyKey.js - - -function _toPropertyKey(arg) { - var key = _toPrimitive(arg, "string"); - return _typeof(key) === "symbol" ? key : String(key); -} -;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/defineProperty.js - -function _defineProperty(obj, key, value) { - key = _toPropertyKey(key); - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; - } - return obj; -} -;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/objectSpread2.js - -function ownKeys(object, enumerableOnly) { - var keys = Object.keys(object); - if (Object.getOwnPropertySymbols) { - var symbols = Object.getOwnPropertySymbols(object); - enumerableOnly && (symbols = symbols.filter(function (sym) { - return Object.getOwnPropertyDescriptor(object, sym).enumerable; - })), keys.push.apply(keys, symbols); - } - return keys; -} -function _objectSpread2(target) { - for (var i = 1; i < arguments.length; i++) { - var source = null != arguments[i] ? arguments[i] : {}; - i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { - _defineProperty(target, key, source[key]); - }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { - Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); - }); - } - return target; -} -;// CONCATENATED MODULE: ./node_modules/redux/es/redux.js - - -/** - * Adapted from React: https://github.com/facebook/react/blob/master/packages/shared/formatProdErrorMessage.js - * - * Do not require this module directly! Use normal throw error calls. These messages will be replaced with error codes - * during build. - * @param {number} code - */ -function formatProdErrorMessage(code) { - return "Minified Redux error #" + code + "; visit https://redux.js.org/Errors?code=" + code + " for the full message or " + 'use the non-minified dev environment for full errors. '; -} - -// Inlined version of the `symbol-observable` polyfill -var $$observable = (function () { - return typeof Symbol === 'function' && Symbol.observable || '@@observable'; -})(); - -/** - * These are private action types reserved by Redux. - * For any unknown actions, you must return the current state. - * If the current state is undefined, you must return the initial state. - * Do not reference these action types directly in your code. - */ -var randomString = function randomString() { - return Math.random().toString(36).substring(7).split('').join('.'); -}; - -var ActionTypes = { - INIT: "@@redux/INIT" + randomString(), - REPLACE: "@@redux/REPLACE" + randomString(), - PROBE_UNKNOWN_ACTION: function PROBE_UNKNOWN_ACTION() { - return "@@redux/PROBE_UNKNOWN_ACTION" + randomString(); - } -}; - -/** - * @param {any} obj The object to inspect. - * @returns {boolean} True if the argument appears to be a plain object. - */ -function isPlainObject(obj) { - if (typeof obj !== 'object' || obj === null) return false; - var proto = obj; - - while (Object.getPrototypeOf(proto) !== null) { - proto = Object.getPrototypeOf(proto); - } - - return Object.getPrototypeOf(obj) === proto; -} - -// Inlined / shortened version of `kindOf` from https://github.com/jonschlinkert/kind-of -function miniKindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; - var type = typeof val; - - switch (type) { - case 'boolean': - case 'string': - case 'number': - case 'symbol': - case 'function': - { - return type; - } - } - - if (Array.isArray(val)) return 'array'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - var constructorName = ctorName(val); - - switch (constructorName) { - case 'Symbol': - case 'Promise': - case 'WeakMap': - case 'WeakSet': - case 'Map': - case 'Set': - return constructorName; - } // other - - - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -} - -function ctorName(val) { - return typeof val.constructor === 'function' ? val.constructor.name : null; -} - -function isError(val) { - return val instanceof Error || typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'; -} - -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' && typeof val.getDate === 'function' && typeof val.setDate === 'function'; -} - -function kindOf(val) { - var typeOfVal = typeof val; - - if (false) {} - - return typeOfVal; -} - -/** - * @deprecated - * - * **We recommend using the `configureStore` method - * of the `@reduxjs/toolkit` package**, which replaces `createStore`. - * - * Redux Toolkit is our recommended approach for writing Redux logic today, - * including store setup, reducers, data fetching, and more. - * - * **For more details, please read this Redux docs page:** - * **https://redux.js.org/introduction/why-rtk-is-redux-today** - * - * `configureStore` from Redux Toolkit is an improved version of `createStore` that - * simplifies setup and helps avoid common bugs. - * - * You should not be using the `redux` core package by itself today, except for learning purposes. - * The `createStore` method from the core `redux` package will not be removed, but we encourage - * all users to migrate to using Redux Toolkit for all Redux code. - * - * If you want to use `createStore` without this visual deprecation warning, use - * the `legacy_createStore` import instead: - * - * `import { legacy_createStore as createStore} from 'redux'` - * - */ - -function createStore(reducer, preloadedState, enhancer) { - var _ref2; - - if (typeof preloadedState === 'function' && typeof enhancer === 'function' || typeof enhancer === 'function' && typeof arguments[3] === 'function') { - throw new Error( true ? formatProdErrorMessage(0) : 0); - } - - if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { - enhancer = preloadedState; - preloadedState = undefined; - } - - if (typeof enhancer !== 'undefined') { - if (typeof enhancer !== 'function') { - throw new Error( true ? formatProdErrorMessage(1) : 0); - } - - return enhancer(createStore)(reducer, preloadedState); - } - - if (typeof reducer !== 'function') { - throw new Error( true ? formatProdErrorMessage(2) : 0); - } - - var currentReducer = reducer; - var currentState = preloadedState; - var currentListeners = []; - var nextListeners = currentListeners; - var isDispatching = false; - /** - * This makes a shallow copy of currentListeners so we can use - * nextListeners as a temporary list while dispatching. - * - * This prevents any bugs around consumers calling - * subscribe/unsubscribe in the middle of a dispatch. - */ - - function ensureCanMutateNextListeners() { - if (nextListeners === currentListeners) { - nextListeners = currentListeners.slice(); - } - } - /** - * Reads the state tree managed by the store. - * - * @returns {any} The current state tree of your application. - */ - - - function getState() { - if (isDispatching) { - throw new Error( true ? formatProdErrorMessage(3) : 0); - } - - return currentState; - } - /** - * Adds a change listener. It will be called any time an action is dispatched, - * and some part of the state tree may potentially have changed. You may then - * call `getState()` to read the current state tree inside the callback. - * - * You may call `dispatch()` from a change listener, with the following - * caveats: - * - * 1. The subscriptions are snapshotted just before every `dispatch()` call. - * If you subscribe or unsubscribe while the listeners are being invoked, this - * will not have any effect on the `dispatch()` that is currently in progress. - * However, the next `dispatch()` call, whether nested or not, will use a more - * recent snapshot of the subscription list. - * - * 2. The listener should not expect to see all state changes, as the state - * might have been updated multiple times during a nested `dispatch()` before - * the listener is called. It is, however, guaranteed that all subscribers - * registered before the `dispatch()` started will be called with the latest - * state by the time it exits. - * - * @param {Function} listener A callback to be invoked on every dispatch. - * @returns {Function} A function to remove this change listener. - */ - - - function subscribe(listener) { - if (typeof listener !== 'function') { - throw new Error( true ? formatProdErrorMessage(4) : 0); - } - - if (isDispatching) { - throw new Error( true ? formatProdErrorMessage(5) : 0); - } - - var isSubscribed = true; - ensureCanMutateNextListeners(); - nextListeners.push(listener); - return function unsubscribe() { - if (!isSubscribed) { - return; - } - - if (isDispatching) { - throw new Error( true ? formatProdErrorMessage(6) : 0); - } - - isSubscribed = false; - ensureCanMutateNextListeners(); - var index = nextListeners.indexOf(listener); - nextListeners.splice(index, 1); - currentListeners = null; - }; - } - /** - * Dispatches an action. It is the only way to trigger a state change. - * - * The `reducer` function, used to create the store, will be called with the - * current state tree and the given `action`. Its return value will - * be considered the **next** state of the tree, and the change listeners - * will be notified. - * - * The base implementation only supports plain object actions. If you want to - * dispatch a Promise, an Observable, a thunk, or something else, you need to - * wrap your store creating function into the corresponding middleware. For - * example, see the documentation for the `redux-thunk` package. Even the - * middleware will eventually dispatch plain object actions using this method. - * - * @param {Object} action A plain object representing “what changed”. It is - * a good idea to keep actions serializable so you can record and replay user - * sessions, or use the time travelling `redux-devtools`. An action must have - * a `type` property which may not be `undefined`. It is a good idea to use - * string constants for action types. - * - * @returns {Object} For convenience, the same action object you dispatched. - * - * Note that, if you use a custom middleware, it may wrap `dispatch()` to - * return something else (for example, a Promise you can await). - */ - - - function dispatch(action) { - if (!isPlainObject(action)) { - throw new Error( true ? formatProdErrorMessage(7) : 0); - } - - if (typeof action.type === 'undefined') { - throw new Error( true ? formatProdErrorMessage(8) : 0); - } - - if (isDispatching) { - throw new Error( true ? formatProdErrorMessage(9) : 0); - } - - try { - isDispatching = true; - currentState = currentReducer(currentState, action); - } finally { - isDispatching = false; - } - - var listeners = currentListeners = nextListeners; - - for (var i = 0; i < listeners.length; i++) { - var listener = listeners[i]; - listener(); - } - - return action; - } - /** - * Replaces the reducer currently used by the store to calculate the state. - * - * You might need this if your app implements code splitting and you want to - * load some of the reducers dynamically. You might also need this if you - * implement a hot reloading mechanism for Redux. - * - * @param {Function} nextReducer The reducer for the store to use instead. - * @returns {void} - */ - - - function replaceReducer(nextReducer) { - if (typeof nextReducer !== 'function') { - throw new Error( true ? formatProdErrorMessage(10) : 0); - } - - currentReducer = nextReducer; // This action has a similiar effect to ActionTypes.INIT. - // Any reducers that existed in both the new and old rootReducer - // will receive the previous state. This effectively populates - // the new state tree with any relevant data from the old one. - - dispatch({ - type: ActionTypes.REPLACE - }); - } - /** - * Interoperability point for observable/reactive libraries. - * @returns {observable} A minimal observable of state changes. - * For more information, see the observable proposal: - * https://github.com/tc39/proposal-observable - */ - - - function observable() { - var _ref; - - var outerSubscribe = subscribe; - return _ref = { - /** - * The minimal observable subscription method. - * @param {Object} observer Any object that can be used as an observer. - * The observer object should have a `next` method. - * @returns {subscription} An object with an `unsubscribe` method that can - * be used to unsubscribe the observable from the store, and prevent further - * emission of values from the observable. - */ - subscribe: function subscribe(observer) { - if (typeof observer !== 'object' || observer === null) { - throw new Error( true ? formatProdErrorMessage(11) : 0); - } - - function observeState() { - if (observer.next) { - observer.next(getState()); + } else { + const { + v: text, + n: norm + } = value; + const { + isMatch, + score, + indices + } = searcher.searchIn(text); + if (isMatch) { + matches.push({ + score, + key, + value: text, + norm, + indices + }); } } - - observeState(); - var unsubscribe = outerSubscribe(observeState); - return { - unsubscribe: unsubscribe - }; + return matches; } - }, _ref[$$observable] = function () { - return this; - }, _ref; - } // When a store is created, an "INIT" action is dispatched so that every - // reducer returns their initial state. This effectively populates - // the initial state tree. - - - dispatch({ - type: ActionTypes.INIT - }); - return _ref2 = { - dispatch: dispatch, - subscribe: subscribe, - getState: getState, - replaceReducer: replaceReducer - }, _ref2[$$observable] = observable, _ref2; -} -/** - * Creates a Redux store that holds the state tree. - * - * **We recommend using `configureStore` from the - * `@reduxjs/toolkit` package**, which replaces `createStore`: - * **https://redux.js.org/introduction/why-rtk-is-redux-today** - * - * The only way to change the data in the store is to call `dispatch()` on it. - * - * There should only be a single store in your app. To specify how different - * parts of the state tree respond to actions, you may combine several reducers - * into a single reducer function by using `combineReducers`. - * - * @param {Function} reducer A function that returns the next state tree, given - * the current state tree and the action to handle. - * - * @param {any} [preloadedState] The initial state. You may optionally specify it - * to hydrate the state from the server in universal apps, or to restore a - * previously serialized user session. - * If you use `combineReducers` to produce the root reducer function, this must be - * an object with the same shape as `combineReducers` keys. - * - * @param {Function} [enhancer] The store enhancer. You may optionally specify it - * to enhance the store with third-party capabilities such as middleware, - * time travel, persistence, etc. The only store enhancer that ships with Redux - * is `applyMiddleware()`. - * - * @returns {Store} A Redux store that lets you read the state, dispatch actions - * and subscribe to changes. - */ - -var legacy_createStore = createStore; - -/** - * Prints a warning in the console if it exists. - * - * @param {String} message The warning message. - * @returns {void} - */ -function warning(message) { - /* eslint-disable no-console */ - if (typeof console !== 'undefined' && typeof console.error === 'function') { - console.error(message); - } - /* eslint-enable no-console */ - - - try { - // This error was thrown as a convenience so that if you enable - // "break on all exceptions" in your console, - // it would pause the execution at this line. - throw new Error(message); - } catch (e) {} // eslint-disable-line no-empty - -} - -function getUnexpectedStateShapeWarningMessage(inputState, reducers, action, unexpectedKeyCache) { - var reducerKeys = Object.keys(reducers); - var argumentName = action && action.type === ActionTypes.INIT ? 'preloadedState argument passed to createStore' : 'previous state received by the reducer'; - - if (reducerKeys.length === 0) { - return 'Store does not have a valid reducer. Make sure the argument passed ' + 'to combineReducers is an object whose values are reducers.'; - } - - if (!isPlainObject(inputState)) { - return "The " + argumentName + " has unexpected type of \"" + kindOf(inputState) + "\". Expected argument to be an object with the following " + ("keys: \"" + reducerKeys.join('", "') + "\""); - } - - var unexpectedKeys = Object.keys(inputState).filter(function (key) { - return !reducers.hasOwnProperty(key) && !unexpectedKeyCache[key]; - }); - unexpectedKeys.forEach(function (key) { - unexpectedKeyCache[key] = true; - }); - if (action && action.type === ActionTypes.REPLACE) return; - - if (unexpectedKeys.length > 0) { - return "Unexpected " + (unexpectedKeys.length > 1 ? 'keys' : 'key') + " " + ("\"" + unexpectedKeys.join('", "') + "\" found in " + argumentName + ". ") + "Expected to find one of the known reducer keys instead: " + ("\"" + reducerKeys.join('", "') + "\". Unexpected keys will be ignored."); - } -} - -function assertReducerShape(reducers) { - Object.keys(reducers).forEach(function (key) { - var reducer = reducers[key]; - var initialState = reducer(undefined, { - type: ActionTypes.INIT - }); - - if (typeof initialState === 'undefined') { - throw new Error( true ? formatProdErrorMessage(12) : 0); + } + Fuse.version = '7.0.0'; + Fuse.createIndex = createIndex; + Fuse.parseIndex = parseIndex; + Fuse.config = Config; + { + Fuse.parseQuery = parse; + } + { + register(ExtendedSearch); } - if (typeof reducer(undefined, { - type: ActionTypes.PROBE_UNKNOWN_ACTION() - }) === 'undefined') { - throw new Error( true ? formatProdErrorMessage(13) : 0); - } - }); -} -/** - * Turns an object whose values are different reducer functions, into a single - * reducer function. It will call every child reducer, and gather their results - * into a single state object, whose keys correspond to the keys of the passed - * reducer functions. - * - * @param {Object} reducers An object whose values correspond to different - * reducer functions that need to be combined into one. One handy way to obtain - * it is to use ES6 `import * as reducers` syntax. The reducers may never return - * undefined for any action. Instead, they should return their initial state - * if the state passed to them was undefined, and the current state for any - * unrecognized action. - * - * @returns {Function} A reducer function that invokes every reducer inside the - * passed object, and builds a state object with the same shape. - */ - - -function combineReducers(reducers) { - var reducerKeys = Object.keys(reducers); - var finalReducers = {}; - - for (var i = 0; i < reducerKeys.length; i++) { - var key = reducerKeys[i]; - - if (false) {} - - if (typeof reducers[key] === 'function') { - finalReducers[key] = reducers[key]; - } - } - - var finalReducerKeys = Object.keys(finalReducers); // This is used to make sure we don't warn about the same - // keys multiple times. - - var unexpectedKeyCache; - - if (false) {} - - var shapeAssertionError; - - try { - assertReducerShape(finalReducers); - } catch (e) { - shapeAssertionError = e; - } - - return function combination(state, action) { - if (state === void 0) { - state = {}; - } - - if (shapeAssertionError) { - throw shapeAssertionError; - } - - if (false) { var warningMessage; } - - var hasChanged = false; - var nextState = {}; - - for (var _i = 0; _i < finalReducerKeys.length; _i++) { - var _key = finalReducerKeys[_i]; - var reducer = finalReducers[_key]; - var previousStateForKey = state[_key]; - var nextStateForKey = reducer(previousStateForKey, action); - - if (typeof nextStateForKey === 'undefined') { - var actionType = action && action.type; - throw new Error( true ? formatProdErrorMessage(14) : 0); - } - - nextState[_key] = nextStateForKey; - hasChanged = hasChanged || nextStateForKey !== previousStateForKey; - } - - hasChanged = hasChanged || finalReducerKeys.length !== Object.keys(state).length; - return hasChanged ? nextState : state; - }; -} - -function bindActionCreator(actionCreator, dispatch) { - return function () { - return dispatch(actionCreator.apply(this, arguments)); - }; -} -/** - * Turns an object whose values are action creators, into an object with the - * same keys, but with every function wrapped into a `dispatch` call so they - * may be invoked directly. This is just a convenience method, as you can call - * `store.dispatch(MyActionCreators.doSomething())` yourself just fine. - * - * For convenience, you can also pass an action creator as the first argument, - * and get a dispatch wrapped function in return. - * - * @param {Function|Object} actionCreators An object whose values are action - * creator functions. One handy way to obtain it is to use ES6 `import * as` - * syntax. You may also pass a single function. - * - * @param {Function} dispatch The `dispatch` function available on your Redux - * store. - * - * @returns {Function|Object} The object mimicking the original object, but with - * every action creator wrapped into the `dispatch` call. If you passed a - * function as `actionCreators`, the return value will also be a single - * function. - */ - - -function bindActionCreators(actionCreators, dispatch) { - if (typeof actionCreators === 'function') { - return bindActionCreator(actionCreators, dispatch); - } - - if (typeof actionCreators !== 'object' || actionCreators === null) { - throw new Error( true ? formatProdErrorMessage(16) : 0); - } - - var boundActionCreators = {}; - - for (var key in actionCreators) { - var actionCreator = actionCreators[key]; - - if (typeof actionCreator === 'function') { - boundActionCreators[key] = bindActionCreator(actionCreator, dispatch); - } - } - - return boundActionCreators; -} - -/** - * Composes single-argument functions from right to left. The rightmost - * function can take multiple arguments as it provides the signature for - * the resulting composite function. - * - * @param {...Function} funcs The functions to compose. - * @returns {Function} A function obtained by composing the argument functions - * from right to left. For example, compose(f, g, h) is identical to doing - * (...args) => f(g(h(...args))). - */ -function compose() { - for (var _len = arguments.length, funcs = new Array(_len), _key = 0; _key < _len; _key++) { - funcs[_key] = arguments[_key]; - } - - if (funcs.length === 0) { - return function (arg) { - return arg; - }; - } - - if (funcs.length === 1) { - return funcs[0]; - } - - return funcs.reduce(function (a, b) { - return function () { - return a(b.apply(void 0, arguments)); - }; - }); -} - -/** - * Creates a store enhancer that applies middleware to the dispatch method - * of the Redux store. This is handy for a variety of tasks, such as expressing - * asynchronous actions in a concise manner, or logging every action payload. - * - * See `redux-thunk` package as an example of the Redux middleware. - * - * Because middleware is potentially asynchronous, this should be the first - * store enhancer in the composition chain. - * - * Note that each middleware will be given the `dispatch` and `getState` functions - * as named arguments. - * - * @param {...Function} middlewares The middleware chain to be applied. - * @returns {Function} A store enhancer applying the middleware. - */ - -function applyMiddleware() { - for (var _len = arguments.length, middlewares = new Array(_len), _key = 0; _key < _len; _key++) { - middlewares[_key] = arguments[_key]; - } - - return function (createStore) { - return function () { - var store = createStore.apply(void 0, arguments); - - var _dispatch = function dispatch() { - throw new Error( true ? formatProdErrorMessage(15) : 0); - }; - - var middlewareAPI = { - getState: store.getState, - dispatch: function dispatch() { - return _dispatch.apply(void 0, arguments); + var SearchByFuse = /** @class */ (function () { + function SearchByFuse(config) { + this._haystack = []; + this._fuseOptions = __assign(__assign({}, config.fuseOptions), { keys: __spreadArray([], config.searchFields, true), includeMatches: true }); } - }; - var chain = middlewares.map(function (middleware) { - return middleware(middlewareAPI); - }); - _dispatch = compose.apply(void 0, chain)(store.dispatch); - return _objectSpread2(_objectSpread2({}, store), {}, { - dispatch: _dispatch - }); + SearchByFuse.prototype.index = function (data) { + this._haystack = data; + if (this._fuse) { + this._fuse.setCollection(data); + } + }; + SearchByFuse.prototype.reset = function () { + this._haystack = []; + this._fuse = undefined; + }; + SearchByFuse.prototype.isEmptyIndex = function () { + return !this._haystack.length; + }; + SearchByFuse.prototype.search = function (needle) { + if (!this._fuse) { + { + this._fuse = new Fuse(this._haystack, this._fuseOptions); + } + } + var results = this._fuse.search(needle); + return results.map(function (value, i) { + return { + item: value.item, + score: value.score || 0, + rank: i + 1, // If value.score is used for sorting, this can create non-stable sorts! + }; + }); + }; + return SearchByFuse; + }()); + + function getSearcher(config) { + { + return new SearchByFuse(config); + } + } + + /** + * Helpers to create HTML elements used by Choices + * Can be overridden by providing `callbackOnCreateTemplates` option. + * `Choices.defaults.templates` allows access to the default template methods from `callbackOnCreateTemplates` + */ + var isEmptyObject = function (obj) { + // eslint-disable-next-line no-restricted-syntax + for (var prop in obj) { + if (Object.prototype.hasOwnProperty.call(obj, prop)) { + return false; + } + } + return true; + }; + var assignCustomProperties = function (el, choice, withCustomProperties) { + var dataset = el.dataset; + var customProperties = choice.customProperties, labelClass = choice.labelClass, labelDescription = choice.labelDescription; + if (labelClass) { + dataset.labelClass = getClassNames(labelClass).join(' '); + } + if (labelDescription) { + dataset.labelDescription = labelDescription; + } + if (withCustomProperties && customProperties) { + if (typeof customProperties === 'string') { + dataset.customProperties = customProperties; + } + else if (typeof customProperties === 'object' && !isEmptyObject(customProperties)) { + dataset.customProperties = JSON.stringify(customProperties); + } + } + }; + var addAriaLabel = function (docRoot, id, element) { + var label = id && docRoot.querySelector("label[for='".concat(id, "']")); + var text = label && label.innerText; + if (text) { + element.setAttribute('aria-label', text); + } + }; + var templates = { + containerOuter: function (_a, dir, isSelectElement, isSelectOneElement, searchEnabled, passedElementType, labelId) { + var containerOuter = _a.classNames.containerOuter; + var div = document.createElement('div'); + div.className = getClassNames(containerOuter).join(' '); + div.dataset.type = passedElementType; + if (dir) { + div.dir = dir; + } + if (isSelectOneElement) { + div.tabIndex = 0; + } + if (isSelectElement) { + div.setAttribute('role', searchEnabled ? 'combobox' : 'listbox'); + if (searchEnabled) { + div.setAttribute('aria-autocomplete', 'list'); + } + else if (!labelId) { + addAriaLabel(this._docRoot, this.passedElement.element.id, div); + } + div.setAttribute('aria-haspopup', 'true'); + div.setAttribute('aria-expanded', 'false'); + } + if (labelId) { + div.setAttribute('aria-labelledby', labelId); + } + return div; + }, + containerInner: function (_a) { + var containerInner = _a.classNames.containerInner; + var div = document.createElement('div'); + div.className = getClassNames(containerInner).join(' '); + return div; + }, + itemList: function (_a, isSelectOneElement) { + var searchEnabled = _a.searchEnabled, _b = _a.classNames, list = _b.list, listSingle = _b.listSingle, listItems = _b.listItems; + var div = document.createElement('div'); + div.className = "".concat(getClassNames(list).join(' '), " ").concat(isSelectOneElement ? getClassNames(listSingle).join(' ') : getClassNames(listItems).join(' ')); + if (this._isSelectElement && searchEnabled) { + div.setAttribute('role', 'listbox'); + } + return div; + }, + placeholder: function (_a, value) { + var allowHTML = _a.allowHTML, placeholder = _a.classNames.placeholder; + var div = document.createElement('div'); + div.className = getClassNames(placeholder).join(' '); + setElementHtml(div, allowHTML, value); + return div; + }, + item: function (_a, choice, removeItemButton) { + var _b, _c, _d; + var allowHTML = _a.allowHTML, removeItemButtonAlignLeft = _a.removeItemButtonAlignLeft, removeItemIconText = _a.removeItemIconText, removeItemLabelText = _a.removeItemLabelText, _e = _a.classNames, item = _e.item, button = _e.button, highlightedState = _e.highlightedState, itemSelectable = _e.itemSelectable, placeholder = _e.placeholder; + var labelClass = choice.labelClass, label = choice.label, disabled = choice.disabled, value = choice.value; + var rawValue = unwrapStringForRaw(value); + var div = document.createElement('div'); + div.className = getClassNames(item).join(' '); + if (labelClass) { + var spanLabel = document.createElement('span'); + setElementHtml(spanLabel, allowHTML, label); + spanLabel.className = getClassNames(labelClass).join(' '); + div.appendChild(spanLabel); + } + else { + setElementHtml(div, allowHTML, label); + } + var dataset = div.dataset; + dataset.item = ''; + dataset.id = choice.id; + dataset.value = rawValue; + assignCustomProperties(div, choice, true); + if (disabled || this.containerOuter.isDisabled) { + div.setAttribute('aria-disabled', 'true'); + } + if (this._isSelectElement) { + div.setAttribute('aria-selected', 'true'); + div.setAttribute('role', 'option'); + } + if (choice.placeholder) { + (_b = div.classList).add.apply(_b, getClassNames(placeholder)); + dataset.placeholder = ''; + } + (_c = div.classList).add.apply(_c, (choice.highlighted ? getClassNames(highlightedState) : getClassNames(itemSelectable))); + if (removeItemButton) { + if (disabled) { + (_d = div.classList).remove.apply(_d, getClassNames(itemSelectable)); + } + dataset.deletable = ''; + var removeButton = document.createElement('button'); + removeButton.type = 'button'; + removeButton.className = getClassNames(button).join(' '); + setElementHtml(removeButton, true, resolveNoticeFunction(removeItemIconText, value)); + var REMOVE_ITEM_LABEL = resolveNoticeFunction(removeItemLabelText, value); + if (REMOVE_ITEM_LABEL) { + removeButton.setAttribute('aria-label', REMOVE_ITEM_LABEL); + } + removeButton.dataset.button = ''; + if (removeItemButtonAlignLeft) { + div.insertAdjacentElement('afterbegin', removeButton); + } + else { + div.appendChild(removeButton); + } + } + return div; + }, + choiceList: function (_a, isSelectOneElement) { + var list = _a.classNames.list; + var div = document.createElement('div'); + div.className = getClassNames(list).join(' '); + if (!isSelectOneElement) { + div.setAttribute('aria-multiselectable', 'true'); + } + div.setAttribute('role', 'listbox'); + return div; + }, + choiceGroup: function (_a, _b) { + var allowHTML = _a.allowHTML, _c = _a.classNames, group = _c.group, groupHeading = _c.groupHeading, itemDisabled = _c.itemDisabled; + var id = _b.id, label = _b.label, disabled = _b.disabled; + var rawLabel = unwrapStringForRaw(label); + var div = document.createElement('div'); + div.className = "".concat(getClassNames(group).join(' '), " ").concat(disabled ? getClassNames(itemDisabled).join(' ') : ''); + div.setAttribute('role', 'group'); + var dataset = div.dataset; + dataset.group = ''; + dataset.id = id; + dataset.value = rawLabel; + if (disabled) { + div.setAttribute('aria-disabled', 'true'); + } + var heading = document.createElement('div'); + heading.className = getClassNames(groupHeading).join(' '); + setElementHtml(heading, allowHTML, label); + div.appendChild(heading); + return div; + }, + choice: function (_a, choice, selectText) { + var _b, _c, _d, _e, _f; + var allowHTML = _a.allowHTML, _g = _a.classNames, item = _g.item, itemChoice = _g.itemChoice, itemSelectable = _g.itemSelectable, selectedState = _g.selectedState, itemDisabled = _g.itemDisabled, description = _g.description, placeholder = _g.placeholder; + var value = choice.value, elementId = choice.elementId, groupId = choice.groupId, label = choice.label, labelClass = choice.labelClass, labelDescription = choice.labelDescription; + var rawValue = unwrapStringForRaw(value); + var div = document.createElement('div'); + div.id = elementId; + div.className = "".concat(getClassNames(item).join(' '), " ").concat(getClassNames(itemChoice).join(' ')); + var describedBy = div; + if (labelClass) { + var spanLabel = document.createElement('span'); + setElementHtml(spanLabel, allowHTML, label); + spanLabel.className = getClassNames(labelClass).join(' '); + describedBy = spanLabel; + div.appendChild(spanLabel); + } + else { + setElementHtml(div, allowHTML, label); + } + if (labelDescription) { + var descId = "".concat(elementId, "-description"); + describedBy.setAttribute('aria-describedby', descId); + var spanDesc = document.createElement('span'); + setElementHtml(spanDesc, allowHTML, labelDescription); + spanDesc.id = descId; + (_b = spanDesc.classList).add.apply(_b, getClassNames(description)); + div.appendChild(spanDesc); + } + if (choice.selected) { + (_c = div.classList).add.apply(_c, getClassNames(selectedState)); + } + if (choice.placeholder) { + (_d = div.classList).add.apply(_d, getClassNames(placeholder)); + } + var dataset = div.dataset; + var showGroupId = groupId && groupId > 0; + div.setAttribute('role', showGroupId ? 'treeitem' : 'option'); + if (showGroupId) { + dataset.groupId = "".concat(groupId); + } + dataset.choice = ''; + dataset.id = choice.id; + dataset.value = rawValue; + dataset.selectText = selectText; + assignCustomProperties(div, choice, false); + if (choice.disabled) { + (_e = div.classList).add.apply(_e, getClassNames(itemDisabled)); + dataset.choiceDisabled = ''; + div.setAttribute('aria-disabled', 'true'); + } + else { + (_f = div.classList).add.apply(_f, getClassNames(itemSelectable)); + dataset.choiceSelectable = ''; + } + return div; + }, + input: function (_a, placeholderValue) { + var _b = _a.classNames, input = _b.input, inputCloned = _b.inputCloned, labelId = _a.labelId; + var inp = document.createElement('input'); + inp.type = 'search'; + inp.className = "".concat(getClassNames(input).join(' '), " ").concat(getClassNames(inputCloned).join(' ')); + inp.autocomplete = 'off'; + inp.autocapitalize = 'off'; + inp.spellcheck = false; + inp.setAttribute('role', 'textbox'); + inp.setAttribute('aria-autocomplete', 'list'); + if (placeholderValue) { + inp.setAttribute('aria-label', placeholderValue); + } + else if (!labelId) { + addAriaLabel(this._docRoot, this.passedElement.element.id, inp); + } + return inp; + }, + dropdown: function (_a) { + var _b, _c; + var _d = _a.classNames, list = _d.list, listDropdown = _d.listDropdown; + var div = document.createElement('div'); + (_b = div.classList).add.apply(_b, getClassNames(list)); + (_c = div.classList).add.apply(_c, getClassNames(listDropdown)); + div.setAttribute('aria-expanded', 'false'); + return div; + }, + notice: function (_a, innerHTML, type) { + var _b = _a.classNames, item = _b.item, itemChoice = _b.itemChoice, addChoice = _b.addChoice, noResults = _b.noResults, noChoices = _b.noChoices, noticeItem = _b.notice; + if (type === void 0) { type = NoticeTypes.generic; } + var classes = __spreadArray(__spreadArray(__spreadArray([], getClassNames(item), true), getClassNames(itemChoice), true), getClassNames(noticeItem), true); + // eslint-disable-next-line default-case + switch (type) { + case NoticeTypes.addChoice: + classes.push.apply(classes, getClassNames(addChoice)); + break; + case NoticeTypes.noResults: + classes.push.apply(classes, getClassNames(noResults)); + break; + case NoticeTypes.noChoices: + classes.push.apply(classes, getClassNames(noChoices)); + break; + } + var notice = document.createElement('div'); + setElementHtml(notice, true, innerHTML); + notice.className = classes.join(' '); + if (type === NoticeTypes.addChoice) { + var dataset = notice.dataset; + dataset.choiceSelectable = ''; + dataset.choice = ''; + } + return notice; + }, + option: function (choice) { + // HtmlOptionElement's label value does not support HTML, so the avoid double escaping unwrap the untrusted string. + var labelValue = unwrapStringForRaw(choice.label); + var opt = new Option(labelValue, choice.value, false, choice.selected); + assignCustomProperties(opt, choice, true); + opt.disabled = choice.disabled; + if (choice.selected) { + opt.setAttribute('selected', ''); + } + return opt; + }, }; - }; -} -/* - * This is a dummy function to check if the function name has been altered by minification. - * If the function has been minified and NODE_ENV !== 'production', warn the user. - */ + /** @see {@link http://browserhacks.com/#hack-acea075d0ac6954f275a70023906050c} */ + var IS_IE11 = '-ms-scroll-limit' in document.documentElement.style && + '-ms-ime-align' in document.documentElement.style; + var USER_DEFAULTS = {}; + var parseDataSetId = function (element) { + if (!element) { + return undefined; + } + var id = element.dataset.id; + return id ? parseInt(id, 10) : undefined; + }; + /** + * Choices + * @author Josh Johnson + */ + var Choices = /** @class */ (function () { + function Choices(element, userConfig) { + if (element === void 0) { element = '[data-choice]'; } + if (userConfig === void 0) { userConfig = {}; } + var _this = this; + this.initialisedOK = undefined; + this._hasNonChoicePlaceholder = false; + this._lastAddedChoiceId = 0; + this._lastAddedGroupId = 0; + var defaults = Choices.defaults; + this.config = __assign(__assign(__assign({}, defaults.allOptions), defaults.options), userConfig); + ObjectsInConfig.forEach(function (key) { + _this.config[key] = __assign(__assign(__assign({}, defaults.allOptions[key]), defaults.options[key]), userConfig[key]); + }); + var config = this.config; + if (!config.silent) { + this._validateConfig(); + } + var docRoot = config.shadowRoot || document.documentElement; + this._docRoot = docRoot; + var passedElement = typeof element === 'string' ? docRoot.querySelector(element) : element; + if (!passedElement || + typeof passedElement !== 'object' || + !(isHtmlInputElement(passedElement) || isHtmlSelectElement(passedElement))) { + if (!passedElement && typeof element === 'string') { + throw TypeError("Selector ".concat(element, " failed to find an element")); + } + throw TypeError("Expected one of the following types text|select-one|select-multiple"); + } + this._elementType = passedElement.type; + this._isTextElement = this._elementType === TEXT_TYPE; + if (this._isTextElement || config.maxItemCount !== 1) { + config.singleModeForMultiSelect = false; + } + if (config.singleModeForMultiSelect) { + this._elementType = SELECT_MULTIPLE_TYPE; + } + this._isSelectOneElement = this._elementType === SELECT_ONE_TYPE; + this._isSelectMultipleElement = this._elementType === SELECT_MULTIPLE_TYPE; + this._isSelectElement = this._isSelectOneElement || this._isSelectMultipleElement; + this._canAddUserChoices = (this._isTextElement && config.addItems) || (this._isSelectElement && config.addChoices); + if (!['auto', 'always'].includes("".concat(config.renderSelectedChoices))) { + config.renderSelectedChoices = 'auto'; + } + if (config.closeDropdownOnSelect === 'auto') { + config.closeDropdownOnSelect = this._isTextElement || this._isSelectOneElement || config.singleModeForMultiSelect; + } + else { + config.closeDropdownOnSelect = coerceBool(config.closeDropdownOnSelect); + } + if (config.placeholder) { + if (config.placeholderValue) { + this._hasNonChoicePlaceholder = true; + } + else if (passedElement.dataset.placeholder) { + this._hasNonChoicePlaceholder = true; + config.placeholderValue = passedElement.dataset.placeholder; + } + } + if (userConfig.addItemFilter && typeof userConfig.addItemFilter !== 'function') { + var re = userConfig.addItemFilter instanceof RegExp ? userConfig.addItemFilter : new RegExp(userConfig.addItemFilter); + config.addItemFilter = re.test.bind(re); + } + if (this._isTextElement) { + this.passedElement = new WrappedInput({ + element: passedElement, + classNames: config.classNames, + }); + } + else { + var selectEl = passedElement; + this.passedElement = new WrappedSelect({ + element: selectEl, + classNames: config.classNames, + template: function (data) { return _this._templates.option(data); }, + extractPlaceholder: config.placeholder && !this._hasNonChoicePlaceholder, + }); + } + this.initialised = false; + this._store = new Store(); + this._currentValue = ''; + config.searchEnabled = (!this._isTextElement && config.searchEnabled) || this._elementType === SELECT_MULTIPLE_TYPE; + this._canSearch = config.searchEnabled; + this._isScrollingOnIe = false; + this._highlightPosition = 0; + this._wasTap = true; + this._placeholderValue = this._generatePlaceholderValue(); + this._baseId = generateId(passedElement, 'choices-'); + /** + * setting direction in cases where it's explicitly set on passedElement + * or when calculated direction is different from the document + */ + this._direction = this.passedElement.dir; + if (!this._direction) { + var elementDirection = window.getComputedStyle(this.passedElement.element).direction; + var documentDirection = window.getComputedStyle(document.documentElement).direction; + if (elementDirection !== documentDirection) { + this._direction = elementDirection; + } + } + this._idNames = { + itemChoice: 'item-choice', + }; + this._templates = defaults.templates; + this._render = this._render.bind(this); + this._onFocus = this._onFocus.bind(this); + this._onBlur = this._onBlur.bind(this); + this._onKeyUp = this._onKeyUp.bind(this); + this._onKeyDown = this._onKeyDown.bind(this); + this._onInput = this._onInput.bind(this); + this._onClick = this._onClick.bind(this); + this._onTouchMove = this._onTouchMove.bind(this); + this._onTouchEnd = this._onTouchEnd.bind(this); + this._onMouseDown = this._onMouseDown.bind(this); + this._onMouseOver = this._onMouseOver.bind(this); + this._onFormReset = this._onFormReset.bind(this); + this._onSelectKey = this._onSelectKey.bind(this); + this._onEnterKey = this._onEnterKey.bind(this); + this._onEscapeKey = this._onEscapeKey.bind(this); + this._onDirectionKey = this._onDirectionKey.bind(this); + this._onDeleteKey = this._onDeleteKey.bind(this); + // If element has already been initialised with Choices, fail silently + if (this.passedElement.isActive) { + if (!config.silent) { + console.warn('Trying to initialise Choices on element already initialised', { element: element }); + } + this.initialised = true; + this.initialisedOK = false; + return; + } + // Let's go + this.init(); + // preserve the selected item list after setup for form reset + this._initialItems = this._store.items.map(function (choice) { return choice.value; }); + } + Object.defineProperty(Choices, "defaults", { + get: function () { + return Object.preventExtensions({ + get options() { + return USER_DEFAULTS; + }, + get allOptions() { + return DEFAULT_CONFIG; + }, + get templates() { + return templates; + }, + }); + }, + enumerable: false, + configurable: true + }); + Choices.prototype.init = function () { + if (this.initialised || this.initialisedOK !== undefined) { + return; + } + this._searcher = getSearcher(this.config); + this._loadChoices(); + this._createTemplates(); + this._createElements(); + this._createStructure(); + if ((this._isTextElement && !this.config.addItems) || + this.passedElement.element.hasAttribute('disabled') || + !!this.passedElement.element.closest('fieldset:disabled')) { + this.disable(); + } + else { + this.enable(); + this._addEventListeners(); + } + // should be triggered **after** disabled state to avoid additional re-draws + this._initStore(); + this.initialised = true; + this.initialisedOK = true; + var callbackOnInit = this.config.callbackOnInit; + // Run callback if it is a function + if (callbackOnInit && typeof callbackOnInit === 'function') { + callbackOnInit.call(this); + } + }; + Choices.prototype.destroy = function () { + if (!this.initialised) { + return; + } + this._removeEventListeners(); + this.passedElement.reveal(); + this.containerOuter.unwrap(this.passedElement.element); + this._store._listeners = []; // prevents select/input value being wiped + this.clearStore(); + this._stopSearch(); + this._templates = Choices.defaults.templates; + this.initialised = false; + this.initialisedOK = undefined; + }; + Choices.prototype.enable = function () { + var _a = this, passedElement = _a.passedElement, containerOuter = _a.containerOuter; + if (passedElement.isDisabled) { + passedElement.enable(); + } + if (containerOuter.isDisabled) { + this._addEventListeners(); + this.input.enable(); + containerOuter.enable(); + this._render(); + } + return this; + }; + Choices.prototype.disable = function () { + var _a = this, passedElement = _a.passedElement, containerOuter = _a.containerOuter; + if (!passedElement.isDisabled) { + passedElement.disable(); + } + if (!containerOuter.isDisabled) { + this._removeEventListeners(); + this.input.disable(); + containerOuter.disable(); + this._render(); + } + return this; + }; + Choices.prototype.highlightItem = function (item, runEvent) { + if (runEvent === void 0) { runEvent = true; } + if (!item || !item.id) { + return this; + } + var choice = this._store.choices.find(function (c) { return c.id === item.id; }); + if (!choice || choice.highlighted) { + return this; + } + this._store.dispatch(highlightItem(choice, true)); + if (runEvent) { + this.passedElement.triggerEvent("highlightItem" /* EventType.highlightItem */, this._getChoiceForOutput(choice)); + } + return this; + }; + Choices.prototype.unhighlightItem = function (item, runEvent) { + if (runEvent === void 0) { runEvent = true; } + if (!item || !item.id) { + return this; + } + var choice = this._store.choices.find(function (c) { return c.id === item.id; }); + if (!choice || !choice.highlighted) { + return this; + } + this._store.dispatch(highlightItem(choice, false)); + if (runEvent) { + this.passedElement.triggerEvent("highlightItem" /* EventType.highlightItem */, this._getChoiceForOutput(choice)); + } + return this; + }; + Choices.prototype.highlightAll = function () { + var _this = this; + this._store.withTxn(function () { + _this._store.items.forEach(function (item) { return _this.highlightItem(item); }); + }); + return this; + }; + Choices.prototype.unhighlightAll = function () { + var _this = this; + this._store.withTxn(function () { + _this._store.items.forEach(function (item) { return _this.unhighlightItem(item); }); + }); + return this; + }; + Choices.prototype.removeActiveItemsByValue = function (value) { + var _this = this; + this._store.withTxn(function () { + _this._store.items.filter(function (item) { return item.value === value; }).forEach(function (item) { return _this._removeItem(item); }); + }); + return this; + }; + Choices.prototype.removeActiveItems = function (excludedId) { + var _this = this; + this._store.withTxn(function () { + _this._store.items.filter(function (_a) { + var id = _a.id; + return id !== excludedId; + }).forEach(function (item) { return _this._removeItem(item); }); + }); + return this; + }; + Choices.prototype.removeHighlightedItems = function (runEvent) { + var _this = this; + if (runEvent === void 0) { runEvent = false; } + this._store.withTxn(function () { + _this._store.highlightedActiveItems.forEach(function (item) { + _this._removeItem(item); + // If this action was performed by the user + // trigger the event + if (runEvent) { + _this._triggerChange(item.value); + } + }); + }); + return this; + }; + Choices.prototype.showDropdown = function (preventInputFocus) { + var _this = this; + if (this.dropdown.isActive) { + return this; + } + requestAnimationFrame(function () { + _this.dropdown.show(); + _this.containerOuter.open(_this.dropdown.distanceFromTopWindow); + if (!preventInputFocus && _this._canSearch) { + _this.input.focus(); + } + _this.passedElement.triggerEvent("showDropdown" /* EventType.showDropdown */); + }); + return this; + }; + Choices.prototype.hideDropdown = function (preventInputBlur) { + var _this = this; + if (!this.dropdown.isActive) { + return this; + } + requestAnimationFrame(function () { + _this.dropdown.hide(); + _this.containerOuter.close(); + if (!preventInputBlur && _this._canSearch) { + _this.input.removeActiveDescendant(); + _this.input.blur(); + } + _this.passedElement.triggerEvent("hideDropdown" /* EventType.hideDropdown */); + }); + return this; + }; + Choices.prototype.getValue = function (valueOnly) { + var _this = this; + if (valueOnly === void 0) { valueOnly = false; } + var values = this._store.items.reduce(function (selectedItems, item) { + var itemValue = valueOnly ? item.value : _this._getChoiceForOutput(item); + selectedItems.push(itemValue); + return selectedItems; + }, []); + return this._isSelectOneElement || this.config.singleModeForMultiSelect ? values[0] : values; + }; + Choices.prototype.setValue = function (items) { + var _this = this; + if (!this.initialisedOK) { + this._warnChoicesInitFailed('setValue'); + return this; + } + this._store.withTxn(function () { + items.forEach(function (value) { + if (value) { + _this._addChoice(mapInputToChoice(value, false)); + } + }); + }); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + Choices.prototype.setChoiceByValue = function (value) { + var _this = this; + if (!this.initialisedOK) { + this._warnChoicesInitFailed('setChoiceByValue'); + return this; + } + if (this._isTextElement) { + return this; + } + this._store.withTxn(function () { + // If only one value has been passed, convert to array + var choiceValue = Array.isArray(value) ? value : [value]; + // Loop through each value and + choiceValue.forEach(function (val) { return _this._findAndSelectChoiceByValue(val); }); + }); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + /** + * Set choices of select input via an array of objects (or function that returns array of object or promise of it), + * a value field name and a label field name. + * This behaves the same as passing items via the choices option but can be called after initialising Choices. + * This can also be used to add groups of choices (see example 2); Optionally pass a true `replaceChoices` value to remove any existing choices. + * Optionally pass a `customProperties` object to add additional data to your choices (useful when searching/filtering etc). + * + * **Input types affected:** select-one, select-multiple + * + * @example + * ```js + * const example = new Choices(element); + * + * example.setChoices([ + * {value: 'One', label: 'Label One', disabled: true}, + * {value: 'Two', label: 'Label Two', selected: true}, + * {value: 'Three', label: 'Label Three'}, + * ], 'value', 'label', false); + * ``` + * + * @example + * ```js + * const example = new Choices(element); + * + * example.setChoices(async () => { + * try { + * const items = await fetch('/items'); + * return items.json() + * } catch(err) { + * console.error(err) + * } + * }); + * ``` + * + * @example + * ```js + * const example = new Choices(element); + * + * example.setChoices([{ + * label: 'Group one', + * id: 1, + * disabled: false, + * choices: [ + * {value: 'Child One', label: 'Child One', selected: true}, + * {value: 'Child Two', label: 'Child Two', disabled: true}, + * {value: 'Child Three', label: 'Child Three'}, + * ] + * }, + * { + * label: 'Group two', + * id: 2, + * disabled: false, + * choices: [ + * {value: 'Child Four', label: 'Child Four', disabled: true}, + * {value: 'Child Five', label: 'Child Five'}, + * {value: 'Child Six', label: 'Child Six', customProperties: { + * description: 'Custom description about child six', + * random: 'Another random custom property' + * }}, + * ] + * }], 'value', 'label', false); + * ``` + */ + Choices.prototype.setChoices = function (choicesArrayOrFetcher, value, label, replaceChoices) { + var _this = this; + if (choicesArrayOrFetcher === void 0) { choicesArrayOrFetcher = []; } + if (value === void 0) { value = 'value'; } + if (label === void 0) { label = 'label'; } + if (replaceChoices === void 0) { replaceChoices = false; } + if (!this.initialisedOK) { + this._warnChoicesInitFailed('setChoices'); + return this; + } + if (!this._isSelectElement) { + throw new TypeError("setChoices can't be used with INPUT based Choices"); + } + if (typeof value !== 'string' || !value) { + throw new TypeError("value parameter must be a name of 'value' field in passed objects"); + } + // Clear choices if needed + if (replaceChoices) { + this.clearChoices(); + } + if (typeof choicesArrayOrFetcher === 'function') { + // it's a choices fetcher function + var fetcher_1 = choicesArrayOrFetcher(this); + if (typeof Promise === 'function' && fetcher_1 instanceof Promise) { + // that's a promise + // eslint-disable-next-line no-promise-executor-return + return new Promise(function (resolve) { return requestAnimationFrame(resolve); }) + .then(function () { return _this._handleLoadingState(true); }) + .then(function () { return fetcher_1; }) + .then(function (data) { return _this.setChoices(data, value, label, replaceChoices); }) + .catch(function (err) { + if (!_this.config.silent) { + console.error(err); + } + }) + .then(function () { return _this._handleLoadingState(false); }) + .then(function () { return _this; }); + } + // function returned something else than promise, let's check if it's an array of choices + if (!Array.isArray(fetcher_1)) { + throw new TypeError(".setChoices first argument function must return either array of choices or Promise, got: ".concat(typeof fetcher_1)); + } + // recursion with results, it's sync and choices were cleared already + return this.setChoices(fetcher_1, value, label, false); + } + if (!Array.isArray(choicesArrayOrFetcher)) { + throw new TypeError(".setChoices must be called either with array of choices with a function resulting into Promise of array of choices"); + } + this.containerOuter.removeLoadingState(); + this._store.withTxn(function () { + var isDefaultValue = value === 'value'; + var isDefaultLabel = label === 'label'; + choicesArrayOrFetcher.forEach(function (groupOrChoice) { + if ('choices' in groupOrChoice) { + var group = groupOrChoice; + if (!isDefaultLabel) { + group = __assign(__assign({}, group), { label: group[label] }); + } + _this._addGroup(mapInputToChoice(group, true)); + } + else { + var choice = groupOrChoice; + if (!isDefaultLabel || !isDefaultValue) { + choice = __assign(__assign({}, choice), { value: choice[value], label: choice[label] }); + } + _this._addChoice(mapInputToChoice(choice, false)); + } + }); + }); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + Choices.prototype.refresh = function (withEvents, selectFirstOption, deselectAll) { + var _this = this; + if (withEvents === void 0) { withEvents = false; } + if (selectFirstOption === void 0) { selectFirstOption = false; } + if (deselectAll === void 0) { deselectAll = false; } + if (!this._isSelectElement) { + if (!this.config.silent) { + console.warn('refresh method can only be used on choices backed by a element"),this)},e.prototype.removeChoice=function(e){var t=this._store.choices.find((function(t){return t.value===e}));return t?(this._store.dispatch(function(e){return{type:r,choice:e}}(t)),this._searcher.reset(),t.selected&&this.passedElement.triggerEvent("removeItem",this._getChoiceForOutput(t)),this):this},e.prototype.clearChoices=function(){return this.passedElement.element.innerHTML="",this._store.dispatch({type:h}),this._searcher.reset(),this},e.prototype.clearStore=function(){return this._store.reset(),this._lastAddedChoiceId=0,this._lastAddedGroupId=0,this._searcher.reset(),this},e.prototype.clearInput=function(){return this.input.clear(!this._isSelectOneElement),this._clearNotice(),this._isSearching&&this._stopSearch(),this},e.prototype._validateConfig=function(){var e,t,i,n=this.config,s=(e=V,t=Object.keys(n).sort(),i=Object.keys(e).sort(),t.filter((function(e){return i.indexOf(e)<0})));s.length&&console.warn("Unknown config option(s) passed",s.join(", ")),n.allowHTML&&n.allowHtmlUserInput&&(n.addItems&&console.warn("Warning: allowHTML/allowHtmlUserInput/addItems all being true is strongly not recommended and may lead to XSS attacks"),n.addChoices&&console.warn("Warning: allowHTML/allowHtmlUserInput/addChoices all being true is strongly not recommended and may lead to XSS attacks"))},e.prototype._render=function(e){void 0===e&&(e={choices:!0,groups:!0,items:!0}),this._store.inTxn()||(this._isSelectElement&&(e.choices||e.groups)&&this._renderChoices(),e.items&&this._renderItems())},e.prototype._renderChoices=function(){var e=this;if(this.choiceList.clear(),this._canAddItems()){var t=this.config,i=this._store,n=i.activeGroups,s=i.activeChoices,o=document.createDocumentFragment(),r=!0;if(s.length){if(t.resetScrollPosition&&requestAnimationFrame((function(){return e.choiceList.scrollToTop()})),n.length&&!this._isSearching){if(!this._hasNonChoicePlaceholder){var a=s.filter((function(e){return e.placeholder&&-1===e.groupId}));a.length&&(o=this._createChoicesFragment(a,o))}o=this._createGroupsFragment(n,s,o)}else o=this._createChoicesFragment(s,o);r=!o.childNodes.length}var c=this._notice;r?c||(this._notice={text:b(t.noChoicesText),type:W}):c&&c.type===W&&(this._notice=void 0),this._renderNotice(),r||(this.choiceList.element.append(o),this._highlightChoice())}},e.prototype._renderItems=function(){var e=this._store.items||[];this.itemList.clear();var t=this._createItemsFragment(e);t.childNodes.length&&this.itemList.element.append(t)},e.prototype._createGroupsFragment=function(e,t,i){var n=this;void 0===i&&(i=document.createDocumentFragment());var s=this.config;s.shouldSort&&e.sort(s.sorter);var o=t.filter((function(e){return!e.groupId}));return o.length&&this._createChoicesFragment(o,i,!1),e.forEach((function(e){var o=function(e){return t.filter((function(t){return n._isSelectOneElement?t.groupId===e.id:t.groupId===e.id&&("always"===s.renderSelectedChoices||!t.selected)}))}(e);if(o.length){var r=n._templates.choiceGroup(n.config,e);i.appendChild(r),n._createChoicesFragment(o,i,!0)}})),i},e.prototype._createChoicesFragment=function(e,t,i){var s=this;void 0===t&&(t=document.createDocumentFragment()),void 0===i&&(i=!1);var o=this,r=o.config,a=o._isSearching,c=o._isSelectOneElement,h=r.searchResultLimit,l=r.renderChoiceLimit,u=[],d=r.appendGroupInSearch&&a;if(d&&this._store.groups.forEach((function(e){u[e.id]=e.label})),this._isSelectElement){var p=e.filter((function(e){return!e.element}));p.length&&this.passedElement.addOptions(p)}var f="auto"===r.renderSelectedChoices&&!c,m=[],v=[];e.forEach((function(e){a&&!e.rank||f&&e.selected||(s._hasNonChoicePlaceholder||!e.placeholder?v.push(e):m.push(e))})),a?v.sort(w):r.shouldSort&&v.sort(r.sorter);var g=c&&m.length?n(n([],m,!0),v,!0):v,_=g.length,y=_;return a&&h>0?y=h:l>0&&!i&&(y=l),y<_&&(_=y),_--,g.every((function(e,i){var n=s._templates.choice(r,e,r.itemSelectText);if(d&&e.groupId>0){var o=u[e.groupId];o&&(n.innerHTML+=" (".concat(o,")"))}return t.appendChild(n),i<_})),t},e.prototype._createItemsFragment=function(e,t){var i=this;void 0===t&&(t=document.createDocumentFragment());var n=this.config,s=n.removeItemButton,o=n.delimiter;n.shouldSortItems&&!this._isSelectOneElement&&e.sort(n.sorter),this._isTextElement&&(this.passedElement.value=e.map((function(e){return e.value})).join(o));var r=function(e){var o=i._templates.item(n,e,s);t.appendChild(o)};return e.forEach(r),this._isSelectOneElement&&this._hasNonChoicePlaceholder&&!e.length&&r(K({selected:!0,value:"",label:this.config.placeholderValue||"",active:!0,placeholder:!0},!1)),t},e.prototype._displayNotice=function(e,t,i){void 0===i&&(i=!0);var n=this._notice;n&&(n.type===t&&n.text===e||n.type===U&&(t===G||t===W))?i&&this.showDropdown(!0):(this._clearNotice(),this._notice=e?{text:e,type:t}:void 0,this._renderNotice(),i&&e&&this.showDropdown(!0))},e.prototype._clearNotice=function(){if(this._notice){var e=this.choiceList.element.querySelector(A(this.config.classNames.notice));e&&e.remove(),this._notice=void 0}},e.prototype._renderNotice=function(){var e=this._notice;if(e){var t=this._templates.notice(this.config,e.text,e.type);this.choiceList.prepend(t)}},e.prototype._getChoiceForOutput=function(e,t){if(e){var i=e.groupId>0?this._store.getGroupById(e.groupId):null;return{id:e.id,highlighted:e.highlighted,labelClass:e.labelClass,labelDescription:e.labelDescription,customProperties:e.customProperties,disabled:e.disabled,active:e.active,label:e.label,placeholder:e.placeholder,value:e.value,groupValue:i&&i.label?i.label:void 0,element:e.element,keyCode:t}}},e.prototype._triggerChange=function(e){null!=e&&this.passedElement.triggerEvent("change",{value:e})},e.prototype._handleButtonAction=function(e){var t=this._store.items;if(t.length&&this.config.removeItems&&this.config.removeItemButton){var i=e&&qe(e.parentNode),n=i&&t.find((function(e){return e.id===i}));if(n&&(this._removeItem(n),this._triggerChange(n.value),this._isSelectOneElement&&!this._hasNonChoicePlaceholder)){var s=this._store.choices.reverse().find((function(e){return!e.disabled&&e.placeholder}));s&&(this._addItem(s),s.value&&this._triggerChange(s.value))}}},e.prototype._handleItemAction=function(e,t){var i=this;void 0===t&&(t=!1);var n=this._store.items;if(n.length&&this.config.removeItems&&!this._isSelectOneElement){var s=qe(e);s&&(n.forEach((function(e){e.id!==s||e.highlighted?!t&&e.highlighted&&i.unhighlightItem(e):i.highlightItem(e)})),this.input.focus())}},e.prototype._handleChoiceAction=function(e){var t=this,i=qe(e),n=i&&this._store.getChoiceById(i);if(!n||n.disabled)return!1;var s=this.dropdown.isActive;if(!n.selected){if(!this._canAddItems())return!0;this._store.withTxn((function(){t._addItem(n,!0,!0),t.clearInput(),t.unhighlightAll()})),this._triggerChange(n.value)}return s&&this.config.closeDropdownOnSelect&&(this.hideDropdown(!0),this.containerOuter.element.focus()),!0},e.prototype._handleBackspace=function(e){var t=this.config;if(t.removeItems&&e.length){var i=e[e.length-1],n=e.some((function(e){return e.highlighted}));t.editItems&&!n&&i?(this.input.value=i.value,this.input.setWidth(),this._removeItem(i),this._triggerChange(i.value)):(n||this.highlightItem(i,!1),this.removeHighlightedItems(!0))}},e.prototype._loadChoices=function(){var e,t=this.config;if(this._isTextElement){this._presetChoices=t.items.map((function(e){return K(e,!1)}));var i=this.passedElement.value;if(i){var n=i.split(t.delimiter).map((function(e){return K(e,!1)}));this._presetChoices=this._presetChoices.concat(n)}this._presetChoices.forEach((function(e){e.selected=!0}))}else if(this._isSelectElement){this._presetChoices=t.choices.map((function(e){return K(e,!0)}));var s=this.passedElement.optionsAsChoices();s&&(e=this._presetChoices).push.apply(e,s)}},e.prototype._handleLoadingState=function(e){void 0===e&&(e=!0);var t=this.config;e?(this.disable(),this.containerOuter.addLoadingState(),this._isSelectOneElement?(this.itemList.clear(),this.itemList.element.append(this._templates.placeholder(t,t.loadingText))):this.input.placeholder=t.loadingText):(this.enable(),this.containerOuter.removeLoadingState(),this._isSelectOneElement||(this.input.placeholder=this._placeholderValue||""))},e.prototype._handleSearch=function(e){if(this.input.isFocussed){var t=this.config,i=t.searchFloor,n=t.searchChoices,s=this._store.choices.some((function(e){return!e.active}));if(null!=e&&e.length>=i){var o=n?this._searchChoices(e):0;null!==o&&this.passedElement.triggerEvent("search",{value:e,resultCount:o})}else s&&this._stopSearch()}},e.prototype._canAddItems=function(){var e=this.config,t=e.maxItemCount,i=e.maxItemText;return!(!e.singleModeForMultiSelect&&t>0&&t<=this._store.items.length&&(this._displayNotice("function"==typeof i?i(t):i,U),1))},e.prototype._canCreateItem=function(e){var t=this.config,i=!0,n="";if(i&&"function"==typeof t.addItemFilter&&!t.addItemFilter(e)&&(i=!1,n=y(t.customAddItemText,e)),i){var s=this._store.choices.find((function(i){return t.valueComparer(i.value,e)}));if(this._isSelectElement){if(s)return this._displayNotice("",U),!1}else this._isTextElement&&!t.duplicateItemsAllowed&&s&&(i=!1,n=y(t.uniqueItemText,e))}return i&&(n=y(t.addItemText,e)),n&&this._displayNotice(n,U),i},e.prototype._searchChoices=function(e){var t=e.trim().replace(/\s{2,}/," ");if(!t.length||t===this._currentValue)return null;var i=this._searcher;i.isEmptyIndex()&&i.index(this._store.searchableChoices);var n=i.search(t);this._currentValue=t,this._highlightPosition=0,this._isSearching=!0;var s=this._notice,o=s&&s.type;return o!==U&&(n.length?o===G&&this._clearNotice():this._displayNotice(b(this.config.noResultsText),G)),this._store.dispatch(function(e){return{type:a,results:e}}(n)),n.length},e.prototype._stopSearch=function(){var e=this._isSearching;this._currentValue="",this._isSearching=!1,e&&(this._store.dispatch({type:c,active:!0}),this.passedElement.triggerEvent("search",{value:"",resultCount:0}))},e.prototype._addEventListeners=function(){var e=this._docRoot,t=this.containerOuter.element,i=this.input.element;e.addEventListener("touchend",this._onTouchEnd,!0),t.addEventListener("keydown",this._onKeyDown,!0),t.addEventListener("mousedown",this._onMouseDown,!0),e.addEventListener("click",this._onClick,{passive:!0}),e.addEventListener("touchmove",this._onTouchMove,{passive:!0}),this.dropdown.element.addEventListener("mouseover",this._onMouseOver,{passive:!0}),this._isSelectOneElement&&(t.addEventListener("focus",this._onFocus,{passive:!0}),t.addEventListener("blur",this._onBlur,{passive:!0})),i.addEventListener("keyup",this._onKeyUp,{passive:!0}),i.addEventListener("input",this._onInput,{passive:!0}),i.addEventListener("focus",this._onFocus,{passive:!0}),i.addEventListener("blur",this._onBlur,{passive:!0}),i.form&&i.form.addEventListener("reset",this._onFormReset,{passive:!0}),this.input.addEventListeners()},e.prototype._removeEventListeners=function(){var e=this._docRoot,t=this.containerOuter.element,i=this.input.element;e.removeEventListener("touchend",this._onTouchEnd,!0),t.removeEventListener("keydown",this._onKeyDown,!0),t.removeEventListener("mousedown",this._onMouseDown,!0),e.removeEventListener("click",this._onClick),e.removeEventListener("touchmove",this._onTouchMove),this.dropdown.element.removeEventListener("mouseover",this._onMouseOver),this._isSelectOneElement&&(t.removeEventListener("focus",this._onFocus),t.removeEventListener("blur",this._onBlur)),i.removeEventListener("keyup",this._onKeyUp),i.removeEventListener("input",this._onInput),i.removeEventListener("focus",this._onFocus),i.removeEventListener("blur",this._onBlur),i.form&&i.form.removeEventListener("reset",this._onFormReset),this.input.removeEventListeners()},e.prototype._onKeyDown=function(e){var t=e.keyCode,i=this._store.items,n=this.input.isFocussed,s=this.dropdown.isActive,o=this.itemList.element.hasChildNodes(),r=1===e.key.length||2===e.key.length&&e.key.charCodeAt(0)>=55296||"Unidentified"===e.key;switch(this._isTextElement||s||(this.showDropdown(),!this.input.isFocussed&&r&&(this.input.value+=e.key," "===e.key&&e.preventDefault())),t){case 65:return this._onSelectKey(e,o);case 13:return this._onEnterKey(e,s);case 27:return this._onEscapeKey(e,s);case 38:case 33:case 40:case 34:return this._onDirectionKey(e,s);case 8:case 46:return this._onDeleteKey(e,i,n)}},e.prototype._onKeyUp=function(){this._canSearch=this.config.searchEnabled},e.prototype._onInput=function(){var e=this.input.value;if(!e)return this._isTextElement?this.hideDropdown(!0):this._stopSearch(),void this._clearNotice();this._canAddItems()&&(this._canSearch&&this._handleSearch(e),this._canAddUserChoices&&(this._canCreateItem(e),this._isSelectElement&&(this._highlightPosition=0,this._highlightChoice())))},e.prototype._onSelectKey=function(e,t){(e.ctrlKey||e.metaKey)&&t&&(this._canSearch=!1,this.config.removeItems&&!this.input.value&&this.input.element===document.activeElement&&this.highlightAll())},e.prototype._onEnterKey=function(e,t){var i=this,n=this.config,s=this.input.value,o=e.target,r=o&&o.hasAttribute("data-button");if(e.preventDefault(),r)this._handleButtonAction(o);else if(t){var a=this.dropdown.element.querySelector(A(n.classNames.highlightedState));if(!a||!this._handleChoiceAction(a))if(o&&s){if(this._canAddItems()){var c=!1;this._store.withTxn((function(){if(!(c=i._findAndSelectChoiceByValue(s,!0))){if(!i._canAddUserChoices)return;if(!i._canCreateItem(s))return;var e=g(s),t=n.allowHtmlUserInput||e===s?s:{escaped:e,raw:s};i._addChoice(K({value:t,label:t,selected:!0},!1),!0,!0),c=!0}i.clearInput(),i.unhighlightAll()})),c&&(this._triggerChange(s),n.closeDropdownOnSelect&&this.hideDropdown(!0))}}else this.hideDropdown(!0)}else(this._isSelectElement||this._notice)&&this.showDropdown()},e.prototype._onEscapeKey=function(e,t){t&&(e.stopPropagation(),this.hideDropdown(!0),this.containerOuter.element.focus())},e.prototype._onDirectionKey=function(e,t){var i,n,s,o=e.keyCode,r=e.metaKey;if(t||this._isSelectOneElement){this.showDropdown(),this._canSearch=!1;var a=40===o||34===o?1:-1,c="[data-choice-selectable]",h=void 0;if(r||34===o||33===o)h=this.dropdown.element.querySelector(a>0?"".concat(c,":last-of-type"):c);else{var l=this.dropdown.element.querySelector(A(this.config.classNames.highlightedState));h=l?function(e,t,i){void 0===i&&(i=1);for(var n="".concat(i>0?"next":"previous","ElementSibling"),s=e[n];s;){if(s.matches(t))return s;s=s[n]}return null}(l,c,a):this.dropdown.element.querySelector(c)}h&&(i=h,n=this.choiceList.element,void 0===(s=a)&&(s=1),(s>0?n.scrollTop+n.offsetHeight>=i.offsetTop+i.offsetHeight:i.offsetTop>=n.scrollTop)||this.choiceList.scrollToChildElement(h,a),this._highlightChoice(h)),e.preventDefault()}},e.prototype._onDeleteKey=function(e,t,i){this._isSelectOneElement||e.target.value||!i||(this._handleBackspace(t),e.preventDefault())},e.prototype._onTouchMove=function(){this._wasTap&&(this._wasTap=!1)},e.prototype._onTouchEnd=function(e){var t=(e||e.touches[0]).target;this._wasTap&&this.containerOuter.element.contains(t)&&((t===this.containerOuter.element||t===this.containerInner.element)&&(this._isTextElement?this.input.focus():this._isSelectMultipleElement&&this.showDropdown()),e.stopPropagation()),this._wasTap=!0},e.prototype._onMouseDown=function(e){var t=e.target;if(t instanceof HTMLElement){if(Ve&&this.choiceList.element.contains(t)){var i=this.choiceList.element.firstElementChild;this._isScrollingOnIe="ltr"===this._direction?e.offsetX>=i.offsetWidth:e.offsetXthis._highlightPosition?n[this._highlightPosition]:n[n.length-1])||(s=n[0]),(t=s.classList).add.apply(t,I(i)),s.setAttribute("aria-selected","true"),this.passedElement.triggerEvent("highlightChoice",{el:s}),this.dropdown.isActive&&(this.input.setActiveDescendant(s.id),this.containerOuter.setActiveDescendant(s.id))}},e.prototype._addItem=function(e,t,i){void 0===t&&(t=!0),void 0===i&&(i=!1);var n=e.id;if(!n)throw new TypeError("item.id must be set before _addItem is called for a choice/item");(this.config.singleModeForMultiSelect||this._isSelectOneElement)&&this.removeActiveItems(n),this._store.dispatch(function(e){return{type:u,item:e}}(e)),t&&(this.passedElement.triggerEvent("addItem",this._getChoiceForOutput(e)),i&&this.passedElement.triggerEvent("choice",this._getChoiceForOutput(e)))},e.prototype._removeItem=function(e){e.id&&(this._store.dispatch(function(e){return{type:d,item:e}}(e)),this.passedElement.triggerEvent("removeItem",this._getChoiceForOutput(e)))},e.prototype._addChoice=function(e,t,i){if(void 0===t&&(t=!0),void 0===i&&(i=!1),e.id)throw new TypeError("Can not re-add a choice which has already been added");this._lastAddedChoiceId++,e.id=this._lastAddedChoiceId,e.elementId="".concat(this._baseId,"-").concat(this._idNames.itemChoice,"-").concat(e.id);var n=this.config,s=n.prependValue,r=n.appendValue;s&&(e.value=s+e.value),r&&(e.value+=r.toString()),(s||r)&&e.element&&(e.element.value=e.value),this._store.dispatch(function(e){return{type:o,choice:e}}(e)),e.selected&&this._addItem(e,t,i)},e.prototype._addGroup=function(e,t){var i=this;if(void 0===t&&(t=!0),e.id)throw new TypeError("Can not re-add a group which has already been added");if(this._store.dispatch(function(e){return{type:l,group:e}}(e)),e.choices){var n=e;this._lastAddedGroupId++,n.id=this._lastAddedGroupId;var s=e.id,o=e.choices;n.choices=[],o.forEach((function(n){n.groupId=s,e.disabled&&(n.disabled=!0),i._addChoice(n,t)}))}},e.prototype._createTemplates=function(){var e=this,t=this.config.callbackOnCreateTemplates,i={};t&&"function"==typeof t&&(i=t.call(this,_,C));var n={};Object.keys(this._templates).forEach((function(t){n[t]=t in i?i[t].bind(e):e._templates[t].bind(e)})),this._templates=n},e.prototype._createElements=function(){var e=this._templates,t=this.config,i=t.position,n=t.classNames,s=this._elementType;this.containerOuter=new N({element:e.containerOuter(t,this._direction,this._isSelectElement,this._isSelectOneElement,t.searchEnabled,s,t.labelId),classNames:n,type:s,position:i}),this.containerInner=new N({element:e.containerInner(t),classNames:n,type:s,position:i}),this.input=new F({element:e.input(t,this._placeholderValue),classNames:n,type:s,preventPaste:!t.paste}),this.choiceList=new k({element:e.choiceList(t,this._isSelectOneElement)}),this.itemList=new k({element:e.itemList(t,this._isSelectOneElement)}),this.dropdown=new L({element:e.dropdown(t),classNames:n,type:s})},e.prototype._createStructure=function(){var e=this,t=e.containerInner,i=e.containerOuter,n=e.passedElement,s=e.dropdown,o=e.input;n.conceal(),t.wrap(n.element),i.wrap(t.element),this._isSelectOneElement?o.placeholder=this.config.searchPlaceholderValue||"":(this._placeholderValue&&(o.placeholder=this._placeholderValue),o.setWidth()),i.element.appendChild(t.element),i.element.appendChild(s.element),t.element.appendChild(this.itemList.element),s.element.appendChild(this.choiceList.element),this._isSelectOneElement?this.config.searchEnabled&&s.element.insertBefore(o.element,s.element.firstChild):t.element.appendChild(o.element),this._highlightPosition=0,this._isSearching=!1},e.prototype._initStore=function(){var e=this;this._store.subscribe(this._render),this._store.withTxn((function(){e._addPredefinedChoices(e._presetChoices,e._isSelectOneElement&&!e._hasNonChoicePlaceholder,!1)})),this._isSelectOneElement&&this._hasNonChoicePlaceholder&&this._render({choices:!1,groups:!1,items:!0})},e.prototype._addPredefinedChoices=function(e,t,i){var n=this;void 0===t&&(t=!1),void 0===i&&(i=!0),t&&-1===e.findIndex((function(e){return e.selected}))&&e.some((function(e){return!e.disabled&&!("choices"in e)&&(e.selected=!0,!0)})),e.forEach((function(e){"choices"in e?n._isSelectElement&&n._addGroup(e,i):n._addChoice(e,i)}))},e.prototype._findAndSelectChoiceByValue=function(e,t){var i=this;void 0===t&&(t=!1);var n=this._store.choices.find((function(t){return i.config.valueComparer(t.value,e)}));return!(!n||n.disabled||n.selected||(this._addItem(n,!0,t),0))},e.prototype._generatePlaceholderValue=function(){var e=this.config;if(!e.placeholder)return null;if(this._hasNonChoicePlaceholder)return e.placeholderValue;if(this._isSelectElement){var t=this.passedElement.placeholderOption;return t?t.text:null}return null},e.prototype._warnChoicesInitFailed=function(e){if(!this.config.silent){if(!this.initialised)throw new TypeError("".concat(e," called on a non-initialised instance of Choices"));if(!this.initialisedOK)throw new TypeError("".concat(e," called for an element which has multiple instances of Choices initialised on it"))}},e.version="11.0.0-rc7",e}()})); diff --git a/assets/scripts/choices.mjs b/assets/scripts/choices.mjs new file mode 100644 index 00000000..645812fd --- /dev/null +++ b/assets/scripts/choices.mjs @@ -0,0 +1,5189 @@ +/*! choices.js v11.0.0-rc7 | © 2024 Josh Johnson | https://github.com/jshjohnson/Choices#readme */ + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise, SuppressedError, Symbol */ + +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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; + }; + return extendStatics(d, b); +}; +function __extends(d, b) { + if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} +var __assign = function () { + __assign = Object.assign || function __assign(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); +}; +function __spreadArray(to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +} +typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}; + +var ActionType = { + ADD_CHOICE: 'ADD_CHOICE', + REMOVE_CHOICE: 'REMOVE_CHOICE', + FILTER_CHOICES: 'FILTER_CHOICES', + ACTIVATE_CHOICES: 'ACTIVATE_CHOICES', + CLEAR_CHOICES: 'CLEAR_CHOICES', + ADD_GROUP: 'ADD_GROUP', + ADD_ITEM: 'ADD_ITEM', + REMOVE_ITEM: 'REMOVE_ITEM', + HIGHLIGHT_ITEM: 'HIGHLIGHT_ITEM', +}; + +var ObjectsInConfig = ['fuseOptions', 'classNames']; + +var addChoice = function (choice) { return ({ + type: ActionType.ADD_CHOICE, + choice: choice, +}); }; +var removeChoice = function (choice) { return ({ + type: ActionType.REMOVE_CHOICE, + choice: choice, +}); }; +var filterChoices = function (results) { return ({ + type: ActionType.FILTER_CHOICES, + results: results, +}); }; +var activateChoices = function (active) { + return ({ + type: ActionType.ACTIVATE_CHOICES, + active: active, + }); +}; +var clearChoices = function () { return ({ + type: ActionType.CLEAR_CHOICES, +}); }; + +var addGroup = function (group) { return ({ + type: ActionType.ADD_GROUP, + group: group, +}); }; + +var addItem = function (item) { return ({ + type: ActionType.ADD_ITEM, + item: item, +}); }; +var removeItem = function (item) { return ({ + type: ActionType.REMOVE_ITEM, + item: item, +}); }; +var highlightItem = function (item, highlighted) { return ({ + type: ActionType.HIGHLIGHT_ITEM, + item: item, + highlighted: highlighted, +}); }; + +/* eslint-disable @typescript-eslint/no-explicit-any */ +var getRandomNumber = function (min, max) { return Math.floor(Math.random() * (max - min) + min); }; +var generateChars = function (length) { + return Array.from({ length: length }, function () { return getRandomNumber(0, 36).toString(36); }).join(''); +}; +var generateId = function (element, prefix) { + var id = element.id || (element.name && "".concat(element.name, "-").concat(generateChars(2))) || generateChars(4); + id = id.replace(/(:|\.|\[|\]|,)/g, ''); + id = "".concat(prefix, "-").concat(id); + return id; +}; +var getAdjacentEl = function (startEl, selector, direction) { + if (direction === void 0) { direction = 1; } + var prop = "".concat(direction > 0 ? 'next' : 'previous', "ElementSibling"); + var sibling = startEl[prop]; + while (sibling) { + if (sibling.matches(selector)) { + return sibling; + } + sibling = sibling[prop]; + } + return null; +}; +var isScrolledIntoView = function (element, parent, direction) { + if (direction === void 0) { direction = 1; } + var isVisible; + if (direction > 0) { + // In view from bottom + isVisible = parent.scrollTop + parent.offsetHeight >= element.offsetTop + element.offsetHeight; + } + else { + // In view from top + isVisible = element.offsetTop >= parent.scrollTop; + } + return isVisible; +}; +var sanitise = function (value) { + if (typeof value !== 'string') { + if (value === null || value === undefined) { + return ''; + } + if (typeof value === 'object') { + if ('raw' in value) { + return sanitise(value.raw); + } + if ('trusted' in value) { + return value.trusted; + } + } + return value; + } + return value + .replace(/&/g, '&') + .replace(/>/g, '>') + .replace(/ 0 ? this.element.scrollTop + elementPos - listScrollPosition : element.offsetTop; + requestAnimationFrame(function () { + _this._animateScroll(destination, direction); + }); + }; + List.prototype._scrollDown = function (scrollPos, strength, destination) { + var easing = (destination - scrollPos) / strength; + var distance = easing > 1 ? easing : 1; + this.element.scrollTop = scrollPos + distance; + }; + List.prototype._scrollUp = function (scrollPos, strength, destination) { + var easing = (scrollPos - destination) / strength; + var distance = easing > 1 ? easing : 1; + this.element.scrollTop = scrollPos - distance; + }; + List.prototype._animateScroll = function (destination, direction) { + var _this = this; + var strength = SCROLLING_SPEED; + var choiceListScrollTop = this.element.scrollTop; + var continueAnimation = false; + if (direction > 0) { + this._scrollDown(choiceListScrollTop, strength, destination); + if (choiceListScrollTop < destination) { + continueAnimation = true; + } + } + else { + this._scrollUp(choiceListScrollTop, strength, destination); + if (choiceListScrollTop > destination) { + continueAnimation = true; + } + } + if (continueAnimation) { + requestAnimationFrame(function () { + _this._animateScroll(destination, direction); + }); + } + }; + return List; +}()); + +var WrappedElement = /** @class */ (function () { + function WrappedElement(_a) { + var element = _a.element, classNames = _a.classNames; + this.element = element; + this.classNames = classNames; + this.isDisabled = false; + } + Object.defineProperty(WrappedElement.prototype, "isActive", { + get: function () { + return this.element.dataset.choice === 'active'; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(WrappedElement.prototype, "dir", { + get: function () { + return this.element.dir; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(WrappedElement.prototype, "value", { + get: function () { + return this.element.value; + }, + set: function (value) { + this.element.setAttribute('value', value); + this.element.value = value; + }, + enumerable: false, + configurable: true + }); + WrappedElement.prototype.conceal = function () { + var _a; + var el = this.element; + // Hide passed input + (_a = el.classList).add.apply(_a, getClassNames(this.classNames.input)); + el.hidden = true; + // Remove element from tab index + el.tabIndex = -1; + // Backup original styles if any + var origStyle = el.getAttribute('style'); + if (origStyle) { + el.setAttribute('data-choice-orig-style', origStyle); + } + el.setAttribute('data-choice', 'active'); + }; + WrappedElement.prototype.reveal = function () { + var _a; + var el = this.element; + // Reinstate passed element + (_a = el.classList).remove.apply(_a, getClassNames(this.classNames.input)); + el.hidden = false; + el.removeAttribute('tabindex'); + // Recover original styles if any + var origStyle = el.getAttribute('data-choice-orig-style'); + if (origStyle) { + el.removeAttribute('data-choice-orig-style'); + el.setAttribute('style', origStyle); + } + else { + el.removeAttribute('style'); + } + el.removeAttribute('data-choice'); + }; + WrappedElement.prototype.enable = function () { + var element = this.element; + element.removeAttribute('disabled'); + element.disabled = false; + this.isDisabled = false; + }; + WrappedElement.prototype.disable = function () { + var element = this.element; + element.setAttribute('disabled', ''); + element.disabled = true; + this.isDisabled = true; + }; + WrappedElement.prototype.triggerEvent = function (eventType, data) { + dispatchEvent(this.element, eventType, data || {}); + }; + return WrappedElement; +}()); + +var WrappedInput = /** @class */ (function (_super) { + __extends(WrappedInput, _super); + function WrappedInput() { + return _super !== null && _super.apply(this, arguments) || this; + } + return WrappedInput; +}(WrappedElement)); + +var coerceBool = function (arg, defaultValue) { + if (defaultValue === void 0) { defaultValue = true; } + return typeof arg === 'undefined' ? defaultValue : !!arg; +}; +var stringToHtmlClass = function (input) { + if (typeof input === 'string') { + // eslint-disable-next-line no-param-reassign + input = input.split(' ').filter(function (s) { return s.length; }); + } + if (Array.isArray(input) && input.length) { + return input; + } + return undefined; +}; +var mapInputToChoice = function (value, allowGroup) { + if (typeof value === 'string') { + var result_1 = mapInputToChoice({ + value: value, + label: value, + }, false); + return result_1; + } + var groupOrChoice = value; + if ('choices' in groupOrChoice) { + if (!allowGroup) { + // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup + throw new TypeError("optGroup is not allowed"); + } + var group = groupOrChoice; + var choices = group.choices.map(function (e) { return mapInputToChoice(e, false); }); + var result_2 = { + id: 0, // actual ID will be assigned during _addGroup + label: unwrapStringForRaw(group.label) || group.value, + active: !!choices.length, + disabled: !!group.disabled, + choices: choices, + }; + return result_2; + } + var choice = groupOrChoice; + var result = { + id: 0, // actual ID will be assigned during _addChoice + groupId: 0, // actual ID will be assigned during _addGroup but before _addChoice + score: 0, // used in search + rank: 0, // used in search, stable sort order + value: choice.value, + label: choice.label || choice.value, + active: coerceBool(choice.active), + selected: coerceBool(choice.selected, false), + disabled: coerceBool(choice.disabled, false), + placeholder: coerceBool(choice.placeholder, false), + highlighted: false, + labelClass: stringToHtmlClass(choice.labelClass), + labelDescription: choice.labelDescription, + customProperties: choice.customProperties, + }; + return result; +}; + +var isHtmlInputElement = function (e) { return e.tagName === 'INPUT'; }; +var isHtmlSelectElement = function (e) { return e.tagName === 'SELECT'; }; +var isHtmlOption = function (e) { return e.tagName === 'OPTION'; }; +var isHtmlOptgroup = function (e) { return e.tagName === 'OPTGROUP'; }; + +var WrappedSelect = /** @class */ (function (_super) { + __extends(WrappedSelect, _super); + function WrappedSelect(_a) { + var element = _a.element, classNames = _a.classNames, template = _a.template, extractPlaceholder = _a.extractPlaceholder; + var _this = _super.call(this, { element: element, classNames: classNames }) || this; + _this.template = template; + _this.extractPlaceholder = extractPlaceholder; + return _this; + } + Object.defineProperty(WrappedSelect.prototype, "placeholderOption", { + get: function () { + return (this.element.querySelector('option[value=""]') || + // Backward compatibility layer for the non-standard placeholder attribute supported in older versions. + this.element.querySelector('option[placeholder]')); + }, + enumerable: false, + configurable: true + }); + WrappedSelect.prototype.addOptions = function (choices) { + var _this = this; + var fragment = document.createDocumentFragment(); + choices.forEach(function (obj) { + var choice = obj; + if (choice.element) { + return; + } + var option = _this.template(choice); + fragment.appendChild(option); + choice.element = option; + }); + this.element.appendChild(fragment); + }; + WrappedSelect.prototype.optionsAsChoices = function () { + var _this = this; + var choices = []; + this.element.querySelectorAll(':scope > option, :scope > optgroup').forEach(function (e) { + if (isHtmlOption(e)) { + choices.push(_this._optionToChoice(e)); + } + else if (isHtmlOptgroup(e)) { + choices.push(_this._optgroupToChoice(e)); + } + // todo: hr as empty optgroup, requires displaying empty opt-groups to be useful + }); + return choices; + }; + // eslint-disable-next-line class-methods-use-this + WrappedSelect.prototype._optionToChoice = function (option) { + // option.value returns the label if there is no value attribute, which can break legacy placeholder attribute support + if (!option.hasAttribute('value') && option.hasAttribute('placeholder')) { + option.setAttribute('value', ''); + option.value = ''; + } + var dataset = option.dataset; + return { + id: 0, + groupId: 0, + score: 0, + rank: 0, + value: option.value, + label: option.innerHTML, + element: option, + active: true, + // this returns true if nothing is selected on initial load, which will break placeholder support + selected: this.extractPlaceholder ? option.selected : option.hasAttribute('selected'), + disabled: option.disabled, + highlighted: false, + placeholder: this.extractPlaceholder && (!option.value || option.hasAttribute('placeholder')), + labelClass: typeof dataset.labelClass !== 'undefined' ? stringToHtmlClass(dataset.labelClass) : undefined, + labelDescription: typeof dataset.labelDescription !== 'undefined' ? dataset.labelDescription : undefined, + customProperties: parseCustomProperties(dataset.customProperties), + }; + }; + WrappedSelect.prototype._optgroupToChoice = function (optgroup) { + var _this = this; + var options = optgroup.querySelectorAll('option'); + var choices = Array.from(options).map(function (option) { return _this._optionToChoice(option); }); + return { + id: 0, + label: optgroup.label || '', + element: optgroup, + active: !!choices.length, + disabled: optgroup.disabled, + choices: choices, + }; + }; + return WrappedSelect; +}(WrappedElement)); + +var DEFAULT_CLASSNAMES = { + containerOuter: ['choices'], + containerInner: ['choices__inner'], + input: ['choices__input'], + inputCloned: ['choices__input--cloned'], + list: ['choices__list'], + listItems: ['choices__list--multiple'], + listSingle: ['choices__list--single'], + listDropdown: ['choices__list--dropdown'], + item: ['choices__item'], + itemSelectable: ['choices__item--selectable'], + itemDisabled: ['choices__item--disabled'], + itemChoice: ['choices__item--choice'], + description: ['choices__description'], + placeholder: ['choices__placeholder'], + group: ['choices__group'], + groupHeading: ['choices__heading'], + button: ['choices__button'], + activeState: ['is-active'], + focusState: ['is-focused'], + openState: ['is-open'], + disabledState: ['is-disabled'], + highlightedState: ['is-highlighted'], + selectedState: ['is-selected'], + flippedState: ['is-flipped'], + loadingState: ['is-loading'], + notice: ['choices__notice'], + addChoice: ['choices__item--selectable', 'add-choice'], + noResults: ['has-no-results'], + noChoices: ['has-no-choices'], +}; +var DEFAULT_CONFIG = { + items: [], + choices: [], + silent: false, + renderChoiceLimit: -1, + maxItemCount: -1, + closeDropdownOnSelect: 'auto', + singleModeForMultiSelect: false, + addChoices: false, + addItems: true, + addItemFilter: function (value) { return !!value && value !== ''; }, + removeItems: true, + removeItemButton: false, + removeItemButtonAlignLeft: false, + editItems: false, + allowHTML: false, + allowHtmlUserInput: false, + duplicateItemsAllowed: true, + delimiter: ',', + paste: true, + searchEnabled: true, + searchChoices: true, + searchFloor: 1, + searchResultLimit: 4, + searchFields: ['label', 'value'], + position: 'auto', + resetScrollPosition: true, + shouldSort: true, + shouldSortItems: false, + sorter: sortByAlpha, + shadowRoot: null, + placeholder: true, + placeholderValue: null, + searchPlaceholderValue: null, + prependValue: null, + appendValue: null, + renderSelectedChoices: 'auto', + loadingText: 'Loading...', + noResultsText: 'No results found', + noChoicesText: 'No choices to choose from', + itemSelectText: 'Press to select', + uniqueItemText: 'Only unique values can be added', + customAddItemText: 'Only values matching specific conditions can be added', + addItemText: function (value) { return "Press Enter to add \"".concat(value, "\""); }, + removeItemIconText: function () { return "Remove item"; }, + removeItemLabelText: function (value) { return "Remove item: ".concat(value); }, + maxItemText: function (maxItemCount) { return "Only ".concat(maxItemCount, " values can be added"); }, + valueComparer: function (value1, value2) { return value1 === value2; }, + fuseOptions: { + includeScore: true, + }, + labelId: '', + callbackOnInit: null, + callbackOnCreateTemplates: null, + classNames: DEFAULT_CLASSNAMES, + appendGroupInSearch: false, +}; + +function items(s, action) { + var state = s; + var update = true; + switch (action.type) { + case ActionType.ADD_ITEM: { + var item = action.item; + item.selected = true; + var el = item.element; + if (el) { + el.selected = true; + el.setAttribute('selected', ''); + } + state.push(item); + state.forEach(function (choice) { + choice.highlighted = false; + }); + break; + } + case ActionType.REMOVE_ITEM: { + var item_1 = action.item; + item_1.selected = false; + var el = item_1.element; + if (el) { + el.selected = false; + el.removeAttribute('selected'); + // For a select-one, if all options are deselected, the first item is selected. To set a black value, select.value needs to be set + var select = el.parentElement; + if (select && isHtmlSelectElement(select) && select.type === SELECT_ONE_TYPE) { + select.value = ''; + } + } + state = state.filter(function (choice) { return choice.id !== item_1.id; }); + break; + } + case ActionType.REMOVE_CHOICE: { + state = state.filter(function (item) { return item.id !== action.choice.id; }); + break; + } + case ActionType.HIGHLIGHT_ITEM: { + var highlightItemAction_1 = action; + state.forEach(function (choice) { + if (choice.id === highlightItemAction_1.item.id) { + choice.highlighted = highlightItemAction_1.highlighted; + } + }); + break; + } + default: { + update = false; + break; + } + } + return { state: state, update: update }; +} + +function groups(s, action) { + var state = s; + var update = true; + switch (action.type) { + case ActionType.ADD_GROUP: { + state.push(action.group); + break; + } + case ActionType.CLEAR_CHOICES: { + state = []; + break; + } + default: { + update = false; + break; + } + } + return { state: state, update: update }; +} + +/* eslint-disable */ +function choices(s, action) { + var state = s; + var update = true; + switch (action.type) { + case ActionType.ADD_CHOICE: { + /* + A disabled choice appears in the choice dropdown but cannot be selected + A selected choice has been added to the passed input's value (added as an item) + An active choice appears within the choice dropdown + */ + state.push(action.choice); + break; + } + case ActionType.REMOVE_CHOICE: { + state = state.filter(function (obj) { return obj.id !== action.choice.id; }); + break; + } + case ActionType.ADD_ITEM: + case ActionType.REMOVE_ITEM: { + break; + } + case ActionType.FILTER_CHOICES: { + // avoid O(n^2) algorithm complexity when searching/filtering choices + var scoreLookup_1 = []; + action.results.forEach(function (result) { + scoreLookup_1[result.item.id] = result; + }); + state.forEach(function (choice) { + var result = scoreLookup_1[choice.id]; + if (result !== undefined) { + choice.score = result.score; + choice.rank = result.rank; + choice.active = true; + } + else { + choice.score = 0; + choice.rank = 0; + choice.active = false; + } + }); + break; + } + case ActionType.ACTIVATE_CHOICES: { + state.forEach(function (choice) { + choice.active = action.active; + }); + break; + } + case ActionType.CLEAR_CHOICES: { + state = []; + break; + } + default: { + update = false; + break; + } + } + return { state: state, update: update }; +} + +var reducers = { + groups: groups, + items: items, + choices: choices, +}; +var Store = /** @class */ (function () { + function Store() { + this._state = this.defaultState; + this._listeners = []; + this._txn = 0; + } + Object.defineProperty(Store.prototype, "defaultState", { + // eslint-disable-next-line class-methods-use-this + get: function () { + return { + groups: [], + items: [], + choices: [], + }; + }, + enumerable: false, + configurable: true + }); + // eslint-disable-next-line class-methods-use-this + Store.prototype.changeSet = function (init) { + return { + groups: init, + items: init, + choices: init, + }; + }; + Store.prototype.reset = function () { + this._state = this.defaultState; + var changes = this.changeSet(true); + if (this._txn) { + this._changeSet = changes; + } + else { + this._listeners.forEach(function (l) { return l(changes); }); + } + }; + Store.prototype.subscribe = function (onChange) { + this._listeners.push(onChange); + }; + Store.prototype.dispatch = function (action) { + var state = this._state; + var hasChanges = false; + var changes = this._changeSet || this.changeSet(false); + Object.keys(reducers).forEach(function (key) { + var stateUpdate = reducers[key](state[key], action); + if (stateUpdate.update) { + hasChanges = true; + changes[key] = true; + state[key] = stateUpdate.state; + } + }); + if (hasChanges) { + if (this._txn) { + this._changeSet = changes; + } + else { + this._listeners.forEach(function (l) { return l(changes); }); + } + } + }; + Store.prototype.withTxn = function (func) { + this._txn++; + try { + func(); + } + finally { + this._txn = Math.max(0, this._txn - 1); + if (!this._txn) { + var changeSet_1 = this._changeSet; + if (changeSet_1) { + this._changeSet = undefined; + this._listeners.forEach(function (l) { return l(changeSet_1); }); + } + } + } + }; + Object.defineProperty(Store.prototype, "state", { + /** + * Get store object + */ + get: function () { + return this._state; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "items", { + /** + * Get items from store + */ + get: function () { + return this.state.items; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "highlightedActiveItems", { + /** + * Get highlighted items from store + */ + get: function () { + return this.items.filter(function (item) { return !item.disabled && item.active && item.highlighted; }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "choices", { + /** + * Get choices from store + */ + get: function () { + return this.state.choices; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "activeChoices", { + /** + * Get active choices from store + */ + get: function () { + return this.choices.filter(function (choice) { return choice.active; }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "searchableChoices", { + /** + * Get choices that can be searched (excluding placeholders) + */ + get: function () { + return this.choices.filter(function (choice) { return !choice.disabled && !choice.placeholder; }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "groups", { + /** + * Get groups from store + */ + get: function () { + return this.state.groups; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "activeGroups", { + /** + * Get active groups from store + */ + get: function () { + var _this = this; + return this.state.groups.filter(function (group) { + var isActive = group.active && !group.disabled; + var hasActiveOptions = _this.state.choices.some(function (choice) { return choice.active && !choice.disabled; }); + return isActive && hasActiveOptions; + }, []); + }, + enumerable: false, + configurable: true + }); + Store.prototype.inTxn = function () { + return this._txn > 0; + }; + /** + * Get single choice by it's ID + */ + Store.prototype.getChoiceById = function (id) { + return this.activeChoices.find(function (choice) { return choice.id === id; }); + }; + /** + * Get group by group id + */ + Store.prototype.getGroupById = function (id) { + return this.groups.find(function (group) { return group.id === id; }); + }; + return Store; +}()); + +var NoticeTypes = { + noChoices: 'no-choices', + noResults: 'no-results', + addChoice: 'add-choice', + generic: '', +}; + +function _defineProperty(e, r, t) { + return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { + value: t, + enumerable: !0, + configurable: !0, + writable: !0 + }) : e[r] = t, e; +} +function ownKeys(e, r) { + var t = Object.keys(e); + if (Object.getOwnPropertySymbols) { + var o = Object.getOwnPropertySymbols(e); + r && (o = o.filter(function (r) { + return Object.getOwnPropertyDescriptor(e, r).enumerable; + })), t.push.apply(t, o); + } + return t; +} +function _objectSpread2(e) { + for (var r = 1; r < arguments.length; r++) { + var t = null != arguments[r] ? arguments[r] : {}; + r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { + _defineProperty(e, r, t[r]); + }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { + Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); + }); + } + return e; +} +function _toPrimitive(t, r) { + if ("object" != typeof t || !t) return t; + var e = t[Symbol.toPrimitive]; + if (void 0 !== e) { + var i = e.call(t, r || "default"); + if ("object" != typeof i) return i; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return ("string" === r ? String : Number)(t); +} +function _toPropertyKey(t) { + var i = _toPrimitive(t, "string"); + return "symbol" == typeof i ? i : i + ""; +} + +/** + * Fuse.js v7.0.0 - Lightweight fuzzy-search (http://fusejs.io) + * + * Copyright (c) 2023 Kiro Risk (http://kiro.me) + * All Rights Reserved. Apache Software License 2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +function isArray(value) { + return !Array.isArray ? getTag(value) === '[object Array]' : Array.isArray(value); +} + +// Adapted from: https://github.com/lodash/lodash/blob/master/.internal/baseToString.js +const INFINITY = 1 / 0; +function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + let result = value + ''; + return result == '0' && 1 / value == -INFINITY ? '-0' : result; +} +function toString(value) { + return value == null ? '' : baseToString(value); +} +function isString(value) { + return typeof value === 'string'; +} +function isNumber(value) { + return typeof value === 'number'; +} + +// Adapted from: https://github.com/lodash/lodash/blob/master/isBoolean.js +function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && getTag(value) == '[object Boolean]'; +} +function isObject(value) { + return typeof value === 'object'; +} + +// Checks if `value` is object-like. +function isObjectLike(value) { + return isObject(value) && value !== null; +} +function isDefined(value) { + return value !== undefined && value !== null; +} +function isBlank(value) { + return !value.trim().length; +} + +// Gets the `toStringTag` of `value`. +// Adapted from: https://github.com/lodash/lodash/blob/master/.internal/getTag.js +function getTag(value) { + return value == null ? value === undefined ? '[object Undefined]' : '[object Null]' : Object.prototype.toString.call(value); +} +const EXTENDED_SEARCH_UNAVAILABLE = 'Extended search is not available'; +const INCORRECT_INDEX_TYPE = "Incorrect 'index' type"; +const LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY = key => `Invalid value for key ${key}`; +const PATTERN_LENGTH_TOO_LARGE = max => `Pattern length exceeds max of ${max}.`; +const MISSING_KEY_PROPERTY = name => `Missing ${name} property in key`; +const INVALID_KEY_WEIGHT_VALUE = key => `Property 'weight' in key '${key}' must be a positive integer`; +const hasOwn = Object.prototype.hasOwnProperty; +class KeyStore { + constructor(keys) { + this._keys = []; + this._keyMap = {}; + let totalWeight = 0; + keys.forEach(key => { + let obj = createKey(key); + this._keys.push(obj); + this._keyMap[obj.id] = obj; + totalWeight += obj.weight; + }); + + // Normalize weights so that their sum is equal to 1 + this._keys.forEach(key => { + key.weight /= totalWeight; + }); + } + get(keyId) { + return this._keyMap[keyId]; + } + keys() { + return this._keys; + } + toJSON() { + return JSON.stringify(this._keys); + } +} +function createKey(key) { + let path = null; + let id = null; + let src = null; + let weight = 1; + let getFn = null; + if (isString(key) || isArray(key)) { + src = key; + path = createKeyPath(key); + id = createKeyId(key); + } else { + if (!hasOwn.call(key, 'name')) { + throw new Error(MISSING_KEY_PROPERTY('name')); + } + const name = key.name; + src = name; + if (hasOwn.call(key, 'weight')) { + weight = key.weight; + if (weight <= 0) { + throw new Error(INVALID_KEY_WEIGHT_VALUE(name)); + } + } + path = createKeyPath(name); + id = createKeyId(name); + getFn = key.getFn; + } + return { + path, + id, + weight, + src, + getFn + }; +} +function createKeyPath(key) { + return isArray(key) ? key : key.split('.'); +} +function createKeyId(key) { + return isArray(key) ? key.join('.') : key; +} +function get(obj, path) { + let list = []; + let arr = false; + const deepGet = (obj, path, index) => { + if (!isDefined(obj)) { + return; + } + if (!path[index]) { + // If there's no path left, we've arrived at the object we care about. + list.push(obj); + } else { + let key = path[index]; + const value = obj[key]; + if (!isDefined(value)) { + return; + } + + // If we're at the last value in the path, and if it's a string/number/bool, + // add it to the list + if (index === path.length - 1 && (isString(value) || isNumber(value) || isBoolean(value))) { + list.push(toString(value)); + } else if (isArray(value)) { + arr = true; + // Search each item in the array. + for (let i = 0, len = value.length; i < len; i += 1) { + deepGet(value[i], path, index + 1); + } + } else if (path.length) { + // An object. Recurse further. + deepGet(value, path, index + 1); + } + } + }; + + // Backwards compatibility (since path used to be a string) + deepGet(obj, isString(path) ? path.split('.') : path, 0); + return arr ? list : list[0]; +} +const MatchOptions = { + // Whether the matches should be included in the result set. When `true`, each record in the result + // set will include the indices of the matched characters. + // These can consequently be used for highlighting purposes. + includeMatches: false, + // When `true`, the matching function will continue to the end of a search pattern even if + // a perfect match has already been located in the string. + findAllMatches: false, + // Minimum number of characters that must be matched before a result is considered a match + minMatchCharLength: 1 +}; +const BasicOptions = { + // When `true`, the algorithm continues searching to the end of the input even if a perfect + // match is found before the end of the same input. + isCaseSensitive: false, + // When true, the matching function will continue to the end of a search pattern even if + includeScore: false, + // List of properties that will be searched. This also supports nested properties. + keys: [], + // Whether to sort the result list, by score + shouldSort: true, + // Default sort function: sort by ascending score, ascending index + sortFn: (a, b) => a.score === b.score ? a.idx < b.idx ? -1 : 1 : a.score < b.score ? -1 : 1 +}; +const FuzzyOptions = { + // Approximately where in the text is the pattern expected to be found? + location: 0, + // At what point does the match algorithm give up. A threshold of '0.0' requires a perfect match + // (of both letters and location), a threshold of '1.0' would match anything. + threshold: 0.6, + // Determines how close the match must be to the fuzzy location (specified above). + // An exact letter match which is 'distance' characters away from the fuzzy location + // would score as a complete mismatch. A distance of '0' requires the match be at + // the exact location specified, a threshold of '1000' would require a perfect match + // to be within 800 characters of the fuzzy location to be found using a 0.8 threshold. + distance: 100 +}; +const AdvancedOptions = { + // When `true`, it enables the use of unix-like search commands + useExtendedSearch: false, + // The get function to use when fetching an object's properties. + // The default will search nested paths *ie foo.bar.baz* + getFn: get, + // When `true`, search will ignore `location` and `distance`, so it won't matter + // where in the string the pattern appears. + // More info: https://fusejs.io/concepts/scoring-theory.html#fuzziness-score + ignoreLocation: false, + // When `true`, the calculation for the relevance score (used for sorting) will + // ignore the field-length norm. + // More info: https://fusejs.io/concepts/scoring-theory.html#field-length-norm + ignoreFieldNorm: false, + // The weight to determine how much field length norm effects scoring. + fieldNormWeight: 1 +}; +var Config = _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, BasicOptions), MatchOptions), FuzzyOptions), AdvancedOptions); +const SPACE = /[^ ]+/g; + +// Field-length norm: the shorter the field, the higher the weight. +// Set to 3 decimals to reduce index size. +function norm(weight = 1, mantissa = 3) { + const cache = new Map(); + const m = Math.pow(10, mantissa); + return { + get(value) { + const numTokens = value.match(SPACE).length; + if (cache.has(numTokens)) { + return cache.get(numTokens); + } + + // Default function is 1/sqrt(x), weight makes that variable + const norm = 1 / Math.pow(numTokens, 0.5 * weight); + + // In place of `toFixed(mantissa)`, for faster computation + const n = parseFloat(Math.round(norm * m) / m); + cache.set(numTokens, n); + return n; + }, + clear() { + cache.clear(); + } + }; +} +class FuseIndex { + constructor({ + getFn = Config.getFn, + fieldNormWeight = Config.fieldNormWeight + } = {}) { + this.norm = norm(fieldNormWeight, 3); + this.getFn = getFn; + this.isCreated = false; + this.setIndexRecords(); + } + setSources(docs = []) { + this.docs = docs; + } + setIndexRecords(records = []) { + this.records = records; + } + setKeys(keys = []) { + this.keys = keys; + this._keysMap = {}; + keys.forEach((key, idx) => { + this._keysMap[key.id] = idx; + }); + } + create() { + if (this.isCreated || !this.docs.length) { + return; + } + this.isCreated = true; + + // List is Array + if (isString(this.docs[0])) { + this.docs.forEach((doc, docIndex) => { + this._addString(doc, docIndex); + }); + } else { + // List is Array + this.docs.forEach((doc, docIndex) => { + this._addObject(doc, docIndex); + }); + } + this.norm.clear(); + } + // Adds a doc to the end of the index + add(doc) { + const idx = this.size(); + if (isString(doc)) { + this._addString(doc, idx); + } else { + this._addObject(doc, idx); + } + } + // Removes the doc at the specified index of the index + removeAt(idx) { + this.records.splice(idx, 1); + + // Change ref index of every subsquent doc + for (let i = idx, len = this.size(); i < len; i += 1) { + this.records[i].i -= 1; + } + } + getValueForItemAtKeyId(item, keyId) { + return item[this._keysMap[keyId]]; + } + size() { + return this.records.length; + } + _addString(doc, docIndex) { + if (!isDefined(doc) || isBlank(doc)) { + return; + } + let record = { + v: doc, + i: docIndex, + n: this.norm.get(doc) + }; + this.records.push(record); + } + _addObject(doc, docIndex) { + let record = { + i: docIndex, + $: {} + }; + + // Iterate over every key (i.e, path), and fetch the value at that key + this.keys.forEach((key, keyIndex) => { + let value = key.getFn ? key.getFn(doc) : this.getFn(doc, key.path); + if (!isDefined(value)) { + return; + } + if (isArray(value)) { + let subRecords = []; + const stack = [{ + nestedArrIndex: -1, + value + }]; + while (stack.length) { + const { + nestedArrIndex, + value + } = stack.pop(); + if (!isDefined(value)) { + continue; + } + if (isString(value) && !isBlank(value)) { + let subRecord = { + v: value, + i: nestedArrIndex, + n: this.norm.get(value) + }; + subRecords.push(subRecord); + } else if (isArray(value)) { + value.forEach((item, k) => { + stack.push({ + nestedArrIndex: k, + value: item + }); + }); + } else ; + } + record.$[keyIndex] = subRecords; + } else if (isString(value) && !isBlank(value)) { + let subRecord = { + v: value, + n: this.norm.get(value) + }; + record.$[keyIndex] = subRecord; + } + }); + this.records.push(record); + } + toJSON() { + return { + keys: this.keys, + records: this.records + }; + } +} +function createIndex(keys, docs, { + getFn = Config.getFn, + fieldNormWeight = Config.fieldNormWeight +} = {}) { + const myIndex = new FuseIndex({ + getFn, + fieldNormWeight + }); + myIndex.setKeys(keys.map(createKey)); + myIndex.setSources(docs); + myIndex.create(); + return myIndex; +} +function parseIndex(data, { + getFn = Config.getFn, + fieldNormWeight = Config.fieldNormWeight +} = {}) { + const { + keys, + records + } = data; + const myIndex = new FuseIndex({ + getFn, + fieldNormWeight + }); + myIndex.setKeys(keys); + myIndex.setIndexRecords(records); + return myIndex; +} +function computeScore$1(pattern, { + errors = 0, + currentLocation = 0, + expectedLocation = 0, + distance = Config.distance, + ignoreLocation = Config.ignoreLocation +} = {}) { + const accuracy = errors / pattern.length; + if (ignoreLocation) { + return accuracy; + } + const proximity = Math.abs(expectedLocation - currentLocation); + if (!distance) { + // Dodge divide by zero error. + return proximity ? 1.0 : accuracy; + } + return accuracy + proximity / distance; +} +function convertMaskToIndices(matchmask = [], minMatchCharLength = Config.minMatchCharLength) { + let indices = []; + let start = -1; + let end = -1; + let i = 0; + for (let len = matchmask.length; i < len; i += 1) { + let match = matchmask[i]; + if (match && start === -1) { + start = i; + } else if (!match && start !== -1) { + end = i - 1; + if (end - start + 1 >= minMatchCharLength) { + indices.push([start, end]); + } + start = -1; + } + } + + // (i-1 - start) + 1 => i - start + if (matchmask[i - 1] && i - start >= minMatchCharLength) { + indices.push([start, i - 1]); + } + return indices; +} + +// Machine word size +const MAX_BITS = 32; +function search(text, pattern, patternAlphabet, { + location = Config.location, + distance = Config.distance, + threshold = Config.threshold, + findAllMatches = Config.findAllMatches, + minMatchCharLength = Config.minMatchCharLength, + includeMatches = Config.includeMatches, + ignoreLocation = Config.ignoreLocation +} = {}) { + if (pattern.length > MAX_BITS) { + throw new Error(PATTERN_LENGTH_TOO_LARGE(MAX_BITS)); + } + const patternLen = pattern.length; + // Set starting location at beginning text and initialize the alphabet. + const textLen = text.length; + // Handle the case when location > text.length + const expectedLocation = Math.max(0, Math.min(location, textLen)); + // Highest score beyond which we give up. + let currentThreshold = threshold; + // Is there a nearby exact match? (speedup) + let bestLocation = expectedLocation; + + // Performance: only computer matches when the minMatchCharLength > 1 + // OR if `includeMatches` is true. + const computeMatches = minMatchCharLength > 1 || includeMatches; + // A mask of the matches, used for building the indices + const matchMask = computeMatches ? Array(textLen) : []; + let index; + + // Get all exact matches, here for speed up + while ((index = text.indexOf(pattern, bestLocation)) > -1) { + let score = computeScore$1(pattern, { + currentLocation: index, + expectedLocation, + distance, + ignoreLocation + }); + currentThreshold = Math.min(score, currentThreshold); + bestLocation = index + patternLen; + if (computeMatches) { + let i = 0; + while (i < patternLen) { + matchMask[index + i] = 1; + i += 1; + } + } + } + + // Reset the best location + bestLocation = -1; + let lastBitArr = []; + let finalScore = 1; + let binMax = patternLen + textLen; + const mask = 1 << patternLen - 1; + for (let i = 0; i < patternLen; i += 1) { + // Scan for the best match; each iteration allows for one more error. + // Run a binary search to determine how far from the match location we can stray + // at this error level. + let binMin = 0; + let binMid = binMax; + while (binMin < binMid) { + const score = computeScore$1(pattern, { + errors: i, + currentLocation: expectedLocation + binMid, + expectedLocation, + distance, + ignoreLocation + }); + if (score <= currentThreshold) { + binMin = binMid; + } else { + binMax = binMid; + } + binMid = Math.floor((binMax - binMin) / 2 + binMin); + } + + // Use the result from this iteration as the maximum for the next. + binMax = binMid; + let start = Math.max(1, expectedLocation - binMid + 1); + let finish = findAllMatches ? textLen : Math.min(expectedLocation + binMid, textLen) + patternLen; + + // Initialize the bit array + let bitArr = Array(finish + 2); + bitArr[finish + 1] = (1 << i) - 1; + for (let j = finish; j >= start; j -= 1) { + let currentLocation = j - 1; + let charMatch = patternAlphabet[text.charAt(currentLocation)]; + if (computeMatches) { + // Speed up: quick bool to int conversion (i.e, `charMatch ? 1 : 0`) + matchMask[currentLocation] = +!!charMatch; + } + + // First pass: exact match + bitArr[j] = (bitArr[j + 1] << 1 | 1) & charMatch; + + // Subsequent passes: fuzzy match + if (i) { + bitArr[j] |= (lastBitArr[j + 1] | lastBitArr[j]) << 1 | 1 | lastBitArr[j + 1]; + } + if (bitArr[j] & mask) { + finalScore = computeScore$1(pattern, { + errors: i, + currentLocation, + expectedLocation, + distance, + ignoreLocation + }); + + // This match will almost certainly be better than any existing match. + // But check anyway. + if (finalScore <= currentThreshold) { + // Indeed it is + currentThreshold = finalScore; + bestLocation = currentLocation; + + // Already passed `loc`, downhill from here on in. + if (bestLocation <= expectedLocation) { + break; + } + + // When passing `bestLocation`, don't exceed our current distance from `expectedLocation`. + start = Math.max(1, 2 * expectedLocation - bestLocation); + } + } + } + + // No hope for a (better) match at greater error levels. + const score = computeScore$1(pattern, { + errors: i + 1, + currentLocation: expectedLocation, + expectedLocation, + distance, + ignoreLocation + }); + if (score > currentThreshold) { + break; + } + lastBitArr = bitArr; + } + const result = { + isMatch: bestLocation >= 0, + // Count exact matches (those with a score of 0) to be "almost" exact + score: Math.max(0.001, finalScore) + }; + if (computeMatches) { + const indices = convertMaskToIndices(matchMask, minMatchCharLength); + if (!indices.length) { + result.isMatch = false; + } else if (includeMatches) { + result.indices = indices; + } + } + return result; +} +function createPatternAlphabet(pattern) { + let mask = {}; + for (let i = 0, len = pattern.length; i < len; i += 1) { + const char = pattern.charAt(i); + mask[char] = (mask[char] || 0) | 1 << len - i - 1; + } + return mask; +} +class BitapSearch { + constructor(pattern, { + location = Config.location, + threshold = Config.threshold, + distance = Config.distance, + includeMatches = Config.includeMatches, + findAllMatches = Config.findAllMatches, + minMatchCharLength = Config.minMatchCharLength, + isCaseSensitive = Config.isCaseSensitive, + ignoreLocation = Config.ignoreLocation + } = {}) { + this.options = { + location, + threshold, + distance, + includeMatches, + findAllMatches, + minMatchCharLength, + isCaseSensitive, + ignoreLocation + }; + this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase(); + this.chunks = []; + if (!this.pattern.length) { + return; + } + const addChunk = (pattern, startIndex) => { + this.chunks.push({ + pattern, + alphabet: createPatternAlphabet(pattern), + startIndex + }); + }; + const len = this.pattern.length; + if (len > MAX_BITS) { + let i = 0; + const remainder = len % MAX_BITS; + const end = len - remainder; + while (i < end) { + addChunk(this.pattern.substr(i, MAX_BITS), i); + i += MAX_BITS; + } + if (remainder) { + const startIndex = len - MAX_BITS; + addChunk(this.pattern.substr(startIndex), startIndex); + } + } else { + addChunk(this.pattern, 0); + } + } + searchIn(text) { + const { + isCaseSensitive, + includeMatches + } = this.options; + if (!isCaseSensitive) { + text = text.toLowerCase(); + } + + // Exact match + if (this.pattern === text) { + let result = { + isMatch: true, + score: 0 + }; + if (includeMatches) { + result.indices = [[0, text.length - 1]]; + } + return result; + } + + // Otherwise, use Bitap algorithm + const { + location, + distance, + threshold, + findAllMatches, + minMatchCharLength, + ignoreLocation + } = this.options; + let allIndices = []; + let totalScore = 0; + let hasMatches = false; + this.chunks.forEach(({ + pattern, + alphabet, + startIndex + }) => { + const { + isMatch, + score, + indices + } = search(text, pattern, alphabet, { + location: location + startIndex, + distance, + threshold, + findAllMatches, + minMatchCharLength, + includeMatches, + ignoreLocation + }); + if (isMatch) { + hasMatches = true; + } + totalScore += score; + if (isMatch && indices) { + allIndices = [...allIndices, ...indices]; + } + }); + let result = { + isMatch: hasMatches, + score: hasMatches ? totalScore / this.chunks.length : 1 + }; + if (hasMatches && includeMatches) { + result.indices = allIndices; + } + return result; + } +} +class BaseMatch { + constructor(pattern) { + this.pattern = pattern; + } + static isMultiMatch(pattern) { + return getMatch(pattern, this.multiRegex); + } + static isSingleMatch(pattern) { + return getMatch(pattern, this.singleRegex); + } + search( /*text*/) {} +} +function getMatch(pattern, exp) { + const matches = pattern.match(exp); + return matches ? matches[1] : null; +} + +// Token: 'file + +class ExactMatch extends BaseMatch { + constructor(pattern) { + super(pattern); + } + static get type() { + return 'exact'; + } + static get multiRegex() { + return /^="(.*)"$/; + } + static get singleRegex() { + return /^=(.*)$/; + } + search(text) { + const isMatch = text === this.pattern; + return { + isMatch, + score: isMatch ? 0 : 1, + indices: [0, this.pattern.length - 1] + }; + } +} + +// Token: !fire + +class InverseExactMatch extends BaseMatch { + constructor(pattern) { + super(pattern); + } + static get type() { + return 'inverse-exact'; + } + static get multiRegex() { + return /^!"(.*)"$/; + } + static get singleRegex() { + return /^!(.*)$/; + } + search(text) { + const index = text.indexOf(this.pattern); + const isMatch = index === -1; + return { + isMatch, + score: isMatch ? 0 : 1, + indices: [0, text.length - 1] + }; + } +} + +// Token: ^file + +class PrefixExactMatch extends BaseMatch { + constructor(pattern) { + super(pattern); + } + static get type() { + return 'prefix-exact'; + } + static get multiRegex() { + return /^\^"(.*)"$/; + } + static get singleRegex() { + return /^\^(.*)$/; + } + search(text) { + const isMatch = text.startsWith(this.pattern); + return { + isMatch, + score: isMatch ? 0 : 1, + indices: [0, this.pattern.length - 1] + }; + } +} + +// Token: !^fire + +class InversePrefixExactMatch extends BaseMatch { + constructor(pattern) { + super(pattern); + } + static get type() { + return 'inverse-prefix-exact'; + } + static get multiRegex() { + return /^!\^"(.*)"$/; + } + static get singleRegex() { + return /^!\^(.*)$/; + } + search(text) { + const isMatch = !text.startsWith(this.pattern); + return { + isMatch, + score: isMatch ? 0 : 1, + indices: [0, text.length - 1] + }; + } +} + +// Token: .file$ + +class SuffixExactMatch extends BaseMatch { + constructor(pattern) { + super(pattern); + } + static get type() { + return 'suffix-exact'; + } + static get multiRegex() { + return /^"(.*)"\$$/; + } + static get singleRegex() { + return /^(.*)\$$/; + } + search(text) { + const isMatch = text.endsWith(this.pattern); + return { + isMatch, + score: isMatch ? 0 : 1, + indices: [text.length - this.pattern.length, text.length - 1] + }; + } +} + +// Token: !.file$ + +class InverseSuffixExactMatch extends BaseMatch { + constructor(pattern) { + super(pattern); + } + static get type() { + return 'inverse-suffix-exact'; + } + static get multiRegex() { + return /^!"(.*)"\$$/; + } + static get singleRegex() { + return /^!(.*)\$$/; + } + search(text) { + const isMatch = !text.endsWith(this.pattern); + return { + isMatch, + score: isMatch ? 0 : 1, + indices: [0, text.length - 1] + }; + } +} +class FuzzyMatch extends BaseMatch { + constructor(pattern, { + location = Config.location, + threshold = Config.threshold, + distance = Config.distance, + includeMatches = Config.includeMatches, + findAllMatches = Config.findAllMatches, + minMatchCharLength = Config.minMatchCharLength, + isCaseSensitive = Config.isCaseSensitive, + ignoreLocation = Config.ignoreLocation + } = {}) { + super(pattern); + this._bitapSearch = new BitapSearch(pattern, { + location, + threshold, + distance, + includeMatches, + findAllMatches, + minMatchCharLength, + isCaseSensitive, + ignoreLocation + }); + } + static get type() { + return 'fuzzy'; + } + static get multiRegex() { + return /^"(.*)"$/; + } + static get singleRegex() { + return /^(.*)$/; + } + search(text) { + return this._bitapSearch.searchIn(text); + } +} + +// Token: 'file + +class IncludeMatch extends BaseMatch { + constructor(pattern) { + super(pattern); + } + static get type() { + return 'include'; + } + static get multiRegex() { + return /^'"(.*)"$/; + } + static get singleRegex() { + return /^'(.*)$/; + } + search(text) { + let location = 0; + let index; + const indices = []; + const patternLen = this.pattern.length; + + // Get all exact matches + while ((index = text.indexOf(this.pattern, location)) > -1) { + location = index + patternLen; + indices.push([index, location - 1]); + } + const isMatch = !!indices.length; + return { + isMatch, + score: isMatch ? 0 : 1, + indices + }; + } +} + +// ❗Order is important. DO NOT CHANGE. +const searchers = [ExactMatch, IncludeMatch, PrefixExactMatch, InversePrefixExactMatch, InverseSuffixExactMatch, SuffixExactMatch, InverseExactMatch, FuzzyMatch]; +const searchersLen = searchers.length; + +// Regex to split by spaces, but keep anything in quotes together +const SPACE_RE = / +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/; +const OR_TOKEN = '|'; + +// Return a 2D array representation of the query, for simpler parsing. +// Example: +// "^core go$ | rb$ | py$ xy$" => [["^core", "go$"], ["rb$"], ["py$", "xy$"]] +function parseQuery(pattern, options = {}) { + return pattern.split(OR_TOKEN).map(item => { + let query = item.trim().split(SPACE_RE).filter(item => item && !!item.trim()); + let results = []; + for (let i = 0, len = query.length; i < len; i += 1) { + const queryItem = query[i]; + + // 1. Handle multiple query match (i.e, once that are quoted, like `"hello world"`) + let found = false; + let idx = -1; + while (!found && ++idx < searchersLen) { + const searcher = searchers[idx]; + let token = searcher.isMultiMatch(queryItem); + if (token) { + results.push(new searcher(token, options)); + found = true; + } + } + if (found) { + continue; + } + + // 2. Handle single query matches (i.e, once that are *not* quoted) + idx = -1; + while (++idx < searchersLen) { + const searcher = searchers[idx]; + let token = searcher.isSingleMatch(queryItem); + if (token) { + results.push(new searcher(token, options)); + break; + } + } + } + return results; + }); +} + +// These extended matchers can return an array of matches, as opposed +// to a singl match +const MultiMatchSet = new Set([FuzzyMatch.type, IncludeMatch.type]); + +/** + * Command-like searching + * ====================== + * + * Given multiple search terms delimited by spaces.e.g. `^jscript .python$ ruby !java`, + * search in a given text. + * + * Search syntax: + * + * | Token | Match type | Description | + * | ----------- | -------------------------- | -------------------------------------- | + * | `jscript` | fuzzy-match | Items that fuzzy match `jscript` | + * | `=scheme` | exact-match | Items that are `scheme` | + * | `'python` | include-match | Items that include `python` | + * | `!ruby` | inverse-exact-match | Items that do not include `ruby` | + * | `^java` | prefix-exact-match | Items that start with `java` | + * | `!^earlang` | inverse-prefix-exact-match | Items that do not start with `earlang` | + * | `.js$` | suffix-exact-match | Items that end with `.js` | + * | `!.go$` | inverse-suffix-exact-match | Items that do not end with `.go` | + * + * A single pipe character acts as an OR operator. For example, the following + * query matches entries that start with `core` and end with either`go`, `rb`, + * or`py`. + * + * ``` + * ^core go$ | rb$ | py$ + * ``` + */ +class ExtendedSearch { + constructor(pattern, { + isCaseSensitive = Config.isCaseSensitive, + includeMatches = Config.includeMatches, + minMatchCharLength = Config.minMatchCharLength, + ignoreLocation = Config.ignoreLocation, + findAllMatches = Config.findAllMatches, + location = Config.location, + threshold = Config.threshold, + distance = Config.distance + } = {}) { + this.query = null; + this.options = { + isCaseSensitive, + includeMatches, + minMatchCharLength, + findAllMatches, + ignoreLocation, + location, + threshold, + distance + }; + this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase(); + this.query = parseQuery(this.pattern, this.options); + } + static condition(_, options) { + return options.useExtendedSearch; + } + searchIn(text) { + const query = this.query; + if (!query) { + return { + isMatch: false, + score: 1 + }; + } + const { + includeMatches, + isCaseSensitive + } = this.options; + text = isCaseSensitive ? text : text.toLowerCase(); + let numMatches = 0; + let allIndices = []; + let totalScore = 0; + + // ORs + for (let i = 0, qLen = query.length; i < qLen; i += 1) { + const searchers = query[i]; + + // Reset indices + allIndices.length = 0; + numMatches = 0; + + // ANDs + for (let j = 0, pLen = searchers.length; j < pLen; j += 1) { + const searcher = searchers[j]; + const { + isMatch, + indices, + score + } = searcher.search(text); + if (isMatch) { + numMatches += 1; + totalScore += score; + if (includeMatches) { + const type = searcher.constructor.type; + if (MultiMatchSet.has(type)) { + allIndices = [...allIndices, ...indices]; + } else { + allIndices.push(indices); + } + } + } else { + totalScore = 0; + numMatches = 0; + allIndices.length = 0; + break; + } + } + + // OR condition, so if TRUE, return + if (numMatches) { + let result = { + isMatch: true, + score: totalScore / numMatches + }; + if (includeMatches) { + result.indices = allIndices; + } + return result; + } + } + + // Nothing was matched + return { + isMatch: false, + score: 1 + }; + } +} +const registeredSearchers = []; +function register(...args) { + registeredSearchers.push(...args); +} +function createSearcher(pattern, options) { + for (let i = 0, len = registeredSearchers.length; i < len; i += 1) { + let searcherClass = registeredSearchers[i]; + if (searcherClass.condition(pattern, options)) { + return new searcherClass(pattern, options); + } + } + return new BitapSearch(pattern, options); +} +const LogicalOperator = { + AND: '$and', + OR: '$or' +}; +const KeyType = { + PATH: '$path', + PATTERN: '$val' +}; +const isExpression = query => !!(query[LogicalOperator.AND] || query[LogicalOperator.OR]); +const isPath = query => !!query[KeyType.PATH]; +const isLeaf = query => !isArray(query) && isObject(query) && !isExpression(query); +const convertToExplicit = query => ({ + [LogicalOperator.AND]: Object.keys(query).map(key => ({ + [key]: query[key] + })) +}); + +// When `auto` is `true`, the parse function will infer and initialize and add +// the appropriate `Searcher` instance +function parse(query, options, { + auto = true +} = {}) { + const next = query => { + let keys = Object.keys(query); + const isQueryPath = isPath(query); + if (!isQueryPath && keys.length > 1 && !isExpression(query)) { + return next(convertToExplicit(query)); + } + if (isLeaf(query)) { + const key = isQueryPath ? query[KeyType.PATH] : keys[0]; + const pattern = isQueryPath ? query[KeyType.PATTERN] : query[key]; + if (!isString(pattern)) { + throw new Error(LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key)); + } + const obj = { + keyId: createKeyId(key), + pattern + }; + if (auto) { + obj.searcher = createSearcher(pattern, options); + } + return obj; + } + let node = { + children: [], + operator: keys[0] + }; + keys.forEach(key => { + const value = query[key]; + if (isArray(value)) { + value.forEach(item => { + node.children.push(next(item)); + }); + } + }); + return node; + }; + if (!isExpression(query)) { + query = convertToExplicit(query); + } + return next(query); +} + +// Practical scoring function +function computeScore(results, { + ignoreFieldNorm = Config.ignoreFieldNorm +}) { + results.forEach(result => { + let totalScore = 1; + result.matches.forEach(({ + key, + norm, + score + }) => { + const weight = key ? key.weight : null; + totalScore *= Math.pow(score === 0 && weight ? Number.EPSILON : score, (weight || 1) * (ignoreFieldNorm ? 1 : norm)); + }); + result.score = totalScore; + }); +} +function transformMatches(result, data) { + const matches = result.matches; + data.matches = []; + if (!isDefined(matches)) { + return; + } + matches.forEach(match => { + if (!isDefined(match.indices) || !match.indices.length) { + return; + } + const { + indices, + value + } = match; + let obj = { + indices, + value + }; + if (match.key) { + obj.key = match.key.src; + } + if (match.idx > -1) { + obj.refIndex = match.idx; + } + data.matches.push(obj); + }); +} +function transformScore(result, data) { + data.score = result.score; +} +function format(results, docs, { + includeMatches = Config.includeMatches, + includeScore = Config.includeScore +} = {}) { + const transformers = []; + if (includeMatches) transformers.push(transformMatches); + if (includeScore) transformers.push(transformScore); + return results.map(result => { + const { + idx + } = result; + const data = { + item: docs[idx], + refIndex: idx + }; + if (transformers.length) { + transformers.forEach(transformer => { + transformer(result, data); + }); + } + return data; + }); +} +class Fuse { + constructor(docs, options = {}, index) { + this.options = _objectSpread2(_objectSpread2({}, Config), options); + if (this.options.useExtendedSearch && !true) { + throw new Error(EXTENDED_SEARCH_UNAVAILABLE); + } + this._keyStore = new KeyStore(this.options.keys); + this.setCollection(docs, index); + } + setCollection(docs, index) { + this._docs = docs; + if (index && !(index instanceof FuseIndex)) { + throw new Error(INCORRECT_INDEX_TYPE); + } + this._myIndex = index || createIndex(this.options.keys, this._docs, { + getFn: this.options.getFn, + fieldNormWeight: this.options.fieldNormWeight + }); + } + add(doc) { + if (!isDefined(doc)) { + return; + } + this._docs.push(doc); + this._myIndex.add(doc); + } + remove(predicate = ( /* doc, idx */) => false) { + const results = []; + for (let i = 0, len = this._docs.length; i < len; i += 1) { + const doc = this._docs[i]; + if (predicate(doc, i)) { + this.removeAt(i); + i -= 1; + len -= 1; + results.push(doc); + } + } + return results; + } + removeAt(idx) { + this._docs.splice(idx, 1); + this._myIndex.removeAt(idx); + } + getIndex() { + return this._myIndex; + } + search(query, { + limit = -1 + } = {}) { + const { + includeMatches, + includeScore, + shouldSort, + sortFn, + ignoreFieldNorm + } = this.options; + let results = isString(query) ? isString(this._docs[0]) ? this._searchStringList(query) : this._searchObjectList(query) : this._searchLogical(query); + computeScore(results, { + ignoreFieldNorm + }); + if (shouldSort) { + results.sort(sortFn); + } + if (isNumber(limit) && limit > -1) { + results = results.slice(0, limit); + } + return format(results, this._docs, { + includeMatches, + includeScore + }); + } + _searchStringList(query) { + const searcher = createSearcher(query, this.options); + const { + records + } = this._myIndex; + const results = []; + + // Iterate over every string in the index + records.forEach(({ + v: text, + i: idx, + n: norm + }) => { + if (!isDefined(text)) { + return; + } + const { + isMatch, + score, + indices + } = searcher.searchIn(text); + if (isMatch) { + results.push({ + item: text, + idx, + matches: [{ + score, + value: text, + norm, + indices + }] + }); + } + }); + return results; + } + _searchLogical(query) { + const expression = parse(query, this.options); + const evaluate = (node, item, idx) => { + if (!node.children) { + const { + keyId, + searcher + } = node; + const matches = this._findMatches({ + key: this._keyStore.get(keyId), + value: this._myIndex.getValueForItemAtKeyId(item, keyId), + searcher + }); + if (matches && matches.length) { + return [{ + idx, + item, + matches + }]; + } + return []; + } + const res = []; + for (let i = 0, len = node.children.length; i < len; i += 1) { + const child = node.children[i]; + const result = evaluate(child, item, idx); + if (result.length) { + res.push(...result); + } else if (node.operator === LogicalOperator.AND) { + return []; + } + } + return res; + }; + const records = this._myIndex.records; + const resultMap = {}; + const results = []; + records.forEach(({ + $: item, + i: idx + }) => { + if (isDefined(item)) { + let expResults = evaluate(expression, item, idx); + if (expResults.length) { + // Dedupe when adding + if (!resultMap[idx]) { + resultMap[idx] = { + idx, + item, + matches: [] + }; + results.push(resultMap[idx]); + } + expResults.forEach(({ + matches + }) => { + resultMap[idx].matches.push(...matches); + }); + } + } + }); + return results; + } + _searchObjectList(query) { + const searcher = createSearcher(query, this.options); + const { + keys, + records + } = this._myIndex; + const results = []; + + // List is Array + records.forEach(({ + $: item, + i: idx + }) => { + if (!isDefined(item)) { + return; + } + let matches = []; + + // Iterate over every key (i.e, path), and fetch the value at that key + keys.forEach((key, keyIndex) => { + matches.push(...this._findMatches({ + key, + value: item[keyIndex], + searcher + })); + }); + if (matches.length) { + results.push({ + idx, + item, + matches + }); + } + }); + return results; + } + _findMatches({ + key, + value, + searcher + }) { + if (!isDefined(value)) { + return []; + } + let matches = []; + if (isArray(value)) { + value.forEach(({ + v: text, + i: idx, + n: norm + }) => { + if (!isDefined(text)) { + return; + } + const { + isMatch, + score, + indices + } = searcher.searchIn(text); + if (isMatch) { + matches.push({ + score, + key, + value: text, + idx, + norm, + indices + }); + } + }); + } else { + const { + v: text, + n: norm + } = value; + const { + isMatch, + score, + indices + } = searcher.searchIn(text); + if (isMatch) { + matches.push({ + score, + key, + value: text, + norm, + indices + }); + } + } + return matches; + } +} +Fuse.version = '7.0.0'; +Fuse.createIndex = createIndex; +Fuse.parseIndex = parseIndex; +Fuse.config = Config; +{ + Fuse.parseQuery = parse; +} +{ + register(ExtendedSearch); +} + +var SearchByFuse = /** @class */ (function () { + function SearchByFuse(config) { + this._haystack = []; + this._fuseOptions = __assign(__assign({}, config.fuseOptions), { keys: __spreadArray([], config.searchFields, true), includeMatches: true }); + } + SearchByFuse.prototype.index = function (data) { + this._haystack = data; + if (this._fuse) { + this._fuse.setCollection(data); + } + }; + SearchByFuse.prototype.reset = function () { + this._haystack = []; + this._fuse = undefined; + }; + SearchByFuse.prototype.isEmptyIndex = function () { + return !this._haystack.length; + }; + SearchByFuse.prototype.search = function (needle) { + if (!this._fuse) { + { + this._fuse = new Fuse(this._haystack, this._fuseOptions); + } + } + var results = this._fuse.search(needle); + return results.map(function (value, i) { + return { + item: value.item, + score: value.score || 0, + rank: i + 1, // If value.score is used for sorting, this can create non-stable sorts! + }; + }); + }; + return SearchByFuse; +}()); + +function getSearcher(config) { + { + return new SearchByFuse(config); + } +} + +/** + * Helpers to create HTML elements used by Choices + * Can be overridden by providing `callbackOnCreateTemplates` option. + * `Choices.defaults.templates` allows access to the default template methods from `callbackOnCreateTemplates` + */ +var isEmptyObject = function (obj) { + // eslint-disable-next-line no-restricted-syntax + for (var prop in obj) { + if (Object.prototype.hasOwnProperty.call(obj, prop)) { + return false; + } + } + return true; +}; +var assignCustomProperties = function (el, choice, withCustomProperties) { + var dataset = el.dataset; + var customProperties = choice.customProperties, labelClass = choice.labelClass, labelDescription = choice.labelDescription; + if (labelClass) { + dataset.labelClass = getClassNames(labelClass).join(' '); + } + if (labelDescription) { + dataset.labelDescription = labelDescription; + } + if (withCustomProperties && customProperties) { + if (typeof customProperties === 'string') { + dataset.customProperties = customProperties; + } + else if (typeof customProperties === 'object' && !isEmptyObject(customProperties)) { + dataset.customProperties = JSON.stringify(customProperties); + } + } +}; +var addAriaLabel = function (docRoot, id, element) { + var label = id && docRoot.querySelector("label[for='".concat(id, "']")); + var text = label && label.innerText; + if (text) { + element.setAttribute('aria-label', text); + } +}; +var templates = { + containerOuter: function (_a, dir, isSelectElement, isSelectOneElement, searchEnabled, passedElementType, labelId) { + var containerOuter = _a.classNames.containerOuter; + var div = document.createElement('div'); + div.className = getClassNames(containerOuter).join(' '); + div.dataset.type = passedElementType; + if (dir) { + div.dir = dir; + } + if (isSelectOneElement) { + div.tabIndex = 0; + } + if (isSelectElement) { + div.setAttribute('role', searchEnabled ? 'combobox' : 'listbox'); + if (searchEnabled) { + div.setAttribute('aria-autocomplete', 'list'); + } + else if (!labelId) { + addAriaLabel(this._docRoot, this.passedElement.element.id, div); + } + div.setAttribute('aria-haspopup', 'true'); + div.setAttribute('aria-expanded', 'false'); + } + if (labelId) { + div.setAttribute('aria-labelledby', labelId); + } + return div; + }, + containerInner: function (_a) { + var containerInner = _a.classNames.containerInner; + var div = document.createElement('div'); + div.className = getClassNames(containerInner).join(' '); + return div; + }, + itemList: function (_a, isSelectOneElement) { + var searchEnabled = _a.searchEnabled, _b = _a.classNames, list = _b.list, listSingle = _b.listSingle, listItems = _b.listItems; + var div = document.createElement('div'); + div.className = "".concat(getClassNames(list).join(' '), " ").concat(isSelectOneElement ? getClassNames(listSingle).join(' ') : getClassNames(listItems).join(' ')); + if (this._isSelectElement && searchEnabled) { + div.setAttribute('role', 'listbox'); + } + return div; + }, + placeholder: function (_a, value) { + var allowHTML = _a.allowHTML, placeholder = _a.classNames.placeholder; + var div = document.createElement('div'); + div.className = getClassNames(placeholder).join(' '); + setElementHtml(div, allowHTML, value); + return div; + }, + item: function (_a, choice, removeItemButton) { + var _b, _c, _d; + var allowHTML = _a.allowHTML, removeItemButtonAlignLeft = _a.removeItemButtonAlignLeft, removeItemIconText = _a.removeItemIconText, removeItemLabelText = _a.removeItemLabelText, _e = _a.classNames, item = _e.item, button = _e.button, highlightedState = _e.highlightedState, itemSelectable = _e.itemSelectable, placeholder = _e.placeholder; + var labelClass = choice.labelClass, label = choice.label, disabled = choice.disabled, value = choice.value; + var rawValue = unwrapStringForRaw(value); + var div = document.createElement('div'); + div.className = getClassNames(item).join(' '); + if (labelClass) { + var spanLabel = document.createElement('span'); + setElementHtml(spanLabel, allowHTML, label); + spanLabel.className = getClassNames(labelClass).join(' '); + div.appendChild(spanLabel); + } + else { + setElementHtml(div, allowHTML, label); + } + var dataset = div.dataset; + dataset.item = ''; + dataset.id = choice.id; + dataset.value = rawValue; + assignCustomProperties(div, choice, true); + if (disabled || this.containerOuter.isDisabled) { + div.setAttribute('aria-disabled', 'true'); + } + if (this._isSelectElement) { + div.setAttribute('aria-selected', 'true'); + div.setAttribute('role', 'option'); + } + if (choice.placeholder) { + (_b = div.classList).add.apply(_b, getClassNames(placeholder)); + dataset.placeholder = ''; + } + (_c = div.classList).add.apply(_c, (choice.highlighted ? getClassNames(highlightedState) : getClassNames(itemSelectable))); + if (removeItemButton) { + if (disabled) { + (_d = div.classList).remove.apply(_d, getClassNames(itemSelectable)); + } + dataset.deletable = ''; + var removeButton = document.createElement('button'); + removeButton.type = 'button'; + removeButton.className = getClassNames(button).join(' '); + setElementHtml(removeButton, true, resolveNoticeFunction(removeItemIconText, value)); + var REMOVE_ITEM_LABEL = resolveNoticeFunction(removeItemLabelText, value); + if (REMOVE_ITEM_LABEL) { + removeButton.setAttribute('aria-label', REMOVE_ITEM_LABEL); + } + removeButton.dataset.button = ''; + if (removeItemButtonAlignLeft) { + div.insertAdjacentElement('afterbegin', removeButton); + } + else { + div.appendChild(removeButton); + } + } + return div; + }, + choiceList: function (_a, isSelectOneElement) { + var list = _a.classNames.list; + var div = document.createElement('div'); + div.className = getClassNames(list).join(' '); + if (!isSelectOneElement) { + div.setAttribute('aria-multiselectable', 'true'); + } + div.setAttribute('role', 'listbox'); + return div; + }, + choiceGroup: function (_a, _b) { + var allowHTML = _a.allowHTML, _c = _a.classNames, group = _c.group, groupHeading = _c.groupHeading, itemDisabled = _c.itemDisabled; + var id = _b.id, label = _b.label, disabled = _b.disabled; + var rawLabel = unwrapStringForRaw(label); + var div = document.createElement('div'); + div.className = "".concat(getClassNames(group).join(' '), " ").concat(disabled ? getClassNames(itemDisabled).join(' ') : ''); + div.setAttribute('role', 'group'); + var dataset = div.dataset; + dataset.group = ''; + dataset.id = id; + dataset.value = rawLabel; + if (disabled) { + div.setAttribute('aria-disabled', 'true'); + } + var heading = document.createElement('div'); + heading.className = getClassNames(groupHeading).join(' '); + setElementHtml(heading, allowHTML, label); + div.appendChild(heading); + return div; + }, + choice: function (_a, choice, selectText) { + var _b, _c, _d, _e, _f; + var allowHTML = _a.allowHTML, _g = _a.classNames, item = _g.item, itemChoice = _g.itemChoice, itemSelectable = _g.itemSelectable, selectedState = _g.selectedState, itemDisabled = _g.itemDisabled, description = _g.description, placeholder = _g.placeholder; + var value = choice.value, elementId = choice.elementId, groupId = choice.groupId, label = choice.label, labelClass = choice.labelClass, labelDescription = choice.labelDescription; + var rawValue = unwrapStringForRaw(value); + var div = document.createElement('div'); + div.id = elementId; + div.className = "".concat(getClassNames(item).join(' '), " ").concat(getClassNames(itemChoice).join(' ')); + var describedBy = div; + if (labelClass) { + var spanLabel = document.createElement('span'); + setElementHtml(spanLabel, allowHTML, label); + spanLabel.className = getClassNames(labelClass).join(' '); + describedBy = spanLabel; + div.appendChild(spanLabel); + } + else { + setElementHtml(div, allowHTML, label); + } + if (labelDescription) { + var descId = "".concat(elementId, "-description"); + describedBy.setAttribute('aria-describedby', descId); + var spanDesc = document.createElement('span'); + setElementHtml(spanDesc, allowHTML, labelDescription); + spanDesc.id = descId; + (_b = spanDesc.classList).add.apply(_b, getClassNames(description)); + div.appendChild(spanDesc); + } + if (choice.selected) { + (_c = div.classList).add.apply(_c, getClassNames(selectedState)); + } + if (choice.placeholder) { + (_d = div.classList).add.apply(_d, getClassNames(placeholder)); + } + var dataset = div.dataset; + var showGroupId = groupId && groupId > 0; + div.setAttribute('role', showGroupId ? 'treeitem' : 'option'); + if (showGroupId) { + dataset.groupId = "".concat(groupId); + } + dataset.choice = ''; + dataset.id = choice.id; + dataset.value = rawValue; + dataset.selectText = selectText; + assignCustomProperties(div, choice, false); + if (choice.disabled) { + (_e = div.classList).add.apply(_e, getClassNames(itemDisabled)); + dataset.choiceDisabled = ''; + div.setAttribute('aria-disabled', 'true'); + } + else { + (_f = div.classList).add.apply(_f, getClassNames(itemSelectable)); + dataset.choiceSelectable = ''; + } + return div; + }, + input: function (_a, placeholderValue) { + var _b = _a.classNames, input = _b.input, inputCloned = _b.inputCloned, labelId = _a.labelId; + var inp = document.createElement('input'); + inp.type = 'search'; + inp.className = "".concat(getClassNames(input).join(' '), " ").concat(getClassNames(inputCloned).join(' ')); + inp.autocomplete = 'off'; + inp.autocapitalize = 'off'; + inp.spellcheck = false; + inp.setAttribute('role', 'textbox'); + inp.setAttribute('aria-autocomplete', 'list'); + if (placeholderValue) { + inp.setAttribute('aria-label', placeholderValue); + } + else if (!labelId) { + addAriaLabel(this._docRoot, this.passedElement.element.id, inp); + } + return inp; + }, + dropdown: function (_a) { + var _b, _c; + var _d = _a.classNames, list = _d.list, listDropdown = _d.listDropdown; + var div = document.createElement('div'); + (_b = div.classList).add.apply(_b, getClassNames(list)); + (_c = div.classList).add.apply(_c, getClassNames(listDropdown)); + div.setAttribute('aria-expanded', 'false'); + return div; + }, + notice: function (_a, innerHTML, type) { + var _b = _a.classNames, item = _b.item, itemChoice = _b.itemChoice, addChoice = _b.addChoice, noResults = _b.noResults, noChoices = _b.noChoices, noticeItem = _b.notice; + if (type === void 0) { type = NoticeTypes.generic; } + var classes = __spreadArray(__spreadArray(__spreadArray([], getClassNames(item), true), getClassNames(itemChoice), true), getClassNames(noticeItem), true); + // eslint-disable-next-line default-case + switch (type) { + case NoticeTypes.addChoice: + classes.push.apply(classes, getClassNames(addChoice)); + break; + case NoticeTypes.noResults: + classes.push.apply(classes, getClassNames(noResults)); + break; + case NoticeTypes.noChoices: + classes.push.apply(classes, getClassNames(noChoices)); + break; + } + var notice = document.createElement('div'); + setElementHtml(notice, true, innerHTML); + notice.className = classes.join(' '); + if (type === NoticeTypes.addChoice) { + var dataset = notice.dataset; + dataset.choiceSelectable = ''; + dataset.choice = ''; + } + return notice; + }, + option: function (choice) { + // HtmlOptionElement's label value does not support HTML, so the avoid double escaping unwrap the untrusted string. + var labelValue = unwrapStringForRaw(choice.label); + var opt = new Option(labelValue, choice.value, false, choice.selected); + assignCustomProperties(opt, choice, true); + opt.disabled = choice.disabled; + if (choice.selected) { + opt.setAttribute('selected', ''); + } + return opt; + }, +}; + +/** @see {@link http://browserhacks.com/#hack-acea075d0ac6954f275a70023906050c} */ +var IS_IE11 = '-ms-scroll-limit' in document.documentElement.style && + '-ms-ime-align' in document.documentElement.style; +var USER_DEFAULTS = {}; +var parseDataSetId = function (element) { + if (!element) { + return undefined; + } + var id = element.dataset.id; + return id ? parseInt(id, 10) : undefined; +}; +/** + * Choices + * @author Josh Johnson + */ +var Choices = /** @class */ (function () { + function Choices(element, userConfig) { + if (element === void 0) { element = '[data-choice]'; } + if (userConfig === void 0) { userConfig = {}; } + var _this = this; + this.initialisedOK = undefined; + this._hasNonChoicePlaceholder = false; + this._lastAddedChoiceId = 0; + this._lastAddedGroupId = 0; + var defaults = Choices.defaults; + this.config = __assign(__assign(__assign({}, defaults.allOptions), defaults.options), userConfig); + ObjectsInConfig.forEach(function (key) { + _this.config[key] = __assign(__assign(__assign({}, defaults.allOptions[key]), defaults.options[key]), userConfig[key]); + }); + var config = this.config; + if (!config.silent) { + this._validateConfig(); + } + var docRoot = config.shadowRoot || document.documentElement; + this._docRoot = docRoot; + var passedElement = typeof element === 'string' ? docRoot.querySelector(element) : element; + if (!passedElement || + typeof passedElement !== 'object' || + !(isHtmlInputElement(passedElement) || isHtmlSelectElement(passedElement))) { + if (!passedElement && typeof element === 'string') { + throw TypeError("Selector ".concat(element, " failed to find an element")); + } + throw TypeError("Expected one of the following types text|select-one|select-multiple"); + } + this._elementType = passedElement.type; + this._isTextElement = this._elementType === TEXT_TYPE; + if (this._isTextElement || config.maxItemCount !== 1) { + config.singleModeForMultiSelect = false; + } + if (config.singleModeForMultiSelect) { + this._elementType = SELECT_MULTIPLE_TYPE; + } + this._isSelectOneElement = this._elementType === SELECT_ONE_TYPE; + this._isSelectMultipleElement = this._elementType === SELECT_MULTIPLE_TYPE; + this._isSelectElement = this._isSelectOneElement || this._isSelectMultipleElement; + this._canAddUserChoices = (this._isTextElement && config.addItems) || (this._isSelectElement && config.addChoices); + if (!['auto', 'always'].includes("".concat(config.renderSelectedChoices))) { + config.renderSelectedChoices = 'auto'; + } + if (config.closeDropdownOnSelect === 'auto') { + config.closeDropdownOnSelect = this._isTextElement || this._isSelectOneElement || config.singleModeForMultiSelect; + } + else { + config.closeDropdownOnSelect = coerceBool(config.closeDropdownOnSelect); + } + if (config.placeholder) { + if (config.placeholderValue) { + this._hasNonChoicePlaceholder = true; + } + else if (passedElement.dataset.placeholder) { + this._hasNonChoicePlaceholder = true; + config.placeholderValue = passedElement.dataset.placeholder; + } + } + if (userConfig.addItemFilter && typeof userConfig.addItemFilter !== 'function') { + var re = userConfig.addItemFilter instanceof RegExp ? userConfig.addItemFilter : new RegExp(userConfig.addItemFilter); + config.addItemFilter = re.test.bind(re); + } + if (this._isTextElement) { + this.passedElement = new WrappedInput({ + element: passedElement, + classNames: config.classNames, + }); + } + else { + var selectEl = passedElement; + this.passedElement = new WrappedSelect({ + element: selectEl, + classNames: config.classNames, + template: function (data) { return _this._templates.option(data); }, + extractPlaceholder: config.placeholder && !this._hasNonChoicePlaceholder, + }); + } + this.initialised = false; + this._store = new Store(); + this._currentValue = ''; + config.searchEnabled = (!this._isTextElement && config.searchEnabled) || this._elementType === SELECT_MULTIPLE_TYPE; + this._canSearch = config.searchEnabled; + this._isScrollingOnIe = false; + this._highlightPosition = 0; + this._wasTap = true; + this._placeholderValue = this._generatePlaceholderValue(); + this._baseId = generateId(passedElement, 'choices-'); + /** + * setting direction in cases where it's explicitly set on passedElement + * or when calculated direction is different from the document + */ + this._direction = this.passedElement.dir; + if (!this._direction) { + var elementDirection = window.getComputedStyle(this.passedElement.element).direction; + var documentDirection = window.getComputedStyle(document.documentElement).direction; + if (elementDirection !== documentDirection) { + this._direction = elementDirection; + } + } + this._idNames = { + itemChoice: 'item-choice', + }; + this._templates = defaults.templates; + this._render = this._render.bind(this); + this._onFocus = this._onFocus.bind(this); + this._onBlur = this._onBlur.bind(this); + this._onKeyUp = this._onKeyUp.bind(this); + this._onKeyDown = this._onKeyDown.bind(this); + this._onInput = this._onInput.bind(this); + this._onClick = this._onClick.bind(this); + this._onTouchMove = this._onTouchMove.bind(this); + this._onTouchEnd = this._onTouchEnd.bind(this); + this._onMouseDown = this._onMouseDown.bind(this); + this._onMouseOver = this._onMouseOver.bind(this); + this._onFormReset = this._onFormReset.bind(this); + this._onSelectKey = this._onSelectKey.bind(this); + this._onEnterKey = this._onEnterKey.bind(this); + this._onEscapeKey = this._onEscapeKey.bind(this); + this._onDirectionKey = this._onDirectionKey.bind(this); + this._onDeleteKey = this._onDeleteKey.bind(this); + // If element has already been initialised with Choices, fail silently + if (this.passedElement.isActive) { + if (!config.silent) { + console.warn('Trying to initialise Choices on element already initialised', { element: element }); + } + this.initialised = true; + this.initialisedOK = false; + return; + } + // Let's go + this.init(); + // preserve the selected item list after setup for form reset + this._initialItems = this._store.items.map(function (choice) { return choice.value; }); + } + Object.defineProperty(Choices, "defaults", { + get: function () { + return Object.preventExtensions({ + get options() { + return USER_DEFAULTS; + }, + get allOptions() { + return DEFAULT_CONFIG; + }, + get templates() { + return templates; + }, + }); + }, + enumerable: false, + configurable: true + }); + Choices.prototype.init = function () { + if (this.initialised || this.initialisedOK !== undefined) { + return; + } + this._searcher = getSearcher(this.config); + this._loadChoices(); + this._createTemplates(); + this._createElements(); + this._createStructure(); + if ((this._isTextElement && !this.config.addItems) || + this.passedElement.element.hasAttribute('disabled') || + !!this.passedElement.element.closest('fieldset:disabled')) { + this.disable(); + } + else { + this.enable(); + this._addEventListeners(); + } + // should be triggered **after** disabled state to avoid additional re-draws + this._initStore(); + this.initialised = true; + this.initialisedOK = true; + var callbackOnInit = this.config.callbackOnInit; + // Run callback if it is a function + if (callbackOnInit && typeof callbackOnInit === 'function') { + callbackOnInit.call(this); + } + }; + Choices.prototype.destroy = function () { + if (!this.initialised) { + return; + } + this._removeEventListeners(); + this.passedElement.reveal(); + this.containerOuter.unwrap(this.passedElement.element); + this._store._listeners = []; // prevents select/input value being wiped + this.clearStore(); + this._stopSearch(); + this._templates = Choices.defaults.templates; + this.initialised = false; + this.initialisedOK = undefined; + }; + Choices.prototype.enable = function () { + var _a = this, passedElement = _a.passedElement, containerOuter = _a.containerOuter; + if (passedElement.isDisabled) { + passedElement.enable(); + } + if (containerOuter.isDisabled) { + this._addEventListeners(); + this.input.enable(); + containerOuter.enable(); + this._render(); + } + return this; + }; + Choices.prototype.disable = function () { + var _a = this, passedElement = _a.passedElement, containerOuter = _a.containerOuter; + if (!passedElement.isDisabled) { + passedElement.disable(); + } + if (!containerOuter.isDisabled) { + this._removeEventListeners(); + this.input.disable(); + containerOuter.disable(); + this._render(); + } + return this; + }; + Choices.prototype.highlightItem = function (item, runEvent) { + if (runEvent === void 0) { runEvent = true; } + if (!item || !item.id) { + return this; + } + var choice = this._store.choices.find(function (c) { return c.id === item.id; }); + if (!choice || choice.highlighted) { + return this; + } + this._store.dispatch(highlightItem(choice, true)); + if (runEvent) { + this.passedElement.triggerEvent("highlightItem" /* EventType.highlightItem */, this._getChoiceForOutput(choice)); + } + return this; + }; + Choices.prototype.unhighlightItem = function (item, runEvent) { + if (runEvent === void 0) { runEvent = true; } + if (!item || !item.id) { + return this; + } + var choice = this._store.choices.find(function (c) { return c.id === item.id; }); + if (!choice || !choice.highlighted) { + return this; + } + this._store.dispatch(highlightItem(choice, false)); + if (runEvent) { + this.passedElement.triggerEvent("highlightItem" /* EventType.highlightItem */, this._getChoiceForOutput(choice)); + } + return this; + }; + Choices.prototype.highlightAll = function () { + var _this = this; + this._store.withTxn(function () { + _this._store.items.forEach(function (item) { return _this.highlightItem(item); }); + }); + return this; + }; + Choices.prototype.unhighlightAll = function () { + var _this = this; + this._store.withTxn(function () { + _this._store.items.forEach(function (item) { return _this.unhighlightItem(item); }); + }); + return this; + }; + Choices.prototype.removeActiveItemsByValue = function (value) { + var _this = this; + this._store.withTxn(function () { + _this._store.items.filter(function (item) { return item.value === value; }).forEach(function (item) { return _this._removeItem(item); }); + }); + return this; + }; + Choices.prototype.removeActiveItems = function (excludedId) { + var _this = this; + this._store.withTxn(function () { + _this._store.items.filter(function (_a) { + var id = _a.id; + return id !== excludedId; + }).forEach(function (item) { return _this._removeItem(item); }); + }); + return this; + }; + Choices.prototype.removeHighlightedItems = function (runEvent) { + var _this = this; + if (runEvent === void 0) { runEvent = false; } + this._store.withTxn(function () { + _this._store.highlightedActiveItems.forEach(function (item) { + _this._removeItem(item); + // If this action was performed by the user + // trigger the event + if (runEvent) { + _this._triggerChange(item.value); + } + }); + }); + return this; + }; + Choices.prototype.showDropdown = function (preventInputFocus) { + var _this = this; + if (this.dropdown.isActive) { + return this; + } + requestAnimationFrame(function () { + _this.dropdown.show(); + _this.containerOuter.open(_this.dropdown.distanceFromTopWindow); + if (!preventInputFocus && _this._canSearch) { + _this.input.focus(); + } + _this.passedElement.triggerEvent("showDropdown" /* EventType.showDropdown */); + }); + return this; + }; + Choices.prototype.hideDropdown = function (preventInputBlur) { + var _this = this; + if (!this.dropdown.isActive) { + return this; + } + requestAnimationFrame(function () { + _this.dropdown.hide(); + _this.containerOuter.close(); + if (!preventInputBlur && _this._canSearch) { + _this.input.removeActiveDescendant(); + _this.input.blur(); + } + _this.passedElement.triggerEvent("hideDropdown" /* EventType.hideDropdown */); + }); + return this; + }; + Choices.prototype.getValue = function (valueOnly) { + var _this = this; + if (valueOnly === void 0) { valueOnly = false; } + var values = this._store.items.reduce(function (selectedItems, item) { + var itemValue = valueOnly ? item.value : _this._getChoiceForOutput(item); + selectedItems.push(itemValue); + return selectedItems; + }, []); + return this._isSelectOneElement || this.config.singleModeForMultiSelect ? values[0] : values; + }; + Choices.prototype.setValue = function (items) { + var _this = this; + if (!this.initialisedOK) { + this._warnChoicesInitFailed('setValue'); + return this; + } + this._store.withTxn(function () { + items.forEach(function (value) { + if (value) { + _this._addChoice(mapInputToChoice(value, false)); + } + }); + }); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + Choices.prototype.setChoiceByValue = function (value) { + var _this = this; + if (!this.initialisedOK) { + this._warnChoicesInitFailed('setChoiceByValue'); + return this; + } + if (this._isTextElement) { + return this; + } + this._store.withTxn(function () { + // If only one value has been passed, convert to array + var choiceValue = Array.isArray(value) ? value : [value]; + // Loop through each value and + choiceValue.forEach(function (val) { return _this._findAndSelectChoiceByValue(val); }); + }); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + /** + * Set choices of select input via an array of objects (or function that returns array of object or promise of it), + * a value field name and a label field name. + * This behaves the same as passing items via the choices option but can be called after initialising Choices. + * This can also be used to add groups of choices (see example 2); Optionally pass a true `replaceChoices` value to remove any existing choices. + * Optionally pass a `customProperties` object to add additional data to your choices (useful when searching/filtering etc). + * + * **Input types affected:** select-one, select-multiple + * + * @example + * ```js + * const example = new Choices(element); + * + * example.setChoices([ + * {value: 'One', label: 'Label One', disabled: true}, + * {value: 'Two', label: 'Label Two', selected: true}, + * {value: 'Three', label: 'Label Three'}, + * ], 'value', 'label', false); + * ``` + * + * @example + * ```js + * const example = new Choices(element); + * + * example.setChoices(async () => { + * try { + * const items = await fetch('/items'); + * return items.json() + * } catch(err) { + * console.error(err) + * } + * }); + * ``` + * + * @example + * ```js + * const example = new Choices(element); + * + * example.setChoices([{ + * label: 'Group one', + * id: 1, + * disabled: false, + * choices: [ + * {value: 'Child One', label: 'Child One', selected: true}, + * {value: 'Child Two', label: 'Child Two', disabled: true}, + * {value: 'Child Three', label: 'Child Three'}, + * ] + * }, + * { + * label: 'Group two', + * id: 2, + * disabled: false, + * choices: [ + * {value: 'Child Four', label: 'Child Four', disabled: true}, + * {value: 'Child Five', label: 'Child Five'}, + * {value: 'Child Six', label: 'Child Six', customProperties: { + * description: 'Custom description about child six', + * random: 'Another random custom property' + * }}, + * ] + * }], 'value', 'label', false); + * ``` + */ + Choices.prototype.setChoices = function (choicesArrayOrFetcher, value, label, replaceChoices) { + var _this = this; + if (choicesArrayOrFetcher === void 0) { choicesArrayOrFetcher = []; } + if (value === void 0) { value = 'value'; } + if (label === void 0) { label = 'label'; } + if (replaceChoices === void 0) { replaceChoices = false; } + if (!this.initialisedOK) { + this._warnChoicesInitFailed('setChoices'); + return this; + } + if (!this._isSelectElement) { + throw new TypeError("setChoices can't be used with INPUT based Choices"); + } + if (typeof value !== 'string' || !value) { + throw new TypeError("value parameter must be a name of 'value' field in passed objects"); + } + // Clear choices if needed + if (replaceChoices) { + this.clearChoices(); + } + if (typeof choicesArrayOrFetcher === 'function') { + // it's a choices fetcher function + var fetcher_1 = choicesArrayOrFetcher(this); + if (typeof Promise === 'function' && fetcher_1 instanceof Promise) { + // that's a promise + // eslint-disable-next-line no-promise-executor-return + return new Promise(function (resolve) { return requestAnimationFrame(resolve); }) + .then(function () { return _this._handleLoadingState(true); }) + .then(function () { return fetcher_1; }) + .then(function (data) { return _this.setChoices(data, value, label, replaceChoices); }) + .catch(function (err) { + if (!_this.config.silent) { + console.error(err); + } + }) + .then(function () { return _this._handleLoadingState(false); }) + .then(function () { return _this; }); + } + // function returned something else than promise, let's check if it's an array of choices + if (!Array.isArray(fetcher_1)) { + throw new TypeError(".setChoices first argument function must return either array of choices or Promise, got: ".concat(typeof fetcher_1)); + } + // recursion with results, it's sync and choices were cleared already + return this.setChoices(fetcher_1, value, label, false); + } + if (!Array.isArray(choicesArrayOrFetcher)) { + throw new TypeError(".setChoices must be called either with array of choices with a function resulting into Promise of array of choices"); + } + this.containerOuter.removeLoadingState(); + this._store.withTxn(function () { + var isDefaultValue = value === 'value'; + var isDefaultLabel = label === 'label'; + choicesArrayOrFetcher.forEach(function (groupOrChoice) { + if ('choices' in groupOrChoice) { + var group = groupOrChoice; + if (!isDefaultLabel) { + group = __assign(__assign({}, group), { label: group[label] }); + } + _this._addGroup(mapInputToChoice(group, true)); + } + else { + var choice = groupOrChoice; + if (!isDefaultLabel || !isDefaultValue) { + choice = __assign(__assign({}, choice), { value: choice[value], label: choice[label] }); + } + _this._addChoice(mapInputToChoice(choice, false)); + } + }); + }); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + Choices.prototype.refresh = function (withEvents, selectFirstOption, deselectAll) { + var _this = this; + if (withEvents === void 0) { withEvents = false; } + if (selectFirstOption === void 0) { selectFirstOption = false; } + if (deselectAll === void 0) { deselectAll = false; } + if (!this._isSelectElement) { + if (!this.config.silent) { + console.warn('refresh method can only be used on choices backed by a element'); + } + return this; + } + this._store.withTxn(function () { + var choicesFromOptions = _this.passedElement.optionsAsChoices(); + var items = _this._store.items; + // Build the list of items which require preserving + var existingItems = {}; + if (!deselectAll) { + items.forEach(function (choice) { + if (choice.id && choice.active && choice.selected && !choice.disabled) { + existingItems[choice.value] = true; + } + }); + } + choicesFromOptions.forEach(function (groupOrChoice) { + if ('choices' in groupOrChoice) { + return; + } + var choice = groupOrChoice; + if (deselectAll) { + choice.selected = false; + } + else if (existingItems[choice.value]) { + choice.selected = true; + } + }); + _this.clearStore(); + /* @todo only generate add events for the added options instead of all + if (withEvents) { + items.forEach((choice) => { + if (existingItems[choice.value]) { + this.passedElement.triggerEvent( + EventType.removeItem, + this._getChoiceForEvent(choice), + ); + } + }); + } + */ + // load new choices & items + _this._addPredefinedChoices(choicesFromOptions, selectFirstOption, withEvents); + // re-do search if required + if (_this._isSearching) { + _this._searchChoices(_this.input.value); + } + }); + return this; + }; + Choices.prototype.removeChoice = function (value) { + var choice = this._store.choices.find(function (c) { return c.value === value; }); + if (!choice) { + return this; + } + this._store.dispatch(removeChoice(choice)); + // @todo integrate with Store + this._searcher.reset(); + if (choice.selected) { + this.passedElement.triggerEvent("removeItem" /* EventType.removeItem */, this._getChoiceForOutput(choice)); + } + return this; + }; + Choices.prototype.clearChoices = function () { + this.passedElement.element.innerHTML = ''; + this._store.dispatch(clearChoices()); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + Choices.prototype.clearStore = function () { + this._store.reset(); + this._lastAddedChoiceId = 0; + this._lastAddedGroupId = 0; + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + Choices.prototype.clearInput = function () { + var shouldSetInputWidth = !this._isSelectOneElement; + this.input.clear(shouldSetInputWidth); + this._clearNotice(); + if (this._isSearching) { + this._stopSearch(); + } + return this; + }; + Choices.prototype._validateConfig = function () { + var config = this.config; + var invalidConfigOptions = diff(config, DEFAULT_CONFIG); + if (invalidConfigOptions.length) { + console.warn('Unknown config option(s) passed', invalidConfigOptions.join(', ')); + } + if (config.allowHTML && config.allowHtmlUserInput) { + if (config.addItems) { + console.warn('Warning: allowHTML/allowHtmlUserInput/addItems all being true is strongly not recommended and may lead to XSS attacks'); + } + if (config.addChoices) { + console.warn('Warning: allowHTML/allowHtmlUserInput/addChoices all being true is strongly not recommended and may lead to XSS attacks'); + } + } + }; + Choices.prototype._render = function (changes) { + if (changes === void 0) { changes = { choices: true, groups: true, items: true }; } + if (this._store.inTxn()) { + return; + } + if (this._isSelectElement) { + if (changes.choices || changes.groups) { + this._renderChoices(); + } + } + if (changes.items) { + this._renderItems(); + } + }; + Choices.prototype._renderChoices = function () { + var _this = this; + this.choiceList.clear(); + if (!this._canAddItems()) { + return; // block rendering choices if the input limit is reached. + } + var config = this.config; + var _a = this._store, activeGroups = _a.activeGroups, activeChoices = _a.activeChoices; + var choiceListFragment = document.createDocumentFragment(); + var noChoices = true; + if (activeChoices.length) { + if (config.resetScrollPosition) { + requestAnimationFrame(function () { return _this.choiceList.scrollToTop(); }); + } + // If we have grouped options + if (activeGroups.length && !this._isSearching) { + if (!this._hasNonChoicePlaceholder) { + // If we have a placeholder choice along with groups + var activePlaceholders = activeChoices.filter(function (activeChoice) { return activeChoice.placeholder && activeChoice.groupId === -1; }); + if (activePlaceholders.length) { + choiceListFragment = this._createChoicesFragment(activePlaceholders, choiceListFragment); + } + } + choiceListFragment = this._createGroupsFragment(activeGroups, activeChoices, choiceListFragment); + } + else { + choiceListFragment = this._createChoicesFragment(activeChoices, choiceListFragment); + } + noChoices = !choiceListFragment.childNodes.length; + } + var notice = this._notice; + if (noChoices) { + if (!notice) { + this._notice = { + text: resolveStringFunction(config.noChoicesText), + type: NoticeTypes.noChoices, + }; + } + } + else if (notice && notice.type === NoticeTypes.noChoices) { + this._notice = undefined; + } + this._renderNotice(); + if (!noChoices) { + this.choiceList.element.append(choiceListFragment); + this._highlightChoice(); + } + }; + Choices.prototype._renderItems = function () { + var items = this._store.items || []; + this.itemList.clear(); + // Create a fragment to store our list items + // (so we don't have to update the DOM for each item) + var itemListFragment = this._createItemsFragment(items); + // If we have items to add, append them + if (itemListFragment.childNodes.length) { + this.itemList.element.append(itemListFragment); + } + }; + Choices.prototype._createGroupsFragment = function (groups, choices, fragment) { + var _this = this; + if (fragment === void 0) { fragment = document.createDocumentFragment(); } + var config = this.config; + var getGroupChoices = function (group) { + return choices.filter(function (choice) { + if (_this._isSelectOneElement) { + return choice.groupId === group.id; + } + return choice.groupId === group.id && (config.renderSelectedChoices === 'always' || !choice.selected); + }); + }; + // If sorting is enabled, filter groups + if (config.shouldSort) { + groups.sort(config.sorter); + } + // Add Choices without group first, regardless of sort, otherwise they won't be distinguishable + // from the last group + var choicesWithoutGroup = choices.filter(function (c) { return !c.groupId; }); + if (choicesWithoutGroup.length) { + this._createChoicesFragment(choicesWithoutGroup, fragment, false); + } + groups.forEach(function (group) { + var groupChoices = getGroupChoices(group); + if (groupChoices.length) { + var dropdownGroup = _this._templates.choiceGroup(_this.config, group); + fragment.appendChild(dropdownGroup); + _this._createChoicesFragment(groupChoices, fragment, true); + } + }); + return fragment; + }; + Choices.prototype._createChoicesFragment = function (choices, fragment, withinGroup) { + var _this = this; + if (fragment === void 0) { fragment = document.createDocumentFragment(); } + if (withinGroup === void 0) { withinGroup = false; } + // Create a fragment to store our list items (so we don't have to update the DOM for each item) + var _a = this, config = _a.config, isSearching = _a._isSearching, isSelectOneElement = _a._isSelectOneElement; + var searchResultLimit = config.searchResultLimit, renderChoiceLimit = config.renderChoiceLimit; + var groupLookup = []; + var appendGroupInSearch = config.appendGroupInSearch && isSearching; + if (appendGroupInSearch) { + this._store.groups.forEach(function (group) { + groupLookup[group.id] = group.label; + }); + } + if (this._isSelectElement) { + var backingOptions = choices.filter(function (choice) { return !choice.element; }); + if (backingOptions.length) { + this.passedElement.addOptions(backingOptions); + } + } + var skipSelected = config.renderSelectedChoices === 'auto' && !isSelectOneElement; + var placeholderChoices = []; + var normalChoices = []; + choices.forEach(function (choice) { + if ((isSearching && !choice.rank) || (skipSelected && choice.selected)) { + return; + } + if (_this._hasNonChoicePlaceholder || !choice.placeholder) { + normalChoices.push(choice); + } + else { + placeholderChoices.push(choice); + } + }); + if (isSearching) { + // sortByRank is used to ensure stable sorting, as scores are non-unique + // this additionally ensures fuseOptions.sortFn is not ignored + normalChoices.sort(sortByRank); + } + else if (config.shouldSort) { + normalChoices.sort(config.sorter); + } + var sortedChoices = isSelectOneElement && placeholderChoices.length ? __spreadArray(__spreadArray([], placeholderChoices, true), normalChoices, true) : normalChoices; + var choiceLimit = sortedChoices.length; + var limit = choiceLimit; + if (isSearching && searchResultLimit > 0) { + limit = searchResultLimit; + } + else if (renderChoiceLimit > 0 && !withinGroup) { + limit = renderChoiceLimit; + } + if (limit < choiceLimit) { + choiceLimit = limit; + } + choiceLimit--; + // Add each choice to dropdown within range + sortedChoices.every(function (choice, index) { + var dropdownItem = _this._templates.choice(config, choice, config.itemSelectText); + if (appendGroupInSearch && choice.groupId > 0) { + var groupName = groupLookup[choice.groupId]; + if (groupName) { + dropdownItem.innerHTML += " (".concat(groupName, ")"); + } + } + fragment.appendChild(dropdownItem); + return index < choiceLimit; + }); + return fragment; + }; + Choices.prototype._createItemsFragment = function (items, fragment) { + var _this = this; + if (fragment === void 0) { fragment = document.createDocumentFragment(); } + // Create fragment to add elements to + var config = this.config; + var shouldSortItems = config.shouldSortItems, sorter = config.sorter, removeItemButton = config.removeItemButton, delimiter = config.delimiter; + // If sorting is enabled, filter items + if (shouldSortItems && !this._isSelectOneElement) { + items.sort(sorter); + } + if (this._isTextElement) { + // Update the value of the hidden input + this.passedElement.value = items.map(function (_a) { + var value = _a.value; + return value; + }).join(delimiter); + } + var addItemToFragment = function (item) { + // Create new list element + var listItem = _this._templates.item(config, item, removeItemButton); + // Append it to list + fragment.appendChild(listItem); + }; + // Add each list item to list + items.forEach(addItemToFragment); + if (this._isSelectOneElement && this._hasNonChoicePlaceholder && !items.length) { + addItemToFragment(mapInputToChoice({ + selected: true, + value: '', + label: this.config.placeholderValue || '', + active: true, + placeholder: true, + }, false)); + } + return fragment; + }; + Choices.prototype._displayNotice = function (text, type, openDropdown) { + if (openDropdown === void 0) { openDropdown = true; } + var oldNotice = this._notice; + if (oldNotice && + ((oldNotice.type === type && oldNotice.text === text) || + (oldNotice.type === NoticeTypes.addChoice && + (type === NoticeTypes.noResults || type === NoticeTypes.noChoices)))) { + if (openDropdown) { + this.showDropdown(true); + } + return; + } + this._clearNotice(); + this._notice = text + ? { + text: text, + type: type, + } + : undefined; + this._renderNotice(); + if (openDropdown && text) { + this.showDropdown(true); + } + }; + Choices.prototype._clearNotice = function () { + if (!this._notice) { + return; + } + var noticeElement = this.choiceList.element.querySelector(getClassNamesSelector(this.config.classNames.notice)); + if (noticeElement) { + noticeElement.remove(); + } + this._notice = undefined; + }; + Choices.prototype._renderNotice = function () { + var noticeConf = this._notice; + if (noticeConf) { + var notice = this._templates.notice(this.config, noticeConf.text, noticeConf.type); + this.choiceList.prepend(notice); + } + }; + Choices.prototype._getChoiceForOutput = function (choice, keyCode) { + if (!choice) { + return undefined; + } + var group = choice.groupId > 0 ? this._store.getGroupById(choice.groupId) : null; + return { + id: choice.id, + highlighted: choice.highlighted, + labelClass: choice.labelClass, + labelDescription: choice.labelDescription, + customProperties: choice.customProperties, + disabled: choice.disabled, + active: choice.active, + label: choice.label, + placeholder: choice.placeholder, + value: choice.value, + groupValue: group && group.label ? group.label : undefined, + element: choice.element, + keyCode: keyCode, + }; + }; + Choices.prototype._triggerChange = function (value) { + if (value === undefined || value === null) { + return; + } + this.passedElement.triggerEvent("change" /* EventType.change */, { + value: value, + }); + }; + Choices.prototype._handleButtonAction = function (element) { + var items = this._store.items; + if (!items.length || !this.config.removeItems || !this.config.removeItemButton) { + return; + } + var id = element && parseDataSetId(element.parentNode); + var itemToRemove = id && items.find(function (item) { return item.id === id; }); + if (!itemToRemove) { + return; + } + // Remove item associated with button + this._removeItem(itemToRemove); + this._triggerChange(itemToRemove.value); + if (this._isSelectOneElement && !this._hasNonChoicePlaceholder) { + var placeholderChoice = this._store.choices.reverse().find(function (choice) { return !choice.disabled && choice.placeholder; }); + if (placeholderChoice) { + this._addItem(placeholderChoice); + if (placeholderChoice.value) { + this._triggerChange(placeholderChoice.value); + } + } + } + }; + Choices.prototype._handleItemAction = function (element, hasShiftKey) { + var _this = this; + if (hasShiftKey === void 0) { hasShiftKey = false; } + var items = this._store.items; + if (!items.length || !this.config.removeItems || this._isSelectOneElement) { + return; + } + var id = parseDataSetId(element); + if (!id) { + return; + } + // We only want to select one item with a click + // so we deselect any items that aren't the target + // unless shift is being pressed + items.forEach(function (item) { + if (item.id === id && !item.highlighted) { + _this.highlightItem(item); + } + else if (!hasShiftKey && item.highlighted) { + _this.unhighlightItem(item); + } + }); + // Focus input as without focus, a user cannot do anything with a + // highlighted item + this.input.focus(); + }; + Choices.prototype._handleChoiceAction = function (element) { + var _this = this; + // If we are clicking on an option + var id = parseDataSetId(element); + var choice = id && this._store.getChoiceById(id); + if (!choice || choice.disabled) { + return false; + } + var hasActiveDropdown = this.dropdown.isActive; + if (!choice.selected) { + if (!this._canAddItems()) { + return true; // causes _onEnterKey to early out + } + this._store.withTxn(function () { + _this._addItem(choice, true, true); + _this.clearInput(); + _this.unhighlightAll(); + }); + this._triggerChange(choice.value); + } + // We want to close the dropdown if we are dealing with a single select box + if (hasActiveDropdown && this.config.closeDropdownOnSelect) { + this.hideDropdown(true); + this.containerOuter.element.focus(); + } + return true; + }; + Choices.prototype._handleBackspace = function (items) { + var config = this.config; + if (!config.removeItems || !items.length) { + return; + } + var lastItem = items[items.length - 1]; + var hasHighlightedItems = items.some(function (item) { return item.highlighted; }); + // If editing the last item is allowed and there are not other selected items, + // we can edit the item value. Otherwise if we can remove items, remove all selected items + if (config.editItems && !hasHighlightedItems && lastItem) { + this.input.value = lastItem.value; + this.input.setWidth(); + this._removeItem(lastItem); + this._triggerChange(lastItem.value); + } + else { + if (!hasHighlightedItems) { + // Highlight last item if none already highlighted + this.highlightItem(lastItem, false); + } + this.removeHighlightedItems(true); + } + }; + Choices.prototype._loadChoices = function () { + var _a; + var config = this.config; + if (this._isTextElement) { + // Assign preset items from passed object first + this._presetChoices = config.items.map(function (e) { return mapInputToChoice(e, false); }); + // Add any values passed from attribute + var value = this.passedElement.value; + if (value) { + var elementItems = value + .split(config.delimiter) + .map(function (e) { return mapInputToChoice(e, false); }); + this._presetChoices = this._presetChoices.concat(elementItems); + } + this._presetChoices.forEach(function (choice) { + choice.selected = true; + }); + } + else if (this._isSelectElement) { + // Assign preset choices from passed object + this._presetChoices = config.choices.map(function (e) { return mapInputToChoice(e, true); }); + // Create array of choices from option elements + var choicesFromOptions = this.passedElement.optionsAsChoices(); + if (choicesFromOptions) { + (_a = this._presetChoices).push.apply(_a, choicesFromOptions); + } + } + }; + Choices.prototype._handleLoadingState = function (setLoading) { + if (setLoading === void 0) { setLoading = true; } + var config = this.config; + if (setLoading) { + this.disable(); + this.containerOuter.addLoadingState(); + if (this._isSelectOneElement) { + this.itemList.clear(); + this.itemList.element.append(this._templates.placeholder(config, config.loadingText)); + } + else { + this.input.placeholder = config.loadingText; + } + } + else { + this.enable(); + this.containerOuter.removeLoadingState(); + if (!this._isSelectOneElement) { + this.input.placeholder = this._placeholderValue || ''; + } + } + }; + Choices.prototype._handleSearch = function (value) { + if (!this.input.isFocussed) { + return; + } + var choices = this._store.choices; + var _a = this.config, searchFloor = _a.searchFloor, searchChoices = _a.searchChoices; + var hasUnactiveChoices = choices.some(function (option) { return !option.active; }); + // Check that we have a value to search and the input was an alphanumeric character + if (value !== null && typeof value !== 'undefined' && value.length >= searchFloor) { + var resultCount = searchChoices ? this._searchChoices(value) : 0; + if (resultCount !== null) { + // Trigger search event + this.passedElement.triggerEvent("search" /* EventType.search */, { + value: value, + resultCount: resultCount, + }); + } + } + else if (hasUnactiveChoices) { + this._stopSearch(); + } + }; + Choices.prototype._canAddItems = function () { + var config = this.config; + var maxItemCount = config.maxItemCount, maxItemText = config.maxItemText; + if (!config.singleModeForMultiSelect && maxItemCount > 0 && maxItemCount <= this._store.items.length) { + this._displayNotice(typeof maxItemText === 'function' ? maxItemText(maxItemCount) : maxItemText, NoticeTypes.addChoice); + return false; + } + return true; + }; + Choices.prototype._canCreateItem = function (value) { + var config = this.config; + var canAddItem = true; + var notice = ''; + if (canAddItem && typeof config.addItemFilter === 'function' && !config.addItemFilter(value)) { + canAddItem = false; + notice = resolveNoticeFunction(config.customAddItemText, value); + } + if (canAddItem) { + var foundChoice = this._store.choices.find(function (choice) { return config.valueComparer(choice.value, value); }); + if (this._isSelectElement) { + // for exact matches, do not prompt to add it as a custom choice + if (foundChoice) { + this._displayNotice('', NoticeTypes.addChoice); + return false; + } + } + else if (this._isTextElement && !config.duplicateItemsAllowed) { + if (foundChoice) { + canAddItem = false; + notice = resolveNoticeFunction(config.uniqueItemText, value); + } + } + } + if (canAddItem) { + notice = resolveNoticeFunction(config.addItemText, value); + } + if (notice) { + this._displayNotice(notice, NoticeTypes.addChoice); + } + return canAddItem; + }; + Choices.prototype._searchChoices = function (value) { + var newValue = value.trim().replace(/\s{2,}/, ' '); + // signal input didn't change search + if (!newValue.length || newValue === this._currentValue) { + return null; + } + var searcher = this._searcher; + if (searcher.isEmptyIndex()) { + searcher.index(this._store.searchableChoices); + } + // If new value matches the desired length and is not the same as the current value with a space + var results = searcher.search(newValue); + this._currentValue = newValue; + this._highlightPosition = 0; + this._isSearching = true; + var notice = this._notice; + var noticeType = notice && notice.type; + if (noticeType !== NoticeTypes.addChoice) { + if (!results.length) { + this._displayNotice(resolveStringFunction(this.config.noResultsText), NoticeTypes.noResults); + } + else if (noticeType === NoticeTypes.noResults) { + this._clearNotice(); + } + } + this._store.dispatch(filterChoices(results)); + return results.length; + }; + Choices.prototype._stopSearch = function () { + var wasSearching = this._isSearching; + this._currentValue = ''; + this._isSearching = false; + if (wasSearching) { + this._store.dispatch(activateChoices(true)); + this.passedElement.triggerEvent("search" /* EventType.search */, { + value: '', + resultCount: 0, + }); + } + }; + Choices.prototype._addEventListeners = function () { + var documentElement = this._docRoot; + var outerElement = this.containerOuter.element; + var inputElement = this.input.element; + // capture events - can cancel event processing or propagation + documentElement.addEventListener('touchend', this._onTouchEnd, true); + outerElement.addEventListener('keydown', this._onKeyDown, true); + outerElement.addEventListener('mousedown', this._onMouseDown, true); + // passive events - doesn't call `preventDefault` or `stopPropagation` + documentElement.addEventListener('click', this._onClick, { passive: true }); + documentElement.addEventListener('touchmove', this._onTouchMove, { + passive: true, + }); + this.dropdown.element.addEventListener('mouseover', this._onMouseOver, { + passive: true, + }); + if (this._isSelectOneElement) { + outerElement.addEventListener('focus', this._onFocus, { + passive: true, + }); + outerElement.addEventListener('blur', this._onBlur, { + passive: true, + }); + } + inputElement.addEventListener('keyup', this._onKeyUp, { + passive: true, + }); + inputElement.addEventListener('input', this._onInput, { + passive: true, + }); + inputElement.addEventListener('focus', this._onFocus, { + passive: true, + }); + inputElement.addEventListener('blur', this._onBlur, { + passive: true, + }); + if (inputElement.form) { + inputElement.form.addEventListener('reset', this._onFormReset, { + passive: true, + }); + } + this.input.addEventListeners(); + }; + Choices.prototype._removeEventListeners = function () { + var documentElement = this._docRoot; + var outerElement = this.containerOuter.element; + var inputElement = this.input.element; + documentElement.removeEventListener('touchend', this._onTouchEnd, true); + outerElement.removeEventListener('keydown', this._onKeyDown, true); + outerElement.removeEventListener('mousedown', this._onMouseDown, true); + documentElement.removeEventListener('click', this._onClick); + documentElement.removeEventListener('touchmove', this._onTouchMove); + this.dropdown.element.removeEventListener('mouseover', this._onMouseOver); + if (this._isSelectOneElement) { + outerElement.removeEventListener('focus', this._onFocus); + outerElement.removeEventListener('blur', this._onBlur); + } + inputElement.removeEventListener('keyup', this._onKeyUp); + inputElement.removeEventListener('input', this._onInput); + inputElement.removeEventListener('focus', this._onFocus); + inputElement.removeEventListener('blur', this._onBlur); + if (inputElement.form) { + inputElement.form.removeEventListener('reset', this._onFormReset); + } + this.input.removeEventListeners(); + }; + Choices.prototype._onKeyDown = function (event) { + var keyCode = event.keyCode; + var items = this._store.items; + var hasFocusedInput = this.input.isFocussed; + var hasActiveDropdown = this.dropdown.isActive; + var hasItems = this.itemList.element.hasChildNodes(); + /* + See: + https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key + https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values + https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF - UTF-16 surrogate pairs + https://stackoverflow.com/a/70866532 - "Unidentified" for mobile + http://www.unicode.org/versions/Unicode5.2.0/ch16.pdf#G19635 - U+FFFF is reserved (Section 16.7) + + Logic: when a key event is sent, `event.key` represents its printable value _or_ one + of a large list of special values indicating meta keys/functionality. In addition, + key events for compose functionality contain a value of `Dead` when mid-composition. + + I can't quite verify it, but non-English IMEs may also be able to generate key codes + for code points in the surrogate-pair range, which could potentially be seen as having + key.length > 1. Since `Fn` is one of the special keys, we can't distinguish by that + alone. + + Here, key.length === 1 means we know for sure the input was printable and not a special + `key` value. When the length is greater than 1, it could be either a printable surrogate + pair or a special `key` value. We can tell the difference by checking if the _character + code_ value (not code point!) is in the "surrogate pair" range or not. + + We don't use .codePointAt because an invalid code point would return 65535, which wouldn't + pass the >= 0x10000 check we would otherwise use. + + > ...The Unicode Standard sets aside 66 noncharacter code points. The last two code points + > of each plane are noncharacters: U+FFFE and U+FFFF on the BMP... + */ + var wasPrintableChar = event.key.length === 1 || + (event.key.length === 2 && event.key.charCodeAt(0) >= 0xd800) || + event.key === 'Unidentified'; + if (!this._isTextElement && !hasActiveDropdown) { + this.showDropdown(); + if (!this.input.isFocussed && wasPrintableChar) { + /* + We update the input value with the pressed key as + the input was not focussed at the time of key press + therefore does not have the value of the key. + */ + this.input.value += event.key; + // browsers interpret a space as pagedown + if (event.key === ' ') { + event.preventDefault(); + } + } + } + switch (keyCode) { + case 65 /* KeyCodeMap.A_KEY */: + return this._onSelectKey(event, hasItems); + case 13 /* KeyCodeMap.ENTER_KEY */: + return this._onEnterKey(event, hasActiveDropdown); + case 27 /* KeyCodeMap.ESC_KEY */: + return this._onEscapeKey(event, hasActiveDropdown); + case 38 /* KeyCodeMap.UP_KEY */: + case 33 /* KeyCodeMap.PAGE_UP_KEY */: + case 40 /* KeyCodeMap.DOWN_KEY */: + case 34 /* KeyCodeMap.PAGE_DOWN_KEY */: + return this._onDirectionKey(event, hasActiveDropdown); + case 8 /* KeyCodeMap.DELETE_KEY */: + case 46 /* KeyCodeMap.BACK_KEY */: + return this._onDeleteKey(event, items, hasFocusedInput); + } + }; + Choices.prototype._onKeyUp = function ( /* event: KeyboardEvent */) { + this._canSearch = this.config.searchEnabled; + }; + Choices.prototype._onInput = function ( /* event: InputEvent */) { + var value = this.input.value; + if (!value) { + if (this._isTextElement) { + this.hideDropdown(true); + } + else { + this._stopSearch(); + } + this._clearNotice(); + return; + } + if (!this._canAddItems()) { + return; + } + if (this._canSearch) { + // do the search even if the entered text can not be added + this._handleSearch(value); + } + if (!this._canAddUserChoices) { + return; + } + // determine if a notice needs to be displayed for why a search result can't be added + this._canCreateItem(value); + if (this._isSelectElement) { + this._highlightPosition = 0; // reset to select the notice and/or exact match + this._highlightChoice(); + } + }; + Choices.prototype._onSelectKey = function (event, hasItems) { + var ctrlKey = event.ctrlKey, metaKey = event.metaKey; + var hasCtrlDownKeyPressed = ctrlKey || metaKey; + // If CTRL + A or CMD + A have been pressed and there are items to select + if (hasCtrlDownKeyPressed && hasItems) { + this._canSearch = false; + var shouldHightlightAll = this.config.removeItems && !this.input.value && this.input.element === document.activeElement; + if (shouldHightlightAll) { + this.highlightAll(); + } + } + }; + Choices.prototype._onEnterKey = function (event, hasActiveDropdown) { + var _this = this; + var config = this.config; + var value = this.input.value; + var target = event.target; + var targetWasRemoveButton = target && target.hasAttribute('data-button'); + event.preventDefault(); + if (targetWasRemoveButton) { + this._handleButtonAction(target); + return; + } + if (!hasActiveDropdown) { + if (this._isSelectElement || this._notice) { + this.showDropdown(); + } + return; + } + var highlightedChoice = this.dropdown.element.querySelector(getClassNamesSelector(config.classNames.highlightedState)); + if (highlightedChoice && this._handleChoiceAction(highlightedChoice)) { + return; + } + if (!target || !value) { + this.hideDropdown(true); + return; + } + if (!this._canAddItems()) { + return; + } + var addedItem = false; + this._store.withTxn(function () { + addedItem = _this._findAndSelectChoiceByValue(value, true); + if (!addedItem) { + if (!_this._canAddUserChoices) { + return; + } + if (!_this._canCreateItem(value)) { + return; + } + var sanitisedValue = sanitise(value); + var userValue = config.allowHtmlUserInput || sanitisedValue === value ? value : { escaped: sanitisedValue, raw: value }; + _this._addChoice(mapInputToChoice({ + value: userValue, + label: userValue, + selected: true, + }, false), true, true); + addedItem = true; + } + _this.clearInput(); + _this.unhighlightAll(); + }); + if (!addedItem) { + return; + } + this._triggerChange(value); + if (config.closeDropdownOnSelect) { + this.hideDropdown(true); + } + }; + Choices.prototype._onEscapeKey = function (event, hasActiveDropdown) { + if (hasActiveDropdown) { + event.stopPropagation(); + this.hideDropdown(true); + this.containerOuter.element.focus(); + } + }; + Choices.prototype._onDirectionKey = function (event, hasActiveDropdown) { + var keyCode = event.keyCode, metaKey = event.metaKey; + // If up or down key is pressed, traverse through options + if (hasActiveDropdown || this._isSelectOneElement) { + this.showDropdown(); + this._canSearch = false; + var directionInt = keyCode === 40 /* KeyCodeMap.DOWN_KEY */ || keyCode === 34 /* KeyCodeMap.PAGE_DOWN_KEY */ ? 1 : -1; + var skipKey = metaKey || keyCode === 34 /* KeyCodeMap.PAGE_DOWN_KEY */ || keyCode === 33 /* KeyCodeMap.PAGE_UP_KEY */; + var selectableChoiceIdentifier = '[data-choice-selectable]'; + var nextEl = void 0; + if (skipKey) { + if (directionInt > 0) { + nextEl = this.dropdown.element.querySelector("".concat(selectableChoiceIdentifier, ":last-of-type")); + } + else { + nextEl = this.dropdown.element.querySelector(selectableChoiceIdentifier); + } + } + else { + var currentEl = this.dropdown.element.querySelector(getClassNamesSelector(this.config.classNames.highlightedState)); + if (currentEl) { + nextEl = getAdjacentEl(currentEl, selectableChoiceIdentifier, directionInt); + } + else { + nextEl = this.dropdown.element.querySelector(selectableChoiceIdentifier); + } + } + if (nextEl) { + // We prevent default to stop the cursor moving + // when pressing the arrow + if (!isScrolledIntoView(nextEl, this.choiceList.element, directionInt)) { + this.choiceList.scrollToChildElement(nextEl, directionInt); + } + this._highlightChoice(nextEl); + } + // Prevent default to maintain cursor position whilst + // traversing dropdown options + event.preventDefault(); + } + }; + Choices.prototype._onDeleteKey = function (event, items, hasFocusedInput) { + var target = event.target; + // If backspace or delete key is pressed and the input has no value + if (!this._isSelectOneElement && !target.value && hasFocusedInput) { + this._handleBackspace(items); + event.preventDefault(); + } + }; + Choices.prototype._onTouchMove = function () { + if (this._wasTap) { + this._wasTap = false; + } + }; + Choices.prototype._onTouchEnd = function (event) { + var target = (event || event.touches[0]).target; + var touchWasWithinContainer = this._wasTap && this.containerOuter.element.contains(target); + if (touchWasWithinContainer) { + var containerWasExactTarget = target === this.containerOuter.element || target === this.containerInner.element; + if (containerWasExactTarget) { + if (this._isTextElement) { + this.input.focus(); + } + else if (this._isSelectMultipleElement) { + this.showDropdown(); + } + } + // Prevents focus event firing + event.stopPropagation(); + } + this._wasTap = true; + }; + /** + * Handles mousedown event in capture mode for containetOuter.element + */ + Choices.prototype._onMouseDown = function (event) { + var target = event.target; + if (!(target instanceof HTMLElement)) { + return; + } + // If we have our mouse down on the scrollbar and are on IE11... + if (IS_IE11 && this.choiceList.element.contains(target)) { + // check if click was on a scrollbar area + var firstChoice = this.choiceList.element.firstElementChild; + this._isScrollingOnIe = + this._direction === 'ltr' ? event.offsetX >= firstChoice.offsetWidth : event.offsetX < firstChoice.offsetLeft; + } + if (target === this.input.element) { + return; + } + var item = target.closest('[data-button],[data-item],[data-choice]'); + if (item instanceof HTMLElement) { + var hasShiftKey = event.shiftKey; + var dataset = item.dataset; + if ('button' in dataset) { + this._handleButtonAction(item); + } + else if ('item' in dataset) { + this._handleItemAction(item, hasShiftKey); + } + else if ('choice' in dataset) { + this._handleChoiceAction(item); + } + } + event.preventDefault(); + }; + /** + * Handles mouseover event over this.dropdown + * @param {MouseEvent} event + */ + Choices.prototype._onMouseOver = function (_a) { + var target = _a.target; + if (target instanceof HTMLElement && 'choice' in target.dataset) { + this._highlightChoice(target); + } + }; + Choices.prototype._onClick = function (_a) { + var target = _a.target; + var containerOuter = this.containerOuter; + var clickWasWithinContainer = containerOuter.element.contains(target); + if (clickWasWithinContainer) { + if (!this.dropdown.isActive && !this.containerOuter.isDisabled) { + if (this._isTextElement) { + if (document.activeElement !== this.input.element) { + this.input.focus(); + } + } + else { + this.showDropdown(); + containerOuter.element.focus(); + } + } + else if (this._isSelectOneElement && + target !== this.input.element && + !this.dropdown.element.contains(target)) { + this.hideDropdown(); + } + } + else { + var hasHighlightedItems = !!this._store.highlightedActiveItems.length; + if (hasHighlightedItems) { + this.unhighlightAll(); + } + containerOuter.removeFocusState(); + this.hideDropdown(true); + } + }; + Choices.prototype._onFocus = function (_a) { + var _b; + var _this = this; + var target = _a.target; + var containerOuter = this.containerOuter; + var focusWasWithinContainer = target && containerOuter.element.contains(target); + if (!focusWasWithinContainer) { + return; + } + var targetIsInput = target === this.input.element; + var focusActions = (_b = {}, + _b[TEXT_TYPE] = function () { + if (targetIsInput) { + containerOuter.addFocusState(); + } + }, + _b[SELECT_ONE_TYPE] = function () { + containerOuter.addFocusState(); + if (targetIsInput) { + _this.showDropdown(true); + } + }, + _b[SELECT_MULTIPLE_TYPE] = function () { + if (targetIsInput) { + _this.showDropdown(true); + // If element is a select box, the focused element is the container and the dropdown + // isn't already open, focus and show dropdown + containerOuter.addFocusState(); + } + }, + _b); + focusActions[this._elementType](); + }; + Choices.prototype._onBlur = function (_a) { + var _b; + var _this = this; + var target = _a.target; + var containerOuter = this.containerOuter; + var blurWasWithinContainer = target && containerOuter.element.contains(target); + if (blurWasWithinContainer && !this._isScrollingOnIe) { + var activeChoices = this._store.activeChoices; + var hasHighlightedItems_1 = activeChoices.some(function (item) { return item.highlighted; }); + var targetIsInput_1 = target === this.input.element; + var blurActions = (_b = {}, + _b[TEXT_TYPE] = function () { + if (targetIsInput_1) { + containerOuter.removeFocusState(); + if (hasHighlightedItems_1) { + _this.unhighlightAll(); + } + _this.hideDropdown(true); + } + }, + _b[SELECT_ONE_TYPE] = function () { + containerOuter.removeFocusState(); + if (targetIsInput_1 || (target === containerOuter.element && !_this._canSearch)) { + _this.hideDropdown(true); + } + }, + _b[SELECT_MULTIPLE_TYPE] = function () { + if (targetIsInput_1) { + containerOuter.removeFocusState(); + _this.hideDropdown(true); + if (hasHighlightedItems_1) { + _this.unhighlightAll(); + } + } + }, + _b); + blurActions[this._elementType](); + } + else { + // On IE11, clicking the scollbar blurs our input and thus + // closes the dropdown. To stop this, we refocus our input + // if we know we are on IE *and* are scrolling. + this._isScrollingOnIe = false; + this.input.element.focus(); + } + }; + Choices.prototype._onFormReset = function () { + var _this = this; + this._store.withTxn(function () { + _this.clearInput(); + _this.hideDropdown(); + _this.refresh(false, false, true); + if (_this._initialItems.length) { + _this.setChoiceByValue(_this._initialItems); + } + }); + }; + Choices.prototype._highlightChoice = function (el) { + var _a; + if (el === void 0) { el = null; } + var highlightedState = this.config.classNames.highlightedState; + var choices = Array.from(this.dropdown.element.querySelectorAll('[data-choice-selectable]')); + if (!choices.length) { + return; + } + var passedEl = el; + var highlightedChoices = Array.from(this.dropdown.element.querySelectorAll(getClassNamesSelector(highlightedState))); + // Remove any highlighted choices + highlightedChoices.forEach(function (choice) { + var _a; + (_a = choice.classList).remove.apply(_a, getClassNames(highlightedState)); + choice.setAttribute('aria-selected', 'false'); + }); + if (passedEl) { + this._highlightPosition = choices.indexOf(passedEl); + } + else { + // Highlight choice based on last known highlight location + if (choices.length > this._highlightPosition) { + // If we have an option to highlight + passedEl = choices[this._highlightPosition]; + } + else { + // Otherwise highlight the option before + passedEl = choices[choices.length - 1]; + } + if (!passedEl) { + passedEl = choices[0]; + } + } + (_a = passedEl.classList).add.apply(_a, getClassNames(highlightedState)); + passedEl.setAttribute('aria-selected', 'true'); + this.passedElement.triggerEvent("highlightChoice" /* EventType.highlightChoice */, { + el: passedEl, + }); + if (this.dropdown.isActive) { + // IE11 ignores aria-label and blocks virtual keyboard + // if aria-activedescendant is set without a dropdown + this.input.setActiveDescendant(passedEl.id); + this.containerOuter.setActiveDescendant(passedEl.id); + } + }; + Choices.prototype._addItem = function (item, withEvents, userTriggered) { + if (withEvents === void 0) { withEvents = true; } + if (userTriggered === void 0) { userTriggered = false; } + var id = item.id; + if (!id) { + throw new TypeError('item.id must be set before _addItem is called for a choice/item'); + } + if (this.config.singleModeForMultiSelect || this._isSelectOneElement) { + this.removeActiveItems(id); + } + this._store.dispatch(addItem(item)); + if (withEvents) { + this.passedElement.triggerEvent("addItem" /* EventType.addItem */, this._getChoiceForOutput(item)); + if (userTriggered) { + this.passedElement.triggerEvent("choice" /* EventType.choice */, this._getChoiceForOutput(item)); + } + } + }; + Choices.prototype._removeItem = function (item) { + var id = item.id; + if (!id) { + return; + } + this._store.dispatch(removeItem(item)); + this.passedElement.triggerEvent("removeItem" /* EventType.removeItem */, this._getChoiceForOutput(item)); + }; + Choices.prototype._addChoice = function (choice, withEvents, userTriggered) { + if (withEvents === void 0) { withEvents = true; } + if (userTriggered === void 0) { userTriggered = false; } + if (choice.id) { + throw new TypeError('Can not re-add a choice which has already been added'); + } + // Generate unique id, in-place update is required so chaining _addItem works as expected + this._lastAddedChoiceId++; + choice.id = this._lastAddedChoiceId; + choice.elementId = "".concat(this._baseId, "-").concat(this._idNames.itemChoice, "-").concat(choice.id); + var _a = this.config, prependValue = _a.prependValue, appendValue = _a.appendValue; + if (prependValue) { + choice.value = prependValue + choice.value; + } + if (appendValue) { + choice.value += appendValue.toString(); + } + if ((prependValue || appendValue) && choice.element) { + choice.element.value = choice.value; + } + this._store.dispatch(addChoice(choice)); + if (choice.selected) { + this._addItem(choice, withEvents, userTriggered); + } + }; + Choices.prototype._addGroup = function (group, withEvents) { + var _this = this; + if (withEvents === void 0) { withEvents = true; } + if (group.id) { + throw new TypeError('Can not re-add a group which has already been added'); + } + this._store.dispatch(addGroup(group)); + if (!group.choices) { + return; + } + // add unique id for the group(s), and do not store the full list of choices in this group + var g = group; + this._lastAddedGroupId++; + g.id = this._lastAddedGroupId; + var id = group.id, choices = group.choices; + g.choices = []; + choices.forEach(function (item) { + item.groupId = id; + if (group.disabled) { + item.disabled = true; + } + _this._addChoice(item, withEvents); + }); + }; + Choices.prototype._createTemplates = function () { + var _this = this; + var callbackOnCreateTemplates = this.config.callbackOnCreateTemplates; + var userTemplates = {}; + if (callbackOnCreateTemplates && typeof callbackOnCreateTemplates === 'function') { + userTemplates = callbackOnCreateTemplates.call(this, strToEl, escapeForTemplate); + } + var templating = {}; + Object.keys(this._templates).forEach(function (name) { + if (name in userTemplates) { + templating[name] = userTemplates[name].bind(_this); + } + else { + templating[name] = _this._templates[name].bind(_this); + } + }); + this._templates = templating; + }; + Choices.prototype._createElements = function () { + var templating = this._templates; + var config = this.config; + var position = config.position, classNames = config.classNames; + var elementType = this._elementType; + this.containerOuter = new Container({ + element: templating.containerOuter(config, this._direction, this._isSelectElement, this._isSelectOneElement, config.searchEnabled, elementType, config.labelId), + classNames: classNames, + type: elementType, + position: position, + }); + this.containerInner = new Container({ + element: templating.containerInner(config), + classNames: classNames, + type: elementType, + position: position, + }); + this.input = new Input({ + element: templating.input(config, this._placeholderValue), + classNames: classNames, + type: elementType, + preventPaste: !config.paste, + }); + this.choiceList = new List({ + element: templating.choiceList(config, this._isSelectOneElement), + }); + this.itemList = new List({ + element: templating.itemList(config, this._isSelectOneElement), + }); + this.dropdown = new Dropdown({ + element: templating.dropdown(config), + classNames: classNames, + type: elementType, + }); + }; + Choices.prototype._createStructure = function () { + var _a = this, containerInner = _a.containerInner, containerOuter = _a.containerOuter, passedElement = _a.passedElement, dropdown = _a.dropdown, input = _a.input; + // Hide original element + passedElement.conceal(); + // Wrap input in container preserving DOM ordering + containerInner.wrap(passedElement.element); + // Wrapper inner container with outer container + containerOuter.wrap(containerInner.element); + if (this._isSelectOneElement) { + input.placeholder = this.config.searchPlaceholderValue || ''; + } + else { + if (this._placeholderValue) { + input.placeholder = this._placeholderValue; + } + input.setWidth(); + } + containerOuter.element.appendChild(containerInner.element); + containerOuter.element.appendChild(dropdown.element); + containerInner.element.appendChild(this.itemList.element); + dropdown.element.appendChild(this.choiceList.element); + if (!this._isSelectOneElement) { + containerInner.element.appendChild(input.element); + } + else if (this.config.searchEnabled) { + dropdown.element.insertBefore(input.element, dropdown.element.firstChild); + } + this._highlightPosition = 0; + this._isSearching = false; + }; + Choices.prototype._initStore = function () { + var _this = this; + this._store.subscribe(this._render); + this._store.withTxn(function () { + _this._addPredefinedChoices(_this._presetChoices, _this._isSelectOneElement && !_this._hasNonChoicePlaceholder, false); + }); + if (this._isSelectOneElement && this._hasNonChoicePlaceholder) { + this._render({ choices: false, groups: false, items: true }); + } + }; + Choices.prototype._addPredefinedChoices = function (choices, selectFirstOption, withEvents) { + var _this = this; + if (selectFirstOption === void 0) { selectFirstOption = false; } + if (withEvents === void 0) { withEvents = true; } + if (selectFirstOption) { + /** + * If there is a selected choice already or the choice is not the first in + * the array, add each choice normally. + * + * Otherwise we pre-select the first enabled choice in the array ("select-one" only) + */ + var noSelectedChoices = choices.findIndex(function (choice) { return choice.selected; }) === -1; + if (noSelectedChoices) { + choices.some(function (choice) { + if (choice.disabled || 'choices' in choice) { + return false; + } + choice.selected = true; + return true; + }); + } + } + choices.forEach(function (item) { + if ('choices' in item) { + if (_this._isSelectElement) { + _this._addGroup(item, withEvents); + } + } + else { + _this._addChoice(item, withEvents); + } + }); + }; + Choices.prototype._findAndSelectChoiceByValue = function (value, userTriggered) { + var _this = this; + if (userTriggered === void 0) { userTriggered = false; } + var choices = this._store.choices; + // Check 'value' property exists and the choice isn't already selected + var foundChoice = choices.find(function (choice) { return _this.config.valueComparer(choice.value, value); }); + if (foundChoice && !foundChoice.disabled && !foundChoice.selected) { + this._addItem(foundChoice, true, userTriggered); + return true; + } + return false; + }; + Choices.prototype._generatePlaceholderValue = function () { + var config = this.config; + if (!config.placeholder) { + return null; + } + if (this._hasNonChoicePlaceholder) { + return config.placeholderValue; + } + if (this._isSelectElement) { + var placeholderOption = this.passedElement.placeholderOption; + return placeholderOption ? placeholderOption.text : null; + } + return null; + }; + Choices.prototype._warnChoicesInitFailed = function (caller) { + if (this.config.silent) { + return; + } + if (!this.initialised) { + throw new TypeError("".concat(caller, " called on a non-initialised instance of Choices")); + } + else if (!this.initialisedOK) { + throw new TypeError("".concat(caller, " called for an element which has multiple instances of Choices initialised on it")); + } + }; + Choices.version = '11.0.0-rc7'; + return Choices; + }()); + + return Choices; + +})); diff --git a/assets/scripts/choices.search-basic.min.js b/assets/scripts/choices.search-basic.min.js new file mode 100644 index 00000000..a33f1223 --- /dev/null +++ b/assets/scripts/choices.search-basic.min.js @@ -0,0 +1,2 @@ +/*! choices.js v11.0.0-rc7 | © 2024 Josh Johnson | https://github.com/jshjohnson/Choices#readme */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Choices=t()}(this,(function(){"use strict";var e=function(t,i){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i])},e(t,i)};function t(t,i){if("function"!=typeof i&&null!==i)throw new TypeError("Class extends value "+String(i)+" is not a constructor or null");function n(){this.constructor=t}e(t,i),t.prototype=null===i?Object.create(i):(n.prototype=i.prototype,new n)}var i=function(){return i=Object.assign||function(e){for(var t,i=1,n=arguments.length;i/g,">").replace(/0?this.element.scrollTop+(e.offsetTop+e.offsetHeight)-(this.element.scrollTop+this.element.offsetHeight):e.offsetTop;requestAnimationFrame((function(){i._animateScroll(n,t)}))}},e.prototype._scrollDown=function(e,t,i){var n=(i-e)/t;this.element.scrollTop=e+(n>1?n:1)},e.prototype._scrollUp=function(e,t,i){var n=(e-i)/t;this.element.scrollTop=e-(n>1?n:1)},e.prototype._animateScroll=function(e,t){var i=this,n=this.element.scrollTop,s=!1;t>0?(this._scrollDown(n,4,e),ne&&(s=!0)),s&&requestAnimationFrame((function(){i._animateScroll(e,t)}))},e}(),k=function(){function e(e){var t=e.classNames;this.element=e.element,this.classNames=t,this.isDisabled=!1}return Object.defineProperty(e.prototype,"isActive",{get:function(){return"active"===this.element.dataset.choice},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"dir",{get:function(){return this.element.dir},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"value",{get:function(){return this.element.value},set:function(e){this.element.setAttribute("value",e),this.element.value=e},enumerable:!1,configurable:!0}),e.prototype.conceal=function(){var e,t=this.element;(e=t.classList).add.apply(e,I(this.classNames.input)),t.hidden=!0,t.tabIndex=-1;var i=t.getAttribute("style");i&&t.setAttribute("data-choice-orig-style",i),t.setAttribute("data-choice","active")},e.prototype.reveal=function(){var e,t=this.element;(e=t.classList).remove.apply(e,I(this.classNames.input)),t.hidden=!1,t.removeAttribute("tabindex");var i=t.getAttribute("data-choice-orig-style");i?(t.removeAttribute("data-choice-orig-style"),t.setAttribute("style",i)):t.removeAttribute("style"),t.removeAttribute("data-choice")},e.prototype.enable=function(){var e=this.element;e.removeAttribute("disabled"),e.disabled=!1,this.isDisabled=!1},e.prototype.disable=function(){var e=this.element;e.setAttribute("disabled",""),e.disabled=!0,this.isDisabled=!0},e.prototype.triggerEvent=function(e,t){var i;void 0===(i=t||{})&&(i=null),this.element.dispatchEvent(new CustomEvent(e,{detail:i,bubbles:!0,cancelable:!0}))},e}(),P=function(e){function i(){return null!==e&&e.apply(this,arguments)||this}return t(i,e),i}(k),j=function(e,t){return void 0===t&&(t=!0),void 0===e?t:!!e},K=function(e){if("string"==typeof e&&(e=e.split(" ").filter((function(e){return e.length}))),Array.isArray(e)&&e.length)return e},B=function(e,t){if("string"==typeof e)return B({value:e,label:e},!1);var i=e;if("choices"in i){if(!t)throw new TypeError("optGroup is not allowed");var n=i,s=n.choices.map((function(e){return B(e,!1)}));return{id:0,label:E(n.label)||n.value,active:!!s.length,disabled:!!n.disabled,choices:s}}var o=i;return{id:0,groupId:0,score:0,rank:0,value:o.value,label:o.label||o.value,active:j(o.active),selected:j(o.selected,!1),disabled:j(o.disabled,!1),placeholder:j(o.placeholder,!1),highlighted:!1,labelClass:K(o.labelClass),labelDescription:o.labelDescription,customProperties:o.customProperties}},H=function(e){return"SELECT"===e.tagName},V=function(e){function i(t){var i=t.template,n=t.extractPlaceholder,s=e.call(this,{element:t.element,classNames:t.classNames})||this;return s.template=i,s.extractPlaceholder=n,s}return t(i,e),Object.defineProperty(i.prototype,"placeholderOption",{get:function(){return this.element.querySelector('option[value=""]')||this.element.querySelector("option[placeholder]")},enumerable:!1,configurable:!0}),i.prototype.addOptions=function(e){var t=this,i=document.createDocumentFragment();e.forEach((function(e){var n=e;if(!n.element){var s=t.template(n);i.appendChild(s),n.element=s}})),this.element.appendChild(i)},i.prototype.optionsAsChoices=function(){var e=this,t=[];return this.element.querySelectorAll(":scope > option, :scope > optgroup").forEach((function(i){!function(e){return"OPTION"===e.tagName}(i)?function(e){return"OPTGROUP"===e.tagName}(i)&&t.push(e._optgroupToChoice(i)):t.push(e._optionToChoice(i))})),t},i.prototype._optionToChoice=function(e){!e.hasAttribute("value")&&e.hasAttribute("placeholder")&&(e.setAttribute("value",""),e.value="");var t=e.dataset;return{id:0,groupId:0,score:0,rank:0,value:e.value,label:e.innerHTML,element:e,active:!0,selected:this.extractPlaceholder?e.selected:e.hasAttribute("selected"),disabled:e.disabled,highlighted:!1,placeholder:this.extractPlaceholder&&(!e.value||e.hasAttribute("placeholder")),labelClass:void 0!==t.labelClass?K(t.labelClass):void 0,labelDescription:void 0!==t.labelDescription?t.labelDescription:void 0,customProperties:O(t.customProperties)}},i.prototype._optgroupToChoice=function(e){var t=this,i=e.querySelectorAll("option"),n=Array.from(i).map((function(e){return t._optionToChoice(e)}));return{id:0,label:e.label||"",element:e,active:!!n.length,disabled:e.disabled,choices:n}},i}(k),R={items:[],choices:[],silent:!1,renderChoiceLimit:-1,maxItemCount:-1,closeDropdownOnSelect:"auto",singleModeForMultiSelect:!1,addChoices:!1,addItems:!0,addItemFilter:function(e){return!!e&&""!==e},removeItems:!0,removeItemButton:!1,removeItemButtonAlignLeft:!1,editItems:!1,allowHTML:!1,allowHtmlUserInput:!1,duplicateItemsAllowed:!0,delimiter:",",paste:!0,searchEnabled:!0,searchChoices:!0,searchFloor:1,searchResultLimit:4,searchFields:["label","value"],position:"auto",resetScrollPosition:!0,shouldSort:!0,shouldSortItems:!1,sorter:function(e,t){var i=e.label,n=t.label,s=void 0===n?t.value:n;return E(void 0===i?e.value:i).localeCompare(E(s),[],{sensitivity:"base",ignorePunctuation:!0,numeric:!0})},shadowRoot:null,placeholder:!0,placeholderValue:null,searchPlaceholderValue:null,prependValue:null,appendValue:null,renderSelectedChoices:"auto",loadingText:"Loading...",noResultsText:"No results found",noChoicesText:"No choices to choose from",itemSelectText:"Press to select",uniqueItemText:"Only unique values can be added",customAddItemText:"Only values matching specific conditions can be added",addItemText:function(e){return'Press Enter to add "'.concat(e,'"')},removeItemIconText:function(){return"Remove item"},removeItemLabelText:function(e){return"Remove item: ".concat(e)},maxItemText:function(e){return"Only ".concat(e," values can be added")},valueComparer:function(e,t){return e===t},fuseOptions:{includeScore:!0},labelId:"",callbackOnInit:null,callbackOnCreateTemplates:null,classNames:{containerOuter:["choices"],containerInner:["choices__inner"],input:["choices__input"],inputCloned:["choices__input--cloned"],list:["choices__list"],listItems:["choices__list--multiple"],listSingle:["choices__list--single"],listDropdown:["choices__list--dropdown"],item:["choices__item"],itemSelectable:["choices__item--selectable"],itemDisabled:["choices__item--disabled"],itemChoice:["choices__item--choice"],description:["choices__description"],placeholder:["choices__placeholder"],group:["choices__group"],groupHeading:["choices__heading"],button:["choices__button"],activeState:["is-active"],focusState:["is-focused"],openState:["is-open"],disabledState:["is-disabled"],highlightedState:["is-highlighted"],selectedState:["is-selected"],flippedState:["is-flipped"],loadingState:["is-loading"],notice:["choices__notice"],addChoice:["choices__item--selectable","add-choice"],noResults:["has-no-results"],noChoices:["has-no-choices"]},appendGroupInSearch:!1},q={groups:function(e,t){var i=e,n=!0;switch(t.type){case h:i.push(t.group);break;case l:i=[];break;default:n=!1}return{state:i,update:n}},items:function(e,t){var i=e,n=!0;switch(t.type){case u:var s=t.item;s.selected=!0,(o=s.element)&&(o.selected=!0,o.setAttribute("selected","")),i.push(s),i.forEach((function(e){e.highlighted=!1}));break;case d:var o,a=t.item;if(a.selected=!1,o=a.element){o.selected=!1,o.removeAttribute("selected");var c=o.parentElement;c&&H(c)&&c.type===T&&(c.value="")}i=i.filter((function(e){return e.id!==a.id}));break;case r:i=i.filter((function(e){return e.id!==t.choice.id}));break;case p:var l=t;i.forEach((function(e){e.id===l.item.id&&(e.highlighted=l.highlighted)}));break;default:n=!1}return{state:i,update:n}},choices:function(e,t){var i=e,n=!0;switch(t.type){case o:i.push(t.choice);break;case r:i=i.filter((function(e){return e.id!==t.choice.id}));break;case u:case d:break;case a:var s=[];t.results.forEach((function(e){s[e.item.id]=e})),i.forEach((function(e){var t=s[e.id];void 0!==t?(e.score=t.score,e.rank=t.rank,e.active=!0):(e.score=0,e.rank=0,e.active=!1)}));break;case c:i.forEach((function(e){e.active=t.active}));break;case l:i=[];break;default:n=!1}return{state:i,update:n}}},G=function(){function e(){this._state=this.defaultState,this._listeners=[],this._txn=0}return Object.defineProperty(e.prototype,"defaultState",{get:function(){return{groups:[],items:[],choices:[]}},enumerable:!1,configurable:!0}),e.prototype.changeSet=function(e){return{groups:e,items:e,choices:e}},e.prototype.reset=function(){this._state=this.defaultState;var e=this.changeSet(!0);this._txn?this._changeSet=e:this._listeners.forEach((function(t){return t(e)}))},e.prototype.subscribe=function(e){this._listeners.push(e)},e.prototype.dispatch=function(e){var t=this._state,i=!1,n=this._changeSet||this.changeSet(!1);Object.keys(q).forEach((function(s){var o=q[s](t[s],e);o.update&&(i=!0,n[s]=!0,t[s]=o.state)})),i&&(this._txn?this._changeSet=n:this._listeners.forEach((function(e){return e(n)})))},e.prototype.withTxn=function(e){this._txn++;try{e()}finally{if(this._txn=Math.max(0,this._txn-1),!this._txn){var t=this._changeSet;t&&(this._changeSet=void 0,this._listeners.forEach((function(e){return e(t)})))}}},Object.defineProperty(e.prototype,"state",{get:function(){return this._state},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"items",{get:function(){return this.state.items},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"highlightedActiveItems",{get:function(){return this.items.filter((function(e){return!e.disabled&&e.active&&e.highlighted}))},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"choices",{get:function(){return this.state.choices},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"activeChoices",{get:function(){return this.choices.filter((function(e){return e.active}))},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"searchableChoices",{get:function(){return this.choices.filter((function(e){return!e.disabled&&!e.placeholder}))},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"groups",{get:function(){return this.state.groups},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"activeGroups",{get:function(){var e=this;return this.state.groups.filter((function(t){var i=t.active&&!t.disabled,n=e.state.choices.some((function(e){return e.active&&!e.disabled}));return i&&n}),[])},enumerable:!1,configurable:!0}),e.prototype.inTxn=function(){return this._txn>0},e.prototype.getChoiceById=function(e){return this.activeChoices.find((function(t){return t.id===e}))},e.prototype.getGroupById=function(e){return this.groups.find((function(t){return t.id===e}))},e}(),U="no-choices",W="no-results",$="add-choice";function J(e,t,i){return(t=function(e){var t=function(e){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var i=t.call(e,"string");if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}function z(e,t){var i=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),i.push.apply(i,n)}return i}function X(e){for(var t=1;t`Missing ${e} property in key`,oe=e=>`Property 'weight' in key '${e}' must be a positive integer`,re=Object.prototype.hasOwnProperty;class ae{constructor(e){this._keys=[],this._keyMap={};let t=0;e.forEach((e=>{let i=ce(e);this._keys.push(i),this._keyMap[i.id]=i,t+=i.weight})),this._keys.forEach((e=>{e.weight/=t}))}get(e){return this._keyMap[e]}keys(){return this._keys}toJSON(){return JSON.stringify(this._keys)}}function ce(e){let t=null,i=null,n=null,s=1,o=null;if(Y(e)||Q(e))n=e,t=le(e),i=he(e);else{if(!re.call(e,"name"))throw new Error(se("name"));const r=e.name;if(n=r,re.call(e,"weight")&&(s=e.weight,s<=0))throw new Error(oe(r));t=le(r),i=he(r),o=e.getFn}return{path:t,id:i,weight:s,src:n,getFn:o}}function le(e){return Q(e)?e:e.split(".")}function he(e){return Q(e)?e.join("."):e}const ue={useExtendedSearch:!1,getFn:function(e,t){let i=[],n=!1;const s=(e,t,o)=>{if(te(e))if(t[o]){const r=e[t[o]];if(!te(r))return;if(o===t.length-1&&(Y(r)||Z(r)||function(e){return!0===e||!1===e||function(e){return ee(e)&&null!==e}(e)&&"[object Boolean]"==ne(e)}(r)))i.push(function(e){return null==e?"":function(e){if("string"==typeof e)return e;let t=e+"";return"0"==t&&1/e==-1/0?"-0":t}(e)}(r));else if(Q(r)){n=!0;for(let e=0,i=r.length;ee.score===t.score?e.idx{this._keysMap[e.id]=t}))}create(){!this.isCreated&&this.docs.length&&(this.isCreated=!0,Y(this.docs[0])?this.docs.forEach(((e,t)=>{this._addString(e,t)})):this.docs.forEach(((e,t)=>{this._addObject(e,t)})),this.norm.clear())}add(e){const t=this.size();Y(e)?this._addString(e,t):this._addObject(e,t)}removeAt(e){this.records.splice(e,1);for(let t=e,i=this.size();t{let s=t.getFn?t.getFn(e):this.getFn(e,t.path);if(te(s))if(Q(s)){let e=[];const t=[{nestedArrIndex:-1,value:s}];for(;t.length;){const{nestedArrIndex:i,value:n}=t.pop();if(te(n))if(Y(n)&&!ie(n)){let t={v:n,i:i,n:this.norm.get(n)};e.push(t)}else Q(n)&&n.forEach(((e,i)=>{t.push({nestedArrIndex:i,value:e})}))}i.$[n]=e}else if(Y(s)&&!ie(s)){let e={v:s,n:this.norm.get(s)};i.$[n]=e}})),this.records.push(i)}toJSON(){return{keys:this.keys,records:this.records}}}function fe(e,t,{getFn:i=de.getFn,fieldNormWeight:n=de.fieldNormWeight}={}){const s=new me({getFn:i,fieldNormWeight:n});return s.setKeys(e.map(ce)),s.setSources(t),s.create(),s}function ve(e,{errors:t=0,currentLocation:i=0,expectedLocation:n=0,distance:s=de.distance,ignoreLocation:o=de.ignoreLocation}={}){const r=t/e.length;if(o)return r;const a=Math.abs(n-i);return s?r+a/s:a?1:r}const _e=32;function ge(e){let t={};for(let i=0,n=e.length;i{this.chunks.push({pattern:e,alphabet:ge(e),startIndex:t})},h=this.pattern.length;if(h>_e){let e=0;const t=h%_e,i=h-t;for(;e{const{isMatch:m,score:f,indices:v}=function(e,t,i,{location:n=de.location,distance:s=de.distance,threshold:o=de.threshold,findAllMatches:r=de.findAllMatches,minMatchCharLength:a=de.minMatchCharLength,includeMatches:c=de.includeMatches,ignoreLocation:l=de.ignoreLocation}={}){if(t.length>_e)throw new Error("Pattern length exceeds max of 32.");const h=t.length,u=e.length,d=Math.max(0,Math.min(n,u));let p=o,m=d;const f=a>1||c,v=f?Array(u):[];let _;for(;(_=e.indexOf(t,m))>-1;){let e=ve(t,{currentLocation:_,expectedLocation:d,distance:s,ignoreLocation:l});if(p=Math.min(e,p),m=_+h,f){let e=0;for(;e=c;o-=1){let r=o-1,a=i[e.charAt(r)];if(f&&(v[r]=+!!a),w[o]=(w[o+1]<<1|1)&a,n&&(w[o]|=(g[o+1]|g[o])<<1|1|g[o+1]),w[o]&E&&(y=ve(t,{errors:n,currentLocation:r,expectedLocation:d,distance:s,ignoreLocation:l}),y<=p)){if(p=y,m=r,m<=d)break;c=Math.max(1,2*d-m)}}if(ve(t,{errors:n+1,currentLocation:d,expectedLocation:d,distance:s,ignoreLocation:l})>p)break;g=w}const w={isMatch:m>=0,score:Math.max(.001,y)};if(f){const e=function(e=[],t=de.minMatchCharLength){let i=[],n=-1,s=-1,o=0;for(let r=e.length;o=t&&i.push([n,s]),n=-1)}return e[o-1]&&o-n>=t&&i.push([n,o-1]),i}(v,a);e.length?c&&(w.indices=e):w.isMatch=!1}return w}(e,t,d,{location:n+p,distance:s,threshold:o,findAllMatches:r,minMatchCharLength:a,includeMatches:i,ignoreLocation:c});m&&(u=!0),h+=f,m&&v&&(l=[...l,...v])}));let d={isMatch:u,score:u?h/this.chunks.length:1};return u&&i&&(d.indices=l),d}}const be=[];function Ee(e,t){for(let i=0,n=be.length;i!(!e[we]&&!e.$or),Ie=e=>({[we]:Object.keys(e).map((t=>({[t]:e[t]})))});function Ae(e,t){const i=e.matches;t.matches=[],te(i)&&i.forEach((e=>{if(!te(e.indices)||!e.indices.length)return;const{indices:i,value:n}=e;let s={indices:i,value:n};e.key&&(s.key=e.key.src),e.idx>-1&&(s.refIndex=e.idx),t.matches.push(s)}))}function Oe(e,t){t.score=e.score}class Le{constructor(e,t={},i){if(this.options=X(X({},de),t),this.options.useExtendedSearch)throw new Error("Extended search is not available");this._keyStore=new ae(this.options.keys),this.setCollection(e,i)}setCollection(e,t){if(this._docs=e,t&&!(t instanceof me))throw new Error("Incorrect 'index' type");this._myIndex=t||fe(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}add(e){te(e)&&(this._docs.push(e),this._myIndex.add(e))}remove(e=()=>!1){const t=[];for(let i=0,n=this._docs.length;i{let i=1;e.matches.forEach((({key:e,norm:n,score:s})=>{const o=e?e.weight:null;i*=Math.pow(0===s&&o?Number.EPSILON:s,(o||1)*(t?1:n))})),e.score=i}))}(a,{ignoreFieldNorm:r}),s&&a.sort(o),Z(t)&&t>-1&&(a=a.slice(0,t)),function(e,t,{includeMatches:i=de.includeMatches,includeScore:n=de.includeScore}={}){const s=[];return i&&s.push(Ae),n&&s.push(Oe),e.map((e=>{const{idx:i}=e,n={item:t[i],refIndex:i};return s.length&&s.forEach((t=>{t(e,n)})),n}))}(a,this._docs,{includeMatches:i,includeScore:n})}_searchStringList(e){const t=Ee(e,this.options),{records:i}=this._myIndex,n=[];return i.forEach((({v:e,i:i,n:s})=>{if(!te(e))return;const{isMatch:o,score:r,indices:a}=t.searchIn(e);o&&n.push({item:e,idx:i,matches:[{score:r,value:e,norm:s,indices:a}]})})),n}_searchLogical(e){throw new Error("Logical search is not available")}_searchObjectList(e){const t=Ee(e,this.options),{keys:i,records:n}=this._myIndex,s=[];return n.forEach((({$:e,i:n})=>{if(!te(e))return;let o=[];i.forEach(((i,n)=>{o.push(...this._findMatches({key:i,value:e[n],searcher:t}))})),o.length&&s.push({idx:n,item:e,matches:o})})),s}_findMatches({key:e,value:t,searcher:i}){if(!te(t))return[];let n=[];if(Q(t))t.forEach((({v:t,i:s,n:o})=>{if(!te(t))return;const{isMatch:r,score:a,indices:c}=i.searchIn(t);r&&n.push({score:a,key:e,value:t,idx:s,norm:o,indices:c})}));else{const{v:s,n:o}=t,{isMatch:r,score:a,indices:c}=i.searchIn(s);r&&n.push({score:a,key:e,value:s,norm:o,indices:c})}return n}}Le.version="7.0.0",Le.createIndex=fe,Le.parseIndex=function(e,{getFn:t=de.getFn,fieldNormWeight:i=de.fieldNormWeight}={}){const{keys:n,records:s}=e,o=new me({getFn:t,fieldNormWeight:i});return o.setKeys(n),o.setIndexRecords(s),o},Le.config=de,Le.parseQuery=function(e,t,{auto:i=!0}={}){const n=e=>{let s=Object.keys(e);const o=(e=>!!e[Se])(e);if(!o&&s.length>1&&!Ce(e))return n(Ie(e));if((e=>!Q(e)&&ee(e)&&!Ce(e))(e)){const n=o?e[Se]:s[0],r=o?e.$val:e[n];if(!Y(r))throw new Error((e=>`Invalid value for key ${e}`)(n));const a={keyId:he(n),pattern:r};return i&&(a.searcher=Ee(r,t)),a}let r={children:[],operator:s[0]};return s.forEach((t=>{const i=e[t];Q(i)&&i.forEach((e=>{r.children.push(n(e))}))})),r};return Ce(e)||(e=Ie(e)),n(e)};var xe=function(){function e(e){this._haystack=[],this._fuseOptions=i(i({},e.fuseOptions),{keys:n([],e.searchFields,!0),includeMatches:!0})}return e.prototype.index=function(e){this._haystack=e,this._fuse&&this._fuse.setCollection(e)},e.prototype.reset=function(){this._haystack=[],this._fuse=void 0},e.prototype.isEmptyIndex=function(){return!this._haystack.length},e.prototype.search=function(e){return this._fuse||(this._fuse=new Le(this._haystack,this._fuseOptions)),this._fuse.search(e).map((function(e,t){return{item:e.item,score:e.score||0,rank:t+1}}))},e}(),Te=function(e,t,i){var n=e.dataset,s=t.customProperties,o=t.labelClass,r=t.labelDescription;o&&(n.labelClass=I(o).join(" ")),r&&(n.labelDescription=r),i&&s&&("string"==typeof s?n.customProperties=s:"object"!=typeof s||function(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t))return!1;return!0}(s)||(n.customProperties=JSON.stringify(s)))},Ne=function(e,t,i){var n=t&&e.querySelector("label[for='".concat(t,"']")),s=n&&n.innerText;s&&i.setAttribute("aria-label",s)},Fe={containerOuter:function(e,t,i,n,s,o,r){var a=e.classNames.containerOuter,c=document.createElement("div");return c.className=I(a).join(" "),c.dataset.type=o,t&&(c.dir=t),n&&(c.tabIndex=0),i&&(c.setAttribute("role",s?"combobox":"listbox"),s?c.setAttribute("aria-autocomplete","list"):r||Ne(this._docRoot,this.passedElement.element.id,c),c.setAttribute("aria-haspopup","true"),c.setAttribute("aria-expanded","false")),r&&c.setAttribute("aria-labelledby",r),c},containerInner:function(e){var t=e.classNames.containerInner,i=document.createElement("div");return i.className=I(t).join(" "),i},itemList:function(e,t){var i=e.searchEnabled,n=e.classNames,s=n.list,o=n.listSingle,r=n.listItems,a=document.createElement("div");return a.className="".concat(I(s).join(" ")," ").concat(t?I(o).join(" "):I(r).join(" ")),this._isSelectElement&&i&&a.setAttribute("role","listbox"),a},placeholder:function(e,t){var i=e.allowHTML,n=e.classNames.placeholder,s=document.createElement("div");return s.className=I(n).join(" "),S(s,i,t),s},item:function(e,t,i){var n,s,o,r=e.allowHTML,a=e.removeItemButtonAlignLeft,c=e.removeItemIconText,l=e.removeItemLabelText,h=e.classNames,u=h.item,d=h.button,p=h.highlightedState,m=h.itemSelectable,f=h.placeholder,v=t.labelClass,_=t.label,g=t.disabled,b=t.value,w=E(b),C=document.createElement("div");if(C.className=I(u).join(" "),v){var A=document.createElement("span");S(A,r,_),A.className=I(v).join(" "),C.appendChild(A)}else S(C,r,_);var O=C.dataset;if(O.item="",O.id=t.id,O.value=w,Te(C,t,!0),(g||this.containerOuter.isDisabled)&&C.setAttribute("aria-disabled","true"),this._isSelectElement&&(C.setAttribute("aria-selected","true"),C.setAttribute("role","option")),t.placeholder&&((n=C.classList).add.apply(n,I(f)),O.placeholder=""),(s=C.classList).add.apply(s,I(t.highlighted?p:m)),i){g&&(o=C.classList).remove.apply(o,I(m)),O.deletable="";var L=document.createElement("button");L.type="button",L.className=I(d).join(" "),S(L,!0,y(c,b));var x=y(l,b);x&&L.setAttribute("aria-label",x),L.dataset.button="",a?C.insertAdjacentElement("afterbegin",L):C.appendChild(L)}return C},choiceList:function(e,t){var i=e.classNames.list,n=document.createElement("div");return n.className=I(i).join(" "),t||n.setAttribute("aria-multiselectable","true"),n.setAttribute("role","listbox"),n},choiceGroup:function(e,t){var i=e.allowHTML,n=e.classNames,s=n.group,o=n.groupHeading,r=n.itemDisabled,a=t.id,c=t.label,l=t.disabled,h=E(c),u=document.createElement("div");u.className="".concat(I(s).join(" ")," ").concat(l?I(r).join(" "):""),u.setAttribute("role","group");var d=u.dataset;d.group="",d.id=a,d.value=h,l&&u.setAttribute("aria-disabled","true");var p=document.createElement("div");return p.className=I(o).join(" "),S(p,i,c),u.appendChild(p),u},choice:function(e,t,i){var n,s,o,r,a,c=e.allowHTML,l=e.classNames,h=l.item,u=l.itemChoice,d=l.itemSelectable,p=l.selectedState,m=l.itemDisabled,f=l.description,v=l.placeholder,_=t.elementId,g=t.groupId,y=t.label,b=t.labelClass,w=t.labelDescription,C=E(t.value),A=document.createElement("div");A.id=_,A.className="".concat(I(h).join(" ")," ").concat(I(u).join(" "));var O=A;if(b){var L=document.createElement("span");S(L,c,y),L.className=I(b).join(" "),O=L,A.appendChild(L)}else S(A,c,y);if(w){var x="".concat(_,"-description");O.setAttribute("aria-describedby",x);var T=document.createElement("span");S(T,c,w),T.id=x,(n=T.classList).add.apply(n,I(f)),A.appendChild(T)}t.selected&&(s=A.classList).add.apply(s,I(p)),t.placeholder&&(o=A.classList).add.apply(o,I(v));var N=A.dataset,F=g&&g>0;return A.setAttribute("role",F?"treeitem":"option"),F&&(N.groupId="".concat(g)),N.choice="",N.id=t.id,N.value=C,N.selectText=i,Te(A,t,!1),t.disabled?((r=A.classList).add.apply(r,I(m)),N.choiceDisabled="",A.setAttribute("aria-disabled","true")):((a=A.classList).add.apply(a,I(d)),N.choiceSelectable=""),A},input:function(e,t){var i=e.classNames,n=i.input,s=i.inputCloned,o=e.labelId,r=document.createElement("input");return r.type="search",r.className="".concat(I(n).join(" ")," ").concat(I(s).join(" ")),r.autocomplete="off",r.autocapitalize="off",r.spellcheck=!1,r.setAttribute("role","textbox"),r.setAttribute("aria-autocomplete","list"),t?r.setAttribute("aria-label",t):o||Ne(this._docRoot,this.passedElement.element.id,r),r},dropdown:function(e){var t,i,n=e.classNames,s=n.list,o=n.listDropdown,r=document.createElement("div");return(t=r.classList).add.apply(t,I(s)),(i=r.classList).add.apply(i,I(o)),r.setAttribute("aria-expanded","false"),r},notice:function(e,t,i){var s=e.classNames,o=s.itemChoice,r=s.addChoice,a=s.noResults,c=s.noChoices,l=s.notice;void 0===i&&(i="");var h=n(n(n([],I(s.item),!0),I(o),!0),I(l),!0);switch(i){case $:h.push.apply(h,I(r));break;case W:h.push.apply(h,I(a));break;case U:h.push.apply(h,I(c))}var u=document.createElement("div");if(S(u,!0,t),u.className=h.join(" "),i===$){var d=u.dataset;d.choiceSelectable="",d.choice=""}return u},option:function(e){var t=E(e.label),i=new Option(t,e.value,!1,e.selected);return Te(i,e,!0),i.disabled=e.disabled,e.selected&&i.setAttribute("selected",""),i}},Me="-ms-scroll-limit"in document.documentElement.style&&"-ms-ime-align"in document.documentElement.style,De={},ke=function(e){if(e){var t=e.dataset.id;return t?parseInt(t,10):void 0}};return function(){function e(t,n){void 0===t&&(t="[data-choice]"),void 0===n&&(n={});var s=this;this.initialisedOK=void 0,this._hasNonChoicePlaceholder=!1,this._lastAddedChoiceId=0,this._lastAddedGroupId=0;var o=e.defaults;this.config=i(i(i({},o.allOptions),o.options),n),m.forEach((function(e){s.config[e]=i(i(i({},o.allOptions[e]),o.options[e]),n[e])}));var r=this.config;r.silent||this._validateConfig();var a=r.shadowRoot||document.documentElement;this._docRoot=a;var c="string"==typeof t?a.querySelector(t):t;if(!c||"object"!=typeof c||"INPUT"!==c.tagName&&!H(c)){if(!c&&"string"==typeof t)throw TypeError("Selector ".concat(t," failed to find an element"));throw TypeError("Expected one of the following types text|select-one|select-multiple")}if(this._elementType=c.type,this._isTextElement=this._elementType===x,(this._isTextElement||1!==r.maxItemCount)&&(r.singleModeForMultiSelect=!1),r.singleModeForMultiSelect&&(this._elementType=N),this._isSelectOneElement=this._elementType===T,this._isSelectMultipleElement=this._elementType===N,this._isSelectElement=this._isSelectOneElement||this._isSelectMultipleElement,this._canAddUserChoices=this._isTextElement&&r.addItems||this._isSelectElement&&r.addChoices,["auto","always"].includes("".concat(r.renderSelectedChoices))||(r.renderSelectedChoices="auto"),r.closeDropdownOnSelect="auto"===r.closeDropdownOnSelect?this._isTextElement||this._isSelectOneElement||r.singleModeForMultiSelect:j(r.closeDropdownOnSelect),r.placeholder&&(r.placeholderValue?this._hasNonChoicePlaceholder=!0:c.dataset.placeholder&&(this._hasNonChoicePlaceholder=!0,r.placeholderValue=c.dataset.placeholder)),n.addItemFilter&&"function"!=typeof n.addItemFilter){var l=n.addItemFilter instanceof RegExp?n.addItemFilter:new RegExp(n.addItemFilter);r.addItemFilter=l.test.bind(l)}if(this.passedElement=this._isTextElement?new P({element:c,classNames:r.classNames}):new V({element:c,classNames:r.classNames,template:function(e){return s._templates.option(e)},extractPlaceholder:r.placeholder&&!this._hasNonChoicePlaceholder}),this.initialised=!1,this._store=new G,this._currentValue="",r.searchEnabled=!this._isTextElement&&r.searchEnabled||this._elementType===N,this._canSearch=r.searchEnabled,this._isScrollingOnIe=!1,this._highlightPosition=0,this._wasTap=!0,this._placeholderValue=this._generatePlaceholderValue(),this._baseId=function(e){var t=e.id||e.name&&"".concat(e.name,"-").concat(v(2))||v(4);return t=t.replace(/(:|\.|\[|\]|,)/g,""),"".concat("choices-","-").concat(t)}(c),this._direction=this.passedElement.dir,!this._direction){var h=window.getComputedStyle(this.passedElement.element).direction;h!==window.getComputedStyle(document.documentElement).direction&&(this._direction=h)}if(this._idNames={itemChoice:"item-choice"},this._templates=o.templates,this._render=this._render.bind(this),this._onFocus=this._onFocus.bind(this),this._onBlur=this._onBlur.bind(this),this._onKeyUp=this._onKeyUp.bind(this),this._onKeyDown=this._onKeyDown.bind(this),this._onInput=this._onInput.bind(this),this._onClick=this._onClick.bind(this),this._onTouchMove=this._onTouchMove.bind(this),this._onTouchEnd=this._onTouchEnd.bind(this),this._onMouseDown=this._onMouseDown.bind(this),this._onMouseOver=this._onMouseOver.bind(this),this._onFormReset=this._onFormReset.bind(this),this._onSelectKey=this._onSelectKey.bind(this),this._onEnterKey=this._onEnterKey.bind(this),this._onEscapeKey=this._onEscapeKey.bind(this),this._onDirectionKey=this._onDirectionKey.bind(this),this._onDeleteKey=this._onDeleteKey.bind(this),this.passedElement.isActive)return r.silent||console.warn("Trying to initialise Choices on element already initialised",{element:t}),this.initialised=!0,void(this.initialisedOK=!1);this.init(),this._initialItems=this._store.items.map((function(e){return e.value}))}return Object.defineProperty(e,"defaults",{get:function(){return Object.preventExtensions({get options(){return De},get allOptions(){return R},get templates(){return Fe}})},enumerable:!1,configurable:!0}),e.prototype.init=function(){if(!this.initialised&&void 0===this.initialisedOK){this._searcher=new xe(this.config),this._loadChoices(),this._createTemplates(),this._createElements(),this._createStructure(),this._isTextElement&&!this.config.addItems||this.passedElement.element.hasAttribute("disabled")||this.passedElement.element.closest("fieldset:disabled")?this.disable():(this.enable(),this._addEventListeners()),this._initStore(),this.initialised=!0,this.initialisedOK=!0;var e=this.config.callbackOnInit;e&&"function"==typeof e&&e.call(this)}},e.prototype.destroy=function(){this.initialised&&(this._removeEventListeners(),this.passedElement.reveal(),this.containerOuter.unwrap(this.passedElement.element),this._store._listeners=[],this.clearStore(),this._stopSearch(),this._templates=e.defaults.templates,this.initialised=!1,this.initialisedOK=void 0)},e.prototype.enable=function(){var e=this.passedElement,t=this.containerOuter;return e.isDisabled&&e.enable(),t.isDisabled&&(this._addEventListeners(),this.input.enable(),t.enable(),this._render()),this},e.prototype.disable=function(){var e=this.passedElement,t=this.containerOuter;return e.isDisabled||e.disable(),t.isDisabled||(this._removeEventListeners(),this.input.disable(),t.disable(),this._render()),this},e.prototype.highlightItem=function(e,t){if(void 0===t&&(t=!0),!e||!e.id)return this;var i=this._store.choices.find((function(t){return t.id===e.id}));return!i||i.highlighted||(this._store.dispatch(f(i,!0)),t&&this.passedElement.triggerEvent("highlightItem",this._getChoiceForOutput(i))),this},e.prototype.unhighlightItem=function(e,t){if(void 0===t&&(t=!0),!e||!e.id)return this;var i=this._store.choices.find((function(t){return t.id===e.id}));return i&&i.highlighted?(this._store.dispatch(f(i,!1)),t&&this.passedElement.triggerEvent("highlightItem",this._getChoiceForOutput(i)),this):this},e.prototype.highlightAll=function(){var e=this;return this._store.withTxn((function(){e._store.items.forEach((function(t){return e.highlightItem(t)}))})),this},e.prototype.unhighlightAll=function(){var e=this;return this._store.withTxn((function(){e._store.items.forEach((function(t){return e.unhighlightItem(t)}))})),this},e.prototype.removeActiveItemsByValue=function(e){var t=this;return this._store.withTxn((function(){t._store.items.filter((function(t){return t.value===e})).forEach((function(e){return t._removeItem(e)}))})),this},e.prototype.removeActiveItems=function(e){var t=this;return this._store.withTxn((function(){t._store.items.filter((function(t){return t.id!==e})).forEach((function(e){return t._removeItem(e)}))})),this},e.prototype.removeHighlightedItems=function(e){var t=this;return void 0===e&&(e=!1),this._store.withTxn((function(){t._store.highlightedActiveItems.forEach((function(i){t._removeItem(i),e&&t._triggerChange(i.value)}))})),this},e.prototype.showDropdown=function(e){var t=this;return this.dropdown.isActive||requestAnimationFrame((function(){t.dropdown.show(),t.containerOuter.open(t.dropdown.distanceFromTopWindow),!e&&t._canSearch&&t.input.focus(),t.passedElement.triggerEvent("showDropdown")})),this},e.prototype.hideDropdown=function(e){var t=this;return this.dropdown.isActive?(requestAnimationFrame((function(){t.dropdown.hide(),t.containerOuter.close(),!e&&t._canSearch&&(t.input.removeActiveDescendant(),t.input.blur()),t.passedElement.triggerEvent("hideDropdown")})),this):this},e.prototype.getValue=function(e){var t=this;void 0===e&&(e=!1);var i=this._store.items.reduce((function(i,n){var s=e?n.value:t._getChoiceForOutput(n);return i.push(s),i}),[]);return this._isSelectOneElement||this.config.singleModeForMultiSelect?i[0]:i},e.prototype.setValue=function(e){var t=this;return this.initialisedOK?(this._store.withTxn((function(){e.forEach((function(e){e&&t._addChoice(B(e,!1))}))})),this._searcher.reset(),this):(this._warnChoicesInitFailed("setValue"),this)},e.prototype.setChoiceByValue=function(e){var t=this;return this.initialisedOK?(this._isTextElement||(this._store.withTxn((function(){(Array.isArray(e)?e:[e]).forEach((function(e){return t._findAndSelectChoiceByValue(e)}))})),this._searcher.reset()),this):(this._warnChoicesInitFailed("setChoiceByValue"),this)},e.prototype.setChoices=function(e,t,n,s){var o=this;if(void 0===e&&(e=[]),void 0===t&&(t="value"),void 0===n&&(n="label"),void 0===s&&(s=!1),!this.initialisedOK)return this._warnChoicesInitFailed("setChoices"),this;if(!this._isSelectElement)throw new TypeError("setChoices can't be used with INPUT based Choices");if("string"!=typeof t||!t)throw new TypeError("value parameter must be a name of 'value' field in passed objects");if(s&&this.clearChoices(),"function"==typeof e){var r=e(this);if("function"==typeof Promise&&r instanceof Promise)return new Promise((function(e){return requestAnimationFrame(e)})).then((function(){return o._handleLoadingState(!0)})).then((function(){return r})).then((function(e){return o.setChoices(e,t,n,s)})).catch((function(e){o.config.silent||console.error(e)})).then((function(){return o._handleLoadingState(!1)})).then((function(){return o}));if(!Array.isArray(r))throw new TypeError(".setChoices first argument function must return either array of choices or Promise, got: ".concat(typeof r));return this.setChoices(r,t,n,!1)}if(!Array.isArray(e))throw new TypeError(".setChoices must be called either with array of choices with a function resulting into Promise of array of choices");return this.containerOuter.removeLoadingState(),this._store.withTxn((function(){var s="value"===t,r="label"===n;e.forEach((function(e){if("choices"in e){var a=e;r||(a=i(i({},a),{label:a[n]})),o._addGroup(B(a,!0))}else{var c=e;r&&s||(c=i(i({},c),{value:c[t],label:c[n]})),o._addChoice(B(c,!1))}}))})),this._searcher.reset(),this},e.prototype.refresh=function(e,t,i){var n=this;return void 0===e&&(e=!1),void 0===t&&(t=!1),void 0===i&&(i=!1),this._isSelectElement?(this._store.withTxn((function(){var s=n.passedElement.optionsAsChoices(),o={};i||n._store.items.forEach((function(e){e.id&&e.active&&e.selected&&!e.disabled&&(o[e.value]=!0)})),s.forEach((function(e){if(!("choices"in e)){var t=e;i?t.selected=!1:o[t.value]&&(t.selected=!0)}})),n.clearStore(),n._addPredefinedChoices(s,t,e),n._isSearching&&n._searchChoices(n.input.value)})),this):(this.config.silent||console.warn("refresh method can only be used on choices backed by a element'); + } + return this; + } + this._store.withTxn(function () { + var choicesFromOptions = _this.passedElement.optionsAsChoices(); + var items = _this._store.items; + // Build the list of items which require preserving + var existingItems = {}; + if (!deselectAll) { + items.forEach(function (choice) { + if (choice.id && choice.active && choice.selected && !choice.disabled) { + existingItems[choice.value] = true; + } + }); + } + choicesFromOptions.forEach(function (groupOrChoice) { + if ('choices' in groupOrChoice) { + return; + } + var choice = groupOrChoice; + if (deselectAll) { + choice.selected = false; + } + else if (existingItems[choice.value]) { + choice.selected = true; + } + }); + _this.clearStore(); + /* @todo only generate add events for the added options instead of all + if (withEvents) { + items.forEach((choice) => { + if (existingItems[choice.value]) { + this.passedElement.triggerEvent( + EventType.removeItem, + this._getChoiceForEvent(choice), + ); + } + }); + } + */ + // load new choices & items + _this._addPredefinedChoices(choicesFromOptions, selectFirstOption, withEvents); + // re-do search if required + if (_this._isSearching) { + _this._searchChoices(_this.input.value); + } + }); + return this; + }; + Choices.prototype.removeChoice = function (value) { + var choice = this._store.choices.find(function (c) { return c.value === value; }); + if (!choice) { + return this; + } + this._store.dispatch(removeChoice(choice)); + // @todo integrate with Store + this._searcher.reset(); + if (choice.selected) { + this.passedElement.triggerEvent("removeItem" /* EventType.removeItem */, this._getChoiceForOutput(choice)); + } + return this; + }; + Choices.prototype.clearChoices = function () { + this.passedElement.element.innerHTML = ''; + this._store.dispatch(clearChoices()); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + Choices.prototype.clearStore = function () { + this._store.reset(); + this._lastAddedChoiceId = 0; + this._lastAddedGroupId = 0; + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + Choices.prototype.clearInput = function () { + var shouldSetInputWidth = !this._isSelectOneElement; + this.input.clear(shouldSetInputWidth); + this._clearNotice(); + if (this._isSearching) { + this._stopSearch(); + } + return this; + }; + Choices.prototype._validateConfig = function () { + var config = this.config; + var invalidConfigOptions = diff(config, DEFAULT_CONFIG); + if (invalidConfigOptions.length) { + console.warn('Unknown config option(s) passed', invalidConfigOptions.join(', ')); + } + if (config.allowHTML && config.allowHtmlUserInput) { + if (config.addItems) { + console.warn('Warning: allowHTML/allowHtmlUserInput/addItems all being true is strongly not recommended and may lead to XSS attacks'); + } + if (config.addChoices) { + console.warn('Warning: allowHTML/allowHtmlUserInput/addChoices all being true is strongly not recommended and may lead to XSS attacks'); + } + } + }; + Choices.prototype._render = function (changes) { + if (changes === void 0) { changes = { choices: true, groups: true, items: true }; } + if (this._store.inTxn()) { + return; + } + if (this._isSelectElement) { + if (changes.choices || changes.groups) { + this._renderChoices(); + } + } + if (changes.items) { + this._renderItems(); + } + }; + Choices.prototype._renderChoices = function () { + var _this = this; + this.choiceList.clear(); + if (!this._canAddItems()) { + return; // block rendering choices if the input limit is reached. + } + var config = this.config; + var _a = this._store, activeGroups = _a.activeGroups, activeChoices = _a.activeChoices; + var choiceListFragment = document.createDocumentFragment(); + var noChoices = true; + if (activeChoices.length) { + if (config.resetScrollPosition) { + requestAnimationFrame(function () { return _this.choiceList.scrollToTop(); }); + } + // If we have grouped options + if (activeGroups.length && !this._isSearching) { + if (!this._hasNonChoicePlaceholder) { + // If we have a placeholder choice along with groups + var activePlaceholders = activeChoices.filter(function (activeChoice) { return activeChoice.placeholder && activeChoice.groupId === -1; }); + if (activePlaceholders.length) { + choiceListFragment = this._createChoicesFragment(activePlaceholders, choiceListFragment); + } + } + choiceListFragment = this._createGroupsFragment(activeGroups, activeChoices, choiceListFragment); + } + else { + choiceListFragment = this._createChoicesFragment(activeChoices, choiceListFragment); + } + noChoices = !choiceListFragment.childNodes.length; + } + var notice = this._notice; + if (noChoices) { + if (!notice) { + this._notice = { + text: resolveStringFunction(config.noChoicesText), + type: NoticeTypes.noChoices, + }; + } + } + else if (notice && notice.type === NoticeTypes.noChoices) { + this._notice = undefined; + } + this._renderNotice(); + if (!noChoices) { + this.choiceList.element.append(choiceListFragment); + this._highlightChoice(); + } + }; + Choices.prototype._renderItems = function () { + var items = this._store.items || []; + this.itemList.clear(); + // Create a fragment to store our list items + // (so we don't have to update the DOM for each item) + var itemListFragment = this._createItemsFragment(items); + // If we have items to add, append them + if (itemListFragment.childNodes.length) { + this.itemList.element.append(itemListFragment); + } + }; + Choices.prototype._createGroupsFragment = function (groups, choices, fragment) { + var _this = this; + if (fragment === void 0) { fragment = document.createDocumentFragment(); } + var config = this.config; + var getGroupChoices = function (group) { + return choices.filter(function (choice) { + if (_this._isSelectOneElement) { + return choice.groupId === group.id; + } + return choice.groupId === group.id && (config.renderSelectedChoices === 'always' || !choice.selected); + }); + }; + // If sorting is enabled, filter groups + if (config.shouldSort) { + groups.sort(config.sorter); + } + // Add Choices without group first, regardless of sort, otherwise they won't be distinguishable + // from the last group + var choicesWithoutGroup = choices.filter(function (c) { return !c.groupId; }); + if (choicesWithoutGroup.length) { + this._createChoicesFragment(choicesWithoutGroup, fragment, false); + } + groups.forEach(function (group) { + var groupChoices = getGroupChoices(group); + if (groupChoices.length) { + var dropdownGroup = _this._templates.choiceGroup(_this.config, group); + fragment.appendChild(dropdownGroup); + _this._createChoicesFragment(groupChoices, fragment, true); + } + }); + return fragment; + }; + Choices.prototype._createChoicesFragment = function (choices, fragment, withinGroup) { + var _this = this; + if (fragment === void 0) { fragment = document.createDocumentFragment(); } + if (withinGroup === void 0) { withinGroup = false; } + // Create a fragment to store our list items (so we don't have to update the DOM for each item) + var _a = this, config = _a.config, isSearching = _a._isSearching, isSelectOneElement = _a._isSelectOneElement; + var searchResultLimit = config.searchResultLimit, renderChoiceLimit = config.renderChoiceLimit; + var groupLookup = []; + var appendGroupInSearch = config.appendGroupInSearch && isSearching; + if (appendGroupInSearch) { + this._store.groups.forEach(function (group) { + groupLookup[group.id] = group.label; + }); + } + if (this._isSelectElement) { + var backingOptions = choices.filter(function (choice) { return !choice.element; }); + if (backingOptions.length) { + this.passedElement.addOptions(backingOptions); + } + } + var skipSelected = config.renderSelectedChoices === 'auto' && !isSelectOneElement; + var placeholderChoices = []; + var normalChoices = []; + choices.forEach(function (choice) { + if ((isSearching && !choice.rank) || (skipSelected && choice.selected)) { + return; + } + if (_this._hasNonChoicePlaceholder || !choice.placeholder) { + normalChoices.push(choice); + } + else { + placeholderChoices.push(choice); + } + }); + if (isSearching) { + // sortByRank is used to ensure stable sorting, as scores are non-unique + // this additionally ensures fuseOptions.sortFn is not ignored + normalChoices.sort(sortByRank); + } + else if (config.shouldSort) { + normalChoices.sort(config.sorter); + } + var sortedChoices = isSelectOneElement && placeholderChoices.length ? __spreadArray(__spreadArray([], placeholderChoices, true), normalChoices, true) : normalChoices; + var choiceLimit = sortedChoices.length; + var limit = choiceLimit; + if (isSearching && searchResultLimit > 0) { + limit = searchResultLimit; + } + else if (renderChoiceLimit > 0 && !withinGroup) { + limit = renderChoiceLimit; + } + if (limit < choiceLimit) { + choiceLimit = limit; + } + choiceLimit--; + // Add each choice to dropdown within range + sortedChoices.every(function (choice, index) { + var dropdownItem = _this._templates.choice(config, choice, config.itemSelectText); + if (appendGroupInSearch && choice.groupId > 0) { + var groupName = groupLookup[choice.groupId]; + if (groupName) { + dropdownItem.innerHTML += " (".concat(groupName, ")"); + } + } + fragment.appendChild(dropdownItem); + return index < choiceLimit; + }); + return fragment; + }; + Choices.prototype._createItemsFragment = function (items, fragment) { + var _this = this; + if (fragment === void 0) { fragment = document.createDocumentFragment(); } + // Create fragment to add elements to + var config = this.config; + var shouldSortItems = config.shouldSortItems, sorter = config.sorter, removeItemButton = config.removeItemButton, delimiter = config.delimiter; + // If sorting is enabled, filter items + if (shouldSortItems && !this._isSelectOneElement) { + items.sort(sorter); + } + if (this._isTextElement) { + // Update the value of the hidden input + this.passedElement.value = items.map(function (_a) { + var value = _a.value; + return value; + }).join(delimiter); + } + var addItemToFragment = function (item) { + // Create new list element + var listItem = _this._templates.item(config, item, removeItemButton); + // Append it to list + fragment.appendChild(listItem); + }; + // Add each list item to list + items.forEach(addItemToFragment); + if (this._isSelectOneElement && this._hasNonChoicePlaceholder && !items.length) { + addItemToFragment(mapInputToChoice({ + selected: true, + value: '', + label: this.config.placeholderValue || '', + active: true, + placeholder: true, + }, false)); + } + return fragment; + }; + Choices.prototype._displayNotice = function (text, type, openDropdown) { + if (openDropdown === void 0) { openDropdown = true; } + var oldNotice = this._notice; + if (oldNotice && + ((oldNotice.type === type && oldNotice.text === text) || + (oldNotice.type === NoticeTypes.addChoice && + (type === NoticeTypes.noResults || type === NoticeTypes.noChoices)))) { + if (openDropdown) { + this.showDropdown(true); + } + return; + } + this._clearNotice(); + this._notice = text + ? { + text: text, + type: type, + } + : undefined; + this._renderNotice(); + if (openDropdown && text) { + this.showDropdown(true); + } + }; + Choices.prototype._clearNotice = function () { + if (!this._notice) { + return; + } + var noticeElement = this.choiceList.element.querySelector(getClassNamesSelector(this.config.classNames.notice)); + if (noticeElement) { + noticeElement.remove(); + } + this._notice = undefined; + }; + Choices.prototype._renderNotice = function () { + var noticeConf = this._notice; + if (noticeConf) { + var notice = this._templates.notice(this.config, noticeConf.text, noticeConf.type); + this.choiceList.prepend(notice); + } + }; + Choices.prototype._getChoiceForOutput = function (choice, keyCode) { + if (!choice) { + return undefined; + } + var group = choice.groupId > 0 ? this._store.getGroupById(choice.groupId) : null; + return { + id: choice.id, + highlighted: choice.highlighted, + labelClass: choice.labelClass, + labelDescription: choice.labelDescription, + customProperties: choice.customProperties, + disabled: choice.disabled, + active: choice.active, + label: choice.label, + placeholder: choice.placeholder, + value: choice.value, + groupValue: group && group.label ? group.label : undefined, + element: choice.element, + keyCode: keyCode, + }; + }; + Choices.prototype._triggerChange = function (value) { + if (value === undefined || value === null) { + return; + } + this.passedElement.triggerEvent("change" /* EventType.change */, { + value: value, + }); + }; + Choices.prototype._handleButtonAction = function (element) { + var items = this._store.items; + if (!items.length || !this.config.removeItems || !this.config.removeItemButton) { + return; + } + var id = element && parseDataSetId(element.parentNode); + var itemToRemove = id && items.find(function (item) { return item.id === id; }); + if (!itemToRemove) { + return; + } + // Remove item associated with button + this._removeItem(itemToRemove); + this._triggerChange(itemToRemove.value); + if (this._isSelectOneElement && !this._hasNonChoicePlaceholder) { + var placeholderChoice = this._store.choices.reverse().find(function (choice) { return !choice.disabled && choice.placeholder; }); + if (placeholderChoice) { + this._addItem(placeholderChoice); + if (placeholderChoice.value) { + this._triggerChange(placeholderChoice.value); + } + } + } + }; + Choices.prototype._handleItemAction = function (element, hasShiftKey) { + var _this = this; + if (hasShiftKey === void 0) { hasShiftKey = false; } + var items = this._store.items; + if (!items.length || !this.config.removeItems || this._isSelectOneElement) { + return; + } + var id = parseDataSetId(element); + if (!id) { + return; + } + // We only want to select one item with a click + // so we deselect any items that aren't the target + // unless shift is being pressed + items.forEach(function (item) { + if (item.id === id && !item.highlighted) { + _this.highlightItem(item); + } + else if (!hasShiftKey && item.highlighted) { + _this.unhighlightItem(item); + } + }); + // Focus input as without focus, a user cannot do anything with a + // highlighted item + this.input.focus(); + }; + Choices.prototype._handleChoiceAction = function (element) { + var _this = this; + // If we are clicking on an option + var id = parseDataSetId(element); + var choice = id && this._store.getChoiceById(id); + if (!choice || choice.disabled) { + return false; + } + var hasActiveDropdown = this.dropdown.isActive; + if (!choice.selected) { + if (!this._canAddItems()) { + return true; // causes _onEnterKey to early out + } + this._store.withTxn(function () { + _this._addItem(choice, true, true); + _this.clearInput(); + _this.unhighlightAll(); + }); + this._triggerChange(choice.value); + } + // We want to close the dropdown if we are dealing with a single select box + if (hasActiveDropdown && this.config.closeDropdownOnSelect) { + this.hideDropdown(true); + this.containerOuter.element.focus(); + } + return true; + }; + Choices.prototype._handleBackspace = function (items) { + var config = this.config; + if (!config.removeItems || !items.length) { + return; + } + var lastItem = items[items.length - 1]; + var hasHighlightedItems = items.some(function (item) { return item.highlighted; }); + // If editing the last item is allowed and there are not other selected items, + // we can edit the item value. Otherwise if we can remove items, remove all selected items + if (config.editItems && !hasHighlightedItems && lastItem) { + this.input.value = lastItem.value; + this.input.setWidth(); + this._removeItem(lastItem); + this._triggerChange(lastItem.value); + } + else { + if (!hasHighlightedItems) { + // Highlight last item if none already highlighted + this.highlightItem(lastItem, false); + } + this.removeHighlightedItems(true); + } + }; + Choices.prototype._loadChoices = function () { + var _a; + var config = this.config; + if (this._isTextElement) { + // Assign preset items from passed object first + this._presetChoices = config.items.map(function (e) { return mapInputToChoice(e, false); }); + // Add any values passed from attribute + var value = this.passedElement.value; + if (value) { + var elementItems = value + .split(config.delimiter) + .map(function (e) { return mapInputToChoice(e, false); }); + this._presetChoices = this._presetChoices.concat(elementItems); + } + this._presetChoices.forEach(function (choice) { + choice.selected = true; + }); + } + else if (this._isSelectElement) { + // Assign preset choices from passed object + this._presetChoices = config.choices.map(function (e) { return mapInputToChoice(e, true); }); + // Create array of choices from option elements + var choicesFromOptions = this.passedElement.optionsAsChoices(); + if (choicesFromOptions) { + (_a = this._presetChoices).push.apply(_a, choicesFromOptions); + } + } + }; + Choices.prototype._handleLoadingState = function (setLoading) { + if (setLoading === void 0) { setLoading = true; } + var config = this.config; + if (setLoading) { + this.disable(); + this.containerOuter.addLoadingState(); + if (this._isSelectOneElement) { + this.itemList.clear(); + this.itemList.element.append(this._templates.placeholder(config, config.loadingText)); + } + else { + this.input.placeholder = config.loadingText; + } + } + else { + this.enable(); + this.containerOuter.removeLoadingState(); + if (!this._isSelectOneElement) { + this.input.placeholder = this._placeholderValue || ''; + } + } + }; + Choices.prototype._handleSearch = function (value) { + if (!this.input.isFocussed) { + return; + } + var choices = this._store.choices; + var _a = this.config, searchFloor = _a.searchFloor, searchChoices = _a.searchChoices; + var hasUnactiveChoices = choices.some(function (option) { return !option.active; }); + // Check that we have a value to search and the input was an alphanumeric character + if (value !== null && typeof value !== 'undefined' && value.length >= searchFloor) { + var resultCount = searchChoices ? this._searchChoices(value) : 0; + if (resultCount !== null) { + // Trigger search event + this.passedElement.triggerEvent("search" /* EventType.search */, { + value: value, + resultCount: resultCount, + }); + } + } + else if (hasUnactiveChoices) { + this._stopSearch(); + } + }; + Choices.prototype._canAddItems = function () { + var config = this.config; + var maxItemCount = config.maxItemCount, maxItemText = config.maxItemText; + if (!config.singleModeForMultiSelect && maxItemCount > 0 && maxItemCount <= this._store.items.length) { + this._displayNotice(typeof maxItemText === 'function' ? maxItemText(maxItemCount) : maxItemText, NoticeTypes.addChoice); + return false; + } + return true; + }; + Choices.prototype._canCreateItem = function (value) { + var config = this.config; + var canAddItem = true; + var notice = ''; + if (canAddItem && typeof config.addItemFilter === 'function' && !config.addItemFilter(value)) { + canAddItem = false; + notice = resolveNoticeFunction(config.customAddItemText, value); + } + if (canAddItem) { + var foundChoice = this._store.choices.find(function (choice) { return config.valueComparer(choice.value, value); }); + if (this._isSelectElement) { + // for exact matches, do not prompt to add it as a custom choice + if (foundChoice) { + this._displayNotice('', NoticeTypes.addChoice); + return false; + } + } + else if (this._isTextElement && !config.duplicateItemsAllowed) { + if (foundChoice) { + canAddItem = false; + notice = resolveNoticeFunction(config.uniqueItemText, value); + } + } + } + if (canAddItem) { + notice = resolveNoticeFunction(config.addItemText, value); + } + if (notice) { + this._displayNotice(notice, NoticeTypes.addChoice); + } + return canAddItem; + }; + Choices.prototype._searchChoices = function (value) { + var newValue = value.trim().replace(/\s{2,}/, ' '); + // signal input didn't change search + if (!newValue.length || newValue === this._currentValue) { + return null; + } + var searcher = this._searcher; + if (searcher.isEmptyIndex()) { + searcher.index(this._store.searchableChoices); + } + // If new value matches the desired length and is not the same as the current value with a space + var results = searcher.search(newValue); + this._currentValue = newValue; + this._highlightPosition = 0; + this._isSearching = true; + var notice = this._notice; + var noticeType = notice && notice.type; + if (noticeType !== NoticeTypes.addChoice) { + if (!results.length) { + this._displayNotice(resolveStringFunction(this.config.noResultsText), NoticeTypes.noResults); + } + else if (noticeType === NoticeTypes.noResults) { + this._clearNotice(); + } + } + this._store.dispatch(filterChoices(results)); + return results.length; + }; + Choices.prototype._stopSearch = function () { + var wasSearching = this._isSearching; + this._currentValue = ''; + this._isSearching = false; + if (wasSearching) { + this._store.dispatch(activateChoices(true)); + this.passedElement.triggerEvent("search" /* EventType.search */, { + value: '', + resultCount: 0, + }); + } + }; + Choices.prototype._addEventListeners = function () { + var documentElement = this._docRoot; + var outerElement = this.containerOuter.element; + var inputElement = this.input.element; + // capture events - can cancel event processing or propagation + documentElement.addEventListener('touchend', this._onTouchEnd, true); + outerElement.addEventListener('keydown', this._onKeyDown, true); + outerElement.addEventListener('mousedown', this._onMouseDown, true); + // passive events - doesn't call `preventDefault` or `stopPropagation` + documentElement.addEventListener('click', this._onClick, { passive: true }); + documentElement.addEventListener('touchmove', this._onTouchMove, { + passive: true, + }); + this.dropdown.element.addEventListener('mouseover', this._onMouseOver, { + passive: true, + }); + if (this._isSelectOneElement) { + outerElement.addEventListener('focus', this._onFocus, { + passive: true, + }); + outerElement.addEventListener('blur', this._onBlur, { + passive: true, + }); + } + inputElement.addEventListener('keyup', this._onKeyUp, { + passive: true, + }); + inputElement.addEventListener('input', this._onInput, { + passive: true, + }); + inputElement.addEventListener('focus', this._onFocus, { + passive: true, + }); + inputElement.addEventListener('blur', this._onBlur, { + passive: true, + }); + if (inputElement.form) { + inputElement.form.addEventListener('reset', this._onFormReset, { + passive: true, + }); + } + this.input.addEventListeners(); + }; + Choices.prototype._removeEventListeners = function () { + var documentElement = this._docRoot; + var outerElement = this.containerOuter.element; + var inputElement = this.input.element; + documentElement.removeEventListener('touchend', this._onTouchEnd, true); + outerElement.removeEventListener('keydown', this._onKeyDown, true); + outerElement.removeEventListener('mousedown', this._onMouseDown, true); + documentElement.removeEventListener('click', this._onClick); + documentElement.removeEventListener('touchmove', this._onTouchMove); + this.dropdown.element.removeEventListener('mouseover', this._onMouseOver); + if (this._isSelectOneElement) { + outerElement.removeEventListener('focus', this._onFocus); + outerElement.removeEventListener('blur', this._onBlur); + } + inputElement.removeEventListener('keyup', this._onKeyUp); + inputElement.removeEventListener('input', this._onInput); + inputElement.removeEventListener('focus', this._onFocus); + inputElement.removeEventListener('blur', this._onBlur); + if (inputElement.form) { + inputElement.form.removeEventListener('reset', this._onFormReset); + } + this.input.removeEventListeners(); + }; + Choices.prototype._onKeyDown = function (event) { + var keyCode = event.keyCode; + var items = this._store.items; + var hasFocusedInput = this.input.isFocussed; + var hasActiveDropdown = this.dropdown.isActive; + var hasItems = this.itemList.element.hasChildNodes(); + /* + See: + https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key + https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values + https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF - UTF-16 surrogate pairs + https://stackoverflow.com/a/70866532 - "Unidentified" for mobile + http://www.unicode.org/versions/Unicode5.2.0/ch16.pdf#G19635 - U+FFFF is reserved (Section 16.7) + + Logic: when a key event is sent, `event.key` represents its printable value _or_ one + of a large list of special values indicating meta keys/functionality. In addition, + key events for compose functionality contain a value of `Dead` when mid-composition. + + I can't quite verify it, but non-English IMEs may also be able to generate key codes + for code points in the surrogate-pair range, which could potentially be seen as having + key.length > 1. Since `Fn` is one of the special keys, we can't distinguish by that + alone. + + Here, key.length === 1 means we know for sure the input was printable and not a special + `key` value. When the length is greater than 1, it could be either a printable surrogate + pair or a special `key` value. We can tell the difference by checking if the _character + code_ value (not code point!) is in the "surrogate pair" range or not. + + We don't use .codePointAt because an invalid code point would return 65535, which wouldn't + pass the >= 0x10000 check we would otherwise use. + + > ...The Unicode Standard sets aside 66 noncharacter code points. The last two code points + > of each plane are noncharacters: U+FFFE and U+FFFF on the BMP... + */ + var wasPrintableChar = event.key.length === 1 || + (event.key.length === 2 && event.key.charCodeAt(0) >= 0xd800) || + event.key === 'Unidentified'; + if (!this._isTextElement && !hasActiveDropdown) { + this.showDropdown(); + if (!this.input.isFocussed && wasPrintableChar) { + /* + We update the input value with the pressed key as + the input was not focussed at the time of key press + therefore does not have the value of the key. + */ + this.input.value += event.key; + // browsers interpret a space as pagedown + if (event.key === ' ') { + event.preventDefault(); + } + } + } + switch (keyCode) { + case 65 /* KeyCodeMap.A_KEY */: + return this._onSelectKey(event, hasItems); + case 13 /* KeyCodeMap.ENTER_KEY */: + return this._onEnterKey(event, hasActiveDropdown); + case 27 /* KeyCodeMap.ESC_KEY */: + return this._onEscapeKey(event, hasActiveDropdown); + case 38 /* KeyCodeMap.UP_KEY */: + case 33 /* KeyCodeMap.PAGE_UP_KEY */: + case 40 /* KeyCodeMap.DOWN_KEY */: + case 34 /* KeyCodeMap.PAGE_DOWN_KEY */: + return this._onDirectionKey(event, hasActiveDropdown); + case 8 /* KeyCodeMap.DELETE_KEY */: + case 46 /* KeyCodeMap.BACK_KEY */: + return this._onDeleteKey(event, items, hasFocusedInput); + } + }; + Choices.prototype._onKeyUp = function ( /* event: KeyboardEvent */) { + this._canSearch = this.config.searchEnabled; + }; + Choices.prototype._onInput = function ( /* event: InputEvent */) { + var value = this.input.value; + if (!value) { + if (this._isTextElement) { + this.hideDropdown(true); + } + else { + this._stopSearch(); + } + this._clearNotice(); + return; + } + if (!this._canAddItems()) { + return; + } + if (this._canSearch) { + // do the search even if the entered text can not be added + this._handleSearch(value); + } + if (!this._canAddUserChoices) { + return; + } + // determine if a notice needs to be displayed for why a search result can't be added + this._canCreateItem(value); + if (this._isSelectElement) { + this._highlightPosition = 0; // reset to select the notice and/or exact match + this._highlightChoice(); + } + }; + Choices.prototype._onSelectKey = function (event, hasItems) { + var ctrlKey = event.ctrlKey, metaKey = event.metaKey; + var hasCtrlDownKeyPressed = ctrlKey || metaKey; + // If CTRL + A or CMD + A have been pressed and there are items to select + if (hasCtrlDownKeyPressed && hasItems) { + this._canSearch = false; + var shouldHightlightAll = this.config.removeItems && !this.input.value && this.input.element === document.activeElement; + if (shouldHightlightAll) { + this.highlightAll(); + } + } + }; + Choices.prototype._onEnterKey = function (event, hasActiveDropdown) { + var _this = this; + var config = this.config; + var value = this.input.value; + var target = event.target; + var targetWasRemoveButton = target && target.hasAttribute('data-button'); + event.preventDefault(); + if (targetWasRemoveButton) { + this._handleButtonAction(target); + return; + } + if (!hasActiveDropdown) { + if (this._isSelectElement || this._notice) { + this.showDropdown(); + } + return; + } + var highlightedChoice = this.dropdown.element.querySelector(getClassNamesSelector(config.classNames.highlightedState)); + if (highlightedChoice && this._handleChoiceAction(highlightedChoice)) { + return; + } + if (!target || !value) { + this.hideDropdown(true); + return; + } + if (!this._canAddItems()) { + return; + } + var addedItem = false; + this._store.withTxn(function () { + addedItem = _this._findAndSelectChoiceByValue(value, true); + if (!addedItem) { + if (!_this._canAddUserChoices) { + return; + } + if (!_this._canCreateItem(value)) { + return; + } + var sanitisedValue = sanitise(value); + var userValue = config.allowHtmlUserInput || sanitisedValue === value ? value : { escaped: sanitisedValue, raw: value }; + _this._addChoice(mapInputToChoice({ + value: userValue, + label: userValue, + selected: true, + }, false), true, true); + addedItem = true; + } + _this.clearInput(); + _this.unhighlightAll(); + }); + if (!addedItem) { + return; + } + this._triggerChange(value); + if (config.closeDropdownOnSelect) { + this.hideDropdown(true); + } + }; + Choices.prototype._onEscapeKey = function (event, hasActiveDropdown) { + if (hasActiveDropdown) { + event.stopPropagation(); + this.hideDropdown(true); + this.containerOuter.element.focus(); + } + }; + Choices.prototype._onDirectionKey = function (event, hasActiveDropdown) { + var keyCode = event.keyCode, metaKey = event.metaKey; + // If up or down key is pressed, traverse through options + if (hasActiveDropdown || this._isSelectOneElement) { + this.showDropdown(); + this._canSearch = false; + var directionInt = keyCode === 40 /* KeyCodeMap.DOWN_KEY */ || keyCode === 34 /* KeyCodeMap.PAGE_DOWN_KEY */ ? 1 : -1; + var skipKey = metaKey || keyCode === 34 /* KeyCodeMap.PAGE_DOWN_KEY */ || keyCode === 33 /* KeyCodeMap.PAGE_UP_KEY */; + var selectableChoiceIdentifier = '[data-choice-selectable]'; + var nextEl = void 0; + if (skipKey) { + if (directionInt > 0) { + nextEl = this.dropdown.element.querySelector("".concat(selectableChoiceIdentifier, ":last-of-type")); + } + else { + nextEl = this.dropdown.element.querySelector(selectableChoiceIdentifier); + } + } + else { + var currentEl = this.dropdown.element.querySelector(getClassNamesSelector(this.config.classNames.highlightedState)); + if (currentEl) { + nextEl = getAdjacentEl(currentEl, selectableChoiceIdentifier, directionInt); + } + else { + nextEl = this.dropdown.element.querySelector(selectableChoiceIdentifier); + } + } + if (nextEl) { + // We prevent default to stop the cursor moving + // when pressing the arrow + if (!isScrolledIntoView(nextEl, this.choiceList.element, directionInt)) { + this.choiceList.scrollToChildElement(nextEl, directionInt); + } + this._highlightChoice(nextEl); + } + // Prevent default to maintain cursor position whilst + // traversing dropdown options + event.preventDefault(); + } + }; + Choices.prototype._onDeleteKey = function (event, items, hasFocusedInput) { + var target = event.target; + // If backspace or delete key is pressed and the input has no value + if (!this._isSelectOneElement && !target.value && hasFocusedInput) { + this._handleBackspace(items); + event.preventDefault(); + } + }; + Choices.prototype._onTouchMove = function () { + if (this._wasTap) { + this._wasTap = false; + } + }; + Choices.prototype._onTouchEnd = function (event) { + var target = (event || event.touches[0]).target; + var touchWasWithinContainer = this._wasTap && this.containerOuter.element.contains(target); + if (touchWasWithinContainer) { + var containerWasExactTarget = target === this.containerOuter.element || target === this.containerInner.element; + if (containerWasExactTarget) { + if (this._isTextElement) { + this.input.focus(); + } + else if (this._isSelectMultipleElement) { + this.showDropdown(); + } + } + // Prevents focus event firing + event.stopPropagation(); + } + this._wasTap = true; + }; + /** + * Handles mousedown event in capture mode for containetOuter.element + */ + Choices.prototype._onMouseDown = function (event) { + var target = event.target; + if (!(target instanceof HTMLElement)) { + return; + } + // If we have our mouse down on the scrollbar and are on IE11... + if (IS_IE11 && this.choiceList.element.contains(target)) { + // check if click was on a scrollbar area + var firstChoice = this.choiceList.element.firstElementChild; + this._isScrollingOnIe = + this._direction === 'ltr' ? event.offsetX >= firstChoice.offsetWidth : event.offsetX < firstChoice.offsetLeft; + } + if (target === this.input.element) { + return; + } + var item = target.closest('[data-button],[data-item],[data-choice]'); + if (item instanceof HTMLElement) { + var hasShiftKey = event.shiftKey; + var dataset = item.dataset; + if ('button' in dataset) { + this._handleButtonAction(item); + } + else if ('item' in dataset) { + this._handleItemAction(item, hasShiftKey); + } + else if ('choice' in dataset) { + this._handleChoiceAction(item); + } + } + event.preventDefault(); + }; + /** + * Handles mouseover event over this.dropdown + * @param {MouseEvent} event + */ + Choices.prototype._onMouseOver = function (_a) { + var target = _a.target; + if (target instanceof HTMLElement && 'choice' in target.dataset) { + this._highlightChoice(target); + } + }; + Choices.prototype._onClick = function (_a) { + var target = _a.target; + var containerOuter = this.containerOuter; + var clickWasWithinContainer = containerOuter.element.contains(target); + if (clickWasWithinContainer) { + if (!this.dropdown.isActive && !this.containerOuter.isDisabled) { + if (this._isTextElement) { + if (document.activeElement !== this.input.element) { + this.input.focus(); + } + } + else { + this.showDropdown(); + containerOuter.element.focus(); + } + } + else if (this._isSelectOneElement && + target !== this.input.element && + !this.dropdown.element.contains(target)) { + this.hideDropdown(); + } + } + else { + var hasHighlightedItems = !!this._store.highlightedActiveItems.length; + if (hasHighlightedItems) { + this.unhighlightAll(); + } + containerOuter.removeFocusState(); + this.hideDropdown(true); + } + }; + Choices.prototype._onFocus = function (_a) { + var _b; + var _this = this; + var target = _a.target; + var containerOuter = this.containerOuter; + var focusWasWithinContainer = target && containerOuter.element.contains(target); + if (!focusWasWithinContainer) { + return; + } + var targetIsInput = target === this.input.element; + var focusActions = (_b = {}, + _b[TEXT_TYPE] = function () { + if (targetIsInput) { + containerOuter.addFocusState(); + } + }, + _b[SELECT_ONE_TYPE] = function () { + containerOuter.addFocusState(); + if (targetIsInput) { + _this.showDropdown(true); + } + }, + _b[SELECT_MULTIPLE_TYPE] = function () { + if (targetIsInput) { + _this.showDropdown(true); + // If element is a select box, the focused element is the container and the dropdown + // isn't already open, focus and show dropdown + containerOuter.addFocusState(); + } + }, + _b); + focusActions[this._elementType](); + }; + Choices.prototype._onBlur = function (_a) { + var _b; + var _this = this; + var target = _a.target; + var containerOuter = this.containerOuter; + var blurWasWithinContainer = target && containerOuter.element.contains(target); + if (blurWasWithinContainer && !this._isScrollingOnIe) { + var activeChoices = this._store.activeChoices; + var hasHighlightedItems_1 = activeChoices.some(function (item) { return item.highlighted; }); + var targetIsInput_1 = target === this.input.element; + var blurActions = (_b = {}, + _b[TEXT_TYPE] = function () { + if (targetIsInput_1) { + containerOuter.removeFocusState(); + if (hasHighlightedItems_1) { + _this.unhighlightAll(); + } + _this.hideDropdown(true); + } + }, + _b[SELECT_ONE_TYPE] = function () { + containerOuter.removeFocusState(); + if (targetIsInput_1 || (target === containerOuter.element && !_this._canSearch)) { + _this.hideDropdown(true); + } + }, + _b[SELECT_MULTIPLE_TYPE] = function () { + if (targetIsInput_1) { + containerOuter.removeFocusState(); + _this.hideDropdown(true); + if (hasHighlightedItems_1) { + _this.unhighlightAll(); + } + } + }, + _b); + blurActions[this._elementType](); + } + else { + // On IE11, clicking the scollbar blurs our input and thus + // closes the dropdown. To stop this, we refocus our input + // if we know we are on IE *and* are scrolling. + this._isScrollingOnIe = false; + this.input.element.focus(); + } + }; + Choices.prototype._onFormReset = function () { + var _this = this; + this._store.withTxn(function () { + _this.clearInput(); + _this.hideDropdown(); + _this.refresh(false, false, true); + if (_this._initialItems.length) { + _this.setChoiceByValue(_this._initialItems); + } + }); + }; + Choices.prototype._highlightChoice = function (el) { + var _a; + if (el === void 0) { el = null; } + var highlightedState = this.config.classNames.highlightedState; + var choices = Array.from(this.dropdown.element.querySelectorAll('[data-choice-selectable]')); + if (!choices.length) { + return; + } + var passedEl = el; + var highlightedChoices = Array.from(this.dropdown.element.querySelectorAll(getClassNamesSelector(highlightedState))); + // Remove any highlighted choices + highlightedChoices.forEach(function (choice) { + var _a; + (_a = choice.classList).remove.apply(_a, getClassNames(highlightedState)); + choice.setAttribute('aria-selected', 'false'); + }); + if (passedEl) { + this._highlightPosition = choices.indexOf(passedEl); + } + else { + // Highlight choice based on last known highlight location + if (choices.length > this._highlightPosition) { + // If we have an option to highlight + passedEl = choices[this._highlightPosition]; + } + else { + // Otherwise highlight the option before + passedEl = choices[choices.length - 1]; + } + if (!passedEl) { + passedEl = choices[0]; + } + } + (_a = passedEl.classList).add.apply(_a, getClassNames(highlightedState)); + passedEl.setAttribute('aria-selected', 'true'); + this.passedElement.triggerEvent("highlightChoice" /* EventType.highlightChoice */, { + el: passedEl, + }); + if (this.dropdown.isActive) { + // IE11 ignores aria-label and blocks virtual keyboard + // if aria-activedescendant is set without a dropdown + this.input.setActiveDescendant(passedEl.id); + this.containerOuter.setActiveDescendant(passedEl.id); + } + }; + Choices.prototype._addItem = function (item, withEvents, userTriggered) { + if (withEvents === void 0) { withEvents = true; } + if (userTriggered === void 0) { userTriggered = false; } + var id = item.id; + if (!id) { + throw new TypeError('item.id must be set before _addItem is called for a choice/item'); + } + if (this.config.singleModeForMultiSelect || this._isSelectOneElement) { + this.removeActiveItems(id); + } + this._store.dispatch(addItem(item)); + if (withEvents) { + this.passedElement.triggerEvent("addItem" /* EventType.addItem */, this._getChoiceForOutput(item)); + if (userTriggered) { + this.passedElement.triggerEvent("choice" /* EventType.choice */, this._getChoiceForOutput(item)); + } + } + }; + Choices.prototype._removeItem = function (item) { + var id = item.id; + if (!id) { + return; + } + this._store.dispatch(removeItem(item)); + this.passedElement.triggerEvent("removeItem" /* EventType.removeItem */, this._getChoiceForOutput(item)); + }; + Choices.prototype._addChoice = function (choice, withEvents, userTriggered) { + if (withEvents === void 0) { withEvents = true; } + if (userTriggered === void 0) { userTriggered = false; } + if (choice.id) { + throw new TypeError('Can not re-add a choice which has already been added'); + } + // Generate unique id, in-place update is required so chaining _addItem works as expected + this._lastAddedChoiceId++; + choice.id = this._lastAddedChoiceId; + choice.elementId = "".concat(this._baseId, "-").concat(this._idNames.itemChoice, "-").concat(choice.id); + var _a = this.config, prependValue = _a.prependValue, appendValue = _a.appendValue; + if (prependValue) { + choice.value = prependValue + choice.value; + } + if (appendValue) { + choice.value += appendValue.toString(); + } + if ((prependValue || appendValue) && choice.element) { + choice.element.value = choice.value; + } + this._store.dispatch(addChoice(choice)); + if (choice.selected) { + this._addItem(choice, withEvents, userTriggered); + } + }; + Choices.prototype._addGroup = function (group, withEvents) { + var _this = this; + if (withEvents === void 0) { withEvents = true; } + if (group.id) { + throw new TypeError('Can not re-add a group which has already been added'); + } + this._store.dispatch(addGroup(group)); + if (!group.choices) { + return; + } + // add unique id for the group(s), and do not store the full list of choices in this group + var g = group; + this._lastAddedGroupId++; + g.id = this._lastAddedGroupId; + var id = group.id, choices = group.choices; + g.choices = []; + choices.forEach(function (item) { + item.groupId = id; + if (group.disabled) { + item.disabled = true; + } + _this._addChoice(item, withEvents); + }); + }; + Choices.prototype._createTemplates = function () { + var _this = this; + var callbackOnCreateTemplates = this.config.callbackOnCreateTemplates; + var userTemplates = {}; + if (callbackOnCreateTemplates && typeof callbackOnCreateTemplates === 'function') { + userTemplates = callbackOnCreateTemplates.call(this, strToEl, escapeForTemplate); + } + var templating = {}; + Object.keys(this._templates).forEach(function (name) { + if (name in userTemplates) { + templating[name] = userTemplates[name].bind(_this); + } + else { + templating[name] = _this._templates[name].bind(_this); + } + }); + this._templates = templating; + }; + Choices.prototype._createElements = function () { + var templating = this._templates; + var config = this.config; + var position = config.position, classNames = config.classNames; + var elementType = this._elementType; + this.containerOuter = new Container({ + element: templating.containerOuter(config, this._direction, this._isSelectElement, this._isSelectOneElement, config.searchEnabled, elementType, config.labelId), + classNames: classNames, + type: elementType, + position: position, + }); + this.containerInner = new Container({ + element: templating.containerInner(config), + classNames: classNames, + type: elementType, + position: position, + }); + this.input = new Input({ + element: templating.input(config, this._placeholderValue), + classNames: classNames, + type: elementType, + preventPaste: !config.paste, + }); + this.choiceList = new List({ + element: templating.choiceList(config, this._isSelectOneElement), + }); + this.itemList = new List({ + element: templating.itemList(config, this._isSelectOneElement), + }); + this.dropdown = new Dropdown({ + element: templating.dropdown(config), + classNames: classNames, + type: elementType, + }); + }; + Choices.prototype._createStructure = function () { + var _a = this, containerInner = _a.containerInner, containerOuter = _a.containerOuter, passedElement = _a.passedElement, dropdown = _a.dropdown, input = _a.input; + // Hide original element + passedElement.conceal(); + // Wrap input in container preserving DOM ordering + containerInner.wrap(passedElement.element); + // Wrapper inner container with outer container + containerOuter.wrap(containerInner.element); + if (this._isSelectOneElement) { + input.placeholder = this.config.searchPlaceholderValue || ''; + } + else { + if (this._placeholderValue) { + input.placeholder = this._placeholderValue; + } + input.setWidth(); + } + containerOuter.element.appendChild(containerInner.element); + containerOuter.element.appendChild(dropdown.element); + containerInner.element.appendChild(this.itemList.element); + dropdown.element.appendChild(this.choiceList.element); + if (!this._isSelectOneElement) { + containerInner.element.appendChild(input.element); + } + else if (this.config.searchEnabled) { + dropdown.element.insertBefore(input.element, dropdown.element.firstChild); + } + this._highlightPosition = 0; + this._isSearching = false; + }; + Choices.prototype._initStore = function () { + var _this = this; + this._store.subscribe(this._render); + this._store.withTxn(function () { + _this._addPredefinedChoices(_this._presetChoices, _this._isSelectOneElement && !_this._hasNonChoicePlaceholder, false); + }); + if (this._isSelectOneElement && this._hasNonChoicePlaceholder) { + this._render({ choices: false, groups: false, items: true }); + } + }; + Choices.prototype._addPredefinedChoices = function (choices, selectFirstOption, withEvents) { + var _this = this; + if (selectFirstOption === void 0) { selectFirstOption = false; } + if (withEvents === void 0) { withEvents = true; } + if (selectFirstOption) { + /** + * If there is a selected choice already or the choice is not the first in + * the array, add each choice normally. + * + * Otherwise we pre-select the first enabled choice in the array ("select-one" only) + */ + var noSelectedChoices = choices.findIndex(function (choice) { return choice.selected; }) === -1; + if (noSelectedChoices) { + choices.some(function (choice) { + if (choice.disabled || 'choices' in choice) { + return false; + } + choice.selected = true; + return true; + }); + } + } + choices.forEach(function (item) { + if ('choices' in item) { + if (_this._isSelectElement) { + _this._addGroup(item, withEvents); + } + } + else { + _this._addChoice(item, withEvents); + } + }); + }; + Choices.prototype._findAndSelectChoiceByValue = function (value, userTriggered) { + var _this = this; + if (userTriggered === void 0) { userTriggered = false; } + var choices = this._store.choices; + // Check 'value' property exists and the choice isn't already selected + var foundChoice = choices.find(function (choice) { return _this.config.valueComparer(choice.value, value); }); + if (foundChoice && !foundChoice.disabled && !foundChoice.selected) { + this._addItem(foundChoice, true, userTriggered); + return true; + } + return false; + }; + Choices.prototype._generatePlaceholderValue = function () { + var config = this.config; + if (!config.placeholder) { + return null; + } + if (this._hasNonChoicePlaceholder) { + return config.placeholderValue; + } + if (this._isSelectElement) { + var placeholderOption = this.passedElement.placeholderOption; + return placeholderOption ? placeholderOption.text : null; + } + return null; + }; + Choices.prototype._warnChoicesInitFailed = function (caller) { + if (this.config.silent) { + return; + } + if (!this.initialised) { + throw new TypeError("".concat(caller, " called on a non-initialised instance of Choices")); + } + else if (!this.initialisedOK) { + throw new TypeError("".concat(caller, " called for an element which has multiple instances of Choices initialised on it")); + } + }; + Choices.version = '11.0.0-rc7'; + return Choices; +}()); + +export { Choices as default }; diff --git a/assets/scripts/choices.search-prefix.js b/assets/scripts/choices.search-prefix.js new file mode 100644 index 00000000..176bcd61 --- /dev/null +++ b/assets/scripts/choices.search-prefix.js @@ -0,0 +1,3566 @@ +/*! choices.js v11.0.0-rc7 | © 2024 Josh Johnson | https://github.com/jshjohnson/Choices#readme */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Choices = factory()); +})(this, (function () { 'use strict'; + + /****************************************************************************** + Copyright (c) Microsoft Corporation. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + ***************************************************************************** */ + /* global Reflect, Promise, SuppressedError, Symbol */ + + 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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; + }; + return extendStatics(d, b); + }; + function __extends(d, b) { + if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + var __assign = function () { + __assign = Object.assign || function __assign(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); + }; + function __spreadArray(to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); + } + typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; + }; + + var ActionType = { + ADD_CHOICE: 'ADD_CHOICE', + REMOVE_CHOICE: 'REMOVE_CHOICE', + FILTER_CHOICES: 'FILTER_CHOICES', + ACTIVATE_CHOICES: 'ACTIVATE_CHOICES', + CLEAR_CHOICES: 'CLEAR_CHOICES', + ADD_GROUP: 'ADD_GROUP', + ADD_ITEM: 'ADD_ITEM', + REMOVE_ITEM: 'REMOVE_ITEM', + HIGHLIGHT_ITEM: 'HIGHLIGHT_ITEM', + }; + + var ObjectsInConfig = ['fuseOptions', 'classNames']; + + var addChoice = function (choice) { return ({ + type: ActionType.ADD_CHOICE, + choice: choice, + }); }; + var removeChoice = function (choice) { return ({ + type: ActionType.REMOVE_CHOICE, + choice: choice, + }); }; + var filterChoices = function (results) { return ({ + type: ActionType.FILTER_CHOICES, + results: results, + }); }; + var activateChoices = function (active) { + return ({ + type: ActionType.ACTIVATE_CHOICES, + active: active, + }); + }; + var clearChoices = function () { return ({ + type: ActionType.CLEAR_CHOICES, + }); }; + + var addGroup = function (group) { return ({ + type: ActionType.ADD_GROUP, + group: group, + }); }; + + var addItem = function (item) { return ({ + type: ActionType.ADD_ITEM, + item: item, + }); }; + var removeItem = function (item) { return ({ + type: ActionType.REMOVE_ITEM, + item: item, + }); }; + var highlightItem = function (item, highlighted) { return ({ + type: ActionType.HIGHLIGHT_ITEM, + item: item, + highlighted: highlighted, + }); }; + + /* eslint-disable @typescript-eslint/no-explicit-any */ + var getRandomNumber = function (min, max) { return Math.floor(Math.random() * (max - min) + min); }; + var generateChars = function (length) { + return Array.from({ length: length }, function () { return getRandomNumber(0, 36).toString(36); }).join(''); + }; + var generateId = function (element, prefix) { + var id = element.id || (element.name && "".concat(element.name, "-").concat(generateChars(2))) || generateChars(4); + id = id.replace(/(:|\.|\[|\]|,)/g, ''); + id = "".concat(prefix, "-").concat(id); + return id; + }; + var getAdjacentEl = function (startEl, selector, direction) { + if (direction === void 0) { direction = 1; } + var prop = "".concat(direction > 0 ? 'next' : 'previous', "ElementSibling"); + var sibling = startEl[prop]; + while (sibling) { + if (sibling.matches(selector)) { + return sibling; + } + sibling = sibling[prop]; + } + return null; + }; + var isScrolledIntoView = function (element, parent, direction) { + if (direction === void 0) { direction = 1; } + var isVisible; + if (direction > 0) { + // In view from bottom + isVisible = parent.scrollTop + parent.offsetHeight >= element.offsetTop + element.offsetHeight; + } + else { + // In view from top + isVisible = element.offsetTop >= parent.scrollTop; + } + return isVisible; + }; + var sanitise = function (value) { + if (typeof value !== 'string') { + if (value === null || value === undefined) { + return ''; + } + if (typeof value === 'object') { + if ('raw' in value) { + return sanitise(value.raw); + } + if ('trusted' in value) { + return value.trusted; + } + } + return value; + } + return value + .replace(/&/g, '&') + .replace(/>/g, '>') + .replace(/ 0 ? this.element.scrollTop + elementPos - listScrollPosition : element.offsetTop; + requestAnimationFrame(function () { + _this._animateScroll(destination, direction); + }); + }; + List.prototype._scrollDown = function (scrollPos, strength, destination) { + var easing = (destination - scrollPos) / strength; + var distance = easing > 1 ? easing : 1; + this.element.scrollTop = scrollPos + distance; + }; + List.prototype._scrollUp = function (scrollPos, strength, destination) { + var easing = (scrollPos - destination) / strength; + var distance = easing > 1 ? easing : 1; + this.element.scrollTop = scrollPos - distance; + }; + List.prototype._animateScroll = function (destination, direction) { + var _this = this; + var strength = SCROLLING_SPEED; + var choiceListScrollTop = this.element.scrollTop; + var continueAnimation = false; + if (direction > 0) { + this._scrollDown(choiceListScrollTop, strength, destination); + if (choiceListScrollTop < destination) { + continueAnimation = true; + } + } + else { + this._scrollUp(choiceListScrollTop, strength, destination); + if (choiceListScrollTop > destination) { + continueAnimation = true; + } + } + if (continueAnimation) { + requestAnimationFrame(function () { + _this._animateScroll(destination, direction); + }); + } + }; + return List; + }()); + + var WrappedElement = /** @class */ (function () { + function WrappedElement(_a) { + var element = _a.element, classNames = _a.classNames; + this.element = element; + this.classNames = classNames; + this.isDisabled = false; + } + Object.defineProperty(WrappedElement.prototype, "isActive", { + get: function () { + return this.element.dataset.choice === 'active'; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(WrappedElement.prototype, "dir", { + get: function () { + return this.element.dir; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(WrappedElement.prototype, "value", { + get: function () { + return this.element.value; + }, + set: function (value) { + this.element.setAttribute('value', value); + this.element.value = value; + }, + enumerable: false, + configurable: true + }); + WrappedElement.prototype.conceal = function () { + var _a; + var el = this.element; + // Hide passed input + (_a = el.classList).add.apply(_a, getClassNames(this.classNames.input)); + el.hidden = true; + // Remove element from tab index + el.tabIndex = -1; + // Backup original styles if any + var origStyle = el.getAttribute('style'); + if (origStyle) { + el.setAttribute('data-choice-orig-style', origStyle); + } + el.setAttribute('data-choice', 'active'); + }; + WrappedElement.prototype.reveal = function () { + var _a; + var el = this.element; + // Reinstate passed element + (_a = el.classList).remove.apply(_a, getClassNames(this.classNames.input)); + el.hidden = false; + el.removeAttribute('tabindex'); + // Recover original styles if any + var origStyle = el.getAttribute('data-choice-orig-style'); + if (origStyle) { + el.removeAttribute('data-choice-orig-style'); + el.setAttribute('style', origStyle); + } + else { + el.removeAttribute('style'); + } + el.removeAttribute('data-choice'); + }; + WrappedElement.prototype.enable = function () { + var element = this.element; + element.removeAttribute('disabled'); + element.disabled = false; + this.isDisabled = false; + }; + WrappedElement.prototype.disable = function () { + var element = this.element; + element.setAttribute('disabled', ''); + element.disabled = true; + this.isDisabled = true; + }; + WrappedElement.prototype.triggerEvent = function (eventType, data) { + dispatchEvent(this.element, eventType, data || {}); + }; + return WrappedElement; + }()); + + var WrappedInput = /** @class */ (function (_super) { + __extends(WrappedInput, _super); + function WrappedInput() { + return _super !== null && _super.apply(this, arguments) || this; + } + return WrappedInput; + }(WrappedElement)); + + var coerceBool = function (arg, defaultValue) { + if (defaultValue === void 0) { defaultValue = true; } + return typeof arg === 'undefined' ? defaultValue : !!arg; + }; + var stringToHtmlClass = function (input) { + if (typeof input === 'string') { + // eslint-disable-next-line no-param-reassign + input = input.split(' ').filter(function (s) { return s.length; }); + } + if (Array.isArray(input) && input.length) { + return input; + } + return undefined; + }; + var mapInputToChoice = function (value, allowGroup) { + if (typeof value === 'string') { + var result_1 = mapInputToChoice({ + value: value, + label: value, + }, false); + return result_1; + } + var groupOrChoice = value; + if ('choices' in groupOrChoice) { + if (!allowGroup) { + // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup + throw new TypeError("optGroup is not allowed"); + } + var group = groupOrChoice; + var choices = group.choices.map(function (e) { return mapInputToChoice(e, false); }); + var result_2 = { + id: 0, // actual ID will be assigned during _addGroup + label: unwrapStringForRaw(group.label) || group.value, + active: !!choices.length, + disabled: !!group.disabled, + choices: choices, + }; + return result_2; + } + var choice = groupOrChoice; + var result = { + id: 0, // actual ID will be assigned during _addChoice + groupId: 0, // actual ID will be assigned during _addGroup but before _addChoice + score: 0, // used in search + rank: 0, // used in search, stable sort order + value: choice.value, + label: choice.label || choice.value, + active: coerceBool(choice.active), + selected: coerceBool(choice.selected, false), + disabled: coerceBool(choice.disabled, false), + placeholder: coerceBool(choice.placeholder, false), + highlighted: false, + labelClass: stringToHtmlClass(choice.labelClass), + labelDescription: choice.labelDescription, + customProperties: choice.customProperties, + }; + return result; + }; + + var isHtmlInputElement = function (e) { return e.tagName === 'INPUT'; }; + var isHtmlSelectElement = function (e) { return e.tagName === 'SELECT'; }; + var isHtmlOption = function (e) { return e.tagName === 'OPTION'; }; + var isHtmlOptgroup = function (e) { return e.tagName === 'OPTGROUP'; }; + + var WrappedSelect = /** @class */ (function (_super) { + __extends(WrappedSelect, _super); + function WrappedSelect(_a) { + var element = _a.element, classNames = _a.classNames, template = _a.template, extractPlaceholder = _a.extractPlaceholder; + var _this = _super.call(this, { element: element, classNames: classNames }) || this; + _this.template = template; + _this.extractPlaceholder = extractPlaceholder; + return _this; + } + Object.defineProperty(WrappedSelect.prototype, "placeholderOption", { + get: function () { + return (this.element.querySelector('option[value=""]') || + // Backward compatibility layer for the non-standard placeholder attribute supported in older versions. + this.element.querySelector('option[placeholder]')); + }, + enumerable: false, + configurable: true + }); + WrappedSelect.prototype.addOptions = function (choices) { + var _this = this; + var fragment = document.createDocumentFragment(); + choices.forEach(function (obj) { + var choice = obj; + if (choice.element) { + return; + } + var option = _this.template(choice); + fragment.appendChild(option); + choice.element = option; + }); + this.element.appendChild(fragment); + }; + WrappedSelect.prototype.optionsAsChoices = function () { + var _this = this; + var choices = []; + this.element.querySelectorAll(':scope > option, :scope > optgroup').forEach(function (e) { + if (isHtmlOption(e)) { + choices.push(_this._optionToChoice(e)); + } + else if (isHtmlOptgroup(e)) { + choices.push(_this._optgroupToChoice(e)); + } + // todo: hr as empty optgroup, requires displaying empty opt-groups to be useful + }); + return choices; + }; + // eslint-disable-next-line class-methods-use-this + WrappedSelect.prototype._optionToChoice = function (option) { + // option.value returns the label if there is no value attribute, which can break legacy placeholder attribute support + if (!option.hasAttribute('value') && option.hasAttribute('placeholder')) { + option.setAttribute('value', ''); + option.value = ''; + } + var dataset = option.dataset; + return { + id: 0, + groupId: 0, + score: 0, + rank: 0, + value: option.value, + label: option.innerHTML, + element: option, + active: true, + // this returns true if nothing is selected on initial load, which will break placeholder support + selected: this.extractPlaceholder ? option.selected : option.hasAttribute('selected'), + disabled: option.disabled, + highlighted: false, + placeholder: this.extractPlaceholder && (!option.value || option.hasAttribute('placeholder')), + labelClass: typeof dataset.labelClass !== 'undefined' ? stringToHtmlClass(dataset.labelClass) : undefined, + labelDescription: typeof dataset.labelDescription !== 'undefined' ? dataset.labelDescription : undefined, + customProperties: parseCustomProperties(dataset.customProperties), + }; + }; + WrappedSelect.prototype._optgroupToChoice = function (optgroup) { + var _this = this; + var options = optgroup.querySelectorAll('option'); + var choices = Array.from(options).map(function (option) { return _this._optionToChoice(option); }); + return { + id: 0, + label: optgroup.label || '', + element: optgroup, + active: !!choices.length, + disabled: optgroup.disabled, + choices: choices, + }; + }; + return WrappedSelect; + }(WrappedElement)); + + var DEFAULT_CLASSNAMES = { + containerOuter: ['choices'], + containerInner: ['choices__inner'], + input: ['choices__input'], + inputCloned: ['choices__input--cloned'], + list: ['choices__list'], + listItems: ['choices__list--multiple'], + listSingle: ['choices__list--single'], + listDropdown: ['choices__list--dropdown'], + item: ['choices__item'], + itemSelectable: ['choices__item--selectable'], + itemDisabled: ['choices__item--disabled'], + itemChoice: ['choices__item--choice'], + description: ['choices__description'], + placeholder: ['choices__placeholder'], + group: ['choices__group'], + groupHeading: ['choices__heading'], + button: ['choices__button'], + activeState: ['is-active'], + focusState: ['is-focused'], + openState: ['is-open'], + disabledState: ['is-disabled'], + highlightedState: ['is-highlighted'], + selectedState: ['is-selected'], + flippedState: ['is-flipped'], + loadingState: ['is-loading'], + notice: ['choices__notice'], + addChoice: ['choices__item--selectable', 'add-choice'], + noResults: ['has-no-results'], + noChoices: ['has-no-choices'], + }; + var DEFAULT_CONFIG = { + items: [], + choices: [], + silent: false, + renderChoiceLimit: -1, + maxItemCount: -1, + closeDropdownOnSelect: 'auto', + singleModeForMultiSelect: false, + addChoices: false, + addItems: true, + addItemFilter: function (value) { return !!value && value !== ''; }, + removeItems: true, + removeItemButton: false, + removeItemButtonAlignLeft: false, + editItems: false, + allowHTML: false, + allowHtmlUserInput: false, + duplicateItemsAllowed: true, + delimiter: ',', + paste: true, + searchEnabled: true, + searchChoices: true, + searchFloor: 1, + searchResultLimit: 4, + searchFields: ['label', 'value'], + position: 'auto', + resetScrollPosition: true, + shouldSort: true, + shouldSortItems: false, + sorter: sortByAlpha, + shadowRoot: null, + placeholder: true, + placeholderValue: null, + searchPlaceholderValue: null, + prependValue: null, + appendValue: null, + renderSelectedChoices: 'auto', + loadingText: 'Loading...', + noResultsText: 'No results found', + noChoicesText: 'No choices to choose from', + itemSelectText: 'Press to select', + uniqueItemText: 'Only unique values can be added', + customAddItemText: 'Only values matching specific conditions can be added', + addItemText: function (value) { return "Press Enter to add \"".concat(value, "\""); }, + removeItemIconText: function () { return "Remove item"; }, + removeItemLabelText: function (value) { return "Remove item: ".concat(value); }, + maxItemText: function (maxItemCount) { return "Only ".concat(maxItemCount, " values can be added"); }, + valueComparer: function (value1, value2) { return value1 === value2; }, + fuseOptions: { + includeScore: true, + }, + labelId: '', + callbackOnInit: null, + callbackOnCreateTemplates: null, + classNames: DEFAULT_CLASSNAMES, + appendGroupInSearch: false, + }; + + function items(s, action) { + var state = s; + var update = true; + switch (action.type) { + case ActionType.ADD_ITEM: { + var item = action.item; + item.selected = true; + var el = item.element; + if (el) { + el.selected = true; + el.setAttribute('selected', ''); + } + state.push(item); + state.forEach(function (choice) { + choice.highlighted = false; + }); + break; + } + case ActionType.REMOVE_ITEM: { + var item_1 = action.item; + item_1.selected = false; + var el = item_1.element; + if (el) { + el.selected = false; + el.removeAttribute('selected'); + // For a select-one, if all options are deselected, the first item is selected. To set a black value, select.value needs to be set + var select = el.parentElement; + if (select && isHtmlSelectElement(select) && select.type === SELECT_ONE_TYPE) { + select.value = ''; + } + } + state = state.filter(function (choice) { return choice.id !== item_1.id; }); + break; + } + case ActionType.REMOVE_CHOICE: { + state = state.filter(function (item) { return item.id !== action.choice.id; }); + break; + } + case ActionType.HIGHLIGHT_ITEM: { + var highlightItemAction_1 = action; + state.forEach(function (choice) { + if (choice.id === highlightItemAction_1.item.id) { + choice.highlighted = highlightItemAction_1.highlighted; + } + }); + break; + } + default: { + update = false; + break; + } + } + return { state: state, update: update }; + } + + function groups(s, action) { + var state = s; + var update = true; + switch (action.type) { + case ActionType.ADD_GROUP: { + state.push(action.group); + break; + } + case ActionType.CLEAR_CHOICES: { + state = []; + break; + } + default: { + update = false; + break; + } + } + return { state: state, update: update }; + } + + /* eslint-disable */ + function choices(s, action) { + var state = s; + var update = true; + switch (action.type) { + case ActionType.ADD_CHOICE: { + /* + A disabled choice appears in the choice dropdown but cannot be selected + A selected choice has been added to the passed input's value (added as an item) + An active choice appears within the choice dropdown + */ + state.push(action.choice); + break; + } + case ActionType.REMOVE_CHOICE: { + state = state.filter(function (obj) { return obj.id !== action.choice.id; }); + break; + } + case ActionType.ADD_ITEM: + case ActionType.REMOVE_ITEM: { + break; + } + case ActionType.FILTER_CHOICES: { + // avoid O(n^2) algorithm complexity when searching/filtering choices + var scoreLookup_1 = []; + action.results.forEach(function (result) { + scoreLookup_1[result.item.id] = result; + }); + state.forEach(function (choice) { + var result = scoreLookup_1[choice.id]; + if (result !== undefined) { + choice.score = result.score; + choice.rank = result.rank; + choice.active = true; + } + else { + choice.score = 0; + choice.rank = 0; + choice.active = false; + } + }); + break; + } + case ActionType.ACTIVATE_CHOICES: { + state.forEach(function (choice) { + choice.active = action.active; + }); + break; + } + case ActionType.CLEAR_CHOICES: { + state = []; + break; + } + default: { + update = false; + break; + } + } + return { state: state, update: update }; + } + + var reducers = { + groups: groups, + items: items, + choices: choices, + }; + var Store = /** @class */ (function () { + function Store() { + this._state = this.defaultState; + this._listeners = []; + this._txn = 0; + } + Object.defineProperty(Store.prototype, "defaultState", { + // eslint-disable-next-line class-methods-use-this + get: function () { + return { + groups: [], + items: [], + choices: [], + }; + }, + enumerable: false, + configurable: true + }); + // eslint-disable-next-line class-methods-use-this + Store.prototype.changeSet = function (init) { + return { + groups: init, + items: init, + choices: init, + }; + }; + Store.prototype.reset = function () { + this._state = this.defaultState; + var changes = this.changeSet(true); + if (this._txn) { + this._changeSet = changes; + } + else { + this._listeners.forEach(function (l) { return l(changes); }); + } + }; + Store.prototype.subscribe = function (onChange) { + this._listeners.push(onChange); + }; + Store.prototype.dispatch = function (action) { + var state = this._state; + var hasChanges = false; + var changes = this._changeSet || this.changeSet(false); + Object.keys(reducers).forEach(function (key) { + var stateUpdate = reducers[key](state[key], action); + if (stateUpdate.update) { + hasChanges = true; + changes[key] = true; + state[key] = stateUpdate.state; + } + }); + if (hasChanges) { + if (this._txn) { + this._changeSet = changes; + } + else { + this._listeners.forEach(function (l) { return l(changes); }); + } + } + }; + Store.prototype.withTxn = function (func) { + this._txn++; + try { + func(); + } + finally { + this._txn = Math.max(0, this._txn - 1); + if (!this._txn) { + var changeSet_1 = this._changeSet; + if (changeSet_1) { + this._changeSet = undefined; + this._listeners.forEach(function (l) { return l(changeSet_1); }); + } + } + } + }; + Object.defineProperty(Store.prototype, "state", { + /** + * Get store object + */ + get: function () { + return this._state; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "items", { + /** + * Get items from store + */ + get: function () { + return this.state.items; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "highlightedActiveItems", { + /** + * Get highlighted items from store + */ + get: function () { + return this.items.filter(function (item) { return !item.disabled && item.active && item.highlighted; }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "choices", { + /** + * Get choices from store + */ + get: function () { + return this.state.choices; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "activeChoices", { + /** + * Get active choices from store + */ + get: function () { + return this.choices.filter(function (choice) { return choice.active; }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "searchableChoices", { + /** + * Get choices that can be searched (excluding placeholders) + */ + get: function () { + return this.choices.filter(function (choice) { return !choice.disabled && !choice.placeholder; }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "groups", { + /** + * Get groups from store + */ + get: function () { + return this.state.groups; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "activeGroups", { + /** + * Get active groups from store + */ + get: function () { + var _this = this; + return this.state.groups.filter(function (group) { + var isActive = group.active && !group.disabled; + var hasActiveOptions = _this.state.choices.some(function (choice) { return choice.active && !choice.disabled; }); + return isActive && hasActiveOptions; + }, []); + }, + enumerable: false, + configurable: true + }); + Store.prototype.inTxn = function () { + return this._txn > 0; + }; + /** + * Get single choice by it's ID + */ + Store.prototype.getChoiceById = function (id) { + return this.activeChoices.find(function (choice) { return choice.id === id; }); + }; + /** + * Get group by group id + */ + Store.prototype.getGroupById = function (id) { + return this.groups.find(function (group) { return group.id === id; }); + }; + return Store; + }()); + + var NoticeTypes = { + noChoices: 'no-choices', + noResults: 'no-results', + addChoice: 'add-choice', + generic: '', + }; + + var SearchByPrefixFilter = /** @class */ (function () { + function SearchByPrefixFilter(config) { + this._haystack = []; + this._fields = config.searchFields; + } + SearchByPrefixFilter.prototype.index = function (data) { + this._haystack = data; + }; + SearchByPrefixFilter.prototype.reset = function () { + this._haystack = []; + }; + SearchByPrefixFilter.prototype.isEmptyIndex = function () { + return !this._haystack.length; + }; + SearchByPrefixFilter.prototype.search = function (_needle) { + var fields = this._fields; + if (!fields || !fields.length || !_needle) { + return []; + } + var needle = _needle.toLowerCase(); + return this._haystack + .filter(function (obj) { return fields.some(function (field) { return field in obj && obj[field].toLowerCase().startsWith(needle); }); }) + .map(function (value, index) { + return { + item: value, + score: index, + rank: index + 1, + }; + }); + }; + return SearchByPrefixFilter; + }()); + + function getSearcher(config) { + return new SearchByPrefixFilter(config); + } + + /** + * Helpers to create HTML elements used by Choices + * Can be overridden by providing `callbackOnCreateTemplates` option. + * `Choices.defaults.templates` allows access to the default template methods from `callbackOnCreateTemplates` + */ + var isEmptyObject = function (obj) { + // eslint-disable-next-line no-restricted-syntax + for (var prop in obj) { + if (Object.prototype.hasOwnProperty.call(obj, prop)) { + return false; + } + } + return true; + }; + var assignCustomProperties = function (el, choice, withCustomProperties) { + var dataset = el.dataset; + var customProperties = choice.customProperties, labelClass = choice.labelClass, labelDescription = choice.labelDescription; + if (labelClass) { + dataset.labelClass = getClassNames(labelClass).join(' '); + } + if (labelDescription) { + dataset.labelDescription = labelDescription; + } + if (withCustomProperties && customProperties) { + if (typeof customProperties === 'string') { + dataset.customProperties = customProperties; + } + else if (typeof customProperties === 'object' && !isEmptyObject(customProperties)) { + dataset.customProperties = JSON.stringify(customProperties); + } + } + }; + var addAriaLabel = function (docRoot, id, element) { + var label = id && docRoot.querySelector("label[for='".concat(id, "']")); + var text = label && label.innerText; + if (text) { + element.setAttribute('aria-label', text); + } + }; + var templates = { + containerOuter: function (_a, dir, isSelectElement, isSelectOneElement, searchEnabled, passedElementType, labelId) { + var containerOuter = _a.classNames.containerOuter; + var div = document.createElement('div'); + div.className = getClassNames(containerOuter).join(' '); + div.dataset.type = passedElementType; + if (dir) { + div.dir = dir; + } + if (isSelectOneElement) { + div.tabIndex = 0; + } + if (isSelectElement) { + div.setAttribute('role', searchEnabled ? 'combobox' : 'listbox'); + if (searchEnabled) { + div.setAttribute('aria-autocomplete', 'list'); + } + else if (!labelId) { + addAriaLabel(this._docRoot, this.passedElement.element.id, div); + } + div.setAttribute('aria-haspopup', 'true'); + div.setAttribute('aria-expanded', 'false'); + } + if (labelId) { + div.setAttribute('aria-labelledby', labelId); + } + return div; + }, + containerInner: function (_a) { + var containerInner = _a.classNames.containerInner; + var div = document.createElement('div'); + div.className = getClassNames(containerInner).join(' '); + return div; + }, + itemList: function (_a, isSelectOneElement) { + var searchEnabled = _a.searchEnabled, _b = _a.classNames, list = _b.list, listSingle = _b.listSingle, listItems = _b.listItems; + var div = document.createElement('div'); + div.className = "".concat(getClassNames(list).join(' '), " ").concat(isSelectOneElement ? getClassNames(listSingle).join(' ') : getClassNames(listItems).join(' ')); + if (this._isSelectElement && searchEnabled) { + div.setAttribute('role', 'listbox'); + } + return div; + }, + placeholder: function (_a, value) { + var allowHTML = _a.allowHTML, placeholder = _a.classNames.placeholder; + var div = document.createElement('div'); + div.className = getClassNames(placeholder).join(' '); + setElementHtml(div, allowHTML, value); + return div; + }, + item: function (_a, choice, removeItemButton) { + var _b, _c, _d; + var allowHTML = _a.allowHTML, removeItemButtonAlignLeft = _a.removeItemButtonAlignLeft, removeItemIconText = _a.removeItemIconText, removeItemLabelText = _a.removeItemLabelText, _e = _a.classNames, item = _e.item, button = _e.button, highlightedState = _e.highlightedState, itemSelectable = _e.itemSelectable, placeholder = _e.placeholder; + var labelClass = choice.labelClass, label = choice.label, disabled = choice.disabled, value = choice.value; + var rawValue = unwrapStringForRaw(value); + var div = document.createElement('div'); + div.className = getClassNames(item).join(' '); + if (labelClass) { + var spanLabel = document.createElement('span'); + setElementHtml(spanLabel, allowHTML, label); + spanLabel.className = getClassNames(labelClass).join(' '); + div.appendChild(spanLabel); + } + else { + setElementHtml(div, allowHTML, label); + } + var dataset = div.dataset; + dataset.item = ''; + dataset.id = choice.id; + dataset.value = rawValue; + assignCustomProperties(div, choice, true); + if (disabled || this.containerOuter.isDisabled) { + div.setAttribute('aria-disabled', 'true'); + } + if (this._isSelectElement) { + div.setAttribute('aria-selected', 'true'); + div.setAttribute('role', 'option'); + } + if (choice.placeholder) { + (_b = div.classList).add.apply(_b, getClassNames(placeholder)); + dataset.placeholder = ''; + } + (_c = div.classList).add.apply(_c, (choice.highlighted ? getClassNames(highlightedState) : getClassNames(itemSelectable))); + if (removeItemButton) { + if (disabled) { + (_d = div.classList).remove.apply(_d, getClassNames(itemSelectable)); + } + dataset.deletable = ''; + var removeButton = document.createElement('button'); + removeButton.type = 'button'; + removeButton.className = getClassNames(button).join(' '); + setElementHtml(removeButton, true, resolveNoticeFunction(removeItemIconText, value)); + var REMOVE_ITEM_LABEL = resolveNoticeFunction(removeItemLabelText, value); + if (REMOVE_ITEM_LABEL) { + removeButton.setAttribute('aria-label', REMOVE_ITEM_LABEL); + } + removeButton.dataset.button = ''; + if (removeItemButtonAlignLeft) { + div.insertAdjacentElement('afterbegin', removeButton); + } + else { + div.appendChild(removeButton); + } + } + return div; + }, + choiceList: function (_a, isSelectOneElement) { + var list = _a.classNames.list; + var div = document.createElement('div'); + div.className = getClassNames(list).join(' '); + if (!isSelectOneElement) { + div.setAttribute('aria-multiselectable', 'true'); + } + div.setAttribute('role', 'listbox'); + return div; + }, + choiceGroup: function (_a, _b) { + var allowHTML = _a.allowHTML, _c = _a.classNames, group = _c.group, groupHeading = _c.groupHeading, itemDisabled = _c.itemDisabled; + var id = _b.id, label = _b.label, disabled = _b.disabled; + var rawLabel = unwrapStringForRaw(label); + var div = document.createElement('div'); + div.className = "".concat(getClassNames(group).join(' '), " ").concat(disabled ? getClassNames(itemDisabled).join(' ') : ''); + div.setAttribute('role', 'group'); + var dataset = div.dataset; + dataset.group = ''; + dataset.id = id; + dataset.value = rawLabel; + if (disabled) { + div.setAttribute('aria-disabled', 'true'); + } + var heading = document.createElement('div'); + heading.className = getClassNames(groupHeading).join(' '); + setElementHtml(heading, allowHTML, label); + div.appendChild(heading); + return div; + }, + choice: function (_a, choice, selectText) { + var _b, _c, _d, _e, _f; + var allowHTML = _a.allowHTML, _g = _a.classNames, item = _g.item, itemChoice = _g.itemChoice, itemSelectable = _g.itemSelectable, selectedState = _g.selectedState, itemDisabled = _g.itemDisabled, description = _g.description, placeholder = _g.placeholder; + var value = choice.value, elementId = choice.elementId, groupId = choice.groupId, label = choice.label, labelClass = choice.labelClass, labelDescription = choice.labelDescription; + var rawValue = unwrapStringForRaw(value); + var div = document.createElement('div'); + div.id = elementId; + div.className = "".concat(getClassNames(item).join(' '), " ").concat(getClassNames(itemChoice).join(' ')); + var describedBy = div; + if (labelClass) { + var spanLabel = document.createElement('span'); + setElementHtml(spanLabel, allowHTML, label); + spanLabel.className = getClassNames(labelClass).join(' '); + describedBy = spanLabel; + div.appendChild(spanLabel); + } + else { + setElementHtml(div, allowHTML, label); + } + if (labelDescription) { + var descId = "".concat(elementId, "-description"); + describedBy.setAttribute('aria-describedby', descId); + var spanDesc = document.createElement('span'); + setElementHtml(spanDesc, allowHTML, labelDescription); + spanDesc.id = descId; + (_b = spanDesc.classList).add.apply(_b, getClassNames(description)); + div.appendChild(spanDesc); + } + if (choice.selected) { + (_c = div.classList).add.apply(_c, getClassNames(selectedState)); + } + if (choice.placeholder) { + (_d = div.classList).add.apply(_d, getClassNames(placeholder)); + } + var dataset = div.dataset; + var showGroupId = groupId && groupId > 0; + div.setAttribute('role', showGroupId ? 'treeitem' : 'option'); + if (showGroupId) { + dataset.groupId = "".concat(groupId); + } + dataset.choice = ''; + dataset.id = choice.id; + dataset.value = rawValue; + dataset.selectText = selectText; + assignCustomProperties(div, choice, false); + if (choice.disabled) { + (_e = div.classList).add.apply(_e, getClassNames(itemDisabled)); + dataset.choiceDisabled = ''; + div.setAttribute('aria-disabled', 'true'); + } + else { + (_f = div.classList).add.apply(_f, getClassNames(itemSelectable)); + dataset.choiceSelectable = ''; + } + return div; + }, + input: function (_a, placeholderValue) { + var _b = _a.classNames, input = _b.input, inputCloned = _b.inputCloned, labelId = _a.labelId; + var inp = document.createElement('input'); + inp.type = 'search'; + inp.className = "".concat(getClassNames(input).join(' '), " ").concat(getClassNames(inputCloned).join(' ')); + inp.autocomplete = 'off'; + inp.autocapitalize = 'off'; + inp.spellcheck = false; + inp.setAttribute('role', 'textbox'); + inp.setAttribute('aria-autocomplete', 'list'); + if (placeholderValue) { + inp.setAttribute('aria-label', placeholderValue); + } + else if (!labelId) { + addAriaLabel(this._docRoot, this.passedElement.element.id, inp); + } + return inp; + }, + dropdown: function (_a) { + var _b, _c; + var _d = _a.classNames, list = _d.list, listDropdown = _d.listDropdown; + var div = document.createElement('div'); + (_b = div.classList).add.apply(_b, getClassNames(list)); + (_c = div.classList).add.apply(_c, getClassNames(listDropdown)); + div.setAttribute('aria-expanded', 'false'); + return div; + }, + notice: function (_a, innerHTML, type) { + var _b = _a.classNames, item = _b.item, itemChoice = _b.itemChoice, addChoice = _b.addChoice, noResults = _b.noResults, noChoices = _b.noChoices, noticeItem = _b.notice; + if (type === void 0) { type = NoticeTypes.generic; } + var classes = __spreadArray(__spreadArray(__spreadArray([], getClassNames(item), true), getClassNames(itemChoice), true), getClassNames(noticeItem), true); + // eslint-disable-next-line default-case + switch (type) { + case NoticeTypes.addChoice: + classes.push.apply(classes, getClassNames(addChoice)); + break; + case NoticeTypes.noResults: + classes.push.apply(classes, getClassNames(noResults)); + break; + case NoticeTypes.noChoices: + classes.push.apply(classes, getClassNames(noChoices)); + break; + } + var notice = document.createElement('div'); + setElementHtml(notice, true, innerHTML); + notice.className = classes.join(' '); + if (type === NoticeTypes.addChoice) { + var dataset = notice.dataset; + dataset.choiceSelectable = ''; + dataset.choice = ''; + } + return notice; + }, + option: function (choice) { + // HtmlOptionElement's label value does not support HTML, so the avoid double escaping unwrap the untrusted string. + var labelValue = unwrapStringForRaw(choice.label); + var opt = new Option(labelValue, choice.value, false, choice.selected); + assignCustomProperties(opt, choice, true); + opt.disabled = choice.disabled; + if (choice.selected) { + opt.setAttribute('selected', ''); + } + return opt; + }, + }; + + /** @see {@link http://browserhacks.com/#hack-acea075d0ac6954f275a70023906050c} */ + var IS_IE11 = '-ms-scroll-limit' in document.documentElement.style && + '-ms-ime-align' in document.documentElement.style; + var USER_DEFAULTS = {}; + var parseDataSetId = function (element) { + if (!element) { + return undefined; + } + var id = element.dataset.id; + return id ? parseInt(id, 10) : undefined; + }; + /** + * Choices + * @author Josh Johnson + */ + var Choices = /** @class */ (function () { + function Choices(element, userConfig) { + if (element === void 0) { element = '[data-choice]'; } + if (userConfig === void 0) { userConfig = {}; } + var _this = this; + this.initialisedOK = undefined; + this._hasNonChoicePlaceholder = false; + this._lastAddedChoiceId = 0; + this._lastAddedGroupId = 0; + var defaults = Choices.defaults; + this.config = __assign(__assign(__assign({}, defaults.allOptions), defaults.options), userConfig); + ObjectsInConfig.forEach(function (key) { + _this.config[key] = __assign(__assign(__assign({}, defaults.allOptions[key]), defaults.options[key]), userConfig[key]); + }); + var config = this.config; + if (!config.silent) { + this._validateConfig(); + } + var docRoot = config.shadowRoot || document.documentElement; + this._docRoot = docRoot; + var passedElement = typeof element === 'string' ? docRoot.querySelector(element) : element; + if (!passedElement || + typeof passedElement !== 'object' || + !(isHtmlInputElement(passedElement) || isHtmlSelectElement(passedElement))) { + if (!passedElement && typeof element === 'string') { + throw TypeError("Selector ".concat(element, " failed to find an element")); + } + throw TypeError("Expected one of the following types text|select-one|select-multiple"); + } + this._elementType = passedElement.type; + this._isTextElement = this._elementType === TEXT_TYPE; + if (this._isTextElement || config.maxItemCount !== 1) { + config.singleModeForMultiSelect = false; + } + if (config.singleModeForMultiSelect) { + this._elementType = SELECT_MULTIPLE_TYPE; + } + this._isSelectOneElement = this._elementType === SELECT_ONE_TYPE; + this._isSelectMultipleElement = this._elementType === SELECT_MULTIPLE_TYPE; + this._isSelectElement = this._isSelectOneElement || this._isSelectMultipleElement; + this._canAddUserChoices = (this._isTextElement && config.addItems) || (this._isSelectElement && config.addChoices); + if (!['auto', 'always'].includes("".concat(config.renderSelectedChoices))) { + config.renderSelectedChoices = 'auto'; + } + if (config.closeDropdownOnSelect === 'auto') { + config.closeDropdownOnSelect = this._isTextElement || this._isSelectOneElement || config.singleModeForMultiSelect; + } + else { + config.closeDropdownOnSelect = coerceBool(config.closeDropdownOnSelect); + } + if (config.placeholder) { + if (config.placeholderValue) { + this._hasNonChoicePlaceholder = true; + } + else if (passedElement.dataset.placeholder) { + this._hasNonChoicePlaceholder = true; + config.placeholderValue = passedElement.dataset.placeholder; + } + } + if (userConfig.addItemFilter && typeof userConfig.addItemFilter !== 'function') { + var re = userConfig.addItemFilter instanceof RegExp ? userConfig.addItemFilter : new RegExp(userConfig.addItemFilter); + config.addItemFilter = re.test.bind(re); + } + if (this._isTextElement) { + this.passedElement = new WrappedInput({ + element: passedElement, + classNames: config.classNames, + }); + } + else { + var selectEl = passedElement; + this.passedElement = new WrappedSelect({ + element: selectEl, + classNames: config.classNames, + template: function (data) { return _this._templates.option(data); }, + extractPlaceholder: config.placeholder && !this._hasNonChoicePlaceholder, + }); + } + this.initialised = false; + this._store = new Store(); + this._currentValue = ''; + config.searchEnabled = (!this._isTextElement && config.searchEnabled) || this._elementType === SELECT_MULTIPLE_TYPE; + this._canSearch = config.searchEnabled; + this._isScrollingOnIe = false; + this._highlightPosition = 0; + this._wasTap = true; + this._placeholderValue = this._generatePlaceholderValue(); + this._baseId = generateId(passedElement, 'choices-'); + /** + * setting direction in cases where it's explicitly set on passedElement + * or when calculated direction is different from the document + */ + this._direction = this.passedElement.dir; + if (!this._direction) { + var elementDirection = window.getComputedStyle(this.passedElement.element).direction; + var documentDirection = window.getComputedStyle(document.documentElement).direction; + if (elementDirection !== documentDirection) { + this._direction = elementDirection; + } + } + this._idNames = { + itemChoice: 'item-choice', + }; + this._templates = defaults.templates; + this._render = this._render.bind(this); + this._onFocus = this._onFocus.bind(this); + this._onBlur = this._onBlur.bind(this); + this._onKeyUp = this._onKeyUp.bind(this); + this._onKeyDown = this._onKeyDown.bind(this); + this._onInput = this._onInput.bind(this); + this._onClick = this._onClick.bind(this); + this._onTouchMove = this._onTouchMove.bind(this); + this._onTouchEnd = this._onTouchEnd.bind(this); + this._onMouseDown = this._onMouseDown.bind(this); + this._onMouseOver = this._onMouseOver.bind(this); + this._onFormReset = this._onFormReset.bind(this); + this._onSelectKey = this._onSelectKey.bind(this); + this._onEnterKey = this._onEnterKey.bind(this); + this._onEscapeKey = this._onEscapeKey.bind(this); + this._onDirectionKey = this._onDirectionKey.bind(this); + this._onDeleteKey = this._onDeleteKey.bind(this); + // If element has already been initialised with Choices, fail silently + if (this.passedElement.isActive) { + if (!config.silent) { + console.warn('Trying to initialise Choices on element already initialised', { element: element }); + } + this.initialised = true; + this.initialisedOK = false; + return; + } + // Let's go + this.init(); + // preserve the selected item list after setup for form reset + this._initialItems = this._store.items.map(function (choice) { return choice.value; }); + } + Object.defineProperty(Choices, "defaults", { + get: function () { + return Object.preventExtensions({ + get options() { + return USER_DEFAULTS; + }, + get allOptions() { + return DEFAULT_CONFIG; + }, + get templates() { + return templates; + }, + }); + }, + enumerable: false, + configurable: true + }); + Choices.prototype.init = function () { + if (this.initialised || this.initialisedOK !== undefined) { + return; + } + this._searcher = getSearcher(this.config); + this._loadChoices(); + this._createTemplates(); + this._createElements(); + this._createStructure(); + if ((this._isTextElement && !this.config.addItems) || + this.passedElement.element.hasAttribute('disabled') || + !!this.passedElement.element.closest('fieldset:disabled')) { + this.disable(); + } + else { + this.enable(); + this._addEventListeners(); + } + // should be triggered **after** disabled state to avoid additional re-draws + this._initStore(); + this.initialised = true; + this.initialisedOK = true; + var callbackOnInit = this.config.callbackOnInit; + // Run callback if it is a function + if (callbackOnInit && typeof callbackOnInit === 'function') { + callbackOnInit.call(this); + } + }; + Choices.prototype.destroy = function () { + if (!this.initialised) { + return; + } + this._removeEventListeners(); + this.passedElement.reveal(); + this.containerOuter.unwrap(this.passedElement.element); + this._store._listeners = []; // prevents select/input value being wiped + this.clearStore(); + this._stopSearch(); + this._templates = Choices.defaults.templates; + this.initialised = false; + this.initialisedOK = undefined; + }; + Choices.prototype.enable = function () { + var _a = this, passedElement = _a.passedElement, containerOuter = _a.containerOuter; + if (passedElement.isDisabled) { + passedElement.enable(); + } + if (containerOuter.isDisabled) { + this._addEventListeners(); + this.input.enable(); + containerOuter.enable(); + this._render(); + } + return this; + }; + Choices.prototype.disable = function () { + var _a = this, passedElement = _a.passedElement, containerOuter = _a.containerOuter; + if (!passedElement.isDisabled) { + passedElement.disable(); + } + if (!containerOuter.isDisabled) { + this._removeEventListeners(); + this.input.disable(); + containerOuter.disable(); + this._render(); + } + return this; + }; + Choices.prototype.highlightItem = function (item, runEvent) { + if (runEvent === void 0) { runEvent = true; } + if (!item || !item.id) { + return this; + } + var choice = this._store.choices.find(function (c) { return c.id === item.id; }); + if (!choice || choice.highlighted) { + return this; + } + this._store.dispatch(highlightItem(choice, true)); + if (runEvent) { + this.passedElement.triggerEvent("highlightItem" /* EventType.highlightItem */, this._getChoiceForOutput(choice)); + } + return this; + }; + Choices.prototype.unhighlightItem = function (item, runEvent) { + if (runEvent === void 0) { runEvent = true; } + if (!item || !item.id) { + return this; + } + var choice = this._store.choices.find(function (c) { return c.id === item.id; }); + if (!choice || !choice.highlighted) { + return this; + } + this._store.dispatch(highlightItem(choice, false)); + if (runEvent) { + this.passedElement.triggerEvent("highlightItem" /* EventType.highlightItem */, this._getChoiceForOutput(choice)); + } + return this; + }; + Choices.prototype.highlightAll = function () { + var _this = this; + this._store.withTxn(function () { + _this._store.items.forEach(function (item) { return _this.highlightItem(item); }); + }); + return this; + }; + Choices.prototype.unhighlightAll = function () { + var _this = this; + this._store.withTxn(function () { + _this._store.items.forEach(function (item) { return _this.unhighlightItem(item); }); + }); + return this; + }; + Choices.prototype.removeActiveItemsByValue = function (value) { + var _this = this; + this._store.withTxn(function () { + _this._store.items.filter(function (item) { return item.value === value; }).forEach(function (item) { return _this._removeItem(item); }); + }); + return this; + }; + Choices.prototype.removeActiveItems = function (excludedId) { + var _this = this; + this._store.withTxn(function () { + _this._store.items.filter(function (_a) { + var id = _a.id; + return id !== excludedId; + }).forEach(function (item) { return _this._removeItem(item); }); + }); + return this; + }; + Choices.prototype.removeHighlightedItems = function (runEvent) { + var _this = this; + if (runEvent === void 0) { runEvent = false; } + this._store.withTxn(function () { + _this._store.highlightedActiveItems.forEach(function (item) { + _this._removeItem(item); + // If this action was performed by the user + // trigger the event + if (runEvent) { + _this._triggerChange(item.value); + } + }); + }); + return this; + }; + Choices.prototype.showDropdown = function (preventInputFocus) { + var _this = this; + if (this.dropdown.isActive) { + return this; + } + requestAnimationFrame(function () { + _this.dropdown.show(); + _this.containerOuter.open(_this.dropdown.distanceFromTopWindow); + if (!preventInputFocus && _this._canSearch) { + _this.input.focus(); + } + _this.passedElement.triggerEvent("showDropdown" /* EventType.showDropdown */); + }); + return this; + }; + Choices.prototype.hideDropdown = function (preventInputBlur) { + var _this = this; + if (!this.dropdown.isActive) { + return this; + } + requestAnimationFrame(function () { + _this.dropdown.hide(); + _this.containerOuter.close(); + if (!preventInputBlur && _this._canSearch) { + _this.input.removeActiveDescendant(); + _this.input.blur(); + } + _this.passedElement.triggerEvent("hideDropdown" /* EventType.hideDropdown */); + }); + return this; + }; + Choices.prototype.getValue = function (valueOnly) { + var _this = this; + if (valueOnly === void 0) { valueOnly = false; } + var values = this._store.items.reduce(function (selectedItems, item) { + var itemValue = valueOnly ? item.value : _this._getChoiceForOutput(item); + selectedItems.push(itemValue); + return selectedItems; + }, []); + return this._isSelectOneElement || this.config.singleModeForMultiSelect ? values[0] : values; + }; + Choices.prototype.setValue = function (items) { + var _this = this; + if (!this.initialisedOK) { + this._warnChoicesInitFailed('setValue'); + return this; + } + this._store.withTxn(function () { + items.forEach(function (value) { + if (value) { + _this._addChoice(mapInputToChoice(value, false)); + } + }); + }); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + Choices.prototype.setChoiceByValue = function (value) { + var _this = this; + if (!this.initialisedOK) { + this._warnChoicesInitFailed('setChoiceByValue'); + return this; + } + if (this._isTextElement) { + return this; + } + this._store.withTxn(function () { + // If only one value has been passed, convert to array + var choiceValue = Array.isArray(value) ? value : [value]; + // Loop through each value and + choiceValue.forEach(function (val) { return _this._findAndSelectChoiceByValue(val); }); + }); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + /** + * Set choices of select input via an array of objects (or function that returns array of object or promise of it), + * a value field name and a label field name. + * This behaves the same as passing items via the choices option but can be called after initialising Choices. + * This can also be used to add groups of choices (see example 2); Optionally pass a true `replaceChoices` value to remove any existing choices. + * Optionally pass a `customProperties` object to add additional data to your choices (useful when searching/filtering etc). + * + * **Input types affected:** select-one, select-multiple + * + * @example + * ```js + * const example = new Choices(element); + * + * example.setChoices([ + * {value: 'One', label: 'Label One', disabled: true}, + * {value: 'Two', label: 'Label Two', selected: true}, + * {value: 'Three', label: 'Label Three'}, + * ], 'value', 'label', false); + * ``` + * + * @example + * ```js + * const example = new Choices(element); + * + * example.setChoices(async () => { + * try { + * const items = await fetch('/items'); + * return items.json() + * } catch(err) { + * console.error(err) + * } + * }); + * ``` + * + * @example + * ```js + * const example = new Choices(element); + * + * example.setChoices([{ + * label: 'Group one', + * id: 1, + * disabled: false, + * choices: [ + * {value: 'Child One', label: 'Child One', selected: true}, + * {value: 'Child Two', label: 'Child Two', disabled: true}, + * {value: 'Child Three', label: 'Child Three'}, + * ] + * }, + * { + * label: 'Group two', + * id: 2, + * disabled: false, + * choices: [ + * {value: 'Child Four', label: 'Child Four', disabled: true}, + * {value: 'Child Five', label: 'Child Five'}, + * {value: 'Child Six', label: 'Child Six', customProperties: { + * description: 'Custom description about child six', + * random: 'Another random custom property' + * }}, + * ] + * }], 'value', 'label', false); + * ``` + */ + Choices.prototype.setChoices = function (choicesArrayOrFetcher, value, label, replaceChoices) { + var _this = this; + if (choicesArrayOrFetcher === void 0) { choicesArrayOrFetcher = []; } + if (value === void 0) { value = 'value'; } + if (label === void 0) { label = 'label'; } + if (replaceChoices === void 0) { replaceChoices = false; } + if (!this.initialisedOK) { + this._warnChoicesInitFailed('setChoices'); + return this; + } + if (!this._isSelectElement) { + throw new TypeError("setChoices can't be used with INPUT based Choices"); + } + if (typeof value !== 'string' || !value) { + throw new TypeError("value parameter must be a name of 'value' field in passed objects"); + } + // Clear choices if needed + if (replaceChoices) { + this.clearChoices(); + } + if (typeof choicesArrayOrFetcher === 'function') { + // it's a choices fetcher function + var fetcher_1 = choicesArrayOrFetcher(this); + if (typeof Promise === 'function' && fetcher_1 instanceof Promise) { + // that's a promise + // eslint-disable-next-line no-promise-executor-return + return new Promise(function (resolve) { return requestAnimationFrame(resolve); }) + .then(function () { return _this._handleLoadingState(true); }) + .then(function () { return fetcher_1; }) + .then(function (data) { return _this.setChoices(data, value, label, replaceChoices); }) + .catch(function (err) { + if (!_this.config.silent) { + console.error(err); + } + }) + .then(function () { return _this._handleLoadingState(false); }) + .then(function () { return _this; }); + } + // function returned something else than promise, let's check if it's an array of choices + if (!Array.isArray(fetcher_1)) { + throw new TypeError(".setChoices first argument function must return either array of choices or Promise, got: ".concat(typeof fetcher_1)); + } + // recursion with results, it's sync and choices were cleared already + return this.setChoices(fetcher_1, value, label, false); + } + if (!Array.isArray(choicesArrayOrFetcher)) { + throw new TypeError(".setChoices must be called either with array of choices with a function resulting into Promise of array of choices"); + } + this.containerOuter.removeLoadingState(); + this._store.withTxn(function () { + var isDefaultValue = value === 'value'; + var isDefaultLabel = label === 'label'; + choicesArrayOrFetcher.forEach(function (groupOrChoice) { + if ('choices' in groupOrChoice) { + var group = groupOrChoice; + if (!isDefaultLabel) { + group = __assign(__assign({}, group), { label: group[label] }); + } + _this._addGroup(mapInputToChoice(group, true)); + } + else { + var choice = groupOrChoice; + if (!isDefaultLabel || !isDefaultValue) { + choice = __assign(__assign({}, choice), { value: choice[value], label: choice[label] }); + } + _this._addChoice(mapInputToChoice(choice, false)); + } + }); + }); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + Choices.prototype.refresh = function (withEvents, selectFirstOption, deselectAll) { + var _this = this; + if (withEvents === void 0) { withEvents = false; } + if (selectFirstOption === void 0) { selectFirstOption = false; } + if (deselectAll === void 0) { deselectAll = false; } + if (!this._isSelectElement) { + if (!this.config.silent) { + console.warn('refresh method can only be used on choices backed by a element"),this)},e.prototype.removeChoice=function(e){var t=this._store.choices.find((function(t){return t.value===e}));return t?(this._store.dispatch(function(e){return{type:r,choice:e}}(t)),this._searcher.reset(),t.selected&&this.passedElement.triggerEvent("removeItem",this._getChoiceForOutput(t)),this):this},e.prototype.clearChoices=function(){return this.passedElement.element.innerHTML="",this._store.dispatch({type:l}),this._searcher.reset(),this},e.prototype.clearStore=function(){return this._store.reset(),this._lastAddedChoiceId=0,this._lastAddedGroupId=0,this._searcher.reset(),this},e.prototype.clearInput=function(){return this.input.clear(!this._isSelectOneElement),this._clearNotice(),this._isSearching&&this._stopSearch(),this},e.prototype._validateConfig=function(){var e,t,i,n=this.config,s=(e=R,t=Object.keys(n).sort(),i=Object.keys(e).sort(),t.filter((function(e){return i.indexOf(e)<0})));s.length&&console.warn("Unknown config option(s) passed",s.join(", ")),n.allowHTML&&n.allowHtmlUserInput&&(n.addItems&&console.warn("Warning: allowHTML/allowHtmlUserInput/addItems all being true is strongly not recommended and may lead to XSS attacks"),n.addChoices&&console.warn("Warning: allowHTML/allowHtmlUserInput/addChoices all being true is strongly not recommended and may lead to XSS attacks"))},e.prototype._render=function(e){void 0===e&&(e={choices:!0,groups:!0,items:!0}),this._store.inTxn()||(this._isSelectElement&&(e.choices||e.groups)&&this._renderChoices(),e.items&&this._renderItems())},e.prototype._renderChoices=function(){var e=this;if(this.choiceList.clear(),this._canAddItems()){var t=this.config,i=this._store,n=i.activeGroups,s=i.activeChoices,o=document.createDocumentFragment(),r=!0;if(s.length){if(t.resetScrollPosition&&requestAnimationFrame((function(){return e.choiceList.scrollToTop()})),n.length&&!this._isSearching){if(!this._hasNonChoicePlaceholder){var a=s.filter((function(e){return e.placeholder&&-1===e.groupId}));a.length&&(o=this._createChoicesFragment(a,o))}o=this._createGroupsFragment(n,s,o)}else o=this._createChoicesFragment(s,o);r=!o.childNodes.length}var c=this._notice;r?c||(this._notice={text:b(t.noChoicesText),type:U}):c&&c.type===U&&(this._notice=void 0),this._renderNotice(),r||(this.choiceList.element.append(o),this._highlightChoice())}},e.prototype._renderItems=function(){var e=this._store.items||[];this.itemList.clear();var t=this._createItemsFragment(e);t.childNodes.length&&this.itemList.element.append(t)},e.prototype._createGroupsFragment=function(e,t,i){var n=this;void 0===i&&(i=document.createDocumentFragment());var s=this.config;s.shouldSort&&e.sort(s.sorter);var o=t.filter((function(e){return!e.groupId}));return o.length&&this._createChoicesFragment(o,i,!1),e.forEach((function(e){var o=function(e){return t.filter((function(t){return n._isSelectOneElement?t.groupId===e.id:t.groupId===e.id&&("always"===s.renderSelectedChoices||!t.selected)}))}(e);if(o.length){var r=n._templates.choiceGroup(n.config,e);i.appendChild(r),n._createChoicesFragment(o,i,!0)}})),i},e.prototype._createChoicesFragment=function(e,t,i){var s=this;void 0===t&&(t=document.createDocumentFragment()),void 0===i&&(i=!1);var o=this,r=o.config,a=o._isSearching,c=o._isSelectOneElement,l=r.searchResultLimit,h=r.renderChoiceLimit,u=[],d=r.appendGroupInSearch&&a;if(d&&this._store.groups.forEach((function(e){u[e.id]=e.label})),this._isSelectElement){var p=e.filter((function(e){return!e.element}));p.length&&this.passedElement.addOptions(p)}var m="auto"===r.renderSelectedChoices&&!c,f=[],v=[];e.forEach((function(e){a&&!e.rank||m&&e.selected||(s._hasNonChoicePlaceholder||!e.placeholder?v.push(e):f.push(e))})),a?v.sort(w):r.shouldSort&&v.sort(r.sorter);var _=c&&f.length?n(n([],f,!0),v,!0):v,g=_.length,y=g;return a&&l>0?y=l:h>0&&!i&&(y=h),y0){var o=u[e.groupId];o&&(n.innerHTML+=" (".concat(o,")"))}return t.appendChild(n),i0?this._store.getGroupById(e.groupId):null;return{id:e.id,highlighted:e.highlighted,labelClass:e.labelClass,labelDescription:e.labelDescription,customProperties:e.customProperties,disabled:e.disabled,active:e.active,label:e.label,placeholder:e.placeholder,value:e.value,groupValue:i&&i.label?i.label:void 0,element:e.element,keyCode:t}}},e.prototype._triggerChange=function(e){null!=e&&this.passedElement.triggerEvent("change",{value:e})},e.prototype._handleButtonAction=function(e){var t=this._store.items;if(t.length&&this.config.removeItems&&this.config.removeItemButton){var i=e&&ee(e.parentNode),n=i&&t.find((function(e){return e.id===i}));if(n&&(this._removeItem(n),this._triggerChange(n.value),this._isSelectOneElement&&!this._hasNonChoicePlaceholder)){var s=this._store.choices.reverse().find((function(e){return!e.disabled&&e.placeholder}));s&&(this._addItem(s),s.value&&this._triggerChange(s.value))}}},e.prototype._handleItemAction=function(e,t){var i=this;void 0===t&&(t=!1);var n=this._store.items;if(n.length&&this.config.removeItems&&!this._isSelectOneElement){var s=ee(e);s&&(n.forEach((function(e){e.id!==s||e.highlighted?!t&&e.highlighted&&i.unhighlightItem(e):i.highlightItem(e)})),this.input.focus())}},e.prototype._handleChoiceAction=function(e){var t=this,i=ee(e),n=i&&this._store.getChoiceById(i);if(!n||n.disabled)return!1;var s=this.dropdown.isActive;if(!n.selected){if(!this._canAddItems())return!0;this._store.withTxn((function(){t._addItem(n,!0,!0),t.clearInput(),t.unhighlightAll()})),this._triggerChange(n.value)}return s&&this.config.closeDropdownOnSelect&&(this.hideDropdown(!0),this.containerOuter.element.focus()),!0},e.prototype._handleBackspace=function(e){var t=this.config;if(t.removeItems&&e.length){var i=e[e.length-1],n=e.some((function(e){return e.highlighted}));t.editItems&&!n&&i?(this.input.value=i.value,this.input.setWidth(),this._removeItem(i),this._triggerChange(i.value)):(n||this.highlightItem(i,!1),this.removeHighlightedItems(!0))}},e.prototype._loadChoices=function(){var e,t=this.config;if(this._isTextElement){this._presetChoices=t.items.map((function(e){return H(e,!1)}));var i=this.passedElement.value;if(i){var n=i.split(t.delimiter).map((function(e){return H(e,!1)}));this._presetChoices=this._presetChoices.concat(n)}this._presetChoices.forEach((function(e){e.selected=!0}))}else if(this._isSelectElement){this._presetChoices=t.choices.map((function(e){return H(e,!0)}));var s=this.passedElement.optionsAsChoices();s&&(e=this._presetChoices).push.apply(e,s)}},e.prototype._handleLoadingState=function(e){void 0===e&&(e=!0);var t=this.config;e?(this.disable(),this.containerOuter.addLoadingState(),this._isSelectOneElement?(this.itemList.clear(),this.itemList.element.append(this._templates.placeholder(t,t.loadingText))):this.input.placeholder=t.loadingText):(this.enable(),this.containerOuter.removeLoadingState(),this._isSelectOneElement||(this.input.placeholder=this._placeholderValue||""))},e.prototype._handleSearch=function(e){if(this.input.isFocussed){var t=this.config,i=t.searchFloor,n=t.searchChoices,s=this._store.choices.some((function(e){return!e.active}));if(null!=e&&e.length>=i){var o=n?this._searchChoices(e):0;null!==o&&this.passedElement.triggerEvent("search",{value:e,resultCount:o})}else s&&this._stopSearch()}},e.prototype._canAddItems=function(){var e=this.config,t=e.maxItemCount,i=e.maxItemText;return!(!e.singleModeForMultiSelect&&t>0&&t<=this._store.items.length&&(this._displayNotice("function"==typeof i?i(t):i,X),1))},e.prototype._canCreateItem=function(e){var t=this.config,i=!0,n="";if(i&&"function"==typeof t.addItemFilter&&!t.addItemFilter(e)&&(i=!1,n=y(t.customAddItemText,e)),i){var s=this._store.choices.find((function(i){return t.valueComparer(i.value,e)}));if(this._isSelectElement){if(s)return this._displayNotice("",X),!1}else this._isTextElement&&!t.duplicateItemsAllowed&&s&&(i=!1,n=y(t.uniqueItemText,e))}return i&&(n=y(t.addItemText,e)),n&&this._displayNotice(n,X),i},e.prototype._searchChoices=function(e){var t=e.trim().replace(/\s{2,}/," ");if(!t.length||t===this._currentValue)return null;var i=this._searcher;i.isEmptyIndex()&&i.index(this._store.searchableChoices);var n=i.search(t);this._currentValue=t,this._highlightPosition=0,this._isSearching=!0;var s=this._notice,o=s&&s.type;return o!==X&&(n.length?o===W&&this._clearNotice():this._displayNotice(b(this.config.noResultsText),W)),this._store.dispatch(function(e){return{type:a,results:e}}(n)),n.length},e.prototype._stopSearch=function(){var e=this._isSearching;this._currentValue="",this._isSearching=!1,e&&(this._store.dispatch({type:c,active:!0}),this.passedElement.triggerEvent("search",{value:"",resultCount:0}))},e.prototype._addEventListeners=function(){var e=this._docRoot,t=this.containerOuter.element,i=this.input.element;e.addEventListener("touchend",this._onTouchEnd,!0),t.addEventListener("keydown",this._onKeyDown,!0),t.addEventListener("mousedown",this._onMouseDown,!0),e.addEventListener("click",this._onClick,{passive:!0}),e.addEventListener("touchmove",this._onTouchMove,{passive:!0}),this.dropdown.element.addEventListener("mouseover",this._onMouseOver,{passive:!0}),this._isSelectOneElement&&(t.addEventListener("focus",this._onFocus,{passive:!0}),t.addEventListener("blur",this._onBlur,{passive:!0})),i.addEventListener("keyup",this._onKeyUp,{passive:!0}),i.addEventListener("input",this._onInput,{passive:!0}),i.addEventListener("focus",this._onFocus,{passive:!0}),i.addEventListener("blur",this._onBlur,{passive:!0}),i.form&&i.form.addEventListener("reset",this._onFormReset,{passive:!0}),this.input.addEventListeners()},e.prototype._removeEventListeners=function(){var e=this._docRoot,t=this.containerOuter.element,i=this.input.element;e.removeEventListener("touchend",this._onTouchEnd,!0),t.removeEventListener("keydown",this._onKeyDown,!0),t.removeEventListener("mousedown",this._onMouseDown,!0),e.removeEventListener("click",this._onClick),e.removeEventListener("touchmove",this._onTouchMove),this.dropdown.element.removeEventListener("mouseover",this._onMouseOver),this._isSelectOneElement&&(t.removeEventListener("focus",this._onFocus),t.removeEventListener("blur",this._onBlur)),i.removeEventListener("keyup",this._onKeyUp),i.removeEventListener("input",this._onInput),i.removeEventListener("focus",this._onFocus),i.removeEventListener("blur",this._onBlur),i.form&&i.form.removeEventListener("reset",this._onFormReset),this.input.removeEventListeners()},e.prototype._onKeyDown=function(e){var t=e.keyCode,i=this._store.items,n=this.input.isFocussed,s=this.dropdown.isActive,o=this.itemList.element.hasChildNodes(),r=1===e.key.length||2===e.key.length&&e.key.charCodeAt(0)>=55296||"Unidentified"===e.key;switch(this._isTextElement||s||(this.showDropdown(),!this.input.isFocussed&&r&&(this.input.value+=e.key," "===e.key&&e.preventDefault())),t){case 65:return this._onSelectKey(e,o);case 13:return this._onEnterKey(e,s);case 27:return this._onEscapeKey(e,s);case 38:case 33:case 40:case 34:return this._onDirectionKey(e,s);case 8:case 46:return this._onDeleteKey(e,i,n)}},e.prototype._onKeyUp=function(){this._canSearch=this.config.searchEnabled},e.prototype._onInput=function(){var e=this.input.value;if(!e)return this._isTextElement?this.hideDropdown(!0):this._stopSearch(),void this._clearNotice();this._canAddItems()&&(this._canSearch&&this._handleSearch(e),this._canAddUserChoices&&(this._canCreateItem(e),this._isSelectElement&&(this._highlightPosition=0,this._highlightChoice())))},e.prototype._onSelectKey=function(e,t){(e.ctrlKey||e.metaKey)&&t&&(this._canSearch=!1,this.config.removeItems&&!this.input.value&&this.input.element===document.activeElement&&this.highlightAll())},e.prototype._onEnterKey=function(e,t){var i=this,n=this.config,s=this.input.value,o=e.target,r=o&&o.hasAttribute("data-button");if(e.preventDefault(),r)this._handleButtonAction(o);else if(t){var a=this.dropdown.element.querySelector(A(n.classNames.highlightedState));if(!a||!this._handleChoiceAction(a))if(o&&s){if(this._canAddItems()){var c=!1;this._store.withTxn((function(){if(!(c=i._findAndSelectChoiceByValue(s,!0))){if(!i._canAddUserChoices)return;if(!i._canCreateItem(s))return;var e=_(s),t=n.allowHtmlUserInput||e===s?s:{escaped:e,raw:s};i._addChoice(H({value:t,label:t,selected:!0},!1),!0,!0),c=!0}i.clearInput(),i.unhighlightAll()})),c&&(this._triggerChange(s),n.closeDropdownOnSelect&&this.hideDropdown(!0))}}else this.hideDropdown(!0)}else(this._isSelectElement||this._notice)&&this.showDropdown()},e.prototype._onEscapeKey=function(e,t){t&&(e.stopPropagation(),this.hideDropdown(!0),this.containerOuter.element.focus())},e.prototype._onDirectionKey=function(e,t){var i,n,s,o=e.keyCode,r=e.metaKey;if(t||this._isSelectOneElement){this.showDropdown(),this._canSearch=!1;var a=40===o||34===o?1:-1,c="[data-choice-selectable]",l=void 0;if(r||34===o||33===o)l=this.dropdown.element.querySelector(a>0?"".concat(c,":last-of-type"):c);else{var h=this.dropdown.element.querySelector(A(this.config.classNames.highlightedState));l=h?function(e,t,i){void 0===i&&(i=1);for(var n="".concat(i>0?"next":"previous","ElementSibling"),s=e[n];s;){if(s.matches(t))return s;s=s[n]}return null}(h,c,a):this.dropdown.element.querySelector(c)}l&&(i=l,n=this.choiceList.element,void 0===(s=a)&&(s=1),(s>0?n.scrollTop+n.offsetHeight>=i.offsetTop+i.offsetHeight:i.offsetTop>=n.scrollTop)||this.choiceList.scrollToChildElement(l,a),this._highlightChoice(l)),e.preventDefault()}},e.prototype._onDeleteKey=function(e,t,i){this._isSelectOneElement||e.target.value||!i||(this._handleBackspace(t),e.preventDefault())},e.prototype._onTouchMove=function(){this._wasTap&&(this._wasTap=!1)},e.prototype._onTouchEnd=function(e){var t=(e||e.touches[0]).target;this._wasTap&&this.containerOuter.element.contains(t)&&((t===this.containerOuter.element||t===this.containerInner.element)&&(this._isTextElement?this.input.focus():this._isSelectMultipleElement&&this.showDropdown()),e.stopPropagation()),this._wasTap=!0},e.prototype._onMouseDown=function(e){var t=e.target;if(t instanceof HTMLElement){if(Z&&this.choiceList.element.contains(t)){var i=this.choiceList.element.firstElementChild;this._isScrollingOnIe="ltr"===this._direction?e.offsetX>=i.offsetWidth:e.offsetXthis._highlightPosition?n[this._highlightPosition]:n[n.length-1])||(s=n[0]),(t=s.classList).add.apply(t,I(i)),s.setAttribute("aria-selected","true"),this.passedElement.triggerEvent("highlightChoice",{el:s}),this.dropdown.isActive&&(this.input.setActiveDescendant(s.id),this.containerOuter.setActiveDescendant(s.id))}},e.prototype._addItem=function(e,t,i){void 0===t&&(t=!0),void 0===i&&(i=!1);var n=e.id;if(!n)throw new TypeError("item.id must be set before _addItem is called for a choice/item");(this.config.singleModeForMultiSelect||this._isSelectOneElement)&&this.removeActiveItems(n),this._store.dispatch(function(e){return{type:u,item:e}}(e)),t&&(this.passedElement.triggerEvent("addItem",this._getChoiceForOutput(e)),i&&this.passedElement.triggerEvent("choice",this._getChoiceForOutput(e)))},e.prototype._removeItem=function(e){e.id&&(this._store.dispatch(function(e){return{type:d,item:e}}(e)),this.passedElement.triggerEvent("removeItem",this._getChoiceForOutput(e)))},e.prototype._addChoice=function(e,t,i){if(void 0===t&&(t=!0),void 0===i&&(i=!1),e.id)throw new TypeError("Can not re-add a choice which has already been added");this._lastAddedChoiceId++,e.id=this._lastAddedChoiceId,e.elementId="".concat(this._baseId,"-").concat(this._idNames.itemChoice,"-").concat(e.id);var n=this.config,s=n.prependValue,r=n.appendValue;s&&(e.value=s+e.value),r&&(e.value+=r.toString()),(s||r)&&e.element&&(e.element.value=e.value),this._store.dispatch(function(e){return{type:o,choice:e}}(e)),e.selected&&this._addItem(e,t,i)},e.prototype._addGroup=function(e,t){var i=this;if(void 0===t&&(t=!0),e.id)throw new TypeError("Can not re-add a group which has already been added");if(this._store.dispatch(function(e){return{type:h,group:e}}(e)),e.choices){var n=e;this._lastAddedGroupId++,n.id=this._lastAddedGroupId;var s=e.id,o=e.choices;n.choices=[],o.forEach((function(n){n.groupId=s,e.disabled&&(n.disabled=!0),i._addChoice(n,t)}))}},e.prototype._createTemplates=function(){var e=this,t=this.config.callbackOnCreateTemplates,i={};t&&"function"==typeof t&&(i=t.call(this,g,C));var n={};Object.keys(this._templates).forEach((function(t){n[t]=t in i?i[t].bind(e):e._templates[t].bind(e)})),this._templates=n},e.prototype._createElements=function(){var e=this._templates,t=this.config,i=t.position,n=t.classNames,s=this._elementType;this.containerOuter=new D({element:e.containerOuter(t,this._direction,this._isSelectElement,this._isSelectOneElement,t.searchEnabled,s,t.labelId),classNames:n,type:s,position:i}),this.containerInner=new D({element:e.containerInner(t),classNames:n,type:s,position:i}),this.input=new F({element:e.input(t,this._placeholderValue),classNames:n,type:s,preventPaste:!t.paste}),this.choiceList=new P({element:e.choiceList(t,this._isSelectOneElement)}),this.itemList=new P({element:e.itemList(t,this._isSelectOneElement)}),this.dropdown=new O({element:e.dropdown(t),classNames:n,type:s})},e.prototype._createStructure=function(){var e=this,t=e.containerInner,i=e.containerOuter,n=e.passedElement,s=e.dropdown,o=e.input;n.conceal(),t.wrap(n.element),i.wrap(t.element),this._isSelectOneElement?o.placeholder=this.config.searchPlaceholderValue||"":(this._placeholderValue&&(o.placeholder=this._placeholderValue),o.setWidth()),i.element.appendChild(t.element),i.element.appendChild(s.element),t.element.appendChild(this.itemList.element),s.element.appendChild(this.choiceList.element),this._isSelectOneElement?this.config.searchEnabled&&s.element.insertBefore(o.element,s.element.firstChild):t.element.appendChild(o.element),this._highlightPosition=0,this._isSearching=!1},e.prototype._initStore=function(){var e=this;this._store.subscribe(this._render),this._store.withTxn((function(){e._addPredefinedChoices(e._presetChoices,e._isSelectOneElement&&!e._hasNonChoicePlaceholder,!1)})),this._isSelectOneElement&&this._hasNonChoicePlaceholder&&this._render({choices:!1,groups:!1,items:!0})},e.prototype._addPredefinedChoices=function(e,t,i){var n=this;void 0===t&&(t=!1),void 0===i&&(i=!0),t&&-1===e.findIndex((function(e){return e.selected}))&&e.some((function(e){return!e.disabled&&!("choices"in e)&&(e.selected=!0,!0)})),e.forEach((function(e){"choices"in e?n._isSelectElement&&n._addGroup(e,i):n._addChoice(e,i)}))},e.prototype._findAndSelectChoiceByValue=function(e,t){var i=this;void 0===t&&(t=!1);var n=this._store.choices.find((function(t){return i.config.valueComparer(t.value,e)}));return!(!n||n.disabled||n.selected||(this._addItem(n,!0,t),0))},e.prototype._generatePlaceholderValue=function(){var e=this.config;if(!e.placeholder)return null;if(this._hasNonChoicePlaceholder)return e.placeholderValue;if(this._isSelectElement){var t=this.passedElement.placeholderOption;return t?t.text:null}return null},e.prototype._warnChoicesInitFailed=function(e){if(!this.config.silent){if(!this.initialised)throw new TypeError("".concat(e," called on a non-initialised instance of Choices"));if(!this.initialisedOK)throw new TypeError("".concat(e," called for an element which has multiple instances of Choices initialised on it"))}},e.version="11.0.0-rc7",e}()})); diff --git a/assets/scripts/choices.search-prefix.mjs b/assets/scripts/choices.search-prefix.mjs new file mode 100644 index 00000000..ff825273 --- /dev/null +++ b/assets/scripts/choices.search-prefix.mjs @@ -0,0 +1,3558 @@ +/*! choices.js v11.0.0-rc7 | © 2024 Josh Johnson | https://github.com/jshjohnson/Choices#readme */ + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise, SuppressedError, Symbol */ + +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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; + }; + return extendStatics(d, b); +}; +function __extends(d, b) { + if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} +var __assign = function () { + __assign = Object.assign || function __assign(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); +}; +function __spreadArray(to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +} +typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}; + +var ActionType = { + ADD_CHOICE: 'ADD_CHOICE', + REMOVE_CHOICE: 'REMOVE_CHOICE', + FILTER_CHOICES: 'FILTER_CHOICES', + ACTIVATE_CHOICES: 'ACTIVATE_CHOICES', + CLEAR_CHOICES: 'CLEAR_CHOICES', + ADD_GROUP: 'ADD_GROUP', + ADD_ITEM: 'ADD_ITEM', + REMOVE_ITEM: 'REMOVE_ITEM', + HIGHLIGHT_ITEM: 'HIGHLIGHT_ITEM', +}; + +var ObjectsInConfig = ['fuseOptions', 'classNames']; + +var addChoice = function (choice) { return ({ + type: ActionType.ADD_CHOICE, + choice: choice, +}); }; +var removeChoice = function (choice) { return ({ + type: ActionType.REMOVE_CHOICE, + choice: choice, +}); }; +var filterChoices = function (results) { return ({ + type: ActionType.FILTER_CHOICES, + results: results, +}); }; +var activateChoices = function (active) { + return ({ + type: ActionType.ACTIVATE_CHOICES, + active: active, + }); +}; +var clearChoices = function () { return ({ + type: ActionType.CLEAR_CHOICES, +}); }; + +var addGroup = function (group) { return ({ + type: ActionType.ADD_GROUP, + group: group, +}); }; + +var addItem = function (item) { return ({ + type: ActionType.ADD_ITEM, + item: item, +}); }; +var removeItem = function (item) { return ({ + type: ActionType.REMOVE_ITEM, + item: item, +}); }; +var highlightItem = function (item, highlighted) { return ({ + type: ActionType.HIGHLIGHT_ITEM, + item: item, + highlighted: highlighted, +}); }; + +/* eslint-disable @typescript-eslint/no-explicit-any */ +var getRandomNumber = function (min, max) { return Math.floor(Math.random() * (max - min) + min); }; +var generateChars = function (length) { + return Array.from({ length: length }, function () { return getRandomNumber(0, 36).toString(36); }).join(''); +}; +var generateId = function (element, prefix) { + var id = element.id || (element.name && "".concat(element.name, "-").concat(generateChars(2))) || generateChars(4); + id = id.replace(/(:|\.|\[|\]|,)/g, ''); + id = "".concat(prefix, "-").concat(id); + return id; +}; +var getAdjacentEl = function (startEl, selector, direction) { + if (direction === void 0) { direction = 1; } + var prop = "".concat(direction > 0 ? 'next' : 'previous', "ElementSibling"); + var sibling = startEl[prop]; + while (sibling) { + if (sibling.matches(selector)) { + return sibling; + } + sibling = sibling[prop]; + } + return null; +}; +var isScrolledIntoView = function (element, parent, direction) { + if (direction === void 0) { direction = 1; } + var isVisible; + if (direction > 0) { + // In view from bottom + isVisible = parent.scrollTop + parent.offsetHeight >= element.offsetTop + element.offsetHeight; + } + else { + // In view from top + isVisible = element.offsetTop >= parent.scrollTop; + } + return isVisible; +}; +var sanitise = function (value) { + if (typeof value !== 'string') { + if (value === null || value === undefined) { + return ''; + } + if (typeof value === 'object') { + if ('raw' in value) { + return sanitise(value.raw); + } + if ('trusted' in value) { + return value.trusted; + } + } + return value; + } + return value + .replace(/&/g, '&') + .replace(/>/g, '>') + .replace(/ 0 ? this.element.scrollTop + elementPos - listScrollPosition : element.offsetTop; + requestAnimationFrame(function () { + _this._animateScroll(destination, direction); + }); + }; + List.prototype._scrollDown = function (scrollPos, strength, destination) { + var easing = (destination - scrollPos) / strength; + var distance = easing > 1 ? easing : 1; + this.element.scrollTop = scrollPos + distance; + }; + List.prototype._scrollUp = function (scrollPos, strength, destination) { + var easing = (scrollPos - destination) / strength; + var distance = easing > 1 ? easing : 1; + this.element.scrollTop = scrollPos - distance; + }; + List.prototype._animateScroll = function (destination, direction) { + var _this = this; + var strength = SCROLLING_SPEED; + var choiceListScrollTop = this.element.scrollTop; + var continueAnimation = false; + if (direction > 0) { + this._scrollDown(choiceListScrollTop, strength, destination); + if (choiceListScrollTop < destination) { + continueAnimation = true; + } + } + else { + this._scrollUp(choiceListScrollTop, strength, destination); + if (choiceListScrollTop > destination) { + continueAnimation = true; + } + } + if (continueAnimation) { + requestAnimationFrame(function () { + _this._animateScroll(destination, direction); + }); + } + }; + return List; +}()); + +var WrappedElement = /** @class */ (function () { + function WrappedElement(_a) { + var element = _a.element, classNames = _a.classNames; + this.element = element; + this.classNames = classNames; + this.isDisabled = false; + } + Object.defineProperty(WrappedElement.prototype, "isActive", { + get: function () { + return this.element.dataset.choice === 'active'; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(WrappedElement.prototype, "dir", { + get: function () { + return this.element.dir; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(WrappedElement.prototype, "value", { + get: function () { + return this.element.value; + }, + set: function (value) { + this.element.setAttribute('value', value); + this.element.value = value; + }, + enumerable: false, + configurable: true + }); + WrappedElement.prototype.conceal = function () { + var _a; + var el = this.element; + // Hide passed input + (_a = el.classList).add.apply(_a, getClassNames(this.classNames.input)); + el.hidden = true; + // Remove element from tab index + el.tabIndex = -1; + // Backup original styles if any + var origStyle = el.getAttribute('style'); + if (origStyle) { + el.setAttribute('data-choice-orig-style', origStyle); + } + el.setAttribute('data-choice', 'active'); + }; + WrappedElement.prototype.reveal = function () { + var _a; + var el = this.element; + // Reinstate passed element + (_a = el.classList).remove.apply(_a, getClassNames(this.classNames.input)); + el.hidden = false; + el.removeAttribute('tabindex'); + // Recover original styles if any + var origStyle = el.getAttribute('data-choice-orig-style'); + if (origStyle) { + el.removeAttribute('data-choice-orig-style'); + el.setAttribute('style', origStyle); + } + else { + el.removeAttribute('style'); + } + el.removeAttribute('data-choice'); + }; + WrappedElement.prototype.enable = function () { + var element = this.element; + element.removeAttribute('disabled'); + element.disabled = false; + this.isDisabled = false; + }; + WrappedElement.prototype.disable = function () { + var element = this.element; + element.setAttribute('disabled', ''); + element.disabled = true; + this.isDisabled = true; + }; + WrappedElement.prototype.triggerEvent = function (eventType, data) { + dispatchEvent(this.element, eventType, data || {}); + }; + return WrappedElement; +}()); + +var WrappedInput = /** @class */ (function (_super) { + __extends(WrappedInput, _super); + function WrappedInput() { + return _super !== null && _super.apply(this, arguments) || this; + } + return WrappedInput; +}(WrappedElement)); + +var coerceBool = function (arg, defaultValue) { + if (defaultValue === void 0) { defaultValue = true; } + return typeof arg === 'undefined' ? defaultValue : !!arg; +}; +var stringToHtmlClass = function (input) { + if (typeof input === 'string') { + // eslint-disable-next-line no-param-reassign + input = input.split(' ').filter(function (s) { return s.length; }); + } + if (Array.isArray(input) && input.length) { + return input; + } + return undefined; +}; +var mapInputToChoice = function (value, allowGroup) { + if (typeof value === 'string') { + var result_1 = mapInputToChoice({ + value: value, + label: value, + }, false); + return result_1; + } + var groupOrChoice = value; + if ('choices' in groupOrChoice) { + if (!allowGroup) { + // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup + throw new TypeError("optGroup is not allowed"); + } + var group = groupOrChoice; + var choices = group.choices.map(function (e) { return mapInputToChoice(e, false); }); + var result_2 = { + id: 0, // actual ID will be assigned during _addGroup + label: unwrapStringForRaw(group.label) || group.value, + active: !!choices.length, + disabled: !!group.disabled, + choices: choices, + }; + return result_2; + } + var choice = groupOrChoice; + var result = { + id: 0, // actual ID will be assigned during _addChoice + groupId: 0, // actual ID will be assigned during _addGroup but before _addChoice + score: 0, // used in search + rank: 0, // used in search, stable sort order + value: choice.value, + label: choice.label || choice.value, + active: coerceBool(choice.active), + selected: coerceBool(choice.selected, false), + disabled: coerceBool(choice.disabled, false), + placeholder: coerceBool(choice.placeholder, false), + highlighted: false, + labelClass: stringToHtmlClass(choice.labelClass), + labelDescription: choice.labelDescription, + customProperties: choice.customProperties, + }; + return result; +}; + +var isHtmlInputElement = function (e) { return e.tagName === 'INPUT'; }; +var isHtmlSelectElement = function (e) { return e.tagName === 'SELECT'; }; +var isHtmlOption = function (e) { return e.tagName === 'OPTION'; }; +var isHtmlOptgroup = function (e) { return e.tagName === 'OPTGROUP'; }; + +var WrappedSelect = /** @class */ (function (_super) { + __extends(WrappedSelect, _super); + function WrappedSelect(_a) { + var element = _a.element, classNames = _a.classNames, template = _a.template, extractPlaceholder = _a.extractPlaceholder; + var _this = _super.call(this, { element: element, classNames: classNames }) || this; + _this.template = template; + _this.extractPlaceholder = extractPlaceholder; + return _this; + } + Object.defineProperty(WrappedSelect.prototype, "placeholderOption", { + get: function () { + return (this.element.querySelector('option[value=""]') || + // Backward compatibility layer for the non-standard placeholder attribute supported in older versions. + this.element.querySelector('option[placeholder]')); + }, + enumerable: false, + configurable: true + }); + WrappedSelect.prototype.addOptions = function (choices) { + var _this = this; + var fragment = document.createDocumentFragment(); + choices.forEach(function (obj) { + var choice = obj; + if (choice.element) { + return; + } + var option = _this.template(choice); + fragment.appendChild(option); + choice.element = option; + }); + this.element.appendChild(fragment); + }; + WrappedSelect.prototype.optionsAsChoices = function () { + var _this = this; + var choices = []; + this.element.querySelectorAll(':scope > option, :scope > optgroup').forEach(function (e) { + if (isHtmlOption(e)) { + choices.push(_this._optionToChoice(e)); + } + else if (isHtmlOptgroup(e)) { + choices.push(_this._optgroupToChoice(e)); + } + // todo: hr as empty optgroup, requires displaying empty opt-groups to be useful + }); + return choices; + }; + // eslint-disable-next-line class-methods-use-this + WrappedSelect.prototype._optionToChoice = function (option) { + // option.value returns the label if there is no value attribute, which can break legacy placeholder attribute support + if (!option.hasAttribute('value') && option.hasAttribute('placeholder')) { + option.setAttribute('value', ''); + option.value = ''; + } + var dataset = option.dataset; + return { + id: 0, + groupId: 0, + score: 0, + rank: 0, + value: option.value, + label: option.innerHTML, + element: option, + active: true, + // this returns true if nothing is selected on initial load, which will break placeholder support + selected: this.extractPlaceholder ? option.selected : option.hasAttribute('selected'), + disabled: option.disabled, + highlighted: false, + placeholder: this.extractPlaceholder && (!option.value || option.hasAttribute('placeholder')), + labelClass: typeof dataset.labelClass !== 'undefined' ? stringToHtmlClass(dataset.labelClass) : undefined, + labelDescription: typeof dataset.labelDescription !== 'undefined' ? dataset.labelDescription : undefined, + customProperties: parseCustomProperties(dataset.customProperties), + }; + }; + WrappedSelect.prototype._optgroupToChoice = function (optgroup) { + var _this = this; + var options = optgroup.querySelectorAll('option'); + var choices = Array.from(options).map(function (option) { return _this._optionToChoice(option); }); + return { + id: 0, + label: optgroup.label || '', + element: optgroup, + active: !!choices.length, + disabled: optgroup.disabled, + choices: choices, + }; + }; + return WrappedSelect; +}(WrappedElement)); + +var DEFAULT_CLASSNAMES = { + containerOuter: ['choices'], + containerInner: ['choices__inner'], + input: ['choices__input'], + inputCloned: ['choices__input--cloned'], + list: ['choices__list'], + listItems: ['choices__list--multiple'], + listSingle: ['choices__list--single'], + listDropdown: ['choices__list--dropdown'], + item: ['choices__item'], + itemSelectable: ['choices__item--selectable'], + itemDisabled: ['choices__item--disabled'], + itemChoice: ['choices__item--choice'], + description: ['choices__description'], + placeholder: ['choices__placeholder'], + group: ['choices__group'], + groupHeading: ['choices__heading'], + button: ['choices__button'], + activeState: ['is-active'], + focusState: ['is-focused'], + openState: ['is-open'], + disabledState: ['is-disabled'], + highlightedState: ['is-highlighted'], + selectedState: ['is-selected'], + flippedState: ['is-flipped'], + loadingState: ['is-loading'], + notice: ['choices__notice'], + addChoice: ['choices__item--selectable', 'add-choice'], + noResults: ['has-no-results'], + noChoices: ['has-no-choices'], +}; +var DEFAULT_CONFIG = { + items: [], + choices: [], + silent: false, + renderChoiceLimit: -1, + maxItemCount: -1, + closeDropdownOnSelect: 'auto', + singleModeForMultiSelect: false, + addChoices: false, + addItems: true, + addItemFilter: function (value) { return !!value && value !== ''; }, + removeItems: true, + removeItemButton: false, + removeItemButtonAlignLeft: false, + editItems: false, + allowHTML: false, + allowHtmlUserInput: false, + duplicateItemsAllowed: true, + delimiter: ',', + paste: true, + searchEnabled: true, + searchChoices: true, + searchFloor: 1, + searchResultLimit: 4, + searchFields: ['label', 'value'], + position: 'auto', + resetScrollPosition: true, + shouldSort: true, + shouldSortItems: false, + sorter: sortByAlpha, + shadowRoot: null, + placeholder: true, + placeholderValue: null, + searchPlaceholderValue: null, + prependValue: null, + appendValue: null, + renderSelectedChoices: 'auto', + loadingText: 'Loading...', + noResultsText: 'No results found', + noChoicesText: 'No choices to choose from', + itemSelectText: 'Press to select', + uniqueItemText: 'Only unique values can be added', + customAddItemText: 'Only values matching specific conditions can be added', + addItemText: function (value) { return "Press Enter to add \"".concat(value, "\""); }, + removeItemIconText: function () { return "Remove item"; }, + removeItemLabelText: function (value) { return "Remove item: ".concat(value); }, + maxItemText: function (maxItemCount) { return "Only ".concat(maxItemCount, " values can be added"); }, + valueComparer: function (value1, value2) { return value1 === value2; }, + fuseOptions: { + includeScore: true, + }, + labelId: '', + callbackOnInit: null, + callbackOnCreateTemplates: null, + classNames: DEFAULT_CLASSNAMES, + appendGroupInSearch: false, +}; + +function items(s, action) { + var state = s; + var update = true; + switch (action.type) { + case ActionType.ADD_ITEM: { + var item = action.item; + item.selected = true; + var el = item.element; + if (el) { + el.selected = true; + el.setAttribute('selected', ''); + } + state.push(item); + state.forEach(function (choice) { + choice.highlighted = false; + }); + break; + } + case ActionType.REMOVE_ITEM: { + var item_1 = action.item; + item_1.selected = false; + var el = item_1.element; + if (el) { + el.selected = false; + el.removeAttribute('selected'); + // For a select-one, if all options are deselected, the first item is selected. To set a black value, select.value needs to be set + var select = el.parentElement; + if (select && isHtmlSelectElement(select) && select.type === SELECT_ONE_TYPE) { + select.value = ''; + } + } + state = state.filter(function (choice) { return choice.id !== item_1.id; }); + break; + } + case ActionType.REMOVE_CHOICE: { + state = state.filter(function (item) { return item.id !== action.choice.id; }); + break; + } + case ActionType.HIGHLIGHT_ITEM: { + var highlightItemAction_1 = action; + state.forEach(function (choice) { + if (choice.id === highlightItemAction_1.item.id) { + choice.highlighted = highlightItemAction_1.highlighted; + } + }); + break; + } + default: { + update = false; + break; + } + } + return { state: state, update: update }; +} + +function groups(s, action) { + var state = s; + var update = true; + switch (action.type) { + case ActionType.ADD_GROUP: { + state.push(action.group); + break; + } + case ActionType.CLEAR_CHOICES: { + state = []; + break; + } + default: { + update = false; + break; + } + } + return { state: state, update: update }; +} + +/* eslint-disable */ +function choices(s, action) { + var state = s; + var update = true; + switch (action.type) { + case ActionType.ADD_CHOICE: { + /* + A disabled choice appears in the choice dropdown but cannot be selected + A selected choice has been added to the passed input's value (added as an item) + An active choice appears within the choice dropdown + */ + state.push(action.choice); + break; + } + case ActionType.REMOVE_CHOICE: { + state = state.filter(function (obj) { return obj.id !== action.choice.id; }); + break; + } + case ActionType.ADD_ITEM: + case ActionType.REMOVE_ITEM: { + break; + } + case ActionType.FILTER_CHOICES: { + // avoid O(n^2) algorithm complexity when searching/filtering choices + var scoreLookup_1 = []; + action.results.forEach(function (result) { + scoreLookup_1[result.item.id] = result; + }); + state.forEach(function (choice) { + var result = scoreLookup_1[choice.id]; + if (result !== undefined) { + choice.score = result.score; + choice.rank = result.rank; + choice.active = true; + } + else { + choice.score = 0; + choice.rank = 0; + choice.active = false; + } + }); + break; + } + case ActionType.ACTIVATE_CHOICES: { + state.forEach(function (choice) { + choice.active = action.active; + }); + break; + } + case ActionType.CLEAR_CHOICES: { + state = []; + break; + } + default: { + update = false; + break; + } + } + return { state: state, update: update }; +} + +var reducers = { + groups: groups, + items: items, + choices: choices, +}; +var Store = /** @class */ (function () { + function Store() { + this._state = this.defaultState; + this._listeners = []; + this._txn = 0; + } + Object.defineProperty(Store.prototype, "defaultState", { + // eslint-disable-next-line class-methods-use-this + get: function () { + return { + groups: [], + items: [], + choices: [], + }; + }, + enumerable: false, + configurable: true + }); + // eslint-disable-next-line class-methods-use-this + Store.prototype.changeSet = function (init) { + return { + groups: init, + items: init, + choices: init, + }; + }; + Store.prototype.reset = function () { + this._state = this.defaultState; + var changes = this.changeSet(true); + if (this._txn) { + this._changeSet = changes; + } + else { + this._listeners.forEach(function (l) { return l(changes); }); + } + }; + Store.prototype.subscribe = function (onChange) { + this._listeners.push(onChange); + }; + Store.prototype.dispatch = function (action) { + var state = this._state; + var hasChanges = false; + var changes = this._changeSet || this.changeSet(false); + Object.keys(reducers).forEach(function (key) { + var stateUpdate = reducers[key](state[key], action); + if (stateUpdate.update) { + hasChanges = true; + changes[key] = true; + state[key] = stateUpdate.state; + } + }); + if (hasChanges) { + if (this._txn) { + this._changeSet = changes; + } + else { + this._listeners.forEach(function (l) { return l(changes); }); + } + } + }; + Store.prototype.withTxn = function (func) { + this._txn++; + try { + func(); + } + finally { + this._txn = Math.max(0, this._txn - 1); + if (!this._txn) { + var changeSet_1 = this._changeSet; + if (changeSet_1) { + this._changeSet = undefined; + this._listeners.forEach(function (l) { return l(changeSet_1); }); + } + } + } + }; + Object.defineProperty(Store.prototype, "state", { + /** + * Get store object + */ + get: function () { + return this._state; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "items", { + /** + * Get items from store + */ + get: function () { + return this.state.items; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "highlightedActiveItems", { + /** + * Get highlighted items from store + */ + get: function () { + return this.items.filter(function (item) { return !item.disabled && item.active && item.highlighted; }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "choices", { + /** + * Get choices from store + */ + get: function () { + return this.state.choices; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "activeChoices", { + /** + * Get active choices from store + */ + get: function () { + return this.choices.filter(function (choice) { return choice.active; }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "searchableChoices", { + /** + * Get choices that can be searched (excluding placeholders) + */ + get: function () { + return this.choices.filter(function (choice) { return !choice.disabled && !choice.placeholder; }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "groups", { + /** + * Get groups from store + */ + get: function () { + return this.state.groups; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Store.prototype, "activeGroups", { + /** + * Get active groups from store + */ + get: function () { + var _this = this; + return this.state.groups.filter(function (group) { + var isActive = group.active && !group.disabled; + var hasActiveOptions = _this.state.choices.some(function (choice) { return choice.active && !choice.disabled; }); + return isActive && hasActiveOptions; + }, []); + }, + enumerable: false, + configurable: true + }); + Store.prototype.inTxn = function () { + return this._txn > 0; + }; + /** + * Get single choice by it's ID + */ + Store.prototype.getChoiceById = function (id) { + return this.activeChoices.find(function (choice) { return choice.id === id; }); + }; + /** + * Get group by group id + */ + Store.prototype.getGroupById = function (id) { + return this.groups.find(function (group) { return group.id === id; }); + }; + return Store; +}()); + +var NoticeTypes = { + noChoices: 'no-choices', + noResults: 'no-results', + addChoice: 'add-choice', + generic: '', +}; + +var SearchByPrefixFilter = /** @class */ (function () { + function SearchByPrefixFilter(config) { + this._haystack = []; + this._fields = config.searchFields; + } + SearchByPrefixFilter.prototype.index = function (data) { + this._haystack = data; + }; + SearchByPrefixFilter.prototype.reset = function () { + this._haystack = []; + }; + SearchByPrefixFilter.prototype.isEmptyIndex = function () { + return !this._haystack.length; + }; + SearchByPrefixFilter.prototype.search = function (_needle) { + var fields = this._fields; + if (!fields || !fields.length || !_needle) { + return []; + } + var needle = _needle.toLowerCase(); + return this._haystack + .filter(function (obj) { return fields.some(function (field) { return field in obj && obj[field].toLowerCase().startsWith(needle); }); }) + .map(function (value, index) { + return { + item: value, + score: index, + rank: index + 1, + }; + }); + }; + return SearchByPrefixFilter; +}()); + +function getSearcher(config) { + return new SearchByPrefixFilter(config); +} + +/** + * Helpers to create HTML elements used by Choices + * Can be overridden by providing `callbackOnCreateTemplates` option. + * `Choices.defaults.templates` allows access to the default template methods from `callbackOnCreateTemplates` + */ +var isEmptyObject = function (obj) { + // eslint-disable-next-line no-restricted-syntax + for (var prop in obj) { + if (Object.prototype.hasOwnProperty.call(obj, prop)) { + return false; + } + } + return true; +}; +var assignCustomProperties = function (el, choice, withCustomProperties) { + var dataset = el.dataset; + var customProperties = choice.customProperties, labelClass = choice.labelClass, labelDescription = choice.labelDescription; + if (labelClass) { + dataset.labelClass = getClassNames(labelClass).join(' '); + } + if (labelDescription) { + dataset.labelDescription = labelDescription; + } + if (withCustomProperties && customProperties) { + if (typeof customProperties === 'string') { + dataset.customProperties = customProperties; + } + else if (typeof customProperties === 'object' && !isEmptyObject(customProperties)) { + dataset.customProperties = JSON.stringify(customProperties); + } + } +}; +var addAriaLabel = function (docRoot, id, element) { + var label = id && docRoot.querySelector("label[for='".concat(id, "']")); + var text = label && label.innerText; + if (text) { + element.setAttribute('aria-label', text); + } +}; +var templates = { + containerOuter: function (_a, dir, isSelectElement, isSelectOneElement, searchEnabled, passedElementType, labelId) { + var containerOuter = _a.classNames.containerOuter; + var div = document.createElement('div'); + div.className = getClassNames(containerOuter).join(' '); + div.dataset.type = passedElementType; + if (dir) { + div.dir = dir; + } + if (isSelectOneElement) { + div.tabIndex = 0; + } + if (isSelectElement) { + div.setAttribute('role', searchEnabled ? 'combobox' : 'listbox'); + if (searchEnabled) { + div.setAttribute('aria-autocomplete', 'list'); + } + else if (!labelId) { + addAriaLabel(this._docRoot, this.passedElement.element.id, div); + } + div.setAttribute('aria-haspopup', 'true'); + div.setAttribute('aria-expanded', 'false'); + } + if (labelId) { + div.setAttribute('aria-labelledby', labelId); + } + return div; + }, + containerInner: function (_a) { + var containerInner = _a.classNames.containerInner; + var div = document.createElement('div'); + div.className = getClassNames(containerInner).join(' '); + return div; + }, + itemList: function (_a, isSelectOneElement) { + var searchEnabled = _a.searchEnabled, _b = _a.classNames, list = _b.list, listSingle = _b.listSingle, listItems = _b.listItems; + var div = document.createElement('div'); + div.className = "".concat(getClassNames(list).join(' '), " ").concat(isSelectOneElement ? getClassNames(listSingle).join(' ') : getClassNames(listItems).join(' ')); + if (this._isSelectElement && searchEnabled) { + div.setAttribute('role', 'listbox'); + } + return div; + }, + placeholder: function (_a, value) { + var allowHTML = _a.allowHTML, placeholder = _a.classNames.placeholder; + var div = document.createElement('div'); + div.className = getClassNames(placeholder).join(' '); + setElementHtml(div, allowHTML, value); + return div; + }, + item: function (_a, choice, removeItemButton) { + var _b, _c, _d; + var allowHTML = _a.allowHTML, removeItemButtonAlignLeft = _a.removeItemButtonAlignLeft, removeItemIconText = _a.removeItemIconText, removeItemLabelText = _a.removeItemLabelText, _e = _a.classNames, item = _e.item, button = _e.button, highlightedState = _e.highlightedState, itemSelectable = _e.itemSelectable, placeholder = _e.placeholder; + var labelClass = choice.labelClass, label = choice.label, disabled = choice.disabled, value = choice.value; + var rawValue = unwrapStringForRaw(value); + var div = document.createElement('div'); + div.className = getClassNames(item).join(' '); + if (labelClass) { + var spanLabel = document.createElement('span'); + setElementHtml(spanLabel, allowHTML, label); + spanLabel.className = getClassNames(labelClass).join(' '); + div.appendChild(spanLabel); + } + else { + setElementHtml(div, allowHTML, label); + } + var dataset = div.dataset; + dataset.item = ''; + dataset.id = choice.id; + dataset.value = rawValue; + assignCustomProperties(div, choice, true); + if (disabled || this.containerOuter.isDisabled) { + div.setAttribute('aria-disabled', 'true'); + } + if (this._isSelectElement) { + div.setAttribute('aria-selected', 'true'); + div.setAttribute('role', 'option'); + } + if (choice.placeholder) { + (_b = div.classList).add.apply(_b, getClassNames(placeholder)); + dataset.placeholder = ''; + } + (_c = div.classList).add.apply(_c, (choice.highlighted ? getClassNames(highlightedState) : getClassNames(itemSelectable))); + if (removeItemButton) { + if (disabled) { + (_d = div.classList).remove.apply(_d, getClassNames(itemSelectable)); + } + dataset.deletable = ''; + var removeButton = document.createElement('button'); + removeButton.type = 'button'; + removeButton.className = getClassNames(button).join(' '); + setElementHtml(removeButton, true, resolveNoticeFunction(removeItemIconText, value)); + var REMOVE_ITEM_LABEL = resolveNoticeFunction(removeItemLabelText, value); + if (REMOVE_ITEM_LABEL) { + removeButton.setAttribute('aria-label', REMOVE_ITEM_LABEL); + } + removeButton.dataset.button = ''; + if (removeItemButtonAlignLeft) { + div.insertAdjacentElement('afterbegin', removeButton); + } + else { + div.appendChild(removeButton); + } + } + return div; + }, + choiceList: function (_a, isSelectOneElement) { + var list = _a.classNames.list; + var div = document.createElement('div'); + div.className = getClassNames(list).join(' '); + if (!isSelectOneElement) { + div.setAttribute('aria-multiselectable', 'true'); + } + div.setAttribute('role', 'listbox'); + return div; + }, + choiceGroup: function (_a, _b) { + var allowHTML = _a.allowHTML, _c = _a.classNames, group = _c.group, groupHeading = _c.groupHeading, itemDisabled = _c.itemDisabled; + var id = _b.id, label = _b.label, disabled = _b.disabled; + var rawLabel = unwrapStringForRaw(label); + var div = document.createElement('div'); + div.className = "".concat(getClassNames(group).join(' '), " ").concat(disabled ? getClassNames(itemDisabled).join(' ') : ''); + div.setAttribute('role', 'group'); + var dataset = div.dataset; + dataset.group = ''; + dataset.id = id; + dataset.value = rawLabel; + if (disabled) { + div.setAttribute('aria-disabled', 'true'); + } + var heading = document.createElement('div'); + heading.className = getClassNames(groupHeading).join(' '); + setElementHtml(heading, allowHTML, label); + div.appendChild(heading); + return div; + }, + choice: function (_a, choice, selectText) { + var _b, _c, _d, _e, _f; + var allowHTML = _a.allowHTML, _g = _a.classNames, item = _g.item, itemChoice = _g.itemChoice, itemSelectable = _g.itemSelectable, selectedState = _g.selectedState, itemDisabled = _g.itemDisabled, description = _g.description, placeholder = _g.placeholder; + var value = choice.value, elementId = choice.elementId, groupId = choice.groupId, label = choice.label, labelClass = choice.labelClass, labelDescription = choice.labelDescription; + var rawValue = unwrapStringForRaw(value); + var div = document.createElement('div'); + div.id = elementId; + div.className = "".concat(getClassNames(item).join(' '), " ").concat(getClassNames(itemChoice).join(' ')); + var describedBy = div; + if (labelClass) { + var spanLabel = document.createElement('span'); + setElementHtml(spanLabel, allowHTML, label); + spanLabel.className = getClassNames(labelClass).join(' '); + describedBy = spanLabel; + div.appendChild(spanLabel); + } + else { + setElementHtml(div, allowHTML, label); + } + if (labelDescription) { + var descId = "".concat(elementId, "-description"); + describedBy.setAttribute('aria-describedby', descId); + var spanDesc = document.createElement('span'); + setElementHtml(spanDesc, allowHTML, labelDescription); + spanDesc.id = descId; + (_b = spanDesc.classList).add.apply(_b, getClassNames(description)); + div.appendChild(spanDesc); + } + if (choice.selected) { + (_c = div.classList).add.apply(_c, getClassNames(selectedState)); + } + if (choice.placeholder) { + (_d = div.classList).add.apply(_d, getClassNames(placeholder)); + } + var dataset = div.dataset; + var showGroupId = groupId && groupId > 0; + div.setAttribute('role', showGroupId ? 'treeitem' : 'option'); + if (showGroupId) { + dataset.groupId = "".concat(groupId); + } + dataset.choice = ''; + dataset.id = choice.id; + dataset.value = rawValue; + dataset.selectText = selectText; + assignCustomProperties(div, choice, false); + if (choice.disabled) { + (_e = div.classList).add.apply(_e, getClassNames(itemDisabled)); + dataset.choiceDisabled = ''; + div.setAttribute('aria-disabled', 'true'); + } + else { + (_f = div.classList).add.apply(_f, getClassNames(itemSelectable)); + dataset.choiceSelectable = ''; + } + return div; + }, + input: function (_a, placeholderValue) { + var _b = _a.classNames, input = _b.input, inputCloned = _b.inputCloned, labelId = _a.labelId; + var inp = document.createElement('input'); + inp.type = 'search'; + inp.className = "".concat(getClassNames(input).join(' '), " ").concat(getClassNames(inputCloned).join(' ')); + inp.autocomplete = 'off'; + inp.autocapitalize = 'off'; + inp.spellcheck = false; + inp.setAttribute('role', 'textbox'); + inp.setAttribute('aria-autocomplete', 'list'); + if (placeholderValue) { + inp.setAttribute('aria-label', placeholderValue); + } + else if (!labelId) { + addAriaLabel(this._docRoot, this.passedElement.element.id, inp); + } + return inp; + }, + dropdown: function (_a) { + var _b, _c; + var _d = _a.classNames, list = _d.list, listDropdown = _d.listDropdown; + var div = document.createElement('div'); + (_b = div.classList).add.apply(_b, getClassNames(list)); + (_c = div.classList).add.apply(_c, getClassNames(listDropdown)); + div.setAttribute('aria-expanded', 'false'); + return div; + }, + notice: function (_a, innerHTML, type) { + var _b = _a.classNames, item = _b.item, itemChoice = _b.itemChoice, addChoice = _b.addChoice, noResults = _b.noResults, noChoices = _b.noChoices, noticeItem = _b.notice; + if (type === void 0) { type = NoticeTypes.generic; } + var classes = __spreadArray(__spreadArray(__spreadArray([], getClassNames(item), true), getClassNames(itemChoice), true), getClassNames(noticeItem), true); + // eslint-disable-next-line default-case + switch (type) { + case NoticeTypes.addChoice: + classes.push.apply(classes, getClassNames(addChoice)); + break; + case NoticeTypes.noResults: + classes.push.apply(classes, getClassNames(noResults)); + break; + case NoticeTypes.noChoices: + classes.push.apply(classes, getClassNames(noChoices)); + break; + } + var notice = document.createElement('div'); + setElementHtml(notice, true, innerHTML); + notice.className = classes.join(' '); + if (type === NoticeTypes.addChoice) { + var dataset = notice.dataset; + dataset.choiceSelectable = ''; + dataset.choice = ''; + } + return notice; + }, + option: function (choice) { + // HtmlOptionElement's label value does not support HTML, so the avoid double escaping unwrap the untrusted string. + var labelValue = unwrapStringForRaw(choice.label); + var opt = new Option(labelValue, choice.value, false, choice.selected); + assignCustomProperties(opt, choice, true); + opt.disabled = choice.disabled; + if (choice.selected) { + opt.setAttribute('selected', ''); + } + return opt; + }, +}; + +/** @see {@link http://browserhacks.com/#hack-acea075d0ac6954f275a70023906050c} */ +var IS_IE11 = '-ms-scroll-limit' in document.documentElement.style && + '-ms-ime-align' in document.documentElement.style; +var USER_DEFAULTS = {}; +var parseDataSetId = function (element) { + if (!element) { + return undefined; + } + var id = element.dataset.id; + return id ? parseInt(id, 10) : undefined; +}; +/** + * Choices + * @author Josh Johnson + */ +var Choices = /** @class */ (function () { + function Choices(element, userConfig) { + if (element === void 0) { element = '[data-choice]'; } + if (userConfig === void 0) { userConfig = {}; } + var _this = this; + this.initialisedOK = undefined; + this._hasNonChoicePlaceholder = false; + this._lastAddedChoiceId = 0; + this._lastAddedGroupId = 0; + var defaults = Choices.defaults; + this.config = __assign(__assign(__assign({}, defaults.allOptions), defaults.options), userConfig); + ObjectsInConfig.forEach(function (key) { + _this.config[key] = __assign(__assign(__assign({}, defaults.allOptions[key]), defaults.options[key]), userConfig[key]); + }); + var config = this.config; + if (!config.silent) { + this._validateConfig(); + } + var docRoot = config.shadowRoot || document.documentElement; + this._docRoot = docRoot; + var passedElement = typeof element === 'string' ? docRoot.querySelector(element) : element; + if (!passedElement || + typeof passedElement !== 'object' || + !(isHtmlInputElement(passedElement) || isHtmlSelectElement(passedElement))) { + if (!passedElement && typeof element === 'string') { + throw TypeError("Selector ".concat(element, " failed to find an element")); + } + throw TypeError("Expected one of the following types text|select-one|select-multiple"); + } + this._elementType = passedElement.type; + this._isTextElement = this._elementType === TEXT_TYPE; + if (this._isTextElement || config.maxItemCount !== 1) { + config.singleModeForMultiSelect = false; + } + if (config.singleModeForMultiSelect) { + this._elementType = SELECT_MULTIPLE_TYPE; + } + this._isSelectOneElement = this._elementType === SELECT_ONE_TYPE; + this._isSelectMultipleElement = this._elementType === SELECT_MULTIPLE_TYPE; + this._isSelectElement = this._isSelectOneElement || this._isSelectMultipleElement; + this._canAddUserChoices = (this._isTextElement && config.addItems) || (this._isSelectElement && config.addChoices); + if (!['auto', 'always'].includes("".concat(config.renderSelectedChoices))) { + config.renderSelectedChoices = 'auto'; + } + if (config.closeDropdownOnSelect === 'auto') { + config.closeDropdownOnSelect = this._isTextElement || this._isSelectOneElement || config.singleModeForMultiSelect; + } + else { + config.closeDropdownOnSelect = coerceBool(config.closeDropdownOnSelect); + } + if (config.placeholder) { + if (config.placeholderValue) { + this._hasNonChoicePlaceholder = true; + } + else if (passedElement.dataset.placeholder) { + this._hasNonChoicePlaceholder = true; + config.placeholderValue = passedElement.dataset.placeholder; + } + } + if (userConfig.addItemFilter && typeof userConfig.addItemFilter !== 'function') { + var re = userConfig.addItemFilter instanceof RegExp ? userConfig.addItemFilter : new RegExp(userConfig.addItemFilter); + config.addItemFilter = re.test.bind(re); + } + if (this._isTextElement) { + this.passedElement = new WrappedInput({ + element: passedElement, + classNames: config.classNames, + }); + } + else { + var selectEl = passedElement; + this.passedElement = new WrappedSelect({ + element: selectEl, + classNames: config.classNames, + template: function (data) { return _this._templates.option(data); }, + extractPlaceholder: config.placeholder && !this._hasNonChoicePlaceholder, + }); + } + this.initialised = false; + this._store = new Store(); + this._currentValue = ''; + config.searchEnabled = (!this._isTextElement && config.searchEnabled) || this._elementType === SELECT_MULTIPLE_TYPE; + this._canSearch = config.searchEnabled; + this._isScrollingOnIe = false; + this._highlightPosition = 0; + this._wasTap = true; + this._placeholderValue = this._generatePlaceholderValue(); + this._baseId = generateId(passedElement, 'choices-'); + /** + * setting direction in cases where it's explicitly set on passedElement + * or when calculated direction is different from the document + */ + this._direction = this.passedElement.dir; + if (!this._direction) { + var elementDirection = window.getComputedStyle(this.passedElement.element).direction; + var documentDirection = window.getComputedStyle(document.documentElement).direction; + if (elementDirection !== documentDirection) { + this._direction = elementDirection; + } + } + this._idNames = { + itemChoice: 'item-choice', + }; + this._templates = defaults.templates; + this._render = this._render.bind(this); + this._onFocus = this._onFocus.bind(this); + this._onBlur = this._onBlur.bind(this); + this._onKeyUp = this._onKeyUp.bind(this); + this._onKeyDown = this._onKeyDown.bind(this); + this._onInput = this._onInput.bind(this); + this._onClick = this._onClick.bind(this); + this._onTouchMove = this._onTouchMove.bind(this); + this._onTouchEnd = this._onTouchEnd.bind(this); + this._onMouseDown = this._onMouseDown.bind(this); + this._onMouseOver = this._onMouseOver.bind(this); + this._onFormReset = this._onFormReset.bind(this); + this._onSelectKey = this._onSelectKey.bind(this); + this._onEnterKey = this._onEnterKey.bind(this); + this._onEscapeKey = this._onEscapeKey.bind(this); + this._onDirectionKey = this._onDirectionKey.bind(this); + this._onDeleteKey = this._onDeleteKey.bind(this); + // If element has already been initialised with Choices, fail silently + if (this.passedElement.isActive) { + if (!config.silent) { + console.warn('Trying to initialise Choices on element already initialised', { element: element }); + } + this.initialised = true; + this.initialisedOK = false; + return; + } + // Let's go + this.init(); + // preserve the selected item list after setup for form reset + this._initialItems = this._store.items.map(function (choice) { return choice.value; }); + } + Object.defineProperty(Choices, "defaults", { + get: function () { + return Object.preventExtensions({ + get options() { + return USER_DEFAULTS; + }, + get allOptions() { + return DEFAULT_CONFIG; + }, + get templates() { + return templates; + }, + }); + }, + enumerable: false, + configurable: true + }); + Choices.prototype.init = function () { + if (this.initialised || this.initialisedOK !== undefined) { + return; + } + this._searcher = getSearcher(this.config); + this._loadChoices(); + this._createTemplates(); + this._createElements(); + this._createStructure(); + if ((this._isTextElement && !this.config.addItems) || + this.passedElement.element.hasAttribute('disabled') || + !!this.passedElement.element.closest('fieldset:disabled')) { + this.disable(); + } + else { + this.enable(); + this._addEventListeners(); + } + // should be triggered **after** disabled state to avoid additional re-draws + this._initStore(); + this.initialised = true; + this.initialisedOK = true; + var callbackOnInit = this.config.callbackOnInit; + // Run callback if it is a function + if (callbackOnInit && typeof callbackOnInit === 'function') { + callbackOnInit.call(this); + } + }; + Choices.prototype.destroy = function () { + if (!this.initialised) { + return; + } + this._removeEventListeners(); + this.passedElement.reveal(); + this.containerOuter.unwrap(this.passedElement.element); + this._store._listeners = []; // prevents select/input value being wiped + this.clearStore(); + this._stopSearch(); + this._templates = Choices.defaults.templates; + this.initialised = false; + this.initialisedOK = undefined; + }; + Choices.prototype.enable = function () { + var _a = this, passedElement = _a.passedElement, containerOuter = _a.containerOuter; + if (passedElement.isDisabled) { + passedElement.enable(); + } + if (containerOuter.isDisabled) { + this._addEventListeners(); + this.input.enable(); + containerOuter.enable(); + this._render(); + } + return this; + }; + Choices.prototype.disable = function () { + var _a = this, passedElement = _a.passedElement, containerOuter = _a.containerOuter; + if (!passedElement.isDisabled) { + passedElement.disable(); + } + if (!containerOuter.isDisabled) { + this._removeEventListeners(); + this.input.disable(); + containerOuter.disable(); + this._render(); + } + return this; + }; + Choices.prototype.highlightItem = function (item, runEvent) { + if (runEvent === void 0) { runEvent = true; } + if (!item || !item.id) { + return this; + } + var choice = this._store.choices.find(function (c) { return c.id === item.id; }); + if (!choice || choice.highlighted) { + return this; + } + this._store.dispatch(highlightItem(choice, true)); + if (runEvent) { + this.passedElement.triggerEvent("highlightItem" /* EventType.highlightItem */, this._getChoiceForOutput(choice)); + } + return this; + }; + Choices.prototype.unhighlightItem = function (item, runEvent) { + if (runEvent === void 0) { runEvent = true; } + if (!item || !item.id) { + return this; + } + var choice = this._store.choices.find(function (c) { return c.id === item.id; }); + if (!choice || !choice.highlighted) { + return this; + } + this._store.dispatch(highlightItem(choice, false)); + if (runEvent) { + this.passedElement.triggerEvent("highlightItem" /* EventType.highlightItem */, this._getChoiceForOutput(choice)); + } + return this; + }; + Choices.prototype.highlightAll = function () { + var _this = this; + this._store.withTxn(function () { + _this._store.items.forEach(function (item) { return _this.highlightItem(item); }); + }); + return this; + }; + Choices.prototype.unhighlightAll = function () { + var _this = this; + this._store.withTxn(function () { + _this._store.items.forEach(function (item) { return _this.unhighlightItem(item); }); + }); + return this; + }; + Choices.prototype.removeActiveItemsByValue = function (value) { + var _this = this; + this._store.withTxn(function () { + _this._store.items.filter(function (item) { return item.value === value; }).forEach(function (item) { return _this._removeItem(item); }); + }); + return this; + }; + Choices.prototype.removeActiveItems = function (excludedId) { + var _this = this; + this._store.withTxn(function () { + _this._store.items.filter(function (_a) { + var id = _a.id; + return id !== excludedId; + }).forEach(function (item) { return _this._removeItem(item); }); + }); + return this; + }; + Choices.prototype.removeHighlightedItems = function (runEvent) { + var _this = this; + if (runEvent === void 0) { runEvent = false; } + this._store.withTxn(function () { + _this._store.highlightedActiveItems.forEach(function (item) { + _this._removeItem(item); + // If this action was performed by the user + // trigger the event + if (runEvent) { + _this._triggerChange(item.value); + } + }); + }); + return this; + }; + Choices.prototype.showDropdown = function (preventInputFocus) { + var _this = this; + if (this.dropdown.isActive) { + return this; + } + requestAnimationFrame(function () { + _this.dropdown.show(); + _this.containerOuter.open(_this.dropdown.distanceFromTopWindow); + if (!preventInputFocus && _this._canSearch) { + _this.input.focus(); + } + _this.passedElement.triggerEvent("showDropdown" /* EventType.showDropdown */); + }); + return this; + }; + Choices.prototype.hideDropdown = function (preventInputBlur) { + var _this = this; + if (!this.dropdown.isActive) { + return this; + } + requestAnimationFrame(function () { + _this.dropdown.hide(); + _this.containerOuter.close(); + if (!preventInputBlur && _this._canSearch) { + _this.input.removeActiveDescendant(); + _this.input.blur(); + } + _this.passedElement.triggerEvent("hideDropdown" /* EventType.hideDropdown */); + }); + return this; + }; + Choices.prototype.getValue = function (valueOnly) { + var _this = this; + if (valueOnly === void 0) { valueOnly = false; } + var values = this._store.items.reduce(function (selectedItems, item) { + var itemValue = valueOnly ? item.value : _this._getChoiceForOutput(item); + selectedItems.push(itemValue); + return selectedItems; + }, []); + return this._isSelectOneElement || this.config.singleModeForMultiSelect ? values[0] : values; + }; + Choices.prototype.setValue = function (items) { + var _this = this; + if (!this.initialisedOK) { + this._warnChoicesInitFailed('setValue'); + return this; + } + this._store.withTxn(function () { + items.forEach(function (value) { + if (value) { + _this._addChoice(mapInputToChoice(value, false)); + } + }); + }); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + Choices.prototype.setChoiceByValue = function (value) { + var _this = this; + if (!this.initialisedOK) { + this._warnChoicesInitFailed('setChoiceByValue'); + return this; + } + if (this._isTextElement) { + return this; + } + this._store.withTxn(function () { + // If only one value has been passed, convert to array + var choiceValue = Array.isArray(value) ? value : [value]; + // Loop through each value and + choiceValue.forEach(function (val) { return _this._findAndSelectChoiceByValue(val); }); + }); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + /** + * Set choices of select input via an array of objects (or function that returns array of object or promise of it), + * a value field name and a label field name. + * This behaves the same as passing items via the choices option but can be called after initialising Choices. + * This can also be used to add groups of choices (see example 2); Optionally pass a true `replaceChoices` value to remove any existing choices. + * Optionally pass a `customProperties` object to add additional data to your choices (useful when searching/filtering etc). + * + * **Input types affected:** select-one, select-multiple + * + * @example + * ```js + * const example = new Choices(element); + * + * example.setChoices([ + * {value: 'One', label: 'Label One', disabled: true}, + * {value: 'Two', label: 'Label Two', selected: true}, + * {value: 'Three', label: 'Label Three'}, + * ], 'value', 'label', false); + * ``` + * + * @example + * ```js + * const example = new Choices(element); + * + * example.setChoices(async () => { + * try { + * const items = await fetch('/items'); + * return items.json() + * } catch(err) { + * console.error(err) + * } + * }); + * ``` + * + * @example + * ```js + * const example = new Choices(element); + * + * example.setChoices([{ + * label: 'Group one', + * id: 1, + * disabled: false, + * choices: [ + * {value: 'Child One', label: 'Child One', selected: true}, + * {value: 'Child Two', label: 'Child Two', disabled: true}, + * {value: 'Child Three', label: 'Child Three'}, + * ] + * }, + * { + * label: 'Group two', + * id: 2, + * disabled: false, + * choices: [ + * {value: 'Child Four', label: 'Child Four', disabled: true}, + * {value: 'Child Five', label: 'Child Five'}, + * {value: 'Child Six', label: 'Child Six', customProperties: { + * description: 'Custom description about child six', + * random: 'Another random custom property' + * }}, + * ] + * }], 'value', 'label', false); + * ``` + */ + Choices.prototype.setChoices = function (choicesArrayOrFetcher, value, label, replaceChoices) { + var _this = this; + if (choicesArrayOrFetcher === void 0) { choicesArrayOrFetcher = []; } + if (value === void 0) { value = 'value'; } + if (label === void 0) { label = 'label'; } + if (replaceChoices === void 0) { replaceChoices = false; } + if (!this.initialisedOK) { + this._warnChoicesInitFailed('setChoices'); + return this; + } + if (!this._isSelectElement) { + throw new TypeError("setChoices can't be used with INPUT based Choices"); + } + if (typeof value !== 'string' || !value) { + throw new TypeError("value parameter must be a name of 'value' field in passed objects"); + } + // Clear choices if needed + if (replaceChoices) { + this.clearChoices(); + } + if (typeof choicesArrayOrFetcher === 'function') { + // it's a choices fetcher function + var fetcher_1 = choicesArrayOrFetcher(this); + if (typeof Promise === 'function' && fetcher_1 instanceof Promise) { + // that's a promise + // eslint-disable-next-line no-promise-executor-return + return new Promise(function (resolve) { return requestAnimationFrame(resolve); }) + .then(function () { return _this._handleLoadingState(true); }) + .then(function () { return fetcher_1; }) + .then(function (data) { return _this.setChoices(data, value, label, replaceChoices); }) + .catch(function (err) { + if (!_this.config.silent) { + console.error(err); + } + }) + .then(function () { return _this._handleLoadingState(false); }) + .then(function () { return _this; }); + } + // function returned something else than promise, let's check if it's an array of choices + if (!Array.isArray(fetcher_1)) { + throw new TypeError(".setChoices first argument function must return either array of choices or Promise, got: ".concat(typeof fetcher_1)); + } + // recursion with results, it's sync and choices were cleared already + return this.setChoices(fetcher_1, value, label, false); + } + if (!Array.isArray(choicesArrayOrFetcher)) { + throw new TypeError(".setChoices must be called either with array of choices with a function resulting into Promise of array of choices"); + } + this.containerOuter.removeLoadingState(); + this._store.withTxn(function () { + var isDefaultValue = value === 'value'; + var isDefaultLabel = label === 'label'; + choicesArrayOrFetcher.forEach(function (groupOrChoice) { + if ('choices' in groupOrChoice) { + var group = groupOrChoice; + if (!isDefaultLabel) { + group = __assign(__assign({}, group), { label: group[label] }); + } + _this._addGroup(mapInputToChoice(group, true)); + } + else { + var choice = groupOrChoice; + if (!isDefaultLabel || !isDefaultValue) { + choice = __assign(__assign({}, choice), { value: choice[value], label: choice[label] }); + } + _this._addChoice(mapInputToChoice(choice, false)); + } + }); + }); + // @todo integrate with Store + this._searcher.reset(); + return this; + }; + Choices.prototype.refresh = function (withEvents, selectFirstOption, deselectAll) { + var _this = this; + if (withEvents === void 0) { withEvents = false; } + if (selectFirstOption === void 0) { selectFirstOption = false; } + if (deselectAll === void 0) { deselectAll = false; } + if (!this._isSelectElement) { + if (!this.config.silent) { + console.warn('refresh method can only be used on choices backed by a +
+

Below is an example of how you could have two select inputs depend on @@ -520,6 +522,7 @@

Form interaction

Change the values and press reset to restore to initial state.

+
+
- * + *